本文为做者原创,转载请注明出处:http://www.javashuo.com/article/p-nbtinpnl-cm.htmlhtml
ffplay是一个很简单的播放器,可是初次接触仍会感到概念和细节至关繁多,分析并不容易。深刻理解一项技术须要足够的时间和大量的实践,由浅入深逐步迭代,没有时间就成了最大难题。本次分析过程断断续续持续了挺久,先是边读代码边加注释,后面才整理了笔记,再加上理解浅薄很难精简语言,所以行文比较啰嗦。笔记记录仓促,错误不免,欢迎指正交流。后续如有时间继续研究,将持续修正错误完善文档。git
ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg提供的解码器和SDL库进行视频播放。本文基于FFmpeg工程4.1版本进行分析,其中ffplay源码清单以下:
https://github.com/FFmpeg/FFmpeg/blob/n4.1/fftools/ffplay.cgithub
在尝试分析源码前,可先阅读以下参考文章做为铺垫:
[1]. 雷霄骅,视音频编解码技术零基础学习方法
[2]. 视频编解码基础概念
[3]. 色彩空间与像素格式
[4]. 音频参数解析
[5]. FFmpeg使用基础
另外,本文最后的参考资料对理解源码帮助很大,在此向各位分享者表示感谢。参考资料内容更精彩,建议阅读。网络
本笔记只放在一篇文档里的话篇幅过长,遂拆分红下面一系列文章:
[1]. ffplay源码分析1-概述
[2]. ffplay源码分析2-数据结构
[3]. ffplay源码分析3-代码框架
[4]. ffplay源码分析4-音视频同步
[5]. ffplay源码分析5-图像格式转换
[6]. ffplay源码分析6-音频重采样
[7]. ffplay源码分析7-播放控制数据结构
下图引用自“雷霄骅,视音频编解码技术零基础学习方法”,因原图过小,看不太清楚,故从新制做了一张图片。
以下内容引用自“雷霄骅,视音频编解码技术零基础学习方法”:框架
解协议
将流媒体协议的数据,解析为标准的相应的封装格式数据。视音频在网络上传播的时候,经常采用各类流媒体协议,例如HTTP,RTMP,或是MMS等等。这些协议在传输视音频数据的同时,也会传输一些信令数据。这些信令数据包括对播放的控制(播放,暂停,中止),或者对网络状态的描述等。解协议的过程当中会去除掉信令数据而只保留视音频数据。例如,采用RTMP协议传输的数据,通过解协议操做后,输出FLV格式的数据。ide解封装
将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类不少,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的做用就是将已经压缩编码的视频数据和音频数据按照必定的格式放到一块儿。例如,FLV格式的数据,通过解封装操做后,输出H.264编码的视频码流和AAC编码的音频码流。函数解码
将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含AAC,MP3,AC-3等等,视频的压缩编码标准则包含H.264,MPEG2,VC-1等等。解码是整个系统中最重要也是最复杂的一个环节。经过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如YUV420P,RGB等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如PCM数据。源码分析音视频同步
根据解封装模块处理过程当中获取到的参数信息,同步解码出来的视频和音频数据,并将视频音频数据送至系统的显卡和声卡播放出来。学习
_______ ______________ | | | | | input | demuxer | encoded data | decoder | file | ---------> | packets | -----+ |_______| |______________| | v _________ | | | decoded | | frames | |_________| ________ ______________ | | | | | | | output | <-------- | encoded data | <----+ | file | muxer | packets | encoder |________| |______________|
ffmpeg
调用libavformat库(包含解复用器demuxer),从输入文件中读取到包含编码数据的包(packet)。若是有多个输入文件,ffmpeg
尝试追踪多个有效输入流的最小时间戳(timestamp),用这种方式实现多个输入文件的同步。
而后编码包被传递到解码器(decoder),解码器解码后生成原始帧(frame),原始帧能够被滤镜(filter)处理(图中未画滤镜),经滤镜处理后的帧送给编码器,编码器将之编码后输出编码包。最终,由复用器(muxex)将编码码写入特定封装格式的输出文件。
ffplay不须要编码过程,是将上图中的解码后帧送往屏幕显示。
本节内容引用自“雷霄骅,最简单的视音频播放示例7:SDL2播放RGB/YUV”
SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成。SDL提供了数种控制图像、声音、输出入的函数,让开发者只要用相同或是类似的代码就能够开发出跨多个平台(Linux、Windows、Mac OS X等)的应用软件。目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。用下面这张图能够很明确地说明SDL的位置。
SDL实际上并不限于视音频的播放,它将功能分红下列数个子系统(subsystem):
Video(图像):图像控制以及线程(thread)和事件管理(event)
Audio(声音):声音控制
Joystick(摇杆):游戏摇杆控制
CD-ROM(光盘驱动器):光盘媒体控制
Window Management(视窗管理):与视窗程序设计集成
Event(事件驱动):处理事件驱动
SDL播放视频流程以下:
可参考示例程序:“FFmpeg简易播放器的实现-最简版”
[1] 雷霄骅,视音频编解码技术零基础学习方法
[2] 视频编解码基础概念, http://www.javashuo.com/article/p-kfylstit-o.html
[3] 色彩空间与像素格式, http://www.javashuo.com/article/p-kwxfzypa-bs.html
[4] 音频参数解析, http://www.javashuo.com/article/p-qkmpwcem-bt.html
[5] FFmpeg基础概念, http://www.javashuo.com/article/p-hkmuzuvf-cb.html
[6] 零基础读懂视频播放器控制原理:ffplay播放器源代码分析, https://cloud.tencent.com/developer/article/1004559
[7] An ffmpeg and SDL Tutorial, Tutorial 05: Synching Video
[8] 视频同步音频, https://zhuanlan.zhihu.com/p/44615401
[9] 即时通信音视频开发(一):视频编解码之理论概述, http://www.52im.net/thread-228-1-1.html
[10] 音频同步视频, https://zhuanlan.zhihu.com/p/44680734
[11] 音视频同步(播放)原理, http://www.javashuo.com/article/p-cohhhvtj-ea.html
[12] 对ffmpeg的时间戳的理解笔记, https://blog.csdn.net/topsluo/article/details/76239136
[13] ffmpeg音视频同步---视频同步到音频时钟, http://www.javashuo.com/article/p-kkvxtpch-bh.html
[14] FFmpeg音视频同步原理与实现, https://www.jianshu.com/p/3578e794f6b5
[15] FFmpeg学习4:音频格式转换, http://www.javashuo.com/article/p-vnkeckad-gy.html
[16] ffmpeg关于音频的总结(一), http://www.javashuo.com/article/p-dyxqgfmn-cg.html
[17] FFmpeg关于nb_smples,frame_size以及profile的解释, https://blog.csdn.net/zhuweigangzwg/article/details/53335941
[18] ffplay frame queue分析, https://zhuanlan.zhihu.com/p/43564980
[19] 难点seek操做, https://github.com/rockcarry/ffplayer/wiki/%E9%9A%BE%E7%82%B9-seek-%E6%93%8D%E4%BD%9C
2018-12-28 V1.0 初稿 2019-01-15 V1.0 增长FrameQueue数据结构说明 2019-01-15 V1.0 增长图像格式转换说明,新增音频重采样章节 2019-01-18 V1.0 增长SEEK操做说明章节 2019-01-19 V1.0 整理章节排序