g3dvl: Rewrite the mpeg 1&2 bitstream parser
authorChristian König <deathsimple@vodafone.de>
Wed, 24 Aug 2011 20:51:31 +0000 (22:51 +0200)
committerChristian König <deathsimple@vodafone.de>
Fri, 26 Aug 2011 10:10:35 +0000 (12:10 +0200)
Based on work of Maarten Lankhorst this time.

Signed-off-by: Christian König <deathsimple@vodafone.de>
Reviewed-by: Younes Manton <younes.m@gmail.com>
src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
src/gallium/auxiliary/vl/vl_mpeg12_bitstream.h
src/gallium/auxiliary/vl/vl_mpeg12_decoder.c
src/gallium/auxiliary/vl/vl_vlc.h
src/gallium/include/pipe/p_video_state.h

index bc889292ad7f87f2957a8bb6212ddc7db14e2004..ef00e2d9466c81c4853bffddfda7988608629354 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
  *
  **************************************************************************/
 
-/**
- * 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_compiler.h>
-#include <pipe/p_video_state.h>
+#include <pipe/p_video_decoder.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 {
-   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}
-};
-
-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}
-};
-
-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}
-};
-
-#undef INTRA
-#undef QUANT
-#undef MC
-#undef CODED
-#undef FWD
-#undef BWD
-#undef INTER
-
-static const MVtab MV_4 [] = {
-   { 3, 6}, { 2, 4}, { 1, 3}, { 1, 3}, { 0, 2}, { 0, 2}, { 0, 2}, { 0, 2}
-};
-
-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}
-};
-
-static const DMVtab DMV_2 [] = {
-   { 0, 1}, { 0, 1}, { 1, 2}, {-1, 2}
-};
-
-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}
-};
-
-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}
+enum {
+   dct_End_of_Block = 0xFF,
+   dct_Escape = 0xFE,
+   dct_DC = 0xFD,
+   dct_AC = 0xFC
 };
 
-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}
+struct dct_coeff
+{
+   uint8_t length;
+   uint8_t run;
+   int16_t level;
 };
 
-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}
+struct dct_coeff_compressed
+{
+   uint32_t bitcode;
+   struct dct_coeff coeff;
 };
 
-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-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 } }
 };
 
-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}
-};
+#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 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-2 */
+static const struct vl_vlc_compressed macroblock_type_i[] = {
+   { 0x8000, { 1, I } },
+   { 0x4000, { 2, Q|I } }
 };
 
