如何理解AVBprint


author: hjjdebug
date: 2025年 03月 27日 星期四 14:56:55 CST
description: 如何理解AVBprint


1. 什么是AVBprint

AVBPrint 是一个打印数据到内存的数据结构.
使用它有2个好处.

1.1 优点1. 它是一个数据流接受器,能够实现数据的拼接.

它有一个内存指针和已打印的长度,每次打印都会从ptr+len处开始打印
即目标点总是会移动,实现了打印的自动拼接,这就是数据流的接受功能.

问题1: 怎样计算被打印的字符串长度? 用vsnprintf
extra_len = vsnprintf(dst, room, fmt, vl);
vsnprintf是带可变参数的,限制大小的格式化打印函数.
返回值: 返回字符串需要占用的大小.
缓存不够大, 内容会被截断.

1.2 优点2. 它自动管理内存分配,当发现内存不能容纳打印的字符串时,会重新分配内存.

具体操作是它每次打印会计算剩余的空间和打印需要的空间大小,
如果发现(extra_len > room), 就要扩大分配的内存,按扩大一倍来进行.
再重新打印这次调用

1.3 av_bprint_init, 初始化时指定空间的标志.

AVBPrint 自带一个1000字节的缓存,
如果初始化时指定AV_BPRINT_SIZE_AUTOMATIC,就使用自带的缓存了.
虽然大小限制为1000字节,一般的打印也够用了.
如果设定内存标志是不限制AV_BPRINT_SIZE_UNLIMITED,
也是首先用这块自带的内存,不够用了才会在堆上分配.

1.4 av_bprint_finalize 功能

1.负责清理内存,如果AVBprint分配过内存的话.
2. 负责导出数据.
如果用户不需要导出, 指针地址给NULL 即可
如果用户需要导出,它可以分配导出内存,并把AVBprint的数据copy出来.
注意:导出内存虽然是由AVBPrint 分配的,但却不由AVBprint来释放.
而导出变量是用户的行为. 不能因为AVBprint 不存在了就把用户的内存也销毁.
导出内存啥时候释放?当然是你不再使用该变量的时候.

可见用AVBPrint 组织信息,收集信息还是很不错的.

下面给一个具体的调用实例,有一些体会标注到代码里了.

2. AVBprint 调用实例

$ cat main.c
#include <libavutil/bprint.h>
#include <libavutil/time.h>
#include <libavutil/mem.h>
#include <inttypes.h>
#include <stdio.h>
// 定义一个结构变量
typedef struct {
	int64_t timestamp;
	int error_code;
	const char* error_messages[3];
} Metadata;

//给一个变量,用json格式输出
//熟悉一下json 格式输出, {} 扩住obj, []扩住数组
//ffprobe中可以指定用json格式输出结果。
void build_metadata_json(const Metadata* meta)
{
	AVBPrint buf; //AVBPrint 是一个内存可以自动增长的数据流接受器,向内存打印
	//不跟入代码,印象不深,不懂实现,容易忘记!
	//AVBPrint 是一个1024字节的大变量,开辟了1K的存储容量
	av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); // 内存不限制,意味着可以动态扩充内存

	// 开始构建 JSON 对象,它会用vsnprint 计算打印需要占用的空间
	av_bprintf(&buf, "{\n");
	av_bprintf(&buf, "  \"timestamp\": %"PRId64",\n", meta->timestamp);
	av_bprintf(&buf, "  \"status\": %s,\n", (meta->error_code == 0) ? "\"OK\"" : "\"ERROR\"");

	// 生成错误信息数组
	av_bprintf(&buf, "  \"errors\": [\n");
	for (int i = 0; i < 3; i++)
	{
		if (meta->error_messages[i] != NULL)
		{
			av_bprintf(&buf, "    \"%s\"%s\n",  // 添加逗号(非最后一个元素)
					meta->error_messages[i],
					(i < 2 && meta->error_messages[i+1] != NULL) ? "," : "");
		}
	}
	av_bprintf(&buf, "  ]\n");
	av_bprintf(&buf, "}");

	// 获取结果并输出,
	// finalize 功能
	// 1.负责清理内存,如果AVBprint分配过内存的话.
	// 2. 如果用户需要导出,可以把缓冲数据copy出来,它可以分配导出内存,但这个内存要自己释放
	char* json_str;
	if (av_bprint_finalize(&buf, &json_str) == 0 && json_str != NULL)
	{
		printf("Generated JSON:\n%s\n", json_str);
		av_free(json_str); // 必须手动释放
	}
}

int main()
{
	//模拟从外部获取的动态数据
	Metadata meta =
	{
		.timestamp = av_gettime(), // 获取当前时间戳
		.error_code = -1,
		.error_messages = {"Invalid frame", "Decoding timeout", NULL}
	};
	//打印该变量到内存,再到屏幕
	//当然你不用AVBprint 也能直接向屏幕输出,用AVBprint 的好处是先用内存收集数据.
	build_metadata_json(&meta);
	return 0;
}

3. 测试结果

hjj@hjj-7090:~/test/temp$ ./temp
Generated JSON:
{
“timestamp”: 1743058236732934,
“status”: “ERROR”,
“errors”: [
“Invalid frame”,
“Decoding timeout”
]
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值