作者:leisure
本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10235926.html
基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文件解码和调用SDL显示两大部分。
前面两个实验分别实现了视频播放和音频播放:
FFmpeg简易播放器的实现-视频播放
FFmpeg简易播放器的实现-音频播放
本实验将视频播放和音频播放结合在一起。
本实验主要参考如下两篇文章:
[1]. 最简单的基于FFMPEG+SDL的视频播放器ver2(采用SDL2.0)
[2]. An ffmpeg and SDL Tutorial
1. 视频播放器基本原理
下图引用自“雷霄骅,视音频编解码技术零基础学习方法”,因原图太小,看不太清楚,故重新制作了一张图片。
如下内容引用自“
2.3 解复用线程
解复用线程就是main()函数所在的主线程。main()函数作一些必要的初始化工作后,创建音频处理线程和视频处理线程。
然后main()函数进入主循环,从输入文件中读取packet,并根据packet类型,将之放入视频packet队列或音频packet队列。
2.4 音频处理线程
音频处理线程是SDL库内建线程。用户提供回调函数供音频处理线程调用。实现过程参考:
FFmpeg简易播放器的实现-音频播放
2.5 视频处理线程
视频处理线程实现视频解码及播放。实现过程参考:
FFmpeg简易播放器的实现-音频播放
2.6 源码清单
代码已经变得挺长了,不贴完整源码了,源码参考:
https://github.com/leihl/exercises/tree/master/source/ffmpeg/player_avideo/ffplayer.c
源码清单中涉及的一些概念简述如下:
container:
对应数据结构AVFormatContext
封装器,将流数据封装为指定格式的文件,文件格式如AVI、MP4等。
FFmpeg可识别五种流类型:视频video(v)、音频audio(a)、attachment(t)、数据data(d)、字幕subtitle。
codec:
对应数据结构AVCodec
编解码器。编码器将未压缩的原始图像或音频数据编码为压缩数据。解码器与之相反。
codec context:
对应数据结构AVCodecContext
编解码器上下文。此为非常重要的一个数据结构,后文分析。各API大量使用AVCodecContext来引用编解码器。
codec par:
对应数据结构AVCodecParameters
编解码器参数。新版本增加的字段。新版本建议使用AVStream->codepar替代AVStream->codec。
packet:
对应数据结构AVPacket
经过编码的数据。通过av_read_frame()从媒体文件中获取得到的一个packet可能包含多个(整数个)音频帧或单个
视频帧,或者其他类型的流数据。
frame:
对应数据结构AVFrame
解码后的原始数据。解码器将packet解码后生成frame。
2.7 编译
gcc -o ffplayer ffplayer.c -lavutil -lavformat -lavcodec -lavutil -lswscale -lSDL22.8 测试
选用clock_320.avi测试文件,此文件
ffprobe clock_320.avi打印视频文件信息如下:
1 2 3 4 5[avi @ 0x9286c0] non-interleaved AVI Input #0, avi, from 'clock_320.avi': Duration: 00:00:12.00, start: 0.000000, bitrate: 42 kb/s Stream #0:0: Video: msrle ([1][0][0][0] / 0x0001), pal8, 320x320, 1 fps, 1 tbr, 1 tbn, 1 tbc Stream #0:1: Audio: truespeech ([34][0][0][0] / 0x0022), 8000 Hz, mono, s16, 8 kb/s
运行测试命令:
./ffplayer clock_320.avi
