简介: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_latency()如何读取GstAudioEncoder当前配置的最小和最大延迟,并通过一个最小编码器子类验证读取结果。
编码器可能会缓存输入样本,等待积累到一定数量后再输出编码数据。缓存和编码过程会带来延迟,管线需要知道这个延迟范围,才能进行全局延迟管理。
gst_audio_encoder_get_latency()读取基类当前保存的延迟值。它不测量编码耗时,也不计算编码器的缓存延迟。延迟值由编码器子类通过gst_audio_encoder_set_latency()设置。
🌻2.应用场景和用法
2.1读取编码器延迟配置
编码器子类可以根据自身的缓存、前视或编码机制,设置最小和最大延迟。其他代码需要检查这些配置时,可以调用gst_audio_encoder_get_latency()。
| 场景 | 读取内容 | 用途 |
|---|---|---|
| 检查编码器配置 | 最小和最大延迟 | 确认子类报告的延迟范围 |
| 调试管线延迟 | 编码器当前保存的延迟值 | 与上游延迟查询结果对照 |
| 动态编码配置 | 延迟配置是否已更新 | 判断子类是否需要重新设置延迟 |
读取到的值表示编码器当前保存的配置,不等同于一次运行中测得的端到端延迟。如果子类没有设置延迟,基类初始化时的最小值和最大值均为0。
2.2函数原型与返回语义
函数原型如下:
voidgst_audio_encoder_get_latency(GstAudioEncoder*enc,GstClockTime*min,GstClockTime*max);| 参数 | 含义 |
|---|---|
enc | 要读取延迟配置的GstAudioEncoder对象 |
min | 可选输出指针,用于接收最小延迟 |
max | 可选输出指针,用于接收最大延迟 |
该函数没有返回值。min和max可以分别传入NULL,表示不需要对应的值。GstClockTime以纳秒为单位,GST_MSECOND可用于表示毫秒。
最小调用方式如下:
GstClockTime min_latency;GstClockTime max_latency;gst_audio_encoder_get_latency(encoder,&min_latency,&max_latency);调用时,基类获取对象锁并读取当前保存的延迟字段。它不会修改这些字段,也不会发送消息。
与它相邻的接口职责不同:
| 接口 | 职责 |
|---|---|
gst_audio_encoder_set_latency() | 设置基类保存的延迟范围,配置变化时发送GST_MESSAGE_LATENCY |
gst_audio_encoder_get_latency() | 读取当前保存的延迟范围 |
GST_QUERY_LATENCY | 在管线中查询并汇总上游和当前编码器的延迟 |
🌻3.调用流程剖析
3.1从编码器对象读取延迟字段
gst_audio_encoder_get_latency()先检查enc是否为有效的GstAudioEncoder对象,然后获取对象锁。
如果min不是NULL,函数把私有状态中的min_latency写入调用者提供的地址。如果max不是NULL,则写入max_latency。读取完成后释放对象锁。
核心逻辑如下:
GST_OBJECT_LOCK(enc);if(min)*min=enc->priv->ctx.min_latency;if(max)*max=enc->priv->ctx.max_latency;GST_OBJECT_UNLOCK(enc);因此,调用前后的关系是:编码器对象中已经有延迟配置,函数读取指定字段,调用者得到对应的纳秒值。函数不会创建新对象,也不会更改编码器配置。
3.2区分读取配置与管线延迟查询
gst_audio_encoder_get_latency()和GST_QUERY_LATENCY都涉及编码器延迟,但处理路径不同。
gst_audio_encoder_get_latency()只把基类保存的值复制到调用者变量。管线发起延迟查询时,GstAudioEncoder的默认查询处理会向上游查询延迟,再把编码器自身保存的最小和最大延迟加到查询结果中。最大延迟为GST_CLOCK_TIME_NONE时,结果继续保持无上限。
延迟查询路径直接读取基类字段,不需要先调用gst_audio_encoder_get_latency()。若延迟配置发生变化,子类应通过gst_audio_encoder_set_latency()更新状态;基类会在值变化时发送GST_MESSAGE_LATENCY,通知管线重新评估延迟。
🌻4.实战案例
4.1准备最小编码器子类
下面的示例定义一个最小的GstAudioEncoder子类。它注册必需的输入、输出Pad模板,并实现handle_frame()虚函数。示例不启动编码数据流,只创建对象并检查延迟配置。
4.2设置延迟并读取
程序先确认基类初始延迟为0,再把延迟范围设置为20ms到80ms,最后调用gst_audio_encoder_get_latency()读取并比较两个值。
4.3完整代码
#include<gst/gst.h>#include<gst/audio/audio.h>typedefstruct_LatencyEncoder{GstAudioEncoder parent;}LatencyEncoder;typedefstruct_LatencyEncoderClass{GstAudioEncoderClass parent_class;}LatencyEncoderClass;G_DEFINE_TYPE(LatencyEncoder,latency_encoder,GST_TYPE_AUDIO_ENCODER);/* 声明编码器的原始音频输入和测试编码格式输出 */staticGstStaticPadTemplate sink_template=GST_STATIC_PAD_TEMPLATE("sink",GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS("audio/x-raw"));staticGstStaticPadTemplate src_template=GST_STATIC_PAD_TEMPLATE("src",GST_PAD_SRC,GST_PAD_ALWAYS,GST_STATIC_CAPS("audio/x-test-encoded"));/* 示例只检查延迟配置,不在此处处理编码帧 */staticGstFlowReturnlatency_encoder_handle_frame(GstAudioEncoder*encoder,GstBuffer*buffer){returnGST_FLOW_OK;}staticvoidlatency_encoder_class_init(LatencyEncoderClass*klass){GstElementClass*element_class=GST_ELEMENT_CLASS(klass);GstAudioEncoderClass*encoder_class=GST_AUDIO_ENCODER_CLASS(klass);gst_element_class_add_static_pad_template(element_class,&sink_template);gst_element_class_add_static_pad_template(element_class,&src_template);gst_element_class_set_metadata(element_class,"Latency Encoder","Encoder/Audio","Minimal encoder for latency API demonstration","GStreamer");/* 提供AudioEncoder子类的帧处理入口 */encoder_class->handle_frame=latency_encoder_handle_frame;}staticvoidlatency_encoder_init(LatencyEncoder*encoder){}intmain(intargc,char*argv[]){GstAudioEncoder*encoder;GstClockTime min_latency;GstClockTime max_latency;gst_init(&argc,&argv);/* 创建自定义GstAudioEncoder对象 */encoder=GST_AUDIO_ENCODER(g_object_new(latency_encoder_get_type(),NULL));if(encoder==NULL)return1;/* 未设置前,基类保存的最小和最大延迟都应为0 */gst_audio_encoder_get_latency(encoder,&min_latency,&max_latency);if(min_latency!=0||max_latency!=0){gst_object_unref(encoder);return1;}/* 子类报告20ms到80ms的延迟范围 */gst_audio_encoder_set_latency(encoder,20*GST_MSECOND,80*GST_MSECOND);/* 读取基类当前保存的延迟值 */gst_audio_encoder_get_latency(encoder,&min_latency,&max_latency);/* 检查读取结果是否与设置值一致 */if(min_latency!=20*GST_MSECOND||max_latency!=80*GST_MSECOND){gst_object_unref(encoder);return1;}gst_object_unref(encoder);return0;}🌻5.总结
gst_audio_encoder_get_latency()就是读取GstAudioEncoder当前保存的最小和最大延迟配置并写入调用者变量。