[FFmpeg-devel] [PATCH 2/6] lavu/channel_layout: implement unknown layouts.

Nicolas George nicolas.george at normalesup.org
Wed Nov 28 16:14:17 CET 2012


Unknown channel layouts are necessary when the channel layout
is the authoritative source of information for the number of
channels; it happens in libavfilter.

Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
 libavutil/channel_layout.c |   36 +++++++++++++++++++++++++++++++++---
 libavutil/channel_layout.h |   23 +++++++++++++++++++++++
 2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c
index ef6bad7..5a956ec 100644
--- a/libavutil/channel_layout.c
+++ b/libavutil/channel_layout.c
@@ -23,6 +23,7 @@
  * audio channel layout utility functions
  */
 
+#include "avassert.h"
 #include "avstring.h"
 #include "avutil.h"
 #include "channel_layout.h"
@@ -160,7 +161,7 @@ void av_bprint_channel_layout(struct AVBPrint *bp,
         }
 
     av_bprintf(bp, "%d channels", nb_channels);
-    if (channel_layout) {
+    if (channel_layout && !(channel_layout & AV_CH_LAYOUT_UNKNOWN)) {
         int i, ch;
         av_bprintf(bp, " (");
         for (i = 0, ch = 0; i < 64; i++) {
@@ -218,7 +219,7 @@ const char *av_get_channel_name(uint64_t channel)
     for (i = 0; i < 64; i++)
         if ((1ULL<<i) & channel)
             return get_channel_name(i);
-    return NULL;
+    return "unknown";
 }
 
 const char *av_get_channel_description(uint64_t channel)
@@ -229,7 +230,7 @@ const char *av_get_channel_description(uint64_t channel)
     for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++)
         if ((1ULL<<i) & channel)
             return channel_names[i].description;
-    return NULL;
+    return "unknown channel";
 }
 
 uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
@@ -255,3 +256,32 @@ int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
     if (name)   *name   = channel_layout_map[index].name;
     return 0;
 }
+
+uint64_t av_channel_layout_make_unknown(int nb_channels)
+{
+    /* Used bits:
+       X.......*...................+++++++...........++++++++++++++++++
+      63      55                 36     29         18                 0 */
+#define BITS(b0, n) ((((uint64_t)1 << (n)) - 1) << (b0))
+    uint64_t               r  = BITS(55, FFMIN( 8, nb_channels -  0));
+    if (nb_channels >=  8) r |= BITS(36, FFMIN(19, nb_channels -  8));
+    if (nb_channels >= 27) r |= BITS(18, FFMIN(11, nb_channels - 27));
+    if (nb_channels >= 38) r |= BITS(29, FFMIN( 7, nb_channels - 27));
+    if (nb_channels >= 45) r |= BITS( 0, FFMIN(18, nb_channels - 45));
+#undef BITS
+    av_assert1(nb_channels <= 63);
+    return r;
+}
+
+void av_channel_layout_fix(int nb_channels, uint64_t *channel_layout)
+{
+    int n = av_get_channel_layout_nb_channels(*channel_layout);
+
+    if (n != nb_channels) {
+        if (n)
+            av_log(NULL, AV_LOG_WARNING,
+                   "Channel layout with %d channels instead of %d, fixed\n",
+                   n, nb_channels);
+        *channel_layout = av_channel_layout_make_unknown(nb_channels);
+    }
+}
diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h
index 9368992..748518d 100644
--- a/libavutil/channel_layout.h
+++ b/libavutil/channel_layout.h
@@ -72,6 +72,15 @@
 #define AV_CH_SURROUND_DIRECT_RIGHT  0x0000000400000000ULL
 #define AV_CH_LOW_FREQUENCY_2        0x0000000800000000ULL
 
+/**
+ * Channel mask value used to specify an unknown channel.
+ * If this bit is set in any channel layout, then the channel layout as a
+ * whole is considered unknown, and only the number of bits set is relevant.
+ * This is useful when an API requires a non-0 channel layout but the real
+ * channel layout is not known or can not be expressed.
+ */
+#define AV_CH_LAYOUT_UNKNOWN         0x0080000000000000ULL
+
 /** Channel mask value used for AVCodecContext.request_channel_layout
     to indicate that the user requests the channel order of the decoder output
     to be the native codec channel order. */
@@ -210,6 +219,20 @@ int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
                                    const char **name);
 
 /**
+ * Return a channel layout for an unknown layout with a specified number of
+ * channels.
+ * The bit mask will use undefined bits in priority.
+ */
+uint64_t av_channel_layout_make_unknown(int nb_channels);
+
+/**
+ * Ensure that a channel layout is consistent with the number of channels.
+ * If the channel layout is 0 or inconsistent, it will be set to a default
+ * mask using av_channel_layout_make_unknown().
+ */
+void av_channel_layout_fix(int nb_channels, uint64_t *channel_layout);
+
+/**
  * @}
  */
 
-- 
1.7.10.4



More information about the ffmpeg-devel mailing list