mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
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:
parent
cc82861367
commit
12c9334667
5 changed files with 146 additions and 4 deletions
20
ChangeLog
20
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -80,6 +80,8 @@ struct _GstFakeSink {
|
|||
gboolean signal_handoffs;
|
||||
GstFakeSinkStateError state_error;
|
||||
gchar *last_message;
|
||||
gint num_buffers;
|
||||
gint num_buffers_left;
|
||||
};
|
||||
|
||||
struct _GstFakeSinkClass {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue