Gstreamer中的uridecodebin插件使用非常方便,可根据给定的uri,自动选择合适的不同媒体解封装组件和音视频解码器,从而屏蔽了不同媒体的封装类型和解码器的类型。在安装deepstream之前,uridecodebin工作很正常,解码器自动选择的是avdec_h264或者avec_h265插件,但是在装deepstream 5.1之后, uridecodebin便全部使用nvv4l2decode进行解码,nvv4l2decode采用显卡解码,要求显卡有视频编解码核心支持,而我的笔记本的只是一个GeForece MX150,根本没有编解码核心。这就导致每次使用uridecodebin就在解码环节卡住不动了。查阅uridecodebin的文档,发现该bin在选择满足需求的插件的时候,会按照插件的rank值高低,选择高rank值的插件:
通过gst-inspect查看,nvv4l2decoder的rank值为267, 而avdec_h264的rank值为256,因此自然而然nvv4l2decoder成了第一选择。
虽然也可以在构建管道的时候使用 filesrc->qtdemux->h264parse->avdec_h264等一众插件替换uridecodebin,但是在deepstream的例程里面大量使用uridecodebin,尤其是在deepstream-app中,代码结构比较复杂,如果更换管道组件,需要大量改写源代码,极易出错。有没有简单的办法,能控制uridecodebin选择哪一种解码器,而不用更改管道结构? 答案是肯定的。
查阅uridecodebin的文档uridecodebin ,发现有autoplug-factories、autoplug-query、autoplug-select、autoplug-sort等几个信号,其中autoplug-factories信号在 uridecodebin插件发现有满足需要的插件是发出,返回满足该媒体要求的factories数组。autoplug-query是一个查询信号,autoplug-select当uridecodebin准备选择某个插件的时候发出,这里如果返回是GST_AUTOPLUG_SELECT_TRY,则uridecodebin会选择该插件工厂,如果返回是GST_AUTOPLUG_SELECT_SKIP,则uridecodebin会跳过该插件工厂,选择下一个满足条件的插件工厂。
显然通过连接该信号,就可以控制uridecodebin使用什么插件了。
用Gstreamermm编写了一段代码实验,其中核心代码为:
uridecodebin->signal_pad_added().connect([uridecodebin,conv](const RefPtr<Pad>& pad){
auto caps = pad->get_current_caps();
auto stru_name = caps->get_structure(0).get_name();
cout<<"新的pad信号:"<<stru_name<<endl;
if (stru_name.find("video") != ustring::npos){
if (pad->link(conv->get_static_pad("sink"))!=Gst::PAD_LINK_OK)
cerr<<"连接uridecodebin到videoconvert错误"<<endl;
}
});
conv->link(sink);
uridecodebin->signal_autoplug_select().connect([uridecodebin](const RefPtr<Pad>& pad, const RefPtr<Caps>& caps, const RefPtr<ElementFactory>& factory ){
auto factory_name = factory->get_name();
cout<<"Ready to select elementfactory: "<<factory_name<<endl;
if (factory->get_name().find("v4l2")!=ustring::npos) {
cout<<"nvv4l2decode不适合本机,skip!!!."<<endl;
return Gst::AUTOPLUG_SELECT_SKIP;
}
else
return Gst::AUTOPLUG_SELECT_TRY;
});
实验结果如下:
0:00:00.034184320 8858 0x55a05c0db800 WARN basesrc gstbasesrc.c:3600:gst_base_src_start_complete:<source> pad not activated yet
0:00:00.034510822 8858 0x55a05c0db800 WARN basesrc gstbasesrc.c:3600:gst_base_src_start_complete:<source> pad not activated yet
Ready to select elementfactory: qtdemux
0:00:00.040910902 8858 0x55a05c0c2f60 WARN qtdemux qtdemux_types.c:239:qtdemux_type_get: unknown QuickTime node type sgpd
0:00:00.040930390 8858 0x55a05c0c2f60 WARN qtdemux qtdemux_types.c:239:qtdemux_type_get: unknown QuickTime node type sbgp
0:00:00.040958105 8858 0x55a05c0c2f60 WARN qtdemux qtdemux.c:3237:qtdemux_parse_trex:<qtdemux0> failed to find fragment defaults for stream 1
0:00:00.041057273 8858 0x55a05c0c2f60 WARN qtdemux qtdemux.c:3237:qtdemux_parse_trex:<qtdemux0> failed to find fragment defaults for stream 2
Ready to select elementfactory: h264parse
Ready to select elementfactory: aacparse
Ready to select elementfactory: avdec_aac
Ready to select elementfactory: nvv4l2decoder
nvv4l2decode不适合本机,skip!!!.
Ready to select elementfactory: avdec_h264