-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}
+/* 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 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}
+/* 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 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}
+#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 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}
+/* 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 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}
+/* 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 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}
+/* 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 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}
+/* 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 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}
+/* 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 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}
+/* 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 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
+/* 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 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;
-      }
-
-   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);
-      }
-      return macroblock_modes;
-
-   case D_TYPE:
+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];
 
-      vl_vlc_dumpbits(&bs->vlc, 1);
-      return MACROBLOCK_INTRA;
-
-   default:
-      return 0;
-   }
-}
-
-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_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *src,
+                     unsigned size, bool is_DC)
 {
-   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))) {
+   unsigned i;
 
-      dct_type = vl_vlc_ubits(&bs->vlc, 1) ? PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
-      vl_vlc_dumpbits(&bs->vlc, 1);
+   for (i=0;i<(1<<17);++i) {
+      dst[i].length = 0;
+      dst[i].level = 0;
+      dst[i].run = dct_End_of_Block;
    }
-   return dct_type;
-}
-
-static INLINE int
-get_quantizer_scale(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc * picture)
-{
-   int quantizer_scale_code;
 
-   quantizer_scale_code = vl_vlc_ubits(&bs->vlc, 5);
-   vl_vlc_dumpbits(&bs->vlc, 5);
+   for(; size > 0; --size, ++src) {
+      struct dct_coeff coeff = src->coeff;
+      bool has_sign = true;
 
-   if (picture->q_scale_type)
-      return non_linear_quantizer_scale[quantizer_scale_code];
-   else
-      return quantizer_scale_code << 1;
-}
-
-static INLINE int
-get_motion_delta(struct vl_mpg12_bs *bs, unsigned f_code)
-{
-   int delta;
-   int sign;
-   const MVtab * tab;
+      switch (coeff.run) {
+      case dct_End_of_Block:
+         if (is_DC)
+            continue;
 
-   if (bs->vlc.buf & 0x80000000) {
-      vl_vlc_dumpbits(&bs->vlc, 1);
-      return 0;
-   } else if (bs->vlc.buf >= 0x0c000000) {
+         has_sign = false;
+         break;
 
-      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;
+      case dct_Escape:
+         has_sign = false;
+         break;
 
-      sign = vl_vlc_sbits(&bs->vlc, 1);
-      bs->vlc.buf <<= 1;
+      case dct_DC:
+         if (!is_DC)
+            continue;
 
-      if (f_code)
-         delta += vl_vlc_ubits(&bs->vlc, f_code);
-      bs->vlc.buf <<= f_code;
+         coeff.length += 1;
+         coeff.run = 1;
+         break;
 
-      return (delta ^ sign) - sign;
+      case dct_AC:
+         if (is_DC)
+            continue;
 
-   } else {
+         coeff.length += 1;
+         coeff.run = 1;
+         break;
 
-      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;
+      default:
+         coeff.length += 1;
+         coeff.run += 1;
+         break;
+      }
 
-      sign = vl_vlc_sbits(&bs->vlc, 1);
-      bs->vlc.buf <<= 1;
+      for(i=0; i<(1 << (17 - coeff.length)); ++i)
+         dst[src->bitcode << 1 | i] = coeff;
 
-      if (f_code) {
-         vl_vlc_needbits(&bs->vlc);
-         delta += vl_vlc_ubits(&bs->vlc, f_code);
-         vl_vlc_dumpbits(&bs->vlc, f_code);
+      if (has_sign) {
+        coeff.level = -coeff.level;
+         for(; i<(1 << (18 - coeff.length)); ++i)
+            dst[src->bitcode << 1 | i] = coeff;
       }
-
-      return (delta ^ sign) - sign;
    }
 }
 
-static INLINE int
-bound_motion_vector(int vec, unsigned f_code)
+static INLINE void
+init_tables()
 {
-#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;
-   }
-#else
-   return ((int32_t)vec << (28 - f_code)) >> (28 - f_code);
-#endif
+   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_dmv(struct vl_mpg12_bs *bs)
+DIV2DOWN(int todiv)
 {
-   const DMVtab * tab;
-
-   tab = DMV_2 + vl_vlc_ubits(&bs->vlc, 2);
-   vl_vlc_dumpbits(&bs->vlc, tab->len);
-   return tab->dmv;
+   return (todiv&~1)/2;
 }
 
 static INLINE int
-get_coded_block_pattern(struct vl_mpg12_bs *bs)
+DIV2UP(int todiv)
 {
-   const CBPtab * tab;
-
-   vl_vlc_needbits(&bs->vlc);
-
-   if (bs->vlc.buf >= 0x20000000) {
-
-      tab = CBP_7 + (vl_vlc_ubits(&bs->vlc, 7) - 16);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      return tab->cbp;
-
-   } else {
-
-      tab = CBP_9 + vl_vlc_ubits(&bs->vlc, 9);
-      vl_vlc_dumpbits(&bs->vlc, tab->len);
-      return tab->cbp;
-   }
+   return (todiv+1)/2;
 }
 
-static INLINE int
-get_luma_dc_dct_diff(struct vl_mpg12_bs *bs)
+static INLINE void
+motion_vector(struct vl_mpg12_bs *bs, int r, int s, int dmv, short delta[2], short dmvector[2])
 {
-   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 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);
    }
 }
 
 static INLINE int
-get_chroma_dc_dct_diff(struct vl_mpg12_bs *bs)
+wrap(short f, int shift)
 {
-   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;
-      }
-   } 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 (f < (-16 << shift))
+      return f + (32 << shift);
+   else if (f >= 16 << shift)
+      return f - (32 << shift);
+   else
+      return f;
 }
 
 static INLINE void
-get_intra_block_B14(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+motion_vector_frame(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
 {
-   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 */
+   int dmv = mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
+   short dmvector[2], delta[2];
 
