flacdec: add planar output support

Signed-off-by: Mans Rullgard <mans@mansr.com>
This commit is contained in:
Mans Rullgard 2012-07-03 00:29:30 +01:00
parent e43f56b205
commit 784514a4a8
4 changed files with 91 additions and 27 deletions

View File

@ -104,10 +104,21 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx,
static void flac_set_bps(FLACContext *s) static void flac_set_bps(FLACContext *s)
{ {
if (s->bps > 16) { enum AVSampleFormat req = s->avctx->request_sample_fmt;
int need32 = s->bps > 16;
int want32 = av_get_bytes_per_sample(req) > 2;
int planar = av_sample_fmt_is_planar(req);
if (need32 || want32) {
if (planar)
s->avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
else
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;
} else { } else {
if (planar)
s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
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;
} }
@ -132,7 +143,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); ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps);
s->got_streaminfo = 1; s->got_streaminfo = 1;
avcodec_get_frame_defaults(&s->frame); avcodec_get_frame_defaults(&s->frame);
@ -233,7 +244,7 @@ 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); flac_set_bps(s);
ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt); ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
s->got_streaminfo = 1; s->got_streaminfo = 1;
return 0; return 0;
@ -492,9 +503,11 @@ static int decode_frame(FLACContext *s)
"supported\n"); "supported\n");
return -1; return -1;
} }
s->bps = s->avctx->bits_per_raw_sample = fi.bps;
if (!s->bps) {
s->bps = s->avctx->bits_per_raw_sample = fi.bps;
flac_set_bps(s); flac_set_bps(s);
}
if (!s->max_blocksize) if (!s->max_blocksize)
s->max_blocksize = FLAC_MAX_BLOCKSIZE; s->max_blocksize = FLAC_MAX_BLOCKSIZE;
@ -520,7 +533,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); ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps);
s->got_streaminfo = 1; s->got_streaminfo = 1;
dump_headers(s->avctx, (FLACStreaminfo *)s); dump_headers(s->avctx, (FLACStreaminfo *)s);
} }
@ -628,4 +641,9 @@ AVCodec ff_flac_decoder = {
.decode = flac_decode_frame, .decode = flac_decode_frame,
.capabilities = CODEC_CAP_DR1, .capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_S16P,
AV_SAMPLE_FMT_S32,
AV_SAMPLE_FMT_S32P,
-1 },
}; };

View File

@ -23,10 +23,21 @@
#include "flacdsp.h" #include "flacdsp.h"
#define SAMPLE_SIZE 16 #define SAMPLE_SIZE 16
#define PLANAR 0
#include "flacdsp_template.c"
#undef PLANAR
#define PLANAR 1
#include "flacdsp_template.c" #include "flacdsp_template.c"
#undef SAMPLE_SIZE #undef SAMPLE_SIZE
#undef PLANAR
#define SAMPLE_SIZE 32 #define SAMPLE_SIZE 32
#define PLANAR 0
#include "flacdsp_template.c"
#undef PLANAR
#define PLANAR 1
#include "flacdsp_template.c" #include "flacdsp_template.c"
static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32], static void flac_lpc_16_c(int32_t *decoded, const int coeffs[32],
@ -72,15 +83,27 @@ static void flac_lpc_32_c(int32_t *decoded, const int coeffs[32],
} }
av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt) av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt,
int bps)
{ {
if (bps > 16)
c->lpc = flac_lpc_32_c;
else
c->lpc = flac_lpc_16_c;
switch (fmt) { switch (fmt) {
case AV_SAMPLE_FMT_S32: case AV_SAMPLE_FMT_S32:
c->decorrelate[0] = flac_decorrelate_indep_c_32; c->decorrelate[0] = flac_decorrelate_indep_c_32;
c->decorrelate[1] = flac_decorrelate_ls_c_32; c->decorrelate[1] = flac_decorrelate_ls_c_32;
c->decorrelate[2] = flac_decorrelate_rs_c_32; c->decorrelate[2] = flac_decorrelate_rs_c_32;
c->decorrelate[3] = flac_decorrelate_ms_c_32; c->decorrelate[3] = flac_decorrelate_ms_c_32;
c->lpc = flac_lpc_32_c; break;
case AV_SAMPLE_FMT_S32P:
c->decorrelate[0] = flac_decorrelate_indep_c_32p;
c->decorrelate[1] = flac_decorrelate_ls_c_32p;
c->decorrelate[2] = flac_decorrelate_rs_c_32p;
c->decorrelate[3] = flac_decorrelate_ms_c_32p;
break; break;
case AV_SAMPLE_FMT_S16: case AV_SAMPLE_FMT_S16:
@ -88,7 +111,13 @@ av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt)
c->decorrelate[1] = flac_decorrelate_ls_c_16; c->decorrelate[1] = flac_decorrelate_ls_c_16;
c->decorrelate[2] = flac_decorrelate_rs_c_16; c->decorrelate[2] = flac_decorrelate_rs_c_16;
c->decorrelate[3] = flac_decorrelate_ms_c_16; c->decorrelate[3] = flac_decorrelate_ms_c_16;
c->lpc = flac_lpc_16_c; break;
case AV_SAMPLE_FMT_S16P:
c->decorrelate[0] = flac_decorrelate_indep_c_16p;
c->decorrelate[1] = flac_decorrelate_ls_c_16p;
c->decorrelate[2] = flac_decorrelate_rs_c_16p;
c->decorrelate[3] = flac_decorrelate_ms_c_16p;
break; break;
} }
} }

View File

@ -29,6 +29,6 @@ typedef struct FLACDSPContext {
int qlevel, int len); int qlevel, int len);
} FLACDSPContext; } FLACDSPContext;
void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt); void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int bps);
#endif /* AVCODEC_FLACDSP_H */ #endif /* AVCODEC_FLACDSP_H */

View File

@ -19,68 +19,85 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include "libavutil/avutil.h"
#undef FUNC #undef FUNC
#undef FSUF
#undef sample #undef sample
#undef sample_type
#undef OUT
#undef S
#if SAMPLE_SIZE == 32 #if SAMPLE_SIZE == 32
# define FUNC(n) n ## _32 # define sample_type int32_t
# define sample int32_t
#else #else
# define FUNC(n) n ## _16 # define sample_type int16_t
# define sample int16_t
#endif #endif
#if PLANAR
# define FSUF AV_JOIN(SAMPLE_SIZE, p)
# define sample sample_type *
# define OUT(n) n
# define S(s, c, i) (s[c][i])
#else
# define FSUF SAMPLE_SIZE
# define sample sample_type
# define OUT(n) n[0]
# define S(s, c, i) (*s++)
#endif
#define FUNC(n) AV_JOIN(n ## _, FSUF)
static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in, static void FUNC(flac_decorrelate_indep_c)(uint8_t **out, int32_t **in,
int channels, int len, int shift) int channels, int len, int shift)
{ {
sample *samples = (sample *) out[0]; sample *samples = (sample *) OUT(out);
int i, j; int i, j;
for (j = 0; j < len; j++) for (j = 0; j < len; j++)
for (i = 0; i < channels; i++) for (i = 0; i < channels; i++)
*samples++ = in[i][j] << shift; S(samples, i, j) = in[i][j] << shift;
} }
static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in, static void FUNC(flac_decorrelate_ls_c)(uint8_t **out, int32_t **in,
int channels, int len, int shift) int channels, int len, int shift)
{ {
sample *samples = (sample *) out[0]; sample *samples = (sample *) OUT(out);
int i; int i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int a = in[0][i]; int a = in[0][i];
int b = in[1][i]; int b = in[1][i];
*samples++ = a << shift; S(samples, 0, i) = a << shift;
*samples++ = (a - b) << shift; S(samples, 1, i) = (a - b) << shift;
} }
} }
static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in, static void FUNC(flac_decorrelate_rs_c)(uint8_t **out, int32_t **in,
int channels, int len, int shift) int channels, int len, int shift)
{ {
sample *samples = (sample *) out[0]; sample *samples = (sample *) OUT(out);
int i; int i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int a = in[0][i]; int a = in[0][i];
int b = in[1][i]; int b = in[1][i];
*samples++ = (a + b) << shift; S(samples, 0, i) = (a + b) << shift;
*samples++ = b << shift; S(samples, 1, i) = b << shift;
} }
} }
static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in, static void FUNC(flac_decorrelate_ms_c)(uint8_t **out, int32_t **in,
int channels, int len, int shift) int channels, int len, int shift)
{ {
sample *samples = (sample *) out[0]; sample *samples = (sample *) OUT(out);
int i; int i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int a = in[0][i]; int a = in[0][i];
int b = in[1][i]; int b = in[1][i];
a -= b >> 1; a -= b >> 1;
*samples++ = (a + b) << shift; S(samples, 0, i) = (a + b) << shift;
*samples++ = a << shift; S(samples, 1, i) = a << shift;
} }
} }