gstreamer核心源码走读typefind原理浅析(二) .

在我的上一篇文章里,谈到:

 8)Filesrc最终会调用open函数打开文件。接着src组件状态也发生切换,创建一个task,最后把文件信息推送给typefind;

 9) typefind会从src读取一部分数据然后送出typefind_callback,在callback里面创建合适的plugin。合适的plugin.

   本文将从源码分析的角度,重点将这2步分析清楚。可以说,理解了这2步以及它涉及到的一些对象通信关系,基本上可以说理解了gstreamer核心源码的精髓。

    先记住这个准则:当文件切换状态时,箱柜(bin)里的元件切换状态的顺序为从sink到source.

    在上篇文章,我已经介绍了source创建和typefind组件创建的过程,并把他们加入到了我们的pipeline中。很显然,当切换状态(NULL-READY_PAUSE)时,就会走到gsttypefindelement.c文件中的切换状态函数去。如下图所示:

 由上图中的标注我们知道,会进一步去调用父类的gst_element_change_state_func,在这个函数里面,会调用activate函数。如下图所示:

 接着,gst_element_pads_activate函数会先遍历src_pads,激活src pads;然后遍历sink_pad,同样激活sink pads.在激活pad时, 都会调用的函数为gst_pad_set_active,该函数进一步会调用(GST_PAD_ACTIVATEFUNC (pad)) (pad)。该宏由gsttypefindelement在实例初始化时设置
  gst_pad_set_activate_function (typefind->sink,
      GST_DEBUG_FUNCPTR (gst_type_find_element_activate)); 即GST_PAD_ACTIVATEFUNC (pad) = gst_type_find_element_activate)

       所以实际上是对于typefind组件来说,会调用gst_type_find_element_activate()函数。

      在gst_type_find_element_activate函数里,会让typefind组件先激活在pull模式,开始typefinding。然后再激活到push模式。如下图所示:

 

 然而,上述的2个函数返回值在我们设置了src的都不是false的,因为source组件在初始化时,basesrc里会设置  gst_pad_set_getrange_function (pad, gst_base_src_pad_get_range);(笔者注:关于这点,读者可暂时没有必要去关注太多细节。)
     于是不会进入if语句下开始push模式的数据流动,而是会开始PULL模式的数据流。它会根据源组件的扩展名去获取数据来进一步作类型识别。

    

    上面的ext是根据src组件文件的uri来获取扩展名。它的办法很简单,根据uri从后往前扫描,当读到uri时,扫描完成。然后把字符串保存到扩展名中。

      接着,由于typefind工厂里保存了支持的文件扩展名信息(具体可参看下图的工厂定义),

gst_typefin_helper_get_range_ext函数把扫描到的文件扩展名与typefind工厂里的扩展名进行对比。

 

 如果找到一个与扩展名匹配的工厂,则调用gst_type_find_factory_call_function去加载相应的插件。

在该函数里,首先,他会调用gst_plugin_feature_load,根据前面查到的匹配的typefind工厂名去加载我们需要的插件以获取媒体功能(编解码等);

然后,他调用该工厂里的GstTypeFindFunction成员函数来实现source识别。这个tyepfind成员函数的实现都是在typefindfunction模块实现的,并且在gstreamer初始化的时候注册到typefind工厂里。

        看到这里,你也许看到一大堆对象:typefind组件,typefind工厂,等等。他们之间是什么关系呢?如何合作来实现我们需要的功能?

        欲知后事如何,且听下回分解

 

需转载,请注明出处:本博客链接http://blog.csdn.net/acs713/article/details/7742976

你可能感兴趣的:(Gstreamer,Linux)