-      normal_code:
-         bs->vlc.buf <<= tab->len;
-         bs->vlc.bits += tab->len + 1;
-         val = tab->level * quantizer_scale;
+   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;
 
-         val = (val ^ vl_vlc_sbits(&bs->vlc, 1)) - vl_vlc_sbits(&bs->vlc, 1);
+      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;
 
-         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 */
+   } else {
+      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]);
    }
-
-   vl_vlc_dumpbits(&bs->vlc, 2);       /* dump end of block code */
 }
 
 static INLINE void
-get_intra_block_B15(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+motion_vector_field(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
 {
-   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) {
-
-         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);
+   int dmv = mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
+   short dmvector[2], delta[2];
 
-            dest[i] = val;
+   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);
 
-            bs->vlc.buf <<= 1;
-            vl_vlc_needbits(&bs->vlc);
-
-            continue;
-
-         } 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);
-
-            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 */
+      mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
+      motion_vector(bs, 1, s, dmv, delta, dmvector);
+   } else {
+      if (!dmv)
+         mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
+      motion_vector(bs, 0, s, dmv, delta, dmvector);
    }
-
-   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;
-
-         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;
-
-      }
-
-   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_dumpbits(&bs->vlc, 2);       /* dump end of block code */
+reset_predictor(struct vl_mpg12_bs *bs) {
+   bs->pred_dc[0] = bs->pred_dc[1] = bs->pred_dc[2] = 0;
 }
 
 static INLINE void
-get_mpeg1_intra_block(struct vl_mpg12_bs *bs, int quantizer_scale, short *dest)
+decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale)
 {
-   int i, val;
-   const DCTtab * tab;
+   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
+   };
 
-   i = 0;
+   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_needbits(&bs->vlc);
+   vl_vlc_fillbits(&bs->vlc);
+   mb->coded_block_pattern = cbp = intra ? 0x3F : vl_vlc_get_vlclbf(&bs->vlc, tbl_B9, 9);
 
