From: Wim Taymans Date: Thu, 5 Apr 2007 11:16:09 +0000 (+0000) Subject: libs/gst/base/gstbasesink.c: Fix leak caused when refusing newsegment after EOS. X-Git-Tag: RELEASE-0_10_13~111 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=12c933466769d9bb8796d7e66b35d0bba14f3971;p=platform%2Fupstream%2Fgstreamer.git libs/gst/base/gstbasesink.c: Fix leak caused when refusing newsegment after EOS. Original commit message from CVS: * libs/gst/base/gstbasesink.c: (gst_base_sink_queue_object_unlocked), (gst_base_sink_event): Fix leak caused when refusing newsegment after EOS. * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init), (gst_fake_sink_init), (gst_fake_sink_set_property), (gst_fake_sink_get_property), (gst_fake_sink_preroll), (gst_fake_sink_render), (gst_fake_sink_change_state): * plugins/elements/gstfakesink.h: Add num-buffers property to make the element generate EOS after a configurable amount of buffers. API: fakesink::num-buffers property. * tests/check/elements/fakesink.c: (GST_START_TEST), (fakesink_suite): Fix GstBus leak in test. Test for fakesink num-buffers. --- diff --git a/ChangeLog b/ChangeLog index eefd3ad..dc492f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,26 @@ 2007-04-05 Wim Taymans * libs/gst/base/gstbasesink.c: + (gst_base_sink_queue_object_unlocked), (gst_base_sink_event): + Fix leak caused when refusing newsegment after EOS. + + * plugins/elements/gstfakesink.c: (gst_fake_sink_class_init), + (gst_fake_sink_init), (gst_fake_sink_set_property), + (gst_fake_sink_get_property), (gst_fake_sink_preroll), + (gst_fake_sink_render), (gst_fake_sink_change_state): + * plugins/elements/gstfakesink.h: + Add num-buffers property to make the element generate EOS after a + configurable amount of buffers. + API: fakesink::num-buffers property. + + * tests/check/elements/fakesink.c: (GST_START_TEST), + (fakesink_suite): + Fix GstBus leak in test. + Test for fakesink num-buffers. + +2007-04-05 Wim Taymans + + * libs/gst/base/gstbasesink.c: (gst_base_sink_queue_object_unlocked), (gst_base_sink_event), (gst_base_sink_change_state): Don't accept anything after an EOS, return UNEXPECTED instead. diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index 9703326..34e9357 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -1879,7 +1879,8 @@ gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad, /* special cases */ was_eos: { - GST_DEBUG_OBJECT (basesink, "we are EOS"); + GST_DEBUG_OBJECT (basesink, + "we are EOS, dropping object, return UNEXPECTED"); gst_mini_object_unref (obj); return GST_FLOW_UNEXPECTED; } @@ -1976,10 +1977,11 @@ gst_base_sink_event (GstPad * pad, GstEvent * event) GST_DEBUG_OBJECT (basesink, "newsegment %p", event); - if (G_UNLIKELY (basesink->priv->received_eos)) + if (G_UNLIKELY (basesink->priv->received_eos)) { /* we can't accept anything when we are EOS */ result = FALSE; - else { + gst_event_unref (event); + } else { /* the new segment is a non prerollable item and does not block anything, * we need to configure the current clipping segment and insert the event * in the queue to serialize it with the buffers for rendering. */ diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c index 280efd0..e38b72a 100644 --- a/plugins/elements/gstfakesink.c +++ b/plugins/elements/gstfakesink.c @@ -69,6 +69,7 @@ enum #define DEFAULT_LAST_MESSAGE NULL #define DEFAULT_CAN_ACTIVATE_PUSH TRUE #define DEFAULT_CAN_ACTIVATE_PULL FALSE +#define DEFAULT_NUM_BUFFERS -1 enum { @@ -79,7 +80,8 @@ enum PROP_SIGNAL_HANDOFFS, PROP_LAST_MESSAGE, PROP_CAN_ACTIVATE_PUSH, - PROP_CAN_ACTIVATE_PULL + PROP_CAN_ACTIVATE_PULL, + PROP_NUM_BUFFERS }; #define GST_TYPE_FAKE_SINK_STATE_ERROR (gst_fake_sink_state_error_get_type()) @@ -186,6 +188,10 @@ gst_fake_sink_class_init (GstFakeSinkClass * klass) g_param_spec_boolean ("can-activate-pull", "Can activate pull", "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_NUM_BUFFERS, + g_param_spec_int ("num-buffers", "num-buffers", + "Number of buffers to accept going EOS", -1, G_MAXINT, + DEFAULT_NUM_BUFFERS, G_PARAM_READWRITE)); /** * GstFakeSink::handoff: @@ -234,6 +240,7 @@ gst_fake_sink_init (GstFakeSink * fakesink, GstFakeSinkClass * g_class) fakesink->last_message = g_strdup (DEFAULT_LAST_MESSAGE); fakesink->state_error = DEFAULT_STATE_ERROR; fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS; + fakesink->num_buffers = DEFAULT_NUM_BUFFERS; } static void @@ -263,6 +270,9 @@ gst_fake_sink_set_property (GObject * object, guint prop_id, case PROP_CAN_ACTIVATE_PULL: GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value); break; + case PROP_NUM_BUFFERS: + sink->num_buffers = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -301,6 +311,9 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value, case PROP_CAN_ACTIVATE_PULL: g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull); break; + case PROP_NUM_BUFFERS: + g_value_set_int (value, sink->num_buffers); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -341,6 +354,9 @@ gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer) { GstFakeSink *sink = GST_FAKE_SINK (bsink); + if (sink->num_buffers_left == 0) + goto eos; + if (!sink->silent) { GST_OBJECT_LOCK (sink); g_free (sink->last_message); @@ -356,6 +372,13 @@ gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer) bsink->sinkpad); } return GST_FLOW_OK; + + /* ERRORS */ +eos: + { + GST_DEBUG_OBJECT (sink, "we are EOS"); + return GST_FLOW_UNEXPECTED; + } } static GstFlowReturn @@ -363,6 +386,12 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) { GstFakeSink *sink = GST_FAKE_SINK_CAST (bsink); + if (sink->num_buffers_left == 0) + goto eos; + + if (sink->num_buffers_left != -1) + sink->num_buffers_left--; + if (!sink->silent) { gchar ts_str[64], dur_str[64]; @@ -400,8 +429,17 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf) if (sink->dump) { gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); } + if (sink->num_buffers_left == 0) + goto eos; return GST_FLOW_OK; + + /* ERRORS */ +eos: + { + GST_DEBUG_OBJECT (sink, "we are EOS"); + return GST_FLOW_UNEXPECTED; + } } static GstStateChangeReturn @@ -418,6 +456,7 @@ gst_fake_sink_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_PAUSED) goto error; + fakesink->num_buffers_left = fakesink->num_buffers; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_PLAYING) diff --git a/plugins/elements/gstfakesink.h b/plugins/elements/gstfakesink.h index 2796492..2db98b9 100644 --- a/plugins/elements/gstfakesink.h +++ b/plugins/elements/gstfakesink.h @@ -80,6 +80,8 @@ struct _GstFakeSink { gboolean signal_handoffs; GstFakeSinkStateError state_error; gchar *last_message; + gint num_buffers; + gint num_buffers_left; }; struct _GstFakeSinkClass { diff --git a/tests/check/elements/fakesink.c b/tests/check/elements/fakesink.c index 3e012ae..0c1b299 100644 --- a/tests/check/elements/fakesink.c +++ b/tests/check/elements/fakesink.c @@ -351,6 +351,7 @@ GST_START_TEST (test_eos) if (type == GST_MESSAGE_EOS) break; } + gst_object_unref (bus); /* send another EOS, this should fail */ { @@ -445,6 +446,83 @@ GST_START_TEST (test_eos) GST_END_TEST; +/* test EOS triggered by the element */ +GST_START_TEST (test_eos2) +{ + GstElement *pipeline, *sink; + GstPad *sinkpad; + GstStateChangeReturn ret; + + /* create sink */ + pipeline = gst_pipeline_new ("pipeline"); + fail_if (pipeline == NULL); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_if (sink == NULL); + g_object_set (G_OBJECT (sink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (sink), "num-buffers", 1, NULL); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_pad (sink, "sink"); + fail_if (sinkpad == NULL); + + /* make pipeline and element ready to accept data */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_ASYNC); + + /* send segment, this should work */ + { + GstEvent *segment; + gboolean eret; + + GST_DEBUG ("sending segment"); + segment = gst_event_new_new_segment (FALSE, + 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, 2 * GST_SECOND, 0 * GST_SECOND); + + eret = gst_pad_send_event (sinkpad, segment); + fail_if (eret == FALSE); + } + + /* send buffer that should return UNEXPECTED */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + /* this buffer will generate UNEXPECTED */ + fret = gst_pad_chain (sinkpad, buffer); + fail_unless (fret == GST_FLOW_UNEXPECTED); + } + + /* send buffer that should return UNEXPECTED */ + { + GstBuffer *buffer; + GstFlowReturn fret; + + buffer = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 1 * GST_SECOND; + + GST_DEBUG ("sending buffer"); + + fret = gst_pad_chain (sinkpad, buffer); + fail_unless (fret == GST_FLOW_UNEXPECTED); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (sinkpad); + gst_object_unref (pipeline); +} + +GST_END_TEST; + Suite * fakesink_suite (void) { @@ -455,6 +533,7 @@ fakesink_suite (void) tcase_add_test (tc_chain, test_clipping); tcase_add_test (tc_chain, test_preroll_sync); tcase_add_test (tc_chain, test_eos); + tcase_add_test (tc_chain, test_eos2); return s; }