[Mesa-dev] [PATCH 1/3] vl: Only initialize vlc once

Maarten Lankhorst m.b.lankhorst at gmail.com
Tue Dec 20 03:43:23 PST 2011


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.lankhorst at 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 */




More information about the mesa-dev mailing list