Signed-off-by: Mans Rullgard <mans@mansr.com>tags/n1.0
| @@ -104,11 +104,22 @@ int avpriv_flac_is_extradata_valid(AVCodecContext *avctx, | |||
| static void flac_set_bps(FLACContext *s) | |||
| { | |||
| if (s->bps > 16) { | |||
| s->avctx->sample_fmt = AV_SAMPLE_FMT_S32; | |||
| 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->sample_shift = 32 - s->bps; | |||
| } else { | |||
| s->avctx->sample_fmt = AV_SAMPLE_FMT_S16; | |||
| if (planar) | |||
| s->avctx->sample_fmt = AV_SAMPLE_FMT_S16P; | |||
| else | |||
| s->avctx->sample_fmt = AV_SAMPLE_FMT_S16; | |||
| 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); | |||
| allocate_buffers(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; | |||
| 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]); | |||
| allocate_buffers(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; | |||
| return 0; | |||
| @@ -492,9 +503,11 @@ static int decode_frame(FLACContext *s) | |||
| "supported\n"); | |||
| return -1; | |||
| } | |||
| s->bps = s->avctx->bits_per_raw_sample = fi.bps; | |||
| flac_set_bps(s); | |||
| if (!s->bps) { | |||
| s->bps = s->avctx->bits_per_raw_sample = fi.bps; | |||
| flac_set_bps(s); | |||
| } | |||
| if (!s->max_blocksize) | |||
| s->max_blocksize = FLAC_MAX_BLOCKSIZE; | |||
| @@ -520,7 +533,7 @@ static int decode_frame(FLACContext *s) | |||
| if (!s->got_streaminfo) { | |||
| 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; | |||
| dump_headers(s->avctx, (FLACStreaminfo *)s); | |||
| } | |||
| @@ -628,4 +641,9 @@ AVCodec ff_flac_decoder = { | |||
| .decode = flac_decode_frame, | |||
| .capabilities = CODEC_CAP_DR1, | |||
| .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 }, | |||
| }; | |||
| @@ -23,10 +23,21 @@ | |||
| #include "flacdsp.h" | |||
| #define SAMPLE_SIZE 16 | |||
| #define PLANAR 0 | |||
| #include "flacdsp_template.c" | |||
| #undef PLANAR | |||
| #define PLANAR 1 | |||
| #include "flacdsp_template.c" | |||
| #undef SAMPLE_SIZE | |||
| #undef PLANAR | |||
| #define SAMPLE_SIZE 32 | |||
| #define PLANAR 0 | |||
| #include "flacdsp_template.c" | |||
| #undef PLANAR | |||
| #define PLANAR 1 | |||
| #include "flacdsp_template.c" | |||
| 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) { | |||
| 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; | |||
| 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; | |||
| 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[2] = flac_decorrelate_rs_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; | |||
| } | |||
| } | |||
| @@ -29,6 +29,6 @@ typedef struct FLACDSPContext { | |||
| int qlevel, int len); | |||
| } 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 */ | |||
| @@ -19,68 +19,85 @@ | |||
| */ | |||
| #include <stdint.h> | |||
| #include "libavutil/avutil.h" | |||
| #undef FUNC | |||
| #undef FSUF | |||
| #undef sample | |||
| #undef sample_type | |||
| #undef OUT | |||
| #undef S | |||
| #if SAMPLE_SIZE == 32 | |||
| # define FUNC(n) n ## _32 | |||
| # define sample int32_t | |||
| # define sample_type int32_t | |||
| #else | |||
| # define FUNC(n) n ## _16 | |||
| # define sample int16_t | |||
| # define sample_type int16_t | |||
| #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, | |||
| int channels, int len, int shift) | |||
| { | |||
| sample *samples = (sample *) out[0]; | |||
| sample *samples = (sample *) OUT(out); | |||
| int i, j; | |||
| for (j = 0; j < len; j++) | |||
| 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, | |||
| int channels, int len, int shift) | |||
| { | |||
| sample *samples = (sample *) out[0]; | |||
| sample *samples = (sample *) OUT(out); | |||
| 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; | |||
| S(samples, 0, i) = a << shift; | |||
| S(samples, 1, i) = (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]; | |||
| sample *samples = (sample *) OUT(out); | |||
| 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; | |||
| S(samples, 0, i) = (a + b) << shift; | |||
| S(samples, 1, i) = 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]; | |||
| sample *samples = (sample *) OUT(out); | |||
| 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; | |||
| S(samples, 0, i) = (a + b) << shift; | |||
| S(samples, 1, i) = a << shift; | |||
| } | |||
| } | |||