-   while (1) {
-      if (bs->vlc.buf >= 0x28000000) {
+   goto entry;
 
-         tab = DCT_B14AC_5 + (vl_vlc_ubits(&bs->vlc, 5) - 5);
+   while(1) {
+      vl_vlc_eatbits(&bs->vlc, entry->length);
+      if (entry->run == dct_End_of_Block) {
 
-         i += tab->run;
-         if (i >= 64)
-            break;     /* end of block */
+         dst += 64;
+         cbp <<= 1;
+         cbp &= 0x3F;
+         blk++;
 
-      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 */
+entry:
+         if (!cbp)
+            break;
 
-         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;
+         while(!(cbp & 0x20)) {
+            cbp <<= 1;
+            blk++;
          }
-         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 */
-}
-
-static INLINE void
-get_mpeg1_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 */
+         vl_vlc_fillbits(&bs->vlc);
 
-      normal_code:
-         bs->vlc.buf <<= tab->len;
-         bs->vlc.bits += tab->len + 1;
-         val = ((2*tab->level+1) * quantizer_scale) >> 1;
+         if (intra) {
+            unsigned cc = blk2cc[blk];
+            unsigned size = vl_vlc_get_vlclbf(&bs->vlc, blk2dcsize[blk], 10);
 
-         /* 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;
-
-      }
-
-   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 */
+            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;
+            }
 
-         i += UBITS(bs->vlc.buf << 6, 6) - 64;
-         if (i >= 64)
-            break;     /* illegal, check needed to avoid buffer overflow */
+            dst[0] = bs->pred_dc[cc];
+            i = 0;
 
-         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;
+         } else {
+            entry = tbl_B14_DC + vl_vlc_peekbits(&bs->vlc, 17);
+            i = -1;
+            continue;
          }
-         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 = 1;
-   bs->ycbcr_stream[cc]->coding = coding;
-   bs->ycbcr_stream[cc]->block_num = bs->block_num++;
-
-   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, dest, sizeof(int16_t) * 64);
-
-   bs->num_ycbcr_blocks[cc]++;
-   bs->ycbcr_stream[cc]++;
-   bs->ycbcr_buffer += 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 = 0;
-   bs->ycbcr_stream[cc]->coding = coding;
-   bs->ycbcr_stream[cc]->block_num = bs->block_num++;
-
-   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, dest, sizeof(int16_t) * 64);
-
-   bs->num_ycbcr_blocks[cc]++;
-   bs->ycbcr_stream[cc]++;
-   bs->ycbcr_buffer += 64;
-}
-
-static INLINE void
-motion_mp1(struct vl_mpg12_bs *bs, unsigned f_code[2], struct vl_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 vl_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 vl_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 vl_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 vl_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 vl_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 vl_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 vl_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 vl_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 vl_motionvector *mv_fwd,
-                    struct vl_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);
+      } else if (entry->run == dct_Escape) {
+         i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
+         if (i > 64)
+            break;
 
-   *quantizer_scale = get_quantizer_scale(bs, picture);
+         dst[i] = vl_vlc_get_simsbf(&bs->vlc, 12) * scale;
 
-   /* ignore intra_slice and all the extra data */
-   while (bs->vlc.buf & 0x80000000) {
-      vl_vlc_dumpbits(&bs->vlc, 9);
-      vl_vlc_needbits(&bs->vlc);
-   }
+      } else {
+         i += entry->run;
+         if (i > 64)
+            break;
 
-   /* 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;
+         dst[i] = entry->level * scale;
       }
-   }
-   vl_vlc_dumpbits(&bs->vlc, mba->len + 1);
-   *x += mba->mba;
 
-   while (*x >= bs->width) {
-      *x -= bs->width;
-      (*y)++;
+      vl_vlc_fillbits(&bs->vlc);
+      entry = table + vl_vlc_peekbits(&bs->vlc, 17);
    }
-   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)
+decode_slice(struct vl_mpg12_bs *bs)
 {
-   enum vl_field_select default_field_select;
-   struct vl_motionvector mv_fwd, mv_bwd;
-   enum pipe_mpeg12_dct_type dct_type;
+   struct pipe_mpeg12_macroblock mb = {};
+   short dct_blocks[64*6];
+   unsigned dct_scale;
+   signed x = -1;
 
-   /* predictor for DC coefficients in intra blocks */
-   int dc_dct_pred[3] = { 0, 0, 0 };
-   int quantizer_scale;
+   mb.base.codec = PIPE_VIDEO_CODEC_MPEG12;
+   mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1;
+   mb.blocks = dct_blocks;
 
-   unsigned x, y, mv_pos;
+   reset_predictor(bs);
+   dct_scale = quant_scale[bs->desc.q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
 
-   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 (vl_vlc_get_uimsbf(&bs->vlc, 1))
+      while (vl_vlc_get_uimsbf(&bs->vlc, 9) & 1)
+         vl_vlc_fillbits(&bs->vlc);
 
-   if (!slice_init(bs, picture, &quantizer_scale, &x, &y, &mv_pos))
-      return false;
+   do {
+      int inc = 0;
 
-   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;
+      vl_vlc_fillbits(&bs->vlc);
 
-   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 (vl_vlc_peekbits(&bs->vlc, 11) == 15) {
+         vl_vlc_eatbits(&bs->vlc, 11);
+         vl_vlc_fillbits(&bs->vlc);
+      }
 
-   while (1) {
-      int macroblock_modes;
-      int mba_inc;
-      const MBAtab * mba;
+      while (vl_vlc_peekbits(&bs->vlc, 11) == 8) {
+         vl_vlc_eatbits(&bs->vlc, 11);
+         vl_vlc_fillbits(&bs->vlc);
+         inc += 33;
+      }
+      inc += vl_vlc_get_vlclbf(&bs->vlc, tbl_B1, 11);
+      if (x != -1) {
+         mb.num_skipped_macroblocks = inc - 1;
+         bs->decoder->decode_macroblock(bs->decoder, &mb.base, 1);
+      }
+      mb.x = x += inc;
 
-      vl_vlc_needbits(&bs->vlc);
+      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;
 
-      macroblock_modes = get_macroblock_modes(bs, picture);
-      dct_type = get_dct_type(bs, picture, macroblock_modes);
+      case PIPE_MPEG12_PICTURE_CODING_TYPE_P:
+         mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B3, 6);
+         break;
 
-      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;
+      case PIPE_MPEG12_PICTURE_CODING_TYPE_B:
+         mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B4, 6);
          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;
+         mb.macroblock_type = 0;
+         /* dumb gcc */
+         assert(0);
+      }
 
-         /* 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;
-         break;
+      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
+               mb.macroblock_modes.bits.frame_motion_type = 2;
+         } else
+            mb.macroblock_modes.bits.field_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
 
-      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;
-         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
+            mb.macroblock_modes.bits.field_motion_type = 1;
       }
 
-      /* maybe integrate MACROBLOCK_QUANT test into get_macroblock_modes ? */
-      if (macroblock_modes & MACROBLOCK_QUANT)
-         quantizer_scale = get_quantizer_scale(bs, picture);
+      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 (macroblock_modes & MACROBLOCK_INTRA) {
+      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)];
 
