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