gstreamer学习笔记---demux使用

版权声明:本文为博主原创文章,未经允许,不得转载。 https://blog.csdn.net/weixin_41944449/article/details/82219885

  在使用gstreamer的过程中,相信很多是都通过gst-launch-1.0直接使用playbin或者自建pipeline完成相应的播放测试,反而很少的会自己编写代码,其实,gst-launch-1.0帮助我们做了很多工作,在自己编写程序的时候,反而会忽略掉,比如我们要说的demux。
  demux,解复用器,我将它理解为解封装,在播放封装音视频的时候,一般都会需要先进行解封装,然后在解码、播放或者显示。但是,在解封装之前,由于demux并不事先知道音视频的格式,所以在代码中,通过gst_element_link_many()或者相关函数link element,发现在demux与下游element连接的时候返回是错误的。
  为什么呢?下面我们来看看,以qtdemux为例。
  首先我们看看qtdemux支持的pad信息,详细如下:

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/quicktime
      video/mj2
      audio/x-m4a
      application/x-3gp

  SRC template: 'video_%u'
    Availability: Sometimes
    Capabilities:
      ANY

  SRC template: 'audio_%u'
    Availability: Sometimes
    Capabilities:
      ANY

  SRC template: 'subtitle_%u'
    Availability: Sometimes
    Capabilities:
      ANY

  细心的会发现,src pad是随机型的,就是说,qtdemux并不知道它的输出是什么,但是分别有这三种,在实际使用过程中,会根据输入数据相应的使用不同的src pad。
  而在我们link的时候,element间数据并没有流通,demux并不知道它的输出是哪种类型的src pad,自然的,link就会失败,但是,有没有办法解决呢,肯定有的,要不然在我们通过gst-launch-1.0自建pipeline的时候又怎么会可以正常播放呢,下面我们再来分析。
  在上面我们已经知道,demux的src pad是随机型的,那么,是什么时候知道src pad是什么类型呢。一般的,是在element从READY状态切换到PAUSED状态时,上游element的数据将会预流到demux,在这个时候,demux将会解析数据,然后配置stream信息,根据数据创建相应的src pad,完成这个操作之后,将会通过gst_element_add_pad()将pad添加到demux,奥秘就在这个函数了。
  在gst_element_add_pad()中,有以下这样的一行代码:

  /* emit the PAD_ADDED signal */
  g_signal_emit (element, gst_element_signals[PAD_ADDED], 0, pad);

  看到这里就明白了吧,在demux添加src pad的时候,将会通过上面的函数发送一个pad-added信号。然后我们在程序中,再接收这个信号,此时再进行link就可以了,简单实例代码如下:

static void qtdemux_pad_added_cb (GstElement *qtdemux, GstPad *pad, GstElement *mjpegdec)
{
  gst_element_link_pads(qtdemux, GST_PAD_NAME (pad), mjpegdec, NULL);
}

int main(int argc, char *argv[])
{
  ...
  /* 其实在这里link,只会link到filesrc和qtdemux,因为在qtdemux与后面的mjpegdec link会
   * 失败,函数就返回了,所以我下面再重新link,这个只是简单示例,实际应用自己商榷 */
  gst_bin_add_many(GST_BIN(pipeline), filesrc, qtdemux, mjpegdec, fbsink, NULL);
  gst_element_link(filesrc, qtdemux);
  gst_element_link(mjpegdec, fbsink);

  /* We'll want to know when the source pad is added */
  g_signal_connect (qtdemux, "pad-added", (GCallback) qtdemux_pad_added_cb, mjpegdec);
  ...
}

  在程序中,通过g_signal_connect()函数绑接收”pad-added”信号的回调函数qtdemux_pad_added_cb()。而回调函数的函数又是怎样确定的呢?可以看到qtdemux_pad_added_cb (GstElement *qtdemux, GstPad *pad, GstElement *mjpegdec),第一个函数参数qtdemux是我们在g_signal_connect()的第一个参数,而第二个参数pad是在g_signal_emit()发送信号是传进来的参数pad,而第三个参数则是g_signal_connect()传进来的mjpegdec,所以,大家知道怎么编写信号回调函数了吧,这里是假设只有视频srcpad的,可能还会有音频或者字幕的,可根据GST_PAD_NAME (pad)得到pad的信息,再相应的link element。
  而为什么我们使用gst-launch-1.0会可以的,是因为在gstreamer-1.xx.x/gst/parse目录下的grammar.y文件进行了延迟link的操作,感兴趣的可以看看该文件的实现。


  以上是个人理解,有理解错误的地方,欢迎指出,感谢

猜你喜欢

转载自blog.csdn.net/weixin_41944449/article/details/82219885
今日推荐