-         if (picture->concealment_motion_vectors) {
-            if (picture->picture_structure == FRAME_PICTURE)
-               motion_fr_conceal(bs, picture->f_code[0], &mv_fwd);
-            else
-               motion_fi_conceal(bs, picture->f_code[0], &mv_fwd);
+      if (inc > 1 && bs->desc.picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_P)
+         memset(mb.PMV, 0, sizeof(mb.PMV));
 
-         } 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;
-            }
+      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
-            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;
-            }
-
-         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
-         }
-
-         dc_dct_pred[0] = dc_dct_pred[1] = dc_dct_pred[2] = 0;
+            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];
       }
-   }
+
+      if (inc > 1 || !(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA))
+         reset_predictor(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;
+
+   } while (vl_vlc_bytes_left(&bs->vlc) && vl_vlc_peekbits(&bs->vlc, 23));
+
+   mb.num_skipped_macroblocks = 0;
+   bs->decoder->decode_macroblock(bs->decoder, &mb.base, 1);
+   return true;
 }
 
 void
-vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height)
+vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder)
 {
+   static bool tables_initialized = false;
+
    assert(bs);
 
    memset(bs, 0, sizeof(struct vl_mpg12_bs));
 
-   bs->width = width;
-   bs->height = height;
+   bs->decoder = decoder;
+
+   if (!tables_initialized) {
+      init_tables();
+      tables_initialized = true;
+   }
 }
 
 void
-vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct vl_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
-                        short *ycbcr_buffer, struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES])
+vl_mpg12_bs_set_picture_desc(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture)
 {
-   unsigned i;
-
-   assert(bs);
-   assert(ycbcr_stream && ycbcr_buffer);
-   assert(mv_stream);
-
-   bs->block_num = 0;
-
-   for (i = 0; i < VL_MAX_PLANES; ++i)
-      bs->ycbcr_stream[i] = ycbcr_stream[i];
-   bs->ycbcr_buffer = ycbcr_buffer;
-
-   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;
-   }
+   bs->desc = *picture;
+   bs->intra_dct_tbl = picture->intra_vlc_format ? tbl_B15 : tbl_B14_AC;
 }
 
 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, unsigned num_bytes, const uint8_t *buffer)
 {
    assert(bs);
-   assert(num_ycbcr_blocks);
    assert(buffer && num_bytes);
 
-   bs->num_ycbcr_blocks = num_ycbcr_blocks;
+   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, buffer, num_bytes);
+
+         if (!decode_slice(bs))
+            return;
 
