From 7d039e70a5ff23a7deaa866684d2e8872acc5169 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 27 May 2013 17:23:15 +0200 Subject: [PATCH] wavpack: extract channel information from the bitstream This way we don't require the caller to parse the block header. It also allows the channel configuration to change mid-stream. --- libavcodec/wavpack.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index 4006d47462..9c766ca181 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -43,6 +43,10 @@ #define WV_HYBRID_SHAPE 0x00000008 #define WV_HYBRID_BITRATE 0x00000200 #define WV_HYBRID_BALANCE 0x00000400 +#define WV_INITIAL_BLOCK 0x00000800 +#define WV_FINAL_BLOCK 0x00001000 + +#define WV_SINGLE_BLOCK (WV_INITIAL_BLOCK | WV_FINAL_BLOCK) #define WV_FLT_SHIFT_ONES 0x01 #define WV_FLT_SHIFT_SAME 0x02 @@ -135,7 +139,6 @@ typedef struct WavpackContext { WavpackFrameContext *fdec[WV_MAX_FRAME_DECODERS]; int fdec_num; - int multichannel; int block; int samples; int ch_offset; @@ -724,12 +727,6 @@ static av_cold int wavpack_decode_init(AVCodecContext *avctx) s->avctx = avctx; - if (avctx->channels <= 2 && !avctx->channel_layout) - avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO - : AV_CH_LAYOUT_MONO; - - s->multichannel = avctx->channels > 2; - s->fdec_num = 0; return 0; @@ -758,7 +755,8 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0, got_float = 0, got_hybrid = 0; int i, j, id, size, ssize, weights, t; - int bpp, chan, chmask, orig_bpp, sample_rate = 0; + int bpp, chan = 0, chmask = 0, orig_bpp, sample_rate = 0; + int multiblock; if (block_no >= wc->fdec_num && wv_alloc_frame_context(wc) < 0) { av_log(avctx, AV_LOG_ERROR, "Error creating frame decode context\n"); @@ -789,6 +787,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, s->frame_flags = bytestream2_get_le32(&gb); bpp = av_get_bytes_per_sample(avctx->sample_fmt); orig_bpp = ((s->frame_flags & 0x03) + 1) << 3; + multiblock = (s->frame_flags & WV_SINGLE_BLOCK) != WV_SINGLE_BLOCK; s->stereo = !(s->frame_flags & WV_MONO); s->stereo_in = (s->frame_flags & WV_FALSE_STEREO) ? 0 : s->stereo; @@ -1039,15 +1038,6 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, chan = avctx->channels; chmask = avctx->channel_layout; } - if (chan != avctx->channels) { - av_log(avctx, AV_LOG_ERROR, - "Block reports total %d channels, " - "decoder believes it's %d channels\n", - chan, avctx->channels); - return AVERROR_INVALIDDATA; - } - if (!avctx->channel_layout) - avctx->channel_layout = chmask; break; case WP_ID_SAMPLE_RATE: if (size != 3) { @@ -1111,6 +1101,17 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } else avctx->sample_rate = wv_rates[sr]; + if (multiblock) { + if (chan) + avctx->channels = chan; + if (chmask) + avctx->channel_layout = chmask; + } else { + avctx->channels = s->stereo ? 2 : 1; + avctx->channel_layout = s->stereo ? AV_CH_LAYOUT_STEREO : + AV_CH_LAYOUT_MONO; + } + /* get output buffer */ frame->nb_samples = s->samples; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { -- 2.11.0