简介:CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀
人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
- 🌻1.前言
- 🌻2.应用场景和用法
- 2.1获取音频元信息描述
- 2.2函数原型与返回语义
- 🌻3.调用流程剖析
- 3.1一次性创建并注册描述对象
- 3.2描述对象与Buffer实例的关系
- 🌻4.实战案例
- 4.1准备音频Buffer和描述对象
- 4.2获取描述并添加Meta实例
- 4.3完整代码
- 🌻5.总结
🌻1.前言
本篇目的:理解
gst_audio_meta_get_info()如何注册并返回GstAudioMeta对应的GstMetaInfo,梳理元信息描述对象与Buffer中元信息实例的关系,并通过代码观察两者如何配合。
GstAudioMeta描述音频Buffer的数据布局,例如音频格式、有效样本数和各声道平面的偏移。gst_audio_meta_get_info()返回的是这个Meta类型的描述信息,不会创建GstAudioMeta实例,也不会修改Buffer。
把实例添加到Buffer的工作由gst_buffer_add_audio_meta()完成。理解这两个接口的边界,可以避免把“注册元信息类型”和“给Buffer附加元信息”混为一谈。
🌻2.应用场景和用法
2.1获取音频元信息描述
gst_audio_meta_get_info()主要供GStreamer的Meta系统和相关API取得GstAudioMeta的类型描述。这个描述包含Meta的API类型、名称、实例大小,以及实例初始化、释放、复制和序列化等处理函数。
| 场景 | 获取描述信息的作用 | 后续动作 |
|---|---|---|
| 添加音频布局Meta | 让Meta系统识别GstAudioMeta类型 | 调用gst_buffer_add_audio_meta() |
| 查询Buffer中的音频Meta | 使用对应API类型查找Meta实例 | 调用gst_buffer_get_audio_meta() |
| 复制Buffer | 提供Meta复制处理函数 | GStreamer在支持的复制操作中调用transform函数 |
| 序列化音频Meta | 提供序列化和反序列化处理函数 | Meta系统按注册信息执行对应操作 |
GstAudioMeta常用于非交错音频。非交错数据中,每个声道分别存放,Buffer需要知道每个声道平面从哪个字节偏移开始。交错音频则通常由音频Caps和Buffer布局表达,不需要额外的平面偏移数组。
2.2函数原型与返回语义
函数原型如下:
constGstMetaInfo*gst_audio_meta_get_info(void);函数没有输入参数,返回进程内注册的GstMetaInfo指针。第一次调用时,它会创建并注册描述对象;后续调用返回同一个静态描述对象。实现使用g_once_init_enter()和g_once_init_leave()保护初始化过程。
调用该函数不会分配Buffer中的Meta实例。Buffer需要可写,才能通过gst_buffer_add_audio_meta()添加实例。添加接口返回的GstAudioMeta由Buffer持有,调用者不应单独释放它。
几个相关接口的职责如下:
| 接口 | 职责 |
|---|---|
gst_audio_meta_get_info() | 获取GstAudioMeta的注册描述 |
GST_AUDIO_META_INFO | 调用gst_audio_meta_get_info()的便捷宏 |
gst_audio_meta_api_get_type() | 获取音频Meta的API类型 |
gst_buffer_add_audio_meta() | 为Buffer创建并初始化GstAudioMeta实例 |
gst_buffer_get_audio_meta() | 从Buffer查找已有的GstAudioMeta实例 |
🌻3.调用流程剖析
3.1一次性创建并注册描述对象
gst_audio_meta_get_info()内部保存一个静态的GstMetaInfo指针。第一次进入时,函数创建描述对象,将GstAudioMeta的初始化、释放、复制、序列化和反序列化函数关联到该对象,再将描述信息注册到Meta系统。
if(g_once_init_enter((GstMetaInfo**)&audio_meta_info)){GstMetaInfo*info=gst_meta_info_new(GST_AUDIO_META_API_TYPE,"GstAudioMeta",sizeof(GstAudioMeta));info->init_func=gst_audio_meta_init;info->free_func=gst_audio_meta_free;info->transform_func=gst_audio_meta_transform;info->serialize_func=gst_audio_meta_serialize;info->deserialize_func=gst_audio_meta_deserialize;audio_meta_info=gst_meta_info_register(info);g_once_init_leave((GstMetaInfo**)&audio_meta_info,(GstMetaInfo*)audio_meta_info);}描述对象注册后,函数返回静态指针。后续调用不再重复创建或注册。这里的GstMetaInfo是Meta类型的说明和操作表,不是附着在某个Buffer上的音频数据。
3.2描述对象与Buffer实例的关系
添加实例时,gst_buffer_add_audio_meta()使用GST_AUDIO_META_INFO把Meta实例附加到Buffer,再将调用者提供的GstAudioInfo和样本数写入实例。非交错布局还会保存或计算声道偏移。
Meta实例的复制、释放和序列化行为来自注册时关联的处理函数。复制整个Buffer时,gst_audio_meta_transform()会在目标Buffer上重新添加音频Meta;释放实例时,gst_audio_meta_free()负责释放动态分配的偏移数组。
因此,读取gst_audio_meta_get_info()只能确认Meta类型描述已经注册。要确认某个Buffer是否实际携带音频布局信息,还需要调用gst_buffer_get_audio_meta()并检查返回的实例。
🌻4.实战案例
4.1准备音频Buffer和描述对象
案例创建一个S16LE、48kHz、双声道的Buffer,包含128个样本帧。每帧包含两个声道的样本,交错布局所需空间为512字节。
4.2获取描述并添加Meta实例
程序先调用gst_audio_meta_get_info()取得注册描述,再调用gst_buffer_add_audio_meta()向Buffer添加实例。添加完成后,通过gst_buffer_get_audio_meta()重新查询,并检查实例引用的描述对象和样本数量。
4.3完整代码
#include<gst/gst.h>#include<gst/audio/audio.h>intmain(intargc,char*argv[]){GstAudioInfo audio_info;GstBuffer*buffer;GstAudioMeta*audio_meta;constGstMetaInfo*meta_info;gsize samples=128;gsize buffer_size;intresult=1;gst_init(&argc,&argv);/* 设置Buffer对应的采样格式、采样率和声道数 */if(!gst_audio_info_set_format(&audio_info,GST_AUDIO_FORMAT_S16,48000,2,NULL))return1;/* 为128个双声道样本帧分配交错音频空间 */buffer_size=samples*GST_AUDIO_INFO_BPF(&audio_info);buffer=gst_buffer_new_allocate(NULL,buffer_size,NULL);if(buffer==NULL)return1;/* 获取GstAudioMeta的注册描述,不会在此处创建Meta实例 */meta_info=gst_audio_meta_get_info();if(meta_info!=GST_AUDIO_META_INFO)gotodone;/* 将音频格式与样本数作为Meta实例附加到Buffer */audio_meta=gst_buffer_add_audio_meta(buffer,&audio_info,samples,NULL);if(audio_meta==NULL)gotodone;/* 从Buffer查询实例,确认Meta描述和样本数 */audio_meta=gst_buffer_get_audio_meta(buffer);if(audio_meta!=NULL&&audio_meta->meta.info==meta_info&&audio_meta->samples==samples)result=0;done:gst_buffer_unref(buffer);returnresult;}🌻5.总结
gst_audio_meta_get_info()负责一次性注册并返回GstAudioMeta类型描述,Buffer中的实际音频布局信息由添加接口创建为Meta实例。