ffplay视频播放原理分析

本文深入解析FFmpeg中的ffplay命令行工具,阐述播放器工作流程,包括解协议、解封装、解码、音视频同步等关键步骤。详细分析了ffplay的main函数、read_thread函数以及视频解码线程video_thread,展示了如何设计一个简易播放器。

图片

作者 | 赵家祝

FFmpeg 框架由命令行工具和函数库组成, ffplay 是其中的一种命令行工具,提供了播放音视频文件的功能,不仅可以播放本地多媒体文件,还可以播放网络流媒体文件。本文从 ffplay 的整体播放流程出发,借鉴其设计思路,学习如何设计一款简易的播放器。

图片

一、播放器工作流程

GEEK TALK

在学习 ffplay 源码之前,为了方便理解,我们先宏观了解一下播放器在播放媒体文件时的工作流程。

  • **解协议:**媒体文件在网络上传输时,需要经过流媒体协议将媒体数据分段成若干个数据包,这样就可以满足用户一边下载一边观看的需求,而不需要等整个媒体文件都下载完成才能观看。常见的流媒体协议有 RTMP、HTTP、HLS、MPEG-DASH、MSS、HDS 等。由于流媒体协议中不仅仅包含媒体数据,还包含控制播放的信令数据。因此,解协议是移除协议中的信令数据,输出音视频封装格式数据。

  • **解封装:**封装格式也叫容器,就是将已经编码压缩好的视频流和音频流按照一定的格式放到一个文件中,常见的封装格式有 MP4、FLV、MPEG2-TS、AVI、MKV、MOV 等。解封装是将封装格式数据中的音频流压缩编码数据和视频流压缩编码数据分离,方便在解码阶段使用不同的解码器解码。

  • **解码:**压缩编码数据是在原始数据基础上采用不同的编码压缩得到的数据,而解码阶段就是编码的逆向操作。常见的视频压缩编码标准有 H.264/H.265 、MPEG-2 、AV1 、V8/9 等,音频压缩编码标准有 AAC 、MP3 等。解压后得到的视频图像数据是 YUV 或 RGB ,音频采样数据是 PCM 。

  • **音视频同步:**解码后的视频数据和音频数据是独立的,在送给显卡和声卡播放前,需要将视频和音频同步,避免播放进度不一致。

图片

二、main函数

GEEK TALK

ffplay 的使用非常简单,以ffplay -i input.mp4 -loop 2为例,表示使用 ffplay 播放器循环播放 input.mp4 文件两遍。执行该命令时,对应的源码在 fftools/ffplay.c 中,程序入口函数是 main 函数 。

注:本文 ffplay 源码基于 ffmpeg 4.4。

2.1 环境初始化

初始化部分主要调用以下函数:

  • init_dynload:调用SetDllDirectory(“”)删除 动态链接库(DLL)搜索路径中的当前工作目录,是 Windows 平台下的一种安全预防措施。

  • av_log_set_flag:设置 log 打印的标记为AV_LOG_SKIP_REPEATED,即跳过重复消息。

  • parse_loglevel:解析 log 的级别,会匹配命令中的-loglevel字段。如果命令中添加-report,会将播放日志输出成文件。

  • avdevice_register_all:注册特殊设备的封装库。

  • avformat_network_init:初始化网络资源,可以从网络中拉流。

  • parse_options:解析命令行参数,示例中的-i input.mp4和-loop 2就是通过这个函数解析的,支持的选项定义在options静态数组中。解析得到的文件名、文件格式分别保存在全局变量input_filename和file_iformat中。

2.2 SDL初始化

SDL的全称是 Simple DirectMedia Layer,是一个跨平台的多媒体开发库,支持 Linux、Windows、Mac OS等多个平台,实际上是对 DirectX、OpenGL、Xlib再封装,在不同操作系统上提供了相同的函数。ffplay 的播放显示是通过 SDL 实现的。

图片

main 函数中主要调用了以下三个 SDL 函数:

  • SDL_Init:初始化 SDL 库,传入的参数 flags,默认支持视频、音频和定时器,如果命令中配置了-an则禁用音频,配置了-vn则禁用视频。

  • SDL_CreateWindow:创建播放视频的窗口,该函数可以指定窗口的位置、大小,默认是 640*480 大小。

  • SDL_CreateRenderer:为指定的窗口创建渲染器上下文,对应的结构体是 SDL_Render 。我们既可以使用渲染器创建纹理,也可以渲染视图。

2.3 解析媒体流

stream_open函数是 ffplay 开始播放流程的起点,该函数传入两个参数,分别是文件名input_filename和文件格式file_iformat。下面是函数内部的处理流程:

**(1) 初始化VideoState:**VideoState 是 ffplay 中最大的结构体,所有的视频信息都定义在其中。初始化 VideoState 时,先定义 VideoState 结构体指针类型的局部变量is,分配堆内存。然后初始化结构体中的变量,例如视频流、音频流、字幕流的索引,并赋值函数入参 filename 和 iformat。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值