[FFmpeg-devel] [PATCH 1/3] lavu: add a channels reordering API.

Nicolas George nicolas.george at normalesup.org
Thu Nov 22 19:13:57 CET 2012


TODO minor bump and APIchanges entry.

Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
 libavutil/Makefile           |    1 +
 libavutil/channels_reorder.c |  136 ++++++++++++++++++++++++++++++++++++++++++
 libavutil/channels_reorder.h |   83 ++++++++++++++++++++++++++
 3 files changed, 220 insertions(+)
 create mode 100644 libavutil/channels_reorder.c
 create mode 100644 libavutil/channels_reorder.h

diff --git a/libavutil/Makefile b/libavutil/Makefile
index 61ddc9a..106e216 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -64,6 +64,7 @@ OBJS = adler32.o                                                        \
        blowfish.o                                                       \
        bprint.o                                                         \
        channel_layout.o                                                 \
+       channels_reorder.o                                               \
        cpu.o                                                            \
        crc.o                                                            \
        des.o                                                            \
diff --git a/libavutil/channels_reorder.c b/libavutil/channels_reorder.c
new file mode 100644
index 0000000..a8fcc03
--- /dev/null
+++ b/libavutil/channels_reorder.c
@@ -0,0 +1,136 @@
+/*
+ * Channels reordering
+ * Copyright (c) 2012 Nicolas George
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include "channel_layout.h"
+#include "channels_reorder.h"
+
+#define NAME(src, dst, nch, size, suffix)                                    \
+    reorder_##src##_##dst##_##nch##_##size##suffix
+
+#define DEFINE_REORDER_SIZE(src, dst, nch, proc, size)                       \
+static void NAME(src, dst, nch, size, )(void *dbuf, void *sbuf, unsigned n)  \
+{                                                                            \
+    int##size##_t t, *s = sbuf, *d = dbuf;                                   \
+    unsigned i;                                                              \
+    for (i = 0; i < n; i++) {                                                \
+        proc                                                                 \
+        s += nch;                                                            \
+        d += nch;                                                            \
+    }                                                                        \
+}                                                                            \
+static void NAME(src, dst, nch, size, _packed)(uint8_t **dp, uint8_t **sp,   \
+                                               unsigned n)      \
+{                                                                            \
+    NAME(src, dst, nch, size, )(dp[0], sp[0], n);                            \
+}
+
+#define DEFINE_REORDER(src, dst, nch, proc)                                  \
+    DEFINE_REORDER_SIZE(src, dst, nch, proc, 8)                              \
+    DEFINE_REORDER_SIZE(src, dst, nch, proc, 16)                             \
+    DEFINE_REORDER_SIZE(src, dst, nch, proc, 32)                             \
+    DEFINE_REORDER_SIZE(src, dst, nch, proc, 64)                             \
+static void NAME(src, dst, nch, planar, )(uint8_t **dp, uint8_t **sp,        \
+                                          unsigned n)                        \
+{                                                                            \
+    if (sizeof(void *) == sizeof(int32_t))                                   \
+        NAME(src, dst, nch, 32, )(dp, sp, 1);                                \
+    else if (sizeof(void *) == sizeof(int64_t))                              \
+        NAME(src, dst, nch, 64, )(dp, sp, 1);                                \
+    else {                                   \
+        /* force build failure */                                            \
+        extern void NAME(src, dst, nch, pointer, )(void);                    \
+        NAME(src, dst, nch, pointer, )();                                    \
+    }                                                                        \
+}
+
+#define FMT_MAP(src, dst, nch)                                               \
+    switch (fmt) {                                                           \
+    case AV_SAMPLE_FMT_U8:  *rfunc = NAME(src, dst, nch,  8, _packed); break;\
+    case AV_SAMPLE_FMT_S16: *rfunc = NAME(src, dst, nch, 16, _packed); break;\
+    case AV_SAMPLE_FMT_S32:                                                  \
+    case AV_SAMPLE_FMT_FLT: *rfunc = NAME(src, dst, nch, 32, _packed); break;\
+    case AV_SAMPLE_FMT_DBL: *rfunc = NAME(src, dst, nch, 64, _packed); break;\
+    case AV_SAMPLE_FMT_U8P:                                                  \
+    case AV_SAMPLE_FMT_S16P:                                                 \
+    case AV_SAMPLE_FMT_S32P:                                                 \
+    case AV_SAMPLE_FMT_FLTP:                                                 \
+    case AV_SAMPLE_FMT_DBLP: *rfunc = NAME(src, dst, nch, planar, );  break; \
+    }                                                                        \
+    return 0;
+
+#define TUPLE(src, dst, nch) (((src) << 16) | ((dst << 8)) | (nch))
+
+#define USE_REORDER_ASYM(src, dst, nch, layouts)                             \
+    case TUPLE(AV_CH_ORDER_##src, AV_CH_ORDER_##dst, nch):                   \
+        if (!(CL(0) || layouts)) return AVERROR(ENOSYS);                     \
+        FMT_MAP(src, dst, nch)
+
+#define USE_REORDER_SYMM(src, dst, nch, layouts)                             \
+    case TUPLE(AV_CH_ORDER_##src, AV_CH_ORDER_##dst, nch):                   \
+    case TUPLE(AV_CH_ORDER_##dst, AV_CH_ORDER_##src, nch):                   \
+        if (!(CL(0) || layouts)) return AVERROR(ENOSYS);                     \
+        FMT_MAP(src, dst, nch)
+
+#define USE_REORDER_NULL(src, dst, nch, layouts)                             \
+    case TUPLE(AV_CH_ORDER_##src, AV_CH_ORDER_##dst, nch):                   \
+    case TUPLE(AV_CH_ORDER_##dst, AV_CH_ORDER_##src, nch):                   \
+        if (!(CL(0) || layouts)) return AVERROR(ENOSYS);                     \
+        *rfunc = NULL; return 0;
+
+#define USE_REORDER_BOTH(src, dst, nch, layouts)                             \
+    USE_REORDER_ASYM(src, dst, nch, layouts)                                 \
+    USE_REORDER_ASYM(dst, src, nch, layouts)
+
+#define AV_CH_LAYOUT_0 0
+#define CL(l) (channel_layout == AV_CH_LAYOUT_##l)
+
+#define C(a) d[a] = s[a]
+#define S(a, b) t = s[a]; d[a] = s[b]; d[b] = t
+#define R3R(a, b, c) t = s[c]; d[c] = s[b]; d[b] = s[a]; d[a] = t
+#define R3L(a, b, c) R3R(c, b, a)
+
+DEFINE_REORDER(INTERNAL, ALSA, 5, { C(0); C(1); R3L(2, 3, 4); })
+DEFINE_REORDER(ALSA, INTERNAL, 5, { C(0); C(1); R3R(2, 3, 4); })
+DEFINE_REORDER(INTERNAL, ALSA, 6, { C(0); C(1); S(2, 4); S(3, 5); })
+DEFINE_REORDER(INTERNAL, ALSA, 8, { C(0); C(1); S(2, 4); S(3, 5); C(6); C(7); })
+
+int av_get_channels_reorder_func(AVChannelsReorderFunc *rfunc,
+                                 enum AVSampleFormat fmt,
+                                 unsigned nb_channels,
+                                 uint64_t channel_layout,
+                                 enum AVChannelsOrderStandard src,
+                                 enum AVChannelsOrderStandard dst,
+                                 unsigned flags)
+{
+    *rfunc = NULL;
+    if (nb_channels >= 256)
+        return AVERROR_PATCHWELCOME;
+    if (nb_channels <= 2)
+        return 0;
+    switch (TUPLE(src, dst, nb_channels)) {
+        USE_REORDER_NULL(INTERNAL, ALSA, 4, CL(QUAD) || CL(2_2));
+        USE_REORDER_BOTH(INTERNAL, ALSA, 5, CL(5POINT0) || CL(5POINT0_BACK));
+        USE_REORDER_SYMM(INTERNAL, ALSA, 6, CL(5POINT1) || CL(5POINT1_BACK));
+        USE_REORDER_SYMM(INTERNAL, ALSA, 8, CL(7POINT1));
+    }
+    return AVERROR_PATCHWELCOME;
+}
diff --git a/libavutil/channels_reorder.h b/libavutil/channels_reorder.h
new file mode 100644
index 0000000..96f7da2
--- /dev/null
+++ b/libavutil/channels_reorder.h
@@ -0,0 +1,83 @@
+/*
+ * Channels reordering
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVUTIL_CHANNELS_REORDER_H
+#define AVUTIL_CHANNELS_REORDER_H
+
+#include "samplefmt.h"
+
+/**
+ * Channels reordering function
+ *
+ * The first argument is the destination samples array,
+ * the second argument is the source samples array,
+ * the third argument is the number of samples.
+ * The source and destination can be the same.
+ * The samples array are the array of pointers to the samples data;
+ * they have a single element for packed formats and
+ * as many elements as there are channels for planar formats.
+ */
+typedef void (*AVChannelsReorderFunc)(uint8_t **, uint8_t **, unsigned);
+
+/**
+ * Supported channels order standards.
+ */
+enum AVChannelsOrderStandard {
+
+    /**
+     * Internal channels order: the channels are in the order they appear in
+     * <channel_layout.h>. This is mostly the same order as WAVE.
+     */
+    AV_CH_ORDER_INTERNAL,
+
+    /**
+     * ALSA (Advanced Linux Sound Architecture) channels order:
+     * FL, FR, BL, BR, FC, LFE, SL, SR.
+     */
+    AV_CH_ORDER_ALSA,
+
+    /**
+     * Vorbis/Opus channels order, see:
+     * http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
+     */
+    AV_CH_ORDER_VORBIS,
+};
+
+/**
+ * Get a channels reordering function.
+ *
+ * @param[out] rfunc           used to return the function; set to NULL if no
+ *                             reordering is needed or if no function exist
+ * @param[in]  fmt             sample format
+ * @param[in]  nb_channels     number of channels
+ * @param[in]  channel_layout  channel layout, can be 0 if unknown
+ * @param[in]  src             source standard
+ * @param[in]  dst             destination standard
+ * @param[in]  flags           flags, currently unused
+ */
+int av_get_channels_reorder_func(AVChannelsReorderFunc *rfunc,
+                                 enum AVSampleFormat fmt,
+                                 unsigned nb_channels,
+                                 uint64_t channel_layout,
+                                 enum AVChannelsOrderStandard src,
+                                 enum AVChannelsOrderStandard dst,
+                                 unsigned flags);
+
+#endif /* AVUTIL_CHANNELS_REORDER_H */
-- 
1.7.10.4



More information about the ffmpeg-devel mailing list