简介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.1Getter读取解码器上下文3.2开关进入BYTE与TIME换算4.实战案例4.1准备一个最小GstAudioDecoder子类4.2切换开关并读取状态4.3完整代码与关键输出5.总结1.前言本篇目的理解gst_audio_decoder_get_estimate_rate()如何读取GstAudioDecoder中的估算开关分析它与BYTE和TIME换算的关系并通过一个可运行的C程序验证开关状态变化。GstAudioDecoder负责维护编码音频解码过程中的输入统计、输出样本数和音频格式信息。对于缺少精确时长信息的编码音频基类可以根据已经接收的字节数、已经输出的样本数和采样率估算BYTE与TIME之间的转换关系。gst_audio_decoder_get_estimate_rate()只负责读取这个功能开关的当前状态。它不计算码率不访问输入Buffer不执行Seek也不修改解码器状态。GstAudioDecoder上下文读取do_estimate_rate返回当前开关状态控制BYTE与TIME估算换算不执行实际解码2.应用场景和用法2.1字节时间估算场景gst_audio_decoder_get_estimate_rate()通常用于检查解码器是否允许基类执行编码数据的BYTE与TIME估算。场景调用动作结果编码流缺少精确时长读取估算开关判断基类是否允许使用统计值换算上游只提供BYTE范围检查开关和音频信息决定是否尝试换算为TIME处理BYTE格式Segment读取当前配置决定是否把Segment起点转换为TIME处理TIME格式Seek检查基类条件决定是否回退为BYTE Seek调试解码器配置读取设置前后的状态确认set_estimate_rate()是否生效估算功能只有在多个条件同时满足时才会真正参与换算。基类不仅检查do_estimate_rate还会检查输出音频的BPF、采样率以及已经输出的样本数量。如果没有足够的统计数据打开开关也不会直接得到有效的时间结果。2.2函数原型与返回语义函数原型如下gintgst_audio_decoder_get_estimate_rate(GstAudioDecoder*dec);参数或返回值含义dec有效的GstAudioDecoder实例返回值当前BYTE到TIME估算开关通常为0或1内部字段是gboolean do_estimate_rate函数返回类型却是gint。调用者可以把返回值当作布尔状态使用。最小调用方式如下gint enabled;enabledgst_audio_decoder_get_estimate_rate(decoder);if(enabled){g_print(byte to time estimation is enabled\n);}调用前decoder必须是GstAudioDecoder实例。调用过程中函数执行类型检查然后读取dec-priv-ctx.do_estimate_rate。调用后解码器对象不发生变化不创建Buffer不触发回调也不会进入上游或下游Pad。相邻接口的职责不同接口作用是否改变开关gst_audio_decoder_set_estimate_rate()写入估算开关是gst_audio_decoder_get_estimate_rate()读取估算开关否gst_audio_decoder_get_audio_info()读取当前输出音频信息否gst_audio_decoder_finish_frame()提交解码后的音频Frame否gst_audio_decoder_negotiate()协商输出格式和下游能力否默认状态来自解码器上下文初始化。上下文被清零后do_estimate_rate默认为FALSE。只有调用gst_audio_decoder_set_estimate_rate()后Getter才会返回1。3.调用流程剖析3.1Getter读取解码器上下文gst_audio_decoder_get_estimate_rate()的实现只有两个关键动作gintgst_audio_decoder_get_estimate_rate(GstAudioDecoder*dec){g_return_val_if_fail(GST_IS_AUDIO_DECODER(dec),0);returndec-priv-ctx.do_estimate_rate;}第一步使用GST_IS_AUDIO_DECODER()检查对象类型。如果对象无效函数返回0。第二步直接读取私有上下文中的do_estimate_rate字段。函数不会调用gst_audio_decoder_set_estimate_rate()也不会重新计算输入码率。调用者提供decoder检查GstAudioDecoder类型读取ctx do_estimate_rate返回gint状态调用者决定后续处理gst_audio_decoder_set_estimate_rate()负责写入同一个字段voidgst_audio_decoder_set_estimate_rate(GstAudioDecoder*dec,gboolean enabled){g_return_if_fail(GST_IS_AUDIO_DECODER(dec));dec-priv-ctx.do_estimate_rateenabled;}因此Setter和Getter之间没有额外对象也没有异步消息。Setter改变字段Getter读取字段。3.2开关进入BYTE与TIME换算Getter返回的状态最终会被gst_audio_decoder_do_byte()使用。基类会同时检查三个条件retdec-priv-ctx.do_estimate_ratedec-priv-ctx.info.bpfdec-priv-ctx.info.ratedec-priv-samples_out;只有下面条件同时成立基类才允许估算转换do_estimate_rate已经打开。输出音频BPF不为0。已经输出的样本数量达到采样率要求。满足条件后基类会使用bytes_in、samples_out和输出采样率估算编码数据的平均字节速率并通过内部转换逻辑完成BYTE与TIME换算。这条路径可能被以下操作使用TIME格式Seek无法直接交给上游时尝试转换为BYTE Seek。查询TIME格式Duration时上游只提供BYTE Duration。收到BYTE格式Segment时尝试把Segment起点转换为TIME。gst_audio_decoder_get_estimate_rate()只决定这条路径是否允许尝试真正的换算由Pad Query和内部音频转换函数完成。是否估算开关已开启检查BPF和输出样本数换算条件满足使用bytes_in和samples_out不执行估算换算完成BYTE与TIME转换这里需要区分两个概念gst_audio_decoder_get_estimate_rate()返回的是配置状态__gst_audio_encoded_audio_convert()使用的是实际统计数据。打开配置并不代表每次BYTE与TIME查询都能成功。上游查询失败、BPF为0、采样率未设置或输出样本不足时基类仍然可能拒绝换算。4.实战案例4.1准备一个最小GstAudioDecoder子类GstAudioDecoder是抽象基类不能直接使用g_object_new()创建实例。实战程序定义一个最小子类只提供Pad模板让对象可以被实例化。本案例不推动真实编码数据只验证Getter和Setter对do_estimate_rate字段的影响。4.2切换开关并读取状态程序按以下顺序运行创建最小GstAudioDecoder子类实例读取默认状态。调用gst_audio_decoder_set_estimate_rate()打开开关再读取状态。再次关闭开关确认Getter返回0。这个实验只验证配置字段不验证BYTE与TIME换算。真实换算还需要完成输出格式协商、产生输入统计并通过Pad Query进入基类转换路径。4.3完整代码与关键输出#includegst/gst.h#includegst/audio/gstaudiodecoder.htypedefstruct_TestAudioDecoder{GstAudioDecoder parent;}TestAudioDecoder;typedefstruct_TestAudioDecoderClass{GstAudioDecoderClass parent_class;}TestAudioDecoderClass;#defineTEST_TYPE_AUDIO_DECODER\(test_audio_decoder_get_type())G_DEFINE_TYPE(TestAudioDecoder,test_audio_decoder,GST_TYPE_AUDIO_DECODER);staticGstStaticPadTemplate sink_templateGST_STATIC_PAD_TEMPLATE(sink,GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS(audio/x-test));staticGstStaticPadTemplate src_templateGST_STATIC_PAD_TEMPLATE(src,GST_PAD_SRC,GST_PAD_ALWAYS,GST_STATIC_CAPS(audio/x-raw));staticvoidtest_audio_decoder_class_init(TestAudioDecoderClass*klass){GstElementClass*element_classGST_ELEMENT_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_static_metadata(element_class,Estimate Rate Test Decoder,Codec/Decoder/Audio,Test decoder for estimate-rate state,GStreamer);}staticvoidtest_audio_decoder_init(TestAudioDecoder*decoder){}intmain(intargc,char*argv[]){GstAudioDecoder*decoder;gint initial_state;gint enabled_state;gint disabled_state;gst_init(argc,argv);decoderGST_AUDIO_DECODER(g_object_new(TEST_TYPE_AUDIO_DECODER,NULL));if(decoderNULL){g_printerr(Failed to create audio decoder\n);return1;}initial_stategst_audio_decoder_get_estimate_rate(decoder);gst_audio_decoder_set_estimate_rate(decoder,TRUE);enabled_stategst_audio_decoder_get_estimate_rate(decoder);gst_audio_decoder_set_estimate_rate(decoder,FALSE);disabled_stategst_audio_decoder_get_estimate_rate(decoder);g_print(Initial estimate rate: %d\n,initial_state);g_print(After enabling: %d\n,enabled_state);g_print(After disabling: %d\n,disabled_state);gst_object_unref(decoder);return0;}编译运行gcc test_audio_decoder_estimate_rate.c\-otest_audio_decoder_estimate_rate\$(pkg-config--cflags--libsgstreamer-1.0 gstreamer-audio-1.0)./test_audio_decoder_estimate_rate关键输出Initial estimate rate: 0 After enabling: 1 After disabling: 0输出说明默认状态为关闭Setter写入TRUE后Getter返回1再写入FALSE后恢复为0。5.总结gst_audio_decoder_get_estimate_rate()就是读取GstAudioDecoder中的BYTE到TIME估算开关它不执行码率计算、数据解码或Seek操作。