mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
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:
parent
b2a162ca77
commit
7ff608889a
4 changed files with 93 additions and 2 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue