gst_plugins_base/gst-libs/gst/audio/multichannel.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
--- a/gst_plugins_base/gst-libs/gst/audio/multichannel.c	Tue Aug 31 15:30:33 2010 +0300
+++ b/gst_plugins_base/gst-libs/gst/audio/multichannel.c	Wed Sep 01 12:16:41 2010 +0100
@@ -16,53 +16,32 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
-/**
- * SECTION:gstmultichannel
- * @short_description: Support for multichannel audio elements
- *
- * This module contains some helper functions and a enum to work with
- * multichannel audio.
- */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "multichannel.h"
 
 #define GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME "channel-positions"
 
-/**
- * gst_audio_check_channel_positions:
- * @pos: An array of #GstAudioChannelPosition.
- * @channels: The number of elements in @pos.
- *
- * This functions checks if the given channel positions are valid. Channel
- * positions are valid if:
- * <itemizedlist>
- *   <listitem><para>No channel positions appears twice or all positions are %GST_AUDIO_CHANNEL_POSITION_NONE.
- *   </para></listitem>
- *   <listitem><para>Either all or none of the channel positions are %GST_AUDIO_CHANNEL_POSITION_NONE.
- *   </para></listitem>
- *   <listitem><para>%GST_AUDIO_CHANNEL_POSITION_FRONT_MONO and %GST_AUDIO_CHANNEL_POSITION_LEFT or %GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT don't appear together in the given positions.
- *   </para></listitem>
- * </itemizedlist>
- *
- * Since: 0.10.20
- *
- * Returns: %TRUE if the given channel positions are valid
- * and %FALSE otherwise.
+/*
+ * This function checks if basic assumptions apply:
+ *  - does each position occur at most once?
+ *  - do conflicting positions occur?
+ *     + front_mono vs. front_left/right
+ *     + front_center vs. front_left/right_of_center
+ *     + rear_center vs. rear_left/right
+ * It also adds some hacks that 0.8.x needs for compatibility:
+ *  - if channels == 1, are we really mono?
+ *  - if channels == 2, are we really stereo?
  */
-#ifdef __SYMBIAN32__
-EXPORT_C
-#endif
 