-   vl_vlc_init(&bs->vlc, buffer, num_bytes);
+         /* it's possible for the vlc to consume up to eight extra bytes */
+         consumed = num_bytes - vl_vlc_bytes_left(&bs->vlc);
+         consumed = consumed > 8 ? consumed - 8 : 0;
 
-   while(decode_slice(bs, picture));
+         /* crap, this is a bug we have consumed more bytes than left in the buffer */
+         assert(consumed <= num_bytes);
+
+         num_bytes -= consumed;
+         buffer += consumed;
+
+      } else {
+         ++buffer;
+         --num_bytes;
+      }
+   }
 }
index 797a7e792a8ee6ba1c59c80a69b322a9ac216a3a..c3f14a1793276b55de986e46e53d4e6d9d254123 100644 (file)
 
 #include "vl_defines.h"
 #include "vl_vlc.h"
-#include "vl_vertex_buffers.h"
 
 struct vl_mpg12_bs
 {
-   unsigned width, height;
+   struct pipe_video_decoder *decoder;
 
-   struct vl_vlc vlc;
-
-   unsigned block_num;
-   unsigned *num_ycbcr_blocks;
+   struct pipe_mpeg12_picture_desc desc;
+   struct dct_coeff *intra_dct_tbl;
 
-   struct vl_ycbcr_block *ycbcr_stream[VL_MAX_PLANES];
-   short *ycbcr_buffer;
-
-   struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES];
+   struct vl_vlc vlc;
+   short pred_dc[3];
 };
 
 void
-vl_mpg12_bs_init(struct vl_mpg12_bs *bs, unsigned width, unsigned height);
+vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder);
 
 void
-vl_mpg12_bs_set_buffers(struct vl_mpg12_bs *bs, struct vl_ycbcr_block *ycbcr_stream[VL_MAX_PLANES],
-                        short *ycbcr_buffer, struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES]);
+vl_mpg12_bs_set_picture_desc(struct vl_mpg12_bs *bs, struct pipe_mpeg12_picture_desc *picture);
 
 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, unsigned num_bytes, const uint8_t *buffer);
 
 #endif /* vl_mpeg12_bitstream_h */
index a27066765eb92d741802c7a805a34e5c044a73a3..e0b477d315a9658243f564c3476ecdd859694fe3 100644 (file)
@@ -450,9 +450,7 @@ vl_mpeg12_create_buffer(struct pipe_video_decoder *decoder)
       goto error_zscan;
 
    if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
-      vl_mpg12_bs_init(&buffer->bs,
-                       dec->base.width / MACROBLOCK_WIDTH,
-                       dec->base.height / MACROBLOCK_HEIGHT);
+      vl_mpg12_bs_init(&buffer->bs, decoder);
 
    return buffer;
 
@@ -614,7 +612,7 @@ vl_mpeg12_begin_frame(struct pipe_video_decoder *decoder)
       buf->mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i);
 
    if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
