From 7ff608889afc46b326a8d1d4fea1813a6fafab0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 9 Mar 2012 10:54:48 +0100 Subject: [PATCH] audio{en,de}coder: Add optional open/close vfuncs This can be used to do something in NULL->READY, like checking if a hardware codec is actually available and to error out early. --- gst-libs/gst/audio/gstaudiodecoder.c | 20 +++++++++++ gst-libs/gst/audio/gstaudiodecoder.h | 12 ++++++- gst-libs/gst/audio/gstaudioencoder.c | 51 ++++++++++++++++++++++++++++ gst-libs/gst/audio/gstaudioencoder.h | 12 ++++++- 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c index 0198d849d8..5dfd278e1d 100644 --- a/gst-libs/gst/audio/gstaudiodecoder.c +++ b/gst-libs/gst/audio/gstaudiodecoder.c @@ -2070,12 +2070,18 @@ static GstStateChangeReturn gst_audio_decoder_change_state (GstElement * element, GstStateChange transition) { GstAudioDecoder *codec; + GstAudioDecoderClass *klass; GstStateChangeReturn ret; codec = GST_AUDIO_DECODER (element); + klass = GST_AUDIO_DECODER_GET_CLASS (codec); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: + if (klass->open) { + if (!klass->open (codec)) + goto open_failed; + } break; case GST_STATE_CHANGE_READY_TO_PAUSED: if (!gst_audio_decoder_start (codec)) { @@ -2099,6 +2105,10 @@ gst_audio_decoder_change_state (GstElement * element, GstStateChange transition) } break; case GST_STATE_CHANGE_READY_TO_NULL: + if (klass->close) { + if (!klass->close (codec)) + goto close_failed; + } break; default: break; @@ -2116,6 +2126,16 @@ stop_failed: GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to stop codec")); return GST_STATE_CHANGE_FAILURE; } +open_failed: + { + GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to open codec")); + return GST_STATE_CHANGE_FAILURE; + } +close_failed: + { + GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to close codec")); + return GST_STATE_CHANGE_FAILURE; + } } GstFlowReturn diff --git a/gst-libs/gst/audio/gstaudiodecoder.h b/gst-libs/gst/audio/gstaudiodecoder.h index bd6cb8988c..bf1c44e96e 100644 --- a/gst-libs/gst/audio/gstaudiodecoder.h +++ b/gst-libs/gst/audio/gstaudiodecoder.h @@ -201,6 +201,12 @@ struct _GstAudioDecoder * Called just prior to pushing (encoded data) buffer downstream. * Subclass has full discretionary access to buffer, * and a not OK flow return will abort downstream pushing. + * @open: Optional. + * Called when the element changes to GST_STATE_READY. + * Allows opening external resources. Since: 0.10.37. + * @close: Optional. + * Called when the element changes to GST_STATE_NULL. + * Allows closing external resources. Since: 0.10.37. * * Subclasses can override any of the available virtual methods or not, as * needed. At minimum @handle_frame (and likely @set_format) needs to be @@ -237,8 +243,12 @@ struct _GstAudioDecoderClass gboolean (*event) (GstAudioDecoder *dec, GstEvent *event); + gboolean (*open) (GstAudioDecoder *dec); + + gboolean (*close) (GstAudioDecoder *dec); + /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; + gpointer _gst_reserved[GST_PADDING_LARGE-2]; }; GType gst_audio_decoder_get_type (void); diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index b915ae7f0b..ea2595eefd 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -301,6 +301,9 @@ static void gst_audio_encoder_set_property (GObject * object, static void gst_audio_encoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static GstStateChangeReturn gst_audio_encoder_change_state (GstElement * + element, GstStateChange transition); + static gboolean gst_audio_encoder_sink_activate_push (GstPad * pad, gboolean active); @@ -317,8 +320,10 @@ static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass) { GObjectClass *gobject_class; + GstElementClass *gstelement_class; gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0, @@ -349,6 +354,9 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) "Consider discontinuity if timestamp jitter/imperfection exceeds tolerance (ns)", 0, G_MAXINT64, DEFAULT_TOLERANCE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_audio_encoder_change_state); } static void @@ -460,6 +468,49 @@ gst_audio_encoder_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static GstStateChangeReturn +gst_audio_encoder_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstAudioEncoder *enc = GST_AUDIO_ENCODER (element); + GstAudioEncoderClass *klass = GST_AUDIO_ENCODER_GET_CLASS (enc); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (klass->open) { + if (!klass->open (enc)) + goto open_failed; + } + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + if (klass->close) { + if (!klass->close (enc)) + goto close_failed; + } + default: + break; + } + + return ret; + +open_failed: + { + GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL), ("Failed to open codec")); + return GST_STATE_CHANGE_FAILURE; + } +close_failed: + { + GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL), ("Failed to close codec")); + return GST_STATE_CHANGE_FAILURE; + } +} + /** * gst_audio_encoder_finish_frame: * @enc: a #GstAudioEncoder diff --git a/gst-libs/gst/audio/gstaudioencoder.h b/gst-libs/gst/audio/gstaudioencoder.h index aa40677222..2db19ab197 100644 --- a/gst-libs/gst/audio/gstaudioencoder.h +++ b/gst-libs/gst/audio/gstaudioencoder.h @@ -151,6 +151,12 @@ struct _GstAudioEncoder { * for multichannel input specification). If not implemented, * default returns gst_audio_encoder_proxy_getcaps * applied to sink template caps. + * @open: Optional. + * Called when the element changes to GST_STATE_READY. + * Allows opening external resources. Since: 0.10.37. + * @close: Optional. + * Called when the element changes to GST_STATE_NULL. + * Allows closing external resources. Since: 0.10.37. * * Subclasses can override any of the available virtual methods or not, as * needed. At minimum @set_format and @handle_frame needs to be overridden. @@ -183,8 +189,12 @@ struct _GstAudioEncoderClass { GstCaps * (*getcaps) (GstAudioEncoder *enc); + gboolean (*open) (GstAudioEncoder *enc); + + gboolean (*close) (GstAudioEncoder *enc); + /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; + gpointer _gst_reserved[GST_PADDING_LARGE-2]; }; GType gst_audio_encoder_get_type (void);