[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