And add more sanity checks to stream. This shouldn't break things beyond those that aren't broken already.
Signed-off-by: Maarten Lankhorst <m.b.lankho...@gmail.com> --- And yes Andy, I mean that I haven't found a good video yet to fix the playback parts that are still broken.. src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c | 56 +++++++++++------------- src/gallium/auxiliary/vl/vl_vlc.h | 33 +++++++++----- 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c index 936cf2c..62d08d7 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c @@ -787,7 +787,7 @@ entry: } static INLINE bool -decode_slice(struct vl_mpg12_bs *bs) +decode_slice(struct vl_mpg12_bs *bs, unsigned code) { struct pipe_mpeg12_macroblock mb; short dct_blocks[64*6]; @@ -796,24 +796,29 @@ decode_slice(struct vl_mpg12_bs *bs) memset(&mb, 0, sizeof(mb)); mb.base.codec = PIPE_VIDEO_CODEC_MPEG12; - mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1; + mb.y = code - 1; mb.blocks = dct_blocks; reset_predictor(bs); + vl_vlc_fillbits(&bs->vlc); dct_scale = quant_scale[bs->desc.q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)]; - if (vl_vlc_get_uimsbf(&bs->vlc, 1)) + if (vl_vlc_get_uimsbf(&bs->vlc, 1)) { + vl_vlc_fillbits(&bs->vlc); while (vl_vlc_get_uimsbf(&bs->vlc, 9) & 1) vl_vlc_fillbits(&bs->vlc); + } vl_vlc_fillbits(&bs->vlc); + assert(vl_vlc_bits_left(&bs->vlc) > 23 && vl_vlc_peekbits(&bs->vlc, 23)); do { int inc = 0; - while (vl_vlc_peekbits(&bs->vlc, 11) == 15) { - vl_vlc_eatbits(&bs->vlc, 11); - vl_vlc_fillbits(&bs->vlc); - } + if (bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) + while (vl_vlc_peekbits(&bs->vlc, 11) == 15) { + vl_vlc_eatbits(&bs->vlc, 11); + vl_vlc_fillbits(&bs->vlc); + } while (vl_vlc_peekbits(&bs->vlc, 11) == 8) { vl_vlc_eatbits(&bs->vlc, 11); @@ -959,32 +964,23 @@ void vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const uint8_t *buffer) { assert(bs); - assert(buffer && num_bytes); - - while(num_bytes > 2) { - if (buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x01 && - buffer[3] >= 0x01 && buffer[3] < 0xAF) { - unsigned consumed; - buffer += 3; - num_bytes -= 3; + vl_vlc_init(&bs->vlc, 1, num_bytes, (void const * const *)&buffer, &num_bytes); - vl_vlc_init(&bs->vlc, buffer, num_bytes); - - if (!decode_slice(bs)) + while (vl_vlc_bits_left(&bs->vlc) >= 32) { + vl_vlc_fillbits(&bs->vlc); + if (vl_vlc_peekbits(&bs->vlc, 24) == 0x000001) { + unsigned code; + vl_vlc_eatbits(&bs->vlc, 24); + code = vl_vlc_get_uimsbf(&bs->vlc, 8); + if (!code || code > 0xaf) + continue; + if (!decode_slice(bs, code)) return; - - consumed = num_bytes - vl_vlc_bits_left(&bs->vlc) / 8; - - /* crap, this is a bug we have consumed more bytes than left in the buffer */ - assert(consumed <= num_bytes); - - num_bytes -= consumed; - buffer += consumed; - + vl_vlc_bitalign(&bs->vlc); } else { - ++buffer; - --num_bytes; + vl_vlc_eatbits(&bs->vlc, 8); + continue; } } } diff --git a/src/gallium/auxiliary/vl/vl_vlc.h b/src/gallium/auxiliary/vl/vl_vlc.h index dc4faed..a4ded70 100644 --- a/src/gallium/auxiliary/vl/vl_vlc.h +++ b/src/gallium/auxiliary/vl/vl_vlc.h @@ -38,7 +38,7 @@ struct vl_vlc { uint64_t buffer; - unsigned valid_bits; + uint32_t valid_bits; uint32_t *data; uint32_t *end; }; @@ -74,11 +74,9 @@ vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_v static INLINE void vl_vlc_fillbits(struct vl_vlc *vlc) { - if (vlc->valid_bits < 32) { + if (vlc->valid_bits < 32 && vlc->data < vlc->end) { uint32_t value = *vlc->data; - //assert(vlc->data <= vlc->end); - #ifndef PIPE_ARCH_BIG_ENDIAN value = util_bswap32(value); #endif @@ -90,10 +88,14 @@ vl_vlc_fillbits(struct vl_vlc *vlc) } static INLINE void -vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len) +vl_vlc_init(struct vl_vlc *vlc, + const unsigned array_size, unsigned total_len, + const const void *const *datas, const unsigned *lens) { + const uint8_t *data = datas[0]; assert(vlc); - assert(data && len); + assert(array_size == 1); // TODO + assert(datas[0] && lens[0]); vlc->buffer = 0; vlc->valid_bits = 0; @@ -102,11 +104,11 @@ vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len) while (pointer_to_uintptr(data) & 3) { vlc->buffer |= (uint64_t)*data << (56 - vlc->valid_bits); ++data; - --len; + --total_len; vlc->valid_bits += 8; } vlc->data = (uint32_t*)data; - vlc->end = (uint32_t*)(data + len); + vlc->end = (uint32_t*)(data + total_len); vl_vlc_fillbits(vlc); vl_vlc_fillbits(vlc); @@ -122,7 +124,7 @@ vl_vlc_bits_left(struct vl_vlc *vlc) static INLINE unsigned vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits) { - //assert(vlc->valid_bits >= num_bits); + assert(vlc->valid_bits >= num_bits || vl_vlc_bits_left(vlc) < num_bits); return vlc->buffer >> (64 - num_bits); } @@ -130,7 +132,7 @@ vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits) static INLINE void vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits) { - //assert(vlc->valid_bits > num_bits); + assert(vlc->valid_bits >= num_bits); vlc->buffer <<= num_bits; vlc->valid_bits -= num_bits; @@ -141,7 +143,7 @@ vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits) { unsigned value; - //assert(vlc->valid_bits >= num_bits); + assert(vlc->valid_bits >= num_bits); value = vlc->buffer >> (64 - num_bits); vl_vlc_eatbits(vlc, num_bits); @@ -154,7 +156,7 @@ vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits) { signed value; - //assert(vlc->valid_bits >= num_bits); + assert(vlc->valid_bits >= num_bits); value = ((int64_t)vlc->buffer) >> (64 - num_bits); vl_vlc_eatbits(vlc, num_bits); @@ -167,7 +169,14 @@ vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned n { tbl += vl_vlc_peekbits(vlc, num_bits); vl_vlc_eatbits(vlc, tbl->length); + assert(tbl->length); return tbl->value; } +static INLINE void +vl_vlc_bitalign(struct vl_vlc *vlc) +{ + vl_vlc_eatbits(vlc, vlc->valid_bits & 7); +} + #endif /* vl_vlc_h */ _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev