Revert "streamsynchronizer: Consider streams having received stream-start as waiting"
This reverts commit a1a189c07cb66af06d7047c74f6421bd36e3d66c. It breaks the uriplaylistbin tests and needs further investigation. See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4506 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9309>
This commit is contained in:
parent
b0d952ef53
commit
46df60ed1d
@ -494,7 +494,6 @@ gst_stream_synchronizer_handle_stream_start (GstStreamSynchronizer * self,
|
||||
gboolean have_group_id;
|
||||
GList *l;
|
||||
gboolean all_wait = TRUE;
|
||||
gboolean others_not_wait = TRUE;
|
||||
gboolean new_stream = TRUE;
|
||||
|
||||
have_group_id = gst_event_parse_group_id (event, &group_id);
|
||||
@ -550,36 +549,16 @@ gst_stream_synchronizer_handle_stream_start (GstStreamSynchronizer * self,
|
||||
|
||||
stream->wait = TRUE;
|
||||
|
||||
/* This variable checks if all the other streams except this one
|
||||
are not waiting. There's an initial special case: If there's only
|
||||
one stream and it's this one, set to FALSE */
|
||||
others_not_wait = self->streams != NULL && !(self->streams->next == NULL
|
||||
&& self->streams->data == stream);
|
||||
|
||||
for (l = self->streams; l; l = l->next) {
|
||||
GstSyncStream *ostream = l->data;
|
||||
/* This condition is reused for compuing both all_wait and
|
||||
others_not_wait, but the former can also support sparse streams */
|
||||
gboolean this_wait = ostream->wait && (!have_group_id
|
||||
|| ostream->group_id == group_id);
|
||||
|
||||
all_wait = all_wait && ((ostream->flags & GST_STREAM_FLAG_SPARSE)
|
||||
|| this_wait);
|
||||
|
||||
if (ostream != stream) {
|
||||
others_not_wait = others_not_wait && !this_wait;
|
||||
}
|
||||
|| (ostream->wait && (!have_group_id
|
||||
|| ostream->group_id == group_id)));
|
||||
if (!all_wait)
|
||||
break;
|
||||
}
|
||||
|
||||
/* When all the streams of a media have been waiting, all of them are
|
||||
unblocked for playback, but if a new stream appears after that (this is
|
||||
detected when stream-start comes), it will be waiting and unaware of
|
||||
all its sibling streams having already been unblocked, leading to a
|
||||
stall. All_but_this_nowait detects that case and automatically sets the
|
||||
new stream (this one) as not waiting. */
|
||||
if (others_not_wait)
|
||||
stream->wait = FALSE;
|
||||
|
||||
if (all_wait) {
|
||||
gint64 position = 0;
|
||||
|
||||
|
@ -40,19 +40,10 @@ typedef struct
|
||||
{
|
||||
GstPad *pad;
|
||||
GList *to_push;
|
||||
GMutex *push_mutex;
|
||||
GCond *push_cond;
|
||||
} MyPushInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GList *expected;
|
||||
GMutex push_mutex;
|
||||
GCond push_cond;
|
||||
gboolean compare_segment_base;
|
||||
} MyPadPrivateData;
|
||||
|
||||
MyPadPrivateData private_data_video, private_data_audio;
|
||||
GMutex push_mutex;
|
||||
GCond push_cond;
|
||||
|
||||
static GstPad *
|
||||
get_other_pad (GstPad * pad)
|
||||
@ -73,36 +64,36 @@ get_other_pad (GstPad * pad)
|
||||
static GstFlowReturn
|
||||
my_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||
{
|
||||
MyPadPrivateData *private_data = GST_PAD_ELEMENT_PRIVATE (pad);
|
||||
GList **expected = GST_PAD_ELEMENT_PRIVATE (pad);
|
||||
GList *next;
|
||||
GstBuffer *exp;
|
||||
|
||||
fail_if (private_data->expected == NULL,
|
||||
fail_if (*expected == NULL,
|
||||
"streamsynchronizer pushed a buffer/event but we didn't expect any");
|
||||
|
||||
next = (private_data->expected)->next;
|
||||
next = (*expected)->next;
|
||||
|
||||
fail_if (GST_IS_EVENT ((private_data->expected)->data),
|
||||
fail_if (GST_IS_EVENT ((*expected)->data),
|
||||
"Expected an event (%s) but got a buffer instead",
|
||||
GST_EVENT_TYPE_NAME (GST_EVENT ((private_data->expected)->data)));
|
||||
GST_EVENT_TYPE_NAME (GST_EVENT ((*expected)->data)));
|
||||
|
||||
exp = GST_BUFFER ((private_data->expected)->data);
|
||||
exp = GST_BUFFER ((*expected)->data);
|
||||
|
||||
fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf),
|
||||
GST_BUFFER_TIMESTAMP (exp));
|
||||
|
||||
GST_DEBUG ("Properly received expected buffer: %p", buf);
|
||||
GST_DEBUG ("Properly received expected buffer");
|
||||
gst_buffer_unref (exp);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
g_list_free1 (private_data->expected);
|
||||
private_data->expected = next;
|
||||
g_list_free1 (*expected);
|
||||
*expected = next;
|
||||
|
||||
/* When done signal main thread */
|
||||
if (next == NULL) {
|
||||
g_mutex_lock (&private_data->push_mutex);
|
||||
g_cond_signal (&private_data->push_cond);
|
||||
g_mutex_unlock (&private_data->push_mutex);
|
||||
g_mutex_lock (&push_mutex);
|
||||
g_cond_signal (&push_cond);
|
||||
g_mutex_unlock (&push_mutex);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
@ -111,19 +102,19 @@ my_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||
static gboolean
|
||||
my_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
{
|
||||
MyPadPrivateData *private_data = GST_PAD_ELEMENT_PRIVATE (pad);
|
||||
GList **expected = GST_PAD_ELEMENT_PRIVATE (pad);
|
||||
GList *next;
|
||||
GstEvent *exp;
|
||||
|
||||
fail_if (private_data->expected == NULL,
|
||||
fail_if (*expected == NULL,
|
||||
"streamsynchronizer pushed a buffer/event but we didn't expect any");
|
||||
|
||||
next = (private_data->expected)->next;
|
||||
next = (*expected)->next;
|
||||
|
||||
fail_unless (GST_IS_EVENT ((private_data->expected)->data),
|
||||
fail_unless (GST_IS_EVENT ((*expected)->data),
|
||||
"We were not expecting an event (But got an event of type %s)",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
exp = GST_EVENT ((private_data->expected)->data);
|
||||
exp = GST_EVENT ((*expected)->data);
|
||||
fail_unless (GST_EVENT_TYPE (event) == GST_EVENT_TYPE (exp),
|
||||
"Got event of type %s but expected of type %s",
|
||||
GST_EVENT_TYPE_NAME (event), GST_EVENT_TYPE_NAME (exp));
|
||||
@ -140,9 +131,7 @@ my_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
gst_event_parse_segment (exp, &expectseg);
|
||||
|
||||
fail_unless_equals_int (recvseg->format, expectseg->format);
|
||||
if (private_data->compare_segment_base) {
|
||||
fail_unless_equals_uint64 (recvseg->base, expectseg->base);
|
||||
}
|
||||
fail_unless_equals_uint64 (recvseg->base, expectseg->base);
|
||||
fail_unless_equals_uint64 (recvseg->offset, expectseg->offset);
|
||||
fail_unless_equals_uint64 (recvseg->start, expectseg->start);
|
||||
fail_unless_equals_uint64 (recvseg->stop, expectseg->stop);
|
||||
@ -155,20 +144,19 @@ my_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG ("Properly received expected event %s: %p",
|
||||
GST_EVENT_TYPE_NAME (exp), event);
|
||||
GST_DEBUG ("Properly received expected event %s", GST_EVENT_TYPE_NAME (exp));
|
||||
|
||||
gst_event_unref (exp);
|
||||
gst_event_unref (event);
|
||||
|
||||
g_list_free1 (private_data->expected);
|
||||
private_data->expected = next;
|
||||
g_list_free1 (*expected);
|
||||
*expected = next;
|
||||
|
||||
/* When done signal main thread */
|
||||
if (next == NULL) {
|
||||
g_mutex_lock (&private_data->push_mutex);
|
||||
g_cond_signal (&private_data->push_cond);
|
||||
g_mutex_unlock (&private_data->push_mutex);
|
||||
g_mutex_lock (&push_mutex);
|
||||
g_cond_signal (&push_cond);
|
||||
g_mutex_unlock (&push_mutex);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -179,25 +167,12 @@ my_push_thread (MyPushInfo * pushinfo)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
GST_DEBUG ("starting thread");
|
||||
|
||||
/* Nothing to do if the to_push list is empty in the first place. Signal main thread */
|
||||
if (pushinfo->to_push == NULL) {
|
||||
g_mutex_lock (pushinfo->push_mutex);
|
||||
g_cond_signal (pushinfo->push_cond);
|
||||
g_mutex_unlock (pushinfo->push_mutex);
|
||||
}
|
||||
|
||||
/* FIXME : Do this in a thread */
|
||||
for (tmp = pushinfo->to_push; tmp; tmp = tmp->next) {
|
||||
if (GST_IS_EVENT (tmp->data)) {
|
||||
GST_DEBUG ("Pushing event %s: %p",
|
||||
GST_EVENT_TYPE_NAME (GST_EVENT (tmp->data)), GST_EVENT (tmp->data));
|
||||
if (GST_IS_EVENT (tmp->data))
|
||||
gst_pad_push_event (pushinfo->pad, GST_EVENT (tmp->data));
|
||||
} else {
|
||||
GST_DEBUG ("Pushing buffer: %p", GST_BUFFER (tmp->data));
|
||||
else
|
||||
gst_pad_push (pushinfo->pad, GST_BUFFER (tmp->data));
|
||||
}
|
||||
}
|
||||
|
||||
GST_INFO ("leaving thread");
|
||||
@ -209,8 +184,7 @@ GST_START_TEST (test_basic)
|
||||
GstElement *synchr;
|
||||
GstPad *sinkpad, *srcpad;
|
||||
GstPad *mysrcpad, *mysinkpad;
|
||||
GList *to_push = NULL;
|
||||
|
||||
GList *to_push = NULL, *expected = NULL;
|
||||
GstEvent *event;
|
||||
GstBuffer *buf;
|
||||
GThread *thread;
|
||||
@ -240,24 +214,17 @@ GST_START_TEST (test_basic)
|
||||
fail_if (mysinkpad == NULL);
|
||||
fail_unless (gst_pad_link (srcpad, mysinkpad) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysinkpad, TRUE));
|
||||
GST_PAD_ELEMENT_PRIVATE (mysinkpad) = &private_data_video;
|
||||
|
||||
/* The segment.base expected time is important for this test */
|
||||
private_data_video.compare_segment_base = TRUE;
|
||||
|
||||
private_data_video.expected = NULL;
|
||||
GST_PAD_ELEMENT_PRIVATE (mysinkpad) = &expected;
|
||||
|
||||
/* Start with a stream START and a new segment */
|
||||
event = gst_event_new_stream_start ("lala");
|
||||
to_push = g_list_append (to_push, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
expected = g_list_append (expected, gst_event_ref (event));
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push = g_list_append (to_push, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
expected = g_list_append (expected, gst_event_ref (event));
|
||||
|
||||
/* Then 10 buffers */
|
||||
for (i = 0; i < 10; i++) {
|
||||
@ -265,15 +232,13 @@ GST_START_TEST (test_basic)
|
||||
GST_BUFFER_TIMESTAMP (buf) = i * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
to_push = g_list_append (to_push, buf);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_buffer_ref (buf));
|
||||
expected = g_list_append (expected, gst_buffer_ref (buf));
|
||||
}
|
||||
|
||||
/* Then a new stream start */
|
||||
event = gst_event_new_stream_start ("lala again");
|
||||
to_push = g_list_append (to_push, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
expected = g_list_append (expected, gst_event_ref (event));
|
||||
|
||||
/* This newsegment will be updated */
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
@ -285,8 +250,7 @@ GST_START_TEST (test_basic)
|
||||
segment.base = 10 * GST_SECOND;
|
||||
event = gst_event_new_segment (&segment);
|
||||
gst_event_set_seqnum (event, seqnum);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, event);
|
||||
expected = g_list_append (expected, event);
|
||||
|
||||
/* Then 10 buffers */
|
||||
for (i = 0; i < 10; i++) {
|
||||
@ -294,25 +258,22 @@ GST_START_TEST (test_basic)
|
||||
GST_BUFFER_TIMESTAMP (buf) = i * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
to_push = g_list_append (to_push, buf);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_buffer_ref (buf));
|
||||
expected = g_list_append (expected, gst_buffer_ref (buf));
|
||||
}
|
||||
|
||||
g_mutex_init (&private_data_video.push_mutex);
|
||||
pushinfo.push_mutex = &private_data_video.push_mutex;
|
||||
g_cond_init (&private_data_video.push_cond);
|
||||
pushinfo.push_cond = &private_data_video.push_cond;
|
||||
g_mutex_init (&push_mutex);
|
||||
g_cond_init (&push_cond);
|
||||
|
||||
pushinfo.pad = mysrcpad;
|
||||
pushinfo.to_push = to_push;
|
||||
g_mutex_lock (&private_data_video.push_mutex);
|
||||
g_mutex_lock (&push_mutex);
|
||||
thread = g_thread_new ("pushthread", (GThreadFunc) my_push_thread, &pushinfo);
|
||||
fail_unless (thread != NULL);
|
||||
|
||||
g_cond_wait (&private_data_video.push_cond, &private_data_video.push_mutex);
|
||||
g_mutex_unlock (&private_data_video.push_mutex);
|
||||
g_cond_wait (&push_cond, &push_mutex);
|
||||
g_mutex_unlock (&push_mutex);
|
||||
|
||||
fail_if (private_data_video.expected != NULL);
|
||||
fail_if (expected != NULL);
|
||||
|
||||
/* wait for thread to exit before freeing things */
|
||||
g_thread_join (thread);
|
||||
@ -330,545 +291,6 @@ GST_START_TEST (test_basic)
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_stream_start_wait)
|
||||
{
|
||||
GstElement *synchr;
|
||||
GstPad *sinkpad_video, *srcpad_video, *sinkpad_audio, *srcpad_audio;
|
||||
GstPad *mysrcpad_video, *mysinkpad_video, *mysrcpad_audio, *mysinkpad_audio;
|
||||
GList *to_push_video = NULL, *to_push_audio = NULL;
|
||||
GstEvent *event;
|
||||
GstBuffer *buf;
|
||||
GThread *thread_video, *thread_audio;
|
||||
MyPushInfo pushinfo_video, pushinfo_audio;
|
||||
GstSegment segment;
|
||||
|
||||
synchr = gst_element_factory_make ("streamsynchronizer", NULL);
|
||||
|
||||
GST_DEBUG ("Get sinkpad/srcpad for a first V0 stream");
|
||||
|
||||
sinkpad_video = gst_element_request_pad_simple (synchr, "sink_%u");
|
||||
fail_unless (sinkpad_video != NULL);
|
||||
srcpad_video = get_other_pad (sinkpad_video);
|
||||
fail_unless (srcpad_video != NULL);
|
||||
|
||||
gst_element_set_state (synchr, GST_STATE_PLAYING);
|
||||
|
||||
mysrcpad_video = gst_pad_new_from_static_template (&mysrctemplate, "src");
|
||||
fail_if (mysrcpad_video == NULL);
|
||||
fail_unless (gst_pad_link (mysrcpad_video, sinkpad_video) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysrcpad_video, TRUE));
|
||||
|
||||
mysinkpad_video = gst_pad_new_from_static_template (&mysinktemplate, "sink");
|
||||
gst_pad_set_chain_function (mysinkpad_video, my_sink_chain);
|
||||
gst_pad_set_event_function (mysinkpad_video, my_sink_event);
|
||||
fail_if (mysinkpad_video == NULL);
|
||||
fail_unless (gst_pad_link (srcpad_video, mysinkpad_video) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysinkpad_video, TRUE));
|
||||
GST_PAD_ELEMENT_PRIVATE (mysinkpad_video) = &private_data_video;
|
||||
|
||||
/* The segment.base expected time is important for this part of the test */
|
||||
private_data_video.compare_segment_base = TRUE;
|
||||
|
||||
private_data_video.expected = NULL;
|
||||
|
||||
GST_DEBUG ("Start with a stream-start and a segment event");
|
||||
|
||||
event = gst_event_new_stream_start ("mse/V0");
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
|
||||
GST_DEBUG ("Then 1 video buffer %p", buf);
|
||||
|
||||
to_push_video = g_list_append (to_push_video, buf);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_buffer_ref (buf));
|
||||
|
||||
GST_DEBUG ("Simulate the effect of a seek to 6s with basic events with...");
|
||||
GST_DEBUG ("...a flush-start event");
|
||||
|
||||
event = gst_event_new_flush_start ();
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
GST_DEBUG ("...a flush-stop event");
|
||||
|
||||
event = gst_event_new_flush_stop (TRUE);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
GST_DEBUG ("...a stream-start event");
|
||||
|
||||
event = gst_event_new_stream_start ("mse/V0");
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
GST_DEBUG ("...and a segment event");
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
segment.format = GST_FORMAT_TIME;
|
||||
segment.start = 6 * GST_SECOND;
|
||||
segment.time = 6 * GST_SECOND;
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
/* Run all these steps until completion before continuing */
|
||||
GST_DEBUG ("Run all these steps until completion before continuing");
|
||||
|
||||
g_mutex_init (&private_data_video.push_mutex);
|
||||
pushinfo_video.push_mutex = &private_data_video.push_mutex;
|
||||
g_cond_init (&private_data_video.push_cond);
|
||||
pushinfo_video.push_cond = &private_data_video.push_cond;
|
||||
|
||||
pushinfo_video.pad = mysrcpad_video;
|
||||
pushinfo_video.to_push = to_push_video;
|
||||
g_mutex_lock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Creating video thread");
|
||||
|
||||
thread_video =
|
||||
g_thread_new ("pushthread_video", (GThreadFunc) my_push_thread,
|
||||
&pushinfo_video);
|
||||
fail_unless (thread_video != NULL);
|
||||
|
||||
GST_DEBUG
|
||||
("Waiting for all expected video events/buffers to be processed and join the video thread");
|
||||
|
||||
g_cond_wait (&private_data_video.push_cond, &private_data_video.push_mutex);
|
||||
g_mutex_unlock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Wait completed");
|
||||
|
||||
fail_if (private_data_video.expected != NULL);
|
||||
g_thread_join (thread_video);
|
||||
|
||||
GST_DEBUG ("Now create a second stream, A0");
|
||||
|
||||
sinkpad_audio = gst_element_request_pad_simple (synchr, "sink_%u");
|
||||
fail_unless (sinkpad_audio != NULL);
|
||||
srcpad_audio = get_other_pad (sinkpad_audio);
|
||||
fail_unless (srcpad_audio != NULL);
|
||||
|
||||
mysrcpad_audio = gst_pad_new_from_static_template (&mysrctemplate, "src");
|
||||
fail_if (mysrcpad_audio == NULL);
|
||||
fail_unless (gst_pad_link (mysrcpad_audio, sinkpad_audio) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysrcpad_audio, TRUE));
|
||||
|
||||
mysinkpad_audio = gst_pad_new_from_static_template (&mysinktemplate, "sink");
|
||||
gst_pad_set_chain_function (mysinkpad_audio, my_sink_chain);
|
||||
gst_pad_set_event_function (mysinkpad_audio, my_sink_event);
|
||||
fail_if (mysinkpad_audio == NULL);
|
||||
fail_unless (gst_pad_link (srcpad_audio, mysinkpad_audio) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysinkpad_audio, TRUE));
|
||||
GST_PAD_ELEMENT_PRIVATE (mysinkpad_audio) = &private_data_audio;
|
||||
|
||||
/* The segment.base expected time is not important for this part of the test,
|
||||
* because it changes depending on the stream and sometimes is 1s for audio
|
||||
* and 0s for video and some other times it's the opposite. It's not
|
||||
* predictable. */
|
||||
private_data_video.compare_segment_base = FALSE;
|
||||
|
||||
private_data_audio.expected = NULL;
|
||||
|
||||
/* Start with a stream START and a new segment like the one used for the simulated seek */
|
||||
GST_DEBUG
|
||||
("Start with a stream-start and a new segment like the one used for the simulated seek");
|
||||
|
||||
event = gst_event_new_stream_start ("mse/A0");
|
||||
to_push_audio = g_list_append (to_push_audio, event);
|
||||
private_data_audio.expected =
|
||||
g_list_append (private_data_audio.expected, gst_event_ref (event));
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
segment.format = GST_FORMAT_TIME;
|
||||
segment.start = 6 * GST_SECOND;
|
||||
segment.time = 6 * GST_SECOND;
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push_audio = g_list_append (to_push_audio, event);
|
||||
private_data_audio.expected =
|
||||
g_list_append (private_data_audio.expected, gst_event_ref (event));
|
||||
|
||||
g_mutex_lock (&private_data_video.push_mutex);
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_TIMESTAMP (buf) = 6 * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
|
||||
GST_DEBUG ("Send one video buffer at 6 sec: %p", buf);
|
||||
|
||||
/* Discard old events/buffers from the list and start from scratch */
|
||||
g_list_free (to_push_video);
|
||||
to_push_video = NULL;
|
||||
|
||||
to_push_video = g_list_append (to_push_video, buf);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_buffer_ref (buf));
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_TIMESTAMP (buf) = 6 * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
|
||||
GST_DEBUG ("Send one audio buffer at 6 sec: %p", buf);
|
||||
|
||||
to_push_audio = g_list_append (to_push_audio, buf);
|
||||
private_data_audio.expected =
|
||||
g_list_append (private_data_audio.expected, gst_buffer_ref (buf));
|
||||
|
||||
g_mutex_init (&private_data_video.push_mutex);
|
||||
pushinfo_video.push_mutex = &private_data_video.push_mutex;
|
||||
g_cond_init (&private_data_video.push_cond);
|
||||
pushinfo_video.push_cond = &private_data_video.push_cond;
|
||||
|
||||
pushinfo_video.pad = mysrcpad_video;
|
||||
pushinfo_video.to_push = to_push_video;
|
||||
g_mutex_lock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Creating video thread again");
|
||||
|
||||
thread_video =
|
||||
g_thread_new ("pushthread_video", (GThreadFunc) my_push_thread,
|
||||
&pushinfo_video);
|
||||
fail_unless (thread_video != NULL);
|
||||
|
||||
g_mutex_init (&private_data_audio.push_mutex);
|
||||
pushinfo_audio.push_mutex = &private_data_audio.push_mutex;
|
||||
g_cond_init (&private_data_audio.push_cond);
|
||||
pushinfo_audio.push_cond = &private_data_audio.push_cond;
|
||||
|
||||
pushinfo_audio.pad = mysrcpad_audio;
|
||||
pushinfo_audio.to_push = to_push_audio;
|
||||
g_mutex_lock (&private_data_audio.push_mutex);
|
||||
|
||||
GST_DEBUG ("Creating audio thread");
|
||||
|
||||
thread_audio =
|
||||
g_thread_new ("pushthread_audio", (GThreadFunc) my_push_thread,
|
||||
&pushinfo_audio);
|
||||
fail_unless (thread_audio != NULL);
|
||||
|
||||
GST_DEBUG ("Waiting for all expected video events/buffers to be processed");
|
||||
|
||||
g_cond_wait (&private_data_video.push_cond, &private_data_video.push_mutex);
|
||||
g_mutex_unlock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Video wait completed");
|
||||
|
||||
fail_if (private_data_video.expected != NULL);
|
||||
|
||||
GST_DEBUG ("Waiting for all expected audio events/buffers to be processed");
|
||||
|
||||
g_cond_wait (&private_data_audio.push_cond, &private_data_audio.push_mutex);
|
||||
g_mutex_unlock (&private_data_audio.push_mutex);
|
||||
|
||||
GST_DEBUG ("Audio wait completed");
|
||||
|
||||
fail_if (private_data_audio.expected != NULL);
|
||||
|
||||
g_thread_join (thread_video);
|
||||
g_thread_join (thread_audio);
|
||||
|
||||
GST_DEBUG ("Cleanup");
|
||||
|
||||
g_list_free (to_push_video);
|
||||
g_list_free (to_push_audio);
|
||||
gst_element_release_request_pad (synchr, sinkpad_video);
|
||||
gst_element_release_request_pad (synchr, sinkpad_audio);
|
||||
gst_object_unref (srcpad_video);
|
||||
gst_object_unref (sinkpad_video);
|
||||
gst_object_unref (mysinkpad_video);
|
||||
gst_object_unref (mysrcpad_video);
|
||||
gst_object_unref (srcpad_audio);
|
||||
gst_object_unref (sinkpad_audio);
|
||||
gst_object_unref (mysinkpad_audio);
|
||||
gst_object_unref (mysrcpad_audio);
|
||||
gst_element_set_state (synchr, GST_STATE_NULL);
|
||||
gst_object_unref (synchr);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_stream_start_wait_sparse)
|
||||
{
|
||||
GstElement *synchr;
|
||||
GstPad *sinkpad_video, *srcpad_video, *sinkpad_audio, *srcpad_audio;
|
||||
GstPad *mysrcpad_video, *mysinkpad_video, *mysrcpad_audio, *mysinkpad_audio;
|
||||
GList *to_push_video = NULL, *to_push_audio = NULL;
|
||||
GstEvent *event;
|
||||
GstBuffer *buf;
|
||||
GThread *thread_video, *thread_audio;
|
||||
MyPushInfo pushinfo_video, pushinfo_audio;
|
||||
GstSegment segment;
|
||||
|
||||
synchr = gst_element_factory_make ("streamsynchronizer", NULL);
|
||||
|
||||
GST_DEBUG ("Get sinkpad/srcpad for a first V0 stream");
|
||||
|
||||
sinkpad_video = gst_element_request_pad_simple (synchr, "sink_%u");
|
||||
fail_unless (sinkpad_video != NULL);
|
||||
srcpad_video = get_other_pad (sinkpad_video);
|
||||
fail_unless (srcpad_video != NULL);
|
||||
|
||||
gst_element_set_state (synchr, GST_STATE_PLAYING);
|
||||
|
||||
mysrcpad_video = gst_pad_new_from_static_template (&mysrctemplate, "src");
|
||||
fail_if (mysrcpad_video == NULL);
|
||||
fail_unless (gst_pad_link (mysrcpad_video, sinkpad_video) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysrcpad_video, TRUE));
|
||||
|
||||
mysinkpad_video = gst_pad_new_from_static_template (&mysinktemplate, "sink");
|
||||
gst_pad_set_chain_function (mysinkpad_video, my_sink_chain);
|
||||
gst_pad_set_event_function (mysinkpad_video, my_sink_event);
|
||||
fail_if (mysinkpad_video == NULL);
|
||||
fail_unless (gst_pad_link (srcpad_video, mysinkpad_video) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysinkpad_video, TRUE));
|
||||
GST_PAD_ELEMENT_PRIVATE (mysinkpad_video) = &private_data_video;
|
||||
|
||||
/* The segment.base expected time is important for this part of the test */
|
||||
private_data_video.compare_segment_base = TRUE;
|
||||
|
||||
private_data_video.expected = NULL;
|
||||
|
||||
GST_DEBUG ("Start with a stream-start (sparse) and a segment event");
|
||||
|
||||
event = gst_event_new_stream_start ("mse/V0");
|
||||
gst_event_set_stream_flags (event, GST_STREAM_FLAG_SPARSE);
|
||||
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
/* The stream is sparse. The segment starts at 0s but the first buffer
|
||||
comes at 1s */
|
||||
GST_BUFFER_TIMESTAMP (buf) = 1 * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
|
||||
GST_DEBUG ("Then 1 video buffer %p", buf);
|
||||
|
||||
to_push_video = g_list_append (to_push_video, buf);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_buffer_ref (buf));
|
||||
|
||||
GST_DEBUG ("Simulate the effect of a seek to 6s with basic events with...");
|
||||
GST_DEBUG ("...a flush-start event");
|
||||
|
||||
event = gst_event_new_flush_start ();
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
GST_DEBUG ("...a flush-stop event");
|
||||
|
||||
event = gst_event_new_flush_stop (TRUE);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
GST_DEBUG ("...a stream-start (sparse) event");
|
||||
|
||||
event = gst_event_new_stream_start ("mse/V0");
|
||||
gst_event_set_stream_flags (event, GST_STREAM_FLAG_SPARSE);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
GST_DEBUG ("...and a segment event");
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
segment.format = GST_FORMAT_TIME;
|
||||
segment.start = 6 * GST_SECOND;
|
||||
segment.time = 6 * GST_SECOND;
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push_video = g_list_append (to_push_video, event);
|
||||
private_data_video.expected =
|
||||
g_list_append (private_data_video.expected, gst_event_ref (event));
|
||||
|
||||
/* Run all these steps until completion before continuing */
|
||||
GST_DEBUG ("Run all these steps until completion before continuing");
|
||||
|
||||
g_mutex_init (&private_data_video.push_mutex);
|
||||
pushinfo_video.push_mutex = &private_data_video.push_mutex;
|
||||
g_cond_init (&private_data_video.push_cond);
|
||||
pushinfo_video.push_cond = &private_data_video.push_cond;
|
||||
|
||||
pushinfo_video.pad = mysrcpad_video;
|
||||
pushinfo_video.to_push = to_push_video;
|
||||
g_mutex_lock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Creating video thread");
|
||||
|
||||
thread_video =
|
||||
g_thread_new ("pushthread_video", (GThreadFunc) my_push_thread,
|
||||
&pushinfo_video);
|
||||
fail_unless (thread_video != NULL);
|
||||
|
||||
GST_DEBUG
|
||||
("Waiting for all expected video events/buffers to be processed and join the video thread");
|
||||
|
||||
g_cond_wait (&private_data_video.push_cond, &private_data_video.push_mutex);
|
||||
g_mutex_unlock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Wait completed");
|
||||
|
||||
fail_if (private_data_video.expected != NULL);
|
||||
g_thread_join (thread_video);
|
||||
|
||||
GST_DEBUG ("Now create a second stream, A0");
|
||||
|
||||
sinkpad_audio = gst_element_request_pad_simple (synchr, "sink_%u");
|
||||
fail_unless (sinkpad_audio != NULL);
|
||||
srcpad_audio = get_other_pad (sinkpad_audio);
|
||||
fail_unless (srcpad_audio != NULL);
|
||||
|
||||
mysrcpad_audio = gst_pad_new_from_static_template (&mysrctemplate, "src");
|
||||
fail_if (mysrcpad_audio == NULL);
|
||||
fail_unless (gst_pad_link (mysrcpad_audio, sinkpad_audio) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysrcpad_audio, TRUE));
|
||||
|
||||
mysinkpad_audio = gst_pad_new_from_static_template (&mysinktemplate, "sink");
|
||||
gst_pad_set_chain_function (mysinkpad_audio, my_sink_chain);
|
||||
gst_pad_set_event_function (mysinkpad_audio, my_sink_event);
|
||||
fail_if (mysinkpad_audio == NULL);
|
||||
fail_unless (gst_pad_link (srcpad_audio, mysinkpad_audio) == GST_PAD_LINK_OK);
|
||||
fail_unless (gst_pad_set_active (mysinkpad_audio, TRUE));
|
||||
GST_PAD_ELEMENT_PRIVATE (mysinkpad_audio) = &private_data_audio;
|
||||
|
||||
/* The segment.base expected time is not important for this part of the test,
|
||||
* because it changes depending on the stream and sometimes is 1s for audio
|
||||
* and 0s for video and some other times it's the opposite. It's not
|
||||
* predictable. */
|
||||
private_data_video.compare_segment_base = FALSE;
|
||||
|
||||
private_data_audio.expected = NULL;
|
||||
|
||||
/* Start with a stream START and a new segment like the one used for the simulated seek */
|
||||
GST_DEBUG
|
||||
("Start with a stream-start (not sparse) and a new segment like the one used for the simulated seek");
|
||||
|
||||
event = gst_event_new_stream_start ("mse/A0");
|
||||
to_push_audio = g_list_append (to_push_audio, event);
|
||||
private_data_audio.expected =
|
||||
g_list_append (private_data_audio.expected, gst_event_ref (event));
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
segment.format = GST_FORMAT_TIME;
|
||||
segment.start = 6 * GST_SECOND;
|
||||
segment.time = 6 * GST_SECOND;
|
||||
event = gst_event_new_segment (&segment);
|
||||
to_push_audio = g_list_append (to_push_audio, event);
|
||||
private_data_audio.expected =
|
||||
g_list_append (private_data_audio.expected, gst_event_ref (event));
|
||||
|
||||
/* Discard old events/buffers from the list and start from scratch */
|
||||
g_list_free (to_push_video);
|
||||
to_push_video = NULL;
|
||||
g_list_free (private_data_video.expected);
|
||||
private_data_video.expected = NULL;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_TIMESTAMP (buf) = 6 * GST_SECOND;
|
||||
GST_BUFFER_DURATION (buf) = GST_SECOND;
|
||||
|
||||
GST_DEBUG ("Send one audio buffer at 6 sec: %p", buf);
|
||||
|
||||
to_push_audio = g_list_append (to_push_audio, buf);
|
||||
private_data_audio.expected =
|
||||
g_list_append (private_data_audio.expected, gst_buffer_ref (buf));
|
||||
|
||||
g_mutex_init (&private_data_video.push_mutex);
|
||||
pushinfo_video.push_mutex = &private_data_video.push_mutex;
|
||||
g_cond_init (&private_data_video.push_cond);
|
||||
pushinfo_video.push_cond = &private_data_video.push_cond;
|
||||
|
||||
pushinfo_video.pad = mysrcpad_video;
|
||||
pushinfo_video.to_push = to_push_video;
|
||||
g_mutex_lock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Creating video thread again");
|
||||
|
||||
thread_video =
|
||||
g_thread_new ("pushthread_video", (GThreadFunc) my_push_thread,
|
||||
&pushinfo_video);
|
||||
fail_unless (thread_video != NULL);
|
||||
|
||||
g_mutex_init (&private_data_audio.push_mutex);
|
||||
pushinfo_audio.push_mutex = &private_data_audio.push_mutex;
|
||||
g_cond_init (&private_data_audio.push_cond);
|
||||
pushinfo_audio.push_cond = &private_data_audio.push_cond;
|
||||
|
||||
pushinfo_audio.pad = mysrcpad_audio;
|
||||
pushinfo_audio.to_push = to_push_audio;
|
||||
g_mutex_lock (&private_data_audio.push_mutex);
|
||||
|
||||
GST_DEBUG ("Creating audio thread");
|
||||
|
||||
thread_audio =
|
||||
g_thread_new ("pushthread_audio", (GThreadFunc) my_push_thread,
|
||||
&pushinfo_audio);
|
||||
fail_unless (thread_audio != NULL);
|
||||
|
||||
GST_DEBUG ("Waiting for all expected audio events/buffers to be processed");
|
||||
|
||||
g_cond_wait (&private_data_audio.push_cond, &private_data_audio.push_mutex);
|
||||
g_mutex_unlock (&private_data_audio.push_mutex);
|
||||
|
||||
GST_DEBUG ("Audio wait completed");
|
||||
|
||||
fail_if (private_data_audio.expected != NULL);
|
||||
|
||||
GST_DEBUG ("Waiting for all expected video events/buffers to be processed");
|
||||
|
||||
g_cond_wait (&private_data_video.push_cond, &private_data_video.push_mutex);
|
||||
g_mutex_unlock (&private_data_video.push_mutex);
|
||||
|
||||
GST_DEBUG ("Video wait completed");
|
||||
|
||||
fail_if (private_data_video.expected != NULL);
|
||||
|
||||
g_thread_join (thread_video);
|
||||
g_thread_join (thread_audio);
|
||||
|
||||
GST_DEBUG ("Cleanup");
|
||||
|
||||
g_list_free (to_push_video);
|
||||
g_list_free (to_push_audio);
|
||||
gst_element_release_request_pad (synchr, sinkpad_video);
|
||||
gst_element_release_request_pad (synchr, sinkpad_audio);
|
||||
gst_object_unref (srcpad_video);
|
||||
gst_object_unref (sinkpad_video);
|
||||
gst_object_unref (mysinkpad_video);
|
||||
gst_object_unref (mysrcpad_video);
|
||||
gst_object_unref (srcpad_audio);
|
||||
gst_object_unref (sinkpad_audio);
|
||||
gst_object_unref (mysinkpad_audio);
|
||||
gst_object_unref (mysrcpad_audio);
|
||||
gst_element_set_state (synchr, GST_STATE_NULL);
|
||||
gst_object_unref (synchr);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
streamsynchronizer_suite (void)
|
||||
{
|
||||
@ -877,8 +299,6 @@ streamsynchronizer_suite (void)
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_basic);
|
||||
tcase_add_test (tc_chain, test_stream_start_wait);
|
||||
tcase_add_test (tc_chain, test_stream_start_wait_sparse);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user