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