From 4a8528349f897fba72e6eb41400aca3ca4605a79 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 17 Jun 2012 15:10:40 +0100 Subject: [PATCH] flacdec: split off channel decorrelation as flacdsp Signed-off-by: Mans Rullgard --- libavcodec/Makefile | 2 +- libavcodec/flacdec.c | 53 +++++---------------- libavcodec/flacdsp.c | 49 ++++++++++++++++++++ libavcodec/flacdsp.h | 32 +++++++++++++ libavcodec/flacdsp_template.c | 86 +++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 43 deletions(-) create mode 100644 libavcodec/flacdsp.c create mode 100644 libavcodec/flacdsp.h create mode 100644 libavcodec/flacdsp_template.c 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 @@ -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 + * + * 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 +#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 + * + * 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 + +#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; + } +}