libs: audio: add a new gst_audio_buffer_truncate() function
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Fri, 18 May 2018 13:22:47 +0000 (16:22 +0300)
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Thu, 12 Jul 2018 09:08:10 +0000 (12:08 +0300)
Essentially this moves the truncation logic out of gst_audio_buffer_clip()
so that it can be used in other places, like in audiorate.

https://bugzilla.gnome.org/show_bug.cgi?id=796740

gst-libs/gst/audio/audio.c
gst-libs/gst/audio/audio.h

index 79b976b..9c7ed04 100644 (file)
@@ -222,37 +222,10 @@ gst_audio_buffer_clip (GstBuffer * buffer, const GstSegment * segment,
       ret = gst_buffer_make_writable (ret);
       GST_BUFFER_DURATION (ret) = duration;
     }
-  } else if (meta && meta->info.layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
-    /* modify only the meta to avoid making copies of the planes */
-    gint i;
-
-    ret = gst_buffer_make_writable (buffer);
-    meta = gst_buffer_get_audio_meta (buffer);
-
-    meta->samples = size;
-    for (i = 0; i < meta->info.channels; i++) {
-      meta->offsets[i] += trim * bpf / meta->info.channels;
-    }
-
-    GST_BUFFER_TIMESTAMP (ret) = timestamp;
-
-    if (change_duration)
-      GST_BUFFER_DURATION (ret) = duration;
-    if (change_offset)
-      GST_BUFFER_OFFSET (ret) = offset;
-    if (change_offset_end)
-      GST_BUFFER_OFFSET_END (ret) = offset_end;
   } else {
-    /* resize the buffer, effectively cutting out all
-     * the samples that are no longer relevant */
-
-    /* convert samples to bytes */
-    trim *= bpf;
-    size *= bpf;
-
+    /* cut out all the samples that are no longer relevant */
     GST_DEBUG ("trim %" G_GSIZE_FORMAT " size %" G_GSIZE_FORMAT, trim, size);
-    ret = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, trim, size);
-    gst_buffer_unref (buffer);
+    ret = gst_audio_buffer_truncate (buffer, bpf, trim, size);
 
     GST_DEBUG ("timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
     if (ret) {
@@ -265,8 +238,75 @@ gst_audio_buffer_clip (GstBuffer * buffer, const GstSegment * segment,
       if (change_offset_end)
         GST_BUFFER_OFFSET_END (ret) = offset_end;
     } else {
-      GST_ERROR ("copy_region failed");
+      GST_ERROR ("gst_audio_buffer_truncate failed");
     }
   }
   return ret;
 }
+
+/**
+ * gst_audio_buffer_truncate:
+ * @buffer: (transfer full): The buffer to truncate.
+ * @bpf: size of one audio frame in bytes. This is the size of one sample *
+ * number of channels.
+ * @trim: the number of samples to remove from the beginning of the buffer
+ * @samples: the final number of samples that should exist in this buffer or -1
+ * to use all the remaining samples if you are only removing samples from the
+ * beginning.
+ *
+ * Truncate the buffer to finally have @samples number of samples, removing
+ * the necessary amount of samples from the end and @trim number of samples
+ * from the beginning.
+ *
+ * After calling this function the caller does not own a reference to
+ * @buffer anymore.
+ *
+ * Returns: (transfer full): the truncated buffer or %NULL if the arguments
+ *   were invalid
+ *
+ * Since: 1.16
+ */
+GstBuffer *
+gst_audio_buffer_truncate (GstBuffer * buffer, gint bpf, gsize trim,
+    gsize samples)
+{
+  GstAudioMeta *meta = NULL;
+  GstBuffer *ret = NULL;
+  gsize orig_samples;
+  gint i;
+
+  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
+
+  meta = gst_buffer_get_audio_meta (buffer);
+  orig_samples = meta ? meta->samples : gst_buffer_get_size (buffer) / bpf;
+
+  g_return_val_if_fail (trim < orig_samples, NULL);
+  g_return_val_if_fail (samples == -1 || trim + samples <= orig_samples, NULL);
+
+  if (samples == -1)
+    samples = orig_samples - trim;
+
+  /* nothing to truncate */
+  if (samples == orig_samples)
+    return buffer;
+
+  if (!meta || meta->info.layout == GST_AUDIO_LAYOUT_INTERLEAVED) {
+    /* interleaved */
+    ret = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, trim * bpf,
+        samples * bpf);
+    gst_buffer_unref (buffer);
+
+    if ((meta = gst_buffer_get_audio_meta (ret)))
+      meta->samples = samples;
+  } else {
+    /* non-interleaved */
+    ret = gst_buffer_make_writable (buffer);
+    meta = gst_buffer_get_audio_meta (buffer);
+    meta->samples = samples;
+    for (i = 0; i < meta->info.channels; i++) {
+      meta->offsets[i] += trim * bpf / meta->info.channels;
+    }
+  }
+
+  return ret;
+}
index 16a985d..4120f5b 100644 (file)
@@ -97,6 +97,9 @@ GstBuffer *    gst_audio_buffer_clip     (GstBuffer *buffer,
                                           const GstSegment *segment,
                                           gint rate, gint bpf);
 
+GST_EXPORT
+GstBuffer *    gst_audio_buffer_truncate (GstBuffer *buffer,
+                                          gint bpf, gsize trim, gsize samples);
 
 G_END_DECLS