【FFmpeg视频播放器开发】解封装解码流程、常用API和结构体简介(一)

这篇具有很好参考价值的文章主要介绍了【FFmpeg视频播放器开发】解封装解码流程、常用API和结构体简介(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

在正式编写 FFmpeg 播放器前,我们需要先简单了解下所要用到的 FFmpeg 库、播放与解码流程、函数和相关结构体。

二、FFmpeg 库简介

介绍
avcodec 音视频编解码核心库
avformat 音视频容器格式的封装和解析
avutil 核心工具库
swscal 图像格式转换的模块
swresampel 音频重采样
avfilter 音视频滤镜库 如视频加水印、音频变声
avdevice 输入输出设备库,提供设备数据的输入与输出

FFmpeg 就是依靠以上几个库,实现了强大的音视频编码、解码、编辑、转换、采集等能力。这里实现视频播放就除了 avfilter 库没用到。

三、FFmpeg播放流程

通常情况下,视频文件如 MP4,MKV、FLV 等都属于封装格式,就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。当我们播放一个媒体文件时,通常需要经过以下几个步骤:

【FFmpeg视频播放器开发】解封装解码流程、常用API和结构体简介(一)

可以看到这个视频播放器的实现需要涉及到以下内容:

  • 解封装(Demuxing):就是将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。例如,FLV 格式的数据,经过解封装操作后,输出 H.264 编码的视频码流和 AAC 编码的音频码流。

  • 软硬件解码(Decode):就是将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。通过解码,将压缩编码的视频数据 H.264,MPEG2 解码成为非压缩的颜色数据,例如 YUV 等等;将压缩编码的音频数据 AAC,MP3 解码成为非压缩的音频抽样数据,例如 PCM 数据。解码分为硬编码和软编码。

  • 像素格式转换:将 YUV 数据格式转换成 RGB 数据格式。

  • 重采样:对音频重新采样。

  • dts/pts:dts 是解码的时间戳,而 pts 是显示的时间戳。pts 用于获取当前播放进度。进度条移动需要用到av_seek_frame函数。

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

其中解码是最重要的,下面介绍一下解码的流程以及用到的 API 和结构体。

★文末名片可以免费领取音视频开发学习资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

【FFmpeg视频播放器开发】解封装解码流程、常用API和结构体简介(一)

 文章来源地址https://www.toymoban.com/news/detail-400050.html

四、FFmpeg解码流程

【FFmpeg视频播放器开发】解封装解码流程、常用API和结构体简介(一)

五、使用到的FFmpeg API说明

5.1 av_register_all()

  • 注册 FFmpeg 的所有组件。

  • 在 4.0 版本以后已经被弃用,所以实际不加也可以正常编解码音视频。

5.2 avformat_alloc_context()

用于初始化 AVFormatContext 对象。其原型如下:

AVFormatContext *avformat_alloc_context(void)
  • 由于 AVFormatContext 必须初始化为 NULL 或者用avformat_alloc_context()进行初始化。

5.3 avformat_open_input()

打开媒体文件,并获得解封装上下文。其原型如下:

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options)
  • ps:AVFormatContext 双重指针,函数调用成功之后将解封装上下文赋值给 ps。

  • url:可以是 rtsp、http 网络流地址,或者本地视频文件路径。

  • fmt:指定输入音视频的封装格式,一般情况下可以设置为 nullptr,则会自动探索。

  • fmt:强制指定 AVFormatContext 的成员 AVInputFormat,即输入音视频的封装格式。一般情况下可以设置为 NULL,这样会自动探索 AVInputFormat。

  • options:附加的一些选项,一般情况下可以设置为 nullptr,但有时候播放 rtsp 时需要设置下。

5.4 avformat_find_stream_info()

探测获取流信息。其原型如下:

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
  • 因为在一些格式当中没有头部信息,如 flv 格式,h264 格式,调用avformat_open_input()在打开文件之后就没有参数,也就无法获取到里面的信息。

  • 这个时候就可以调用此函数,因为它会试着去探测文件的格式,但是如果格式当中没有头部信息,那么它只能获取到编码、宽高这些信息,还是无法获得总时长。

  • 如果总时长无法获取到,则需要把整个文件读一遍,获取一下它的总帧数来计算。

