From 5b4dc0252323a5f77470531a814d0d2cceac0056 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 16 Feb 2012 12:18:03 +0100 Subject: [PATCH] audioencoder: add some properties to tweak baseclass behaviour ... so subclass can also rely upon never being bothered with less data than it desires or with some NULL buffer it can't do any interesting with. --- gst-libs/gst/audio/gstaudioencoder.c | 123 ++++++++++++++++++++++++++++++++++- gst-libs/gst/audio/gstaudioencoder.h | 10 +++ 2 files changed, 130 insertions(+), 3 deletions(-) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index d64bd22..b915ae7 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -184,6 +184,8 @@ enum #define DEFAULT_GRANULE FALSE #define DEFAULT_HARD_RESYNC FALSE #define DEFAULT_TOLERANCE 40000000 +#define DEFAULT_HARD_MIN FALSE +#define DEFAULT_DRAINABLE TRUE typedef struct _GstAudioEncoderContext { @@ -243,6 +245,8 @@ struct _GstAudioEncoderPrivate gboolean perfect_ts; gboolean hard_resync; gboolean granule; + gboolean hard_min; + gboolean drainable; /* pending tags */ GstTagList *tags; @@ -399,6 +403,8 @@ gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) enc->priv->perfect_ts = DEFAULT_PERFECT_TS; enc->priv->hard_resync = DEFAULT_HARD_RESYNC; enc->priv->tolerance = DEFAULT_TOLERANCE; + enc->priv->hard_min = DEFAULT_HARD_MIN; + enc->priv->drainable = DEFAULT_DRAINABLE; /* init state */ gst_audio_encoder_reset (enc, TRUE); @@ -755,11 +761,15 @@ gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force) } } - if (need) { + priv->got_data = FALSE; + if (G_LIKELY (need)) { buf = gst_buffer_new (); GST_BUFFER_DATA (buf) = (guint8 *) gst_adapter_peek (priv->adapter, priv->offset + need) + priv->offset; GST_BUFFER_SIZE (buf) = need; + } else if (!priv->drainable) { + GST_DEBUG_OBJECT (enc, "non-drainable and no more data"); + goto finish; } GST_LOG_OBJECT (enc, "providing subclass with %d bytes at offset %d", @@ -770,12 +780,19 @@ gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force) priv->offset += need; priv->samples_in += need / ctx->info.bpf; - priv->got_data = FALSE; - ret = klass->handle_frame (enc, buf); + /* subclass might not want to be bothered with leftover data, + * so take care of that here if so, otherwise pass along */ + if (G_UNLIKELY (priv->force && priv->hard_min && buf)) { + GST_DEBUG_OBJECT (enc, "bypassing subclass with leftover"); + ret = gst_audio_encoder_finish_frame (enc, NULL, -1); + } else { + ret = klass->handle_frame (enc, buf); + } if (G_LIKELY (buf)) gst_buffer_unref (buf); + finish: /* no data to feed, no leftover provided, then bail out */ if (G_UNLIKELY (!buf && !priv->got_data)) { priv->drained = TRUE; @@ -2133,6 +2150,106 @@ gst_audio_encoder_get_tolerance (GstAudioEncoder * enc) } /** + * gst_audio_encoder_set_hard_min: + * @enc: a #GstAudioEncoder + * @enabled: new state + * + * Configures encoder hard minimum handling. If enabled, subclass + * will never be handed less samples than it configured, which otherwise + * might occur near end-of-data handling. Instead, the leftover samples + * will simply be discarded. + * + * MT safe. + * + * Since: 0.10.36 + */ +void +gst_audio_encoder_set_hard_min (GstAudioEncoder * enc, gboolean enabled) +{ + g_return_if_fail (GST_IS_AUDIO_ENCODER (enc)); + + GST_OBJECT_LOCK (enc); + enc->priv->hard_min = enabled; + GST_OBJECT_UNLOCK (enc); +} + +/** + * gst_audio_encoder_get_hard_min: + * @enc: a #GstAudioEncoder + * + * Queries encoder hard minimum handling. + * + * Returns: TRUE if hard minimum handling is enabled. + * + * MT safe. + * + * Since: 0.10.36 + */ +gboolean +gst_audio_encoder_get_hard_min (GstAudioEncoder * enc) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0); + + GST_OBJECT_LOCK (enc); + result = enc->priv->hard_min; + GST_OBJECT_UNLOCK (enc); + + return result; +} + +/** + * gst_audio_encoder_set_drainable: + * @enc: a #GstAudioEncoder + * @enabled: new state + * + * Configures encoder drain handling. If drainable, subclass might + * be handed a NULL buffer to have it return any leftover encoded 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_encoder_set_drainable (GstAudioEncoder * enc, gboolean enabled) +{ + g_return_if_fail (GST_IS_AUDIO_ENCODER (enc)); + + GST_OBJECT_LOCK (enc); + enc->priv->drainable = enabled; + GST_OBJECT_UNLOCK (enc); +} + +/** + * gst_audio_encoder_get_drainable: + * @enc: a #GstAudioEncoder + * + * Queries encoder drain handling. + * + * Returns: TRUE if drainable handling is enabled. + * + * MT safe. + * + * Since: 0.10.36 + */ +gboolean +gst_audio_encoder_get_drainable (GstAudioEncoder * enc) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0); + + GST_OBJECT_LOCK (enc); + result = enc->priv->drainable; + GST_OBJECT_UNLOCK (enc); + + return result; +} + +/** * gst_audio_encoder_merge_tags: * @enc: a #GstAudioEncoder * @tags: a #GstTagList to merge diff --git a/gst-libs/gst/audio/gstaudioencoder.h b/gst-libs/gst/audio/gstaudioencoder.h index 1287301..aa40677 100644 --- a/gst-libs/gst/audio/gstaudioencoder.h +++ b/gst-libs/gst/audio/gstaudioencoder.h @@ -246,6 +246,16 @@ void gst_audio_encoder_set_tolerance (GstAudioEncoder * enc, gint64 gst_audio_encoder_get_tolerance (GstAudioEncoder * enc); +void gst_audio_encoder_set_hard_min (GstAudioEncoder * enc, + gboolean enabled); + +gboolean gst_audio_encoder_get_hard_min (GstAudioEncoder * enc); + +void gst_audio_encoder_set_drainable (GstAudioEncoder * enc, + gboolean enabled); + +gboolean gst_audio_encoder_get_drainable (GstAudioEncoder * enc); + void gst_audio_encoder_merge_tags (GstAudioEncoder * enc, const GstTagList * tags, GstTagMergeMode mode); -- 2.7.4