)
简介CSDN博客专家、《Android系统多媒体进阶实战》作者博主新书推荐《Android系统多媒体进阶实战》Android Audio工程师专栏地址Audio工程师进阶系列【原创干货持续更新中……】Android多媒体专栏地址多媒体系统工程师系列【原创干货持续更新中……】专题一 二AAOS车载系统AOSP14系统攻城狮入门视频实战课专题三Android14 Binder之HIDL与AIDL通信实战课专题四Android15快速自定义与集成音效实战课专题五Android15音频策略实战课专题六Android15音频性能实战课(无声/杂音/断音/爆音实战案例)人生格言人生从来没有捷径只有行动才是治疗恐惧和懒惰的唯一良药.更多原创,欢迎关注Android系统攻城狮文章目录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()设置。GstAudioEncoder当前延迟配置gst_audio_encoder_get_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_LATENCYgst_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)*minenc-priv-ctx.min_latency;if(max)*maxenc-priv-ctx.max_latency;GST_OBJECT_UNLOCK(enc);因此调用前后的关系是编码器对象中已经有延迟配置函数读取指定字段调用者得到对应的纳秒值。函数不会创建新对象也不会更改编码器配置。有效的GstAudioEncoder对象获取对象锁读取min_latency和max_latency输出指针是否有效写入调用者变量并释放对象锁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通知管线重新评估延迟。下游发起GST_QUERY_LATENCY编码器向上游查询读取编码器已配置的延迟累加延迟并返回查询结果4.实战案例4.1准备最小编码器子类下面的示例定义一个最小的GstAudioEncoder子类。它注册必需的输入、输出Pad模板并实现handle_frame()虚函数。示例不启动编码数据流只创建对象并检查延迟配置。4.2设置延迟并读取程序先确认基类初始延迟为0再把延迟范围设置为20ms到80ms最后调用gst_audio_encoder_get_latency()读取并比较两个值。4.3完整代码#includegst/gst.h#includegst/audio/audio.htypedefstruct_LatencyEncoder{GstAudioEncoder parent;}LatencyEncoder;typedefstruct_LatencyEncoderClass{GstAudioEncoderClass parent_class;}LatencyEncoderClass;G_DEFINE_TYPE(LatencyEncoder,latency_encoder,GST_TYPE_AUDIO_ENCODER);/* 声明编码器的原始音频输入和测试编码格式输出 */staticGstStaticPadTemplate sink_templateGST_STATIC_PAD_TEMPLATE(sink,GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS(audio/x-raw));staticGstStaticPadTemplate src_templateGST_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_classGST_ELEMENT_CLASS(klass);GstAudioEncoderClass*encoder_classGST_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_framelatency_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对象 */encoderGST_AUDIO_ENCODER(g_object_new(latency_encoder_get_type(),NULL));if(encoderNULL)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当前保存的最小和最大延迟配置并写入调用者变量。