/* class for decoders Copyright (C) 1999 Martin Vogt This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation. For more information look at the file COPYRIGHT in this package */ #include "decoderClass.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef NDEBUG #define NDEBUG #endif #include #define DEBUG_DECODERCLASS(x) //#define DEBUG_DECODERCLASS(x) x /* Array mapping zigzag to array pointer offset. */ static const int zigzag_direct_nommx[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63}; static const int zigzag_direct_mmx[64] = { 0*8+0/* 0*/, 1*8+0/* 1*/, 0*8+1/* 8*/, 0*8+2/*16*/, 1*8+1/* 9*/, 2*8+0/* 2*/, 3*8+0/* 3*/, 2*8+1/*10*/, 1*8+2/*17*/, 0*8+3/*24*/, 0*8+4/*32*/, 1*8+3/*25*/, 2*8+2/*18*/, 3*8+1/*11*/, 4*8+0/* 4*/, 5*8+0/* 5*/, 4*8+1/*12*/, 5*8+2/*19*/, 2*8+3/*26*/, 1*8+4/*33*/, 0*8+5/*40*/, 0*8+6/*48*/, 1*8+5/*41*/, 2*8+4/*34*/, 3*8+3/*27*/, 4*8+2/*20*/, 5*8+1/*13*/, 6*8+0/* 6*/, 7*8+0/* 7*/, 6*8+1/*14*/, 5*8+2/*21*/, 4*8+3/*28*/, 3*8+4/*35*/, 2*8+5/*42*/, 1*8+6/*49*/, 0*8+7/*56*/, 1*8+7/*57*/, 2*8+6/*50*/, 3*8+5/*43*/, 4*8+4/*36*/, 5*8+3/*29*/, 6*8+2/*22*/, 7*8+1/*15*/, 7*8+2/*23*/, 6*8+3/*30*/, 5*8+4/*37*/, 4*8+5/*44*/, 3*8+6/*51*/, 2*8+7/*58*/, 3*8+7/*59*/, 4*8+6/*52*/, 5*8+5/*45*/, 6*8+4/*38*/, 7*8+3/*31*/, 7*8+4/*39*/, 6*8+5/*46*/, 7*8+6/*53*/, 4*8+7/*60*/, 5*8+7/*61*/, 6*8+6/*54*/, 7*8+5/*47*/, 7*8+6/*55*/, 6*8+7/*62*/, 7*8+7/*63*/ }; /* Bit masks used by bit i/o operations. */ static unsigned int bitMask[] = {0xffffffff,0x7fffffff,0x3fffffff,0x1fffffff, 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff, 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff, 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff, 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f, 0x0000000f, 0x00000007, 0x00000003, 0x00000001}; static unsigned int rBitMask[] = {0xffffffff,0xfffffffe,0xfffffffc,0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000}; static unsigned int bitTest[] = { 0x80000000,0x40000000,0x20000000,0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000, 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001}; DecoderClass::DecoderClass(VideoDecoder* vid_stream, MpegVideoStream* mpegVideoStream) { this->vid_stream=vid_stream; this->mpegVideoStream=mpegVideoStream; #ifdef INTEL lmmx=mm_support(); #else lmmx=false; DEBUG_DECODERCLASS(cout << "no INTEL arch- disable MMX in decoderClass"<showBits(5); if (index < 31) { macro_val = dct_dc_size_luminance[index].value; mpegVideoStream->flushBits(dct_dc_size_luminance[index].num_bits); } else { index=mpegVideoStream->showBits(9); index -= 0x1f0; macro_val = dct_dc_size_luminance1[index].value; mpegVideoStream->flushBits(dct_dc_size_luminance1[index].num_bits); } return macro_val; } int DecoderClass::decodeDCTDCSizeChrom() { unsigned int macro_val; unsigned int index; index=mpegVideoStream->showBits(5); if (index < 31) { macro_val = dct_dc_size_chrominance[index].value; mpegVideoStream->flushBits(dct_dc_size_chrominance[index].num_bits); }else { index=mpegVideoStream->showBits(10); index -= 0x3e0; macro_val = dct_dc_size_chrominance1[index].value; mpegVideoStream->flushBits(dct_dc_size_chrominance1[index].num_bits); } return macro_val; } /* *-------------------------------------------------------------- * * DecodeMBAddrInc -- * * Huffman DecoderClass for macro_block_address_increment; the location * in which the result will be placed is being passed as argument. * The decoded value is obtained by doing a table lookup on * mb_addr_inc. * * Results: * The decoded value for macro_block_address_increment or MPGDECODE_ERROR * for unbound values will be placed in the location specified. * * Side effects: * Bit stream is irreversibly parsed. * *-------------------------------------------------------------- */ int DecoderClass::decodeMBAddrInc() { unsigned int index; int val; index=mpegVideoStream->showBits(11); val = mb_addr_inc[index].value; mpegVideoStream->flushBits(mb_addr_inc[index].num_bits); if (mb_addr_inc[index].num_bits==0) { DEBUG_DECODERCLASS(cout<<"num_bits==0"<showBits(11); value = motion_vectors[index].code; mpegVideoStream->flushBits(motion_vectors[index].num_bits); return value; } /* *-------------------------------------------------------------- * * DecodeCBP -- * * Huffman DecoderClass for coded_block_pattern; location in which the * decoded result will be placed is being passed as argument. The * decoded values are obtained by doing a table lookup on * coded_block_pattern. * * Results: * The decoded value for coded_block_pattern or MPGDECODE_ERROR for unbound * values will be placed in the location specified. * * Side effects: * Bit stream is irreversibly parsed. * *-------------------------------------------------------------- */ int DecoderClass::decodeCBP() { unsigned int index; unsigned int coded_bp; index=mpegVideoStream->showBits(9); coded_bp = coded_block_pattern[index].cbp; mpegVideoStream->flushBits(coded_block_pattern[index].num_bits); return coded_bp; } /* *-------------------------------------------------------------- * * DecodeMBTypeB -- * * Huffman Decoder for macro_block_type in bidirectionally-coded * pictures;locations in which the decoded results: macroblock_quant, * macroblock_motion_forward, macro_block_motion_backward, * macroblock_pattern, macro_block_intra, will be placed are * being passed as argument. The decoded values are obtained by * doing a table lookup on mb_type_B. * * Results: * The various decoded values for macro_block_type in * bidirectionally-coded pictures or MPGDECODE_ERROR for unbound values will * be placed in the locations specified. * * Side effects: * Bit stream is irreversibly parsed. * *-------------------------------------------------------------- */ void DecoderClass::decodeMBTypeB(int& quant,int& motion_fwd, int& motion_bwd,int& pat,int& intra){ unsigned int index; index=mpegVideoStream->showBits(6); quant = mb_type_B[index].mb_quant; motion_fwd = mb_type_B[index].mb_motion_forward; motion_bwd = mb_type_B[index].mb_motion_backward; pat = mb_type_B[index].mb_pattern; intra = mb_type_B[index].mb_intra; if (index == 0) { DEBUG_DECODERCLASS(cout << "error in decodeMBTypeB"<flushBits(mb_type_B[index].num_bits); } /* *-------------------------------------------------------------- * * DecodeMBTypeI -- * * Huffman Decoder for macro_block_type in intra-coded pictures; * locations in which the decoded results: macroblock_quant, * macroblock_motion_forward, macro_block_motion_backward, * macroblock_pattern, macro_block_intra, will be placed are * being passed as argument. * * Results: * The various decoded values for macro_block_type in intra-coded * pictures or MPGDECODE_ERROR for unbound values will be placed in the * locations specified. * * Side effects: * Bit stream is irreversibly parsed. * *-------------------------------------------------------------- */ void DecoderClass::decodeMBTypeI(int& quant,int& motion_fwd, int& motion_bwd,int& pat,int& intra) { unsigned int index; static int quantTbl[4] = {MPGDECODE_ERROR, 1, 0, 0}; index=mpegVideoStream->showBits(2); motion_fwd = 0; motion_bwd = 0; pat = 0; intra = 1; quant = quantTbl[index]; if (quant == MPGDECODE_ERROR) { DEBUG_DECODERCLASS(cout << "decodeMBTypeI Error"<flushBits (1 + quant); } } /* *-------------------------------------------------------------- * * DecodeMBTypeP -- * * Huffman Decoder for macro_block_type in predictive-coded pictures; * locations in which the decoded results: macroblock_quant, * macroblock_motion_forward, macro_block_motion_backward, * macroblock_pattern, macro_block_intra, will be placed are * being passed as argument. The decoded values are obtained by * doing a table lookup on mb_type_P. * * Results: * The various decoded values for macro_block_type in * predictive-coded pictures or MPGDECODE_ERROR for unbound values will be * placed in the locations specified. * * Side effects: * Bit stream is irreversibly parsed. * *-------------------------------------------------------------- */ void DecoderClass::decodeMBTypeP(int& quant,int& motion_fwd, int& motion_bwd,int& pat,int& intra) { unsigned int index; index=mpegVideoStream->showBits(6); quant = mb_type_P[index].mb_quant; motion_fwd = mb_type_P[index].mb_motion_forward; motion_bwd = mb_type_P[index].mb_motion_backward; pat = mb_type_P[index].mb_pattern; intra = mb_type_P[index].mb_intra; if (index == 0) { DEBUG_DECODERCLASS(cout << "error in decodeMBTypeP"<flushBits(mb_type_P[index].num_bits); } /* *-------------------------------------------------------------- * * decodeDCTCoeff -- * * Huffman Decoder for dct_coeff_first and dct_coeff_next; * locations where the results of decoding: run and level, are to * be placed and also the type of DCT coefficients, either * dct_coeff_first or dct_coeff_next, are being passed as argument. * * The decoder first examines the next 8 bits in the input stream, * and perform according to the following cases: * * '0000 0000' - examine 8 more bits (i.e. 16 bits total) and * perform a table lookup on dct_coeff_tbl_0. * One more bit is then examined to determine the sign * of level. * * '0000 0001' - examine 4 more bits (i.e. 12 bits total) and * perform a table lookup on dct_coeff_tbl_1. * One more bit is then examined to determine the sign * of level. * * '0000 0010' - examine 2 more bits (i.e. 10 bits total) and * perform a table lookup on dct_coeff_tbl_2. * One more bit is then examined to determine the sign * of level. * * '0000 0011' - examine 2 more bits (i.e. 10 bits total) and * perform a table lookup on dct_coeff_tbl_3. * One more bit is then examined to determine the sign * of level. * * otherwise - perform a table lookup on dct_coeff_tbl. If the * value of run is not ESCAPE, extract one more bit * to determine the sign of level; otherwise 6 more * bits will be extracted to obtain the actual value * of run , and then 8 or 16 bits to get the value of level. * * * * Results: * The decoded values of run and level or MPGDECODE_ERROR * for unbound values * are placed in the locations specified. * * Side effects: * Bit stream is irreversibly parsed. * *-------------------------------------------------------------- */ void DecoderClass::decodeDCTCoeff(unsigned short int* dct_coeff_tbl, unsigned RUNTYPE& run,int& level) { unsigned int temp, index; unsigned int value, next32bits, flushed; /* * Grab the next 32 bits and use it to improve performance of * getting the bits to parse. Thus, calls are translated as: * * show_bitsX <--> next32bits >> (32-X) * get_bitsX <--> val = next32bits >> (32-flushed-X); * flushed += X; * next32bits &= bitMask[flushed]; * flush_bitsX <--> flushed += X; * next32bits &= bitMask[flushed]; * */ next32bits=mpegVideoStream->showBits32(); flushed = 0; /* show_bits8(index); */ index = next32bits >> 24; if (index > 3) { value = dct_coeff_tbl[index]; run = (value & RUN_MASK) >> RUN_SHIFT; if (run == END_OF_BLOCK) { level = END_OF_BLOCK; } else { /* num_bits = (value & NUM_MASK) + 1; */ /* flush_bits(num_bits); */ flushed = (value & NUM_MASK) + 1; next32bits &= bitMask[flushed]; if (run != ESCAPE) { level = (value & LEVEL_MASK) >> LEVEL_SHIFT; /* get_bits1(value); */ /* if (value) *level = -*level; */ if (next32bits >> (31-flushed)) level = -level; flushed++; /* next32bits &= bitMask[flushed]; last op before update */ } else { /* *run == ESCAPE */ /* get_bits14(temp); */ temp = next32bits >> (18-flushed); flushed += 14; next32bits &= bitMask[flushed]; run = temp >> 8; temp &= 0xff; if (temp == 0) { /* get_bits8(*level); */ level = next32bits >> (24-flushed); flushed += 8; /* next32bits &= bitMask[flushed]; last op before update */ assert(level >= 128); } else if (temp != 128) { /* Grab sign bit */ level = ((int) (temp << 24)) >> 24; } else { /* get_bits8(*level); */ level = next32bits >> (24-flushed); flushed += 8; /* next32bits &= bitMask[flushed]; last op before update */ level = level - 256; assert(level <= -128 && level >= -255); } } /* Update bitstream... */ mpegVideoStream->flushBitsDirect(flushed); } } else { if (index == 2) { /* show_bits10(index); */ index = next32bits >> 22; value = dct_coeff_tbl_2[index & 3]; } else if (index == 3) { /* show_bits10(index); */ index = next32bits >> 22; value = dct_coeff_tbl_3[index & 3]; } else if (index) { /* index == 1 */ /* show_bits12(index); */ index = next32bits >> 20; value = dct_coeff_tbl_1[index & 15]; } else { /* index == 0 */ /* show_bits16(index); */ index = next32bits >> 16; value = dct_coeff_tbl_0[index & 255]; } run = (value & RUN_MASK) >> RUN_SHIFT; level = (value & LEVEL_MASK) >> LEVEL_SHIFT; /* * Fold these operations together to make it fast... */ /* num_bits = (value & NUM_MASK) + 1; */ /* flush_bits(num_bits); */ /* get_bits1(value); */ /* if (value) *level = -*level; */ flushed = (value & NUM_MASK) + 2; if ((next32bits >> (32-flushed)) & 0x1) level = -level; /* Update bitstream ... */ mpegVideoStream->flushBitsDirect(flushed); } } void DecoderClass::resetDCT() { /* Reset past dct dc y, cr, and cb values. */ dct_dc_y_past = 1024 << 3; dct_dc_cr_past = 1024 << 3; dct_dc_cb_past = 1024 << 3; } /* *-------------------------------------------------------------- * * ParseReconBlock -- * * Parse values for block structure from bitstream. * n is an indication of the position of the block within * the macroblock (i.e. 0-5) and indicates the type of * block (i.e. luminance or chrominance). Reconstructs * coefficients from values parsed and puts in * block.dct_recon array in vid stream structure. * sparseFlag is set when the block contains only one * coeffictient and is used by the IDCT. * * Results: * * * Side effects: * Bit stream irreversibly parsed. * *-------------------------------------------------------------- */ void DecoderClass::ParseReconBlock(int& n,int& mb_intra, unsigned int& qscale, int& lflag, unsigned int* iqmatrixptr, unsigned int* niqmatrixptr) { int coeffCount=0; if (mpegVideoStream->hasBytes(512) == false) { DEBUG_DECODERCLASS(cout << "cannot get 512 raw bytes"< next16bits >> (16-X) * get_bitsX <--> val = next16bits >> (16-flushed-X); * flushed += X; * next16bits &= bitMask[flushed]; * flush_bitsX <--> flushed += X; * next16bits &= bitMask[flushed]; * * I've streamlined the code a lot, so that we don't have to mask * out the low order bits and a few of the extra adds are removed. * bsmith */ unsigned int next16bits, index, flushed; next16bits=mpegVideoStream->showBits16(); index = next16bits >> (16-5); if (index < 31) { size = dct_dc_size_luminance[index].value; flushed = dct_dc_size_luminance[index].num_bits; } else { index = next16bits >> (16-9); index -= 0x1f0; size = dct_dc_size_luminance1[index].value; flushed = dct_dc_size_luminance1[index].num_bits; } next16bits &= bitMask[(16+flushed)&0x1f]; if (size != 0) { flushed += size; coeff = next16bits >> (16-flushed); if (!(coeff & bitTest[32-size])) { coeff++; coeff|= rBitMask[size&0x1f]; } coeff <<= 3; } else { coeff = 0; } mpegVideoStream->flushBitsDirect(flushed); if ( (n == 0) && (lflag) ) { coeff += 1024; } else { coeff += dct_dc_y_past; } dct_dc_y_past = coeff; } else { /* n = 4 or 5 */ /* * Get the chrominance bits. This code has been hand optimized to * as described above */ unsigned int next16bits, index, flushed; next16bits=mpegVideoStream->showBits16(); index = next16bits >> (16-5); if (index < 31) { size = dct_dc_size_chrominance[index].value; flushed = dct_dc_size_chrominance[index].num_bits; } else { index = next16bits >> (16-10); index -= 0x3e0; size = dct_dc_size_chrominance1[index].value; flushed = dct_dc_size_chrominance1[index].num_bits; } next16bits &= bitMask[(16+flushed)&0x1f]; if (size != 0) { flushed += size; coeff = next16bits >> (16-flushed); if (!(coeff & bitTest[32-size])) { coeff++; coeff|=rBitMask[size&0x1f]; } coeff <<= 3; } else { coeff = 0; } mpegVideoStream->flushBitsDirect(flushed); /* We test 5 first; a result of the mixup of Cr and Cb */ if (n == 5) { if (lflag) { coeff += 1024; } else { coeff += dct_dc_cr_past; } dct_dc_cr_past = coeff; } else { if (lflag) { coeff += 1024; } else { coeff += dct_dc_cb_past; } dct_dc_cb_past = coeff; } } coeff <<= lmmx; reconptr[0] = coeff; pos=0; i = 0; coeffCount = (coeff != 0); // we never have d_types so there is no check while(1) { decodeDCTCoeff(dct_coeff_next,run,level); if (run >=END_OF_BLOCK) { break; } i++; i+=run; pos = zigzag_direct[i&0x3f]; coeff = (level * qscale * iqmatrixptr[pos]) >> 3 ; if (level < 0) { coeff += (1 - (coeff & 1)); } else { coeff -= (1 - (coeff & 1)); } coeff <<= lmmx; reconptr[pos] = coeff; coeffCount++; } mpegVideoStream->flushBitsDirect(2); goto end; } else { /* non-intra-coded macroblock */ decodeDCTCoeff(dct_coeff_first,run,level); i = run; pos = zigzag_direct[i&0x3f]; /* quantizes and oddifies each coefficient */ if (level < 0) { coeff = ((level - 1) * qscale * niqmatrixptr[pos]) >>3; if ((coeff & 1) == 0) {coeff++;} } else { coeff = ((level + 1) * qscale * niqmatrixptr[pos]) >>3; coeff = (coeff-1) | 1; } coeff <<= lmmx; reconptr[pos] = coeff; coeffCount = (coeff!=0); // we never have d_type pictures here, we do not support them while(1) { decodeDCTCoeff(dct_coeff_next,run,level); if (run >= END_OF_BLOCK) { break; } i++; i+=run; pos = zigzag_direct[i&0x3f]; if (level < 0) { coeff = ((level - 1) * qscale * niqmatrixptr[pos]) >>3; if ((coeff & 1) == 0) {coeff++;} } else { coeff = ((level + 1) * qscale * niqmatrixptr[pos]) >> 3; coeff = (coeff-1) | 1; } coeff <<= lmmx; reconptr[pos] = coeff; coeffCount++; } /* end while */ mpegVideoStream->flushBitsDirect(2); goto end; } end: if (coeffCount == 1) { if (lmmx) { emms(); reconptr[pos]>>=lmmx; j_rev_dct_sparse (reconptr, pos); //IDCT_mmx(reconptr); } else { j_rev_dct_sparse (reconptr, pos); } } else { if (lmmx) { IDCT_mmx(reconptr); } else { j_rev_dct(reconptr); } } } // we call this at the edn of the "critical sections" /* if (lmmx) { emms(); } */ return; } void DecoderClass::print() { int i; for(i=0;i<64;i++) { printf(" %d ",zigzag_direct[i]); } printf("\n"); }