You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
flacdec: split off channel decorrelation as flacdsp
Signed-off-by: Mans Rullgard <mans@mansr.com>
This commit is contained in:
@@ -158,7 +158,7 @@ OBJS-$(CONFIG_FFV1_DECODER) += ffv1.o rangecoder.o
|
|||||||
OBJS-$(CONFIG_FFV1_ENCODER) += ffv1.o rangecoder.o
|
OBJS-$(CONFIG_FFV1_ENCODER) += ffv1.o rangecoder.o
|
||||||
OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o
|
OBJS-$(CONFIG_FFVHUFF_DECODER) += huffyuv.o
|
||||||
OBJS-$(CONFIG_FFVHUFF_ENCODER) += 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_FLAC_ENCODER) += flacenc.o flacdata.o flac.o
|
||||||
OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o
|
OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o
|
||||||
OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o
|
OBJS-$(CONFIG_FLASHSV_ENCODER) += flashsvenc.o
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
#include "golomb.h"
|
#include "golomb.h"
|
||||||
#include "flac.h"
|
#include "flac.h"
|
||||||
#include "flacdata.h"
|
#include "flacdata.h"
|
||||||
|
#include "flacdsp.h"
|
||||||
|
|
||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -55,11 +56,12 @@ typedef struct FLACContext {
|
|||||||
|
|
||||||
int blocksize; ///< number of samples in the current frame
|
int blocksize; ///< number of samples in the current frame
|
||||||
int sample_shift; ///< shift required to make output samples 16-bit or 32-bit
|
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 ch_mode; ///< channel decorrelation type in the current frame
|
||||||
int got_streaminfo; ///< indicates if the STREAMINFO has been read
|
int got_streaminfo; ///< indicates if the STREAMINFO has been read
|
||||||
|
|
||||||
int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples
|
int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples
|
||||||
|
|
||||||
|
FLACDSPContext dsp;
|
||||||
} FLACContext;
|
} FLACContext;
|
||||||
|
|
||||||
static const int64_t flac_channel_layouts[6] = {
|
static const int64_t flac_channel_layouts[6] = {
|
||||||
@@ -105,11 +107,9 @@ static void flac_set_bps(FLACContext *s)
|
|||||||
if (s->bps > 16) {
|
if (s->bps > 16) {
|
||||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
|
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
|
||||||
s->sample_shift = 32 - s->bps;
|
s->sample_shift = 32 - s->bps;
|
||||||
s->is32 = 1;
|
|
||||||
} else {
|
} else {
|
||||||
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||||
s->sample_shift = 16 - s->bps;
|
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);
|
avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo);
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
flac_set_bps(s);
|
flac_set_bps(s);
|
||||||
|
ff_flacdsp_init(&s->dsp, avctx->sample_fmt);
|
||||||
s->got_streaminfo = 1;
|
s->got_streaminfo = 1;
|
||||||
|
|
||||||
avcodec_get_frame_defaults(&s->frame);
|
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]);
|
avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]);
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
|
flac_set_bps(s);
|
||||||
|
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
|
||||||
s->got_streaminfo = 1;
|
s->got_streaminfo = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -548,6 +551,7 @@ static int decode_frame(FLACContext *s)
|
|||||||
|
|
||||||
if (!s->got_streaminfo) {
|
if (!s->got_streaminfo) {
|
||||||
allocate_buffers(s);
|
allocate_buffers(s);
|
||||||
|
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt);
|
||||||
s->got_streaminfo = 1;
|
s->got_streaminfo = 1;
|
||||||
dump_headers(s->avctx, (FLACStreaminfo *)s);
|
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;
|
const uint8_t *buf = avpkt->data;
|
||||||
int buf_size = avpkt->size;
|
int buf_size = avpkt->size;
|
||||||
FLACContext *s = avctx->priv_data;
|
FLACContext *s = avctx->priv_data;
|
||||||
int i, j = 0, bytes_read = 0;
|
int bytes_read = 0;
|
||||||
int16_t *samples_16;
|
|
||||||
int32_t *samples_32;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*got_frame_ptr = 0;
|
*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");
|
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
samples_16 = (int16_t *)s->frame.data[0];
|
|
||||||
samples_32 = (int32_t *)s->frame.data[0];
|
|
||||||
|
|
||||||
#define DECORRELATE(left, right)\
|
s->dsp.decorrelate[s->ch_mode](s->frame.data, s->decoded, s->channels,
|
||||||
assert(s->channels == 2);\
|
s->blocksize, s->sample_shift);
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_read > buf_size) {
|
if (bytes_read > buf_size) {
|
||||||
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size);
|
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size);
|
||||||
|
49
libavcodec/flacdsp.c
Normal file
49
libavcodec/flacdsp.c
Normal 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
32
libavcodec/flacdsp.h
Normal 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 */
|
86
libavcodec/flacdsp_template.c
Normal file
86
libavcodec/flacdsp_template.c
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user