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-09-29 01:59:51

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

真功夫内部人曝管理漏洞改革派被边缘化

蔡达标等真功夫餐饮管理有限公司(以下简称"真功夫")部分高管因涉嫌经济犯罪被捕距今已超过一年,警方并没有公布案情的最新进展,但真功夫的夺权尘嚣并未消停,而近日举行的关于更换公司掌舵人的听证会,更引起外界对这家家族式连锁餐饮企业命运的忧虑. 4月9日上午9点半,真功夫就公司变更法定代表人.备案董事长和董事以及补发营业执照申请,在东莞市工商行政管理局举行听证会.截至记者发稿,听证会尚无公开结果,要想在法律层面落实真功夫掌舵者,恐怕仍需一段较长的时间.而在这一年里,随着潘宇海在真功夫内部极力

JVM内存管理及GC机制

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

[CLR via C#]21. 自动内存管理(垃圾回收机制)

原文:[CLR via C#]21. 自动内存管理(垃圾回收机制) 目录 理解垃圾回收平台的基本工作原理 垃圾回收算法 垃圾回收与调试 使用终结操作来释放本地资源 对托管资源使用终结操作 是什么导致Finalize方法被调用 终结操作揭秘 Dispose模式:强制对象清理资源 使用实现了Dispose模式的类型 C#的using语句 手动监视和控制对象的生存期 对象复活 代 线程劫持 大对象 一.理解垃圾回收平台的基本工作原理 值类型(含所有枚举类型).集合类型.String.Attribute

ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的

ActiveMQ消息传送机制以及ACK机制详解     AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的.   一. ActiveMQ消息传送机制     Producer客户端使用来发送消息的, Consumer客户端用来消费消息:它们的协同中心就是ActiveMQ broker,broker也是让producer和consumer调用过程解耦的工具,最终实现了异步RPC

【转】ActiveMQ消息传送机制以及ACK机制详解

本文转载自 http://shift-alt-ctrl.iteye.com/blog/2020182 AcitveMQ是作为一种消息存储和分发组件,涉及到client与broker端数据交互的方方面面,它不仅要担保消息的存储安全性,还要提供额外的手段来确保消息的分发是可靠的.   一. ActiveMQ消息传送机制     Producer客户端使用来发送消息的, Consumer客户端用来消费消息:它们的协同中心就是ActiveMQ broker,broker也是让producer和consu

小而美的自我管理和修复机制

摘要: 借助微信,杭州微车队实现了不可思议的自我组织.协调.分工,这个自发的民间组织不属于任何一个商业机构,但是他们有序的自我管理能力令团队每个成员月收入至少提升了20%以上 借助微信,杭州微车队实现了不可思议的自我组织.协调.分工,这个自发的民间组织不属于任何一个商业机构,但是他们有序的自我管理能力令团队每个成员月收入至少提升了20%以上.今后或许会有越来越多类似的小而美组织的出现,移动互联网令去中心化的社会化协作变得更加高效. 周一下午4点多,邵展成在杭州机场出租车入口处静静地等待.几分钟前

CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用

1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具.2016年末paulcher发现FFmpeg三个堆溢出漏洞分别为CVE-2016-10190.CVE-2016-10191以及CVE-2016-10192.本文对CVE-2016-10190进行了详细的分析,是一个学习如何利用堆溢出达到任意代码执行的一个非常不错的案例. 2. 漏洞分析 FFmpeg的 Http 协议的实现中支持几种不同的数据传输方式,通

畅游多事之秋,总裁陈德文内部吐槽公司管理

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;  对于如今的畅游而言,可谓是多事之秋.高管相继离职.第一季度严重亏损.项目进展乏力.相继裁员这些都与这家老牌游戏公司联系在了一起. 面对这种情况,畅游总裁陈德文更是在公司内部公开表达不满.15日下午,他发表了名为"华为四大禁之一:禁止没有实际业务经验的去做组织优化和流程变革".16日又是发布"我的战斗宣言",公开吐槽对内部管理

java内存管理和回收机制

java类文件是以 .java为后缀的文件,经过javac命令编译后,编译成class文件,class文件中都是二进制格式的数据,所以想要看编译后的内容是什么,可以采用jdk自带的javap命令查看. JVM中有个组成部分为类加载器(ClassLoader),负责java文件编译后class文件的加载,加载到哪呢,加载到内存.那下面来说一下JVM的内存管理. java通过类加载器来加载class文件,加载到内存后,会把类.方法.常变量放到堆内存中.因为java是自动进行垃圾回收的,所以放入堆内存