5.5 avcodec_find_decoder()

查找解码器。函数的参数是所要用解码器的ID,成功返回查找到的解码器(没有找到就返回 NULL)。其原型如下:

AVCodec *avcodec_find_decoder(enum AVCodecID id);
  • id:查找到的解码器

5.6 avcodec_open2()

用于初始化一个音视频编解码器的 AVCodecContext,声明位于 libavcodec\utils.c。其原型如下:

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
  • avctx:需要初始化的 AVCodecContext。

  • codec:输入的AVCodec。

  • options:一些选项。例如使用 libx264 编码的时候,“preset”,“tune” 等都可以通过该参数设置。

5.7 av_read_frame()

读取码流中的音频若干帧或者视频一帧。例如,解码视频的时候,每解码一个视频帧,需要先调用av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码。其原型如下:

int av_read_frame(AVFormatContext *s, AVPacket *pkt)
  • s:解封装上下文。

  • pkt:存储一帧视频的压缩数据。

5.8 avcodec_decode_video2()

解码一帧视频数据。输入一个压缩编码的结构体 AVPacket,输出一个解码后的结构体 AVFrame。其原型如下:

int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
                         int *got_picture_ptr,
                         const AVPacket *avpkt);
  • avctx:需要初始化的 AVCodecContext。

  • codec:输入的AVCodec。

  • options:一些选项。例如使用libx264编码的时候,“preset”,“tune”等都可以通过该参数设置。

5.9 avformat_close_input()

关闭释放解封装上下文,并且设置为 0。其原型如下:

void avformat_close_input(AVFormatContext **s)
  • s:解封装上下文。

六、使用到的FFmpeg结构体说明

6.1 AVFormatContext

解封装上下文,是存储音视频封装格式中包含信息的结构体。

char filename[1024] // 保存打开的文件名,一般用在 rtsp、rtmp 断开重连
unsigned int nb_streams // 音视频流的个数
AVStream **streams // 存储视频流、音频流、字幕流信息
int64_t duration // 媒体文件的总时长,单位是把 1 秒切成 AV_TIME_BASE(1000000)份,即单位。为 us,注意不一定每个视频都能获取到 duration
int64_t bit_rate // 比特率(单位bps,转换为kbps需要除以1000)

6.2 AVStream

AVStream 是存储每一个音频/视频流信息的结构体。其重要的变量如下所示:

int index // 标识该视频/音频流
AVCodecContext *codec // 解码器,4.0 版本后已弃用
AVRational time_base // 时基。通过该值可以把PTS,DTS转化为实际的时间(单位为秒s)
int64_t duration // 该视频/音频流时长,单位为 ms
AVRational avg_frame_rate // 帧率(注:对视频来说,这个挺重要的)
AVPacket attached_pic // 附带的图片。比如说一些 MP3,AAC 音频文件附带的专辑封面
AVCodecParameters *codecpar // 音视频参数,新增用来替换AVCodecContext *codec

6.3 AVCodecContext

AVCodecContext 是一个描述编解码器上下文的结构体,包含了众多编解码器需要的参数信息。下面挑一些关键的变量来看看(这里只考虑解码)。

enum AVMediaType codec_type // 编解码器的类型(视频,音频...)
struct AVCodec  *codec // 采用的解码器AVCodec(H.264,MPEG2...)    
enum AVCodecID codec_id // 标示特定的编解码器(H.264,MPEG2...)
int format // 视频像素格式/音频采样数据格式
int width, height // 表示视频的宽和高
int bit_rate // 平均比特率    
int channels // 声道数(音频)
uint64_t channel_layout // 声道格式
int sample_rate // 采样率(音频)
AVRational time_base; // 时基。通过该值可以把PTS,DTS转化为实际的时间(单位为秒s)
uint8_t *extradata; int extradata_size; // 针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

6.4 AVCodec

AVCodec 是存储编码器信息的结构体。其重要的变量如下所示:

