0

我是 gstreamer 的新手,我想从 3gp 文件中获取音频和视频缓冲区,并在回调中进行一些处理。

(我将管道启动到一个单独的线程中,管道在回调 AudioCallback 中提供音频缓冲区,在 VideoCallback 中提供视频缓冲区。)

这就是我的管道的外观:

GstElement* audioQueue;//global variable , needed in on_pad_added (cant pass both while connecting demuxer to callback)
GstElement* videoQueue;//global variable , needed in on_pad_added (cant pass both while connecting demuxer to callback)


//static functions
static gboolean
bus_call (GstBus* bus, GstMessage* msg, gpointer    data)
{
  GMainLoop* loop = (GMainLoop*) data;

  switch (GST_MESSAGE_TYPE (msg))
  {
  case GST_MESSAGE_EOS:
      g_main_loop_quit (loop);
      break;

  case GST_MESSAGE_ERROR: {
      gchar  *debug;
      GError *error;

      gst_message_parse_error (msg, &error, &debug);
      g_free (debug);

      g_printerr ("Error: %s\n", error->message);
      g_error_free (error);

      g_main_loop_quit (loop);
      break;
    }
  default:
      break;
  }
  return true;
}

static void link_two_elements(GstElement* src_element, GstElement* sink_element)
{
  if(!gst_element_link(src_element, sink_element))
      g_printerr ("Linking Error");

}

static void
 on_pad_added (GstElement *element,
              GstPad     *pad,
              gpointer    data)
{
  GstCaps *caps;
  GstStructure *str;
  gchar *tex;
  GstPad* sinkpad;

  /* check media type */
  caps = gst_pad_get_caps (pad);
  str = gst_caps_get_structure (caps, 0);
  tex = (gchar*)gst_structure_get_name(str);

  if(g_strrstr(tex,"audio"))
  {
    //GstElement *audioQueue = (GstElement *) data;
    sinkpad = gst_element_get_static_pad (audioQueue, "sink");

    if(sinkpad)
    {
        GstPadLinkReturn linkReturn = gst_pad_link (pad, sinkpad);
        gst_object_unref (sinkpad);
    }
  }

  if(g_strrstr(tex,"video"))
  {
    //GstElement *videoQueue = (GstElement *) data;
    sinkpad = gst_element_get_static_pad (videoQueue, "sink");

    GstPadLinkReturn linkReturn = gst_pad_link (pad, sinkpad);
    gst_object_unref (sinkpad);
  }
}

void runPipeline()
    {
    GMainLoop *loop;
    GstElement *__pPipeline, *source, *demuxer, *audioDecoder, *audioConverter, *audioresample, /**audioQueue,*/ *audioSink, *videoDecoder, *videoSink, /**videoQueue,*/ *ffmpegcolorspace, *videoscale;
    GstBus* bus;

     //Initialisation
    gst_init (null,null);

    loop = g_main_loop_new (NULL, FALSE);

    // Create gstreamer elements
    __pPipeline = gst_pipeline_new("test_appsink");
    source = gst_element_factory_make ("filesrc", "file-source");
    demuxer = gst_element_factory_make("qtdemux", "demuxer");
    //audioDecoder = gst_element_factory_make("ffdec_mp3", "audioDecoder");
    audioDecoder = gst_element_factory_make("decodebin", "audioDecoder");
    audioConverter = gst_element_factory_make("audioconvert", "audioConverter");
    audioresample = gst_element_factory_make("audioresample", "audioresample");
    audioSink = gst_element_factory_make("appsink", "audioSink");
    audioQueue = gst_element_factory_make("queue2", "audioQueue");
    //videoDecoder = gst_element_factory_make("ffdec_h264", "videoDecoder");
    videoQueue = gst_element_factory_make("queue2", "videoQueue");
    videoDecoder = gst_element_factory_make("decodebin ", "videoDecoder");
    ffmpegcolorspace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace");
    videoscale = gst_element_factory_make("videoscale", "videoscale");
    videoSink = gst_element_factory_make("appsink", "videoSink");
    //appsink = gst_element_factory_make("appsink", "sink-buffer");

    if (!__pPipeline || !source  || !demuxer || !audioDecoder || !audioConverter ||!audioresample || !audioSink || !videoSink || !audioQueue || !videoQueue || !videoDecoder || !ffmpegcolorspace || !videoscale )
    {
      //return -1;
    }

    //we set the input filename to the source element
    g_object_set (G_OBJECT (source), "location", "/etc/20000101-161404.3gp", NULL);

    //Make appsink emit the "new-preroll" and "new-buffer" signals.
    gst_app_sink_set_emit_signals ((GstAppSink*) audioSink, TRUE);
    gst_app_sink_set_emit_signals ((GstAppSink*) videoSink, TRUE);

    //we add a message handler
    bus = gst_pipeline_get_bus (GST_PIPELINE (__pPipeline));
    gst_bus_add_watch (bus, bus_call, loop);
    gst_object_unref (bus);

     //we add all elements into the pipeline
    gst_bin_add_many (GST_BIN (__pPipeline),
                    source, demuxer, videoDecoder, audioDecoder, audioConverter, audioresample, audioSink, videoSink,
                    audioQueue, videoQueue, ffmpegcolorspace, videoscale, NULL);


    //link source and demuxer seperately
    link_two_elements(source, demuxer);

    //link rest of the elements
    int retValVideoLinking = (int)gst_element_link_many (videoQueue, videoDecoder, ffmpegcolorspace, videoscale, videoSink, NULL);
    int retValAudioLinking = (int)gst_element_link_many (audioQueue, audioDecoder, audioConverter, audioresample, audioSink, NULL);

    gulong sigConRet =  g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), null);

    _ArAudioIn audioInstance = _ArAudioIn::GetArAudioInstance();

    g_signal_connect (videoSink, "new-buffer",  G_CALLBACK (AudioCallback), null);//AudioCallback static API
    g_signal_connect (audioSink, "new-buffer",  G_CALLBACK (VideoCallback), null);//VideoCallback static API

     //Set the pipeline to "playing" state
    GstStateChangeReturn state = gst_element_set_state (__pPipeline, GST_STATE_PLAYING);

    g_main_loop_run (loop);
    return null;
    }


I'm just getting a single video buffer in my Videocallback and also in the on_pad_addded : I'm getting a linking err for audio pad linking.
GST_PAD_LINK_NOFORMAT         = -4,

I'm trying to link the queue's sink pad to the pad recieved in on_pad_added, same is working for video but not for audio.

If anybody has any idea about this then please give me some pointers to get rid off this err and make this pipeline work.
4

1 回答 1

0

如果你在要求我们调试之前清理你的代码会很好。作为一般建议,检查返回值并记录警告或简单地退出(1)以确保您的管道设置正常工作(例如在 pad_added 处理程序中)。我也会开始使用普通的视频和音频接收器来检查它是否可以播放。

最后,从管道中提取数据通常是个坏主意。也许您可以在回调中有数据后告诉您要如何处理数据,以便我们提供更好的建议。

于 2012-06-25T16:06:47.553 回答