这个播放器调用了FFmpeg中的libavformat和libavcodec两个库完成了视频解码工作。但是这不是一个“纯净”的解码器。
该解码器中libavformat完成封装格式的解析,而libavcodec完成解码工作。
一个“纯净”的解码器,理论上说只需要使用libavcodec就足够了,并不需要使用libavformat。本文记录的解码器就是这样的一个“纯净”的解码器,它仅仅通过调用libavcodec将H.264/HEVC等格式的压缩视频码流解码成为YUV数据。
流程图
本文记录的纯净版本的基于FFmpeg的解码器的函数调用流程图如下图所示。需要注意的是,此解码器的输入必须是只包含视频编码数据“裸流”(例如H.264、HEVC码流文件),而不能是包含封装格式的媒体数据(例如AVI、MKV、MP4)。

流程图中关键函数的作用如下所列:
avcodec_register_all():注册所有的编解码器。
avcodec_find_decoder():查找解码器。
avcodec_alloc_context3():为AVCodecContext分配内存。
avcodec_open2():打开解码器。
avcodec_decode_video2():解码一帧数据。
有两个平时“不太常见”的函数:
av_parser_init():初始化AVCodecParserContext。
av_parser_parse2():解析获得一个Packet。
两个存储数据的结构体如下所列:
AVFrame:存储一帧解码后的像素数据
AVPacket:存储一帧(一般情况下)压缩编码数据
AVCodecParser
AVCodecParser用于解析输入的数据流并把它分成一帧一帧的压缩编码数据。
比较形象的说法就是把长长的一段连续的数据“切割”成一段段的数据。他的核心函数是av_parser_parse2()。它的定义如下所示。
/**
* Parse a packet.
*
* @param s parser context.
* @param avctx codec context.
* @param poutbuf set to pointer to parsed buffer or NULL if not yet finished.
* @param poutbuf_size set to size of parsed buffer or zero if not yet finished.
* @param buf input buffer.
* @param buf_size input length, to signal EOF, this should be 0 (so that the last frame can be output).
* @param pts input presentation timestamp.
* @param dts input decoding timestamp.
* @param pos input byte position in stream.

本文介绍了一个不依赖libavformat的FFmpeg视频解码器,仅使用AVCodec进行解码。解码器通过AVCodecContext进行内存分配和解码操作,输入必须是不含封装格式的裸流数据。文章详细阐述了解码器的流程变化,包括注册编解码器、数据解析、解码帧等关键步骤,并对比了与libavformat相关功能的差异。
最低0.47元/天 解锁文章
606

被折叠的 条评论
为什么被折叠?



