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.
This commit is contained in:
Wim Taymans 2007-04-05 11:16:09 +00:00
parent cc82861367
commit 12c9334667
5 changed files with 146 additions and 4 deletions

View file

@ -1,3 +1,23 @@
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:

View file

@ -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. */

View file

@ -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)

View file

@ -80,6 +80,8 @@ struct _GstFakeSink {
gboolean signal_handoffs;
GstFakeSinkStateError state_error;
gchar *last_message;
gint num_buffers;
gint num_buffers_left;
};
struct _GstFakeSinkClass {

View file

@ -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;
}