summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMans Rullgard <mans@mansr.com>2012-06-17 15:10:40 +0100
committerMans Rullgard <mans@mansr.com>2012-07-04 12:24:30 +0100
commit4a8528349f897fba72e6eb41400aca3ca4605a79 (patch)
tree4110f809093767578d281eb5900929e5199c8a3f
parent296d0da8bd3b5bc5220a3b062d387bf9fa4584c5 (diff)
flacdec: split off channel decorrelation as flacdsp
Signed-off-by: Mans Rullgard <mans@mansr.com>
-rw-r--r--libavcodec/Makefile2
-rw-r--r--libavcodec/flacdec.c53
-rw-r--r--libavcodec/flacdsp.c49
-rw-r--r--libavcodec/flacdsp.h32
-rw-r--r--libavcodec/flacdsp_template.c86
5 files changed, 179 insertions, 43 deletions
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index efedee90fc..b23bc29891 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -158,7 +158,7 @@ OBJS-$(CONFIG_FFV1_DECODER) += ffv1.o rangecoder.o
OBJS-$(CONFIG_FFV1_ENCODER) += ffv1.o rangecoder.o
OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o
OBJS-$(CONFIG_FFVHUFF_ENCODER) += huffyuv.o
-OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o
+OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o flacdsp.o
OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o
OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o
OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o
diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index ca6b4f2dec..daa5bd8daf 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -42,6 +42,7 @@
#include "golomb.h"
#include "flac.h"
#include "flacdata.h"
+#include "flacdsp.h"
#undef NDEBUG
#include <assert.h>
@@ -55,11 +56,12 @@ typedef struct FLACContext {
int blocksize; ///< number of samples in the current frame
int sample_shift; ///< shift required to make output samples 16-bit or 32-bit
- int is32; ///< flag to indicate if output should be 32-bit instead of 16-bit
int ch_mode; ///< channel decorrelation type in the current frame
int got_streaminfo; ///< indicates if the STREAMINFO has been read
int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples
+
+ FLACDSPContext dsp;
} FLACContext;
static const int64_t flac_channel_layouts[6] = {
@@ -105,11 +107,9 @@ static void flac_set_bps(FLACContext *s)
if (s->bps > 16) {
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
s->sample_shift = 32 - s->bps;
- s->is32 = 1;
} else {
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
s->sample_shift = 16 - s->bps;
- s->is32 = 0;
}
}
@@ -132,6 +132,7 @@ static av_cold int flac_decode_init(AVCodecContext *avctx)
avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
allocate_buffers(s);
flac_set_bps(s);
+ ff_flacdsp_init(&s->dsp, avctx->sample_fmt);
s->got_streaminfo = 1;
avcodec_get_frame_defaults(&s->frame);
@@ -231,6 +232,8 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
}
avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
allocate_buffers(s);
+ flac_set_bps(s);
+ ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
s->got_streaminfo = 1;
return 0;
@@ -548,6 +551,7 @@ static int decode_frame(FLACContext *s)
if (!s->got_streaminfo) {
allocate_buffers(s);
+ ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
s->got_streaminfo = 1;
dump_headers(s->avctx, (FLACStreaminfo *)s);
}
@@ -574,9 +578,7 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data,
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
FLACContext *s = avctx->priv_data;
- int i, j = 0, bytes_read = 0;
- int16_t *samples_16;
- int32_t *samples_32;
+ int bytes_read = 0;
int ret;
*got_frame_ptr = 0;
@@ -616,42 +618,9 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
- samples_16 = (int16_t *)s->frame.data[0];
- samples_32 = (int32_t *)s->frame.data[0];
-
-#define DECORRELATE(left, right)\
- assert(s->channels == 2);\
- for (i = 0; i < s->blocksize; i++) {\
- int a= s->decoded[0][i];\
- int b= s->decoded[1][i];\
- if (s->is32) {\
- *samples_32++ = (left) << s->sample_shift;\
- *samples_32++ = (right) << s->sample_shift;\
- } else {\
- *samples_16++ = (left) << s->sample_shift;\
- *samples_16++ = (right) << s->sample_shift;\
- }\
- }\
- break;
-
- switch (s->ch_mode) {
- case FLAC_CHMODE_INDEPENDENT:
- for (j = 0; j < s->blocksize; j++) {
- for (i = 0; i < s->channels; i++) {
- if (s->is32)
- *samples_32++ = s->decoded[i][j] << s->sample_shift;
- else
- *samples_16++ = s->decoded[i][j] << s->sample_shift;
- }
- }
- break;
- case FLAC_CHMODE_LEFT_SIDE:
- DECORRELATE(a,a-b)
- case FLAC_CHMODE_RIGHT_SIDE:
- DECORRELATE(a+b,b)
- case FLAC_CHMODE_MID_SIDE:
- DECORRELATE( (a-=b>>1) + b, a)
- }
+
+ s->dsp.decorrelate[s->ch_mode](s->frame.data, s->decoded, s->channels,
+ s->blocksize, s->sample_shift);
if (bytes_read > buf_size) {
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size);
diff --git a/libavcodec/flacdsp.c b/libavcodec/flacdsp.c
new file mode 100644
index 0000000000..b7e074644e
--- /dev/null
+++ b/libavcodec/flacdsp.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2012 Mans Rullgard <mans@mansr.com>
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/attributes.h"
+#include "libavutil/samplefmt.h"
+#include "flacdsp.h"
+
+#define SAMPLE_SIZE 16
+#include "flacdsp_template.c"
+
+#undef SAMPLE_SIZE
+#define SAMPLE_SIZE 32
+#include "flacdsp_template.c"
+
+av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt)
+{
+ switch (fmt) {
+ case AV_SAMPLE_FMT_S32:
+ c->decorrelate[0] = flac_decorrelate_indep_c_32;
+ c->decorrelate[1] = flac_decorrelate_ls_c_32;
+ c->decorrelate[2] = flac_decorrelate_rs_c_32;
+ c->decorrelate[3] = flac_decorrelate_ms_c_32;
+ break;
+
+ case AV_SAMPLE_FMT_S16:
+ c->decorrelate[0] = flac_decorrelate_indep_c_16;
+ c->decorrelate[1] = flac_decorrelate_ls_c_16;
+ c->decorrelate[2] = flac_decorrelate_rs_c_16;
+ c->decorrelate[3] = flac_decorrelate_ms_c_16;
+ break;
+ }
+}
diff --git a/libavcodec/flacdsp.h b/libavcodec/flacdsp.h
new file mode 100644
index 0000000000..bb289eea13
--- /dev/null
+++ b/libavcodec/flacdsp.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_FLACDSP_H
+#define AVCODEC_FLACDSP_H
+
+#include <stdint.h>
+#include "libavutil/samplefmt.h"
+
+typedef struct FLACDSPContext {
+ void (*decorrelate[4])(uint8_t **out, int32_t **in, int channels,
+ int len, int shift);
+} FLACDSPContext;
+
+void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt);
+
+#endif /* AVCODEC_FLACDSP_H */
diff --git a/libavcodec/flacdsp_template.c b/libavcodec/flacdsp_template.c
new file mode 100644
index 0000000000..34da5a6d25
--- /dev/null
+++ b/libavcodec/flacdsp_template.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012 Mans Rullgard <mans@mansr.com>
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+
+#undef FUNC
+#undef sample
+
+#if SAMPLE_SIZE == 32
+# define FUNC(n) n ## _32
+# define sample int32_t
+#else
+# define FUNC(n) n ## _16
+# define sample int16_t
+#endif
+
+static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in,
+ int channels, int len, int shift)
+{
+ sample *samples = (sample *) out[0];
+ int i, j;
+
+ for (j = 0; j < len; j++)
+ for (i = 0; i < channels; i++)
+ *samples++ = in[i][j] << shift;
+}
+
+static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in,
+ int channels, int len, int shift)
+{
+ sample *samples = (sample *) out[0];
+ int i;
+
+ for (i = 0; i < len; i++) {
+ int a = in[0][i];
+ int b = in[1][i];
+ *samples++ = a << shift;
+ *samples++ = (a - b) << shift;
+ }
+}
+
+static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in,
+ int channels, int len, int shift)
+{
+ sample *samples = (sample *) out[0];
+ int i;
+
+ for (i = 0; i < len; i++) {
+ int a = in[0][i];
+ int b = in[1][i];
+ *samples++ = (a + b) << shift;
+ *samples++ = b << shift;
+ }
+}
+
+static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in,
+ int channels, int len, int shift)
+{
+ sample *samples = (sample *) out[0];
+ int i;
+
+ for (i = 0; i < len; i++) {
+ int a = in[0][i];
+ int b = in[1][i];
+ a -= b >> 1;
+ *samples++ = (a + b) << shift;
+ *samples++ = a << shift;
+ }
+}