#define BITSTREAM_READER_LE
-#include "libavutil/audioconvert.h"
+#include "libavutil/channel_layout.h"
#include "avcodec.h"
#include "get_bits.h"
+#include "internal.h"
#include "unary.h"
/**
int extra_bits;
int and, or, shift;
int post_shift;
- int hybrid, hybrid_bitrate, hybrid_maxclip;
+ int hybrid, hybrid_bitrate;
+ int hybrid_maxclip, hybrid_minclip;
int float_flag;
int float_shift;
int float_max_exp;
}
bit = (S & s->and) | s->or;
- bit = (((S + bit) << s->shift) - bit) << s->post_shift;
+ bit = ((S + bit) << s->shift) - bit;
if (s->hybrid)
- bit = av_clip(bit, -s->hybrid_maxclip - 1, s->hybrid_maxclip);
+ bit = av_clip(bit, s->hybrid_minclip, s->hybrid_maxclip);
- return bit;
+ return bit << s->post_shift;
}
static float wv_get_value_float(WavpackFrameContext *s, uint32_t *crc, int S)
uint32_t u;
} value;
- int sign;
+ unsigned int sign;
int exp = s->float_max_exp;
if (s->got_extra_bits) {
s->sc.crc = s->extra_sc.crc = 0xFFFFFFFF;
}
+static inline int wv_check_crc(WavpackFrameContext *s, uint32_t crc,
+ uint32_t crc_extra_bits)
+{
+ if (crc != s->CRC) {
+ av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
+ return AVERROR_INVALIDDATA;
+ }
+ if (s->got_extra_bits && crc_extra_bits != s->crc_extra_bits) {
+ av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
static inline int wv_unpack_stereo(WavpackFrameContext *s, GetBitContext *gb,
void *dst, const int type)
{
} while (!last && count < s->samples);
wv_reset_saved_context(s);
- if (crc != s->CRC) {
- av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
- return -1;
- }
- if (s->got_extra_bits && crc_extra_bits != s->crc_extra_bits) {
- av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
- return -1;
- }
+ if ((s->avctx->err_recognition & AV_EF_CRCCHECK) &&
+ wv_check_crc(s, crc, crc_extra_bits))
+ return AVERROR_INVALIDDATA;
return count * 2;
}
} while (!last && count < s->samples);
wv_reset_saved_context(s);
- if (crc != s->CRC) {
- av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
- return -1;
- }
- if (s->got_extra_bits && crc_extra_bits != s->crc_extra_bits) {
- av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
- return -1;
- }
+ if ((s->avctx->err_recognition & AV_EF_CRCCHECK) &&
+ wv_check_crc(s, crc, crc_extra_bits))
+ return AVERROR_INVALIDDATA;
return count;
}
const uint8_t *orig_buf = buf;
const uint8_t *buf_end = buf + buf_size;
int i, j, id, size, ssize, weights, t;
- int bpp, chan, chmask;
+ int bpp, chan, chmask, orig_bpp;
if (buf_size == 0) {
*got_frame_ptr = 0;
s->frame_flags = AV_RL32(buf); buf += 4;
bpp = av_get_bytes_per_sample(avctx->sample_fmt);
samples = (uint8_t*)samples + bpp * wc->ch_offset;
+ orig_bpp = ((s->frame_flags & 0x03) + 1) << 3;
s->stereo = !(s->frame_flags & WV_MONO);
s->stereo_in = (s->frame_flags & WV_FALSE_STEREO) ? 0 : s->stereo;
s->joint = s->frame_flags & WV_JOINT_STEREO;
s->hybrid = s->frame_flags & WV_HYBRID_MODE;
s->hybrid_bitrate = s->frame_flags & WV_HYBRID_BITRATE;
- s->hybrid_maxclip = (1LL << ((((s->frame_flags & 0x03) + 1) << 3) - 1)) - 1;
- s->post_shift = 8 * (bpp - 1 - (s->frame_flags & 0x03)) +
- ((s->frame_flags >> 13) & 0x1f);
+ s->post_shift = bpp * 8 - orig_bpp + ((s->frame_flags >> 13) & 0x1f);
+ s->hybrid_maxclip = (( 1LL << (orig_bpp - 1)) - 1);
+ s->hybrid_minclip = ((-1LL << (orig_bpp - 1)));
s->CRC = AV_RL32(buf); buf += 4;
if (wc->mkv_mode)
buf += 4; //skip block size;
} else {
for (j = 0; j < s->decorr[i].value; j++) {
s->decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf)); buf += 2;
- if (s->stereo_in)
+ if (s->stereo_in) {
s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); buf += 2;
+ }
}
t += s->decorr[i].value * 2 * (s->stereo_in + 1);
}
s->and = 1;
s->shift = buf[3];
}
+ /* original WavPack decoder forces 32-bit lossy sound to be treated
+ * as 24-bit one in order to have proper clipping
+ */
+ if (s->hybrid && bpp == 4 && s->post_shift < 8 && s->shift > 8) {
+ s->post_shift += 8;
+ s->shift -= 8;
+ s->hybrid_maxclip >>= 8;
+ s->hybrid_minclip >>= 8;
+ }
buf += 4;
break;
case WP_ID_FLOATINFO:
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
} else {
avctx->sample_fmt = AV_SAMPLE_FMT_S32;
+ avctx->bits_per_raw_sample = ((frame_flags & 0x03) + 1) << 3;
}
/* get output buffer */
s->frame.nb_samples = s->samples;
- 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;
}
AVCodec ff_wavpack_decoder = {
.name = "wavpack",
.type = AVMEDIA_TYPE_AUDIO,
- .id = CODEC_ID_WAVPACK,
+ .id = AV_CODEC_ID_WAVPACK,
.priv_data_size = sizeof(WavpackContext),
.init = wavpack_decode_init,
.close = wavpack_decode_end,