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 = { |