const char *name; // 编解码器的名字的简称
const char *long_name; // 编解码器名字的全称
enum AVMediaType type; // 指明了类型,是视频,音频,还是字幕
enum AVCodecID id; // ID,不重复
const AVRational *supported_framerates; // 支持的帧率(仅视频)
const enum AVPixelFormat *pix_fmts; // 支持的像素格式(仅视频),如RGB24、YUV420P等。
const int *supported_samplerates; // 支持的采样率(仅音频)
const enum AVSampleFormat *sample_fmts; // 支持的采样格式(仅音频)
const uint64_t *channel_layouts; // 支持的声道数(仅音频)
int priv_data_size; // 私有数据的大小

6.5 AVCodecParameters

新增用来替换AVCodecContext *codec。因为 AVCodecContext 结构体包含的参数太多,AVCodecParameters 将编码器的参数从 AVCodecContext 分离出来,AVCodecParameters 结构体中部分重要的参数如下:

enum AVMediaType codec_type // 编解码器的类型(视频,音频...)   
enum AVCodecID codec_id // 标示特定的编解码器(H.264,MPEG2...)
int format // 视频像素格式/音频采样数据格式
int width, height // 表示视频的宽和高
int bit_rate // 平均比特率    
int channels // 声道数(音频)
uint64_t channel_layout // 声道格式
int sample_rate // 采样率(音频)
AVRational time_base; // 时基。通过该值可以把PTS,DTS转化为实际的时间(单位为秒s)
uint8_t *extradata; int extradata_size; // 针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

可以看到两者的成员基本一致。

avcodec_decode_video2():解码一帧视频数据
sws_scale():转换视频数据格式    
av_frame_free():释放xx上下文申请的内存
avcodec_close():关闭解码器

6.6 AVPacket

AVPacket 是存储压缩编码数据相关信息的结构体。其重要的变量如下所示:

uint8_t *data; // 压缩编码的数据。
/* 例如对于H.264来说。1个AVPacket的data通常对应一个NAL。
注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流。因此在使用FFMPEG进行音视频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到音视频的码流文件。*/
int size; // data的大小
int64_t pts; // 显示时间戳
int64_t dts; // 解码时间戳
int stream_index; // 标识该AVPacket所属的视频/音频流。

6.7 AVFrame

AVFrame 结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是 YUV,RGB,对音频来说是 PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP 表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用 FFmpeg 进行码流分析的时候,AVFrame 是一个很重要的结构体。

下面看几个主要变量的作用(在这里考虑解码的情况):

uint8_t *data[AV_NUM_DATA_POINTERS]; // 解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)
int linesize[AV_NUM_DATA_POINTERS]; // data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。
int width, height; // 视频帧宽和高(1920x1080,1280x720...)
int nb_samples; // 音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个
int format; // 解码后原始数据类型(YUV420,YUV422,RGB24...)
int key_frame; // 是否是关键帧
enum AVPictureType pict_type; // 帧类型(I,B,P...)
AVRational sample_aspect_ratio; // 宽高比(16:9,4:3...)
int64_t pts; // 显示时间戳
int coded_picture_number; // 编码帧序号
int display_picture_number; // 显示帧序号

参考:

【雷神 - 解码】

图解FFMPEG打开媒体的函数avformat_open_input

FFmpeg 源代码简单分析:avformat_open_input()

FFmpeg 源代码简单分析:avformat_find_stream_info()

FFmpeg 源代码简单分析:av_read_frame()

FFmpeg 源代码简单分析:avcodec_decode_video2()

FFmpeg 源代码简单分析:avformat_close_input()

【雷神 - FFmpeg结构体】

FFMPEG中最关键的结构体之间的关系

FFMPEG结构体分析:AVFrame

FFMPEG结构体分析:AVFormatContext

FFMPEG结构体分析:AVCodecContext

FFMPEG结构体分析:AVIOContext

FFMPEG结构体分析:AVCodec

FFMPEG结构体分析:AVStream

FFMPEG结构体分析:AVPacket

作者:fengMisaka

★文末名片可以免费领取音视频开发学习资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

