* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define ALT_BITSTREAM_READER_LE
+#define BITSTREAM_READER_LE
#include "avcodec.h"
#include "get_bits.h"
#include "unary.h"
int extra_bits;
int and, or, shift;
int post_shift;
- int hybrid, hybrid_bitrate;
+ int hybrid, hybrid_bitrate, hybrid_maxclip;
int float_flag;
int float_shift;
int float_max_exp;
WvChannel ch[2];
- int samples_left;
- int max_samples;
int pos;
SavedContext sc, extra_sc;
} WavpackFrameContext;
typedef struct WavpackContext {
AVCodecContext *avctx;
+ AVFrame frame;
WavpackFrameContext *fdec[WV_MAX_FRAME_DECODERS];
int fdec_num;
int mkv_mode;
int block;
int samples;
- int samples_left;
int ch_offset;
} WavpackContext;
}
}else{
t = get_unary_0_33(gb);
- if(t >= 2) t = get_bits(gb, t - 1) | (1 << (t-1));
+ if(t >= 2){
+ if(get_bits_left(gb) < t-1)
+ goto error;
+ t = get_bits(gb, t - 1) | (1 << (t-1));
+ }else{
+ if(get_bits_left(gb) < 0)
+ goto error;
+ }
ctx->zeroes = t;
if(ctx->zeroes){
memset(ctx->ch[0].median, 0, sizeof(ctx->ch[0].median));
}
}
- if(get_bits_count(gb) >= ctx->data_size){
- *last = 1;
- return 0;
- }
-
if(ctx->zero){
t = 0;
ctx->zero = 0;
}else{
t = get_unary_0_33(gb);
- if(get_bits_count(gb) >= ctx->data_size){
- *last = 1;
- return 0;
- }
+ if(get_bits_left(gb) < 0)
+ goto error;
if(t == 16) {
t2 = get_unary_0_33(gb);
- if(t2 < 2) t += t2;
- else t += get_bits(gb, t2 - 1) | (1 << (t2 - 1));
+ if(t2 < 2){
+ if(get_bits_left(gb) < 0)
+ goto error;
+ t += t2;
+ }else{
+ if(get_bits_left(gb) < t2 - 1)
+ goto error;
+ t += get_bits(gb, t2 - 1) | (1 << (t2 - 1));
+ }
}
if(ctx->one){
}
if(!c->error_limit){
ret = base + get_tail(gb, add);
+ if (get_bits_left(gb) <= 0)
+ goto error;
}else{
int mid = (base*2 + add + 1) >> 1;
while(add > c->error_limit){
+ if(get_bits_left(gb) <= 0)
+ goto error;
if(get_bits1(gb)){
add -= (mid - base);
base = mid;
if(ctx->hybrid_bitrate)
c->slow_level += wp_log2(ret) - LEVEL_DECAY(c->slow_level);
return sign ? ~ret : ret;
+
+error:
+ *last = 1;
+ return 0;
}
static inline int wv_get_value_integer(WavpackFrameContext *s, uint32_t *crc, int S)
if(s->extra_bits){
S <<= s->extra_bits;
- if(s->got_extra_bits){
+ if(s->got_extra_bits && get_bits_left(&s->gb_extra_bits) >= s->extra_bits){
S |= get_bits(&s->gb_extra_bits, s->extra_bits);
*crc = *crc * 9 + (S&0xffff) * 3 + ((unsigned)S>>16);
}
}
+
bit = (S & s->and) | s->or;
- return (((S + bit) << s->shift) - bit) << s->post_shift;
+ bit = (((S + bit) << s->shift) - bit) << s->post_shift;
+
+ if(s->hybrid)
+ bit = av_clip(bit, -s->hybrid_maxclip - 1, s->hybrid_maxclip);
+
+ return bit;
}
static float wv_get_value_float(WavpackFrameContext *s, uint32_t *crc, int S)
float *dstfl = dst;
const int channel_pad = s->avctx->channels - 2;
- if(s->samples_left == s->samples)
- s->one = s->zero = s->zeroes = 0;
+ s->one = s->zero = s->zeroes = 0;
do{
L = wv_get_value(s, gb, 0, &last);
if(last) break;
dst16 += channel_pad;
}
count++;
- }while(!last && count < s->max_samples);
+ } while (!last && count < s->samples);
- s->samples_left -= count;
- if(!s->samples_left){
+ wv_reset_saved_context(s);
if(crc != s->CRC){
av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
return -1;
av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
return -1;
}
- wv_reset_saved_context(s);
- }else{
- s->pos = pos;
- s->sc.crc = crc;
- s->sc.bits_used = get_bits_count(&s->gb);
- if(s->got_extra_bits){
- s->extra_sc.crc = crc_extra_bits;
- s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits);
- }
- }
+
return count * 2;
}
float *dstfl = dst;
const int channel_stride = s->avctx->channels;
- if(s->samples_left == s->samples)
- s->one = s->zero = s->zeroes = 0;
+ s->one = s->zero = s->zeroes = 0;
do{
T = wv_get_value(s, gb, 0, &last);
S = 0;
dst16 += channel_stride;
}
count++;
- }while(!last && count < s->max_samples);
+ } while (!last && count < s->samples);
- s->samples_left -= count;
- if(!s->samples_left){
+ wv_reset_saved_context(s);
if(crc != s->CRC){
av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
return -1;
av_log(s->avctx, AV_LOG_ERROR, "Extra bits CRC error\n");
return -1;
}
- wv_reset_saved_context(s);
- }else{
- s->pos = pos;
- s->sc.crc = crc;
- s->sc.bits_used = get_bits_count(&s->gb);
- if(s->got_extra_bits){
- s->extra_sc.crc = crc_extra_bits;
- s->extra_sc.bits_used = get_bits_count(&s->gb_extra_bits);
- }
- }
+
return count;
}
s->fdec_num = 0;
+ avcodec_get_frame_defaults(&s->frame);
+ avctx->coded_frame = &s->frame;
+
return 0;
}
}
static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
- void *data, int *data_size,
+ void *data, int *got_frame_ptr,
const uint8_t *buf, int buf_size)
{
WavpackContext *wc = avctx->priv_data;
int bpp, chan, chmask;
if (buf_size == 0){
- *data_size = 0;
+ *got_frame_ptr = 0;
return 0;
}
return -1;
}
- if(!s->samples_left){
memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr));
memset(s->ch, 0, sizeof(s->ch));
s->extra_bits = 0;
s->and = s->or = s->shift = 0;
s->got_extra_bits = 0;
- }
if(!wc->mkv_mode){
s->samples = AV_RL32(buf); buf += 4;
if(!s->samples){
- *data_size = 0;
- return buf_size;
+ *got_frame_ptr = 0;
+ return 0;
}
}else{
s->samples = wc->samples;
}
s->frame_flags = AV_RL32(buf); buf += 4;
if(s->frame_flags&0x80){
- bpp = sizeof(float);
avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
} else if((s->frame_flags&0x03) <= 1){
- bpp = 2;
avctx->sample_fmt = AV_SAMPLE_FMT_S16;
} else {
- bpp = 4;
avctx->sample_fmt = AV_SAMPLE_FMT_S32;
}
+ bpp = av_get_bytes_per_sample(avctx->sample_fmt);
samples = (uint8_t*)samples + bpp * wc->ch_offset;
s->stereo = !(s->frame_flags & WV_MONO);
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->CRC = AV_RL32(buf); buf += 4;
if(wc->mkv_mode)
wc->ch_offset += 1 + s->stereo;
- s->max_samples = *data_size / (bpp * avctx->channels);
- s->max_samples = FFMIN(s->max_samples, s->samples);
- if(s->samples_left > 0){
- s->max_samples = FFMIN(s->max_samples, s->samples_left);
- buf = buf_end;
- }
-
// parse metadata blocks
while(buf < buf_end){
id = *buf++;
}
switch(id & WP_IDF_MASK){
case WP_ID_DECTERMS:
- s->terms = size;
- if(s->terms > MAX_TERMS){
+ if(size > MAX_TERMS){
av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n");
+ s->terms = 0;
buf += ssize;
continue;
}
+ s->terms = size;
for(i = 0; i < s->terms; i++) {
s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5;
s->decorr[s->terms - i - 1].delta = *buf >> 5;
}
if(id & WP_IDF_ODD) buf++;
}
- if(!s->samples_left){
+
if(!got_terms){
av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");
return -1;
s->got_extra_bits = 0;
}
}
- s->samples_left = s->samples;
- }else{
- init_get_bits(&s->gb, orig_buf + s->sc.offset, s->sc.size);
- skip_bits_long(&s->gb, s->sc.bits_used);
- if(s->got_extra_bits){
- init_get_bits(&s->gb_extra_bits, orig_buf + s->extra_sc.offset,
- s->extra_sc.size);
- skip_bits_long(&s->gb_extra_bits, s->extra_sc.bits_used);
- }
- }
if(s->stereo_in){
if(avctx->sample_fmt == AV_SAMPLE_FMT_S16)
samplecount = wv_unpack_stereo(s, &s->gb, samples, AV_SAMPLE_FMT_S32);
else
samplecount = wv_unpack_stereo(s, &s->gb, samples, AV_SAMPLE_FMT_FLT);
+
+ if (samplecount < 0)
+ return -1;
+
samplecount >>= 1;
}else{
const int channel_stride = avctx->channels;
else
samplecount = wv_unpack_mono(s, &s->gb, samples, AV_SAMPLE_FMT_FLT);
+ if (samplecount < 0)
+ return -1;
+
if(s->stereo && avctx->sample_fmt == AV_SAMPLE_FMT_S16){
int16_t *dst = (int16_t*)samples + 1;
int16_t *src = (int16_t*)samples;
}
}
- wc->samples_left = s->samples_left;
+ *got_frame_ptr = 1;
return samplecount * bpp;
}
-static int wavpack_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
- AVPacket *avpkt)
+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;
- int frame_size;
+ int frame_size, ret;
int samplecount = 0;
s->block = 0;
- s->samples_left = 0;
s->ch_offset = 0;
+ /* determine number of samples */
if(s->mkv_mode){
s->samples = AV_RL32(buf); buf += 4;
+ } else {
+ if (s->multichannel)
+ s->samples = AV_RL32(buf + 4);
+ else
+ s->samples = AV_RL32(buf);
}
+ if (s->samples <= 0) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid number of samples: %d\n",
+ s->samples);
+ return AVERROR(EINVAL);
+ }
+
+ /* get output buffer */
+ s->frame.nb_samples = s->samples;
+ if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+ return ret;
+ }
+
while(buf_size > 0){
if(!s->multichannel){
frame_size = buf_size;
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 -1;
}
- if((samplecount = wavpack_decode_block(avctx, s->block, data,
- data_size, buf, frame_size)) < 0)
+ if((samplecount = wavpack_decode_block(avctx, s->block, s->frame.data[0],
+ got_frame_ptr, buf, frame_size)) < 0) {
+ wavpack_decode_flush(avctx);
return -1;
+ }
s->block++;
buf += frame_size; buf_size -= frame_size;
}
- *data_size = samplecount * avctx->channels;
-
- return s->samples_left > 0 ? 0 : avpkt->size;
-}
-static void wavpack_decode_flush(AVCodecContext *avctx)
-{
- WavpackContext *s = avctx->priv_data;
- int i;
+ if (*got_frame_ptr)
+ *(AVFrame *)data = s->frame;
- for (i = 0; i < s->fdec_num; i++)
- s->fdec[i]->samples_left = 0;
+ return avpkt->size;
}
AVCodec ff_wavpack_decoder = {
.close = wavpack_decode_end,
.decode = wavpack_decode_frame,
.flush = wavpack_decode_flush,
- .capabilities = CODEC_CAP_SUBFRAMES,
+ .capabilities = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("WavPack"),
};