热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ffmpeg的内部VideoBuffer管理和传送机制

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

本文主要介绍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

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帧的状态


推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 在Android平台中,播放音频的采样率通常固定为44.1kHz,而录音的采样率则固定为8kHz。为了确保音频设备的正常工作,底层驱动必须预先设定这些固定的采样率。当上层应用提供的采样率与这些预设值不匹配时,需要通过重采样(resample)技术来调整采样率,以保证音频数据的正确处理和传输。本文将详细探讨FFMpeg在音频处理中的基础理论及重采样技术的应用。 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 本文介绍了如何利用Shell脚本高效地部署MHA(MySQL High Availability)高可用集群。通过详细的脚本编写和配置示例,展示了自动化部署过程中的关键步骤和注意事项。该方法不仅简化了集群的部署流程,还提高了系统的稳定性和可用性。 ... [详细]
  • 为了确保iOS应用能够安全地访问网站数据,本文介绍了如何在Nginx服务器上轻松配置CertBot以实现SSL证书的自动化管理。通过这一过程,可以确保应用始终使用HTTPS协议,从而提升数据传输的安全性和可靠性。文章详细阐述了配置步骤和常见问题的解决方法,帮助读者快速上手并成功部署SSL证书。 ... [详细]
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 在本文中,我们将详细介绍如何构建一个用于自动回复消息的XML类。当微信服务器接收到用户消息时,该类将生成相应的自动回复消息。以下是具体的代码实现:```phpclass We_Xml { // 代码内容}```通过这个类,开发者可以轻松地处理各种消息类型,并实现高效的自动回复功能。我们将深入探讨类的各个方法和属性,帮助读者更好地理解和应用这一技术。 ... [详细]
  • PHP预处理常量详解:如何定义与使用常量 ... [详细]
  • 本文探讨了使用JavaScript在不同页面间传递参数的技术方法。具体而言,从a.html页面跳转至b.html时,如何携带参数并使b.html替代当前页面显示,而非新开窗口。文中详细介绍了实现这一功能的代码及注释,帮助开发者更好地理解和应用该技术。 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • 基于 Vue 和 Element UI 实现的简洁登录界面设计
    本文介绍了一种利用 Vue.js 和 Element UI 框架构建的简洁登录界面设计。该设计不仅注重用户体验,还确保了界面的美观性和易用性。通过合理的布局和组件配置,实现了高效、响应式的登录功能,适用于多种前端应用场景。 ... [详细]
author-avatar
临海小少年
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有