最近在着手开发gstreamer的插件,遇到不少问题,有木有!论坛,qq群上所谓的鸟侠关键时候都不懂了,也没人回答,有木有! 尼玛!坑嗲啊!
凡是还是要靠自己,拿出源码,自己好好的分析了一把,果然验证了那句老话,源码面前了无秘密!有木有!
言归正转,gstreamer官方的插件手册我看来基本没有,只是介绍了插件的含义,最为关键的动态加载插件的方式没有过多的介绍。所以我记录下源插件制作过程以备忘记!
插件的模板创建过程就不多说了参考手册就知道了!
我的插件主要是想通过playbin2来动态的调用我的插件实现所期望的功能,那自然要清楚playbin2的运行流程,我们会发现,运行playbin2 uri=file:///home/1.mp4命令行的时候,在playbin2的内部其实是把参数uri传给其中的uridecodebin,那我们来看侠uridecodebin中的实现过程.
当传入uri后,会进入下面这个uridecodebin的接口,
-
static GstElement *
-
gen_source_element (GstURIDecodeBin * decoder)
-
{
-
GstElement *source;
-
-
if (!decoder->uri)
-
goto no_uri;
-
-
GST_LOG_OBJECT (decoder, "finding source for %s", decoder->uri);
-
-
if (!gst_uri_is_valid (decoder->uri))
-
goto invalid_uri;
-
-
if (IS_BLACKLISTED_URI (decoder->uri))
-
goto uri_blacklisted;
-
-
source = gst_element_make_from_uri (GST_URI_SRC, decoder->uri, "source");
-
if (!source)
-
goto no_source;
这个函数主要是做写对uri的格式判断,当认为uri的格式没有问题后,就会调用
gst_element_make_from_uri接口,然后我们在来看这个接口。接口代码如下
-
GstElement *
-
gst_element_make_from_uri (const GstURIType type, const gchar * uri,
-
const gchar * elementname)
-
{
-
GList *possibilities, *walk;
-
gchar *protocol;
-
GstElement *ret = NULL;
-
-
g_return_val_if_fail (GST_URI_TYPE_IS_VALID (type), NULL);
-
g_return_val_if_fail (gst_uri_is_valid (uri), NULL);
-
-
protocol = gst_uri_get_protocol (uri);
-
possibilities = get_element_factories_from_uri_protocol (type, protocol);
-
g_free (protocol);
-
-
if (!possibilities) {
-
GST_DEBUG ("No %s for URI '%s'", type == GST_URI_SINK ? "sink" : "source",
-
uri);
-
return NULL;
-
}
-
-
possibilities = g_list_sort (possibilities, (GCompareFunc) sort_by_rank);
-
walk = possibilities;
-
while (walk) {
-
if ((ret =
-
gst_element_factory_create (GST_ELEMENT_FACTORY_CAST (walk->data),
-
elementname)) != NULL) {
-
GstURIHandler *handler = GST_URI_HANDLER (ret);
-
-
if (gst_uri_handler_set_uri (handler, uri))
-
break;
-
gst_object_unref (ret);
-
ret = NULL;
-
}
-
walk = walk->next;
-
}
-
gst_plugin_feature_list_free (possibilities);
-
-
GST_LOG_OBJECT (ret, "created %s for URL '%s'",
-
type == GST_URI_SINK ? "sink" : "source", uri);
-
return ret;
-
}
get_element_factories_from_uri_protocol (type, protocol)函数实现了主要的插件自动加载机制,我们跟进这个函数看下
-
static GList *
-
get_element_factories_from_uri_protocol (const GstURIType type,
-
const gchar * protocol)
-
{
-
GList *possibilities;
-
SearchEntry entry;
-
-
g_return_val_if_fail (protocol, NULL);
-
-
entry.type = type;
-
entry.protocol = protocol;
-
possibilities = gst_registry_feature_filter (gst_registry_get_default (),
-
search_by_entry, FALSE, &entry);
-
-
return possibilities;
-
}
发现内部把插件的type和前面解析出来的协议头分配给了entry对象,然后看
gst_registry_feature_filter的实现
-
static gboolean
-
search_by_entry (GstPluginFeature * feature, gpointer search_entry)
-
{
-
gchar **protocols;
-
GstElementFactory *factory;
-
SearchEntry *entry = (SearchEntry *) search_entry;
-
-
if (!GST_IS_ELEMENT_FACTORY (feature))
-
return FALSE;
-
factory = GST_ELEMENT_FACTORY_CAST (feature);
-
-
if (factory->uri_type != entry->type)
-
return FALSE;
-
-
protocols = gst_element_factory_get_uri_protocols (factory);
-
-
if (protocols == NULL) {
-
g_warning ("Factory '%s' implements GstUriHandler interface but returned "
-
"no supported protocols!", gst_plugin_feature_get_name (feature));
-
return FALSE;
-
}
-
-
while (*protocols != NULL) {
-
if (g_ascii_strcasecmp (*protocols, entry->protocol) == 0)
-
return TRUE;
-
protocols++;
-
}
-
return FALSE;
-
}
在进行了一番判断后,进入了
gst_element_factory_get_uri_protocols
-
gchar **
-
gst_element_factory_get_uri_protocols (GstElementFactory * factory)
-
{
-
g_return_val_if_fail (GST_IS_ELEMENT_FACTORY (factory), NULL);
-
-
return factory->uri_protocols;
-
}
发现最后这个接口返回的是要动态绑定的插件的协议数据,现在回到
gst_element_make_from_uri接口
就会发现之后就会通过将获得插件元件转换成Gsturihandler来完成对插件的uri设定,主要流程就是这样
从上面的分析也可以知道插件编写的过程中,也要实现GstURIHandlerInterface的一套方法
可以参照已有的gstreamer插件来实现
阅读(9476) | 评论(0) | 转发(0) |