到了这里,关于【FFmpeg视频播放器开发】解封装解码流程、常用API和结构体简介(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • QT软件开发-基于FFMPEG设计视频播放器-软解图像(一)

    QT软件开发-基于FFMPEG设计视频播放器-软解图像(一)

    QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于FFMPEG设计视频播放器-GPU硬解视频(二) https://xiaolong.blog.csdn.net/article/details/126833434 QT软件开发-基于FFMPEG设计视频播放器-解码音频(三) https://xiaolong.blog.csdn.

    2023年04月08日
    浏览(50)
  • 用Qt开发的ffmpeg流媒体播放器,支持截图、录像,支持音视频播放,支持本地文件播放、网络流播放

    用Qt开发的ffmpeg流媒体播放器,支持截图、录像,支持音视频播放,支持本地文件播放、网络流播放

    本工程qt用的版本是5.8-32位,ffmpeg用的版本是较新的5.1版本。它支持TCP或UDP方式拉取实时流,实时流我采用的是监控摄像头的RTSP流。音频播放采用的是QAudioOutput,视频经ffmpeg解码并由YUV转RGB后是在QOpenGLWidget下进行渲染显示。本工程的代码有注释,可以通过本博客查看代码或者

    2024年02月03日
    浏览(59)
  • FFmpeg: 自实现ijkplayer播放器--06封装打开和关闭stream

    FFmpeg: 自实现ijkplayer播放器--06封装打开和关闭stream

    流程图 stream open 初始化SDL以允许⾳频输出; 初始化帧Frame队列 初始化包Packet队列 初始化时钟Clock 初始化音量 创建解复用读取线程read_thread 创建视频刷新线程video_refresh_thread

    2024年04月15日
    浏览(10)
  • FFmpeg参数说明FFmpegAndroid饺子视频播放器

    FFmpegAndroid https://github.com/xufuji456/FFmpegAndroid https://github.com/lipangit/JiaoZiVideoPlayer/tree/develop 饺子视频播放器 \\\'ffmpeg\\\' 不是内部或外部命令,也不是可运行的程序 或批处理文件 http://www.360doc.com/content/21/0204/15/54508727_960674843.shtml 【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式

    2024年02月11日
    浏览(11)
  • 基于 FFmpeg 的跨平台视频播放器简明教程(五):使用 SDL 播放视频

    基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux) 基于 FFmpeg 的跨平台视频播放器简明教程(三):视频解码 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换

    2024年02月12日
    浏览(48)
  • 基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频

    基于 FFmpeg 的跨平台视频播放器简明教程(六):使用 SDL 播放音频和视频

    基于 FFmpeg 的跨平台视频播放器简明教程(一):FFMPEG + Conan 环境集成 基于 FFmpeg 的跨平台视频播放器简明教程(二):基础知识和解封装(demux) 基于 FFmpeg 的跨平台视频播放器简明教程(三):视频解码 基于 FFmpeg 的跨平台视频播放器简明教程(四):像素格式与格式转换

    2024年02月13日
    浏览(71)
  • 基于FFmpeg的视频播放器之三:拉取rtsp流

    拉取网络流和打开本地文件流程差不多,详见:基于FFmpeg的视频播放器之二:解复用,下面是不同地方。 方法有很多,最方便的应该是用VLC串流了,具体步骤如下:https://blog.csdn.net/m0_61353061/article/details/120388230 当然也可以使用live555作为rtsp服务器,可参考:https://blog.csdn.net

    2023年04月25日
    浏览(47)
  • FFmpeg 播放器实现音视频同步的三种方式

    FFmpeg 播放器实现音视频同步的三种方式

    我们基于 FFmpeg 利用 OpenGL ES 和 OpenSL ES 分别实现了对解码后视频和音频的渲染,本文将实现播放器的最后一个重要功能:音视频同步。 老人们经常说, 播放器对音频和视频的播放没有绝对的静态的同步,只有相对的动态的同步,实际上音视频同步就是一个“你追我赶”的过

    2024年02月06日
    浏览(15)
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(三)

    介绍 在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本文,可参考我的前一篇文章音视频项目—基于FFmpeg和SDL的音视

    2024年02月05日
    浏览(54)
  • 音视频项目—基于FFmpeg和SDL的音视频播放器解析(二十一)

    介绍 在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本文,可参考我的前一篇文章音视频项目—基于FFmpeg和SDL的音视

    2024年02月02日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包