summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-02-16 12:19:20 +0100
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-02-16 12:35:53 +0100
commit439884d628fa80e710698e9bb36f063c503b9e79 (patch)
tree8e6660214f4acba923dc5af14f1c970c7a1a9349
parent5b4dc0252323a5f77470531a814d0d2cceac0056 (diff)
audiodecoder: add some properties to tweak baseclass behaviour
... so subclass can also rely upon never being bothered with some NULL buffer it can't do any interesting with, or with any data before it received any format configuration (and setup properly).
-rw-r--r--gst-libs/gst/audio/gstaudiodecoder.c124
-rw-r--r--gst-libs/gst/audio/gstaudiodecoder.h10
2 files changed, 134 insertions, 0 deletions
diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c
index 1a812788f..705197cc6 100644
--- a/gst-libs/gst/audio/gstaudiodecoder.c
+++ b/gst-libs/gst/audio/gstaudiodecoder.c
@@ -178,12 +178,14 @@ enum
PROP_PLC
};
#define DEFAULT_LATENCY 0
#define DEFAULT_TOLERANCE 0
#define DEFAULT_PLC FALSE
+#define DEFAULT_DRAINABLE TRUE
+#define DEFAULT_NEEDS_FORMAT FALSE
typedef struct _GstAudioDecoderContext
{
/* input */
/* (output) audio format */
GstAudioInfo info;
@@ -259,12 +261,14 @@ struct _GstAudioDecoderPrivate
GstAudioDecoderContext ctx;
/* properties */
GstClockTime latency;
GstClockTime tolerance;
gboolean plc;
+ gboolean drainable;
+ gboolean needs_format;
/* pending serialized sink events, will be sent from finish_frame() */
GList *pending_events;
};
@@ -392,12 +396,14 @@ gst_audio_decoder_init (GstAudioDecoder * dec, GstAudioDecoderClass * klass)
g_static_rec_mutex_init (&dec->stream_lock);
/* property default */
dec->priv->latency = DEFAULT_LATENCY;
dec->priv->tolerance = DEFAULT_TOLERANCE;
dec->priv->plc = DEFAULT_PLC;
+ dec->priv->drainable = DEFAULT_DRAINABLE;
+ dec->priv->needs_format = DEFAULT_NEEDS_FORMAT;
/* init state */
gst_audio_decoder_reset (dec, TRUE);
GST_DEBUG_OBJECT (dec, "init ok");
}
@@ -1021,12 +1027,16 @@ gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
buffer = gst_buffer_make_metadata_writable (buffer);
GST_BUFFER_TIMESTAMP (buffer) = ts;
flush += len;
} else {
if (!force)
break;
+ if (!priv->drainable) {
+ priv->drained = TRUE;
+ break;
+ }
buffer = NULL;
}
ret = gst_audio_decoder_handle_frame (dec, klass, buffer);
/* do not keep pushing it ... */
@@ -1341,12 +1351,15 @@ gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer)
{
GstAudioDecoder *dec;
GstFlowReturn ret;
dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
+ if (G_UNLIKELY (!GST_PAD_CAPS (pad) && dec->priv->needs_format))
+ goto not_negotiated;
+
GST_LOG_OBJECT (dec,
"received buffer of size %d with ts %" GST_TIME_FORMAT
", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
@@ -1378,12 +1391,21 @@ gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer)
else
ret = gst_audio_decoder_chain_reverse (dec, buffer);
GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
return ret;
+
+ /* ERRORS */
+not_negotiated:
+ {
+ GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL),
+ ("decoder not initialized"));
+ gst_buffer_unref (buffer);
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
/* perform upstream byte <-> time conversion (duration, seeking)
* if subclass allows and if enough data for moderately decent conversion */
static inline gboolean
gst_audio_decoder_do_byte (GstAudioDecoder * dec)
@@ -2458,6 +2480,108 @@ gst_audio_decoder_get_tolerance (GstAudioDecoder * dec)
GST_OBJECT_LOCK (dec);
result = dec->priv->tolerance;
GST_OBJECT_UNLOCK (dec);
return result;
}
+
+/**
+ * gst_audio_decoder_set_drainable:
+ * @enc: a #GstAudioDecoder
+ * @enabled: new state
+ *
+ * Configures decoder drain handling. If drainable, subclass might
+ * be handed a NULL buffer to have it return any leftover decoded data.
+ * Otherwise, it is not considered so capable and will only ever be passed
+ * real data.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.36
+ */
+void
+gst_audio_decoder_set_drainable (GstAudioDecoder * dec, gboolean enabled)
+{
+ g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
+
+ GST_OBJECT_LOCK (dec);
+ dec->priv->drainable = enabled;
+ GST_OBJECT_UNLOCK (dec);
+}
+
+/**
+ * gst_audio_decoder_get_drainable:
+ * @enc: a #GstAudioDecoder
+ *
+ * Queries decoder drain handling.
+ *
+ * Returns: TRUE if drainable handling is enabled.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.36
+ */
+gboolean
+gst_audio_decoder_get_drainable (GstAudioDecoder * dec)
+{
+ gboolean result;
+
+ g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
+
+ GST_OBJECT_LOCK (dec);
+ result = dec->priv->drainable;
+ GST_OBJECT_UNLOCK (dec);
+
+ return result;
+}
+
+/**
+ * gst_audio_decoder_set_needs_format:
+ * @enc: a #GstAudioDecoder
+ * @enabled: new state
+ *
+ * Configures decoder format needs. If enabled, subclass needs to be
+ * negotiated with format caps before it can process any data. It will then
+ * never be handed any data before it has been configured.
+ * Otherwise, it might be handed data without having been configured and
+ * is then expected being able to do so either by default
+ * or based on the input data.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.36
+ */
+void
+gst_audio_decoder_set_needs_format (GstAudioDecoder * dec, gboolean enabled)
+{
+ g_return_if_fail (GST_IS_AUDIO_DECODER (dec));
+
+ GST_OBJECT_LOCK (dec);
+ dec->priv->needs_format = enabled;
+ GST_OBJECT_UNLOCK (dec);
+}
+
+/**
+ * gst_audio_decoder_get_needs_format:
+ * @enc: a #GstAudioDecoder
+ *
+ * Queries decoder required format handling.
+ *
+ * Returns: TRUE if required format handling is enabled.
+ *
+ * MT safe.
+ *
+ * Since: 0.10.36
+ */
+gboolean
+gst_audio_decoder_get_needs_format (GstAudioDecoder * dec)
+{
+ gboolean result;
+
+ g_return_val_if_fail (GST_IS_AUDIO_DECODER (dec), 0);
+
+ GST_OBJECT_LOCK (dec);
+ result = dec->priv->needs_format;
+ GST_OBJECT_UNLOCK (dec);
+
+ return result;
+}
diff --git a/gst-libs/gst/audio/gstaudiodecoder.h b/gst-libs/gst/audio/gstaudiodecoder.h
index a6ae61803..ba4fff348 100644
--- a/gst-libs/gst/audio/gstaudiodecoder.h
+++ b/gst-libs/gst/audio/gstaudiodecoder.h
@@ -290,9 +290,19 @@ gint64 gst_audio_decoder_get_min_latency (GstAudioDecoder * dec);
void gst_audio_decoder_set_tolerance (GstAudioDecoder * dec,
gint64 tolerance);
gint64 gst_audio_decoder_get_tolerance (GstAudioDecoder * dec);
+void gst_audio_decoder_set_drainable (GstAudioDecoder * dec,
+ gboolean enabled);
+
+gboolean gst_audio_decoder_get_drainable (GstAudioDecoder * dec);
+
+void gst_audio_decoder_set_needs_format (GstAudioDecoder * dec,
+ gboolean enabled);
+
+gboolean gst_audio_decoder_get_needs_format (GstAudioDecoder * dec);
+
G_END_DECLS
#endif /* _GST_AUDIO_DECODER_H_ */