FFmpeg简易播放器的实现-视频播放

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

基于FFmpeg和SDL实现的简易视频播放器,主要分为读取视频文件解码和调用SDL播放两大部分。
本实验仅研究视频播放的实现方式。

FFmpeg简易播放器系列文章如下:
[1]. FFmpeg简易播放器的实现-最简版
[2]. FFmpeg简易播放器的实现-视频播放
[3]. FFmpeg简易播放器的实现-音频播放
[4]. FFmpeg简易播放器的实现-音视频播放
[5]. FFmpeg简易播放器的实现-音视频同步

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数据。

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

2. 简易播放器的实现-视频播放

2.1 实验平台

实验平台:openSUSE Leap 42.3
FFmpeg版本:4.1
SDL版本:2.0.9
FFmpeg开发环境搭建可参考“FFmpeg开发环境构建

2.2 源码清单

代码已经变得挺长了,不贴完整源码了,源码参考:
https://github.com/leichn/exercises/blob/master/source/ffmpeg/player_video/ffplayer.c

源码清单中涉及的一些概念简述如下:
container:
对应数据结构AVFormatContext
封装器,将流数据封装为指定格式的文件,文件格式如AVI、MP4等。
FFmpeg可识别五种流类型:视频video(v)、音频audio(a)、attachment(t)、数据data(d)、字幕subtitle。

codec:
对应数据结构AVCodec
编解码器。编码器将未压缩的原始图像或音频数据编码为压缩数据。解码器与之相反。

codec context:
对应数据结构AVCodecContext
编解码器上下文。此为非常重要的一个数据结构,后文分析。各API大量使用AVCodecContext来引用编解码器。

codec par:
对应数据结构AVCodecParameters
编解码器参数。新版本增加的字段。新版本建议使用AVStream->codepar替代AVStream->codec。

packet:
对应数据结构AVPacket
经过编码的数据。通过av_read_frame()从媒体文件中获取得到的一个packet可能包含多个(整数个)音频帧或单个
视频帧,或者其他类型的流数据。

frame:
对应数据结构AVFrame
解码后的原始数据。解码器将packet解码后生成frame。

plane:
如YUV有Y、U、V三个plane,RGB有R、G、B三个plane

slice:
图像中一片连续的行,必须是连续的,顺序由顶部到底部或由底部到顶部

stride/pitch:
一行图像所占的字节数,Stride = BytesPerPixel × Width,x字节对齐[待确认]

sdl window:
对应数据结构SDL_Window
播放视频时弹出的窗口。在SDL1.x版本中,只可以创建一个窗口。在SDL2.0版本中,可以创建多个窗口。

sdl texture:
对应数据结构SDL_Texture
一个SDL_Texture对应一帧解码后的图像数据。

sdl renderer:
对应数据结构SDL_Renderer
渲染器。将SDL_Texture渲染至SDL_Window。

sdl rect:
对应数据结构SDL_Rect
SDL_Rect用于确定SDL_Texture显示的位置。一个SDL_Window上可以显示多个SDL_Rect。这样可以实现同一窗口的分屏显示。

2.3 源码流程简述

流程比较简单,不画流程图了,简述如下:

media file --[decode]--> raw frame --[scale]--> yuv frame --[SDL]--> display  
media file ------------> p_frm_raw -----------> p_frm_yuv ---------> sdl_renderer  

加上相关关键函数后,流程如下:

media_file ---[av_read_frame()]----------->  
p_packet   ---[avcodec_send_pack
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值