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.
This commit is contained in:
Sebastian Dröge 2012-03-09 10:54:48 +01:00
parent b2a162ca77
commit 7ff608889a
4 changed files with 93 additions and 2 deletions

View file

@ -2070,12 +2070,18 @@ static GstStateChangeReturn
gst_audio_decoder_change_state (GstElement * element, GstStateChange transition) gst_audio_decoder_change_state (GstElement * element, GstStateChange transition)
{ {
GstAudioDecoder *codec; GstAudioDecoder *codec;
GstAudioDecoderClass *klass;
GstStateChangeReturn ret; GstStateChangeReturn ret;
codec = GST_AUDIO_DECODER (element); codec = GST_AUDIO_DECODER (element);
klass = GST_AUDIO_DECODER_GET_CLASS (codec);
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY: case GST_STATE_CHANGE_NULL_TO_READY:
if (klass->open) {
if (!klass->open (codec))
goto open_failed;
}
break; break;
case GST_STATE_CHANGE_READY_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_PAUSED:
if (!gst_audio_decoder_start (codec)) { if (!gst_audio_decoder_start (codec)) {
@ -2099,6 +2105,10 @@ gst_audio_decoder_change_state (GstElement * element, GstStateChange transition)
} }
break; break;
case GST_STATE_CHANGE_READY_TO_NULL: case GST_STATE_CHANGE_READY_TO_NULL:
if (klass->close) {
if (!klass->close (codec))
goto close_failed;
}
break; break;
default: default:
break; break;
@ -2116,6 +2126,16 @@ stop_failed:
GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to stop codec")); GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to stop codec"));
return GST_STATE_CHANGE_FAILURE; 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 GstFlowReturn

View file

@ -201,6 +201,12 @@ struct _GstAudioDecoder
* Called just prior to pushing (encoded data) buffer downstream. * Called just prior to pushing (encoded data) buffer downstream.
* Subclass has full discretionary access to buffer, * Subclass has full discretionary access to buffer,
* and a not OK flow return will abort downstream pushing. * 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 * Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @handle_frame (and likely @set_format) needs to be * needed. At minimum @handle_frame (and likely @set_format) needs to be
@ -237,8 +243,12 @@ struct _GstAudioDecoderClass
gboolean (*event) (GstAudioDecoder *dec, gboolean (*event) (GstAudioDecoder *dec,
GstEvent *event); GstEvent *event);
gboolean (*open) (GstAudioDecoder *dec);
gboolean (*close) (GstAudioDecoder *dec);
/*< private >*/ /*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE]; gpointer _gst_reserved[GST_PADDING_LARGE-2];
}; };
GType gst_audio_decoder_get_type (void); GType gst_audio_decoder_get_type (void);

View file

@ -301,6 +301,9 @@ static void gst_audio_encoder_set_property (GObject * object,
static void gst_audio_encoder_get_property (GObject * object, static void gst_audio_encoder_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec); 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, static gboolean gst_audio_encoder_sink_activate_push (GstPad * pad,
gboolean active); gboolean active);
@ -317,8 +320,10 @@ static void
gst_audio_encoder_class_init (GstAudioEncoderClass * klass) gst_audio_encoder_class_init (GstAudioEncoderClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = G_OBJECT_CLASS (klass); gobject_class = G_OBJECT_CLASS (klass);
gstelement_class = GST_ELEMENT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass); parent_class = g_type_class_peek_parent (klass);
GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0, 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)", "Consider discontinuity if timestamp jitter/imperfection exceeds tolerance (ns)",
0, G_MAXINT64, DEFAULT_TOLERANCE, 0, G_MAXINT64, DEFAULT_TOLERANCE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_audio_encoder_change_state);
} }
static void static void
@ -460,6 +468,49 @@ gst_audio_encoder_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (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: * gst_audio_encoder_finish_frame:
* @enc: a #GstAudioEncoder * @enc: a #GstAudioEncoder

View file

@ -151,6 +151,12 @@ struct _GstAudioEncoder {
* for multichannel input specification). If not implemented, * for multichannel input specification). If not implemented,
* default returns gst_audio_encoder_proxy_getcaps * default returns gst_audio_encoder_proxy_getcaps
* applied to sink template caps. * 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 * Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @set_format and @handle_frame needs to be overridden. * needed. At minimum @set_format and @handle_frame needs to be overridden.
@ -183,8 +189,12 @@ struct _GstAudioEncoderClass {
GstCaps * (*getcaps) (GstAudioEncoder *enc); GstCaps * (*getcaps) (GstAudioEncoder *enc);
gboolean (*open) (GstAudioEncoder *enc);
gboolean (*close) (GstAudioEncoder *enc);
/*< private >*/ /*< private >*/
gpointer _gst_reserved[GST_PADDING_LARGE]; gpointer _gst_reserved[GST_PADDING_LARGE-2];
}; };
GType gst_audio_encoder_get_type (void); GType gst_audio_encoder_get_type (void);