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
This commit is contained in:
Tim-Philipp Müller 2012-12-17 20:28:12 +00:00
parent 4f49c7a33b
commit 68f366a8d3

View file

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