ffplay源码分析1-概述

简介: ffplay是一个很简单的播放器,但是初次接触仍会感到概念和细节相当繁多,分析并不容易。深入理解一项技术需要足够的时间和大量的实践,由浅入深逐步迭代,没有时间就成了最大难题。本次分析过程断断续续持续了挺久,先是边读代码边加注释,后面才整理了笔记,再加上理解浅薄很难精简语言,因此行文比较啰嗦。笔记记录仓促,错误难免,欢迎指正交流。后续若有时间继续研究,将持续修正错误完善文档。

作者:叶余

来源:https://www.cnblogs.com/leisure_chn/p/10301215.html


ffplay是一个很简单的播放器,但是初次接触仍会感到概念和细节相当繁多,分析并不容易。深入理解一项技术需要足够的时间和大量的实践,由浅入深逐步迭代,没有时间就成了最大难题。本次分析过程断断续续持续了挺久,先是边读代码边加注释,后面才整理了笔记,再加上理解浅薄很难精简语言,因此行文比较啰嗦。笔记记录仓促,错误难免,欢迎指正交流。后续若有时间继续研究,将持续修正错误完善文档。

ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg提供的解码器和SDL库进行视频播放。本文基于FFmpeg工程4.1版本进行分析,其中ffplay源码清单如下:

https://github.com/FFmpeg/FFmpeg/blob/n4.1/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 播放器基本原理

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

image.png

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

解协议

将流媒体协议的数据,解析为标准的相应的封装格式数据。视音频在网络上传播的时候,常常采用各种流媒体协议,例如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的位置。

image.png

SDL实际上并不限于视音频的播放,它将功能分成下列数个子系统(subsystem):

Video(图像):图像控制以及线程(thread)和事件管理(event)

Audio(声音):声音控制

Joystick(摇杆):游戏摇杆控制

CD-ROM(光盘驱动器):光盘媒体控制

Window Management(视窗管理):与视窗程序设计集成

Event(事件驱动):处理事件驱动

SDL播放视频流程如下:

  1. 初始化
  2. 初始化SDL
  3. 创建窗口(Window)
  4. 基于窗口创建渲染器(Render)
  5. 创建纹理(Texture)
  6. 循环显示画面
  7. 设置纹理的数据
  8. 纹理复制给渲染目标
  9. 显示

可参考示例程序:“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 整理章节排序


「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。

阿里云视频云@凡科快图.png

相关文章
|
6月前
|
Web App开发 编解码 安全
【WebRTC 入门教程】全面解析WebRTC:从底层原理到Qt和FFmpeg的集成应用
【WebRTC 入门教程】全面解析WebRTC:从底层原理到Qt和FFmpeg的集成应用
2872 1
|
6月前
|
存储 缓存 调度
FFmpeg开发笔记(十九)FFmpeg开启两个线程分别解码音视频
《FFmpeg开发实战》第10章示例playsync.c在处理音频流和视频流交错的文件时能实现同步播放,但对于分开存储的格式,会出现先播放全部声音再快速播放视频的问题。为解决此问题,需改造程序,增加音频处理线程和队列,以及相关锁,先将音视频帧读入缓存,再按时间戳播放。改造包括声明新变量、初始化线程和锁、修改数据包处理方式等。代码修改后在playsync2.c中,编译运行成功,控制台显示日志,SDL窗口播放视频并同步音频,证明改造有效。
108 0
FFmpeg开发笔记(十九)FFmpeg开启两个线程分别解码音视频
|
6月前
|
JavaScript Java 测试技术
基于Java的视频播放器的设计与实现(源码+lw+部署文档+讲解等)
基于Java的视频播放器的设计与实现(源码+lw+部署文档+讲解等)
83 0
|
6月前
|
存储 编解码 缓存
FFmpeg之旅:深入解析FFplay源码
FFmpeg之旅:深入解析FFplay源码
613 0
|
编解码 API 数据处理
[笔记]音视频学习之ffmpeg实践《三》ffmpeg解封装
[笔记]音视频学习之ffmpeg实践《三》ffmpeg解封装
|
编解码 Linux 数据安全/隐私保护
深入浅出FFmpeg:一款强大的多媒体处理工具
深入浅出FFmpeg:一款强大的多媒体处理工具
167 0
|
存储 开发工具 git
如何使用ffmpeg生成视频缩略图
如何使用ffmpeg生成视频缩略图
|
编解码 vr&ar 计算机视觉
ffmpeg工具的简单使用
ffmpeg工具的使用
166 0
|
存储 编解码 缓存
ffplay源码分析3-代码框架
ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg提供的解码器和SDL库进行视频播放。
311 0
ffplay源码分析3-代码框架
|
存储 编解码 算法
FFmpeg libswscale源码分析1-API介绍
libswscale 是 FFmpeg 中完成图像尺寸缩放和像素格式转换的库。用户可以编写程序,调用 libswscale 提供的 API 来进行图像尺寸缩放和像素格式转换。也可以使用 scale 滤镜完成这些功能,scale 滤镜实现中调用了 libswscale 的 API。libswscale 的 API 非常简单,就一个 sws_scale() 接口,但内部的实现却非常复杂。
374 0
FFmpeg libswscale源码分析1-API介绍