播放avi文件的Gstreamer代码挂起了



我是新手。我写了一个使用gstreamer播放avi文件的代码。但是在执行代码,它只是挂了一段时间后,我无法调试什么问题,可以有人帮助我。代码和输出如下:

    Code:
    #include<stdio.h>
    #include<gst/gst.h>
    #include<glib.h>
    //Function to process message on bus of pipeline
    gboolean process_message(GstBus *bus, GstMessage *msg,gpointer data);
    //Function to add pad dynamically for ogg demux
void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data);        
void dynamic_decodepad (GstElement* object, GstPad* arg0, gboolean arg1,gpointer user_data);
     GstElement *source, *demuxer, *audio_decoder, *video_decoder, *audio_convertor,*video_convertor, *audio_sink,*video_sink,*audioqueue,*videoqueue;//*audio_demuxer, *video_demuxer,
    int main(int argc,char* argv[])
    {
      GstPipeline *pipeline;
      GstBin *Bin;
      GstBus *bus;
      GMainLoop *Mainloop;
      gst_init (&argc,&argv);
      Mainloop = g_main_loop_new(NULL,FALSE);//NULL to use the current context and False to tell its not in running state
      pipeline = gst_pipeline_new("PIPELINE");
      Bin = GST_BIN(pipeline);
      bus = gst_pipeline_get_bus(pipeline);

      source = gst_element_factory_make("filesrc","file-source");
      g_object_set(G_OBJECT(source),"location",argv[1],NULL);
      demuxer = gst_element_factory_make("avidemux","avi-demuxer");
      audioqueue = gst_element_factory_make("queue","Queue for audio");
      videoqueue = gst_element_factory_make("queue","Queue for video");
      video_decoder = gst_element_factory_make("decodebin","decoderbin");//"Vorbis audio decoder","vorbis");
      audio_convertor = gst_element_factory_make("audioconvert","audio convertor");//"Audio converter","audioconvert");
      video_convertor = gst_element_factory_make("videoscale","video convertor");//"Audio converter","audioconvert");
      audio_sink = gst_element_factory_make("autoaudiosink","Auto audio sink");
      video_sink = gst_element_factory_make("xvimagesink","XV video sink ");
      if(!source || !demuxer || !audioqueue || !videoqueue || !video_decoder ||!audio_convertor || !video_convertor || !audio_sink || !video_sink  )
      {   g_print("Could not not create elementn");
        return 0;
      }
      gst_bin_add(Bin,source);
      gst_bin_add_many(Bin,demuxer,audioqueue,videoqueue,audio_convertor,video_decoder,video_convertor,audio_sink,video_sink,NULL);
      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);
      g_signal_connect(demuxer,"pad-added",G_CALLBACK(dynamic_addpad),NULL);//demuxer and decoder are passed as instance and data as pads of both the elements are linked in dynamic_addpad
      g_signal_connect(video_decoder,"new-decoded-pad",G_CALLBACK(dynamic_decodepad),NULL);//demuxer and decoder are passed as instance and data as pads of both the elements are linked in dynamic_addpad
      gst_bus_add_watch(bus,process_message,Mainloop); //Mainloop is passed as user data as in the process_message actions are taken on the loop
      g_object_unref(bus);
      g_print("In playing staten");
      gst_element_set_state(pipeline,GST_STATE_PLAYING);//Pipeline is also a bin and bin is also an element at abstract level and hence gst_element_set_state call is used to set state of pipeline.
      g_main_loop_run(Mainloop);
      g_print("In playing state2n");
      gst_element_set_state(pipeline,GST_STATE_NULL);
      g_object_unref(G_OBJECT(pipeline));
    }

    //Function to process message on bus of pipeline
    gboolean process_message(GstBus *bus, GstMessage *msg,gpointer data)
    {
      GError *error;
      gchar *debug;
      GMainLoop *loop = (GMainLoop *)data;
      g_print(" In process message msg->type : %dn",GST_MESSAGE_TYPE(msg));
      switch(GST_MESSAGE_TYPE(msg))
      {
        case   GST_MESSAGE_UNKNOWN :
                g_print("GST_MESSAGE_UNKNOWN n");
                break;
        case   GST_MESSAGE_EOS     :
                g_print("GST_MESSAGE_EOS n");
                g_main_loop_quit(loop);
                break;
        case   GST_MESSAGE_ERROR   :
                g_print("GST_MESSAGE_ERROR n");
                gst_message_parse_error (msg, &error, &debug);
                g_free(debug);
                //if(!error)
                {
                  g_print("GST_MESSAGE_ERROR message : %s n",error->message);
                }
                g_main_loop_quit(loop);
                break;
        case   GST_MESSAGE_WARNING :
                g_print("GST_MESSAGE_WARNING  n");
                break;
        case   GST_MESSAGE_INFO    :
                g_print("GST_MESSAGE_INFO n");
                break;
        case   GST_MESSAGE_TAG     :
                g_print("GST_MESSAGE_TAG n");
                break;
        case   GST_MESSAGE_BUFFERING:
                g_print("GST_MESSAGE_BUFFERING n");
                break;
        case   GST_MESSAGE_STATE_CHANGED:
                g_print("GST_MESSAGE_STATE_CHANGED n");
                break;
        default : 
                g_print("default n");
                break;
      }
      return TRUE; //returns true always as it has to be always registered returning false will deregister the function
    }
    //Function to add pad dynamically for ogg demux
    void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
    {
      GstPad *audiodemuxsink;
      GstPad *videodemuxsink;
      GstElement *decoder = (GstElement *)data;
      g_print(" In dynamic ADDING PADn");
      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 PAD2n");
    }

    void dynamic_decodepad (GstElement* object, GstPad* pad, gboolean arg1,gpointer user_data)
    {
      GstPad *videoconvertsink;
      GstPad *audioconvertsink ;
      g_print(" In dynamic_decodepad ADDING PADn");
      videoconvertsink = gst_element_get_static_pad(video_convertor,"sink");
      gst_pad_link(pad,videoconvertsink);
      audioconvertsink  = gst_element_get_static_pad(audio_convertor,"sink");
      gst_pad_link(pad,audioconvertsink  );
      g_print(" In dynamic_decodepad ADDING PAD2n");
    }

    Output:
    In playing state
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 8192
    default 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 8192
    default 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 8192
    default 
     In process message msg->type : 8192
    default 
     In dynamic ADDING PAD
     In dynamic ADDING PAD2
     In dynamic ADDING PAD
     In dynamic ADDING PAD2
     In process message msg->type : 16
    GST_MESSAGE_TAG 
     In process message msg->type : 16
    GST_MESSAGE_TAG 
     In process message msg->type : 16
    GST_MESSAGE_TAG 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In dynamic_decodepad ADDING PAD
     In dynamic_decodepad ADDING PAD2
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 
     In process message msg->type : 64
    GST_MESSAGE_STATE_CHANGED 