-gboolean
+static gboolean
 gst_audio_check_channel_positions (const GstAudioChannelPosition * pos,
-    guint channels)
+    gint channels)
 {
   gint i, n;
-
   const struct
   {
     const GstAudioChannelPosition pos1[2];
@@ -72,18 +51,27 @@
     { {
     GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
             GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}},
+        /* front center: 2 <-> 1 */
+    { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
+            GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}},
+        /* rear: 2 <-> 1 */
+    { {
+    GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+            GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
+    GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { {
     GST_AUDIO_CHANNEL_POSITION_INVALID}}
   };
 
-  g_return_val_if_fail (pos != NULL, FALSE);
-  g_return_val_if_fail (channels > 0, FALSE);
+  g_assert (pos != NULL && channels > 0);
 
   /* check for invalid channel positions */
   for (n = 0; n < channels; n++) {
     if (pos[n] <= GST_AUDIO_CHANNEL_POSITION_INVALID ||
         pos[n] >= GST_AUDIO_CHANNEL_POSITION_NUM) {
-      GST_WARNING ("Channel position %d for channel %d is invalid", pos[n], n);
+      g_warning ("Channel position %d for channel %d is invalid", pos[n], n);
       return FALSE;
     }
   }
@@ -94,7 +82,7 @@
   if (pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
     for (n = 1; n < channels; ++n) {
       if (pos[n] != GST_AUDIO_CHANNEL_POSITION_NONE) {
-        GST_WARNING ("Either all channel positions must be defined, or all "
+        g_warning ("Either all channel positions must be defined, or all "
             "be set to NONE, having only some defined is not allowed");
         return FALSE;
       }
@@ -115,13 +103,13 @@
 
     /* NONE may not occur mixed with other channel positions */
     if (i == GST_AUDIO_CHANNEL_POSITION_NONE && count > 0) {
-      GST_WARNING ("Either all channel positions must be defined, or all "
+      g_warning ("Either all channel positions must be defined, or all "
           "be set to NONE, having only some defined is not allowed");
       return FALSE;
     }
 
     if (count > 1) {
-      GST_WARNING ("Channel position %d occurred %d times, not allowed",
+      g_warning ("Channel position %d occurred %d times, not allowed",
           i, count);
       return FALSE;
     }
@@ -139,12 +127,21 @@
     }
 
     if (found1 && found2) {
-      GST_WARNING ("Found conflicting channel positions %d/%d and %d",
+      g_warning ("Found conflicting channel positions %d/%d and %d",
           conf[i].pos1[0], conf[i].pos1[1], conf[i].pos2[0]);
       return FALSE;
     }
   }
 
+  /* Throw warning if we encounter an unusual 2-channel configuration,
+   * at least until someone finds a reason why we should not */
+  if (channels == 2 && (pos[0] != GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT ||
+          pos[1] != GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT)) {
+    g_warning ("channels=2 implies stereo, but channel positions are "
+        "< %d, %d>", pos[0], pos[1]);
+    return FALSE;
+  }
+
   return TRUE;
 }
 
@@ -239,13 +236,9 @@
 gst_audio_get_channel_positions (GstStructure * str)
 {
   GstAudioChannelPosition *pos;
-
   gint channels, n;
-
   const GValue *pos_val_arr, *pos_val_entry;
-
   gboolean res;
-
   GType t;
 
   /* get number of channels, general type checkups */
@@ -323,7 +316,6 @@
   GValue pos_val_arr = { 0 }, pos_val_entry = {
   0};
   gint channels, n;
-
   gboolean res;
 
   /* get number of channels, checkups */
@@ -391,6 +383,11 @@
   g_return_if_fail (res);
   g_return_if_fail (channels > 0);
 
+  /* 0.8.x: channels=1 or channels=2 is mono/stereo, no positions needed
+   * there (we discard them anyway) */
+  if (channels == 1 || channels == 2)
+    return;
+
   /* create the array of lists */
   g_value_init (&pos_val_arr, GST_TYPE_ARRAY);
   g_value_init (&pos_val_entry, GST_TYPE_AUDIO_CHANNEL_POSITION);
@@ -420,7 +417,6 @@
     const GstAudioChannelPosition * pos, gint num_positions)
 {
   GstCaps *caps = gst_caps_new_empty ();
-
   const GValue *chan_val;
 
   chan_val = gst_structure_get_value (str, "channels");
@@ -428,7 +424,6 @@
     gst_audio_set_structure_channel_positions_list (str, pos, num_positions);
   } else if (G_VALUE_TYPE (chan_val) == GST_TYPE_LIST) {
     gint size;
-
     const GValue *sub_val;
 
     size = gst_value_list_get_size (chan_val);
@@ -531,13 +526,9 @@
 gst_audio_fixate_channel_positions (GstStructure * str)
 {
   GstAudioChannelPosition *pos;
-
   gint channels, n, num_unfixed = 0, i, c;
-
   const GValue *pos_val_arr, *pos_val_entry, *pos_val;
-
   gboolean res, is_stereo = TRUE;
-
   GType t;
 
   /*
@@ -552,20 +543,19 @@
     const GstAudioChannelPosition pos2[1];
   } conf[] = {
     /* front: mono <-> stereo */
-    {
-      {
-      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+    { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
             GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}},
+        /* front center: 2 <-> 1 */
+    { {
     GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
             GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
-    GST_AUDIO_CHANNEL_POSITION_INVALID}}, { {
-    GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}}, { {
+    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}},
+        /* rear: 2 <-> 1 */
+    { {
     GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
             GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
-    GST_AUDIO_CHANNEL_POSITION_INVALID}}, { {
-    GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, {
     GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { {
     GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, {
     GST_AUDIO_CHANNEL_POSITION_LFE}}, { {