libs: audio: implement planar buffer support in gst_audio_buffer_reorder_channels()
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Tue, 13 Feb 2018 11:24:32 +0000 (13:24 +0200)
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Thu, 12 Jul 2018 10:38:27 +0000 (13:38 +0300)
https://bugzilla.gnome.org/show_bug.cgi?id=796743

gst-libs/gst/audio/audio-channels.c

index 9d3eace..f713bbc 100644 (file)
@@ -196,6 +196,8 @@ check_valid_channel_positions (const GstAudioChannelPosition * position,
  * positions @to. @from and @to must contain the same number of
  * positions and the same positions, only in a different order.
  *
+ * Note: this function assumes the audio data is in interleaved layout
+ *
  * Returns: %TRUE if the reordering was possible.
  */
 gboolean
@@ -248,6 +250,31 @@ gst_audio_reorder_channels (gpointer data, gsize size, GstAudioFormat format,
   return TRUE;
 }
 
+static gboolean
+gst_audio_meta_reorder_channels (GstAudioMeta * meta,
+    const GstAudioChannelPosition * from, const GstAudioChannelPosition * to)
+{
+  gint reorder_map[64] = { 0, };
+  gsize tmp_offsets[64] = { 0, };
+  gint i;
+
+  g_return_val_if_fail (meta, FALSE);
+  g_return_val_if_fail (meta->info.channels > 0, FALSE);
+  g_return_val_if_fail (meta->info.channels <= 64, FALSE);
+  g_return_val_if_fail (meta->offsets != NULL, FALSE);
+
+  if (!gst_audio_get_channel_reorder_map (meta->info.channels, from, to,
+          reorder_map))
+    return FALSE;
+
+  memcpy (tmp_offsets, meta->offsets, meta->info.channels * sizeof (gsize));
+  for (i = 0; i < meta->info.channels; i++) {
+    meta->offsets[reorder_map[i]] = tmp_offsets[i];
+  }
+
+  return TRUE;
+}
+
 /**
  * gst_audio_buffer_reorder_channels:
  * @buffer: The buffer to reorder.
@@ -269,7 +296,8 @@ gst_audio_buffer_reorder_channels (GstBuffer * buffer,
     const GstAudioChannelPosition * from, const GstAudioChannelPosition * to)
 {
   GstMapInfo info;
-  gboolean ret;
+  GstAudioMeta *meta;
+  gboolean ret = TRUE;
 
   g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE);
   g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE);
@@ -277,15 +305,20 @@ gst_audio_buffer_reorder_channels (GstBuffer * buffer,
   if (gst_audio_channel_positions_equal (from, to, channels))
     return TRUE;
 
-  if (!gst_buffer_map (buffer, &info, GST_MAP_READWRITE))
-    return FALSE;
+  meta = gst_buffer_get_audio_meta (buffer);
+  if (meta && meta->info.layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
+    g_return_val_if_fail (channels == meta->info.channels, FALSE);
 
-  ret =
-      gst_audio_reorder_channels (info.data, info.size, format, channels, from,
-      to);
+    ret = gst_audio_meta_reorder_channels (meta, from, to);
+  } else {
+    if (!gst_buffer_map (buffer, &info, GST_MAP_READWRITE))
+      return FALSE;
 
-  gst_buffer_unmap (buffer, &info);
+    ret = gst_audio_reorder_channels (info.data, info.size, format, channels,
+        from, to);
 
+    gst_buffer_unmap (buffer, &info);
+  }
   return ret;
 }