I am wondering that streamsynchronizer is only for 1-video and 1-audio and 1-text

HoonHee Lee hoonh83.lee at gmail.com
Mon Oct 7 03:38:41 PDT 2013


I am trying to play multiple stream with streamsynchronizer and
streamid-demuxer (https://bugzilla.gnome.org/show_bug.cgi?id=707605)



my test code below this.

#include <gst/gst.h>

GstElement *pipeline;
GstElement *audiotestsrc1;
GstElement *audiotestsrc2;
GstElement *audioconvert1;
GstElement *audioconvert2;
GstElement *capsfilter1;
GstElement *capsfilter2;
GstElement *vorbisenc1;
GstElement *vorbisenc2;
GstElement *oggmux1;
GstElement *oggmux2;
GstElement *funnel;
GstElement *rfunnel;
GstElement *stream_synchronizer;
GstElement *queue1;
GstElement *queue2;
GstElement *filesink1;
GstElement *filesink2;


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:{
      g_main_loop_quit (loop);
      break;
    }
    default:
      break;
  }
  return TRUE;
}

static void
src_pad_added_cb (GstElement * rfunnel, GstPad * pad, GstElement * pipeline)
{
  GstPad *sync_sinkpad1, *sync_sinkpad2;
  GstPad *sync_srcpad1, *sync_srcpad2;
  GstPad *queue_sinkpad1, *queue_sinkpad2;
  GstPad *queue_srcpad1, *queue_srcpad2;
  GstPad *filesink_sinkpad1, *filesink_sinkpad2;
  GstIterator *it;
  GValue item = G_VALUE_INIT;

  if (g_str_has_prefix (gst_pad_get_name (pad), "src_0")) {
    sync_sinkpad1 = gst_element_get_request_pad (stream_synchronizer,
"sink_%u");
    it = gst_pad_iterate_internal_links (sync_sinkpad1);
    g_assert (it);
    gst_iterator_next (it, &item);
    sync_srcpad1 = g_value_dup_object (&item);
    g_value_unset (&item);
    gst_iterator_free (it);

    gst_pad_link_full (pad, sync_sinkpad1, GST_PAD_LINK_CHECK_NOTHING);

    queue_sinkpad1 = gst_element_get_static_pad (queue1, "sink");
	gst_pad_link_full (sync_srcpad1, queue_sinkpad1,
GST_PAD_LINK_CHECK_NOTHING);

    queue_srcpad1 = gst_element_get_static_pad (queue1, "src");
    filesink_sinkpad1 = gst_element_get_static_pad (filesink1, "sink");
    gst_pad_link_full (queue_srcpad1, filesink_sinkpad1,
GST_PAD_LINK_CHECK_NOTHING);

  } else {
    sync_sinkpad2 = gst_element_get_request_pad (stream_synchronizer,
"sink_%u");
    it = gst_pad_iterate_internal_links (sync_sinkpad2);
    g_assert (it);
    gst_iterator_next (it, &item);
    sync_srcpad2 = g_value_dup_object (&item);
    g_value_unset (&item);
    gst_iterator_free (it);

    gst_pad_link_full (pad, sync_sinkpad2, GST_PAD_LINK_CHECK_NOTHING);

    queue_sinkpad2 = gst_element_get_static_pad (queue2, "sink");
    gst_pad_link_full (sync_srcpad2, queue_sinkpad2,
GST_PAD_LINK_CHECK_NOTHING);

    queue_srcpad2 = gst_element_get_static_pad (queue2, "src");
    filesink_sinkpad2 = gst_element_get_static_pad (filesink2, "sink");
    gst_pad_link_full (queue_srcpad2, filesink_sinkpad2,
GST_PAD_LINK_CHECK_NOTHING);
  }
}

gint
main (gint argc, gchar * argv[])
{
  GstCaps *caps;

  GstPad *funnel_sinkpad1, *funnel_sinkpad2;
  GstPad *funnel_srcpad;
  GstPad *rfunnel_sinkpad;
  GstPad *oggmux_srcpad1, *oggmux_srcpad2;

  GMainLoop *loop;
  GstBus *bus;
  guint bus_watch_id;

  gst_init (&argc, &argv);

  pipeline = gst_pipeline_new ("pipeline");

  audiotestsrc1 = gst_element_factory_make ("audiotestsrc", NULL);
  audioconvert1 = gst_element_factory_make ("audioconvert", NULL);
  capsfilter1 = gst_element_factory_make ("capsfilter", NULL);
  vorbisenc1 = gst_element_factory_make ("vorbisenc", NULL);
  oggmux1 = gst_element_factory_make ("oggmux", NULL);

  audiotestsrc2 = gst_element_factory_make ("audiotestsrc", NULL);
  audioconvert2 = gst_element_factory_make ("audioconvert", NULL);
  capsfilter2 = gst_element_factory_make ("capsfilter", NULL);
  vorbisenc2 = gst_element_factory_make ("vorbisenc", NULL);
  oggmux2 = gst_element_factory_make ("oggmux", NULL);

  funnel = gst_element_factory_make ("funnel", NULL);
  rfunnel = gst_element_factory_make ("streamiddemux", NULL);
  stream_synchronizer = gst_element_factory_make ("streamsynchronizer",
NULL);

  queue1 = gst_element_factory_make ("queue", NULL);
  filesink1 = gst_element_factory_make ("filesink", NULL);

  queue2 = gst_element_factory_make ("queue", NULL);
  filesink2 = gst_element_factory_make ("filesink", NULL);

  caps = gst_caps_from_string ("audio/x-raw,channels=1;");

  g_object_set (audiotestsrc1, "wave", 0, "num-buffers", 1000, NULL);
  g_object_set (capsfilter1, "caps", caps, NULL);
  g_object_set (filesink1, "location", "sine.ogg", NULL);

  g_object_set (audiotestsrc2, "wave", 6, "num-buffers", 1000, NULL);
  g_object_set (capsfilter2, "caps", caps, NULL);
  g_object_set (filesink2, "location", "pink.ogg", NULL);

  g_signal_connect (rfunnel, "pad-added", G_CALLBACK (src_pad_added_cb),
loop);

  loop = g_main_loop_new (NULL, FALSE);

  bus = gst_element_get_bus (pipeline);
  bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
  g_object_unref (bus);

  gst_bin_add_many (GST_BIN (pipeline), audiotestsrc1, audiotestsrc2,
audioconvert1, audioconvert2, capsfilter1, capsfilter2, vorbisenc1,
vorbisenc2, oggmux1, oggmux2, funnel, rfunnel, stream_synchronizer, queue1,
queue2, filesink1, filesink2, NULL);
  gst_element_link_many (audiotestsrc1, audioconvert1, capsfilter1,
vorbisenc1, oggmux1, NULL);
  gst_element_link_many (audiotestsrc2, audioconvert2, capsfilter2,
vorbisenc2, oggmux2, NULL);

  funnel_sinkpad1 = gst_element_get_request_pad (funnel, "sink_%u");
  funnel_sinkpad2 = gst_element_get_request_pad (funnel, "sink_%u");
  oggmux_srcpad1 = gst_element_get_static_pad (oggmux1, "src");
  oggmux_srcpad2 = gst_element_get_static_pad (oggmux2, "src");
  gst_pad_link (oggmux_srcpad1, funnel_sinkpad1);
  gst_pad_link (oggmux_srcpad2, funnel_sinkpad2);

  funnel_srcpad = gst_element_get_static_pad (funnel, "src");
  rfunnel_sinkpad = gst_element_get_static_pad (rfunnel, "sink");
  gst_pad_link (funnel_srcpad, rfunnel_sinkpad);

  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  g_main_loop_run (loop);

  gst_element_set_state (pipeline, GST_STATE_NULL);
  g_object_unref (pipeline);
  g_source_remove (bus_watch_id);
  g_main_loop_unref (loop);

  return 0;
}


Without streamsynchronizer, this test-code working fine with creating
sine.ogg and pink.ogg
When I tried to use streamsynchronizer, there is a blocking issue with this
function.

static gboolean
gst_stream_synchronizer_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event)
{
...
  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_STREAM_START:
    {
     ...
     for (l = self->streams; l; l = l->next) {
          GstStream *ostream = l->data;

          *all_wait* = all_wait && ostream->wait && (!have_group_id
              || ostream->group_id == group_id);
          if (!all_wait)
            break;
        }
    ...
    case GST_EVENT_SEGMENT:{
    ...
    if (stream) {
        if (stream->wait) {
          *GST_DEBUG_OBJECT (pad, "Stream %d is waiting",
stream->stream_number);*
          g_cond_wait (&stream->stream_finish_cond, &self->lock);
          stream = gst_pad_get_element_private (pad);
          if (stream)
            stream->wait = FALSE;
        }
      }
      ...
}

When second stream-start event is coming, In GST_EVENT_STREAM_START,
"all_wait" is not set as TRUE,
so, in GST_EVENT_SEGMENT, stream->wait is not set FALSE and then "Stream %d
is waiting" message is printed and waiting continuously.

I am wondering that streamsynchronizer is only for 1-video and 1-audio and
1-text not multiple streams such as 2-audio stream.




--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/I-am-wondering-that-streamsynchronizer-is-only-for-1-video-and-1-audio-and-1-text-tp4662414.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.


More information about the gstreamer-devel mailing list