本文主要分为音视频的一些基础概念和FFmpeg相关的基础概念两个部分
音视频基础
封装/解封装
- 封装:将视频码流/音频码流按照一定的格式存储在容器(文件)中,常见的封装格式为MP4、FLV、MKV等
- 解封装:封装的逆过程,将音视频文件分离为音频、视频等码流的过程,比如将MP4解封装为H.264和AAC
编码/解码
- 编码:将原始的视频数据(RGB、YUV等)压缩为视频码流,音频数据(PCM等)压缩为音频码流的过程叫做编码。音视频原始数据如果不经过压缩编码的话,通常体积是非常大的,不利于存储和网络传输。常见的视频编码标准有H.263,H.264,MPEG2等,音频编码标准AAC,MP3,AC-3等
- 解码:编码的逆过程,将音视频压缩编码的数据转为原始数据
软编(解)/硬编(解)
- 软编(解):使用CPU进行编解码处理
- 硬编(解):使用非CPU进行编解码,如显卡GPU、专用的DSP、FPGA等
软编(解)的时候CPU负载重,性能比硬编(解)低,但是通用性更好;硬编(解)性能高但是兼容性问题比较突出,特别是在Android平台,碎片化严重,MediaCodec的坑也是不少
视频帧率
视频一秒显示的帧数
音频采样率
即取样频率,指录音设备在单位时间内对模拟信号采样的多少采样率越高,声音的质量越好,还原越真实。目前主流采集卡上,采样频率一般共分为11025Hz、22050Hz、24000Hz、44100Hz、48000Hz五个等级
不过人耳的分辨能力有限,太高的频率也区分不出来。人耳能感觉到的最低波长为1.7cm,即20000Hz,因此要满足人耳的听觉要求,根据奈奎斯特采样定理,1s采样至少需要40000次,即40kHz
音视频同步
音视频文件经过解封装后,音频/视频解码便开始独立进行,渲染也是独立的。在音频流中播放速度按照音频采样率进行,视频流中播放速度按照帧率进行
理想情况下音视频独立播放是同步的,但实际上如果不做音视频同步处理,基本上都会出现音画不同步的问题,造成的原因主要还是一帧的播放时间很难控制在理想情况,音视频每帧的解码和渲染的耗时不同,可能造成每帧都存在一定误差且误差会逐渐积累
音视频同步的三种方式:视频参考音频时钟、音频/视频参考外部时钟、音频参考视频时钟,常用的是前两种,更详细的内容后面更新到FFmpeg音视频同步的时候再细说~
码率
也叫比特率,单位时间内音频/视频的比特数量。比特率越高文件大小越大,消耗的带宽也就越多,一般用kbps(千比特/秒)来表示
音频比特率:采样率 * 采样精度 * 声道数
视频比特率:帧率 * 每帧数据大小
声道数
即声音的通道的数目。常见的有单声道,双声道,4声道,5.1声道等
采样位数
即采样值,采样精度,用来衡量声音波动变化的一个参数,一般有8bit,16bit等。
分辨率
视频画面的大小或尺寸
I、P、B帧
- I帧(内部编码帧):使用帧内压缩,不使用运动补偿,不依赖其它帧所以可以独立解码为一幅完整的图像。I帧图像的压缩倍数相对较低
- P帧(前向预测帧):采用帧间编码方式,同时利用了空间和时间上的相关性。P帧图像只采用前向时间预测,可以提高压缩效率和图像质量
- B帧(双向内插帧):采用帧间编码方式且双向时间预测,提供了最高的压缩比。B帧既参考之前的I帧或P帧,也参考后面的P帧,所以会造成视频帧的解码顺序和显示顺序不同
GOP
GOP(Group Of Pictures):一组连续的图像,由一个I帧开始和多个B/P帧组成,是编/解码器存取的基本单位
GOP分为闭合GOP和开放GOP
闭合GOP以一个被称为IDR(即时解码刷新)的I帧开始,当解码器遇到IDR帧时,会立即刷新解码图片缓冲区,在IDR之前出现的帧都不能作为该GOP内B/P帧的参考帧,这样就形成了图片序列的中断,可以防止错误的持续传递
(图片来自参考1)
开放GOP和闭合GOP相反,允许其内的帧参考其他GOP内的帧
(两种GOP更详细的作用和差异推荐阅读文末的参考1)
DTS、PTS
- DTS(Decoding Time Stamp):解码时间戳,告知解码器在什么时间点解码这一帧的数据
- PTS(Presentation Time Stamp):显示时间戳,告知播放器什么时间点显示这一帧数据
下面这张图非常方便的辅助理解GOP,I/B/P帧和DTS和PTS
(图片来自网络)
FFmpeg基础
常用so
- libavformat:封装了Protocal/demuxer/muxer层,FFmpeg能否支持一种封装格式的视频的封装和解封装,依赖这个库。例如mp4、flv等容器的封装和解封装;rtmp、rtsp等协议的封装和解封装;
- libavcodec:编码解码模块,封装了codec层。如libx264、FDK-AAC等库因为License的关系不会被FFmpeg带上,如需要可以通过第三方codec插件的形式注册添加到FFmpeg
- libavutil:核心工具模块,提供音视频处理的一些基本操作,比如数学函数、错误码及错误处理、内存相关管理等
- libswresample:音频重采样,可以对数字音频进行声道数、数据格式、采样率等多种基本信息的转换
- libswscale:图像格式转换,比如将YUV转RGB等
- libavfilter:音视频滤镜模块,包含了音频特效和视频特效的处理
重要结构体
- AVFormatContext:在FFmpeg开发中是一个贯穿整个流程的数据结构,存储了整个音视频流和metadata信息
- AVCodecContext:存储视频/音频流使用解码方式的相关数据
- AVStream:存储一个视频/音频流的相关数据,每个AVStream对应一个AVCodecContext,每个AVCodecContext对应一个AVCodec,包含该视频/音频流对应的编解码器
- AVPacket:保存了解复用(demuxer)之后的压缩数据和附加信息,比如pts,dts,duration等
- AVFrame:保存解码后的原始数据
(图片来自网络)
最重要的结构体大概就这几个,我们先知道有这些东西和作用即可,后面在开发中慢慢完善知识树
时间基(time_base)
在FFmpeg中,对时间基time_base的理解也是一个非常基础且重要的点
time_base是时间戳的单位,时间戳乘以时间基可以得到实际的时间值(以秒为单位),我们可以把time_base看作一个时钟脉冲,dts/pts等看作时钟脉冲的计数
例如某一个视频帧dts是40,pts是100,time_base是1/1000秒,那么该视频帧的解码时间点是40ms,显示时间点是100ms
FFmpeg有三种time_base,用ffprob探测音视频文件时可以看到有tbr,tbn,tbc
- tbn对应容器中的时间基,值为AVStream.time_base的倒数
- tbc对应编解码器中的时间基,值为AVCodecContext.time_base的倒数
- tbr是从视频流中猜算得到,可能是帧率或者场率(帧率的2倍)
参考
1.【什么是闭合GOP和开放GOP】
https://cloud.tencent.com/developer/article/1919128
2.【FFMPEG中最关键的结构体之间的关系】
https://blog.csdn.net/leixiaohua1020/article/details/11693997
3.【FFMPEG时间戳详解】
https://www.cnblogs.com/leisure_chn/p/10584910.html
~~END~~
技术交流欢迎扫码添加我的微信:wxid_alaiye
推荐阅读
1. Android FFmpeg系列01--编译与集成
2. Ne10的编译与使用
3. 如何使用OpenGL渲染YUV数据
4. Android中如何使用OpenGL播放视频
5. 如何使用MediaCodec解码音视频