flacdec: split off channel decorrelation as flacdsp

Signed-off-by: Mans Rullgard <mans@mansr.com>
This commit is contained in:
Mans Rullgard 2012-06-17 15:10:40 +01:00
parent 296d0da8bd
commit 4a8528349f
5 changed files with 178 additions and 42 deletions

View File

@ -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

View File

@ -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);

49
libavcodec/flacdsp.c Normal file
View File

@ -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;
}
}

32
libavcodec/flacdsp.h Normal file
View File

@ -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 */

View File

@ -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;
}
}