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
ffmpeg的内部Video Buffer管理和传送机制的更多相关文章
- android摄像头(camera)之buffer管理
一,V4L2驱动申请buffer 视频应用可以通过两种方式从V4L2驱动申请buffer 1. V4L2_MEMORY_USERPTR方式, 顾名思义是用户空间指针的意思,应用层负责分配需要的内存空间 ...
- vlc_input buffer管理 & 时钟同步(转)
vlc_input buffer管理 & 时钟同步 一.背景1.当播放网络视频流时(比如udp视频流),发送方(编码)和接收方(解码)是并行操作的,如果发送太慢(或因为网络原因出现延迟)的话, ...
- 大型分布式C++框架《四:netio之buffer管理器 下》
每周一篇又来了.这次主要介绍netio的buffer管理器. 首先buffer管理是每一个网络层不可回避的问题.怎么高效的使用buffer是很关键的问题.这里主要介绍下我们的netio是怎么处理.说实 ...
- with ffmpeg to encode video for live streaming and for recording to files for on-demand playback
We've been doing some experimentation with ffmpeg to encode video for live streaming and for recordi ...
- Android基本功:Handler消息传送机制
一.什么是UI线程 当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread). 主要负责处理与UI相关的事件. 二.UI线程存在的问题 出于性能优化考虑,Android的 ...
- ActiveMQ讯息传送机制以及ACK机制
http://blog.csdn.net/lulongzhou_llz/article/details/42270113 ActiveMQ消息传送机制以及ACK机制详解 AcitveMQ是作为一种消息 ...
- 总结Flink状态管理和容错机制
本文来自8月11日在北京举行的 Flink Meetup会议,分享来自于施晓罡,目前在阿里大数据团队部从事Blink方面的研发,现在主要负责Blink状态管理和容错相关技术的研发. 本文主要内容如 ...
- JVM内存管理及GC机制
一.概述 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露 ...
- Handler消息传送机制
一.什么是UI线程 当程序第一次启动的时候,Android会同时启动一条主线程( Main Thread). 主要负责处理与UI相关的事件. 二.UI线程存在的问题 出于性能优化考虑,Android的 ...
随机推荐
- 前端学习笔记汇总(之merge方法)
学习笔记 关于Jquery的merge方法 话不多说,先上图 使用jquery时,其智能提示如上,大概意思就是合并first和second两个数组,得到的结果是first+(second去重后的结果) ...
- 关于Backtracing中有重复元素的处理办法
backtracing是一个常用的解法.之前遇到一个题目,求一个集合的子集, 例如给定{1,2,3,4,5},求其大小为3的子集. 利用backtracing可以较快的给出答案. 然而,该题还有一个变 ...
- POJ 2184 Cow Exhibition (01背包的变形)
本文转载,出处:http://www.cnblogs.com/Findxiaoxun/articles/3398075.html 很巧妙的01背包升级.看完题目以后很明显有背包的感觉,然后就往背包上靠 ...
- java基础知识回顾之javaIO类--File类应用:获取指定目录下面的指定扩展名的文件,将文件的绝对路径写入到目的文件当中
/** * File文件综合应用 * 需求:获取指定目录下面,指定扩展名的文件,将文件的绝对路径写到文本文件当中. * * 思路:1.需要深度遍历.--递归 * 2.遍历的过程中过滤指定扩展名的文件 ...
- SDUT 1220 完美数
完美数 Time Limit: 1000ms Memory limit: 65536K 题目描述 任何一个自然数的约数中都有1和它本身,我们把小于它本身的因数叫做这个自然数的真约数. 如6的所有真 ...
- hdu 1333 Smith Numbers
刚开始没看清题意,要找的数一定要是素数 ;}
- C Primer Plus 第4章 字符串和格式化输入/输出 编程练习
1. #include <stdio.h> int main(void) { ]; ]; printf("请输入您的名字: "); scanf("%s&quo ...
- longene QQ 安装目录
longene QQ 在Ubuntu 12.04上的安装目录如下: wy@wy-Inspiron-7420:~/.longene/qq/drive_c/Program Files/Tencent/QQ ...
- Apache源码分析资源
关于作者张中庆, 目前主要的研究方向是嵌入式浏览器,移动中间件以及大规模服务器设计.目前正在进行Apache的源代码分析,计划出版<Apache源代码全景分析>上 下册.Apache系列文 ...
- ApplePay扩大全球发卡行合作,“苹果税”撑不住了?
5月11日Apple Pay全面登陆加拿大地区,更为重要的是,苹果终于在一些地区,开始和美国运通之外的发卡行达成了合作.这对于老是因为分账问题不愿意走出下一步的Apple Pay来说,已经是巨大的进步 ...