dvdlpcmdec: Port to the new raw audio caps
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 4 Jan 2012 14:26:56 +0000 (15:26 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 5 Jan 2012 09:37:04 +0000 (10:37 +0100)
gst/dvdlpcmdec/gstdvdlpcmdec.c
gst/dvdlpcmdec/gstdvdlpcmdec.h

index 215e67b..c835d83 100644 (file)
@@ -26,7 +26,7 @@
 #include <string.h>
 
 #include "gstdvdlpcmdec.h"
-#include <gst/audio/multichannel.h>
+#include <gst/audio/audio.h>
 
 GST_DEBUG_CATEGORY_STATIC (dvdlpcm_debug);
 #define GST_CAT_DEFAULT dvdlpcm_debug
@@ -51,6 +51,7 @@ GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("audio/x-raw, "
         "format = (string) { S16BE, S24BE }, "
+        "layout = (string) interleaved, "
         "rate = (int) { 32000, 44100, 48000, 96000 }, "
         "channels = (int) [ 1, 8 ]")
     );
@@ -167,46 +168,31 @@ gst_dvdlpcmdec_init (GstDvdLpcmDec * dvdlpcmdec)
   gst_dvdlpcm_reset (dvdlpcmdec);
 }
 
-static GstAudioChannelPosition *
-get_audio_channel_positions (GstDvdLpcmDec * dvdlpcmdec)
-{
-  gint n_channels = GST_AUDIO_INFO_CHANNELS (&dvdlpcmdec->info);
-  GstAudioChannelPosition *ret = g_new (GstAudioChannelPosition, n_channels);
-
-  /* FIXME: The channel layouts for 5.1 and 7.1 are just guesses, I can't
-   * find any samples or confirmation */
-  switch (n_channels) {
-    case 8:
-      ret[7] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
-      ret[6] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
-      /* Fall through */
-    case 6:
-      ret[5] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
-      ret[4] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
-      ret[3] = GST_AUDIO_CHANNEL_POSITION_LFE;
-      ret[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
-      /* Fall through */
-    case 2:
-      ret[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
-      ret[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
-      break;
-    case 4:
-      ret[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
-      ret[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
-      ret[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
-      ret[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
-      break;
-    case 1:
-      ret[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
-      break;
-    default:
-      g_free (ret);
-      ret = NULL;
-      break;
-  }
-
-  return ret;
-}
+static const GstAudioChannelPosition channel_positions[][8] = {
+  {GST_AUDIO_CHANNEL_POSITION_MONO},
+  {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
+  {GST_AUDIO_CHANNEL_POSITION_INVALID},
+  {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
+  {GST_AUDIO_CHANNEL_POSITION_INVALID},
+  {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
+        GST_AUDIO_CHANNEL_POSITION_LFE1, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
+  {GST_AUDIO_CHANNEL_POSITION_INVALID},
+  {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
+        GST_AUDIO_CHANNEL_POSITION_LFE1, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT},
+  {GST_AUDIO_CHANNEL_POSITION_INVALID}
+};
 
 static void
 gst_dvdlpcmdec_send_tags (GstDvdLpcmDec * dvdlpcmdec)
@@ -231,17 +217,10 @@ gst_dvdlpcmdec_set_outcaps (GstDvdLpcmDec * dvdlpcmdec)
 {
   gboolean res = TRUE;
   GstCaps *src_caps;
-  GstAudioChannelPosition *pos;
 
   /* Build caps to set on the src pad, which we know from the incoming caps */
   src_caps = gst_audio_info_to_caps (&dvdlpcmdec->info);
 
-  pos = get_audio_channel_positions (dvdlpcmdec);
-  if (pos) {
-    gst_audio_set_channel_positions (gst_caps_get_structure (src_caps, 0), pos);
-    g_free (pos);
-  }
-
   res = gst_pad_set_caps (dvdlpcmdec->srcpad, src_caps);
   if (res) {
     GST_DEBUG_OBJECT (dvdlpcmdec, "Successfully set output caps: %"
@@ -266,6 +245,7 @@ gst_dvdlpcmdec_setcaps (GstPad * pad, GstCaps * caps)
   GstDvdLpcmDec *dvdlpcmdec;
   GstAudioFormat format;
   gint rate, channels, width;
+  const GstAudioChannelPosition *position;
 
   g_return_val_if_fail (caps != NULL, FALSE);
   g_return_val_if_fail (pad != NULL, FALSE);
@@ -307,7 +287,20 @@ gst_dvdlpcmdec_setcaps (GstPad * pad, GstCaps * caps)
       format = GST_AUDIO_FORMAT_UNKNOWN;
       break;
   }
-  gst_audio_info_set_format (&dvdlpcmdec->info, format, rate, channels);
+
+  gst_audio_info_set_format (&dvdlpcmdec->info, format, rate, channels, NULL);
+  if (channels < 9
+      && channel_positions[channels - 1][0] !=
+      GST_AUDIO_CHANNEL_POSITION_INVALID) {
+    dvdlpcmdec->info.flags &= ~GST_AUDIO_FLAG_NONE_LAYOUT;
+    position = channel_positions[channels - 1];
+    dvdlpcmdec->lpcm_layout = position;
+    memcpy (dvdlpcmdec->info.position, position,
+        sizeof (GstAudioChannelPosition) * channels);
+    gst_audio_channel_positions_to_valid_order (dvdlpcmdec->info.position,
+        channels);
+  }
+
   dvdlpcmdec->width = width;
 
   res = gst_dvdlpcmdec_set_outcaps (dvdlpcmdec);
@@ -413,7 +406,19 @@ parse_header (GstDvdLpcmDec * dec, guint32 header)
   /* And, of course, the number of channels (up to 8) */
   channels = ((header >> 8) & 0x7) + 1;
 
-  gst_audio_info_set_format (&dec->info, format, rate, channels);
+  gst_audio_info_set_format (&dec->info, format, rate, channels, NULL);
+  if (channels < 9
+      && channel_positions[channels - 1][0] !=
+      GST_AUDIO_CHANNEL_POSITION_INVALID) {
+    const GstAudioChannelPosition *position;
+
+    dec->info.flags &= ~GST_AUDIO_FLAG_NONE_LAYOUT;
+    position = channel_positions[channels - 1];
+    dec->lpcm_layout = position;
+    memcpy (dec->info.position, position,
+        sizeof (GstAudioChannelPosition) * channels);
+    gst_audio_channel_positions_to_valid_order (dec->info.position, channels);
+  }
 }
 
 static GstFlowReturn
@@ -716,6 +721,11 @@ gst_dvdlpcmdec_chain_raw (GstPad * pad, GstObject * parent, GstBuffer * buf)
 
   update_timestamps (dvdlpcmdec, buf, samples);
 
+  if (dvdlpcmdec->lpcm_layout)
+    gst_audio_buffer_reorder_channels (buf, dvdlpcmdec->info.finfo->format,
+        dvdlpcmdec->info.channels, dvdlpcmdec->lpcm_layout,
+        dvdlpcmdec->info.position);
+
   ret = gst_pad_push (dvdlpcmdec->srcpad, buf);
 
 done:
index cad1e0a..031c033 100644 (file)
@@ -48,6 +48,7 @@ struct _GstDvdLpcmDec {
   guint32 header;
 
   GstAudioInfo info;
+  const GstAudioChannelPosition *lpcm_layout;
   gint width;
   gint dynamic_range;
   gint emphasis;