ffmpeg的内部Video Buffer管理和传送机制

ffmpeg的内部Video
Buffer
管理和传送机制

本文主要介绍ffmpeg解码器内部管理Video
Buffer的原理和过程,ffmpeg的Videobuffer为内部管理,其流程大致为:注册处理函数->帧级释放->帧级申请->清空。

1 注册get_buffer()和release_buffer()

FFAPI_InitCodec()

avcodec_alloc_context()

avcodec_alloc_context2()

avcodec_get_context_default2(AVCodecContext *s,…){

……

s->get_buffer = avcodec_default_get_buffer;

s->release_buffer = avcodec_default_release_buffer;

……

}

2帧级的内存申请和释放调用

图1帧级内存申请和释放的函数调用

2.1
FFAPI函数调用libavcodec相应的codec(WMV3对应的Codec是VC1)函数进行解码,过程中调用内部buffer处理函数。其中buffer管理被统一封装到Mpegvideo接口中(包括的codec有H.261,
H.263, H.264, mpeg12, rv10,rv34, svq1和VC1)

FFAPI_Decode()

avcodec_decode_video2()

avctx->codec->decode()//初始化过程中注册codec,wmv3的解码函数是

vc1_decode_frame(){

decode_vc1_header;

MPV_frame_start();                                     //2.2.2

vc1_decode_blocks();

MPV_frame_end();                                     //2.2.3

}

2.2 MPV_frame_start()//通过调用get_buffer()申请当前帧的video buffer。

MPV_frame_start()

//首先调用release_buffer()释放非参考帧的video buffer

for(i=0; i<MAX_PICTURE_COUNT; i++)

if(s->picture[i].data[0] && !s->picture[i].reference)

free_frame_buffer(s, &s->picture[i]);
//调用s->avctx->get_buffer(),回调avcodec_default_release_buffer()

ff_alloc_picture()

alloc_frame_buffer()

s->avctx->get_buffer()      //回调avcodec_default_get_buffer()

2.3MPV_frame_end()                                          //完成视频加边等操作

3帧级的内存申请和释放处理方法

3.1内部buffer数据结构

–   typedef struct InternalBuffer{

–       int last_pic_num;

–       uint8_t *base[4];

–       uint8_t *data[4];

–       int linesize[4];

–       int width, height;

–       enum PixelFormat pix_fmt;

–   }InternalBuffer;

–   typedef struct AVCodecContext {

–          ……

–   int
internal_buffer_count; //记录当前内部buffer的个数,get_buffer和release_buffer时均需要对其进行维护。

–   void *internal_buffer;//初始化为数组InternalBuffer
[INTERNAL_BUFFER_SIZE]

–   ……

–   } AVCodecContext;

Codec通过维护internal_buffer_count和internal_buffer实现高效的内存管理。

3.2参考帧管理相关数据结构

–   typedef  struct Picture{

–       uint8_t *data[4];

–       int linesize[4];

–       uint8_t *base[4];

–       int reference;

–       ……

–   } Picture;

–   typedef  struct MpegEncContext{

–       ……

–       Picture*
picture;   //初始化为数组Picture[INTERNAL_BUFFER_SIZE]

–       Picture*
last_picture_ptr;      //指向前一帧

–       Picture*
next_picture_ptr;;    //双向预测时,指向后一帧

–       Picture*
current_picture_ptr;//指向当前帧

–   ……

–   } MpegEncContext; 

3.3申请和释放原理

图2 内存申请和释放原理

(1)初始化时将internal_buffer全部清零

(2)释放buffer时,将释放的buffer与最后一个有效buffer交换,而不是用av_free()释放内存。

avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){

s->internal_buffer_count–;

last =
&((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];

//将last buffer和要释放的buffer交换,使last buffer变成无效buffer,在下次get_buffer时能被申请到。

FFSWAP(InternalBuffer, *buf, *last);

for(i=0; i<4; i++){

pic->data[i]=NULL;

}

}

(3)申请buffer时,检查internal_buffer[internal_buffer_count]的基址是否非空,若非空则直接使用internal_buffer[internal_buffer_count];若空,使用av_malloc()函数进行申请。

这样处理的好处是避免了频繁的调用malloc()和free(),从而提升了效率。

avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){

……

buf=
&((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];

get_size_info(size[]);

buf->base[0, 1, 2] = av_malloc(size[0, 1, 2]);

buf->data[0, 1, 2] = buf->base[0, 1, 2] + padding_offset[0, 1, 2];

……

}

(4)决定输出帧是在每帧解码后,根据当前帧的类型和参考信息决定输出帧。

if (s->pict_type == FF_B_TYPE || s->low_delay) {

*pict= *(AVFrame*)s->current_picture_ptr;

} else if (s->last_picture_ptr != NULL) {

*pict= *(AVFrame*)s->last_picture_ptr;

}

3.4举例——假设解码IPBPB的非H.264码流。

(1)初始化后的状态如所示,IBC为ctx->internal_buffer_count,CurPtr为s->current_picture_ptr,LastPtr为s->last_picture_ptr,NextPtr为s->next_picture_ptr。

gpAVPicture指针为输出图像的指针。

图3 初始化状态

(2)解码第一个I帧,过程中不会不调用release_buffer(),get_buffer()得到picture[0] ,此时不输出任何图像。

图4解码第一个I帧后的状态

(3)解码第一个P帧,过程中不调用release_buffer(),get_buffer()得到picture[1] ,输出picture[0]。

图5解码第一个P帧后的状态

(4)解码第一个B帧,过程中不调用release_buffer(),get_buffer()得到picture[2] ,输出picture[2]。

图6解码第一个B帧后的状态

(5)解码第二个P帧,调用release_buffer(&picture[2]),再调用get_buffer(),得到picture[2], 输出picture[1]。

图7解码第二个P帧的状态

ref: http://blog.csdn.net/xietao_live_cn/article/details/6327451

时间: 2024-08-11 18:39:23

ffmpeg的内部Video Buffer管理和传送机制的相关文章

大型分布式C++框架《四:netio之buffer管理器 下》

每周一篇又来了.这次主要介绍netio的buffer管理器. 首先buffer管理是每一个网络层不可回避的问题.怎么高效的使用buffer是很关键的问题.这里主要介绍下我们的netio是怎么处理.说实话 这是我见过比较蛋疼buffer管理.  反正我是看了好几天 才看明白的.      最近看了下Qcon2016的视频.里面很多大牛介绍分布式平台. 感觉特别牛逼~~. 感觉我们的分布式相比他们的这些还是简陋了点.感兴趣的同学可以去看看      http://daxue.qq.com/conte

ANDROID窗口管理服务实现机制和架构分析

 一.功能 窗口管理是ANDROID框架一个重要部分,主要包括如下功能: (1)Z-ordered的维护 (2)窗口的创建.销毁 (3)窗口的绘制.布局 (4)Token管理,AppToken (5)活动窗口管理(FocusWindow) (6)活动应用管理(FocusAPP) (7)输入法管理 (8)系统消息收集与分发 这些功能主要由一个窗口管理服务和相应的客户端来实现的,客户端通过BINDER机制与服务实现交互.       窗口管理服务端负责主要的窗口管理功能,由一个WindowMan

ActiveMQ讯息传送机制以及ACK机制

http://blog.csdn.net/lulongzhou_llz/article/details/42270113 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的. 一. ActiveMQ消息传送机制 Producer客户端使用来发送消息的, Consumer客户端用来消费消息:它们的协同中心就是ActiveMQ br

memcached的内存管理与删除机制

memcached的内存管理与删除机制 简介 注意:Memcache最大的value也只能是1M的空间,超过1M的数据无法保存(修改memcache源代码). ? 注意:内存碎片化永远都存在,只是哪一种方式可以使得内存碎片最小. ? 1. 什么是内存碎片化? 在使用这种内存缓存系统的时候,由于不断的申请,释放,就会形成一些很小的内存片段,无法被利用,这种现象就叫做,内存的碎片化.这个小块就是操作系统无法使用的空间. ????注意:内存碎片化永远存在,无法消除,但是可以利用最好的算法,降到最低.

JVM内存管理及GC机制

一.概述 JavaGC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.经过这么长时间的发展,javaGC机制已经日臻完善,几乎可以自动的为我们做绝大多数的事情. 虽然java不需要开发人员显示的分配和回收内存,这对开发人员确实降低了不少编程难度,但也可能带来一些副作用: 1. 有可能不知不觉浪费了很多内存 2. JVM花费过

Flink状态管理和容错机制介绍

本文主要内容如下: 有状态的流数据处理: Flink中的状态接口: 状态管理和容错机制实现: 阿里相关工作介绍: 一.有状态的流数据处理# 1.1.什么是有状态的计算# 计算任务的结果不仅仅依赖于输入,还依赖于它的当前状态,其实大多数的计算都是有状态的计算. 比如wordcount,给一些word,其计算它的count,这是一个很常见的业务场景.count做为输出,在计算的过程中要不断的把输入累加到count上去,那么count就是一个state. 1.2.传统的流计算系统缺少对于程序状态的有效

ffmpeg转码MPEG2-TS的音视频同步机制分析

http://blog.chinaunix.net/uid-26000296-id-3483782.html 一.FFmpeg忽略了adaptation_field()数据FFmpeg忽略了包含PCR值的adaptation_filed数据; 代码(libavformat/mpegts.c)分析如下: /* 解析TS包 */int handle_packet(MpegTSContext *ts, const uint8_t *packet){  ...   pid = AV_RB16(packe

Linux内存管理3---分页机制

1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本文将主要以X86架构为例来介绍Linux内存管理的分页机制. 2.分页机制 5. Linux中的汇编 6.Linux系统地址映射示例

ActiveMQ讯息传送机制以及ACK机制详解

[http://www.ylzx8.cn/ruanjiangongcheng/software-architecture-design/11922.html] AcitveMQ:消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的. [ActiveMQ消息传送机制]Producer客户端用来发送消息的, Consumer客户端用来消费消息:它们的协同中心就是ActiveMQ broker,broker也