audioencoder: add some properties to tweak baseclass behaviour
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Thu, 16 Feb 2012 11:18:03 +0000 (12:18 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Thu, 16 Feb 2012 11:35:51 +0000 (12:35 +0100)
... 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
gst-libs/gst/audio/gstaudioencoder.h

index d64bd22..b915ae7 100644 (file)
@@ -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
index 1287301..aa40677 100644 (file)
@@ -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);