X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavcodec%2Fflacdec.c;h=f273d145cb82818f79b3f75f4d17c52946e6b81e;hb=9e31729d692f1e721b7ed1a3a0f51b68c064d68f;hp=f3f1b3a2830ddc46c11a2125e536f2c49f4697f4;hpb=44c56a1617342287539c6070309868f431476e48;p=ffmpeg diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index f3f1b3a2830..f273d145cb8 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -33,7 +33,7 @@ #include -#include "libavutil/audioconvert.h" +#include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "avcodec.h" #include "internal.h" @@ -60,20 +60,13 @@ typedef struct FLACContext { int got_streaminfo; ///< indicates if the STREAMINFO has been read int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples + uint8_t *decoded_buffer; + unsigned int decoded_buffer_size; FLACDSPContext dsp; } FLACContext; -static const int64_t flac_channel_layouts[6] = { - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_QUAD, - AV_CH_LAYOUT_5POINT0, - AV_CH_LAYOUT_5POINT1 -}; - -static void allocate_buffers(FLACContext *s); +static int allocate_buffers(FLACContext *s); static void flac_set_bps(FLACContext *s) { @@ -101,6 +94,7 @@ static av_cold int flac_decode_init(AVCodecContext *avctx) { enum FLACExtradataFormat format; uint8_t *streaminfo; + int ret; FLACContext *s = avctx->priv_data; s->avctx = avctx; @@ -114,7 +108,9 @@ static av_cold int flac_decode_init(AVCodecContext *avctx) /* initialize based on the demuxer-supplied streamdata header */ avpriv_flac_parse_streaminfo(avctx, (FLACStreaminfo *)s, streaminfo); - allocate_buffers(s); + ret = allocate_buffers(s); + if (ret < 0) + return ret; flac_set_bps(s); ff_flacdsp_init(&s->dsp, avctx->sample_fmt, s->bps); s->got_streaminfo = 1; @@ -122,9 +118,6 @@ static av_cold int flac_decode_init(AVCodecContext *avctx) avcodec_get_frame_defaults(&s->frame); avctx->coded_frame = &s->frame; - if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts)) - avctx->channel_layout = flac_channel_layouts[avctx->channels - 1]; - return 0; } @@ -137,15 +130,24 @@ static void dump_headers(AVCodecContext *avctx, FLACStreaminfo *s) av_log(avctx, AV_LOG_DEBUG, " Bits: %d\n", s->bps); } -static void allocate_buffers(FLACContext *s) +static int allocate_buffers(FLACContext *s) { - int i; + int buf_size; assert(s->max_blocksize); - for (i = 0; i < s->channels; i++) { - s->decoded[i] = av_malloc(sizeof(int32_t)*s->max_blocksize); - } + buf_size = av_samples_get_buffer_size(NULL, s->channels, s->max_blocksize, + AV_SAMPLE_FMT_S32P, 0); + if (buf_size < 0) + return buf_size; + + av_fast_malloc(&s->decoded_buffer, &s->decoded_buffer_size, buf_size); + if (!s->decoded_buffer) + return AVERROR(ENOMEM); + + return av_samples_fill_arrays((uint8_t **)s->decoded, NULL, + s->decoded_buffer, s->channels, + s->max_blocksize, AV_SAMPLE_FMT_S32P, 0); } /** @@ -157,7 +159,7 @@ static void allocate_buffers(FLACContext *s) */ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size) { - int metadata_type, metadata_size; + int metadata_type, metadata_size, ret; if (buf_size < FLAC_STREAMINFO_SIZE+8) { /* need more data */ @@ -169,7 +171,9 @@ static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size) return AVERROR_INVALIDDATA; } avpriv_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, &buf[8]); - allocate_buffers(s); + ret = allocate_buffers(s); + if (ret < 0) + return ret; flac_set_bps(s); ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps); s->got_streaminfo = 1; @@ -371,8 +375,8 @@ static inline int decode_subframe(FLACContext *s, int channel) bps -= wasted; } if (bps > 32) { - av_log_missing_feature(s->avctx, "decorrelated bit depth > 32", 0); - return -1; + av_log_missing_feature(s->avctx, "Decorrelated bit depth > 32", 0); + return AVERROR_PATCHWELCOME; } //FIXME use av_log2 for types @@ -405,7 +409,7 @@ static inline int decode_subframe(FLACContext *s, int channel) static int decode_frame(FLACContext *s) { - int i; + int i, ret; GetBitContext *gb = &s->gb; FLACFrameInfo fi; @@ -414,12 +418,16 @@ static int decode_frame(FLACContext *s) return -1; } - if (s->channels && fi.channels != s->channels) { - av_log(s->avctx, AV_LOG_ERROR, "switching channel layout mid-stream " - "is not supported\n"); - return -1; + if (s->channels && fi.channels != s->channels && s->got_streaminfo) { + s->channels = s->avctx->channels = fi.channels; + ff_flac_set_channel_layout(s->avctx); + ret = allocate_buffers(s); + if (ret < 0) + return ret; } s->channels = s->avctx->channels = fi.channels; + if (!s->avctx->channel_layout) + ff_flac_set_channel_layout(s->avctx); s->ch_mode = fi.ch_mode; if (!s->bps && !fi.bps) { @@ -453,16 +461,14 @@ static int decode_frame(FLACContext *s) " or frame header\n"); return -1; } - if (fi.samplerate == 0) { + if (fi.samplerate == 0) fi.samplerate = s->samplerate; - } else if (s->samplerate && fi.samplerate != s->samplerate) { - av_log(s->avctx, AV_LOG_WARNING, "sample rate changed from %d to %d\n", - s->samplerate, fi.samplerate); - } s->samplerate = s->avctx->sample_rate = fi.samplerate; if (!s->got_streaminfo) { - allocate_buffers(s); + ret = allocate_buffers(s); + if (ret < 0) + return ret; ff_flacdsp_init(&s->dsp, s->avctx->sample_fmt, s->bps); s->got_streaminfo = 1; dump_headers(s->avctx, (FLACStreaminfo *)s); @@ -526,7 +532,7 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ s->frame.nb_samples = s->blocksize; - if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) { + if ((ret = ff_get_buffer(avctx, &s->frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } @@ -552,11 +558,8 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data, static av_cold int flac_decode_close(AVCodecContext *avctx) { FLACContext *s = avctx->priv_data; - int i; - for (i = 0; i < s->channels; i++) { - av_freep(&s->decoded[i]); - } + av_freep(&s->decoded_buffer); return 0; }