[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