summaryrefslogtreecommitdiff
path: root/libavcodec/wavpack.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2013-05-27 17:23:15 +0200
committerAnton Khirnov <anton@khirnov.net>2013-05-28 17:47:04 +0200
commit7d039e70a5ff23a7deaa866684d2e8872acc5169 (patch)
tree86e8540bfca268b9bd917692beb8e097a387368f /libavcodec/wavpack.c
parent78f75b6fa421dd39a715588e9487579f1ce5bada (diff)
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.
Diffstat (limited to 'libavcodec/wavpack.c')
-rw-r--r--libavcodec/wavpack.c35
1 files 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) {