ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux Gstreamer深度解析之gst_audio_decoder_get_latency调用流程与实战(四十一)

Linux Gstreamer深度解析之gst_audio_decoder_get_latency调用流程与实战(四十一) 简介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_decoder_get_latency()如何读取GstAudioDecoder当前配置的最小和最大延迟并通过一个可运行的C程序验证延迟设置与读取结果。GstAudioDecoder是音频解码器基类。具体解码器完成编解码参数初始化后可以通过gst_audio_decoder_set_latency()记录解码延迟。gst_audio_decoder_get_latency()负责读取这两个延迟值供解码器内部逻辑或应用诊断使用。它不计算编解码耗时不查询下游设备不发送LATENCY消息也不修改解码器状态。已有GstAudioDecoder对象gst_audio_decoder_get_latency读取ctx中的最小和最大延迟写入非空输出指针调用者获得GstClockTime结果2.应用场景和用法2.1解码延迟读取场景gst_audio_decoder_get_latency()主要用于读取解码器已经配置好的延迟边界。场景调用目的得到的结果具体解码器完成参数初始化确认当前编解码延迟得到最小和最大延迟动态编码参数变化读取新配置是否已经生效判断延迟是否同步更新应用诊断查看解码器当前延迟状态得到纳秒单位的GstClockTime延迟问题定位区分解码器延迟和下游设备延迟确认延迟来源是否属于解码器具体解码器通常在采样率、帧大小、FEC或编解码器状态确定后调用gst_audio_decoder_set_latency()。例如Opus解码器启用FEC后可能存在额外缓存延迟。FLAC解码器也会根据当前BlockSize更新延迟。gst_audio_decoder_get_latency()读取的是解码器上下文中的延迟不是min-latency属性也不是gst_audio_decoder_get_delay()返回的解析延迟。2.2函数原型与返回语义函数原型如下voidgst_audio_decoder_get_latency(GstAudioDecoder*dec,GstClockTime*min,GstClockTime*max);参数含义dec有效的GstAudioDecoder实例通常来自具体解码器子类min用于接收最小延迟可传入NULLmax用于接收最大延迟可传入NULL函数返回值是void。如果dec不是有效的音频解码器对象函数通过g_return_if_fail()提前返回。最小调用方式如下GstClockTime min_latency0;GstClockTime max_latency0;gst_audio_decoder_get_latency(decoder,min_latency,max_latency);GstClockTime以纳秒为单位。新创建的解码器上下文默认将最小和最大延迟设置为0。函数内部只读取延迟字段不创建对象不分配Buffer不触发回调也不发送LATENCY消息。min和max都可以独立传入NULL调用者只读取需要的值。几个相邻接口的职责不同接口作用gst_audio_decoder_set_latency()写入解码器上下文的最小和最大延迟并在值变化时发送LATENCY消息gst_audio_decoder_get_latency()读取上下文中的最小和最大延迟gst_audio_decoder_set_min_latency()设置输出聚合使用的最小延迟gst_audio_decoder_get_min_latency()读取输出聚合使用的最小延迟gst_audio_decoder_get_delay()读取解码器当前解析延迟GST_QUERY_LATENCY通过Pad查询整条链路的累计延迟gst_audio_decoder_get_latency()中的延迟字段属于解码器运行上下文与gst_audio_decoder_get_min_latency()读取的聚合属性不是同一个字段。3.调用流程剖析3.1延迟写入与读取关系具体解码器先根据自身状态计算延迟再调用gst_audio_decoder_set_latency()。set_latency会在对象锁保护下写入dec-priv-ctx.min_latency dec-priv-ctx.max_latency如果任意值发生变化set_latency还会向Pipeline发送LATENCY消息提示Pipeline重新计算全局延迟。之后应用或解码器内部调用gst_audio_decoder_get_latency()。该函数只读取已经保存的两个值。具体解码器确定编解码延迟gst_audio_decoder_set_latencyctx保存最小和最大延迟gst_audio_decoder_get_latency调用者得到两个GstClockTime延迟查询时叠加到Peer结果Pipeline进行GST_QUERY_LATENCY查询时解码器会先查询上游Peer的延迟再把自身保存的min_latency和max_latency叠加到查询结果中。因此gst_audio_decoder_get_latency()是读取接口GST_QUERY_LATENCY是链路查询机制两者不能混为一谈。3.2对象锁与字段读取GStreamer1.24.2中的核心实现如下voidgst_audio_decoder_get_latency(GstAudioDecoder*dec,GstClockTime*min,GstClockTime*max){g_return_if_fail(GST_IS_AUDIO_DECODER(dec));GST_OBJECT_LOCK(dec);if(min)*mindec-priv-ctx.min_latency;if(max)*maxdec-priv-ctx.max_latency;GST_OBJECT_UNLOCK(dec);}调用流程可以拆成四步检查dec是否为有效的GstAudioDecoder对象。获取GST_OBJECT_LOCK。将上下文中的延迟字段写入非空输出指针。释放对象锁并返回。有效GstAudioDecoder对象检查对象类型获取对象锁读取ctx延迟字段写入非空输出指针释放对象锁并返回这个函数不会重新计算延迟也不会访问编解码器私有句柄。解码器完整启动或停止时基类可能执行完整复位并将上下文重新清零。具体解码器通常需要在新的格式或启动阶段再次调用gst_audio_decoder_set_latency()。软Flush使用的部分复位不会重新创建延迟字段但具体行为仍取决于解码器子类的状态处理。4.实战案例4.1准备一个可实例化的音频解码器子类GstAudioDecoder本身是抽象基类不能直接通过g_object_new()创建。为了只验证延迟接口可以定义一个最小子类为基类提供SINK和SRC两个Pad模板。这个子类不执行真实音频解码只用于验证延迟字段的写入和读取。4.2设置延迟并读取结果程序按以下顺序运行创建最小GstAudioDecoder子类实例。调用gst_audio_decoder_get_latency()读取初始值。调用gst_audio_decoder_set_latency()写入10ms到20ms的延迟范围。再次调用gst_audio_decoder_get_latency()读取结果。初始上下文中的两个延迟值都是0。设置后最小延迟应为10000000纳秒最大延迟应为20000000纳秒。4.3完整代码与关键输出#includegst/gst.h#includegst/audio/gstaudiodecoder.htypedefstruct_LatencyDecoder{GstAudioDecoder parent;}LatencyDecoder;typedefstruct_LatencyDecoderClass{GstAudioDecoderClass parent_class;}LatencyDecoderClass;G_DEFINE_TYPE(LatencyDecoder,latency_decoder,GST_TYPE_AUDIO_DECODER);staticGstStaticPadTemplate sink_templateGST_STATIC_PAD_TEMPLATE(sink,GST_PAD_SINK,GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);staticGstStaticPadTemplate src_templateGST_STATIC_PAD_TEMPLATE(src,GST_PAD_SRC,GST_PAD_ALWAYS,GST_STATIC_CAPS_ANY);staticvoidlatency_decoder_class_init(LatencyDecoderClass*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,Latency Test Decoder,Codec/Decoder/Audio,Test GstAudioDecoder latency APIs,Example);}staticvoidlatency_decoder_init(LatencyDecoder*decoder){}intmain(intargc,char*argv[]){LatencyDecoder*decoder;GstClockTime min_latency;GstClockTime max_latency;gst_init(argc,argv);decoderg_object_new(latency_decoder_get_type(),NULL);if(decoderNULL){g_printerr(Failed to create decoder\n);return1;}gst_audio_decoder_get_latency(GST_AUDIO_DECODER(decoder),min_latency,max_latency);g_print(Initial latency: min%G_GUINT64_FORMAT ns, max%G_GUINT64_FORMAT ns\n,min_latency,max_latency);gst_audio_decoder_set_latency(GST_AUDIO_DECODER(decoder),10*GST_MSECOND,20*GST_MSECOND);gst_audio_decoder_get_latency(GST_AUDIO_DECODER(decoder),min_latency,max_latency);g_print(Configured latency: min%G_GUINT64_FORMAT ns, max%G_GUINT64_FORMAT ns\n,min_latency,max_latency);gst_audio_decoder_get_latency(GST_AUDIO_DECODER(decoder),min_latency,NULL);g_print(Minimum only: %G_GUINT64_FORMAT ns\n,min_latency);gst_object_unref(decoder);return0;}编译运行gcc test_audio_decoder_latency.c-otest_audio_decoder_latency\$(pkg-config--cflags--libsgstreamer-1.0 gstreamer-audio-1.0)./test_audio_decoder_latency关键输出Initial latency: min0 ns, max0 ns Configured latency: min10000000 ns, max20000000 ns Minimum only: 10000000 ns这个程序验证了gst_audio_decoder_get_latency()的三个行为读取当前上下文中的延迟值支持单独读取最小或最大延迟并且不会修改解码器对象。5.总结gst_audio_decoder_get_latency()就是在对象锁保护下读取GstAudioDecoder上下文中已经配置的最小和最大解码延迟不负责计算实际解码耗时也不负责触发Pipeline延迟重配置。
返回列表