当前位置: 首页 > news >正文

FFmpeg源码:av_buffer_is_writable、av_buffer_realloc函数分析

=================================================================

FFmpeg内存管理相关的源码分析:

FFmpeg中内存分配和释放相关的源码:av_malloc函数、av_mallocz函数、av_free函数和av_freep函数分析

FFmpeg源码:av_realloc、av_reallocp、size_mult、av_realloc_f函数分析
FFmpeg引用计数数据缓冲区相关的结构体:AVBuffer、AVBufferRef简介

FFmpeg源码:buffer_create、av_buffer_create、av_buffer_default_free、av_buffer_alloc、av_buffer_allocz函数分析

FFmpeg源码:av_buffer_ref、av_buffer_unref函数分析

FFmpeg源码:av_buffer_is_writable、av_buffer_realloc函数分析

=================================================================

一、av_buffer_is_writable函数

(一)av_buffer_is_writable函数的声明

av_buffer_is_writable函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavutil/buffer.h中:

/*** @return 1 if the caller may write to the data referred to by buf (which is* true if and only if buf is the only reference to the underlying AVBuffer).* Return 0 otherwise.* A positive answer is valid until av_buffer_ref() is called on buf.*/
int av_buffer_is_writable(const AVBufferRef *buf);

该函数作用是:判断是否可以对buf引用的数据(buf->buffer->data,buf->data)进行写入,当且仅当buf是对底层AVBuffer的唯一引用(buf->buffer->refcount的值为1)时可以写入。如果可以写入,返回1,否则返回0。

(二)av_buffer_is_writable函数的定义

av_buffer_is_writable函数定义在FFmpeg源码的源文件libavutil/buffer.c中:

/*** Always treat the buffer as read-only, even when it has only one* reference.*/
#define AV_BUFFER_FLAG_READONLY (1 << 0)int av_buffer_is_writable(const AVBufferRef *buf)
{if (buf->buffer->flags & AV_BUFFER_FLAG_READONLY)return 0;return atomic_load(&buf->buffer->refcount) == 1;
}

该函数内部,首先通过buf->buffer->flags判断是否始终将缓冲区视为只读的,如果是,返回0,表示不可对buf引用的数据进行写入:

if (buf->buffer->flags & AV_BUFFER_FLAG_READONLY)return 0;

然后通过atomic_load函数读取buf->buffer->refcount的值。如果该值为1,表示引用buf缓冲区的现有AVBufferRef实例的数目为1,即引用计数为1,此时av_buffer_is_writable函数返回1,表示可以对buf引用的数据进行写入;如果引用计数不为1,av_buffer_is_writable函数返回0,表示不可写入:

return atomic_load(&buf->buffer->refcount) == 1;

二、av_buffer_realloc函数

(一)av_buffer_realloc函数的声明

av_buffer_realloc函数声明在头文件libavutil/buffer.h中:

/*** Reallocate a given buffer.** @param buf  a buffer reference to reallocate. On success, buf will be*             unreferenced and a new reference with the required size will be*             written in its place. On failure buf will be left untouched. *buf*             may be NULL, then a new buffer is allocated.* @param size required new buffer size.* @return 0 on success, a negative AVERROR on failure.** @note the buffer is actually reallocated with av_realloc() only if it was* initially allocated through av_buffer_realloc(NULL) and there is only one* reference to it (i.e. the one passed to this function). In all other cases* a new buffer is allocated and the data is copied.*/
int av_buffer_realloc(AVBufferRef **pbuf, size_t size);

该函数作用是:

1.如果(*pbuf)为空,说明AVBufferRef对象不存在。分配一个新的内存块给(*pbuf)指向的AVBufferRef对象,并给(*pbuf)->buffer分配内存,给(*pbuf)->data分配大小为size个字节的内存。然后给(*pbuf)->buffer->flags_internal设置为BUFFER_FLAG_REALLOCATABLE,表示该AVBufferRef对象的缓冲区是可重新分配的。

2.如果(*pbuf)不为空(AVBufferRef对象存在),并且(*pbuf)->size的值等于形参size的值,表示

需要给(*pbuf)->data重新分配的大小等于原来的值,此时av_buffer_realloc函数返回0,不执行也不需要执行其它操作。

3.不满足上述条件1和条件2的情况时,如果该AVBufferRef对象的缓冲区不可重新分配(通过语句!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE)判断)或者不可对该AVBufferRef引用的数据进行写入(通过语句!av_buffer_is_writable(buf)判断)或者(*buf)->data 的地址不等于 (*pbuf)->buffer->data的地址。此时表示该AVBufferRef对象的缓冲区无法重新分配,分配新的可重新分配缓冲区并复制数据到这块新的缓冲区。

