|
|
|
@@ -1585,10 +1585,13 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte |
|
|
|
return ff_mpeg_update_thread_context(dst, src); |
|
|
|
} |
|
|
|
|
|
|
|
static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) |
|
|
|
static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n, int slice_count, int buf_size) |
|
|
|
{ |
|
|
|
if(avctx->slice_count) return avctx->slice_offset[n]; |
|
|
|
else return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8); |
|
|
|
if (n < slice_count) { |
|
|
|
if(avctx->slice_count) return avctx->slice_offset[n]; |
|
|
|
else return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8); |
|
|
|
} else |
|
|
|
return buf_size; |
|
|
|
} |
|
|
|
|
|
|
|
static int finish_frame(AVCodecContext *avctx, AVFrame *pict) |
|
|
|
@@ -1646,6 +1649,7 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, |
|
|
|
const uint8_t *slices_hdr = NULL; |
|
|
|
int last = 0; |
|
|
|
int faulty_b = 0; |
|
|
|
int offset; |
|
|
|
|
|
|
|
/* no supplementary picture */ |
|
|
|
if (buf_size == 0) { |
|
|
|
@@ -1668,13 +1672,13 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, |
|
|
|
}else |
|
|
|
slice_count = avctx->slice_count; |
|
|
|
|
|
|
|
offset = get_slice_offset(avctx, slices_hdr, 0, slice_count, buf_size); |
|
|
|
//parse first slice header to check whether this frame can be decoded |
|
|
|
if(get_slice_offset(avctx, slices_hdr, 0) < 0 || |
|
|
|
get_slice_offset(avctx, slices_hdr, 0) > buf_size){ |
|
|
|
if(offset < 0 || offset > buf_size){ |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, 0), (buf_size-get_slice_offset(avctx, slices_hdr, 0))*8); |
|
|
|
init_get_bits(&s->gb, buf+offset, (buf_size-offset)*8); |
|
|
|
if(r->parse_slice_header(r, &r->s.gb, &si) < 0 || si.start){ |
|
|
|
av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
@@ -1777,40 +1781,32 @@ int ff_rv34_decode_frame(AVCodecContext *avctx, |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
for(i = 0; i < slice_count; i++){ |
|
|
|
int offset = get_slice_offset(avctx, slices_hdr, i); |
|
|
|
int offset = get_slice_offset(avctx, slices_hdr, i , slice_count, buf_size); |
|
|
|
int offset1 = get_slice_offset(avctx, slices_hdr, i+1, slice_count, buf_size); |
|
|
|
int size; |
|
|
|
if(i+1 == slice_count) |
|
|
|
size = buf_size - offset; |
|
|
|
else |
|
|
|
size = get_slice_offset(avctx, slices_hdr, i+1) - offset; |
|
|
|
|
|
|
|
if(offset < 0 || offset > buf_size){ |
|
|
|
if(offset < 0 || offset > offset1 || offset1 > buf_size){ |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); |
|
|
|
break; |
|
|
|
} |
|
|
|
size = offset1 - offset; |
|
|
|
|
|
|
|
r->si.end = s->mb_width * s->mb_height; |
|
|
|
s->mb_num_left = r->s.mb_x + r->s.mb_y*r->s.mb_width - r->si.start; |
|
|
|
|
|
|
|
if(i+1 < slice_count){ |
|
|
|
if (get_slice_offset(avctx, slices_hdr, i+1) < 0 || |
|
|
|
get_slice_offset(avctx, slices_hdr, i+1) > buf_size) { |
|
|
|
int offset2 = get_slice_offset(avctx, slices_hdr, i+2, slice_count, buf_size); |
|
|
|
if (offset2 < offset1 || offset2 > buf_size) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n"); |
|
|
|
break; |
|
|
|
} |
|
|
|
init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, i+1), (buf_size-get_slice_offset(avctx, slices_hdr, i+1))*8); |
|
|
|
init_get_bits(&s->gb, buf+offset1, (buf_size-offset1)*8); |
|
|
|
if(r->parse_slice_header(r, &r->s.gb, &si) < 0){ |
|
|
|
if(i+2 < slice_count) |
|
|
|
size = get_slice_offset(avctx, slices_hdr, i+2) - offset; |
|
|
|
else |
|
|
|
size = buf_size - offset; |
|
|
|
size = offset2 - offset; |
|
|
|
}else |
|
|
|
r->si.end = si.start; |
|
|
|
} |
|
|
|
if (size < 0 || size > buf_size - offset) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Slice size is invalid\n"); |
|
|
|
break; |
|
|
|
} |
|
|
|
av_assert0 (size >= 0 && size <= buf_size - offset); |
|
|
|
last = rv34_decode_slice(r, r->si.end, buf + offset, size); |
|
|
|
if(last) |
|
|
|
break; |
|
|
|
|