[FFmpeg-devel] [PATCH 3/4] lavd/alsa: move channels reordering in a separate file.
Nicolas George
nicolas.george at normalesup.org
Sat Feb 2 17:42:24 CET 2013
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
libavdevice/Makefile | 3 +-
libavdevice/alsa-audio-common.c | 106 ++------------------------------
libavdevice/alsa-audio.h | 3 +-
libavdevice/alsa_reorder.c | 126 +++++++++++++++++++++++++++++++++++++++
libavdevice/alsa_reorder.h | 44 ++++++++++++++
5 files changed, 178 insertions(+), 104 deletions(-)
create mode 100644 libavdevice/alsa_reorder.c
create mode 100644 libavdevice/alsa_reorder.h
diff --git a/libavdevice/Makefile b/libavdevice/Makefile
index efffa8b..515742d 100644
--- a/libavdevice/Makefile
+++ b/libavdevice/Makefile
@@ -14,7 +14,8 @@ OBJS = alldevices.o \
OBJS-$(CONFIG_ALSA_INDEV) += alsa-audio-common.o \
alsa-audio-dec.o timefilter.o
OBJS-$(CONFIG_ALSA_OUTDEV) += alsa-audio-common.o \
- alsa-audio-enc.o
+ alsa-audio-enc.o \
+ alsa_reorder.o
OBJS-$(CONFIG_BKTR_INDEV) += bktr.o
OBJS-$(CONFIG_CACA_OUTDEV) += caca.o
OBJS-$(CONFIG_DSHOW_INDEV) += dshow.o dshow_enummediatypes.o \
diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa-audio-common.c
index 47ef3c5..03b4c44 100644
--- a/libavdevice/alsa-audio-common.c
+++ b/libavdevice/alsa-audio-common.c
@@ -62,105 +62,6 @@ static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id)
}
}
-#define MAKE_REORDER_FUNC(NAME, TYPE, CHANNELS, LAYOUT, MAP) \
-static void alsa_reorder_ ## NAME ## _ ## LAYOUT(const void *in_v, \
- void *out_v, \
- int n) \
-{ \
- const TYPE *in = in_v; \
- TYPE *out = out_v; \
- \
- while (n-- > 0) { \
- MAP \
- in += CHANNELS; \
- out += CHANNELS; \
- } \
-}
-
-#define MAKE_REORDER_FUNCS(CHANNELS, LAYOUT, MAP) \
- MAKE_REORDER_FUNC(int8, int8_t, CHANNELS, LAYOUT, MAP) \
- MAKE_REORDER_FUNC(int16, int16_t, CHANNELS, LAYOUT, MAP) \
- MAKE_REORDER_FUNC(int32, int32_t, CHANNELS, LAYOUT, MAP) \
- MAKE_REORDER_FUNC(f64, double, CHANNELS, LAYOUT, MAP)
-
-MAKE_REORDER_FUNCS(5, out_50, \
- out[0] = in[0]; \
- out[1] = in[1]; \
- out[2] = in[3]; \
- out[3] = in[4]; \
- out[4] = in[2]; \
- );
-
-MAKE_REORDER_FUNCS(6, out_51, \
- out[0] = in[0]; \
- out[1] = in[1]; \
- out[2] = in[4]; \
- out[3] = in[5]; \
- out[4] = in[2]; \
- out[5] = in[3]; \
- );
-
-MAKE_REORDER_FUNCS(8, out_71, \
- out[0] = in[0]; \
- out[1] = in[1]; \
- out[2] = in[4]; \
- out[3] = in[5]; \
- out[4] = in[2]; \
- out[5] = in[3]; \
- out[6] = in[6]; \
- out[7] = in[7]; \
- );
-
-#define PICK_REORDER(layout)\
-switch(size) {\
- case 1: s->reorder_func = alsa_reorder_int8_out_ ##layout; break;\
- case 2: s->reorder_func = alsa_reorder_int16_out_ ##layout; break;\
- case 4: s->reorder_func = alsa_reorder_int32_out_ ##layout; break;\
- case 8: s->reorder_func = alsa_reorder_f64_out_ ##layout; break;\
-}
-
-static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, int out)
-{
- int size;
-
- /* reordering input is not currently supported */
- if (!out)
- return AVERROR(ENOSYS);
-
- /* reordering is not needed for QUAD or 2_2 layout */
- if (layout == AV_CH_LAYOUT_QUAD || layout == AV_CH_LAYOUT_2_2)
- return 0;
-
- switch (codec_id) {
- case AV_CODEC_ID_PCM_S8:
- case AV_CODEC_ID_PCM_U8:
- case AV_CODEC_ID_PCM_ALAW:
- case AV_CODEC_ID_PCM_MULAW: size = 1; break;
- case AV_CODEC_ID_PCM_S16LE:
- case AV_CODEC_ID_PCM_S16BE:
- case AV_CODEC_ID_PCM_U16LE:
- case AV_CODEC_ID_PCM_U16BE: size = 2; break;
- case AV_CODEC_ID_PCM_S32LE:
- case AV_CODEC_ID_PCM_S32BE:
- case AV_CODEC_ID_PCM_U32LE:
- case AV_CODEC_ID_PCM_U32BE:
- case AV_CODEC_ID_PCM_F32LE:
- case AV_CODEC_ID_PCM_F32BE: size = 4; break;
- case AV_CODEC_ID_PCM_F64LE:
- case AV_CODEC_ID_PCM_F64BE: size = 8; break;
- default: return AVERROR(ENOSYS);
- }
-
- if (layout == AV_CH_LAYOUT_5POINT0_BACK || layout == AV_CH_LAYOUT_5POINT0)
- PICK_REORDER(50)
- else if (layout == AV_CH_LAYOUT_5POINT1_BACK || layout == AV_CH_LAYOUT_5POINT1)
- PICK_REORDER(51)
- else if (layout == AV_CH_LAYOUT_7POINT1)
- PICK_REORDER(71)
-
- return s->reorder_func ? 0 : AVERROR(ENOSYS);
-}
-
av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
unsigned int *sample_rate,
int channels, enum AVCodecID *codec_id)
@@ -268,8 +169,10 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
snd_pcm_hw_params_free(hw_params);
- if (channels > 2 && layout) {
- if (find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) {
+ res = ff_alsa_reorder_find(&s->reorder_func, *codec_id, channels, layout,
+ mode == SND_PCM_STREAM_PLAYBACK);
+ /* TODO reindent */
+ if (res < 0) {
char name[128];
av_get_channel_layout_string(name, sizeof(name), channels, layout);
av_log(ctx, AV_LOG_WARNING, "ALSA channel layout unknown or unimplemented for %s %s.\n",
@@ -281,7 +184,6 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
if (!s->reorder_buf)
goto fail1;
}
- }
s->h = h;
return 0;
diff --git a/libavdevice/alsa-audio.h b/libavdevice/alsa-audio.h
index 44b7c72..a7783bd 100644
--- a/libavdevice/alsa-audio.h
+++ b/libavdevice/alsa-audio.h
@@ -35,6 +35,7 @@
#include "libavutil/log.h"
#include "timefilter.h"
#include "avdevice.h"
+#include "alsa_reorder.h"
/* XXX: we make the assumption that the soundcard accepts this format */
/* XXX: find better solution with "preinit" method, needed also in
@@ -54,7 +55,7 @@ typedef struct AlsaData {
int channels; ///< number of channels set by user
int last_period;
TimeFilter *timefilter;
- void (*reorder_func)(const void *, void *, int);
+ FFAlsaReorderFunc reorder_func;
void *reorder_buf;
int reorder_buf_size; ///< in frames
} AlsaData;
diff --git a/libavdevice/alsa_reorder.c b/libavdevice/alsa_reorder.c
new file mode 100644
index 0000000..768601e
--- /dev/null
+++ b/libavdevice/alsa_reorder.c
@@ -0,0 +1,126 @@
+/*
+ * ALSA channels reordering
+ * Copyright (c) 2013 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 "libavutil/avassert.h"
+#include "alsa_reorder.h"
+
+#define MAKE_REORDER_FUNC(NAME, TYPE, CHANNELS, LAYOUT, MAP) \
+static void alsa_reorder_ ## NAME ## _ ## LAYOUT(const void *in_v, \
+ void *out_v, \
+ int n) \
+{ \
+ const TYPE *in = in_v; \
+ TYPE *out = out_v; \
+ \
+ while (n-- > 0) { \
+ MAP \
+ in += CHANNELS; \
+ out += CHANNELS; \
+ } \
+}
+
+#define MAKE_REORDER_FUNCS(CHANNELS, LAYOUT, MAP) \
+ MAKE_REORDER_FUNC(int8, int8_t, CHANNELS, LAYOUT, MAP) \
+ MAKE_REORDER_FUNC(int16, int16_t, CHANNELS, LAYOUT, MAP) \
+ MAKE_REORDER_FUNC(int32, int32_t, CHANNELS, LAYOUT, MAP) \
+ MAKE_REORDER_FUNC(f64, double, CHANNELS, LAYOUT, MAP)
+
+MAKE_REORDER_FUNCS(5, out_50, \
+ out[0] = in[0]; \
+ out[1] = in[1]; \
+ out[2] = in[3]; \
+ out[3] = in[4]; \
+ out[4] = in[2]; \
+ );
+
+MAKE_REORDER_FUNCS(6, out_51, \
+ out[0] = in[0]; \
+ out[1] = in[1]; \
+ out[2] = in[4]; \
+ out[3] = in[5]; \
+ out[4] = in[2]; \
+ out[5] = in[3]; \
+ );
+
+MAKE_REORDER_FUNCS(8, out_71, \
+ out[0] = in[0]; \
+ out[1] = in[1]; \
+ out[2] = in[4]; \
+ out[3] = in[5]; \
+ out[4] = in[2]; \
+ out[5] = in[3]; \
+ out[6] = in[6]; \
+ out[7] = in[7]; \
+ );
+
+#define PICK_REORDER(layout)\
+switch(size) {\
+ case 1: *rf = alsa_reorder_int8_out_ ##layout; break;\
+ case 2: *rf = alsa_reorder_int16_out_ ##layout; break;\
+ case 4: *rf = alsa_reorder_int32_out_ ##layout; break;\
+ case 8: *rf = alsa_reorder_f64_out_ ##layout; break;\
+}
+
+int ff_alsa_reorder_find(FFAlsaReorderFunc *rf, enum AVCodecID codec,
+ int channels, uint64_t layout, int output)
+{
+ int size;
+
+ if (channels <= 2 || !layout)
+ return 0;
+
+ /* reordering input is not currently supported */
+ if (!output)
+ return AVERROR(ENOSYS);
+
+ /* reordering is not needed for QUAD or 2_2 layout */
+ if (layout == AV_CH_LAYOUT_QUAD || layout == AV_CH_LAYOUT_2_2)
+ return 0;
+
+ switch (codec) {
+ case AV_CODEC_ID_PCM_S8:
+ case AV_CODEC_ID_PCM_U8:
+ case AV_CODEC_ID_PCM_ALAW:
+ case AV_CODEC_ID_PCM_MULAW: size = 1; break;
+ case AV_CODEC_ID_PCM_S16LE:
+ case AV_CODEC_ID_PCM_S16BE:
+ case AV_CODEC_ID_PCM_U16LE:
+ case AV_CODEC_ID_PCM_U16BE: size = 2; break;
+ case AV_CODEC_ID_PCM_S32LE:
+ case AV_CODEC_ID_PCM_S32BE:
+ case AV_CODEC_ID_PCM_U32LE:
+ case AV_CODEC_ID_PCM_U32BE:
+ case AV_CODEC_ID_PCM_F32LE:
+ case AV_CODEC_ID_PCM_F32BE: size = 4; break;
+ case AV_CODEC_ID_PCM_F64LE:
+ case AV_CODEC_ID_PCM_F64BE: size = 8; break;
+ default: return AVERROR(ENOSYS);
+ }
+
+ if (layout == AV_CH_LAYOUT_5POINT0_BACK || layout == AV_CH_LAYOUT_5POINT0)
+ PICK_REORDER(50)
+ else if (layout == AV_CH_LAYOUT_5POINT1_BACK || layout == AV_CH_LAYOUT_5POINT1)
+ PICK_REORDER(51)
+ else if (layout == AV_CH_LAYOUT_7POINT1)
+ PICK_REORDER(71)
+
+ return *rf ? 0 : AVERROR(ENOSYS);
+}
diff --git a/libavdevice/alsa_reorder.h b/libavdevice/alsa_reorder.h
new file mode 100644
index 0000000..96502b2
--- /dev/null
+++ b/libavdevice/alsa_reorder.h
@@ -0,0 +1,44 @@
+/*
+ * ALSA channels reordering
+ * Copyright (c) 2013 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
+ */
+
+#ifndef AVDEVICE_ALSA_REORDER_H
+#define AVDEVICE_ALSA_REORDER_H
+
+#include "libavcodec/avcodec.h"
+
+typedef void (*FFAlsaReorderFunc)(const void *, void *, int);
+
+/**
+ * Init a reorder context.
+ *
+ * @param rf reorder function
+ * @param codec PCM codec id of the data
+ * @param channels number of channels
+ * @param layout channel layout, either 0 or compatible with channels
+ * @param output 1 if reordering for output, 0 for input
+ * @param buf_size initial buffer size, in samples
+ * @param frame_size size of a single sample frame, in bytes
+ * @return 0 for success, or <0 error code
+ */
+int ff_alsa_reorder_find(FFAlsaReorderFunc *rf, enum AVCodecID codec,
+ int channels, uint64_t layout, int output);
+
+#endif /* AVDEVICE_ALSA_REORDER_H */
--
1.7.10.4
More information about the ffmpeg-devel
mailing list