| Index: patched-ffmpeg-mt/libavcodec/wavpack.c
|
| ===================================================================
|
| --- patched-ffmpeg-mt/libavcodec/wavpack.c (revision 41250)
|
| +++ patched-ffmpeg-mt/libavcodec/wavpack.c (working copy)
|
| @@ -67,6 +67,13 @@
|
| WP_ID_CHANINFO
|
| };
|
|
|
| +typedef struct SavedContext {
|
| + int offset;
|
| + int size;
|
| + int bits_used;
|
| + uint32_t crc;
|
| +} SavedContext;
|
| +
|
| #define MAX_TERMS 16
|
|
|
| typedef struct Decorr {
|
| @@ -107,6 +114,10 @@
|
| int float_shift;
|
| int float_max_exp;
|
| WvChannel ch[2];
|
| + int samples_left;
|
| + int max_samples;
|
| + int pos;
|
| + SavedContext sc, extra_sc;
|
| } WavpackContext;
|
|
|
| // exponent table copied from WavPack source
|
| @@ -439,19 +450,26 @@
|
| return value.f;
|
| }
|
|
|
| +static void wv_reset_saved_context(WavpackContext *s)
|
| +{
|
| + s->pos = 0;
|
| + s->sc.crc = s->extra_sc.crc = 0xFFFFFFFF;
|
| +}
|
| +
|
| static inline int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, void *dst, const int type)
|
| {
|
| int i, j, count = 0;
|
| int last, t;
|
| int A, B, L, L2, R, R2;
|
| - int pos = 0;
|
| - uint32_t crc = 0xFFFFFFFF;
|
| - uint32_t crc_extra_bits = 0xFFFFFFFF;
|
| + int pos = s->pos;
|
| + uint32_t crc = s->sc.crc;
|
| + uint32_t crc_extra_bits = s->extra_sc.crc;
|
| int16_t *dst16 = dst;
|
| int32_t *dst32 = dst;
|
| float *dstfl = dst;
|
|
|
| - s->one = s->zero = s->zeroes = 0;
|
| + if(s->samples_left == s->samples)
|
| + s->one = s->zero = s->zeroes = 0;
|
| do{
|
| L = wv_get_value(s, gb, 0, &last);
|
| if(last) break;
|
| @@ -539,16 +557,28 @@
|
| *dst16++ = wv_get_value_integer(s, &crc_extra_bits, R);
|
| }
|
| count++;
|
| - }while(!last && count < s->samples);
|
| + }while(!last && count < s->max_samples);
|
|
|
| - if(crc != s->CRC){
|
| - av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
|
| - return -1;
|
| + s->samples_left -= count;
|
| + if(!s->samples_left){
|
| + 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;
|
| + }
|
| + 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);
|
| + }
|
| }
|
| - 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;
|
| - }
|
| return count * 2;
|
| }
|
|
|
| @@ -557,14 +587,15 @@
|
| int i, j, count = 0;
|
| int last, t;
|
| int A, S, T;
|
| - int pos = 0;
|
| - uint32_t crc = 0xFFFFFFFF;
|
| - uint32_t crc_extra_bits = 0xFFFFFFFF;
|
| + int pos = s->pos;
|
| + uint32_t crc = s->sc.crc;
|
| + uint32_t crc_extra_bits = s->extra_sc.crc;
|
| int16_t *dst16 = dst;
|
| int32_t *dst32 = dst;
|
| float *dstfl = dst;
|
|
|
| - s->one = s->zero = s->zeroes = 0;
|
| + if(s->samples_left == s->samples)
|
| + s->one = s->zero = s->zeroes = 0;
|
| do{
|
| T = wv_get_value(s, gb, 0, &last);
|
| S = 0;
|
| @@ -601,14 +632,26 @@
|
| count++;
|
| }while(!last && count < s->samples);
|
|
|
| - if(crc != s->CRC){
|
| - av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
|
| - return -1;
|
| + s->samples_left -= count;
|
| + if(!s->samples_left){
|
| + 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;
|
| + }
|
| + 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);
|
| + }
|
| }
|
| - 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;
|
| - }
|
| return count;
|
| }
|
|
|
| @@ -624,6 +667,8 @@
|
| avctx->sample_fmt = SAMPLE_FMT_S32;
|
| avctx->channel_layout = (avctx->channels==2) ? CH_LAYOUT_STEREO : CH_LAYOUT_MONO;
|
|
|
| + wv_reset_saved_context(s);
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -647,11 +692,13 @@
|
| return 0;
|
| }
|
|
|
| - 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(!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;
|
| + }
|
|
|
| s->samples = AV_RL32(buf); buf += 4;
|
| if(!s->samples){
|
| @@ -676,10 +723,11 @@
|
| s->post_shift = 8 * (bpp-1-(s->frame_flags&0x03)) + ((s->frame_flags >> 13) & 0x1f);
|
| s->CRC = AV_RL32(buf); buf += 4;
|
|
|
| - /* should not happen but who knows */
|
| - if(s->samples * bpp * avctx->channels > *data_size){
|
| - av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n");
|
| - return -1;
|
| + 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
|
| @@ -847,6 +895,8 @@
|
| got_float = 1;
|
| break;
|
| case WP_ID_DATA:
|
| + s->sc.offset = buf - avpkt->data;
|
| + s->sc.size = size * 8;
|
| init_get_bits(&s->gb, buf, size * 8);
|
| s->data_size = size * 8;
|
| buf += size;
|
| @@ -858,6 +908,8 @@
|
| buf += size;
|
| continue;
|
| }
|
| + s->extra_sc.offset = buf - avpkt->data;
|
| + s->extra_sc.size = size * 8;
|
| init_get_bits(&s->gb_extra_bits, buf, size * 8);
|
| s->crc_extra_bits = get_bits_long(&s->gb_extra_bits, 32);
|
| buf += size;
|
| @@ -868,41 +920,52 @@
|
| }
|
| if(id & WP_IDF_ODD) buf++;
|
| }
|
| - if(!got_terms){
|
| - av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");
|
| - return -1;
|
| - }
|
| - if(!got_weights){
|
| - av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n");
|
| - return -1;
|
| - }
|
| - if(!got_samples){
|
| - av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n");
|
| - return -1;
|
| - }
|
| - if(!got_entropy){
|
| - av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n");
|
| - return -1;
|
| - }
|
| - if(s->hybrid && !got_hybrid){
|
| - av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n");
|
| - return -1;
|
| - }
|
| - if(!got_bs){
|
| - av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");
|
| - return -1;
|
| - }
|
| - if(!got_float && avctx->sample_fmt == SAMPLE_FMT_FLT){
|
| - av_log(avctx, AV_LOG_ERROR, "Float information not found\n");
|
| - return -1;
|
| - }
|
| - if(s->got_extra_bits && avctx->sample_fmt != SAMPLE_FMT_FLT){
|
| - const int size = get_bits_left(&s->gb_extra_bits);
|
| - const int wanted = s->samples * s->extra_bits << s->stereo_in;
|
| - if(size < wanted){
|
| - av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n");
|
| - s->got_extra_bits = 0;
|
| + if(!s->samples_left){
|
| + if(!got_terms){
|
| + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");
|
| + return -1;
|
| }
|
| + if(!got_weights){
|
| + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n");
|
| + return -1;
|
| + }
|
| + if(!got_samples){
|
| + av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n");
|
| + return -1;
|
| + }
|
| + if(!got_entropy){
|
| + av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n");
|
| + return -1;
|
| + }
|
| + if(s->hybrid && !got_hybrid){
|
| + av_log(avctx, AV_LOG_ERROR, "Hybrid config not found\n");
|
| + return -1;
|
| + }
|
| + if(!got_bs){
|
| + av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");
|
| + return -1;
|
| + }
|
| + if(!got_float && avctx->sample_fmt == SAMPLE_FMT_FLT){
|
| + av_log(avctx, AV_LOG_ERROR, "Float information not found\n");
|
| + return -1;
|
| + }
|
| + if(s->got_extra_bits && avctx->sample_fmt != SAMPLE_FMT_FLT){
|
| + const int size = get_bits_left(&s->gb_extra_bits);
|
| + const int wanted = s->samples * s->extra_bits << s->stereo_in;
|
| + if(size < wanted){
|
| + av_log(avctx, AV_LOG_ERROR, "Too small EXTRABITS\n");
|
| + s->got_extra_bits = 0;
|
| + }
|
| + }
|
| + s->samples_left = s->samples;
|
| + }else{
|
| + init_get_bits(&s->gb, avpkt->data + 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, avpkt->data + s->extra_sc.offset,
|
| + s->extra_sc.size);
|
| + skip_bits_long(&s->gb_extra_bits, s->extra_sc.bits_used);
|
| + }
|
| }
|
|
|
| if(s->stereo_in){
|
| @@ -952,7 +1015,7 @@
|
| }
|
| *data_size = samplecount * bpp;
|
|
|
| - return buf_size;
|
| + return s->samples_left > 0 ? 0 : buf_size;
|
| }
|
|
|
| AVCodec wavpack_decoder = {
|
|
|