mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +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>
|
2007-04-05 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* libs/gst/base/gstbasesink.c:
|
* libs/gst/base/gstbasesink.c:
|
||||||
|
|
|
@ -1879,7 +1879,8 @@ gst_base_sink_queue_object_unlocked (GstBaseSink * basesink, GstPad * pad,
|
||||||
/* special cases */
|
/* special cases */
|
||||||
was_eos:
|
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);
|
gst_mini_object_unref (obj);
|
||||||
return GST_FLOW_UNEXPECTED;
|
return GST_FLOW_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
@ -1976,10 +1977,11 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (basesink, "newsegment %p", 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 */
|
/* we can't accept anything when we are EOS */
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
else {
|
gst_event_unref (event);
|
||||||
|
} else {
|
||||||
/* the new segment is a non prerollable item and does not block anything,
|
/* 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
|
* we need to configure the current clipping segment and insert the event
|
||||||
* in the queue to serialize it with the buffers for rendering. */
|
* in the queue to serialize it with the buffers for rendering. */
|
||||||
|
|
|
@ -69,6 +69,7 @@ enum
|
||||||
#define DEFAULT_LAST_MESSAGE NULL
|
#define DEFAULT_LAST_MESSAGE NULL
|
||||||
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
#define DEFAULT_CAN_ACTIVATE_PUSH TRUE
|
||||||
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
|
#define DEFAULT_CAN_ACTIVATE_PULL FALSE
|
||||||
|
#define DEFAULT_NUM_BUFFERS -1
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -79,7 +80,8 @@ enum
|
||||||
PROP_SIGNAL_HANDOFFS,
|
PROP_SIGNAL_HANDOFFS,
|
||||||
PROP_LAST_MESSAGE,
|
PROP_LAST_MESSAGE,
|
||||||
PROP_CAN_ACTIVATE_PUSH,
|
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())
|
#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",
|
g_param_spec_boolean ("can-activate-pull", "Can activate pull",
|
||||||
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
|
"Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL,
|
||||||
G_PARAM_READWRITE));
|
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:
|
* GstFakeSink::handoff:
|
||||||
|
@ -234,6 +240,7 @@ gst_fake_sink_init (GstFakeSink * fakesink, GstFakeSinkClass * g_class)
|
||||||
fakesink->last_message = g_strdup (DEFAULT_LAST_MESSAGE);
|
fakesink->last_message = g_strdup (DEFAULT_LAST_MESSAGE);
|
||||||
fakesink->state_error = DEFAULT_STATE_ERROR;
|
fakesink->state_error = DEFAULT_STATE_ERROR;
|
||||||
fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
|
fakesink->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
|
||||||
|
fakesink->num_buffers = DEFAULT_NUM_BUFFERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -263,6 +270,9 @@ gst_fake_sink_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_CAN_ACTIVATE_PULL:
|
case PROP_CAN_ACTIVATE_PULL:
|
||||||
GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
|
GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_NUM_BUFFERS:
|
||||||
|
sink->num_buffers = g_value_get_int (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -301,6 +311,9 @@ gst_fake_sink_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_CAN_ACTIVATE_PULL:
|
case PROP_CAN_ACTIVATE_PULL:
|
||||||
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
|
g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull);
|
||||||
break;
|
break;
|
||||||
|
case PROP_NUM_BUFFERS:
|
||||||
|
g_value_set_int (value, sink->num_buffers);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -341,6 +354,9 @@ gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstFakeSink *sink = GST_FAKE_SINK (bsink);
|
GstFakeSink *sink = GST_FAKE_SINK (bsink);
|
||||||
|
|
||||||
|
if (sink->num_buffers_left == 0)
|
||||||
|
goto eos;
|
||||||
|
|
||||||
if (!sink->silent) {
|
if (!sink->silent) {
|
||||||
GST_OBJECT_LOCK (sink);
|
GST_OBJECT_LOCK (sink);
|
||||||
g_free (sink->last_message);
|
g_free (sink->last_message);
|
||||||
|
@ -356,6 +372,13 @@ gst_fake_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
bsink->sinkpad);
|
bsink->sinkpad);
|
||||||
}
|
}
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
eos:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (sink, "we are EOS");
|
||||||
|
return GST_FLOW_UNEXPECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
|
@ -363,6 +386,12 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstFakeSink *sink = GST_FAKE_SINK_CAST (bsink);
|
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) {
|
if (!sink->silent) {
|
||||||
gchar ts_str[64], dur_str[64];
|
gchar ts_str[64], dur_str[64];
|
||||||
|
|
||||||
|
@ -400,8 +429,17 @@ gst_fake_sink_render (GstBaseSink * bsink, GstBuffer * buf)
|
||||||
if (sink->dump) {
|
if (sink->dump) {
|
||||||
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||||
}
|
}
|
||||||
|
if (sink->num_buffers_left == 0)
|
||||||
|
goto eos;
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
eos:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (sink, "we are EOS");
|
||||||
|
return GST_FLOW_UNEXPECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -418,6 +456,7 @@ gst_fake_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_PAUSED)
|
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_READY_PAUSED)
|
||||||
goto error;
|
goto error;
|
||||||
|
fakesink->num_buffers_left = fakesink->num_buffers;
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_PLAYING)
|
if (fakesink->state_error == FAKE_SINK_STATE_ERROR_PAUSED_PLAYING)
|
||||||
|
|
|
@ -80,6 +80,8 @@ struct _GstFakeSink {
|
||||||
gboolean signal_handoffs;
|
gboolean signal_handoffs;
|
||||||
GstFakeSinkStateError state_error;
|
GstFakeSinkStateError state_error;
|
||||||
gchar *last_message;
|
gchar *last_message;
|
||||||
|
gint num_buffers;
|
||||||
|
gint num_buffers_left;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstFakeSinkClass {
|
struct _GstFakeSinkClass {
|
||||||
|
|
|
@ -351,6 +351,7 @@ GST_START_TEST (test_eos)
|
||||||
if (type == GST_MESSAGE_EOS)
|
if (type == GST_MESSAGE_EOS)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gst_object_unref (bus);
|
||||||
|
|
||||||
/* send another EOS, this should fail */
|
/* send another EOS, this should fail */
|
||||||
{
|
{
|
||||||
|
@ -445,6 +446,83 @@ GST_START_TEST (test_eos)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 *
|
Suite *
|
||||||
fakesink_suite (void)
|
fakesink_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -455,6 +533,7 @@ fakesink_suite (void)
|
||||||
tcase_add_test (tc_chain, test_clipping);
|
tcase_add_test (tc_chain, test_clipping);
|
||||||
tcase_add_test (tc_chain, test_preroll_sync);
|
tcase_add_test (tc_chain, test_preroll_sync);
|
||||||
tcase_add_test (tc_chain, test_eos);
|
tcase_add_test (tc_chain, test_eos);
|
||||||
|
tcase_add_test (tc_chain, test_eos2);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue