本文为作者原创,转载请注明出处: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 播放器基本原理

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



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

解协议

将流媒体协议的数据,解析为标准的相应的封装格式数据。视音频在网络上传播的时候,常常采用各种流媒体协议,例如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实际上并不限于视音频的播放,它将功能分成下列数个子系统(subsystem):

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

Audio(声音):声音控制

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

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

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

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

SDL播放视频流程如下:

  1. 初始化
  1. 初始化SDL
  2. 创建窗口(Window)
  3. 基于窗口创建渲染器(Render)
  4. 创建纹理(Texture)
  1. 循环显示画面
  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 整理章节排序

ffplay源码分析1-概述的更多相关文章

  1. ffplay源码分析5-图像格式转换

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10311376.html ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg ...

  2. ffplay源码分析6-音频重采样

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10312713.html ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg ...

  3. ffplay源码分析7-播放控制

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10316225.html ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg ...

  4. ffplay源码分析4-音视频同步

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10307089.html ffplay是FFmpeg工程自带的简单播放器,使用FFmpeg ...

  5. ffplay源码分析3-代码框架

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

  6. ffplay源码分析2-数据结构

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

  7. Netty源码分析(前言, 概述及目录)

    Netty源码分析(完整版) 前言 前段时间公司准备改造redis的客户端, 原生的客户端是阻塞式链接, 并且链接池初始化的链接数并不高, 高并发场景会有获取不到连接的尴尬, 所以考虑了用netty长 ...

  8. Kafka源码分析(一) - 概述

    系列文章目录 https://zhuanlan.zhihu.com/p/367683572 目录 系列文章目录 一. 实际问题 二. 什么是Kafka, 如何解决这些问题的 三. 基本原理 1. 基本 ...

  9. HDFS源码分析一-概述

    HDFS 主要包含 NameNode, SecondaryNameNode, DataNode 以及 HDFS Client . 我们从以下这几部分讲: 1. HDFS概述 2. NameNode 实 ...

随机推荐

  1. scrapy分布式

    开始之前我们得知道scrapy-redis的一些配置:PS 这些配置是写在Scrapy项目的settings.py中的! #启用Redis调度存储请求队列SCHEDULER = "scrap ...

  2. JPA Annotation注解

    JPA & Hibernate 注解 先说说JPA和Hibernate的关系 JPA(Java Persistence API),是Java EE 5的标准ORM接口,也是ejb3规范的一部分 ...

  3. 8.正则表达式和XPath

    1.使用正则表达式爬取内涵段子 import requests import re def loadPage(page): url = "http://www.neihan8.com/art ...

  4. C# .NET 获取枚举值的自定义属性

    一.定义一个类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  5. [NewCoder 7] 用两个栈实现队列

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 水题,直接上代码: class Solution { public: void push(int nod ...

  6. Spring Security Hello World Example--reference

    In this tutorial, we will see how we can use Spring security to protect specific resources. This Hel ...

  7. Rabbit MQ 入门指南

    rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...

  8. 使用JAVA API 解析ORC File

    使用JAVA API 解析ORC File orc File 的解析过程中,使用FileInputFormat的getSplits(conf, 1)函数, 然后使用 RecordReaderreade ...

  9. HTML给table添加单线边框

    一般来说,给表格加边框都会出现不同的问题,以下是给表格加边框后展现比较好的方式 <style> table,table tr th, table tr td { border:1px so ...

  10. 【转】C#中dynamic的正确用法

    原文:http://www.cnblogs.com/qiuweiguo/archive/2011/08/03/2125982.html dynamic是FrameWork4.0的新特性.dynamic ...