From c257b19eadbff97fac93a163f3d59b07491ffb27 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Mon, 29 Oct 2012 12:08:31 +0000 Subject: [PATCH] queue: don't fail in _sink_event for sticky events Implement the same behaviour as gst_pad_push_event when pushing sticky events fails, that is don't fail immediately but fail when data flow resumes and upstream can aggregate properly. This fixes segment seeks with decodebin and unlinked audio or video branches. Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=687899 --- plugins/elements/gstqueue.c | 21 +++++++++++++++- tests/check/elements/queue.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/plugins/elements/gstqueue.c b/plugins/elements/gstqueue.c index 453e97f..fc6a75c 100644 --- a/plugins/elements/gstqueue.c +++ b/plugins/elements/gstqueue.c @@ -771,7 +771,17 @@ gst_queue_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) default: if (GST_EVENT_IS_SERIALIZED (event)) { /* serialized events go in the queue */ - GST_QUEUE_MUTEX_LOCK_CHECK (queue, out_flushing); + GST_QUEUE_MUTEX_LOCK (queue); + if (queue->srcresult != GST_FLOW_OK) { + /* Errors in sticky event pushing are no problem and ignored here + * as they will cause more meaningful errors during data flow. + * For EOS events, that are not followed by data flow, we still + * return FALSE here though. + */ + if (!GST_EVENT_IS_STICKY (event) || + GST_EVENT_TYPE (event) == GST_EVENT_EOS) + goto out_flow_error; + } /* refuse more events on EOS */ if (queue->eos) goto out_eos; @@ -802,6 +812,15 @@ out_eos: gst_event_unref (event); return FALSE; } +out_flow_error: + { + GST_CAT_LOG_OBJECT (queue_dataflow, queue, + "refusing event, we have a downstream flow error: %s", + gst_flow_get_name (queue->srcresult)); + GST_QUEUE_MUTEX_UNLOCK (queue); + gst_event_unref (event); + return FALSE; + } } static gboolean diff --git a/tests/check/elements/queue.c b/tests/check/elements/queue.c index 7a6e7d9..a489aa1 100644 --- a/tests/check/elements/queue.c +++ b/tests/check/elements/queue.c @@ -630,6 +630,62 @@ GST_START_TEST (test_time_level_task_not_started) GST_END_TEST; +GST_START_TEST (test_sticky_not_linked) +{ + GstEvent *event; + GstSegment segment; + gboolean ret; + GstFlowReturn flow_ret; + + GST_DEBUG ("starting"); + + g_object_set (queue, "max-size-buffers", 1, NULL); + + UNDERRUN_LOCK (); + fail_unless (gst_element_set_state (queue, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + UNDERRUN_WAIT (); + UNDERRUN_UNLOCK (); + + gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); + + gst_segment_init (&segment, GST_FORMAT_TIME); + segment.start = 1 * GST_SECOND; + segment.stop = 5 * GST_SECOND; + segment.time = 0; + segment.position = 1 * GST_SECOND; + + event = gst_event_new_segment (&segment); + ret = gst_pad_push_event (mysrcpad, event); + fail_unless (ret == TRUE); + + /* the first few buffers can return OK as they are queued and gst_queue_loop + * is woken up, tries to push and sets ->srcresult to NOT_LINKED + */ + flow_ret = GST_FLOW_OK; + while (flow_ret != GST_FLOW_NOT_LINKED) + flow_ret = gst_pad_push (mysrcpad, gst_buffer_new ()); + + /* send a new sticky event so that it will be pushed on the next gst_pad_push + */ + event = gst_event_new_segment (&segment); + ret = gst_pad_push_event (mysrcpad, event); + fail_unless (ret == TRUE); + + /* make sure that gst_queue_sink_event doesn't return FALSE if the queue is + * unlinked, as that would make gst_pad_push return ERROR + */ + flow_ret = gst_pad_push (mysrcpad, gst_buffer_new ()); + fail_unless_equals_int (flow_ret, GST_FLOW_NOT_LINKED); + + GST_DEBUG ("stopping"); + fail_unless (gst_element_set_state (queue, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); +} + +GST_END_TEST; + #if 0 static gboolean event_equals_newsegment (GstEvent * event, gboolean update, gdouble rate, @@ -773,6 +829,7 @@ queue_suite (void) #if 0 tcase_add_test (tc_chain, test_newsegment); #endif + tcase_add_test (tc_chain, test_sticky_not_linked); return s; } -- 2.7.4