简介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延迟重配置。
企业数字化 ERP 产品动态
相关推荐
zvec-grep索引构建实战:如何挑选文件范围,为你的仓库打造最佳搜索索引 zvec-grep索引构建实战:如何挑选文件范围,为你的仓库打造最佳搜索索引 【免费下载链接】zvec-grep Local-first search across your workspace, built for humans and AI agents. 项目地址: https://gitcode.com/gh_mirrors/zv/zvec-grep
zvec-gr… · 2026/9/26 11:00:37
养老机构夜间防跌倒:毫米波雷达成像的落地与调优经验 做养老机构智能化改造这几年,我最怕听到的一句话是:老人昨晚摔了,但直到早上查房才发现。更难受的是,很多机构明明装了设备——摄像头、拉绳、红外感应、智能手环——关键时刻却一个能打的都没有。直到我们在一家试点机构把“万蕴… · 2026/9/26 11:00:30
表单验证完整实现:从交互反馈到后端安全校验的实战指南 表单验证大概是所有 Web 项目里最不起眼、却最容易翻车的一环。我这几年接手过不少项目,最典型的坑不是功能没实现,而是“验证规则飘忽不定”:前端改了一版正则,后端又按另一套规则校验,结果线上用户填了“看起来合法”… · 2026/9/26 12:08:47
抖音推流码与OBS配置全攻略:RTMP原理、参数计算与故障排查 1. 抖音推流码到底是什么,为什么值得单独聊做直播的人迟早会碰到一个场景:手机开播画面太单薄,想用电脑摄像头、想接采集卡、想叠一层实时字幕或者做个画中画,这时候就绕不开“推流码”这三个字。抖音官方给的这个东西,… · 2026/9/26 12:08:47
Chatbox接入LangGraph智能体:TaoToken统一Key配置与Trae Solo联调指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 12:08:47
百考通AI实战:毕业设计从选题到答辩的全流程智能辅助方案 每年三四月,我朋友圈的画风就会突然统一起来——全是论文截图,配文不是“刚刚改完第7版”,就是“今晚要把绪论肝完”。这种痛我太熟了,带过几届毕业生,见过太多人被文献综述、数据分析、导师意见来回拉扯,最… · 2026/9/26 12:08:47
JS集合去重与排序全解析:从Set到sort的实战避坑指南 前几天代码评审,同事交上来一行堪称"标准答案"的代码: [...new Set(data)].sort() 。去重调用Set,排序交给sort,看起来一气呵成。结果测试一跑就翻车,数字列表直接乱套:10排在9前面,… · 2026/9/26 12:08:41
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46