-      vl_mpg12_bs_set_buffers(&buf->bs, buf->ycbcr_stream, buf->texels, buf->mv_stream);
+      vl_mpg12_bs_set_picture_desc(&buf->bs, &dec->picture_desc);
 
    } else {
 
@@ -708,7 +706,7 @@ vl_mpeg12_decode_bitstream(struct pipe_video_decoder *decoder,
       vl_zscan_set_layout(&buf->zscan[i], dec->picture_desc.alternate_scan ?
                           dec->zscan_alternate : dec->zscan_normal);
 
-   vl_mpg12_bs_decode(&buf->bs, num_bytes, data, &dec->picture_desc, buf->num_ycbcr_blocks);
+   vl_mpg12_bs_decode(&buf->bs, num_bytes, data);
 }
 
 static void
index e81b1e9afd2c2687cf39ee71e4f79a2344bf73fc..17a7b650c09c0ac75581c3e8e07c7e03ba7b38ac 100644 (file)
  *
  **************************************************************************/
 
-/**
- * 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
- */
-
 #ifndef vl_vlc_h
 #define vl_vlc_h
 
-#include "pipe/p_compiler.h"
+#include <assert.h>
+
+#include <pipe/p_compiler.h>
+
+#include <util/u_math.h>
 
 struct vl_vlc
 {
-   uint32_t buf; /* current 32 bit working set of buffer */
-   int bits;     /* used bits in working set */
-   const uint8_t *ptr; /* buffer with stream data */
-   const uint8_t *max; /* ptr+len of buffer */
+   uint64_t buffer;
+   unsigned valid_bits;
+   uint32_t *data;
+   uint32_t *end;
+};
+
+struct vl_vlc_entry
+{
+   int8_t length;
+   int8_t value;
+};
+
+struct vl_vlc_compressed
+{
+   uint16_t bitcode;
+   struct vl_vlc_entry entry;
 };
 
 static INLINE void
-vl_vlc_restart(struct vl_vlc *vlc)
+vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size)
 {
-   vlc->buf = (vlc->ptr[0] << 24) | (vlc->ptr[1] << 16) | (vlc->ptr[2] << 8) | vlc->ptr[3];
-   vlc->bits = -16;
-   vlc->ptr += 4;
+   unsigned i, bits = util_logbase2(dst_size);
+
+   for (i=0;i<dst_size;++i) {
+      dst[i].length = 0;
+      dst[i].value = 0;
+   }
+
+   for(; src_size > 0; --src_size, ++src) {
+      for(i=0; i<(1 << (bits - src->entry.length)); ++i)
+         dst[src->bitcode >> (16 - bits) | i] = src->entry;
+   }
+}
+
+static INLINE void
+vl_vlc_fillbits(struct vl_vlc *vlc)
+{
+   if (vlc->valid_bits < 32) {
+      uint32_t value = *vlc->data;
+
+      //assert(vlc->data <= vlc->end);
+
+#ifndef PIPE_ARCH_BIG_ENDIAN
+      value = util_bswap32(value);
+#endif
+
+      vlc->buffer |= (uint64_t)value << (32 - vlc->valid_bits);
+      ++vlc->data;
+      vlc->valid_bits += 32;
+   }
 }
 
 static INLINE void
 vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len)
 {
-   vlc->ptr = data;
-   vlc->max = data + len;
-   vl_vlc_restart(vlc);
+   assert(vlc);
+   assert(data && len);
+
+   vlc->buffer = 0;
+   vlc->valid_bits = 0;
+
+   /* align the data pointer */
+   while((uint64_t)data & 3) {
+      vlc->buffer |= (uint64_t)*data << (56 - vlc->valid_bits);
+      ++data;
+      --len;
+      vlc->valid_bits += 8;
+   }
+   vlc->data = (uint32_t*)data;
+   vlc->end = (uint32_t*)(data + len);
+
+   vl_vlc_fillbits(vlc);
+   vl_vlc_fillbits(vlc);
+}
+
+static INLINE unsigned
+vl_vlc_bytes_left(struct vl_vlc *vlc)
+{
+   return ((uint8_t*)vlc->end)-((uint8_t*)vlc->data);
 }
 
-static INLINE bool
-vl_vlc_getbyte(struct vl_vlc *vlc)
+static INLINE unsigned
+vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)
 {
-   vlc->buf <<= 8;
-   vlc->buf |= vlc->ptr[0];
-   vlc->ptr++;
-   return vlc->ptr < vlc->max;
+   //assert(vlc->valid_bits >= num_bits);
+
+   return vlc->buffer >> (64 - num_bits);
 }
 