4.不满足上述条件1、条件2、条件3的情况时,根据size的值扩展或缩小(*buf)->buffer->data指向的内存块。然后(*buf)->buffer->data指向的内存块的大小会变为size。

形参pbuf:既是输入型参数也是输出型参数,为指针的指针。(*pbuf)指向需要重新分配缓冲区的AVBufferRef对象。

形参size:输入型参数,需要给(*pbuf)->data指向的缓冲区重新分配的内存块的大小,单位为字节。

返回值:返回0表示成功,返回AVERROR(ENOMEM)表示分配内存失败。

(二)av_buffer_realloc函数的定义

av_buffer_realloc函数定义在源文件libavutil/buffer.c中:

int av_buffer_realloc(AVBufferRef **pbuf, size_t size)
{AVBufferRef *buf = *pbuf;uint8_t *tmp;int ret;if (!buf) {/* allocate a new buffer with av_realloc(), so it will be reallocatable* later */uint8_t *data = av_realloc(NULL, size);if (!data)return AVERROR(ENOMEM);buf = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);if (!buf) {av_freep(&data);return AVERROR(ENOMEM);}buf->buffer->flags_internal |= BUFFER_FLAG_REALLOCATABLE;*pbuf = buf;return 0;} else if (buf->size == size)return 0;if (!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE) ||!av_buffer_is_writable(buf) || buf->data != buf->buffer->data) {/* cannot realloc, allocate a new reallocable buffer and copy data */AVBufferRef *new = NULL;ret = av_buffer_realloc(&new, size);if (ret < 0)return ret;memcpy(new->data, buf->data, FFMIN(size, buf->size));buffer_replace(pbuf, &new);return 0;}tmp = av_realloc(buf->buffer->data, size);if (!tmp)return AVERROR(ENOMEM);buf->buffer->data = buf->data = tmp;buf->buffer->size = buf->size = size;return 0;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Mybatis声明变量并使用
  • 服务器硬件及RAID配置
  • 基于springboot的乐享田园系统
  • Linux系统性能调优技巧
  • 学习计算机网络(三)——IP地址
  • Golang实现简单的HTTP服务,响应RESTful请求判断形状大小
  • 理解张量拼接(torch.cat)
  • cmseasy的两个注入漏洞
  • GiantPandaCV | 大模型训练:Megatron-Kwai中的内存优化
  • Lesson 57 An unusual day
  • git:安装 / 设置环境变量 / 使用
  • 009集——调用方法与递归算法 ——C#学习笔记
  • 网络安全面试题
  • 飞桨Paddle API index_add 详解
  • 8月8号前端日报:web在线进行eps32固件升级
  • ----------
  • 【译】JS基础算法脚本:字符串结尾
  • CSS相对定位
  • js操作时间(持续更新)
  • ReactNativeweexDeviceOne对比
  • redis学习笔记(三):列表、集合、有序集合
  • vue 个人积累(使用工具,组件)
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • windows下如何用phpstorm同步测试服务器
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 对象引论
  • 给Prometheus造假数据的方法
  • 爬虫模拟登陆 SegmentFault
  • ​Python 3 新特性:类型注解
  • #AngularJS#$sce.trustAsResourceUrl
  • #Datawhale X 李宏毅苹果书 AI夏令营#3.13.2局部极小值与鞍点批量和动量
  • (13)Hive调优——动态分区导致的小文件问题
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (转)平衡树
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .net core 的缓存方案
  • .NET HttpWebRequest、WebClient、HttpClient
  • .net打印*三角形
  • [ MSF使用实例 ] 利用永恒之蓝(MS17-010)漏洞导致windows靶机蓝屏并获取靶机权限
  • [ 数据结构 - C++] AVL树原理及实现
  • [AHK V2]鼠标悬停展开窗口,鼠标离开折叠窗口
  • [AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [Android]创建TabBar
  • [Angular] 笔记 16:模板驱动表单 - 选择框与选项
  • [BJDCTF2020]Easy MD51
  • [BUUCTF NewStarCTF 2023 公开赛道] week4 crypto/pwn
  • [C#]C# winform实现imagecaption图像生成描述图文描述生成
  • [CLR via C#]11. 事件
  • [CUDA手搓]从零开始用C++ CUDA搭建一个卷积神经网络(LeNet),了解神经网络各个层背后算法原理
  • [GXYCTF2019]BabyUpload1 -- 题目分析与详解
  • [HNOI2015]实验比较
  • [IE技巧] IE 中打开Office文件的设置