FFMPEG视音频编解码学习(二)

目录

前言

对于FFmpeg的学习,感觉非常有趣,但是好像随着我的理解,有些概念有点模糊了!

基本流程

0

流概念

  • ES
    ES(Elementary(初级) Streams(原始流))是直接从编码器出来的数据流,可以是编码过的视频数据流(H264等),音频数据流(AAC等),或其他编码数据流的统称ES流经过PES打包器之后,被转换成PES包。
    ES是只包含一种内容的数据流,如只含视频或只含音频等,打包之后的PES也是只含一种性质的ES,如只含视频ESPES,只含音频ESPES等。每个ES都有若干个存取单元(AU)组成,每个视频AU或音频AU都是由头部和编码数据两部分组成,1个AU相当于编码的1幅视频图像或1个音频帧
  • PES
    PES(Packetized Elementary Streams(分组的ES)),ES形成的分组称为PES分组,是用来传递ES的一种数据结构。PES流是ES流经过PES打包器处理后形成的数据流,在这个过程中完成了将ES流分组、打包、加入包头信息等操作(对ES流的第一次打包)。PES流的基本单位是PES包。PES包由包头和payload组成。
  • PTS、DTS
    PTS-Presentation Time Stamp(显示时间标记),表示显示单元出现在系统目标解码器(H264MJPEG等)的时间
    DTS-Decoding Time Stamp(解码时间标记),表示将存取单元全部字节从解码缓存器移走的时间
    PTS/DTS是打在PES包的包头里面的两个参数,是解决音视频同步显示,防止解码器输入缓存上溢或下溢的关键。每一个I(关键帧)、P(预测帧)、B(双向预测帧)帧的包头都有一个PTSDTS,但PTSDTS对于B帧不一样,无需标出B帧的DTS,对于I帧和P帧,显示前一定要存储于视频解码器的重新排序缓存器,经过延迟(重新排序)后再显示,所以一定要分别标明PTSDTS
  • TS
    TS(transport Stream(传输流))由定长的TS包组成(188字节),而TS包是对PES包的一个重新封装(也就是相对ES来说,封装了两次)。PES包的包头信息依然存在于TS包中。
    TS流和PS流的区别在于TS流的包结构是固定长度的,而PS流的包结构是可变长度的PS包由于长度是变化的,一旦丢失某一PS包的同步信息,接收机就会进入失步状态,从而导致严重的信息丢失事件。而TS流由于采用固定长度的包结构,当传输误码破坏了某一TS包的同步信息,接收机可在固定的位置检测它后面包中的同步信息,从而恢复同步,避免信息丢失。因此在信道环境较为恶劣、传输误码较高时一般采用TS流,而在信道环境较好、传输误码较低时一般采用PS码流。
  • TS单一码流、混合码流
    单一性:TS流的基本组成是长度为188字节的TS包。
    混合性:TS流由多种数据组合而成,一个TS包中的数据可以是视频数据,音频数据,填充数据,PSI/SI表格数据等(唯一的PID对应)。

FFmpeg结构体和函数

FFmpeg结构体

FFmpeg函数

  • av_read_frame
    av_read_frame的作用是读取码流中的音频的若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码。

  • av_packet_rescale_ts
    转换时基,ffmpeg存在多个时间基准,对应不同阶段(结构体),每个time_base具体的值不一样。

  • av_interleaved_write_frame
    写一个packet到输出媒体文件,确保正确的间隔。在有多个流的情况下要用av_interleaved_write_frame,只有单一流2个函数都可以用。
    ffmpeg源码跟踪笔记之av_write_frame 与 av_interleaved_write_frame

  • avformat_alloc_output_context2

// avformat_alloc_output_context2可以初始化一个用于输出的AVFormatContext结构体。
int avformat_alloc_output_context2(AVFormatContext **ctx,       
AVOutputFormat *oformat, const char *format_name, const char *filename); 

/* 
参数1:ctx 函数调用成功之后创建的AVFormatContext结构体
参数2:oformat 指定AVFormatContext中的AVOutputFormat,用于确定输出格式。如果指定为NULL,可以设定后两个参数(format_name或者filename),有FFmpeg自动确定输出格式。
参数3:format_name 指定输出格式的名称。根据格式名称,FFmpeg会推测输出格式。输出格式可以是“flv”,"mkv"等。
参数4:file_name 指定输出文件的名称。根据文件名称,FFmpeg会推出输出格式。文件名称可以是“xxx.flv”,"yy.mkv"
*/
// 例如:
avformat_alloc_output_context2(&outputContext, nullptr, "mpegts",    
                            outputUrl.c_str());
这里设置的输出格式是mpegts,输出文件可以是本地文件也可以是网络文件
  • avio_open2
// 功能:avio_open2用于打开FFmpeg的输入输出文件。
int avio_open2(AVIOContext **s, const char *url, int flags,  
               const AVIOInterruptCB *int_cb, AVDictionary **options);  
/*
s:函数调用成功之后创建的AVIOContext结构体
url:输入输出协议的地址(文件也是一种“广义”的协议,对于文件来说就是文件的路径)。
flags:打开地址的方式。可以选择只读,只写,或者读写取值如下:
    AVIO_FLAG_READ:只读。
    AVIO_FLAG_WRITE:只写。
    AVIO_FLAG_READ_WRITE:读写
*/

FFmpeg源代码简单分析:avio_open2()

  • avformat_new_stream
    avformat_new_streamAVFormatContext创建Stream通道。之后,我们可以自行设置AVstream的一些参数信息。例如:codec_idformatbit_ratewidthheight
    ffmpeg——avformat_new_stream创建流通道

  • avcodec_copy_context
    avcodec_copy_context可以将输入视频/音频的参数拷贝至输出视频/音频的AVCodecContext结构体。

  • avformat_write_header

// 功能:avformat_write_header用于写视频文件头
int avformat_write_header(AVFormatContext *s, AVDictionary **options);  
// 参数1:s 用于输出的AVFormatContext
// 参数2:options 额外的选项 一般为NULL
  • avcodec_close
    avcodec_close用于关闭编码器

  • avformat_close_input
    avformat_close_input用于关闭一个AVFormatContext

总结

以上的许多FFmpeg的概念仍然不是很清楚,但是简单说,这些函数是为了实现网络流的转发。根据我的理解,网络流的转发过程如下:
1) 打开输入文件,比如本地文件或者网络文件
2) 打开输出文件,比如本地文件或者网络文件
3) 打开输出文件之后,建立输入到输出的流通道,并且发送头信息
4) 读取输入文件的流信息,通过建立好的流通道转发到输出文件
因为博主对于视音频的编解码还有许多不懂的地方,如果错误,请指出,谢谢指教!

链接地址

关于ESPESPS以及TS码流

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值