-#define vl_vlc_getword(vlc, shift)                                      \
-do {                                                                    \
-   (vlc)->buf |= (((vlc)->ptr[0] << 8) | (vlc)->ptr[1]) << (shift);     \
-   (vlc)->ptr += 2;                                                     \
-} while (0)
-
-/* make sure that there are at least 16 valid bits in bit_buf */
-#define vl_vlc_needbits(vlc)                    \
-do {                                            \
-    if ((vlc)->bits >= 0) {                      \
-       vl_vlc_getword(vlc, (vlc)->bits);       \
-       (vlc)->bits -= 16;                      \
-    }                                           \
-} while (0)
-
-/* make sure that the full 32 bit of the buffer are valid */
 static INLINE void
-vl_vlc_need32bits(struct vl_vlc *vlc)
+vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)
 {
-   vl_vlc_needbits(vlc);
-   if (vlc->bits > -8) {
-      unsigned n = -vlc->bits;
-      vlc->buf <<= n;
-      vlc->buf |= *vlc->ptr << 8;
-      vlc->bits = -8;
-      vlc->ptr++;
-   }
-   if (vlc->bits > -16) {
-      unsigned n = -vlc->bits - 8;
-      vlc->buf <<= n;
-      vlc->buf |= *vlc->ptr;
-      vlc->bits = -16;
-      vlc->ptr++;
-   }
+   //assert(vlc->valid_bits > num_bits);
+
+   vlc->buffer <<= num_bits;
+   vlc->valid_bits -= num_bits;
 }
 
-/* remove num valid bits from bit_buf */
-#define vl_vlc_dumpbits(vlc, num)       \
-do {                                   \
-    (vlc)->buf <<= (num);              \
-    (vlc)->bits += (num);              \
-} while (0)
+static INLINE unsigned
+vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)
+{
+   unsigned value;
+
+   //assert(vlc->valid_bits >= num_bits);
+
+   value = vlc->buffer >> (64 - num_bits);
+   vl_vlc_eatbits(vlc, num_bits);
+
+   return value;
+}
+
+static INLINE signed
+vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)
+{
+   signed value;
+
+   //assert(vlc->valid_bits >= num_bits);
+
+   value = ((int64_t)vlc->buffer) >> (64 - num_bits);
+   vl_vlc_eatbits(vlc, num_bits);
 
-/* take num bits from the high part of bit_buf and zero extend them */
-#define vl_vlc_ubits(vlc, num) (((uint32_t)((vlc)->buf)) >> (32 - (num)))
+   return value;
+}
 
-/* take num bits from the high part of bit_buf and sign extend them */
-#define vl_vlc_sbits(vlc, num) (((int32_t)((vlc)->buf)) >> (32 - (num)))
+static INLINE int8_t
+vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits)
+{
+   tbl += vl_vlc_peekbits(vlc, num_bits);
+   vl_vlc_eatbits(vlc, tbl->length);
+   return tbl->value;
+}
 
 #endif /* vl_vlc_h */
index 8166ac76b632b9f291672e4d2bee72f32abd65f8..f655ed411f4f4545d698a7d0cddae53a21d0d36f 100644 (file)
@@ -43,6 +43,17 @@ struct pipe_video_rect
    unsigned x, y, w, h;
 };
 
+/*
+ * see table 6-12 in the spec
+ */
+enum pipe_mpeg12_picture_coding_type
+{
+   PIPE_MPEG12_PICTURE_CODING_TYPE_I = 0x01,
+   PIPE_MPEG12_PICTURE_CODING_TYPE_P = 0x02,
+   PIPE_MPEG12_PICTURE_CODING_TYPE_B = 0x03,
+   PIPE_MPEG12_PICTURE_CODING_TYPE_D = 0x04
+};
+
 /*
  * see table 6-14 in the spec
  */