此时挂起。任何帮助都是感激的。

你的代码在几个方面都是错误的,这就是为什么我的回答这么长

首先,gst_pipeline_new返回GstElement*而不是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));

然后,您的管道是错误的:您试图用一个decodebin解码两个流(音频和视频),但您需要两个。创建它,不要忘记将它添加到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);

并且,顺便说一下,最好使用decodebin2,因为decodebin已被弃用。

然后动态链接一些元素:demuxer到queue, decodebin到converter。因此,您不应该使用gst_element_link_many:

在decodebin和转换器之间创建链接
   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);
当然,当我们添加audio_decoder解码时,我们需要处理它的pad创建信号:
+  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);

现在我们到了最有趣的部分。

void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
{
  GstPad *audiodemuxsink;
  GstPad *videodemuxsink;
  GstElement *decoder = (GstElement *)data;
  g_print(" In dynamic ADDING PADn");
  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 PAD2n");
}

这是完全错误的!dynamic_addpad在每次创建pad时被调用。avidemux通常创建两个pad(每个数据流一个):"audio_00"one_answers"video_00"。因此,dynamic_addpad将被调用两次,我们需要根据pad名称来区分要链接的内容:

void dynamic_addpad(GstElement *element, GstPad *pad, gpointer data)
{
  char* pad_name = gst_pad_get_name(pad);
  g_print(" In dynamic ADDING PAD %sn", 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);
}

对于dynamic_decodepad来说几乎是一样的。由于decodebin只创建一个src pad,因此为video_decoderaudio_decoder创建单独的处理程序会更容易。
但出于教学原因,我将在一个函数中完成它。现在我们可以通过它的大写字母来区分要连接到pad的元素。

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将不能在dynamic_addpath中工作,因为query元素可以连接到"audio_00"one_answers"video_00"。

就是这样。如果还有其他问题,请尽管问。

最新更新