gstreamer code for playing avi file is hanging

末鹿安然 提交于 2019-11-29 05:12:32

Your code is wrong in several ways, that is why my answer is so long.

First of all, gst_pipeline_new returns GstElement* not GstPipeline*:

-  pipeline = gst_pipeline_new("PIPELINE");
+  GstElement *pipeline = gst_pipeline_new("PIPELINE");
   Bin = GST_BIN(pipeline);
-  bus = gst_pipeline_get_bus(pipeline);
+  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));

Then, your pipeline is wrong: you trying to decode both streams (audio and video) with one decodebin but you need two. Create it and don't forget to add it to the bin:

   videoqueue = gst_element_factory_make("queue","Queue for video");
+  audio_decoder = gst_element_factory_make("decodebin","a_decodebin");
   video_decoder = gst_element_factory_make("decodebin","decoderbin");//"Vorbis audio decoder","vorbis");

-  gst_bin_add_many(Bin,demuxer,audioqueue,videoqueue,audio_convertor,video_decoder,video_convertor,audio_sink,video_sink,NULL);
+  gst_bin_add_many(
+    Bin,
+    demuxer,
+    audioqueue,videoqueue,
+    audio_decoder,audio_convertor,
+    video_decoder,video_convertor,
+    audio_sink,video_sink,
+    NULL);

And, by the way, it's better to use decodebin2 as decodebin is deprecated.

Then you linking some elements dynamically: demuxer to queue and decodebin to convertors. Hence you should not create link between decodebin and convertors with gst_element_link_many:

   gst_element_link(source,demuxer);
-  gst_element_link_many(audioqueue,video_decoder,audio_convertor,audio_sink,NULL);
-  gst_element_link_many(videoqueue,video_decoder,video_convertor,video_sink,NULL);
+  gst_element_link_many(audioqueue,audio_decoder,NULL);
+  gst_element_link_many(audio_convertor,audio_sink,NULL);
+  gst_element_link_many(videoqueue,video_decoder,NULL);
+  gst_element_link_many(video_convertor,video_sink,NULL);

And of course, as we added audio_decoder decodebin, we need to handle it's pad creation signal:

+  g_signal_connect(audio_decoder,"new-decoded-pad",G_CALLBACK(dynamic_decodepad),NULL);
   g_signal_connect(video_decoder,"new-decoded-pad",G_CALLBACK(dynamic_decodepad),NULL);

And now we are at the most interesting part.

void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
{
  GstPad *audiodemuxsink;
  GstPad *videodemuxsink;
  GstElement *decoder = (GstElement *)data;
  g_print(" In dynamic ADDING PAD\n");

  audiodemuxsink = gst_element_get_static_pad(audioqueue,"sink");
  gst_pad_link(pad,audiodemuxsink );
  videodemuxsink = gst_element_get_static_pad(videoqueue,"sink");
  gst_pad_link(pad,videodemuxsink );
  g_print(" In dynamic ADDING PAD2\n");
}

This is completely wrong! dynamic_addpad is called on each pad creation. avidemux commonly creates two pads (one for each data stream): "audio_00" and "video_00". So, dynamic_addpad will be called twice and we need to distinguish what to link depending on pad name:

void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
{
  char* pad_name = gst_pad_get_name(pad);
  g_print(" In dynamic ADDING PAD %s\n", pad_name);

  if (g_str_has_prefix(pad_name,"audio")) {
    GstPad *audiodemuxsink = gst_element_get_static_pad(audioqueue,"sink");
    gst_pad_link(pad,audiodemuxsink );
  }
  else if (g_str_has_prefix(pad_name,"video")) {
    GstPad *videodemuxsink = gst_element_get_static_pad(videoqueue,"sink");
    gst_pad_link(pad,videodemuxsink );
  }
  g_free (pad_name);
}

Almost the same is for dynamic_decodepad. As it's only one src pad is created by decodebin, it will be easier to create separate handlers for video_decoder and audio_decoder.
But for pedagogical reasons I will do it in one function. Now we can distinguish which element to connect to pad by it's caps.

void dynamic_decodepad (GstElement* object, GstPad* pad, gboolean arg1,gpointer user_data)
{
  GstPad* videoconvertsink = gst_element_get_static_pad(video_convertor,"sink");
  if (gst_pad_can_link(pad,videoconvertsink)) {
    gst_pad_link(pad,videoconvertsink);
  }

  GstPad* audioconvertsink  = gst_element_get_static_pad(audio_convertor,"sink");
  if (gst_pad_can_link(pad,audioconvertsink)) {
    gst_pad_link(pad,audioconvertsink);
  }
}

gst_pad_can_link will not work in dynamic_addpath because it's possible to connect query element both to "audio_00" and "video_00".

That's it. Don't hesitate to ask if you have other questions.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!