零基础读懂视频播放器控制原理——ffplay播放器源代码分析(一)

视频播放器原理其实大抵相同,都是对音视频帧序列的控制。只是一些播放器在音视频同步上可能做了更为复杂的帧预测技术,来保证音频和视频有更好的同步性。 

ffplayFFMpeg自带的播放器,使用了 ffmpeg解码库和用于视频渲染显示的sdl 库,也是业界播放器最初参考的设计标准。本文对ffplay源码进行分析,试图用更基础而系统的方法,来尝试解开播放器的音视频同步,以及播放/暂停、快进/后退的控制原理。

由于FFMpeg本身的跨平台特性,相比在移动端看音视频代码,在PC端利用VS查看和调试代码,分析播放器原理,要高效迅速很多。 

由于FFMpeg官方提供的ffmplayconsole中进行使用不够直观,本文直接分析CSDN上将ffplay移植到VC的代码(ffplay for MFC)进行分析。

文章目录:

一、初探mp4文件
二、以最简单播放器开始:FFmpeg解码 + SDL显示
三、先抛五个问题
四、ffplay代码总体结构
五、视频播放器的操作控制
5.1 ffplay所定义的关键结构体VideoState

5.2 补充基础知识——PTS和DTS

5.2 如何控制音视频同步

5.4 如何控制视频的播放和暂停?

5.5 逐帧播放是如何做的?

5.6 快进和后退

六、 这次分析ffplay代码的反省总结

一、初探mp4文件

为了让大家对视频文件有一个初步认识,首先来看对一个MP4文件的简单分析,如图1

1  对MP4文件解参 

从图一我们知道,每个视频文件都会有特定的封装格式、比特率、时长等信息。视频解复用之后,就划分为video_streamaudio_stream,分别对应视频流和音频流。

解复用之后的音视频有自己独立的参数,视频参数包括编码方式、采样率、画面大小等,音频参数包括采样率、编码方式和声道数等。

对解复用之后的音频和视频Packet进行解码之后,就变成原始的音频(PWM)和视频(YUV/RGB)数据,才可以在进行显示和播放。

其实这已经差不多涉及到了,视频解码播放的大部分流程,整个视频播放的流程如图2所示。

 

视频播放流程(图摘自http://blog.csdn.net/leixiaohua1020/article/details/50534150

 

二、以最简单播放器开始:FFmpeg解码 + SDL显示

为将问题简单化,先不考虑播放音频,只播放视频,代码流程图如图3所示:

播放器流程图(图源见水印)

流程图说明如下:

1.FFmpeg初始化的代码比较固定,主要目的就是为了设置AVFormatContext实例中相关成员变量的值,调用av_register_allavformat_open_input av_find_stream_infoavcodec_find_decoder等函数。

      如图4所示,初始化之后的AVFormatContext实例里面具体的值,调用av_find_stream_info就是找到文件中的音视频流数据,对其中的streams(包含音频、视频流)变量进行初始化。

图4 AVFormatContext初始化实例

2.av_read_frame不断读取stream中的下一帧,对其进行解复用得到视频的AVPacket,随后调用avcodec_decode_video2是视频帧AVPacket进行解码,得到图像帧AVFrame 

3.得到AVFrame之后,接下来就是放到SDL中进行渲染显示了,也很简单,流程见下面代码注释:

SDL_Overlay *bmp;
//将解析得到的AVFrame的数据拷贝到SDL_Overlay实例当中
SDL_LockYUVOverlay(bmp);
bmp->pixels[0]=pFrameYUV->data[0];
bmp->pixels[2]=pFrameYUV->data[1];
bmp->pixels[1]=pFrameYUV->data[2];    
bmp->pitches[0]=pFrameYUV->linesize[0];
bmp->pitches[2]=pFrameYUV->linesize[1];  
bmp->pitches[1]=pFrameYUV->linesize[2];

SDL_UnlockYUVOverlay(bmp);
//设置SDL_Rect,因为涉及到起始点和显示大小,用rect进行表示。
SDL_Rect rect;
rect.x = 0;   
rect.y = 0;   
rect.w = pCodecCtx->width; 
rect.h = pCodecCtx->height;   
//将SDL_Overlay数据显示到SDL_Surface当中。
SDL_DisplayYUVOverlay(bmp, &rect);
//延时40ms,留足ffmpeg取到下一帧并解码该帧的时间,随后继续读取下一帧
SDL_Delay(40);

由上面的原理可知,从帧流中获取到AVPacket,并且解码得到AVFrame,渲染到SDL窗口中。 

图5 视频播放状态图 

视频播放的流程总结一下就是:读取下一帧——>解码——>播放——>不断往复,状态图如图5所示。



  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以从FFmpeg项目的官方网站(https://ffmpeg.org/)下载ffplay播放器ffplayFFmpeg的一部分,因此您可以在FFmpeg的下载页面上找到相关的二进制文件或源代码。请注意,根据您的操作系统和需求,提供了不同版本的FFmpegffplay播放器。下载后,您可以按照安装说明进行安装并开始使用ffplay播放器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [ffplay 万能播放器](https://download.csdn.net/download/w13511069150/10970923)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [ffmpeg的下载及安装](https://blog.csdn.net/qq_33697094/article/details/112718101)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [ffmpeg下载安装教程及介绍](https://blog.csdn.net/yinshipin007/article/details/130650738)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值