ARTICLE DETAIL

资讯详情

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

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

Linux Gstreamer深度解析之gst_audio_decoder_set_needs_format调用流程与实战(四十六) 简介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子类初始化与Caps记录3.2输入Buffer的格式门控4.实战案例4.1准备flacdec解码器实例4.2设置格式要求并观察Buffer结果4.3完整代码与关键输出5.总结1.前言本篇目的理解gst_audio_decoder_set_needs_format()如何控制音频解码器的输入格式前置条件并通过实际调用验证格式未协商时的处理结果。GstAudioDecoder负责接收编码音频数据并通过子类的set_format、parse和handle_frame完成解码。不同解码器对输入格式的依赖不同。有些解码器必须先获得Caps才能创建底层Codec对象有些解码器则可以从编码数据中自行推断格式。gst_audio_decoder_set_needs_format()用于配置这项要求设置为TRUE输入Caps没有协商成功前不允许处理输入Buffer。设置为FALSE允许子类在没有调用set_format的情况下接收数据子类必须自行完成初始化。这个函数只修改needs_format状态不发送Caps事件不调用子类的set_format也不直接执行解码。否且需要格式是或无需格式音频解码器实例设置needs_format输入Caps是否已记录返回NOT_NEGOTIATED进入解码链路2.应用场景和用法2.1解码器格式需求场景gst_audio_decoder_set_needs_format()主要用于声明解码器能否在输入Caps缺失时工作。场景设置方式实际作用底层Codec必须先获得采样率和声道数设置为TRUE等待输入Caps和set_format完成后再处理Buffer子类可以从编码数据中推断参数设置为FALSE允许数据先进入parse或handle_frame解码器实例初始化通常在子类init中调用确定该解码器的默认格式策略排查not-negotiated读取当前状态判断是否因为缺少输入Caps被拦截GStreamer中的flacdec、mpg123audiodec和opusdec等解码器会在实例初始化时把该状态设置为TRUE因为它们需要先通过格式协商建立解码上下文。默认值是FALSE。如果子类没有主动设置基类不会因为缺少input_caps而提前拒绝输入Buffer但子类必须确保自己的handle_frame能够处理未配置状态。2.2函数原型与返回语义函数原型如下voidgst_audio_decoder_set_needs_format(GstAudioDecoder*dec,gboolean enabled);参数含义dec有效的GstAudioDecoder对象enabledTRUE表示必须先完成输入格式协商FALSE表示允许未协商格式时接收数据该函数返回void。它通过GST_OBJECT_LOCK保护私有字段needs_format属于线程安全接口。最小调用方式如下gst_audio_decoder_set_needs_format(decoder,TRUE);gboolean needs_formatgst_audio_decoder_get_needs_format(decoder);调用前解码器对象已经创建。调用过程中函数只修改私有状态字段。调用后不会立即触发Caps协商也不会调用子类的set_format。真正的格式处理由后续Caps事件触发。gst_audio_decoder_sink_setcaps()收到新的输入Caps后会调用子类的set_format。只有该回调成功基类才会保存ctx.input_caps。几个相邻接口的职责不同接口作用gst_audio_decoder_set_needs_format()设置是否必须先完成输入格式协商gst_audio_decoder_get_needs_format()读取当前格式前置条件子类set_format回调接收输入Caps并配置解码器gst_audio_decoder_set_output_format()声明解码后的PCM输出格式基类输入链路根据needs_format和input_caps决定是否允许处理Bufferset_needs_format控制的是输入格式前置条件set_output_format控制的是解码后的输出格式两者不能混用。3.调用流程剖析3.1子类初始化与Caps记录解码器子类通常在实例初始化阶段调用gst_audio_decoder_set_needs_format()。以需要格式协商的解码器为例初始化过程会把needs_format设置为TRUE。之后上游发送Caps事件基类进入gst_audio_decoder_sink_setcaps()。gst_audio_decoder_sink_setcaps()执行以下动作检查新的Caps是否发生变化。调用子类的set_format回调。回调成功后把Caps保存到priv-ctx.input_caps。设置函数本身只完成第一个状态配置动作不负责后续Caps传递。解码器子类初始化设置needs_format状态上游发送输入Caps调用子类set_format记录input_caps允许后续Buffer进入如果子类的set_format返回失败input_caps不会更新。即使needs_format已经是TRUE解码器仍然不能进入正常数据处理阶段。3.2输入Buffer的格式门控输入Buffer到达解码器时基类首先获得GstAudioDecoder对象并加上流锁。随后执行格式门控if(dec-priv-ctx.input_capsNULLdec-priv-needs_format)gotonot_negotiated;进入not_negotiated分支后基类会释放流锁。发布GST_ELEMENT_ERROR错误类型为协商失败。释放当前Buffer。返回GST_FLOW_NOT_NEGOTIATED。如果needs_format为FALSE或者input_caps已经记录基类才会继续进入正向或反向数据处理链路后续可能调用子类的parse和handle_frame。是否输入Buffer到达input_caps为空且需要格式返回NOT_NEGOTIATED进入正向或反向处理调用parse或handle_frame因此gst_audio_decoder_set_needs_format()影响的是Buffer能否进入解码链路而不是Caps本身的传递过程。4.实战案例4.1准备flacdec解码器实例本案例使用GStreamer提供的flacdec作为测试对象。该解码器在实例初始化时会把needs_format设置为TRUE。先确认插件已经安装gst-inspect-1.0 flacdec程序创建flacdec实例后读取默认状态再主动设置格式要求并直接向解码器SINKPad提交一个没有输入Caps的测试Buffer。4.2设置格式要求并观察Buffer结果程序按以下顺序运行创建flacdec实例读取当前needs_format。调用gst_audio_decoder_set_needs_format()设置为TRUE。在没有输入Caps的情况下向SINKPad提交一个测试Buffer。观察基类返回的GST_FLOW_NOT_NEGOTIATED。将状态改为FALSE通过Getter确认字段已经变化。该实验验证的是格式门控不是真正的FLAC解码。由于输入Buffer没有携带FLAC格式Capsneeds_formatTRUE时基类会在进入子类解码函数前直接拒绝数据。4.3完整代码与关键输出#includegst/gst.h#includegst/audio/audio.hintmain(intargc,char*argv[]){GstElement*element;GstAudioDecoder*decoder;GstPad*sink_pad;GstBuffer*buffer;GstFlowReturn flow;gst_init(argc,argv);elementgst_element_factory_make(flacdec,decoder);if(elementNULL){g_printerr(flacdec plugin is not available\n);return1;}decoderGST_AUDIO_DECODER(element);g_print(Initial needs_format: %s\n,gst_audio_decoder_get_needs_format(decoder)?TRUE:FALSE);gst_audio_decoder_set_needs_format(decoder,TRUE);g_print(After enabling: %s\n,gst_audio_decoder_get_needs_format(decoder)?TRUE:FALSE);sink_padGST_AUDIO_DECODER_SINK_PAD(decoder);if(!gst_pad_set_active(sink_pad,TRUE)){g_printerr(Failed to activate decoder sink pad\n);gst_object_unref(element);return1;}buffergst_buffer_new_allocate(NULL,1,NULL);if(bufferNULL){g_printerr(Failed to allocate test buffer\n);gst_pad_set_active(sink_pad,FALSE);gst_object_unref(element);return1;}flowgst_pad_chain(sink_pad,buffer);g_print(Chain result without input caps: %s\n,gst_flow_get_name(flow));gst_audio_decoder_set_needs_format(decoder,FALSE);g_print(After disabling: %s\n,gst_audio_decoder_get_needs_format(decoder)?TRUE:FALSE);gst_pad_set_active(sink_pad,FALSE);gst_object_unref(element);returnflowGST_FLOW_NOT_NEGOTIATED?0:1;}编译运行gcc test_audio_decoder_needs_format.c\-otest_audio_decoder_needs_format\$(pkg-config--cflags--libsgstreamer-1.0 gstreamer-audio-1.0)./test_audio_decoder_needs_format关键输出Initial needs_format: TRUE After enabling: TRUE Chain result without input caps: not-negotiated After disabling: FALSE如果系统没有安装flacdec插件程序会在创建元素时退出。实际插件名称和可用状态以gst-inspect-1.0 flacdec的输出为准。5.总结gst_audio_decoder_set_needs_format()就是为GstAudioDecoder设置输入格式前置条件让基类在Caps未协商时决定是否允许Buffer进入子类解码链路。
返回列表