s/Tungsten Graphics/VMware/
[mesa.git] / src / gallium / auxiliary / vl / vl_mpeg12_bitstream.c
index 7a14efb627e2adff90e9088b479eebca6a8d4aea..abb3780f61e86919cbd27b43aeb8fc90d7f0094c 100644 (file)
@@ -1,6 +1,7 @@
 /**************************************************************************
  *
- * Copyright 2011 Christian König.
+ * Copyright 2011 Maarten Lankhorst
+ * Copyright 2011 Christian König
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  **************************************************************************/
 
-/**
- * This file is based uppon slice_xvmc.c and vlc.h from the xine project,
- * which in turn is based on mpeg2dec. The following is the original copyright:
- *
- * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
- * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
- *
- * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
- * See http://libmpeg2.sourceforge.net/ for updates.
- *
- * mpeg2dec is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * mpeg2dec is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <stdint.h>
-
-#include <pipe/p_video_state.h>
+#include "pipe/p_video_codec.h"
+#include "util/u_memory.h"
 
 #include "vl_vlc.h"
 #include "vl_mpeg12_bitstream.h"
 
-/* take num bits from the high part of bit_buf and zero extend them */
-#define UBITS(buf,num) (((uint32_t)(buf)) >> (32 - (num)))
-
-/* take num bits from the high part of bit_buf and sign extend them */
-#define SBITS(buf,num) (((int32_t)(buf)) >> (32 - (num)))
-
-/* macroblock modes */
-#define MACROBLOCK_INTRA 1
-#define MACROBLOCK_PATTERN 2
-#define MACROBLOCK_MOTION_BACKWARD 4
-#define MACROBLOCK_MOTION_FORWARD 8
-#define MACROBLOCK_QUANT 16
-
-/* motion_type */
-#define MOTION_TYPE_MASK (3*64)
-#define MOTION_TYPE_BASE 64
-#define MC_FIELD (1*64)
-#define MC_FRAME (2*64)
-#define MC_16X8 (2*64)
-#define MC_DMV (3*64)
-
-/* picture structure */
-#define TOP_FIELD     1
-#define BOTTOM_FIELD  2
-#define FRAME_PICTURE 3
-
-/* picture coding type (mpeg2 header) */
-#define I_TYPE 1
-#define P_TYPE 2
-#define B_TYPE 3
-#define D_TYPE 4
-
-typedef struct {
-   uint8_t modes;
-   uint8_t len;
-} MBtab;
-
-typedef struct {
-   uint8_t delta;
-   uint8_t len;
-} MVtab;
-
-typedef struct {
-   int8_t dmv;
-   uint8_t len;
-} DMVtab;
-
-typedef struct {
-   uint8_t cbp;
-   uint8_t len;
-} CBPtab;
-
-typedef struct {
-   uint8_t size;
-   uint8_t len;
-} DCtab;
-
-typedef struct {
+enum {
+   dct_End_of_Block = 0xFF,
+   dct_Escape = 0xFE,
+   dct_DC = 0xFD,
+   dct_AC = 0xFC
+};
+
+struct dct_coeff
+{
+   uint8_t length;
    uint8_t run;
-   uint8_t level;
-   uint8_t len;
-} DCTtab;
-
-typedef struct {
-   uint8_t mba;
-   uint8_t len;
-} MBAtab;
-
-#define INTRA MACROBLOCK_INTRA
-#define QUANT MACROBLOCK_QUANT
-#define MC MACROBLOCK_MOTION_FORWARD
-#define CODED MACROBLOCK_PATTERN
-#define FWD MACROBLOCK_MOTION_FORWARD
-#define BWD MACROBLOCK_MOTION_BACKWARD
-#define INTER MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD
-
-static const MBtab MB_I [] = {
-   {INTRA|QUANT, 2}, {INTRA, 1}
+   int16_t level;
 };
 
-static const MBtab MB_P [] = {
-   {INTRA|QUANT, 6}, {CODED|QUANT, 5}, {MC|CODED|QUANT, 5}, {INTRA,    5},
-   {MC,          3}, {MC,          3}, {MC,             3}, {MC,       3},
-   {CODED,       2}, {CODED,       2}, {CODED,          2}, {CODED,    2},
-   {CODED,       2}, {CODED,       2}, {CODED,          2}, {CODED,    2},
-   {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1},
-   {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1},
-   {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1},
-   {MC|CODED,    1}, {MC|CODED,    1}, {MC|CODED,       1}, {MC|CODED, 1}
+struct dct_coeff_compressed
+{
+   uint32_t bitcode;
+   struct dct_coeff coeff;
 };
 
-static const MBtab MB_B [] = {
-   {0,                 0}, {INTRA|QUANT,       6},
-   {BWD|CODED|QUANT,   6}, {FWD|CODED|QUANT,   6},
-   {INTER|CODED|QUANT, 5}, {INTER|CODED|QUANT, 5},
-                                     {INTRA,       5}, {INTRA,       5},
-   {FWD,         4}, {FWD,         4}, {FWD,         4}, {FWD,         4},
-   {FWD|CODED,   4}, {FWD|CODED,   4}, {FWD|CODED,   4}, {FWD|CODED,   4},
-   {BWD,         3}, {BWD,         3}, {BWD,         3}, {BWD,         3},
-   {BWD,         3}, {BWD,         3}, {BWD,         3}, {BWD,         3},
-   {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3},
-   {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3}, {BWD|CODED,   3},
-   {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
-   {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
-   {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
-   {INTER,       2}, {INTER,       2}, {INTER,       2}, {INTER,       2},
-   {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
-   {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
-   {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2},
-   {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}, {INTER|CODED, 2}
+/* coding table as found in the spec annex B.5 table B-1 */
+static const struct vl_vlc_compressed macroblock_address_increment[] = {
+   { 0x8000, { 1, 1 } },
+   { 0x6000, { 3, 2 } },
+   { 0x4000, { 3, 3 } },
+   { 0x3000, { 4, 4 } },
+   { 0x2000, { 4, 5 } },
+   { 0x1800, { 5, 6 } },
+   { 0x1000, { 5, 7 } },
+   { 0x0e00, { 7, 8 } },
+   { 0x0c00, { 7, 9 } },
+   { 0x0b00, { 8, 10 } },
+   { 0x0a00, { 8, 11 } },
+   { 0x0900, { 8, 12 } },
+   { 0x0800, { 8, 13 } },
+   { 0x0700, { 8, 14 } },
+   { 0x0600, { 8, 15 } },
+   { 0x05c0, { 10, 16 } },
+   { 0x0580, { 10, 17 } },
+   { 0x0540, { 10, 18 } },
+   { 0x0500, { 10, 19 } },
+   { 0x04c0, { 10, 20 } },
+   { 0x0480, { 10, 21 } },
+   { 0x0460, { 11, 22 } },
+   { 0x0440, { 11, 23 } },
+   { 0x0420, { 11, 24 } },
+   { 0x0400, { 11, 25 } },
+   { 0x03e0, { 11, 26 } },
+   { 0x03c0, { 11, 27 } },
+   { 0x03a0, { 11, 28 } },
+   { 0x0380, { 11, 29 } },
+   { 0x0360, { 11, 30 } },
+   { 0x0340, { 11, 31 } },
+   { 0x0320, { 11, 32 } },
+   { 0x0300, { 11, 33 } }
 };
 
-#undef INTRA
-#undef QUANT
-#undef MC
-#undef CODED
-#undef FWD
-#undef BWD
-#undef INTER
+#define Q PIPE_MPEG12_MB_TYPE_QUANT
+#define F PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
+#define B PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
+#define P PIPE_MPEG12_MB_TYPE_PATTERN
+#define I PIPE_MPEG12_MB_TYPE_INTRA
 
-static const MVtab MV_4 [] = {
-   { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
+/* coding table as found in the spec annex B.5 table B-2 */
+static const struct vl_vlc_compressed macroblock_type_i[] = {
+   { 0x8000, { 1, I } },
+   { 0x4000, { 2, Q|I } }
 };
 
-static const MVtab MV_10 [] = {
-   { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10}, { 0,10},
-   { 0,10}, { 0,10}, { 0,10}, { 0,10}, {15,10}, {14,10}, {13,10}, {12,10},
-   {11,10}, {10,10}, { 9, 9}, { 9, 9}, { 8, 9}, { 8, 9}, { 7, 9}, { 7, 9},
-   { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7}, { 6, 7},
-   { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7}, { 5, 7},
-   { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}, { 4, 7}
+/* coding table as found in the spec annex B.5 table B-3 */
+static const struct vl_vlc_compressed macroblock_type_p[] = {
+   { 0x8000, { 1, F|P } },
+   { 0x4000, { 2, P } },
+   { 0x2000, { 3, F } },
+   { 0x1800, { 5, I } },
+   { 0x1000, { 5, Q|F|P } },
+   { 0x0800, { 5, Q|P } },
+   { 0x0400, { 6, Q|I } }
 };
 
-static const DMVtab DMV_2 [] = {
-   { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
+/* coding table as found in the spec annex B.5 table B-4 */
+static const struct vl_vlc_compressed macroblock_type_b[] = {
+   { 0x8000, { 2, F|B } },
+   { 0xC000, { 2, F|B|P } },
+   { 0x4000, { 3, B } },
+   { 0x6000, { 3, B|P } },
+   { 0x2000, { 4, F } },
+   { 0x3000, { 4, F|P } },
+   { 0x1800, { 5, I } },
+   { 0x1000, { 5, Q|F|B|P } },
+   { 0x0C00, { 6, Q|F|P } },
+   { 0x0800, { 6, Q|B|P } },
+   { 0x0400, { 6, Q|I } }
 };
 
-static const CBPtab CBP_7 [] = {
-   {0x22, 7}, {0x12, 7}, {0x0a, 7}, {0x06, 7},
-   {0x21, 7}, {0x11, 7}, {0x09, 7}, {0x05, 7},
-   {0x3f, 6}, {0x3f, 6}, {0x03, 6}, {0x03, 6},
-   {0x24, 6}, {0x24, 6}, {0x18, 6}, {0x18, 6},
-   {0x3e, 5}, {0x3e, 5}, {0x3e, 5}, {0x3e, 5},
-   {0x02, 5}, {0x02, 5}, {0x02, 5}, {0x02, 5},
-   {0x3d, 5}, {0x3d, 5}, {0x3d, 5}, {0x3d, 5},
-   {0x01, 5}, {0x01, 5}, {0x01, 5}, {0x01, 5},
-   {0x38, 5}, {0x38, 5}, {0x38, 5}, {0x38, 5},
-   {0x34, 5}, {0x34, 5}, {0x34, 5}, {0x34, 5},
-   {0x2c, 5}, {0x2c, 5}, {0x2c, 5}, {0x2c, 5},
-   {0x1c, 5}, {0x1c, 5}, {0x1c, 5}, {0x1c, 5},
-   {0x28, 5}, {0x28, 5}, {0x28, 5}, {0x28, 5},
-   {0x14, 5}, {0x14, 5}, {0x14, 5}, {0x14, 5},
-   {0x30, 5}, {0x30, 5}, {0x30, 5}, {0x30, 5},
-   {0x0c, 5}, {0x0c, 5}, {0x0c, 5}, {0x0c, 5},
-   {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
-   {0x20, 4}, {0x20, 4}, {0x20, 4}, {0x20, 4},
-   {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
-   {0x10, 4}, {0x10, 4}, {0x10, 4}, {0x10, 4},
-   {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
-   {0x08, 4}, {0x08, 4}, {0x08, 4}, {0x08, 4},
-   {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
-   {0x04, 4}, {0x04, 4}, {0x04, 4}, {0x04, 4},
-   {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
-   {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
-   {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3},
-   {0x3c, 3}, {0x3c, 3}, {0x3c, 3}, {0x3c, 3}
+#undef Q
+#undef F
+#undef B
+#undef P
+#undef I
+
+/* coding table as found in the spec annex B.5 table B-9 */
+static const struct vl_vlc_compressed coded_block_pattern[] = {
+   { 0xE000, { 3, 60 } },
+   { 0xD000, { 4, 4 } },
+   { 0xC000, { 4, 8 } },
+   { 0xB000, { 4, 16 } },
+   { 0xA000, { 4, 32 } },
+   { 0x9800, { 5, 12 } },
+   { 0x9000, { 5, 48 } },
+   { 0x8800, { 5, 20 } },
+   { 0x8000, { 5, 40 } },
+   { 0x7800, { 5, 28 } },
+   { 0x7000, { 5, 44 } },
+   { 0x6800, { 5, 52 } },
+   { 0x6000, { 5, 56 } },
+   { 0x5800, { 5, 1 } },
+   { 0x5000, { 5, 61 } },
+   { 0x4800, { 5, 2 } },
+   { 0x4000, { 5, 62 } },
+   { 0x3C00, { 6, 24 } },
+   { 0x3800, { 6, 36 } },
+   { 0x3400, { 6, 3 } },
+   { 0x3000, { 6, 63 } },
+   { 0x2E00, { 7, 5 } },
+   { 0x2C00, { 7, 9 } },
+   { 0x2A00, { 7, 17 } },
+   { 0x2800, { 7, 33 } },
+   { 0x2600, { 7, 6 } },
+   { 0x2400, { 7, 10 } },
+   { 0x2200, { 7, 18 } },
+   { 0x2000, { 7, 34 } },
+   { 0x1F00, { 8, 7 } },
+   { 0x1E00, { 8, 11 } },
+   { 0x1D00, { 8, 19 } },
+   { 0x1C00, { 8, 35 } },
+   { 0x1B00, { 8, 13 } },
+   { 0x1A00, { 8, 49 } },
+   { 0x1900, { 8, 21 } },
+   { 0x1800, { 8, 41 } },
+   { 0x1700, { 8, 14 } },
+   { 0x1600, { 8, 50 } },
+   { 0x1500, { 8, 22 } },
+   { 0x1400, { 8, 42 } },
+   { 0x1300, { 8, 15 } },
+   { 0x1200, { 8, 51 } },
+   { 0x1100, { 8, 23 } },
+   { 0x1000, { 8, 43 } },
+   { 0x0F00, { 8, 25 } },
+   { 0x0E00, { 8, 37 } },
+   { 0x0D00, { 8, 26 } },
+   { 0x0C00, { 8, 38 } },
+   { 0x0B00, { 8, 29 } },
+   { 0x0A00, { 8, 45 } },
+   { 0x0900, { 8, 53 } },
+   { 0x0800, { 8, 57 } },
+   { 0x0700, { 8, 30 } },
+   { 0x0600, { 8, 46 } },
+   { 0x0500, { 8, 54 } },
+   { 0x0400, { 8, 58 } },
+   { 0x0380, { 9, 31 } },
+   { 0x0300, { 9, 47 } },
+   { 0x0280, { 9, 55 } },
+   { 0x0200, { 9, 59 } },
+   { 0x0180, { 9, 27 } },
+   { 0x0100, { 9, 39 } },
+   { 0x0080, { 9, 0 } }
 };
 
-static const CBPtab CBP_9 [] = {
-   {0,    0}, {0x00, 9}, {0x27, 9}, {0x1b, 9},
-   {0x3b, 9}, {0x37, 9}, {0x2f, 9}, {0x1f, 9},
-   {0x3a, 8}, {0x3a, 8}, {0x36, 8}, {0x36, 8},
-   {0x2e, 8}, {0x2e, 8}, {0x1e, 8}, {0x1e, 8},
-   {0x39, 8}, {0x39, 8}, {0x35, 8}, {0x35, 8},
-   {0x2d, 8}, {0x2d, 8}, {0x1d, 8}, {0x1d, 8},
-   {0x26, 8}, {0x26, 8}, {0x1a, 8}, {0x1a, 8},
-   {0x25, 8}, {0x25, 8}, {0x19, 8}, {0x19, 8},
-   {0x2b, 8}, {0x2b, 8}, {0x17, 8}, {0x17, 8},
-   {0x33, 8}, {0x33, 8}, {0x0f, 8}, {0x0f, 8},
-   {0x2a, 8}, {0x2a, 8}, {0x16, 8}, {0x16, 8},
-   {0x32, 8}, {0x32, 8}, {0x0e, 8}, {0x0e, 8},
-   {0x29, 8}, {0x29, 8}, {0x15, 8}, {0x15, 8},
-   {0x31, 8}, {0x31, 8}, {0x0d, 8}, {0x0d, 8},
-   {0x23, 8}, {0x23, 8}, {0x13, 8}, {0x13, 8},
-   {0x0b, 8}, {0x0b, 8}, {0x07, 8}, {0x07, 8}
+/* coding table as found in the spec annex B.5 table B-10 */
+static const struct vl_vlc_compressed motion_code[] = {
+   { 0x0320, { 11, -16 } },
+   { 0x0360, { 11, -15 } },
+   { 0x03a0, { 11, -14 } },
+   { 0x03e0, { 11, -13 } },
+   { 0x0420, { 11, -12 } },
+   { 0x0460, { 11, -11 } },
+   { 0x04c0, { 10, -10 } },
+   { 0x0540, { 10, -9 } },
+   { 0x05c0, { 10, -8 } },
+   { 0x0700, { 8, -7 } },
+   { 0x0900, { 8, -6 } },
+   { 0x0b00, { 8, -5 } },
+   { 0x0e00, { 7, -4 } },
+   { 0x1800, { 5, -3 } },
+   { 0x3000, { 4, -2 } },
+   { 0x6000, { 3, -1 } },
+   { 0x8000, { 1, 0 } },
+   { 0x4000, { 3, 1 } },
+   { 0x2000, { 4, 2 } },
+   { 0x1000, { 5, 3 } },
+   { 0x0c00, { 7, 4 } },
+   { 0x0a00, { 8, 5 } },
+   { 0x0800, { 8, 6 } },
+   { 0x0600, { 8, 7 } },
+   { 0x0580, { 10, 8 } },
+   { 0x0500, { 10, 9 } },
+   { 0x0480, { 10, 10 } },
+   { 0x0440, { 11, 11 } },
+   { 0x0400, { 11, 12 } },
+   { 0x03c0, { 11, 13 } },
+   { 0x0380, { 11, 14 } },
+   { 0x0340, { 11, 15 } },
+   { 0x0300, { 11, 16 } }
 };
 
-static const DCtab DC_lum_5 [] = {
-   {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
-   {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
-   {0, 3}, {0, 3}, {0, 3}, {0, 3}, {3, 3}, {3, 3}, {3, 3}, {3, 3},
-   {4, 3}, {4, 3}, {4, 3}, {4, 3}, {5, 4}, {5, 4}, {6, 5}
+/* coding table as found in the spec annex B.5 table B-11 */
+static const struct vl_vlc_compressed dmvector[] = {
+   { 0x0000, { 1, 0 } },
+   { 0x8000, { 2, 1 } },
+   { 0xc000, { 2, -1 } }
 };
 
-static const DCtab DC_chrom_5 [] = {
-   {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2}, {0, 2},
-   {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2}, {1, 2},
-   {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2}, {2, 2},
-   {3, 3}, {3, 3}, {3, 3}, {3, 3}, {4, 4}, {4, 4}, {5, 5}
+/* coding table as found in the spec annex B.5 table B-12 */
+static const struct vl_vlc_compressed dct_dc_size_luminance[] = {
+   { 0x8000, { 3, 0 } },
+   { 0x0000, { 2, 1 } },
+   { 0x4000, { 2, 2 } },
+   { 0xA000, { 3, 3 } },
+   { 0xC000, { 3, 4 } },
+   { 0xE000, { 4, 5 } },
+   { 0xF000, { 5, 6 } },
+   { 0xF800, { 6, 7 } },
+   { 0xFC00, { 7, 8 } },
+   { 0xFE00, { 8, 9 } },
+   { 0xFF00, { 9, 10 } },
+   { 0xFF80, { 9, 11 } }
 };
 
-static const DCtab DC_long [] = {
-   {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
-   {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, {6, 5}, { 6, 5}, { 6, 5},
-   {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, {7, 6}, { 7, 6}, { 7, 6},
-   {8, 7}, {8, 7}, {8, 7}, {8, 7}, {9, 8}, {9, 8}, {10, 9}, {11, 9}
+/* coding table as found in the spec annex B.5 table B-13 */
+static const struct vl_vlc_compressed dct_dc_size_chrominance[] = {
+   { 0x0000, { 2, 0 } },
+   { 0x4000, { 2, 1 } },
+   { 0x8000, { 2, 2 } },
+   { 0xC000, { 3, 3 } },
+   { 0xE000, { 4, 4 } },
+   { 0xF000, { 5, 5 } },
+   { 0xF800, { 6, 6 } },
+   { 0xFC00, { 7, 7 } },
+   { 0xFE00, { 8, 8 } },
+   { 0xFF00, { 9, 9 } },
+   { 0xFF80, { 10, 10 } },
+   { 0xFFC0, { 10, 11 } }
 };
 
-static const DCTtab DCT_16 [] = {
-   {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
-   {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
-   {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
-   {129, 0, 0}, {129, 0, 0}, {129, 0, 0}, {129, 0, 0},
-   {  2,18, 0}, {  2,17, 0}, {  2,16, 0}, {  2,15, 0},
-   {  7, 3, 0}, { 17, 2, 0}, { 16, 2, 0}, { 15, 2, 0},
-   { 14, 2, 0}, { 13, 2, 0}, { 12, 2, 0}, { 32, 1, 0},
-   { 31, 1, 0}, { 30, 1, 0}, { 29, 1, 0}, { 28, 1, 0}
+/* coding table as found in the spec annex B.5 table B-14 */
+static const struct dct_coeff_compressed dct_coeff_tbl_zero[] = {
+   { 0x8000, { 2, dct_End_of_Block, 0 } },
+   { 0x8000, { 1, dct_DC, 1 } },
+   { 0xC000, { 2, dct_AC, 1 } },
+   { 0x6000, { 3, 1, 1 } },
+   { 0x4000, { 4, 0, 2 } },
+   { 0x5000, { 4, 2, 1 } },
+   { 0x2800, { 5, 0, 3 } },
+   { 0x3800, { 5, 3, 1 } },
+   { 0x3000, { 5, 4, 1 } },
+   { 0x1800, { 6, 1, 2 } },
+   { 0x1C00, { 6, 5, 1 } },
+   { 0x1400, { 6, 6, 1 } },
+   { 0x1000, { 6, 7, 1 } },
+   { 0x0C00, { 7, 0, 4 } },
+   { 0x0800, { 7, 2, 2 } },
+   { 0x0E00, { 7, 8, 1 } },
+   { 0x0A00, { 7, 9, 1 } },
+   { 0x0400, { 6, dct_Escape, 0 } },
+   { 0x2600, { 8, 0, 5 } },
+   { 0x2100, { 8, 0, 6 } },
+   { 0x2500, { 8, 1, 3 } },
+   { 0x2400, { 8, 3, 2 } },
+   { 0x2700, { 8, 10, 1 } },
+   { 0x2300, { 8, 11, 1 } },
+   { 0x2200, { 8, 12, 1 } },
+   { 0x2000, { 8, 13, 1 } },
+   { 0x0280, { 10, 0, 7 } },
+   { 0x0300, { 10, 1, 4 } },
+   { 0x02C0, { 10, 2, 3 } },
+   { 0x03C0, { 10, 4, 2 } },
+   { 0x0240, { 10, 5, 2 } },
+   { 0x0380, { 10, 14, 1 } },
+   { 0x0340, { 10, 15, 1 } },
+   { 0x0200, { 10, 16, 1 } },
+   { 0x01D0, { 12, 0, 8 } },
+   { 0x0180, { 12, 0, 9 } },
+   { 0x0130, { 12, 0, 10 } },
+   { 0x0100, { 12, 0, 11 } },
+   { 0x01B0, { 12, 1, 5 } },
+   { 0x0140, { 12, 2, 4 } },
+   { 0x01C0, { 12, 3, 3 } },
+   { 0x0120, { 12, 4, 3 } },
+   { 0x01E0, { 12, 6, 2 } },
+   { 0x0150, { 12, 7, 2 } },
+   { 0x0110, { 12, 8, 2 } },
+   { 0x01F0, { 12, 17, 1 } },
+   { 0x01A0, { 12, 18, 1 } },
+   { 0x0190, { 12, 19, 1 } },
+   { 0x0170, { 12, 20, 1 } },
+   { 0x0160, { 12, 21, 1 } },
+   { 0x00D0, { 13, 0, 12 } },
+   { 0x00C8, { 13, 0, 13 } },
+   { 0x00C0, { 13, 0, 14 } },
+   { 0x00B8, { 13, 0, 15 } },
+   { 0x00B0, { 13, 1, 6 } },
+   { 0x00A8, { 13, 1, 7 } },
+   { 0x00A0, { 13, 2, 5 } },
+   { 0x0098, { 13, 3, 4 } },
+   { 0x0090, { 13, 5, 3 } },
+   { 0x0088, { 13, 9, 2 } },
+   { 0x0080, { 13, 10, 2 } },
+   { 0x00F8, { 13, 22, 1 } },
+   { 0x00F0, { 13, 23, 1 } },
+   { 0x00E8, { 13, 24, 1 } },
+   { 0x00E0, { 13, 25, 1 } },
+   { 0x00D8, { 13, 26, 1 } },
+   { 0x007C, { 14, 0, 16 } },
+   { 0x0078, { 14, 0, 17 } },
+   { 0x0074, { 14, 0, 18 } },
+   { 0x0070, { 14, 0, 19 } },
+   { 0x006C, { 14, 0, 20 } },
+   { 0x0068, { 14, 0, 21 } },
+   { 0x0064, { 14, 0, 22 } },
+   { 0x0060, { 14, 0, 23 } },
+   { 0x005C, { 14, 0, 24 } },
+   { 0x0058, { 14, 0, 25 } },
+   { 0x0054, { 14, 0, 26 } },
+   { 0x0050, { 14, 0, 27 } },
+   { 0x004C, { 14, 0, 28 } },
+   { 0x0048, { 14, 0, 29 } },
+   { 0x0044, { 14, 0, 30 } },
+   { 0x0040, { 14, 0, 31 } },
+   { 0x0030, { 15, 0, 32 } },
+   { 0x002E, { 15, 0, 33 } },
+   { 0x002C, { 15, 0, 34 } },
+   { 0x002A, { 15, 0, 35 } },
+   { 0x0028, { 15, 0, 36 } },
+   { 0x0026, { 15, 0, 37 } },
+   { 0x0024, { 15, 0, 38 } },
+   { 0x0022, { 15, 0, 39 } },
+   { 0x0020, { 15, 0, 40 } },
+   { 0x003E, { 15, 1, 8 } },
+   { 0x003C, { 15, 1, 9 } },
+   { 0x003A, { 15, 1, 10 } },
+   { 0x0038, { 15, 1, 11 } },
+   { 0x0036, { 15, 1, 12 } },
+   { 0x0034, { 15, 1, 13 } },
+   { 0x0032, { 15, 1, 14 } },
+   { 0x0013, { 16, 1, 15 } },
+   { 0x0012, { 16, 1, 16 } },
+   { 0x0011, { 16, 1, 17 } },
+   { 0x0010, { 16, 1, 18 } },
+   { 0x0014, { 16, 6, 3 } },
+   { 0x001A, { 16, 11, 2 } },
+   { 0x0019, { 16, 12, 2 } },
+   { 0x0018, { 16, 13, 2 } },
+   { 0x0017, { 16, 14, 2 } },
+   { 0x0016, { 16, 15, 2 } },
+   { 0x0015, { 16, 16, 2 } },
+   { 0x001F, { 16, 27, 1 } },
+   { 0x001E, { 16, 28, 1 } },
+   { 0x001D, { 16, 29, 1 } },
+   { 0x001C, { 16, 30, 1 } },
+   { 0x001B, { 16, 31, 1 } }
 };
 
-static const DCTtab DCT_15 [] = {
-   {  1,40,15}, {  1,39,15}, {  1,38,15}, {  1,37,15},
-   {  1,36,15}, {  1,35,15}, {  1,34,15}, {  1,33,15},
-   {  1,32,15}, {  2,14,15}, {  2,13,15}, {  2,12,15},
-   {  2,11,15}, {  2,10,15}, {  2, 9,15}, {  2, 8,15},
-   {  1,31,14}, {  1,31,14}, {  1,30,14}, {  1,30,14},
-   {  1,29,14}, {  1,29,14}, {  1,28,14}, {  1,28,14},
-   {  1,27,14}, {  1,27,14}, {  1,26,14}, {  1,26,14},
-   {  1,25,14}, {  1,25,14}, {  1,24,14}, {  1,24,14},
-   {  1,23,14}, {  1,23,14}, {  1,22,14}, {  1,22,14},
-   {  1,21,14}, {  1,21,14}, {  1,20,14}, {  1,20,14},
-   {  1,19,14}, {  1,19,14}, {  1,18,14}, {  1,18,14},
-   {  1,17,14}, {  1,17,14}, {  1,16,14}, {  1,16,14}
+/* coding table as found in the spec annex B.5 table B-15 */
+static const struct dct_coeff_compressed dct_coeff_tbl_one[] = {
+   { 0x6000, { 4, dct_End_of_Block, 0 } },
+   { 0x8000, { 2, 0, 1 } },
+   { 0x4000, { 3, 1, 1 } },
+   { 0xC000, { 3, 0, 2 } },
+   { 0x2800, { 5, 2, 1 } },
+   { 0x7000, { 4, 0, 3 } },
+   { 0x3800, { 5, 3, 1 } },
+   { 0x1800, { 6, 4, 1 } },
+   { 0x3000, { 5, 1, 2 } },
+   { 0x1C00, { 6, 5, 1 } },
+   { 0x0C00, { 7, 6, 1 } },
+   { 0x0800, { 7, 7, 1 } },
+   { 0xE000, { 5, 0, 4 } },
+   { 0x0E00, { 7, 2, 2 } },
+   { 0x0A00, { 7, 8, 1 } },
+   { 0xF000, { 7, 9, 1 } },
+   { 0x0400, { 6, dct_Escape, 0 } },
+   { 0xE800, { 5, 0, 5 } },
+   { 0x1400, { 6, 0, 6 } },
+   { 0xF200, { 7, 1, 3 } },
+   { 0x2600, { 8, 3, 2 } },
+   { 0xF400, { 7, 10, 1 } },
+   { 0x2100, { 8, 11, 1 } },
+   { 0x2500, { 8, 12, 1 } },
+   { 0x2400, { 8, 13, 1 } },
+   { 0x1000, { 6, 0, 7 } },
+   { 0x2700, { 8, 1, 4 } },
+   { 0xFC00, { 8, 2, 3 } },
+   { 0xFD00, { 8, 4, 2 } },
+   { 0x0200, { 9, 5, 2 } },
+   { 0x0280, { 9, 14, 1 } },
+   { 0x0380, { 9, 15, 1 } },
+   { 0x0340, { 10, 16, 1 } },
+   { 0xF600, { 7, 0, 8 } },
+   { 0xF800, { 7, 0, 9 } },
+   { 0x2300, { 8, 0, 10 } },
+   { 0x2200, { 8, 0, 11 } },
+   { 0x2000, { 8, 1, 5 } },
+   { 0x0300, { 10, 2, 4 } },
+   { 0x01C0, { 12, 3, 3 } },
+   { 0x0120, { 12, 4, 3 } },
+   { 0x01E0, { 12, 6, 2 } },
+   { 0x0150, { 12, 7, 2 } },
+   { 0x0110, { 12, 8, 2 } },
+   { 0x01F0, { 12, 17, 1 } },
+   { 0x01A0, { 12, 18, 1 } },
+   { 0x0190, { 12, 19, 1 } },
+   { 0x0170, { 12, 20, 1 } },
+   { 0x0160, { 12, 21, 1 } },
+   { 0xFA00, { 8, 0, 12 } },
+   { 0xFB00, { 8, 0, 13 } },
+   { 0xFE00, { 8, 0, 14 } },
+   { 0xFF00, { 8, 0, 15 } },
+   { 0x00B0, { 13, 1, 6 } },
+   { 0x00A8, { 13, 1, 7 } },
+   { 0x00A0, { 13, 2, 5 } },
+   { 0x0098, { 13, 3, 4 } },
+   { 0x0090, { 13, 5, 3 } },
+   { 0x0088, { 13, 9, 2 } },
+   { 0x0080, { 13, 10, 2 } },
+   { 0x00F8, { 13, 22, 1 } },
+   { 0x00F0, { 13, 23, 1 } },
+   { 0x00E8, { 13, 24, 1 } },
+   { 0x00E0, { 13, 25, 1 } },
+   { 0x00D8, { 13, 26, 1 } },
+   { 0x007C, { 14, 0, 16 } },
+   { 0x0078, { 14, 0, 17 } },
+   { 0x0074, { 14, 0, 18 } },
+   { 0x0070, { 14, 0, 19 } },
+   { 0x006C, { 14, 0, 20 } },
+   { 0x0068, { 14, 0, 21 } },
+   { 0x0064, { 14, 0, 22 } },
+   { 0x0060, { 14, 0, 23 } },
+   { 0x005C, { 14, 0, 24 } },
+   { 0x0058, { 14, 0, 25 } },
+   { 0x0054, { 14, 0, 26 } },
+   { 0x0050, { 14, 0, 27 } },
+   { 0x004C, { 14, 0, 28 } },
+   { 0x0048, { 14, 0, 29 } },
+   { 0x0044, { 14, 0, 30 } },
+   { 0x0040, { 14, 0, 31 } },
+   { 0x0030, { 15, 0, 32 } },
+   { 0x002E, { 15, 0, 33 } },
+   { 0x002C, { 15, 0, 34 } },
+   { 0x002A, { 15, 0, 35 } },
+   { 0x0028, { 15, 0, 36 } },
+   { 0x0026, { 15, 0, 37 } },
+   { 0x0024, { 15, 0, 38 } },
+   { 0x0022, { 15, 0, 39 } },
+   { 0x0020, { 15, 0, 40 } },
+   { 0x003E, { 15, 1, 8 } },
+   { 0x003C, { 15, 1, 9 } },
+   { 0x003A, { 15, 1, 10 } },
+   { 0x0038, { 15, 1, 11 } },
+   { 0x0036, { 15, 1, 12 } },
+   { 0x0034, { 15, 1, 13 } },
+   { 0x0032, { 15, 1, 14 } },
+   { 0x0013, { 16, 1, 15 } },
+   { 0x0012, { 16, 1, 16 } },
+   { 0x0011, { 16, 1, 17 } },
+   { 0x0010, { 16, 1, 18 } },
+   { 0x0014, { 16, 6, 3 } },
+   { 0x001A, { 16, 11, 2 } },
+   { 0x0019, { 16, 12, 2 } },
+   { 0x0018, { 16, 13, 2 } },
+   { 0x0017, { 16, 14, 2 } },
+   { 0x0016, { 16, 15, 2 } },
+   { 0x0015, { 16, 16, 2 } },
+   { 0x001F, { 16, 27, 1 } },
+   { 0x001E, { 16, 28, 1 } },
+   { 0x001D, { 16, 29, 1 } },
+   { 0x001C, { 16, 30, 1 } },
+   { 0x001B, { 16, 31, 1 } }
 };
 
-static const DCTtab DCT_13 [] = {
-   { 11, 2,13}, { 10, 2,13}, {  6, 3,13}, {  4, 4,13},
-   {  3, 5,13}, {  2, 7,13}, {  2, 6,13}, {  1,15,13},
-   {  1,14,13}, {  1,13,13}, {  1,12,13}, { 27, 1,13},
-   { 26, 1,13}, { 25, 1,13}, { 24, 1,13}, { 23, 1,13},
-   {  1,11,12}, {  1,11,12}, {  9, 2,12}, {  9, 2,12},
-   {  5, 3,12}, {  5, 3,12}, {  1,10,12}, {  1,10,12},
-   {  3, 4,12}, {  3, 4,12}, {  8, 2,12}, {  8, 2,12},
-   { 22, 1,12}, { 22, 1,12}, { 21, 1,12}, { 21, 1,12},
-   {  1, 9,12}, {  1, 9,12}, { 20, 1,12}, { 20, 1,12},
-   { 19, 1,12}, { 19, 1,12}, {  2, 5,12}, {  2, 5,12},
-   {  4, 3,12}, {  4, 3,12}, {  1, 8,12}, {  1, 8,12},
-   {  7, 2,12}, {  7, 2,12}, { 18, 1,12}, { 18, 1,12}
+/* q_scale_type */
+static const unsigned quant_scale[2][32] = {
+  { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+    32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 },
+  { 0, 1, 2, 3, 4,  5,  6,  7,  8, 10, 12, 14, 16, 18, 20, 22, 24,
+    28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }
 };
 
-static const DCTtab DCT_B14_10 [] = {
-   { 17, 1,10}, {  6, 2,10}, {  1, 7,10}, {  3, 3,10},
-   {  2, 4,10}, { 16, 1,10}, { 15, 1,10}, {  5, 2,10}
-};
+static struct vl_vlc_entry tbl_B1[1 << 11];
+static struct vl_vlc_entry tbl_B2[1 << 2];
+static struct vl_vlc_entry tbl_B3[1 << 6];
+static struct vl_vlc_entry tbl_B4[1 << 6];
+static struct vl_vlc_entry tbl_B9[1 << 9];
+static struct vl_vlc_entry tbl_B10[1 << 11];
+static struct vl_vlc_entry tbl_B11[1 << 2];
+static struct vl_vlc_entry tbl_B12[1 << 10];
+static struct vl_vlc_entry tbl_B13[1 << 10];
+static struct dct_coeff tbl_B14_DC[1 << 17];
+static struct dct_coeff tbl_B14_AC[1 << 17];
+static struct dct_coeff tbl_B15[1 << 17];
+
+static INLINE void
+init_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *src,
+                     unsigned size, bool is_DC)
+{
+   unsigned i;
 
-static const DCTtab DCT_B14_8 [] = {
-   { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
-   {  3, 2, 7}, {  3, 2, 7}, { 10, 1, 7}, { 10, 1, 7},
-   {  1, 4, 7}, {  1, 4, 7}, {  9, 1, 7}, {  9, 1, 7},
-   {  8, 1, 6}, {  8, 1, 6}, {  8, 1, 6}, {  8, 1, 6},
-   {  7, 1, 6}, {  7, 1, 6}, {  7, 1, 6}, {  7, 1, 6},
-   {  2, 2, 6}, {  2, 2, 6}, {  2, 2, 6}, {  2, 2, 6},
-   {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6},
-   { 14, 1, 8}, {  1, 6, 8}, { 13, 1, 8}, { 12, 1, 8},
-   {  4, 2, 8}, {  2, 3, 8}, {  1, 5, 8}, { 11, 1, 8}
-};
+   for (i=0;i<(1<<17);++i) {
+      dst[i].length = 0;
+      dst[i].level = 0;
+      dst[i].run = dct_End_of_Block;
+   }
 
-static const DCTtab DCT_B14AC_5 [] = {
-                {  1, 3, 5}, {  5, 1, 5}, {  4, 1, 5},
-   {  1, 2, 4}, {  1, 2, 4}, {  3, 1, 4}, {  3, 1, 4},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
-   {129, 0, 2}, {129, 0, 2}, {129, 0, 2}, {129, 0, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}
-};
+   for(; size > 0; --size, ++src) {
+      struct dct_coeff coeff = src->coeff;
+      bool has_sign = true;
 
-static const DCTtab DCT_B14DC_5 [] = {
-                {  1, 3, 5}, {  5, 1, 5}, {  4, 1, 5},
-   {  1, 2, 4}, {  1, 2, 4}, {  3, 1, 4}, {  3, 1, 4},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
-   {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
-   {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1},
-   {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}, {  1, 1, 1}
-};
+      switch (coeff.run) {
+      case dct_End_of_Block:
+         if (is_DC)
+            continue;
 
-static const DCTtab DCT_B15_10 [] = {
-   {  6, 2, 9}, {  6, 2, 9}, { 15, 1, 9}, { 15, 1, 9},
-   {  3, 4,10}, { 17, 1,10}, { 16, 1, 9}, { 16, 1, 9}
-};
+         has_sign = false;
+         break;
 
-static const DCTtab DCT_B15_8 [] = {
-   { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6}, { 65, 0, 6},
-   {  8, 1, 7}, {  8, 1, 7}, {  9, 1, 7}, {  9, 1, 7},
-   {  7, 1, 7}, {  7, 1, 7}, {  3, 2, 7}, {  3, 2, 7},
-   {  1, 7, 6}, {  1, 7, 6}, {  1, 7, 6}, {  1, 7, 6},
-   {  1, 6, 6}, {  1, 6, 6}, {  1, 6, 6}, {  1, 6, 6},
-   {  5, 1, 6}, {  5, 1, 6}, {  5, 1, 6}, {  5, 1, 6},
-   {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6}, {  6, 1, 6},
-   {  2, 5, 8}, { 12, 1, 8}, {  1,11, 8}, {  1,10, 8},
-   { 14, 1, 8}, { 13, 1, 8}, {  4, 2, 8}, {  2, 4, 8},
-   {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5},
-   {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5}, {  3, 1, 5},
-   {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5},
-   {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5}, {  2, 2, 5},
-   {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5},
-   {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5}, {  4, 1, 5},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3}, {  2, 1, 3},
-   {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
-   {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
-   {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
-   {129, 0, 4}, {129, 0, 4}, {129, 0, 4}, {129, 0, 4},
-   {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
-   {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
-   {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
-   {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4}, {  1, 3, 4},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2}, {  1, 1, 2},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3}, {  1, 2, 3},
-   {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5},
-   {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5}, {  1, 4, 5},
-   {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5},
-   {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5}, {  1, 5, 5},
-   { 10, 1, 7}, { 10, 1, 7}, {  2, 3, 7}, {  2, 3, 7},
-   { 11, 1, 7}, { 11, 1, 7}, {  1, 8, 7}, {  1, 8, 7},
-   {  1, 9, 7}, {  1, 9, 7}, {  1,12, 8}, {  1,13, 8},
-   {  3, 3, 8}, {  5, 2, 8}, {  1,14, 8}, {  1,15, 8}
-};
+      case dct_Escape:
+         has_sign = false;
+         break;
 
-static const MBAtab MBA_5 [] = {
-                   {6, 5}, {5, 5}, {4, 4}, {4, 4}, {3, 4}, {3, 4},
-   {2, 3}, {2, 3}, {2, 3}, {2, 3}, {1, 3}, {1, 3}, {1, 3}, {1, 3},
-   {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1},
-   {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}
-};
+      case dct_DC:
+         if (!is_DC)
+            continue;
 
-static const MBAtab MBA_11 [] = {
-   {32, 11}, {31, 11}, {30, 11}, {29, 11},
-   {28, 11}, {27, 11}, {26, 11}, {25, 11},
-   {24, 11}, {23, 11}, {22, 11}, {21, 11},
-   {20, 10}, {20, 10}, {19, 10}, {19, 10},
-   {18, 10}, {18, 10}, {17, 10}, {17, 10},
-   {16, 10}, {16, 10}, {15, 10}, {15, 10},
-   {14,  8}, {14,  8}, {14,  8}, {14,  8},
-   {14,  8}, {14,  8}, {14,  8}, {14,  8},
-   {13,  8}, {13,  8}, {13,  8}, {13,  8},
-   {13,  8}, {13,  8}, {13,  8}, {13,  8},
-   {12,  8}, {12,  8}, {12,  8}, {12,  8},
-   {12,  8}, {12,  8}, {12,  8}, {12,  8},
-   {11,  8}, {11,  8}, {11,  8}, {11,  8},
-   {11,  8}, {11,  8}, {11,  8}, {11,  8},
-   {10,  8}, {10,  8}, {10,  8}, {10,  8},
-   {10,  8}, {10,  8}, {10,  8}, {10,  8},
-   { 9,  8}, { 9,  8}, { 9,  8}, { 9,  8},
-   { 9,  8}, { 9,  8}, { 9,  8}, { 9,  8},
-   { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
-   { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
-   { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
-   { 8,  7}, { 8,  7}, { 8,  7}, { 8,  7},
-   { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7},
-   { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7},
-   { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7},
-   { 7,  7}, { 7,  7}, { 7,  7}, { 7,  7}
-};
+         coeff.length += 1;
+         coeff.run = 1;
+         break;
 
-static const int non_linear_quantizer_scale[] = {
-   0,  1,  2,  3,  4,  5,   6,   7,
-   8, 10, 12, 14, 16, 18,  20,  22,
-   24, 28, 32, 36, 40, 44,  48,  52,
-   56, 64, 72, 80, 88, 96, 104, 112
-};
+      case dct_AC:
+         if (is_DC)
+            continue;
 
-static inline int
-get_macroblock_modes(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture)
-{
-   int macroblock_modes;
-   const MBtab * tab;
-
-   switch (picture->picture_coding_type) {
-   case I_TYPE:
-
-      tab = MB_I + vl_vlc_ubits(&bs->vlc, 1);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      macroblock_modes = tab->modes;
-
-      return macroblock_modes;
-
-   case P_TYPE:
-
-      tab = MB_P + vl_vlc_ubits(&bs->vlc, 5);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      macroblock_modes = tab->modes;
-
-      if (picture->picture_structure != FRAME_PICTURE) {
-         if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) {
-            macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
-            vl_vlc_dumpbits(&bs->vlc, 2);
-          }
-          return macroblock_modes;
-      } else if (picture->frame_pred_frame_dct) {
-          if (macroblock_modes & MACROBLOCK_MOTION_FORWARD)
-            macroblock_modes |= MC_FRAME;
-          return macroblock_modes;
-      } else {
-          if (macroblock_modes & MACROBLOCK_MOTION_FORWARD) {
-            macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
-            vl_vlc_dumpbits(&bs->vlc, 2);
-          }
-          return macroblock_modes;
-      }
+         coeff.length += 1;
+         coeff.run = 1;
+         break;
 
-   case B_TYPE:
-
-      tab = MB_B + vl_vlc_ubits(&bs->vlc, 6);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      macroblock_modes = tab->modes;
-
-      if (picture->picture_structure != FRAME_PICTURE) {
-          if (! (macroblock_modes & MACROBLOCK_INTRA)) {
-            macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
-            vl_vlc_dumpbits(&bs->vlc, 2);
-          }
-      } else if (picture->frame_pred_frame_dct) {
-          macroblock_modes |= MC_FRAME;
-      } else if (!(macroblock_modes & MACROBLOCK_INTRA)) {
-          macroblock_modes |= vl_vlc_ubits(&bs->vlc, 2) * MOTION_TYPE_BASE;
-          vl_vlc_dumpbits(&bs->vlc, 2);
+      default:
+         coeff.length += 1;
+         coeff.run += 1;
+         break;
       }
-      return macroblock_modes;
-
-   case D_TYPE:
 
-      vl_vlc_dumpbits(&bs->vlc, 1);
-      return MACROBLOCK_INTRA;
+      for(i=0; i<(1 << (17 - coeff.length)); ++i)
+         dst[src->bitcode << 1 | i] = coeff;
 
-   default:
-      return 0;
+      if (has_sign) {
+        coeff.level = -coeff.level;
+         for(; i<(1 << (18 - coeff.length)); ++i)
+            dst[src->bitcode << 1 | i] = coeff;
+      }
    }
 }
 
-static inline enum pipe_mpeg12_dct_type
-get_dct_type(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture, int macroblock_modes)
+static INLINE void
+init_tables()
 {
-   enum pipe_mpeg12_dct_type dct_type = PIPE_MPEG12_DCT_TYPE_FRAME;
-
-   if ((picture->picture_structure == FRAME_PICTURE) &&
-       (!picture->frame_pred_frame_dct) &&
-       (macroblock_modes & (MACROBLOCK_INTRA | MACROBLOCK_PATTERN))) {
-
-      dct_type = vl_vlc_ubits(&bs->vlc, 1) ? PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
-      vl_vlc_dumpbits(&bs->vlc, 1);
-   }
-   return dct_type;
+   vl_vlc_init_table(tbl_B1, Elements(tbl_B1), macroblock_address_increment, Elements(macroblock_address_increment));
+   vl_vlc_init_table(tbl_B2, Elements(tbl_B2), macroblock_type_i, Elements(macroblock_type_i));
+   vl_vlc_init_table(tbl_B3, Elements(tbl_B3), macroblock_type_p, Elements(macroblock_type_p));
+   vl_vlc_init_table(tbl_B4, Elements(tbl_B4), macroblock_type_b, Elements(macroblock_type_b));
+   vl_vlc_init_table(tbl_B9, Elements(tbl_B9), coded_block_pattern, Elements(coded_block_pattern));
+   vl_vlc_init_table(tbl_B10, Elements(tbl_B10), motion_code, Elements(motion_code));
+   vl_vlc_init_table(tbl_B11, Elements(tbl_B11), dmvector, Elements(dmvector));
+   vl_vlc_init_table(tbl_B12, Elements(tbl_B12), dct_dc_size_luminance, Elements(dct_dc_size_luminance));
+   vl_vlc_init_table(tbl_B13, Elements(tbl_B13), dct_dc_size_chrominance, Elements(dct_dc_size_chrominance));
+   init_dct_coeff_table(tbl_B14_DC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), true);
+   init_dct_coeff_table(tbl_B14_AC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), false);
+   init_dct_coeff_table(tbl_B15, dct_coeff_tbl_one, Elements(dct_coeff_tbl_one), false);
 }
 
-static inline int
-get_quantizer_scale(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture)
+static INLINE int
+DIV2DOWN(int todiv)
 {
-   int quantizer_scale_code;
-
-   quantizer_scale_code = vl_vlc_ubits(&bs->vlc, 5);
-   vl_vlc_dumpbits(&bs->vlc, 5);
-
-   if (picture->q_scale_type)
-      return non_linear_quantizer_scale[quantizer_scale_code];
-   else
-      return quantizer_scale_code << 1;
+   return (todiv&~1)/2;
 }
 
-static inline int
-get_motion_delta(struct vl_mpg12_bs *bs, unsigned f_code)
+static INLINE int
+DIV2UP(int todiv)
 {
-   int delta;
-   int sign;
-   const MVtab * tab;
-
-   if (bs->vlc.buf & 0x80000000) {
-      vl_vlc_dumpbits(&bs->vlc, 1);
-      return 0;
-   } else if (bs->vlc.buf >= 0x0c000000) {
-
-      tab = MV_4 + vl_vlc_ubits(&bs->vlc, 4);
-      delta = (tab->delta << f_code) + 1;
-      bs->vlc.bits += tab->len + f_code + 1;
-      bs->vlc.buf <<= tab->len;
-
-      sign = vl_vlc_sbits(&bs->vlc, 1);
-      bs->vlc.buf <<= 1;
-
-      if (f_code)
-         delta += vl_vlc_ubits(&bs->vlc, f_code);
-      bs->vlc.buf <<= f_code;
-
-      return (delta ^ sign) - sign;
-
-   } else {
-
-      tab = MV_10 + vl_vlc_ubits(&bs->vlc, 10);
-      delta = (tab->delta << f_code) + 1;
-      bs->vlc.bits += tab->len + 1;
-      bs->vlc.buf <<= tab->len;
-
-      sign = vl_vlc_sbits(&bs->vlc, 1);
-      bs->vlc.buf <<= 1;
-
-      if (f_code) {
-         vl_vlc_needbits(&bs->vlc);
-         delta += vl_vlc_ubits(&bs->vlc, f_code);
-         vl_vlc_dumpbits(&bs->vlc, f_code);
-      }
-
-      return (delta ^ sign) - sign;
-   }
+   return (todiv+1)/2;
 }
 
-static inline int
-bound_motion_vector(int vec, unsigned f_code)
+static INLINE void
+motion_vector(struct vl_mpg12_bs *bs, int r, int s, int dmv, short delta[2], short dmvector[2])
 {
-#if 1
-   unsigned int limit;
-   int sign;
-
-   limit = 16 << f_code;
-
-   if ((unsigned int)(vec + limit) < 2 * limit)
-      return vec;
-   else {
-      sign = ((int32_t)vec) >> 31;
-      return vec - ((2 * limit) ^ sign) + sign;
+   int t;
+   for (t = 0; t < 2; ++t) {
+      int motion_code;
+      int r_size = bs->desc->f_code[s][t];
+
+      vl_vlc_fillbits(&bs->vlc);
+      motion_code = vl_vlc_get_vlclbf(&bs->vlc, tbl_B10, 11);
+
+      assert(r_size >= 0);
+      if (r_size && motion_code) {
+         int residual = vl_vlc_get_uimsbf(&bs->vlc, r_size) + 1;
+         delta[t] = ((abs(motion_code) - 1) << r_size) + residual;
+         if (motion_code < 0)
+            delta[t] = -delta[t];
+      } else
+         delta[t] = motion_code;
+      if (dmv)
+         dmvector[t] = vl_vlc_get_vlclbf(&bs->vlc, tbl_B11, 2);
    }
-#else
-   return ((int32_t)vec << (28 - f_code)) >> (28 - f_code);
-#endif
 }
 
-static inline int
-get_dmv(struct vl_mpg12_bs *bs)
+static INLINE int
+wrap(short f, int shift)
 {
-   const DMVtab * tab;
-
-   tab = DMV_2 + vl_vlc_ubits(&bs->vlc, 2);
-   vl_vlc_dumpbits(&bs->vlc, tab->len);
-   return tab->dmv;
+   if (f < (-16 << shift))
+      return f + (32 << shift);
+   else if (f >= 16 << shift)
+      return f - (32 << shift);
+   else
+      return f;
 }
 
-static inline int
-get_coded_block_pattern(struct vl_mpg12_bs *bs)
+static INLINE void
+motion_vector_frame(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
 {
-   const CBPtab * tab;
-
-   vl_vlc_needbits(&bs->vlc);
+   int dmv = mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
+   short dmvector[2], delta[2];
 
-   if (bs->vlc.buf >= 0x20000000) {
+   if (mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_FIELD) {
+      mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+      motion_vector(bs, 0, s, dmv, delta, dmvector);
+      mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc->f_code[s][0]);
+      mb->PMV[0][s][1] = wrap(DIV2DOWN(mb->PMV[0][s][1]) + delta[1], bs->desc->f_code[s][1]) * 2;
 
-      tab = CBP_7 + (vl_vlc_ubits(&bs->vlc, 7) - 16);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      return tab->cbp;
+      mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
+      motion_vector(bs, 1, s, dmv, delta, dmvector);
+      mb->PMV[1][s][0] = wrap(mb->PMV[1][s][0] + delta[0], bs->desc->f_code[s][0]);
+      mb->PMV[1][s][1] = wrap(DIV2DOWN(mb->PMV[1][s][1]) + delta[1], bs->desc->f_code[s][1]) * 2;
 
    } else {
-
-      tab = CBP_9 + vl_vlc_ubits(&bs->vlc, 9);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      return tab->cbp;
+      motion_vector(bs, 0, s, dmv, delta, dmvector);
+      mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc->f_code[s][0]);
+      mb->PMV[0][s][1] = wrap(mb->PMV[0][s][1] + delta[1], bs->desc->f_code[s][1]);
    }
 }
 
-static inline int
-get_luma_dc_dct_diff(struct vl_mpg12_bs *bs)
+static INLINE void
+motion_vector_field(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
 {
-   const DCtab * tab;
-   int size;
-   int dc_diff;
-
-   if (bs->vlc.buf < 0xf8000000) {
-      tab = DC_lum_5 + vl_vlc_ubits(&bs->vlc, 5);
-      size = tab->size;
-      if (size) {
-         bs->vlc.bits += tab->len + size;
-         bs->vlc.buf <<= tab->len;
-         dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
-         bs->vlc.buf <<= size;
-         return dc_diff;
-      } else {
-         vl_vlc_dumpbits(&bs->vlc, 3);
-         return 0;
-      }
-   } else {
-      tab = DC_long + (vl_vlc_ubits(&bs->vlc, 9) - 0x1e0);
-      size = tab->size;
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      vl_vlc_needbits(&bs->vlc);
-      dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
-      vl_vlc_dumpbits(&bs->vlc, size);
-      return dc_diff;
-   }
-}
+   int dmv = mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
+   short dmvector[2], delta[2];
 
-static inline int
-get_chroma_dc_dct_diff(struct vl_mpg12_bs *bs)
-{
-   const DCtab * tab;
-   int size;
-   int dc_diff;
-
-   if (bs->vlc.buf < 0xf8000000) {
-      tab = DC_chrom_5 + vl_vlc_ubits(&bs->vlc, 5);
-      size = tab->size;
-      if (size) {
-         bs->vlc.bits += tab->len + size;
-         bs->vlc.buf <<= tab->len;
-         dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
-         bs->vlc.buf <<= size;
-         return dc_diff;
-      } else {
-         vl_vlc_dumpbits(&bs->vlc, 2);
-         return 0;
-      }
+   if (mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_16x8) {
+      mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+      motion_vector(bs, 0, s, dmv, delta, dmvector);
+
+      mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
+      motion_vector(bs, 1, s, dmv, delta, dmvector);
    } else {
-      tab = DC_long + (vl_vlc_ubits(&bs->vlc, 10) - 0x3e0);
-      size = tab->size;
-      vl_vlc_dumpbits(&bs->vlc, tab->len + 1);
-      vl_vlc_needbits(&bs->vlc);
-      dc_diff = vl_vlc_ubits(&bs->vlc, size) - UBITS (SBITS (~bs->vlc.buf, 1), size);
-      vl_vlc_dumpbits(&bs->vlc, size);
-      return dc_diff;
+      if (!dmv)
+         mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+      motion_vector(bs, 0, s, dmv, delta, dmvector);
    }
 }
 
-static inline void
-get_intra_block_B14(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
-{
-   int i, val;
-   const DCTtab *tab;
-
-   i = 0;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   while (1) {
-      if (bs->vlc.buf >= 0x28000000) {
-
-         tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-
-         i += tab->run;
-         if (i >= 64)
-            break;     /* end of block */
-
-      normal_code:
-         bs->vlc.buf <<= tab->len;
-         bs->vlc.bits += tab->len + 1;
-         val = tab->level * quantizer_scale;
-
-         val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
-
-         dest[i] = val;
-
-         bs->vlc.buf <<= 1;
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      } else if (bs->vlc.buf >= 0x04000000) {
-
-         tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-
-         /* escape code */
-
-         i += UBITS(bs->vlc.buf << 6, 6) - 64;
-         if (i >= 64)
-            break;     /* illegal, check needed to avoid buffer overflow */
-
-         vl_vlc_dumpbits(&bs->vlc, 12);
-         vl_vlc_needbits(&bs->vlc);
-         val = vl_vlc_sbits(&bs->vlc, 12) * quantizer_scale;
-
-         dest[i] = val;
-
-         vl_vlc_dumpbits(&bs->vlc, 12);
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      } else if (bs->vlc.buf >= 0x02000000) {
-         tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00800000) {
-         tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00200000) {
-         tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else {
-         tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
-         bs->vlc.buf <<= 16;
-         vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      }
-      break;   /* illegal, check needed to avoid buffer overflow */
-   }
-
-   vl_vlc_dumpbits(&bs->vlc, 2);       /* dump end of block code */
+static INLINE void
+reset_predictor(struct vl_mpg12_bs *bs) {
+   bs->pred_dc[0] = bs->pred_dc[1] = bs->pred_dc[2] = 0;
 }
 
-static inline void
-get_intra_block_B15(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+static INLINE void
+decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale)
 {
-   int i, val;
-   const DCTtab * tab;
-
-   i = 0;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   while (1) {
-      if (bs->vlc.buf >= 0x04000000) {
-
-         tab = DCT_B15_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
-         i += tab->run;
-         if (i < 64) {
+   static const unsigned blk2cc[] = { 0, 0, 0, 0, 1, 2 };
+   static const struct vl_vlc_entry *blk2dcsize[] = {
+      tbl_B12, tbl_B12, tbl_B12, tbl_B12, tbl_B13, tbl_B13
+   };
+
+   bool intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA;
+   const struct dct_coeff *table = intra ? bs->intra_dct_tbl : tbl_B14_AC;
+   const struct dct_coeff *entry;
+   int i, cbp, blk = 0;
+   short *dst = mb->blocks;
+
+   vl_vlc_fillbits(&bs->vlc);
+   mb->coded_block_pattern = cbp = intra ? 0x3F : vl_vlc_get_vlclbf(&bs->vlc, tbl_B9, 9);
+
+   goto entry;
+
+   while(1) {
+      vl_vlc_eatbits(&bs->vlc, entry->length);
+      if (entry->run == dct_End_of_Block) {
+
+next_d:
+         dst += 64;
+         cbp <<= 1;
+         cbp &= 0x3F;
+         blk++;
+
+entry:
+         if (!cbp)
+            break;
 
-         normal_code:
-            bs->vlc.buf <<= tab->len;
-            bs->vlc.bits += tab->len + 1;
-            val = tab->level * quantizer_scale;
+         while(!(cbp & 0x20)) {
+            cbp <<= 1;
+            blk++;
+         }
 
-            val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
+         vl_vlc_fillbits(&bs->vlc);
 
-            dest[i] = val;
+         if (intra) {
+            unsigned cc = blk2cc[blk];
+            unsigned size = vl_vlc_get_vlclbf(&bs->vlc, blk2dcsize[blk], 10);
 
-            bs->vlc.buf <<= 1;
-            vl_vlc_needbits(&bs->vlc);
+            if (size) {
+               int dct_diff = vl_vlc_get_uimsbf(&bs->vlc, size);
+               int half_range = 1 << (size - 1);
+               if (dct_diff < half_range)
+                  dct_diff = (dct_diff + 1) - (2 * half_range);
+               bs->pred_dc[cc] += dct_diff;
+            }
 
-            continue;
+            dst[0] = bs->pred_dc[cc];
+            i = 0;
 
+            if (bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_D)
+               goto next_d;
          } else {
-
-            /* end of block. I commented out this code because if we */
-            /* dont exit here we will still exit at the later test :) */
-
-            /* if (i >= 128) break;    */      /* end of block */
-
-            /* escape code */
-
-            i += UBITS(bs->vlc.buf << 6, 6) - 64;
-            if (i >= 64)
-                break; /* illegal, check against buffer overflow */
-
-            vl_vlc_dumpbits(&bs->vlc, 12);
-            vl_vlc_needbits(&bs->vlc);
-            val = vl_vlc_sbits(&bs->vlc, 12) * quantizer_scale;
-
-            dest[i] = val;
-
-            vl_vlc_dumpbits(&bs->vlc, 12);
-            vl_vlc_needbits(&bs->vlc);
-
+            entry = tbl_B14_DC + vl_vlc_peekbits(&bs->vlc, 17);
+            i = -1;
             continue;
+         }
 
-          }
-      } else if (bs->vlc.buf >= 0x02000000) {
-         tab = DCT_B15_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00800000) {
-         tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00200000) {
-         tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else {
-         tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
-         bs->vlc.buf <<= 16;
-         vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      }
-      break;   /* illegal, check needed to avoid buffer overflow */
-   }
-
-   vl_vlc_dumpbits(&bs->vlc, 4);       /* dump end of block code */
-}
-
-static inline void
-get_non_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
-{
-   int i, val;
-   const DCTtab *tab;
-
-   i = -1;
-
-   vl_vlc_needbits(&bs->vlc);
-   if (bs->vlc.buf >= 0x28000000) {
-      tab = DCT_B14DC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-      goto entry_1;
-   } else
-      goto entry_2;
-
-   while (1) {
-      if (bs->vlc.buf >= 0x28000000) {
-
-         tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-
-      entry_1:
-         i += tab->run;
-         if (i >= 64)
-            break;     /* end of block */
-
-      normal_code:
-         bs->vlc.buf <<= tab->len;
-         bs->vlc.bits += tab->len + 1;
-         val = ((2*tab->level+1) * quantizer_scale) >> 1;
+      } else if (entry->run == dct_Escape &&
+                 bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) {
+         i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
+         if (i > 64)
+            break;
 
-         val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
+         dst[i] = vl_vlc_get_simsbf(&bs->vlc, 8);
+         if (dst[i] == -128)
+            dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8) - 256;
+         else if (dst[i] == 0)
+            dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8);
 
-         dest[i] = val;
+         dst[i] *= scale;
+      } else if (entry->run == dct_Escape) {
+         i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
+         if (i > 64)
+            break;
 
-         bs->vlc.buf <<= 1;
-         vl_vlc_needbits(&bs->vlc);
+         dst[i] = vl_vlc_get_simsbf(&bs->vlc, 12) * scale;
 
-         continue;
+      } else {
+         i += entry->run;
+         if (i > 64)
+            break;
 
+         dst[i] = entry->level * scale;
       }
 
-   entry_2:
-      if (bs->vlc.buf >= 0x04000000) {
-
-         tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-
-         /* escape code */
-
-         i += UBITS(bs->vlc.buf << 6, 6) - 64;
-         if (i >= 64)
-            break;     /* illegal, check needed to avoid buffer overflow */
-
-         vl_vlc_dumpbits(&bs->vlc, 12);
-         vl_vlc_needbits(&bs->vlc);
-         val = 2 * (vl_vlc_sbits(&bs->vlc, 12) + vl_vlc_sbits(&bs->vlc, 1)) + 1;
-         val = (val * quantizer_scale) / 2;
-
-         dest[i] = val;
-
-         vl_vlc_dumpbits(&bs->vlc, 12);
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      } else if (bs->vlc.buf >= 0x02000000) {
-         tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00800000) {
-         tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00200000) {
-         tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else {
-         tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
-         bs->vlc.buf <<= 16;
-         vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      }
-      break;   /* illegal, check needed to avoid buffer overflow */
+      vl_vlc_fillbits(&bs->vlc);
+      entry = table + vl_vlc_peekbits(&bs->vlc, 17);
    }
-   vl_vlc_dumpbits(&bs->vlc, 2);       /* dump end of block code */
-}
-
-static inline void
-get_mpeg1_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
-{
-   int i, val;
-   const DCTtab * tab;
-
-   i = 0;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   while (1) {
-      if (bs->vlc.buf >= 0x28000000) {
-
-         tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
 
-         i += tab->run;
-         if (i >= 64)
-            break;     /* end of block */
-
-      normal_code:
-         bs->vlc.buf <<= tab->len;
-         bs->vlc.bits += tab->len + 1;
-         val = tab->level * quantizer_scale;
-
-         /* oddification */
-         val = (val - 1) | 1;
-
-         /* if (bitstream_get (1)) val = -val; */
-         val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
-
-         dest[i] = val;
-
-         bs->vlc.buf <<= 1;
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      } else if (bs->vlc.buf >= 0x04000000) {
-
-         tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-
-         /* escape code */
-
-         i += UBITS(bs->vlc.buf << 6, 6) - 64;
-         if (i >= 64)
-            break;     /* illegal, check needed to avoid buffer overflow */
-
-         vl_vlc_dumpbits(&bs->vlc, 12);
-         vl_vlc_needbits(&bs->vlc);
-         val = vl_vlc_sbits(&bs->vlc, 8);
-         if (! (val & 0x7f)) {
-            vl_vlc_dumpbits(&bs->vlc, 8);
-            val = vl_vlc_ubits(&bs->vlc, 8) + 2 * val;
-         }
-         val = val * quantizer_scale;
-
-         /* oddification */
-         val = (val + ~SBITS (val, 1)) | 1;
-
-         dest[i] = val;
-
-         vl_vlc_dumpbits(&bs->vlc, 8);
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      } else if (bs->vlc.buf >= 0x02000000) {
-         tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00800000) {
-         tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00200000) {
-         tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else {
-         tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
-         bs->vlc.buf <<= 16;
-         vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      }
-      break;   /* illegal, check needed to avoid buffer overflow */
-   }
-   vl_vlc_dumpbits(&bs->vlc, 2);       /* dump end of block code */
+   if (bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_D)
+      vl_vlc_eatbits(&bs->vlc, 1);
 }
 
-static inline void
-get_mpeg1_non_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+static INLINE void
+decode_slice(struct vl_mpg12_bs *bs, struct pipe_video_buffer *target)
 {
-   int i, val;
-   const DCTtab * tab;
-
-   i = -1;
-
-   vl_vlc_needbits(&bs->vlc);
-   if (bs->vlc.buf >= 0x28000000) {
-      tab = DCT_B14DC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-      goto entry_1;
-   } else
-      goto entry_2;
-
-   while (1) {
-      if (bs->vlc.buf >= 0x28000000) {
-
-         tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
-
-      entry_1:
-         i += tab->run;
-         if (i >= 64)
-            break;     /* end of block */
+   struct pipe_mpeg12_macroblock mb;
+   short dct_blocks[64*6];
+   unsigned dct_scale;
+   signed x = -1;
 
-      normal_code:
-         bs->vlc.buf <<= tab->len;
-         bs->vlc.bits += tab->len + 1;
-         val = ((2*tab->level+1) * quantizer_scale) >> 1;
+   memset(&mb, 0, sizeof(mb));
+   mb.base.codec = PIPE_VIDEO_FORMAT_MPEG12;
+   mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1;
+   mb.blocks = dct_blocks;
 
-         /* oddification */
-         val = (val - 1) | 1;
+   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 (bitstream_get (1)) val = -val; */
-         val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
+   if (vl_vlc_get_uimsbf(&bs->vlc, 1))
+      while (vl_vlc_get_uimsbf(&bs->vlc, 9) & 1)
+         vl_vlc_fillbits(&bs->vlc);
 
-         dest[i] = val;
+   vl_vlc_fillbits(&bs->vlc);
+   assert(vl_vlc_peekbits(&bs->vlc, 23));
+   do {
+      int inc = 0;
 
-         bs->vlc.buf <<= 1;
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      }
-
-   entry_2:
-      if (bs->vlc.buf >= 0x04000000) {
-
-         tab = DCT_B14_8 + (vl_vlc_ubits(&bs->vlc, 8) - 4);
-
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-
-         /* escape code */
-
-         i += UBITS(bs->vlc.buf << 6, 6) - 64;
-         if (i >= 64)
-            break;     /* illegal, check needed to avoid buffer overflow */
+      while (1) {
+         /* MPEG-1 macroblock stuffing, can appear an arbitrary number of times. */
+         while (vl_vlc_peekbits(&bs->vlc, 11) == 15) {
+            vl_vlc_eatbits(&bs->vlc, 11);
+            vl_vlc_fillbits(&bs->vlc);
+         }
 
-         vl_vlc_dumpbits(&bs->vlc, 12);
-         vl_vlc_needbits(&bs->vlc);
-         val = vl_vlc_sbits(&bs->vlc, 8);
-         if (! (val & 0x7f)) {
-            vl_vlc_dumpbits(&bs->vlc, 8);
-            val = vl_vlc_ubits(&bs->vlc, 8) + 2 * val;
+         if (vl_vlc_peekbits(&bs->vlc, 11) == 8) {
+            vl_vlc_eatbits(&bs->vlc, 11);
+            vl_vlc_fillbits(&bs->vlc);
+            inc += 33;
+         } else {
+            inc += vl_vlc_get_vlclbf(&bs->vlc, tbl_B1, 11);
+            break;
          }
-         val = 2 * (val + SBITS (val, 1)) + 1;
-         val = (val * quantizer_scale) / 2;
-
-         /* oddification */
-         val = (val + ~SBITS (val, 1)) | 1;
-
-         dest[i] = val;
-
-         vl_vlc_dumpbits(&bs->vlc, 8);
-         vl_vlc_needbits(&bs->vlc);
-
-         continue;
-
-      } else if (bs->vlc.buf >= 0x02000000) {
-         tab = DCT_B14_10 + (vl_vlc_ubits(&bs->vlc, 10) - 8);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00800000) {
-         tab = DCT_13 + (vl_vlc_ubits(&bs->vlc, 13) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else if (bs->vlc.buf >= 0x00200000) {
-         tab = DCT_15 + (vl_vlc_ubits(&bs->vlc, 15) - 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
-      } else {
-         tab = DCT_16 + vl_vlc_ubits(&bs->vlc, 16);
-         bs->vlc.buf <<= 16;
-         vl_vlc_getword(&bs->vlc, bs->vlc.bits + 16);
-         i += tab->run;
-         if (i < 64)
-            goto normal_code;
       }
-      break;   /* illegal, check needed to avoid buffer overflow */
-   }
-   vl_vlc_dumpbits(&bs->vlc, 2);       /* dump end of block code */
-}
-
-static inline void
-slice_intra_DCT(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture, int cc,
-                 unsigned x, unsigned y, enum pipe_mpeg12_dct_type coding, int quantizer_scale, int dc_dct_pred[3])
-{
-   short dest[64];
-
-   bs->ycbcr_stream[cc]->x = x;
-   bs->ycbcr_stream[cc]->y = y;
-   bs->ycbcr_stream[cc]->intra = PIPE_MPEG12_DCT_INTRA;
-   bs->ycbcr_stream[cc]->coding = coding;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   /* Get the intra DC coefficient and inverse quantize it */
-   if (cc == 0)
-      dc_dct_pred[0] += get_luma_dc_dct_diff(bs);
-   else
-      dc_dct_pred[cc] += get_chroma_dc_dct_diff(bs);
-
-   memset(dest, 0, sizeof(int16_t) * 64);
-   dest[0] = dc_dct_pred[cc];
-   if (picture->base.profile == PIPE_VIDEO_PROFILE_MPEG1) {
-      if (picture->picture_coding_type != D_TYPE)
-          get_mpeg1_intra_block(bs, quantizer_scale, dest);
-   } else if (picture->intra_vlc_format)
-      get_intra_block_B15(bs, quantizer_scale, dest);
-   else
-      get_intra_block_B14(bs, quantizer_scale, dest);
-
-   memcpy(bs->ycbcr_buffer[cc], dest, sizeof(int16_t) * 64);
-
-   bs->num_ycbcr_blocks[cc]++;
-   bs->ycbcr_stream[cc]++;
-   bs->ycbcr_buffer[cc] += 64;
-}
-
-static inline void
-slice_non_intra_DCT(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture, int cc,
-                    unsigned x, unsigned y,  enum pipe_mpeg12_dct_type coding, int quantizer_scale)
-{
-   short dest[64];
-
-   bs->ycbcr_stream[cc]->x = x;
-   bs->ycbcr_stream[cc]->y = y;
-   bs->ycbcr_stream[cc]->intra = PIPE_MPEG12_DCT_DELTA;
-   bs->ycbcr_stream[cc]->coding = coding;
-
-   memset(dest, 0, sizeof(int16_t) * 64);
-   if (picture->base.profile == PIPE_VIDEO_PROFILE_MPEG1)
-      get_mpeg1_non_intra_block(bs, quantizer_scale, dest);
-   else
-      get_non_intra_block(bs, quantizer_scale, dest);
-
-   memcpy(bs->ycbcr_buffer[cc], dest, sizeof(int16_t) * 64);
-
-   bs->num_ycbcr_blocks[cc]++;
-   bs->ycbcr_stream[cc]++;
-   bs->ycbcr_buffer[cc] += 64;
-}
-
-static inline void
-motion_mp1(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_x = (mv->top.x + (get_motion_delta(bs, f_code[0]) << f_code[1]));
-   motion_x = bound_motion_vector (motion_x, f_code[0] + f_code[1]);
-   mv->top.x = mv->bottom.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = (mv->top.y + (get_motion_delta(bs, f_code[0]) << f_code[1]));
-   motion_y = bound_motion_vector (motion_y, f_code[0] + f_code[1]);
-   mv->top.y = mv->bottom.y = motion_y;
-}
-
-static inline void
-motion_fr_frame(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector(motion_x, f_code[0]);
-   mv->top.x = mv->bottom.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
-   motion_y = bound_motion_vector(motion_y, f_code[1]);
-   mv->top.y = mv->bottom.y = motion_y;
-}
-
-static inline void
-motion_fr_field(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   vl_vlc_needbits(&bs->vlc);
-   mv->top.field_select = vl_vlc_ubits(&bs->vlc, 1) ?
-      PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
-   vl_vlc_dumpbits(&bs->vlc, 1);
-
-   motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector (motion_x, f_code[0]);
-   mv->top.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = (mv->top.y >> 1) + get_motion_delta(bs, f_code[1]);
-   /* motion_y = bound_motion_vector (motion_y, f_code[1]); */
-   mv->top.y = motion_y << 1;
-
-   vl_vlc_needbits(&bs->vlc);
-   mv->bottom.field_select = vl_vlc_ubits(&bs->vlc, 1) ?
-      PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
-   vl_vlc_dumpbits(&bs->vlc, 1);
-
-   motion_x = mv->bottom.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector (motion_x, f_code[0]);
-   mv->bottom.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = (mv->bottom.y >> 1) + get_motion_delta(bs, f_code[1]);
-   /* motion_y = bound_motion_vector (motion_y, f_code[1]); */
-   mv->bottom.y = motion_y << 1;
-}
-
-static inline void
-motion_fr_dmv(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   // TODO Implement dmv
-   mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector(motion_x, f_code[0]);
-   mv->top.x = mv->bottom.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = (mv->top.y >> 1) + get_motion_delta(bs, f_code[1]);
-   /* motion_y = bound_motion_vector (motion_y, f_code[1]); */
-   mv->top.y = mv->bottom.y = motion_y << 1;
-}
-
-/* like motion_frame, but parsing without actual motion compensation */
-static inline void
-motion_fr_conceal(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int tmp;
-
-   mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
-   vl_vlc_needbits(&bs->vlc);
-   tmp = (mv->top.x + get_motion_delta(bs, f_code[0]));
-   tmp = bound_motion_vector (tmp, f_code[0]);
-   mv->top.x = mv->bottom.x = tmp;
-
-   vl_vlc_needbits(&bs->vlc);
-   tmp = (mv->top.y + get_motion_delta(bs, f_code[1]));
-   tmp = bound_motion_vector (tmp, f_code[1]);
-   mv->top.y = mv->bottom.y = tmp;
-
-   vl_vlc_dumpbits(&bs->vlc, 1); /* remove marker_bit */
-}
-
-static inline void
-motion_fi_field(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   // ref_field
-   //vl_vlc_ubits(&bs->vlc, 1);
-
-   // TODO field select may need to do something here for bob (weave ok)
-   mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-   vl_vlc_dumpbits(&bs->vlc, 1);
-
-   motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector (motion_x, f_code[0]);
-   mv->top.x = mv->bottom.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
-   motion_y = bound_motion_vector (motion_y, f_code[1]);
-   mv->top.y = mv->bottom.y = motion_y;
-}
-
-static inline void
-motion_fi_16x8(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   // ref_field
-   //vl_vlc_ubits(&bs->vlc, 1);
-
-   // TODO field select may need to do something here bob  (weave ok)
-   mv->top.field_select = PIPE_VIDEO_FRAME;
-   vl_vlc_dumpbits(&bs->vlc, 1);
-
-   motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector (motion_x, f_code[0]);
-   mv->top.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
-   motion_y = bound_motion_vector (motion_y, f_code[1]);
-   mv->top.y = motion_y;
-
-   vl_vlc_needbits(&bs->vlc);
-   // ref_field
-   //vl_vlc_ubits(&bs->vlc, 1);
-
-   // TODO field select may need to do something here for bob (weave ok)
-   mv->bottom.field_select = PIPE_VIDEO_FRAME;
-   vl_vlc_dumpbits(&bs->vlc, 1);
-
-   motion_x = mv->bottom.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector (motion_x, f_code[0]);
-   mv->bottom.x = motion_x;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = mv->bottom.y + get_motion_delta(bs, f_code[1]);
-   motion_y = bound_motion_vector (motion_y, f_code[1]);
-   mv->bottom.y = motion_y;
-}
-
-static inline void
-motion_fi_dmv(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int motion_x, motion_y;
-
-   // TODO field select may need to do something here for bob  (weave ok)
-   mv->top.field_select = mv->bottom.field_select = PIPE_VIDEO_FRAME;
-
-   vl_vlc_needbits(&bs->vlc);
-   motion_x = mv->top.x + get_motion_delta(bs, f_code[0]);
-   motion_x = bound_motion_vector (motion_x, f_code[0]);
-   mv->top.x = mv->bottom.x = motion_x;
 
-   vl_vlc_needbits(&bs->vlc);
-   motion_y = mv->top.y + get_motion_delta(bs, f_code[1]);
-   motion_y = bound_motion_vector (motion_y, f_code[1]);
-   mv->top.y = mv->bottom.y = motion_y;
-}
-
-
-static inline void
-motion_fi_conceal(struct vl_mpg12_bs *bs, unsigned f_code[2], struct pipe_motionvector *mv)
-{
-   int tmp;
-
-   vl_vlc_needbits(&bs->vlc);
-   vl_vlc_dumpbits(&bs->vlc, 1); /* remove field_select */
-
-   tmp = (mv->top.x + get_motion_delta(bs, f_code[0]));
-   tmp = bound_motion_vector(tmp, f_code[0]);
-   mv->top.x = mv->bottom.x = tmp;
-
-   vl_vlc_needbits(&bs->vlc);
-   tmp = (mv->top.y + get_motion_delta(bs, f_code[1]));
-   tmp = bound_motion_vector(tmp, f_code[1]);
-   mv->top.y = mv->bottom.y = tmp;
-
-   vl_vlc_dumpbits(&bs->vlc, 1); /* remove marker_bit */
-}
-
-#define MOTION_CALL(routine, macroblock_modes)         \
-do {                                                   \
-   if ((macroblock_modes) & MACROBLOCK_MOTION_FORWARD)  \
-      routine(bs, picture->f_code[0], &mv_fwd);         \
-   if ((macroblock_modes) & MACROBLOCK_MOTION_BACKWARD)        \
-      routine(bs, picture->f_code[1], &mv_bwd);         \
-} while (0)
-
-static inline void
-store_motionvectors(struct vl_mpg12_bs *bs, unsigned *mv_pos,
-                    struct pipe_motionvector *mv_fwd,
-                    struct pipe_motionvector *mv_bwd)
-{
-   bs->mv_stream[0][*mv_pos].top = mv_fwd->top;
-   bs->mv_stream[0][*mv_pos].bottom =
-      mv_fwd->top.field_select == PIPE_VIDEO_FRAME ?
-      mv_fwd->top : mv_fwd->bottom;
-
-   bs->mv_stream[1][*mv_pos].top = mv_bwd->top;
-   bs->mv_stream[1][*mv_pos].bottom =
-      mv_bwd->top.field_select == PIPE_VIDEO_FRAME ?
-      mv_bwd->top : mv_bwd->bottom;
-
-   (*mv_pos)++;
-}
-
-static inline bool
-slice_init(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture,
-           int *quantizer_scale, unsigned *x, unsigned *y, unsigned *mv_pos)
-{
-   const MBAtab * mba;
-
-   vl_vlc_need32bits(&bs->vlc);
-   while(bs->vlc.buf < 0x101 || bs->vlc.buf > 0x1AF) {
-      if(!vl_vlc_getbyte(&bs->vlc))
-         return false;
-   }
-   *y = (bs->vlc.buf & 0xFF) - 1;
-   vl_vlc_restart(&bs->vlc);
-
-   *quantizer_scale = get_quantizer_scale(bs, picture);
-
-   /* ignore intra_slice and all the extra data */
-   while (bs->vlc.buf & 0x80000000) {
-      vl_vlc_dumpbits(&bs->vlc, 9);
-      vl_vlc_needbits(&bs->vlc);
-   }
-
-   /* decode initial macroblock address increment */
-   *x = 0;
-   while (1) {
-      if (bs->vlc.buf >= 0x08000000) {
-          mba = MBA_5 + (vl_vlc_ubits(&bs->vlc, 6) - 2);
-          break;
-      } else if (bs->vlc.buf >= 0x01800000) {
-          mba = MBA_11 + (vl_vlc_ubits(&bs->vlc, 12) - 24);
-          break;
-      } else switch (vl_vlc_ubits(&bs->vlc, 12)) {
-      case 8:          /* macroblock_escape */
-          *x += 33;
-          vl_vlc_dumpbits(&bs->vlc, 11);
-          vl_vlc_needbits(&bs->vlc);
-          continue;
-      case 15: /* macroblock_stuffing (MPEG1 only) */
-          bs->vlc.buf &= 0xfffff;
-          vl_vlc_dumpbits(&bs->vlc, 11);
-          vl_vlc_needbits(&bs->vlc);
-          continue;
-      default: /* error */
-          return false;
+      if (x != -1) {
+         if (!inc)
+            return;
+         mb.num_skipped_macroblocks = inc - 1;
+         bs->decoder->decode_macroblock(bs->decoder, target, &bs->desc->base, &mb.base, 1);
+      }
+      mb.x = x += inc;
+      if (bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) {
+         int width = align(bs->decoder->width, 16) / 16;
+         mb.y += mb.x / width;
+         mb.x = x %= width;
       }
-   }
-   vl_vlc_dumpbits(&bs->vlc, mba->len + 1);
-   *x += mba->mba;
-
-   while (*x >= bs->width) {
-      *x -= bs->width;
-      (*y)++;
-   }
-   if (*y > bs->height)
-      return false;
-
-   *mv_pos = *x + *y * bs->width;
-
-   return true;
-}
-
-static inline bool
-decode_slice(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture)
-{
-   enum pipe_video_field_select default_field_select;
-   struct pipe_motionvector mv_fwd, mv_bwd;
-   enum pipe_mpeg12_dct_type dct_type;
-
-   /* predictor for DC coefficients in intra blocks */
-   int dc_dct_pred[3] = { 0, 0, 0 };
-   int quantizer_scale;
-
-   unsigned x, y, mv_pos;
-
-   switch(picture->picture_structure) {
-   case TOP_FIELD:
-      default_field_select = PIPE_VIDEO_TOP_FIELD;
-      break;
-
-   case BOTTOM_FIELD:
-      default_field_select = PIPE_VIDEO_BOTTOM_FIELD;
-      break;
-
-   default:
-      default_field_select = PIPE_VIDEO_FRAME;
-      break;
-   }
-
-   if (!slice_init(bs, picture, &quantizer_scale, &x, &y, &mv_pos))
-      return false;
-
-   mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
-   mv_fwd.top.field_select = mv_fwd.bottom.field_select = default_field_select;
-
-   mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
-   mv_bwd.top.field_select = mv_bwd.bottom.field_select = default_field_select;
-
-   while (1) {
-      int macroblock_modes;
-      int mba_inc;
-      const MBAtab * mba;
-
-      vl_vlc_needbits(&bs->vlc);
-
-      macroblock_modes = get_macroblock_modes(bs, picture);
-      dct_type = get_dct_type(bs, picture, macroblock_modes);
 
-      switch(macroblock_modes & (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD)) {
-      case (MACROBLOCK_MOTION_FORWARD|MACROBLOCK_MOTION_BACKWARD):
-         mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_HALF;
-         mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_HALF;
+      switch (bs->desc->picture_coding_type) {
+      case PIPE_MPEG12_PICTURE_CODING_TYPE_I:
+         mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B2, 2);
          break;
 
-      default:
-         mv_fwd.top.field_select = mv_fwd.bottom.field_select = default_field_select;
-         mv_bwd.top.field_select = mv_bwd.bottom.field_select = default_field_select;
+      case PIPE_MPEG12_PICTURE_CODING_TYPE_P:
+         mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B3, 6);
+         break;
 
-         /* fall through */
-      case MACROBLOCK_MOTION_FORWARD:
-         mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
-         mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
+      case PIPE_MPEG12_PICTURE_CODING_TYPE_B:
+         mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B4, 6);
          break;
 
-      case MACROBLOCK_MOTION_BACKWARD:
-         mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
-         mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
+      case PIPE_MPEG12_PICTURE_CODING_TYPE_D:
+         vl_vlc_eatbits(&bs->vlc, 1);
+         mb.macroblock_type = PIPE_MPEG12_MB_TYPE_INTRA;
          break;
       }
 
-      /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */
-      if (macroblock_modes & MACROBLOCK_QUANT)
-         quantizer_scale = get_quantizer_scale(bs, picture);
-
-      if (macroblock_modes & MACROBLOCK_INTRA) {
-
-         if (picture->concealment_motion_vectors) {
-            if (picture->picture_structure == FRAME_PICTURE)
-               motion_fr_conceal(bs, picture->f_code[0], &mv_fwd);
+      mb.macroblock_modes.value = 0;
+      if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
+         if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) {
+            if (bs->desc->frame_pred_frame_dct == 0)
+               mb.macroblock_modes.bits.frame_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
             else
-               motion_fi_conceal(bs, picture->f_code[0], &mv_fwd);
+               mb.macroblock_modes.bits.frame_motion_type = 2;
+         } else
+            mb.macroblock_modes.bits.field_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
 
-         } else {
-            mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
-            mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
-         }
-         mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
-         mv_bwd.top.weight = mv_bwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
-
-         // unravaled loop of 6 block(i) calls in macroblock()
-         slice_intra_DCT(bs, picture, 0, x*2+0, y*2+0, dct_type, quantizer_scale, dc_dct_pred);
-         slice_intra_DCT(bs, picture, 0, x*2+1, y*2+0, dct_type, quantizer_scale, dc_dct_pred);
-         slice_intra_DCT(bs, picture, 0, x*2+0, y*2+1, dct_type, quantizer_scale, dc_dct_pred);
-         slice_intra_DCT(bs, picture, 0, x*2+1, y*2+1, dct_type, quantizer_scale, dc_dct_pred);
-         slice_intra_DCT(bs, picture, 1, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale, dc_dct_pred);
-         slice_intra_DCT(bs, picture, 2, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale, dc_dct_pred);
-
-         if (picture->picture_coding_type == D_TYPE) {
-            vl_vlc_needbits(&bs->vlc);
-            vl_vlc_dumpbits(&bs->vlc, 1);
-         }
-
-      } else {
-         if (picture->picture_structure == FRAME_PICTURE)
-            switch (macroblock_modes & MOTION_TYPE_MASK) {
-            case MC_FRAME:
-               if (picture->base.profile == PIPE_VIDEO_PROFILE_MPEG1) {
-                  MOTION_CALL(motion_mp1, macroblock_modes);
-               } else {
-                  MOTION_CALL(motion_fr_frame, macroblock_modes);
-               }
-               break;
-
-            case MC_FIELD:
-               MOTION_CALL (motion_fr_field, macroblock_modes);
-               break;
-
-            case MC_DMV:
-               MOTION_CALL (motion_fr_dmv, MACROBLOCK_MOTION_FORWARD);
-               break;
-
-            case 0:
-               /* non-intra mb without forward mv in a P picture */
-               mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
-               mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
-               break;
-            }
+      } else if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) && bs->desc->concealment_motion_vectors) {
+         if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
+            mb.macroblock_modes.bits.frame_motion_type = 2;
          else
-            switch (macroblock_modes & MOTION_TYPE_MASK) {
-            case MC_FIELD:
-               MOTION_CALL (motion_fi_field, macroblock_modes);
-               break;
-
-            case MC_16X8:
-               MOTION_CALL (motion_fi_16x8, macroblock_modes);
-               break;
-
-            case MC_DMV:
-               MOTION_CALL (motion_fi_dmv, MACROBLOCK_MOTION_FORWARD);
-               break;
-
-            case 0:
-               /* non-intra mb without forward mv in a P picture */
-               mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
-               mv_bwd.top.x = mv_bwd.top.y = mv_bwd.bottom.x = mv_bwd.bottom.y = 0;
-               break;
-            }
+            mb.macroblock_modes.bits.field_motion_type = 1;
+      }
 
-         if (macroblock_modes & MACROBLOCK_PATTERN) {
-            int coded_block_pattern = get_coded_block_pattern(bs);
-
-            // TODO  optimize not fully used for idct accel only mc.
-            if (coded_block_pattern & 0x20)
-               slice_non_intra_DCT(bs, picture, 0, x*2+0, y*2+0, dct_type, quantizer_scale); // cc0  luma 0
-            if (coded_block_pattern & 0x10)
-               slice_non_intra_DCT(bs, picture, 0, x*2+1, y*2+0, dct_type, quantizer_scale); // cc0 luma 1
-            if (coded_block_pattern & 0x08)
-               slice_non_intra_DCT(bs, picture, 0, x*2+0, y*2+1, dct_type, quantizer_scale); // cc0 luma 2
-            if (coded_block_pattern & 0x04)
-               slice_non_intra_DCT(bs, picture, 0, x*2+1, y*2+1, dct_type, quantizer_scale); // cc0 luma 3
-            if (coded_block_pattern & 0x2)
-               slice_non_intra_DCT(bs, picture, 1, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale); // cc1 croma
-            if (coded_block_pattern & 0x1)
-               slice_non_intra_DCT(bs, picture, 2, x, y, PIPE_MPEG12_DCT_TYPE_FRAME, quantizer_scale); // cc2 croma
-         }
+      if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME &&
+          bs->desc->frame_pred_frame_dct == 0 &&
+          mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN))
+         mb.macroblock_modes.bits.dct_type = vl_vlc_get_uimsbf(&bs->vlc, 1);
+
+      if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_QUANT)
+         dct_scale = quant_scale[bs->desc->q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
 
-         dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0;
+      if (inc > 1 && bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_P)
+         memset(mb.PMV, 0, sizeof(mb.PMV));
+
+      mb.motion_vertical_field_select = 0;
+      if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD) ||
+          (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc->concealment_motion_vectors)) {
+         if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
+            motion_vector_frame(bs, 0, &mb);
+         else
+            motion_vector_field(bs, 0, &mb);
       }
 
-      store_motionvectors(bs, &mv_pos, &mv_fwd, &mv_bwd);
-      if (++x >= bs->width) {
-         ++y;
-         if (y >= bs->height)
-            return false;
-         x -= bs->width;
+      if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD) {
+         if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
+            motion_vector_frame(bs, 1, &mb);
+         else
+            motion_vector_field(bs, 1, &mb);
       }
 
-      vl_vlc_needbits(&bs->vlc);
-      mba_inc = 0;
-      while (1) {
-         if (bs->vlc.buf >= 0x10000000) {
-            mba = MBA_5 + (vl_vlc_ubits(&bs->vlc, 5) - 2);
-            break;
-         } else if (bs->vlc.buf >= 0x03000000) {
-            mba = MBA_11 + (vl_vlc_ubits(&bs->vlc, 11) - 24);
-            break;
-         } else switch (vl_vlc_ubits(&bs->vlc, 11)) {
-         case 8:               /* macroblock_escape */
-            mba_inc += 33;
-            /* pass through */
-         case 15:      /* macroblock_stuffing (MPEG1 only) */
-            vl_vlc_dumpbits(&bs->vlc, 11);
-            vl_vlc_needbits(&bs->vlc);
-            continue;
-         default:      /* end of slice, or error */
-            return true;
-         }
+      if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc->concealment_motion_vectors) {
+         unsigned extra = vl_vlc_get_uimsbf(&bs->vlc, 1);
+         mb.PMV[1][0][0] = mb.PMV[0][0][0];
+         mb.PMV[1][0][1] = mb.PMV[0][0][1];
+         assert(extra);
+      } else if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA ||
+                !(mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD |
+                                        PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD))) {
+         memset(mb.PMV, 0, sizeof(mb.PMV));
       }
-      vl_vlc_dumpbits(&bs->vlc, mba->len);
-      mba_inc += mba->mba;
-      if (mba_inc) {
-         //TODO  conversion to signed format signed format
-         dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0;
-
-         mv_fwd.top.field_select = mv_fwd.bottom.field_select = default_field_select;
-         mv_bwd.top.field_select = mv_bwd.bottom.field_select = default_field_select;
-
-         if (picture->picture_coding_type == P_TYPE) {
-            mv_fwd.top.x = mv_fwd.top.y = mv_fwd.bottom.x = mv_fwd.bottom.y = 0;
-            mv_fwd.top.weight = mv_fwd.bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
-         }
 
-         x += mba_inc;
-         do {
-            store_motionvectors(bs, &mv_pos, &mv_fwd, &mv_bwd);
-         } while (--mba_inc);
+      if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD &&
+           mb.macroblock_modes.bits.frame_motion_type == 2) ||
+          (mb.macroblock_modes.bits.frame_motion_type == 3)) {
+            mb.PMV[1][0][0] = mb.PMV[0][0][0];
+            mb.PMV[1][0][1] = mb.PMV[0][0][1];
       }
-      while (x >= bs->width) {
-         ++y;
-         if (y >= bs->height)
-            return false;
-         x -= bs->width;
+
+      if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD &&
+          mb.macroblock_modes.bits.frame_motion_type == 2) {
+            mb.PMV[1][1][0] = mb.PMV[0][1][0];
+            mb.PMV[1][1][1] = mb.PMV[0][1][1];
       }
-   }
-}
 
-void
-vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height)
-{
-   assert(bs);
+      if (inc > 1 || !(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA))
+         reset_predictor(bs);
 
-   memset(bs, 0, sizeof(struct vl_mpg12_bs));
+      if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN)) {
+         memset(dct_blocks, 0, sizeof(dct_blocks));
+         decode_dct(bs, &mb, dct_scale);
+      } else
+         mb.coded_block_pattern = 0;
 
-   bs->width = width;
-   bs->height = height;
+      vl_vlc_fillbits(&bs->vlc);
+   } while (vl_vlc_bits_left(&bs->vlc) && vl_vlc_peekbits(&bs->vlc, 23));
+
+   mb.num_skipped_macroblocks = 0;
+   bs->decoder->decode_macroblock(bs->decoder, target, &bs->desc->base, &mb.base, 1);
 }
 
 void
-vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct pipe_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
-                        short *ycbcr_buffer[VL_MAX_PLANES], struct pipe_motionvector *mv_stream[VL_MAX_REF_FRAMES])
+vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_codec *decoder)
 {
-   unsigned i;
+   static bool tables_initialized = false;
 
    assert(bs);
-   assert(ycbcr_stream && ycbcr_buffer);
-   assert(mv_stream);
 
-   for (i = 0; i < VL_MAX_PLANES; ++i) {
-      bs->ycbcr_stream[i] = ycbcr_stream[i];
-      bs->ycbcr_buffer[i] = ycbcr_buffer[i];
-   }
-   for (i = 0; i < VL_MAX_REF_FRAMES; ++i)
-      bs->mv_stream[i] = mv_stream[i];
-
-   // TODO
-   for (i = 0; i < bs->width*bs->height; ++i) {
-      bs->mv_stream[0][i].top.x = bs->mv_stream[0][i].top.y = 0;
-      bs->mv_stream[0][i].top.field_select = PIPE_VIDEO_FRAME;
-      bs->mv_stream[0][i].top.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
-      bs->mv_stream[0][i].bottom.x = bs->mv_stream[0][i].bottom.y = 0;
-      bs->mv_stream[0][i].bottom.field_select = PIPE_VIDEO_FRAME;
-      bs->mv_stream[0][i].bottom.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
-
-      bs->mv_stream[1][i].top.x = bs->mv_stream[1][i].top.y = 0;
-      bs->mv_stream[1][i].top.field_select = PIPE_VIDEO_FRAME;
-      bs->mv_stream[1][i].top.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
-      bs->mv_stream[1][i].bottom.x = bs->mv_stream[1][i].bottom.y = 0;
-      bs->mv_stream[1][i].bottom.field_select = PIPE_VIDEO_FRAME;
-      bs->mv_stream[1][i].bottom.weight = PIPE_VIDEO_MV_WEIGHT_MIN;
+   memset(bs, 0, sizeof(struct vl_mpg12_bs));
+
+   bs->decoder = decoder;
+
+   if (!tables_initialized) {
+      init_tables();
+      tables_initialized = true;
    }
 }
 
 void
-vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const void *buffer,
-                   struct pipe_mpeg12_picture_desc *picture, unsigned num_ycbcr_blocks[3])
+vl_mpg12_bs_decode(struct vl_mpg12_bs *bs,
+                   struct pipe_video_buffer *target,
+                   struct pipe_mpeg12_picture_desc *picture,
+                   unsigned num_buffers,
+                   const void * const *buffers,
+                   const unsigned *sizes)
 {
    assert(bs);
-   assert(num_ycbcr_blocks);
-   assert(buffer && num_bytes);
 
-   bs->num_ycbcr_blocks = num_ycbcr_blocks;
+   bs->desc = picture;
+   bs->intra_dct_tbl = picture->intra_vlc_format ? tbl_B15 : tbl_B14_AC;
+
+   vl_vlc_init(&bs->vlc, num_buffers, buffers, sizes);
+   while (vl_vlc_search_byte(&bs->vlc, ~0, 0x00) && vl_vlc_bits_left(&bs->vlc) > 32) {
+      uint32_t code = vl_vlc_peekbits(&bs->vlc, 32);
 
-   vl_vlc_init(&bs->vlc, buffer, num_bytes);
+      if (code >= 0x101 && code <= 0x1AF) {
+         vl_vlc_eatbits(&bs->vlc, 24);
+         decode_slice(bs, target);
 
-   while(decode_slice(bs, picture));
+         /* align to a byte again */
+         vl_vlc_eatbits(&bs->vlc, vl_vlc_valid_bits(&bs->vlc) & 7);
+
+      } else {
+         vl_vlc_eatbits(&bs->vlc, 8);
+      }
+
+      vl_vlc_fillbits(&bs->vlc);
+   }
 }