From 68f366a8d37e5fb71106869b41911a749382143c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 17 Dec 2012 20:28:12 +0000 Subject: [PATCH] audiobasesrc: bail out if subclass posts an error Use new ringbuffer ERROR state to make all the various threads bail out correctly when the subclass posts an error. It's a bit iffy to communicate this properly between the different bits of code. https://bugzilla.gnome.org/show_bug.cgi?id=690197 --- gst-libs/gst/audio/gstaudiobasesrc.c | 42 +++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/audio/gstaudiobasesrc.c b/gst-libs/gst/audio/gstaudiobasesrc.c index 99d5827670..820e0f9c0f 100644 --- a/gst-libs/gst/audio/gstaudiobasesrc.c +++ b/gst-libs/gst/audio/gstaudiobasesrc.c @@ -130,7 +130,8 @@ static void gst_audio_base_src_dispose (GObject * object); static GstStateChangeReturn gst_audio_base_src_change_state (GstElement * element, GstStateChange transition); - +static gboolean gst_audio_base_src_post_message (GstElement * element, + GstMessage * message); static GstClock *gst_audio_base_src_provide_clock (GstElement * elem); static GstClockTime gst_audio_base_src_get_time (GstClock * clock, GstAudioBaseSrc * src); @@ -215,6 +216,8 @@ gst_audio_base_src_class_init (GstAudioBaseSrcClass * klass) GST_DEBUG_FUNCPTR (gst_audio_base_src_change_state); gstelement_class->provide_clock = GST_DEBUG_FUNCPTR (gst_audio_base_src_provide_clock); + gstelement_class->post_message = + GST_DEBUG_FUNCPTR (gst_audio_base_src_post_message); gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_base_src_setcaps); gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_audio_base_src_event); @@ -825,6 +828,10 @@ gst_audio_base_src_create (GstBaseSrc * bsrc, guint64 offset, guint length, if (read == samples) break; + if (g_atomic_int_get (&ringbuffer->state) == + GST_AUDIO_RING_BUFFER_STATE_ERROR) + goto got_error; + /* else something interrupted us and we wait for playing again. */ GST_DEBUG_OBJECT (src, "wait playing"); if (gst_base_src_wait_playing (bsrc) != GST_FLOW_OK) @@ -1063,6 +1070,12 @@ stopped: GST_DEBUG_OBJECT (src, "ringbuffer stopped"); return GST_FLOW_FLUSHING; } +got_error: + { + gst_buffer_unref (buf); + GST_DEBUG_OBJECT (src, "ringbuffer was in error state, bailing out"); + return GST_FLOW_ERROR; + } } /** @@ -1180,3 +1193,30 @@ open_failed: } } + +static gboolean +gst_audio_base_src_post_message (GstElement * element, GstMessage * message) +{ + GstAudioBaseSrc *src = GST_AUDIO_BASE_SRC (element); + gboolean ret; + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) { + GstAudioRingBuffer *ringbuffer; + + GST_INFO_OBJECT (element, "subclass posted error"); + + ringbuffer = gst_object_ref (src->ringbuffer); + + /* post message first before signalling the error to the ringbuffer, to + * make sure it ends up on the bus before the generic basesrc internal + * flow error message */ + ret = GST_ELEMENT_CLASS (parent_class)->post_message (element, message); + + g_atomic_int_set (&ringbuffer->state, GST_AUDIO_RING_BUFFER_STATE_ERROR); + GST_AUDIO_RING_BUFFER_SIGNAL (ringbuffer); + gst_object_unref (ringbuffer); + } else { + ret = GST_ELEMENT_CLASS (parent_class)->post_message (element, message); + } + return ret; +}