ffplay源码分析1-概述

本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10301215.html

这是一篇音视频自学笔记。ffplay 是一个具备播放器基本功能、能用且好用的、最简单的播放器,学习播放器原理可以从 ffplay 入手。本文研究 ffplay 实现细节,涉及 ffplay 中多线程的创建和职责、音视频滤镜的使用、音视频同步、图像格式转换、音频重采样、SDL 播放等内容。即便 ffplay 是一个很简单的播放器,但是初次接触仍会感到概念和细节相当繁多,分析并不容易。深入理解一项技术需要足够的时间和大量的实践,由浅入深逐步迭代,业余时间来做这些事情时间不足就成了最大难题。本次分析过程断断续续持续了挺久,先是边读代码边加注释,后面才整理了笔记,再加上理解浅薄很难精简语言,因此行文比较啰嗦。笔记记录仓促,错误难免,欢迎指正交流。后续若有时间继续研究,将持续修正错误完善笔记内容。

ffplay 是 FFmpeg 工程自带的简单播放器,使用 FFmpeg 提供的解码器和 SDL 库进行视频播放。本文基于 FFmpeg 工程 8.0 版本进行分析,其中 ffplay 源码清单如下:
https://github.com/FFmpeg/FFmpeg/blob/n8.0/fftools/ffplay.c

在尝试分析源码前,可先阅读如下参考文章作为铺垫:
[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-播放控制

1. 基本原理

1.1 播放器基本原理

下图引用自“雷霄骅,视音频编解码技术零基础学习方法”,因原图太小,看不太清楚,故重新制作了一张图片。

播放器基本原理示意图

如下内容引用自“雷霄骅,视音频编解码技术零基础学习方法”:

解协议
将流媒体协议的数据,解析为标准的相应的封装格式数据。视音频在网络上传播的时候,常常采用各种流媒体协议,例如 HTTP,RTMP,或是 MMS 等等。这些协议在传输视音频数据的同时,也会传输一些信令数据。这些信令数据包括对播放的控制(播放,暂停,停止),或者对网络状态的描述等。解协议的过程中会去除掉信令数据而只保留视音频数据。例如,采用 RTMP 协议传输的数据,经过解协议操作后,输出 FLV 格式的数据。

解封装
将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类很多,例如 MP4,MKV,RMVB,TS,FLV,AVI 等等,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。例如,FLV 格式的数据,经过解封装操作后,输出 H.264 编码的视频码流和 AAC 编码的音频码流。

解码
将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含 AAC,MP3,AC-3 等等,视频的压缩编码标准则包含 H.264,MPEG2,VC-1 等等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如 YUV420P,RGB 等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如 PCM 数据。

音视频同步
根据解封装模块处理过程中获取到的参数信息,同步解码出来的视频和音频数据,并将视频音频数据送至系统的显卡和声卡播放出来。

1.2 FFmpeg 转码流程

 _______              ______________
|       |            |              |
| 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 不需要编码过程,是将上图中解码后的原始帧送往屏幕显示。

1.3 SDL 播放过程简介

本节内容引用自“雷霄骅,最简单的视音频播放示例 7:SDL2 播放 RGB/YUV

SDL (Simple DirectMedia Layer) 是一套开放源代码的跨平台多媒体开发库,使用 C 语言写成。SDL 提供了数种控制图像、声音、输入输出的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台 (Linux、Windows、Mac OS X 等) 的应用软件。目前 SDL 多用于开发游戏、模拟器、媒体播放器等多媒体应用领域。用下面这张图可以很明确地说明 SDL 的位置。

SDL 示意图

SDL 实际上并不限于视音频的播放,它将功能分成下列数个子系统 (subsystem):
图像 (Video):图像控制以及线程 (thread) 和事件 (event) 管理
声音 (Audio):声音控制
摇杆 (Joystick):游戏摇杆控制
光盘驱动器 (CD-ROM):光盘媒体控制
视窗管理 (Window Management):与视窗程序设计集成
事件 (Event) 管理:处理事件驱动

SDL 播放视频流程如下:

1. 初始化  
1) 初始化SDL  
2) 创建窗口(Window)  
3) 基于窗口创建渲染器(Render)  
4) 创建纹理(Texture)  

2. 循环显示画面  
1) 设置纹理的数据  
2) 纹理复制给渲染目标  
3) 显示  

可参考示例程序:“FFmpeg 简易播放器的实现-最简版

8. 参考资料

[1] 雷霄骅,视音频编解码技术零基础学习方法
[2] 视频编解码基础概念, https://www.cnblogs.com/leisure_chn/p/10285829.html
[3] 色彩空间与像素格式, https://www.cnblogs.com/leisure_chn/p/10290575.html
[4] 音频参数解析, https://blog.csdn.net/caoshangpa/article/details/51218597
[5] FFmpeg基础概念, https://www.cnblogs.com/leisure_chn/p/10297002.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] 音视频同步(播放)原理, https://blog.csdn.net/zhuweigangzwg/article/details/25815851
[12] 对ffmpeg的时间戳的理解笔记, https://blog.csdn.net/topsluo/article/details/76239136
[13] ffmpeg音视频同步---视频同步到音频时钟, https://my.oschina.net/u/735973/blog/806117
[14] FFmpeg音视频同步原理与实现, https://www.jianshu.com/p/3578e794f6b5
[15] FFmpeg学习4:音频格式转换, https://www.cnblogs.com/wangguchangqing/p/5851490.html
[16] ffmpeg关于音频的总结(一), https://blog.csdn.net/zhuweigangzwg/article/details/51499123
[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/难点-seek-操作

9. 修改记录

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 整理章节排序
2025-08-12 V1.1 更新 FFmpeg 版本到 8.0

posted @ 2019-01-21 21:46  叶余  阅读(13595)  评论(0)    收藏  举报