summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--libs/gst/base/gstbasesink.c8
-rw-r--r--plugins/elements/gstfakesink.c41
-rw-r--r--plugins/elements/gstfakesink.h2
-rw-r--r--tests/check/elements/fakesink.c79
5 files changed, 146 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index eefd3ad7a..dc492f2fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,26 @@
2007-04-05 Wim Taymans <wim@fluendo.com>
* 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 <wim@fluendo.com>
+
+ * 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 97033264b..34e935712 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 280efd004..e38b72a88 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 279649265..2db98b958 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 3e012ae6f..0c1b29961 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;
}