简介: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基类使用配置组织输入数据
- 🌻4.实战案例
- 4.1准备编码器配置
- 4.2设置参数并查询
- 4.3完整代码
- 🌻5.总结
🌻1.前言
本篇目的:理解
gst_audio_encoder_get_frame_max()读取的配置值是什么,分析它如何影响GstAudioEncoder向子类提交输入数据,并通过最小C程序查询该值。
音频编码器子类可以设置每次交给handle_frame()处理的输入数据大小。固定输入样本数时,如果上游一次送来多个完整编码单元,基类可以把若干单元合并后再交给子类处理。
gst_audio_encoder_get_frame_max()用于查询当前配置的最大处理单元数。它只读取配置,不会设置批量大小,也不会读取或编码PCM数据。
🌻2.应用场景和用法
2.1查询编码器输入批量配置
frame_max用于控制基类一次最多把多少个完整输入单元交给编码器子类处理。它只有在frame_samples_min和frame_samples_max相等时,才参与基类的批量组织逻辑。
| 场景 | 查询目的 | 需要关注的配置 |
|---|---|---|
| 固定帧长编码 | 确认每次handle_frame()最多收到多少个完整单元 | frame_samples_min、frame_samples_max、frame_max |
| 编码器调试 | 判断多份PCM样本为何被合并后提交 | 输入缓存中的可用字节数和frame_max |
| 格式重新协商 | 确认set_format()重新配置后的当前值 | 在子类设置参数后再次查询 |
| 默认配置排查 | 判断当前是否设置了批量上限 | 查询结果为0时检查格式配置阶段 |
frame_max表示可合并处理的单元数量,不是每个单元包含的PCM样本数,也不是编码后的输出帧数。每个单元的样本数由frame_samples_min和frame_samples_max描述。
2.2函数原型与返回语义
函数原型如下:
gintgst_audio_encoder_get_frame_max(GstAudioEncoder*enc);| 参数或返回值 | 含义 |
|---|---|
enc | 有效的GstAudioEncoder对象 |
| 返回值 | 当前配置的最大处理单元数 |
最小调用方式如下:
gint frame_max;frame_max=gst_audio_encoder_get_frame_max(encoder);该函数直接读取编码器私有上下文中的frame_max字段,不修改编码器状态,也不分配对象。传入无效对象时,函数通过参数检查并返回0;有效对象的初始值或尚未配置时也可能是0,因此不能只凭0判断调用失败。
配置通常由编码器子类在set_format()中完成。若要求每个处理单元具有固定样本数,应先将最小和最大样本数设为相同值,再设置最大单元数:
gst_audio_encoder_set_frame_samples_min(encoder,1024);gst_audio_encoder_set_frame_samples_max(encoder,1024);gst_audio_encoder_set_frame_max(encoder,3);gst_audio_encoder_set_frame_max()的值会在基类调用子类set_format()前重置为0。因此,子类应在每次格式配置时重新设置;需要确认生效值时,再调用gst_audio_encoder_get_frame_max()查询。
相邻接口职责如下:
| 接口 | 职责 |
|---|---|
gst_audio_encoder_set_frame_samples_min() | 设置每个处理单元至少需要的每声道样本数 |
gst_audio_encoder_set_frame_samples_max() | 设置每个处理单元最多需要的每声道样本数 |
gst_audio_encoder_set_frame_max() | 设置基类一次最多合并多少个完整处理单元 |
gst_audio_encoder_get_frame_max() | 读取当前最大处理单元数 |
gst_audio_encoder_finish_frame() | 提交编码输出,并告知基类已处理的输入样本数 |
🌻3.调用流程剖析
3.1读取基类上下文中的配置值
gst_audio_encoder_get_frame_max()的实现很短,核心动作是检查对象类型后返回上下文中的frame_max:
gintgst_audio_encoder_get_frame_max(GstAudioEncoder*enc){g_return_val_if_fail(GST_IS_AUDIO_ENCODER(enc),0);returnenc->priv->ctx.frame_max;}这里没有计算输入数据大小,也没有对配置值做转换。返回值反映的是当前保存的配置。
基类在处理新的输入格式时,会先把frame_samples_min、frame_samples_max和frame_max等参数重置,再调用子类的set_format()。子类需要在这个回调中重新设置参数,随后查询才能读到新格式对应的值。
3.2基类使用配置组织输入数据
查询函数本身只读配置。真正使用frame_max的是基类的输入处理逻辑:基类从输入适配器中查看已有数据,并依据每个处理单元的样本数,计算本次交给handle_frame()的数据长度。
当frame_samples_min与frame_samples_max相等且大于0时,输入数据可以按固定大小划分。如果frame_max大于1,基类最多合并指定数量的完整单元;如果frame_max为0,基类可以把当前缓存中可组成的完整单元一起提交。值为1时,每次按一个单元处理。
例如,S16立体声每个样本帧占4字节。若每个处理单元包含1024个每声道样本,则一个单元占:
1024 × 4 = 4096字节当frame_max为3且缓存中至少有3个完整单元时,基类最多提交3个单元,即12288字节。子类随后在handle_frame()中处理输入,并通过gst_audio_encoder_finish_frame()提交编码结果。
🌻4.实战案例
4.1准备编码器配置
案例创建一个最小GstAudioEncoder子类,用来观察frame_max的设置和读取。
编码器将每个处理单元配置为1024个每声道样本,并将最大合并单元数设置为3。这样,查询接口应返回3。示例不启动完整音频管线,重点验证配置接口之间的关系。
4.2设置参数并查询
程序创建编码器对象后,依次执行以下操作:
- 将每个处理单元的最小样本数和最大样本数都设置为1024。
- 调用
gst_audio_encoder_set_frame_max()设置最大单元数为3。 - 调用
gst_audio_encoder_get_frame_max()读取当前值,并与期望值比较。
生产编码器应在set_format()中设置这些参数。示例在对象创建后直接设置,是为了集中展示Getter和Setter读取同一上下文配置的过程。
4.3完整代码
#include<gst/gst.h>#include<gst/audio/audio.h>typedefstruct_FrameMaxDemo{GstAudioEncoder parent;}FrameMaxDemo;typedefstruct_FrameMaxDemoClass{GstAudioEncoderClass parent_class;}FrameMaxDemoClass;staticvoidframe_max_demo_class_init(FrameMaxDemoClass*klass);staticvoidframe_max_demo_init(FrameMaxDemo*self);G_DEFINE_TYPE(FrameMaxDemo,frame_max_demo,GST_TYPE_AUDIO_ENCODER);/* 最小处理回调,本案例只查询配置,不执行真实编码 */staticGstFlowReturnframe_max_demo_handle_frame(GstAudioEncoder*encoder,GstBuffer*buffer){(void)encoder;(void)buffer;returnGST_FLOW_OK;}staticvoidframe_max_demo_class_init(FrameMaxDemoClass*klass){GstAudioEncoderClass*encoder_class=GST_AUDIO_ENCODER_CLASS(klass);/* GstAudioEncoder子类需要提供帧处理回调 */encoder_class->handle_frame=frame_max_demo_handle_frame;}staticvoidframe_max_demo_init(FrameMaxDemo*self){(void)self;}intmain(intargc,char*argv[]){GstAudioEncoder*encoder;gint frame_samples_min;gint frame_samples_max;gint frame_max;gst_init(&argc,&argv);/* 创建自定义GstAudioEncoder对象 */encoder=GST_AUDIO_ENCODER(g_object_new(frame_max_demo_get_type(),NULL));/* 固定每个处理单元的每声道样本数 */gst_audio_encoder_set_frame_samples_min(encoder,1024);gst_audio_encoder_set_frame_samples_max(encoder,1024);/* 设置一次最多合并处理3个完整单元 */gst_audio_encoder_set_frame_max(encoder,3);/* 读取基类当前保存的三个配置值 */frame_samples_min=gst_audio_encoder_get_frame_samples_min(encoder);frame_samples_max=gst_audio_encoder_get_frame_samples_max(encoder);frame_max=gst_audio_encoder_get_frame_max(encoder);g_print("frame_samples_min: %d\n",frame_samples_min);g_print("frame_samples_max: %d\n",frame_samples_max);g_print("frame_max: %d\n",frame_max);/* 最小值和最大值相等时,frame_max才用于固定单元的批量组织 */if(frame_samples_min!=frame_samples_max||frame_max!=3){gst_object_unref(encoder);return1;}gst_object_unref(encoder);return0;}🌻5.总结
gst_audio_encoder_get_frame_max()就是读取GstAudioEncoder当前配置的最大处理单元数,供子类确认基类的输入批量组织参数。