+ avctx->sample_rate = sample_rate;
+ } 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) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+ }
+
+ if (wc->ch_offset + s->stereo >= avctx->channels) {
+ av_log(avctx, AV_LOG_WARNING, "Too many channels coded in a packet.\n");
+ return (avctx->err_recognition & AV_EF_EXPLODE) ? AVERROR_INVALIDDATA : 0;
+ }
+
+ samples_l = frame->extended_data[wc->ch_offset];
+ if (s->stereo)
+ samples_r = frame->extended_data[wc->ch_offset + 1];
+
+ wc->ch_offset += 1 + s->stereo;
+
+ if (s->stereo_in) {
+ ret = wv_unpack_stereo(s, &s->gb, samples_l, samples_r, avctx->sample_fmt);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = wv_unpack_mono(s, &s->gb, samples_l, avctx->sample_fmt);
+ if (ret < 0)
+ return ret;
+
+ if (s->stereo)
+ memcpy(samples_r, samples_l, bpp * s->samples);
+ }
+
+ return 0;
+}
+
+static void wavpack_decode_flush(AVCodecContext *avctx)
+{
+ WavpackContext *s = avctx->priv_data;
+ int i;
+
+ for (i = 0; i < s->fdec_num; i++)
+ wv_reset_saved_context(s->fdec[i]);
+}
+
+static int wavpack_decode_frame(AVCodecContext *avctx, void *data,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ WavpackContext *s = avctx->priv_data;
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ AVFrame *frame = data;
+ int frame_size, ret, frame_flags;
+
+ if (avpkt->size <= WV_HEADER_SIZE)
+ return AVERROR_INVALIDDATA;
+
+ s->block = 0;
+ s->ch_offset = 0;
+
+ /* determine number of samples */
+ s->samples = AV_RL32(buf + 20);
+ frame_flags = AV_RL32(buf + 24);
+ if (s->samples <= 0) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid number of samples: %d\n",
+ s->samples);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (frame_flags & 0x80) {
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+ } else if ((frame_flags & 0x03) <= 1) {
+ avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
+ } else {
+ avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
+ avctx->bits_per_raw_sample = ((frame_flags & 0x03) + 1) << 3;
+ }
+
+ while (buf_size > 0) {
+ if (buf_size <= WV_HEADER_SIZE)
+ break;
+ frame_size = AV_RL32(buf + 4) - 12;
+ buf += 20;
+ buf_size -= 20;
+ if (frame_size <= 0 || frame_size > buf_size) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Block %d has invalid size (size %d vs. %d bytes left)\n",
+ s->block, frame_size, buf_size);
+ wavpack_decode_flush(avctx);
+ return AVERROR_INVALIDDATA;
+ }
+ if ((ret = wavpack_decode_block(avctx, s->block,
+ frame, buf, frame_size)) < 0) {
+ wavpack_decode_flush(avctx);
+ return ret;