--- mbcoding.c 2002/09/08 14:43:04 1.26 +++ mbcoding.c 2002/09/22 17:01:36 1.32 @@ -1,7 +1,7 @@ /***************************************************************************** * * XVID MPEG-4 VIDEO CODEC - * - Vector Length Coding tables - + * - Macro Block coding functions - * * Copyright(C) 2002 Michael Militzer * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: mbcoding.c,v 1.26 2002/09/08 14:43:04 edgomez Exp $ + * $Id: mbcoding.c,v 1.32 2002/09/22 17:01:36 edgomez Exp $ * ****************************************************************************/ @@ -49,14 +49,15 @@ * Local data ****************************************************************************/ -static VLC intra_table[524032]; -static VLC inter_table[524032]; +/* msvc sp5+pp gets confused if they globals are made static */ +VLC intra_table[524032]; +VLC inter_table[524032]; static VLC DCT3Dintra[4096]; static VLC DCT3Dinter[4096]; /***************************************************************************** - * Functions + * Vector Length Coding Initialization ****************************************************************************/ void @@ -65,7 +66,7 @@ int32_t k, l, i, intra, last; VLC *vlc[2]; - VLC **coeff_ptr; + VLC const **coeff_ptr; VLC *vlc1, *vlc2; vlc1 = DCT3Dintra; @@ -86,8 +87,8 @@ coeff_ptr = coeff_vlc[last + 2 * intra]; for (k = -2047; k < 2048; k++) { // level - int8_t *max_level_ptr = max_level[last + 2 * intra]; - int8_t *max_run_ptr = max_run[last + 2 * intra]; + int8_t const *max_level_ptr = max_level[last + 2 * intra]; + int8_t const *max_run_ptr = max_run[last + 2 * intra]; for (l = 0; l < 64; l++) { // run int32_t level = k; @@ -180,6 +181,10 @@ } +/***************************************************************************** + * Local inlined functions for MB coding + ****************************************************************************/ + static __inline void CodeVector(Bitstream * bs, int32_t value, @@ -235,7 +240,6 @@ } - static __inline void CodeCoeff(Bitstream * bs, const int16_t qcoeff[64], @@ -274,6 +278,9 @@ } +/***************************************************************************** + * Local functions + ****************************************************************************/ static void CodeBlockIntra(const FRAMEINFO * frame, @@ -367,13 +374,13 @@ if (frame->global_flags & XVID_INTERLACING) { if (pMB->cbp) { BitstreamPutBit(bs, pMB->field_dct); - DEBUG1("codep: field_dct: ", pMB->field_dct); + DPRINTF(DPRINTF_DEBUG, "codep: field_dct: %d", pMB->field_dct); } // if inter block, write field ME flag if (pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q) { BitstreamPutBit(bs, pMB->field_pred); - DEBUG1("codep: field_pred: ", pMB->field_pred); + DPRINTF(DPRINTF_DEBUG, "codep: field_pred: %d", pMB->field_pred); // write field prediction references if (pMB->field_pred) { @@ -400,6 +407,9 @@ } +/***************************************************************************** + * Macro Block bitstream encoding functions + ****************************************************************************/ void MBCoding(const FRAMEINFO * frame, @@ -428,155 +438,17 @@ return; } - -/*************************************************************** - * bframe encoding start - ***************************************************************/ - -/* - mbtype - 0 1b direct(h263) mvdb - 1 01b interpolate mc+q dbquant, mvdf, mvdb - 2 001b backward mc+q dbquant, mvdb - 3 0001b forward mc+q dbquant, mvdf -*/ - -void -put_bvop_mbtype(Bitstream * bs, - int value) -{ - switch (value) { - case 0: - BitstreamPutBit(bs, 1); - return; - - case 1: - BitstreamPutBit(bs, 0); - BitstreamPutBit(bs, 1); - return; - - case 2: - BitstreamPutBit(bs, 0); - BitstreamPutBit(bs, 0); - BitstreamPutBit(bs, 1); - return; - - case 3: - BitstreamPutBit(bs, 0); - BitstreamPutBit(bs, 0); - BitstreamPutBit(bs, 0); - BitstreamPutBit(bs, 1); - return; - - default:; // invalid! - - } - -} +/***************************************************************************** + * decoding stuff starts here + ****************************************************************************/ /* - dbquant - -2 10b - 0 0b - +2 11b -*/ - -void -put_bvop_dbquant(Bitstream * bs, - int value) -{ - switch (value) { - case 0: - BitstreamPutBit(bs, 0); - return; - - case -2: - BitstreamPutBit(bs, 1); - BitstreamPutBit(bs, 0); - return; - - case 2: - BitstreamPutBit(bs, 1); - BitstreamPutBit(bs, 1); - return; - - default:; // invalid - } -} - - - -void -MBCodingBVOP(const MACROBLOCK * mb, - const int16_t qcoeff[6 * 64], - const int32_t fcode, - const int32_t bcode, - Bitstream * bs, - Statistics * pStat) -{ - int i; - -/* ------------------------------------------------------------------ - when a block is skipped it is decoded DIRECT(0,0) - hence is interpolated from forward & backward frames - ------------------------------------------------------------------ */ - - if (mb->mode == MODE_DIRECT_NONE_MV) { - BitstreamPutBit(bs, 1); // skipped - return; - } - - BitstreamPutBit(bs, 0); // not skipped - - if (mb->cbp == 0) { - BitstreamPutBit(bs, 1); // cbp == 0 - } else { - BitstreamPutBit(bs, 0); // cbp == xxx - } - - put_bvop_mbtype(bs, mb->mode); - - if (mb->cbp) { - BitstreamPutBits(bs, mb->cbp, 6); - } - - if (mb->mode != MODE_DIRECT && mb->cbp != 0) { - put_bvop_dbquant(bs, 0); // todo: mb->dquant = 0 - } - - if (mb->mode == MODE_INTERPOLATE || mb->mode == MODE_FORWARD) { - CodeVector(bs, mb->pmvs[0].x, fcode, pStat); - CodeVector(bs, mb->pmvs[0].y, fcode, pStat); - } + * For IVOP addbits == 0 + * For PVOP addbits == fcode - 1 + * For BVOP addbits == max(fcode,bcode) - 1 + * returns true or false + */ - if (mb->mode == MODE_INTERPOLATE || mb->mode == MODE_BACKWARD) { - CodeVector(bs, mb->b_pmvs[0].x, bcode, pStat); - CodeVector(bs, mb->b_pmvs[0].y, bcode, pStat); - } - - if (mb->mode == MODE_DIRECT) { - CodeVector(bs, mb->deltamv.x, 1, pStat); /* fcode is always 1 for delta vector */ - CodeVector(bs, mb->deltamv.y, 1, pStat); /* prediction is always (0,0) */ - } - - for (i = 0; i < 6; i++) { - if (mb->cbp & (1 << (5 - i))) { - CodeCoeff(bs, &qcoeff[i * 64], inter_table, scan_tables[0], 0); - } - } -} - - - -/*************************************************************** - * decoding stuff starts here * - ***************************************************************/ - - -// for IVOP addbits == 0 -// for PVOP addbits == fcode - 1 -// for BVOP addbits == max(fcode,bcode) - 1 -// returns true or false int check_resync_marker(Bitstream * bs, int addbits) { @@ -753,6 +625,105 @@ } +/***************************************************************************** + * Local inlined function to "decode" written vlc codes + ****************************************************************************/ + +static __inline int +get_coeff(Bitstream * bs, + int *run, + int *last, + int intra, + int short_video_header) +{ + + uint32_t mode; + const VLC *tab; + int32_t level; + + if (short_video_header) // inter-VLCs will be used for both intra and inter blocks + intra = 0; + + tab = &DCT3D[intra][BitstreamShowBits(bs, 12)]; + + if (tab->code == -1) + goto error; + + BitstreamSkip(bs, tab->len); + + if (tab->code != ESCAPE) { + if (!intra) { + *run = (tab->code >> 4) & 255; + level = tab->code & 15; + *last = (tab->code >> 12) & 1; + } else { + *run = (tab->code >> 8) & 255; + level = tab->code & 255; + *last = (tab->code >> 16) & 1; + } + return BitstreamGetBit(bs) ? -level : level; + } + + if (short_video_header) { + // escape mode 4 - H.263 type, only used if short_video_header = 1 + *last = BitstreamGetBit(bs); + *run = BitstreamGetBits(bs, 6); + level = BitstreamGetBits(bs, 8); + + if (level == 0 || level == 128) + DPRINTF(DPRINTF_ERROR, "Illegal LEVEL for ESCAPE mode 4: %d", level); + + return (level >= 128 ? -(256 - level) : level); + } + + mode = BitstreamShowBits(bs, 2); + + if (mode < 3) { + BitstreamSkip(bs, (mode == 2) ? 2 : 1); + + tab = &DCT3D[intra][BitstreamShowBits(bs, 12)]; + if (tab->code == -1) + goto error; + + BitstreamSkip(bs, tab->len); + + if (!intra) { + *run = (tab->code >> 4) & 255; + level = tab->code & 15; + *last = (tab->code >> 12) & 1; + } else { + *run = (tab->code >> 8) & 255; + level = tab->code & 255; + *last = (tab->code >> 16) & 1; + } + + if (mode < 2) // first escape mode, level is offset + level += max_level[*last + (!intra << 1)][*run]; // need to add back the max level + else if (mode == 2) // second escape mode, run is offset + *run += max_run[*last + (!intra << 1)][level] + 1; + + return BitstreamGetBit(bs) ? -level : level; + } + // third escape mode - fixed length codes + BitstreamSkip(bs, 2); + *last = BitstreamGetBits(bs, 1); + *run = BitstreamGetBits(bs, 6); + BitstreamSkip(bs, 1); // marker + level = BitstreamGetBits(bs, 12); + BitstreamSkip(bs, 1); // marker + + return (level & 0x800) ? (level | (-1 ^ 0xfff)) : level; + + error: + *run = VLC_ERROR; + return 0; + +} + +/***************************************************************************** + * MB reading functions + ****************************************************************************/ + void get_intra_block(Bitstream * bs, int16_t * block, @@ -768,7 +739,7 @@ do { level = get_coeff(bs, &run, &last, 1, 0); if (run == -1) { - DEBUG("fatal: invalid run"); + DPRINTF(DPRINTF_DEBUG, "fatal: invalid run"); break; } coeff += run; @@ -778,7 +749,7 @@ //DPRINTF(DPRINTF_COEFF,"block[%i] %i %08x", scan[coeff], level, BitstreamShowBits(bs, 32)); if (level < -127 || level > 127) { - DEBUG1("warning: intra_overflow", level); + DPRINTF(DPRINTF_DEBUG, "warning: intra_overflow: %d", level); } coeff++; } while (!last); @@ -800,7 +771,7 @@ do { level = get_coeff(bs, &run, &last, 0, 0); if (run == -1) { - DEBUG("fatal: invalid run"); + DPRINTF(DPRINTF_ERROR, "fatal: invalid run"); break; } p += run; @@ -808,10 +779,9 @@ block[scan[p]] = level; DPRINTF(DPRINTF_COEFF,"block[%i] %i", scan[p], level); - // DPRINTF(DPRINTF_COEFF,"block[%i] %i %08x", scan[p], level, BitstreamShowBits(bs, 32)); if (level < -127 || level > 127) { - DEBUG1("warning: inter_overflow", level); + DPRINTF(DPRINTF_DEBUG, "warning: inter_overflow: %d", level); } p++; } while (!last);