Android FFmpeg系列02--音视频基础

2022-09-08 14:51:33 浏览数 (1)

本文主要分为音视频的一些基础概念和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解码音视频

0 人点赞