1、音视频编解码基础
我们可以通过http、rtmp或者本地的视频文件去播放视频。这里的"视频"实际上指的是mp4、avi这种既有音频也有视频的文件格式。
这样的视频文件可能会有多条轨道例如视频轨道、音频轨道、字幕轨道等. 有些格式限制比较多,例如AVI视频轨道只能有一条,音频轨道也只能有一条. 而有些格式则比较灵活,例如OGG视频的视频、音频轨道都能有多条.
像音频、视频这种数据量很大的轨道,上面的数据实际上都是通过压缩的。 视频轨道上可能是H264、H256这样压缩过的图像数据,通过解码可以还原成YUV、RGB等格式的图像数据。 音频轨道上可能是MP3、AAC这样压缩过的的音频数据,通过解码可以还原成PCM的音频裸流。
截屏2022-09-04 下午1.47.57.png
实际上使用ffmpeg去播放视频也就是根据文件的格式一步步还原出图像数据交给显示设备显示、还原出音频数据交给音频设备播放:
截屏2022-09-04 下午1.48.08.png
2、ffmpeg简单入门
了解了视频的播放流程之后我们来做一个简单的播放器实际入门一下ffmpeg。由于这篇博客是入门教程,这个播放器功能会进行简化:
使用ffmpeg 4.4.2版本 - 4.x的版本被使用的比较广泛,而且最新的5.x版本资料比较少
只解码一个视频轨道的画面进行播放 - 不需要考虑音视频同步的问题
使用SDL2在主线程解码 - 不需要考虑多线程同步问题
使用源码+Makefile构建 - 在MAC和Ubuntu上验证过,Windows的同学需要自己创建下vs的工程了
使用ffmpeg去解码大概有下面的几个步骤和关键函数,大家可以和上面的流程图对应一下:
2.1 解析文件流(解协议和解封装)
avformat_open_input : 可以打开File、RTMP等协议的数据流,并且读取文件头解析出视频信息,如解析出各个轨道和时长等
avformat_find_stream_info : 对于没有文件头的格式如MPEG或者H264裸流等,可以通过这个函数解析前几帧得到视频的信息
2.2 创建各个轨道的解码器(分流)
avcodec_find_decoder: 查找对应的解码器
avcodec_alloc_context3: 创建解码器上下文
avcodec_parameters_to_context: 设置解码所需要的参数
avcodec_open2: 打开解码器
2.3使用对应的解码器解码各个轨道(解码)
av_read_frame: 从视频流读取视频数据包
avcodec_send_packet: 发送视频数据包给解码器解码