Gstreamer教程 --动态pipeline



demuxer在没有看到容器文件之前无法确定需要做的工作,不能生成对应的内容。也就是说,demuxer开始时是没有source pad给其他element连接用的。

     解决方法是只管建立pipeline,让source和demuxer连接起来,然后开始运行。当demuxer接收到数据之后它就有了足够的信息生成source pad。这时我们就可以继续把其他部分和demuxer新生成的pad连接起来,生成一个完整的pipeline。

g_signal_connect()

#define             g_signal_connect(instance,detailed_signal, c_handler, data)

Connects a GCallback functionto a signal for a particular object.

The handlerwill be called before the default handler of the signal.

instance :

the instance to connect to.

detailed_signal :

a string of the form "signal-name::detail".

c_handler :

the GCallback to connect.

data :

data to pass to c_handler calls.

Returns :

the handler id


只能相邻状态改变,

绝大多数应用都是在PLAYING状态开始播放,然后跳转到PAUSE状态来提供暂停功能,最后在退出时退到NULL状态。

来自 <http://blog.csdn.net/sakulafly/article/details/20936067>

#include <gst/gst.h>

/* Structure to contain all our information, so we can passit to callbacks */

typedef struct _CustomData {

  GstElement *pipeline;

  GstElement *source;

  GstElement *convert;

  GstElement *sink;

} CustomData;

 

/* Handler for the pad-added signal */

staticvoid pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);

 

int main(int argc, char *argv[]) {

  CustomData data;

  GstBus *bus;

  GstMessage *msg;

  GstStateChangeReturn ret;

  gboolean terminate = FALSE;

 

  /* InitializeGStreamer */

  gst_init (&argc,&argv);

  

  /* Create the elements */

  data.source = gst_element_factory_make ("uridecodebin","source");

  data.convert = gst_element_factory_make ("audioconvert","convert");

  data.sink = gst_element_factory_make ("autoaudiosink","sink");

/*

uridecodebin自己会在内部初始化必要的element,然后把一个URI变成一个原始音视频流输出,它差不多做了playbin2的一半工作。因为它自己带着demuxer,所以它的source pad没有初始化,我们等会会用到。

audioconvert在不同的音频格式转换时很有用。这里用这个element是为了确保应用的平台无关性。

autoaudiosink,这个element的输出就是直接送往声卡的音频流。

 

*/ 

  /* Create the emptypipeline */

  data.pipeline =gst_pipeline_new ("test-pipeline");

 

  if (!data.pipeline ||!data.source || !data.convert || !data.sink) {

    g_printerr ("Notall elements could be created.\n");

    return -1;

  }

 

  /* Build thepipeline. Note that we are NOT linking the source at this

   * point. We will doit later. */

  gst_bin_add_many(GST_BIN (data.pipeline), data.source, data.convert , data.sink, NULL);

 

 

/* 连接convert,sink,由于目前没有source pad,之后再连接  */

  if (!gst_element_link (data.convert, data.sink)) {

    g_printerr("Elements could not be linked.\n");

    gst_object_unref (data.pipeline);

    return -1;

  }

 

  /* Set the URI toplay */

  g_object_set(data.source, "uri", "http://docs.gstreamer.com/media/sintel_trailer-480p.webm",NULL);

 

  /* Connect to the pad-added signal */

/*source element最后获得足够的数据时,它就会自动生成source pad,并且触发“pad-added”信号*/

  g_signal_connect(data.source, "pad-added", G_CALLBACK (pad_added_handler),&data);

 

 /* Start playing */

  ret = gst_element_set_state(data.pipeline, GST_STATE_PLAYING);

  if (ret ==GST_STATE_CHANGE_FAILURE) {

    g_printerr("Unable to set the pipeline to the playing state.\n");

    gst_object_unref(data.pipeline);

    return -1;

  }

 

  /* Listen to the bus*/

  bus =gst_element_get_bus (data.pipeline);

  do {

    msg =gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,

       GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

 

    /* Parse message */

    if (msg != NULL) {

      GError *err;

      gchar *debug_info;

     

      switch(GST_MESSAGE_TYPE (msg)) {

        caseGST_MESSAGE_ERROR:

         gst_message_parse_error (msg, &err, &debug_info);

          g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);

          g_printerr("Debugging information: %s\n", debug_info ? debug_info :"none");

          g_clear_error(&err);

          g_free(debug_info);

          terminate =TRUE;

          break;

        caseGST_MESSAGE_EOS:

          g_print ("End-Of-Streamreached.\n");

          terminate =TRUE;

          break;

        case GST_MESSAGE_STATE_CHANGED:

          /* We are onlyinterested in state-changed messages from the pipeline */

          if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {

            GstStateold_state, new_state, pending_state;

           gst_message_parse_state_changed (msg, &old_state, &new_state,&pending_state);

            g_print("Pipeline state changed from %s to %s:\n",

               gst_element_state_get_name (old_state), gst_element_state_get_name(new_state));

          }

          break;

        default:

          /* We shouldnot reach here */

          g_printerr("Unexpected message received.\n");

          break;

      }

      gst_message_unref (msg);

    }

  } while (!terminate);

 

  /* Free resources */

  gst_object_unref (bus);

  gst_element_set_state(data.pipeline, GST_STATE_NULL);

  gst_object_unref(data.pipeline);

  return 0;

}

 

/* This function will be called by the pad-added signal */

static void pad_added_handler (GstElement *src, GstPad*new_pad, CustomData *data) {

 

/*获取convert的sinkpad */

  GstPad *sink_pad =gst_element_get_static_pad (data->convert, "sink");

 

  GstPadLinkReturn ret;

  GstCaps *new_pad_caps =NULL;

  GstStructure*new_pad_struct = NULL;

  const gchar*new_pad_type = NULL;

 

  g_print ("Receivednew pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME(src));

 

//uridecodebin会自动创建许多的pad,对于每一个pad,这个回调函数都会被调用。

  /* If our converter isalready linked, we have nothing to do here */

  if (gst_pad_is_linked(sink_pad)) {

    g_print ("  We are already linked. Ignoring.\n");

    goto exit;

  }

 

//gst_pad_get_caps()方法会获得pad的capability(也就是pad支持的数据类型),是被封装起来的GstCaps结构。一个pad可以有多个capability,GstCaps可以包含多个GstStructure,每个都描述了一个不同的capability。

  /* Check the newpad's type */

  new_pad_caps =gst_pad_get_caps (new_pad);

  new_pad_struct =gst_caps_get_structure (new_pad_caps, 0);

  new_pad_type =gst_structure_get_name (new_pad_struct);

 

/*判断是否以audio/x-raw开头,是否为音频*/

  if (!g_str_has_prefix(new_pad_type, "audio/x-raw")) {

    g_print ("  It has type '%s' which is not raw audio.Ignoring.\n", new_pad_type);

    goto exit;

  }

 

  /* Attempt thelink  src新产生的pad和convert的sink pad*/

  ret = gst_pad_link(new_pad, sink_pad);

  if (GST_PAD_LINK_FAILED(ret)) {

    g_print ("  Type is '%s' but link failed.\n",new_pad_type);

  } else {

    g_print ("  Link succeeded (type '%s').\n",new_pad_type);

  }

 

exit:

  /* Unreference the newpad's caps, if we got them */

  if (new_pad_caps !=NULL)

    gst_caps_unref(new_pad_caps);

 

  /* Unreference the sinkpad */

  gst_object_unref(sink_pad);

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值