[XviD-devel] VLC Table could not understand...........the implementation.

Marco Al xvid-devel@xvid.org
Mon, 6 Jan 2003 11:45:57 +0100


This is a multi-part message in MIME format.

------=_NextPart_000_000C_01C2B579.2D833900
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Amit Bhushan wrote:

> Why there are different tables for encoder and decoder?

VLCs are uniquely decodable, but there are multiple ways to match them ... you
can do the traditional bit by bit matching, traversing the set of VLCs in a
binary tree like manner, but while that might be suited for hardware
implementation it is not terribly efficient on a general purpose processor.
Since the largest VLC (ignoring esc1/2 codes) is only 12 bits we can do it
smarter by using a lookup table from all possible 12 bit words in the bitstream
to their corresponding events and VLC lengths.

This is different from the encoder since the codes shorter than 12 bits occur
multiple times in the table, because they can be followed by arbitrary bits in
the encoded bitstream.

> Can the VLC Table be implemented using Huffman algorith?

I havent seen a list of probabilities, but I guess you could reverse engineer
them.

> If yes, then
> which will be simpler?

Using the existing VLCs.

> Why are 2-d array variables max_level[][] &
> max_run[][] are common for for both encoder & decoder?

Escape1/2 coding provides a translation of a given event to a different event,
this operation can be reversed using the same table ... hence they are used both
in decoding and encoding.

Or rather max_level/run are used when building the lut for encoding, which when
using the small lut is meant to hold all standard VLCs and the ones for
escape1/2 coding. Even with the small lut only the fixed length escape3 codes
are computed instead of looked up ... again because we are using a general
purpose CPU. In hardware you would probably use computations to compute
escape1/2 coding to save on the lut space.

> Can you please
> elaborate the implementation of vlc_codes.h and implementation .i.e init of
> it in mbcoding.c?

It is very simple, the code traverses the copy pasted VLC tables from the ISO
standard as is ... and seeds the lut with them. This will take care of all the
standard VLCs. For codes which remain after this it will first try if there is
an escape1 code, and if they exist put them in the lut. If that doesnt succeed
it tries an escape2 code.

Remaining entries after this are either filled with escape3 codes, or left open
in the case of intra coding with the small lut. This is done since for intra we
only do the lookup for the positive range of levels, and escape3 codes arent as
easy to negate as the VLCs (which just require setting the LSB). So instead we
will just compute them explicitly when we need them.

For all levels which lie beyond the range of -31 - 31 in the case of inter
and -64 - 64 in the case of intra escape3 codes are computed on the fly when
encoding with the small lut.

With the big lut all codes for all possible events can be directly looked up.

A more readable mbcoding.c is attached.

Marco

------=_NextPart_000_000C_01C2B579.2D833900
Content-Type: text/plain;
	name="mbcoding.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="mbcoding.c"

/************************************************************************=
*****
 *
 *  XVID MPEG-4 VIDEO CODEC
 *  - Macro Block coding functions -
 *
 *  Copyright(C) 2002 Michael Militzer <isibaar@xvid.org>
 *
 *  This file is part of XviD, a free MPEG-4 video encoder/decoder
 *
 *  XviD 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.
 *
 *  This program 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
 *
 *  Under section 8 of the GNU General Public License, the copyright
 *  holders of XVID explicitly forbid distribution in the following
 *  countries:
 *
 *    - Japan
 *    - United States of America
 *
 *  Linking XviD statically or dynamically with other modules is making =
a
 *  combined work based on XviD.  Thus, the terms and conditions of the
 *  GNU General Public License cover the whole combination.
 *
 *  As a special exception, the copyright holders of XviD give you
 *  permission to link XviD with independent modules that communicate =
with
 *  XviD solely through the VFW1.1 and DShow interfaces, regardless of =
the
 *  license terms of these independent modules, and to copy and =
distribute
 *  the resulting combined work under terms of your choice, provided =
that
 *  every copy of the combined work is accompanied by a complete copy of
 *  the source code of XviD (the version of XviD used to produce the
 *  combined work), being distributed under the terms of the GNU General
 *  Public License plus this exception.  An independent module is a =
module
 *  which is not derived from or based on XviD.
 *
 *  Note that people who make modified versions of XviD are not =
obligated
 *  to grant this special exception for their modified versions; it is
 *  their choice whether to do so.  The GNU General Public License gives
 *  permission to release a modified version without this exception; =
this
 *  exception also makes it possible to release a modified version which
 *  carries forward this exception.
 *
 * $Id: mbcoding.c,v 1.37 2003/01/05 16:54:36 edgomez Exp $
 *
 =
*************************************************************************=
***/

#include <stdlib.h>
#include "../portab.h"
#include "bitstream.h"
#include "zigzag.h"
#include "vlc_codes.h"
#include "mbcoding.h"

#include "../utils/mbfunctions.h"

#define ABS(X) (((X)>0)?(X):-(X))
#define CLIP(X,A) (X > A) ? (A) : (X)

/*#define _BIGLUT_*/

#ifdef _BIGLUT_
#define LEVELOFFSET 2048
#else
#define LEVELOFFSET 32
#endif

/************************************************************************=
*****
 * Local data
 =
*************************************************************************=
***/

static REVERSE_EVENT DCT3D[2][4096];

#ifdef _BIGLUT_
static VLC coeff_VLC[2][2][4096][64];
static VLC *intra_table, *inter_table;=20
#else
static VLC coeff_VLC[2][2][64][64];
#endif

/************************************************************************=
*****
 * Vector Length Coding Initialization
 =
*************************************************************************=
***/

void
init_vlc_tables(void)
{
	uint32_t i, j, intra, last, run, level_esc, run_esc, offset;
	int32_t level;

#ifdef _BIGLUT_
	intra_table =3D coeff_VLC[1];
	inter_table =3D coeff_VLC[0];=20
#endif


	for (intra =3D 0; intra < 2; intra++)
		for (i =3D 0; i < 4096; i++)
			DCT3D[intra][i].event.level =3D 0;

	for (intra =3D 0; intra < 2; intra++)
		for (last =3D 0; last < 2; last++)
		{
			for (run =3D 0; run < 63 + last; run++)
				for (level =3D 0; level < 32 << intra; level++)
				{
#ifdef _BIGLUT_
					offset =3D LEVELOFFSET;
#else
					offset =3D !intra * LEVELOFFSET;
#endif
					coeff_VLC[intra][last][level + offset][run].len =3D 128;
				}
		}

	for (intra =3D 0; intra < 2; intra++)
		for (i =3D 0; i < 102; i++)
		{
#ifdef _BIGLUT_
			offset =3D LEVELOFFSET;
#else
			offset =3D !intra * LEVELOFFSET;
#endif
			for (j =3D 0; j < 1 << (12 - coeff_tab[intra][i].vlc.len); j++)
			{
				DCT3D[intra][(coeff_tab[intra][i].vlc.code << (12 - =
coeff_tab[intra][i].vlc.len)) | j].len	 =3D coeff_tab[intra][i].vlc.len;
				DCT3D[intra][(coeff_tab[intra][i].vlc.code << (12 - =
coeff_tab[intra][i].vlc.len)) | j].event =3D coeff_tab[intra][i].event;
			}

			=
coeff_VLC[intra][coeff_tab[intra][i].event.last][coeff_tab[intra][i].even=
t.level + offset][coeff_tab[intra][i].event.run].code
				=3D coeff_tab[intra][i].vlc.code << 1;
			=
coeff_VLC[intra][coeff_tab[intra][i].event.last][coeff_tab[intra][i].even=
t.level + offset][coeff_tab[intra][i].event.run].len
				=3D coeff_tab[intra][i].vlc.len + 1;
#ifndef _BIGLUT_
			if (!intra)
#endif
			{
				coeff_VLC[intra][coeff_tab[intra][i].event.last][offset - =
coeff_tab[intra][i].event.level][coeff_tab[intra][i].event.run].code
					=3D (coeff_tab[intra][i].vlc.code << 1) | 1;
				coeff_VLC[intra][coeff_tab[intra][i].event.last][offset - =
coeff_tab[intra][i].event.level][coeff_tab[intra][i].event.run].len
					=3D coeff_tab[intra][i].vlc.len + 1;
			}
		}

	for (intra =3D 0; intra < 2; intra++)
		for (last =3D 0; last < 2; last++)
			for (run =3D 0; run < 63 + last; run++)
			{
				for (level =3D 1; level < 32 << intra; level++)
				{
					if (level <=3D max_level[intra][last][run] && run <=3D =
max_run[intra][last][level])
					    continue;
#ifdef _BIGLUT_
					offset =3D LEVELOFFSET;
#else
					offset =3D !intra * LEVELOFFSET;
#endif
                    level_esc =3D level - max_level[intra][last][run];
					if (level_esc <=3D max_level[intra][last][run] && run <=3D =
max_run[intra][last][level_esc])
					{
						coeff_VLC[intra][last][level + offset][run].code
							=3D (ESCAPE1 << coeff_VLC[intra][last][level_esc + =
offset][run].len)
							|  coeff_VLC[intra][last][level_esc + offset][run].code;
						coeff_VLC[intra][last][level + offset][run].len
							=3D coeff_VLC[intra][last][level_esc + offset][run].len + 7 + 1;
#ifndef _BIGLUT_
    					if (!intra)
#endif
	    				{
		    				coeff_VLC[intra][last][offset - level][run].code
			    				=3D (ESCAPE1 << coeff_VLC[intra][last][level_esc + =
offset][run].len)
				    			|  coeff_VLC[intra][last][level_esc + offset][run].code | 1;
					    	coeff_VLC[intra][last][offset - level][run].len
						    	=3D coeff_VLC[intra][last][level_esc + offset][run].len + 7 + =
1;
					    }
					    continue;
					}
				=09
					run_esc =3D run - 1 - max_run[intra][last][level];
					if (level <=3D max_level[intra][last][run_esc] && run_esc <=3D =
max_run[intra][last][level])
					/*remove the above continue and use the lower test instead to use =
shorter escape codes when possible :
					if (coeff_VLC[intra][last][level + offset][run_esc].len + 7 + 2
						< coeff_VLC[intra][last][level + offset][run].len)*/
					{
						coeff_VLC[intra][last][level + offset][run].code
							=3D (ESCAPE2 << coeff_VLC[intra][last][level + =
offset][run_esc].len)
							|  coeff_VLC[intra][last][level + offset][run_esc].code;
						coeff_VLC[intra][last][level + offset][run].len
							=3D coeff_VLC[intra][last][level + offset][run_esc].len + 7 + 2;
#ifndef _BIGLUT_
						if (!intra)
#endif
						{
							coeff_VLC[intra][last][offset - level][run].code
								=3D (ESCAPE2 << coeff_VLC[intra][last][level + =
offset][run_esc].len)
								|  coeff_VLC[intra][last][level + offset][run_esc].code | 1;
							coeff_VLC[intra][last][offset - level][run].len
								=3D coeff_VLC[intra][last][level + offset][run_esc].len + 7 + 2;
						}
						continue;
					}
#ifndef _BIGLUT_
					if (!intra)
#endif
						if (coeff_VLC[intra][last][level + offset][run].len =3D=3D 128)
						{
							coeff_VLC[intra][last][level + offset][run].code
								=3D (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | =
((level & 0xfff) << 1) | 1;
							coeff_VLC[intra][last][level + offset][run].len =3D 30;

							coeff_VLC[intra][last][offset - level][run].code
								=3D (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | =
((-level & 0xfff) << 1) | 1;
							coeff_VLC[intra][last][offset - level][run].len =3D 30;
						}
				}
#ifdef _BIGLUT_
				for (level =3D 32 << intra; level < 2048; level++)
				{
					coeff_VLC[intra][last][level + offset][run].code
						=3D (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | =
((level & 0xfff) << 1) | 1;
					coeff_VLC[intra][last][level + offset][run].len =3D 30;

					coeff_VLC[intra][last][offset - level][run].code
						=3D (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | =
((-level & 0xfff) << 1) | 1;
					coeff_VLC[intra][last][offset - level][run].len =3D 30;
				}
#else
				if (!intra)
				{
					coeff_VLC[intra][last][0][run].code
						=3D (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | =
((-32 & 0xfff) << 1) | 1;
					coeff_VLC[intra][last][0][run].len =3D 30;
				}
#endif
			}
}

/************************************************************************=
*****
 * Local inlined functions for MB coding
 =
*************************************************************************=
***/

static __inline void
CodeVector(Bitstream * bs,
		   int32_t value,
		   int32_t f_code,
		   Statistics * pStat)
{

	const int scale_factor =3D 1 << (f_code - 1);
	const int cmp =3D scale_factor << 5;

	if (value < (-1 * cmp))
		value +=3D 64 * scale_factor;

	if (value > (cmp - 1))
		value -=3D 64 * scale_factor;

	pStat->iMvSum +=3D value * value;
	pStat->iMvCount++;

	if (value =3D=3D 0) {
		BitstreamPutBits(bs, mb_motion_table[32].code,
						 mb_motion_table[32].len);
	} else {
		uint16_t length, code, mv_res, sign;

		length =3D 16 << f_code;
		f_code--;

		sign =3D (value < 0);

		if (value >=3D length)
			value -=3D 2 * length;
		else if (value < -length)
			value +=3D 2 * length;

		if (sign)
			value =3D -value;

		value--;
		mv_res =3D value & ((1 << f_code) - 1);
		code =3D ((value - mv_res) >> f_code) + 1;

		if (sign)
			code =3D -code;

		code +=3D 32;
		BitstreamPutBits(bs, mb_motion_table[code].code,
						 mb_motion_table[code].len);

		if (f_code)
			BitstreamPutBits(bs, mv_res, f_code);
	}

}

#ifdef __BIGLUT_

static __inline void
CodeCoeff(Bitstream * bs,
		  const int16_t qcoeff[64],
		  VLC * table,
		  const uint16_t * zigzag,
		  uint16_t intra)
{

	uint32_t j, last;
	short v;
	VLC *vlc;

	j =3D intra;
	last =3D intra;

	while (j < 64 && (v =3D qcoeff[zigzag[j]]) =3D=3D 0)
		j++;

	do {
		vlc =3D table + 64 * 2048 + (v << 6) + j - last;
		last =3D ++j;

		/* count zeroes */
		while (j < 64 && (v =3D qcoeff[zigzag[j]]) =3D=3D 0)
			j++;

		/* write code */
		if (j !=3D 64) {
			BitstreamPutBits(bs, vlc->code, vlc->len);
		} else {
			vlc +=3D 64 * 4096;
			BitstreamPutBits(bs, vlc->code, vlc->len);
			break;
		}
	} while (1);

}

#else

static __inline void
CodeCoeffInter(Bitstream * bs,
		  const int16_t qcoeff[64],
		  const uint16_t * zigzag)
{
	uint32_t i, run, prev_run, code, len;
	int32_t level, prev_level, level_shifted;

	i	=3D 0;
	run =3D 0;

	while (!(level =3D qcoeff[zigzag[i++]]))
		run++;

	prev_level =3D level;
	prev_run   =3D run;
	run =3D 0;

	while (i < 64)
	{
		if ((level =3D qcoeff[zigzag[i++]]) !=3D 0)
		{
			level_shifted =3D prev_level + 32;
			if (!(level_shifted & -64))
			{
				code =3D coeff_VLC[0][0][level_shifted][prev_run].code;
				len	 =3D coeff_VLC[0][0][level_shifted][prev_run].len;
			}
			else
			{
				code =3D (ESCAPE3 << 21) | (prev_run << 14) | (1 << 13) | =
((prev_level & 0xfff) << 1) | 1;
				len  =3D 30;
			}
			BitstreamPutBits(bs, code, len);
			prev_level =3D level;
			prev_run   =3D run;
			run =3D 0;
		}
		else
			run++;
	}

	level_shifted =3D prev_level + 32;
	if (!(level_shifted & -64))
	{
		code =3D coeff_VLC[0][1][level_shifted][prev_run].code;
		len	 =3D coeff_VLC[0][1][level_shifted][prev_run].len;
	}
	else
	{
		code =3D (ESCAPE3 << 21) | (1 << 20) | (prev_run << 14) | (1 << 13) | =
((prev_level & 0xfff) << 1) | 1;
		len  =3D 30;
	}
	BitstreamPutBits(bs, code, len);
}

static __inline void
CodeCoeffIntra(Bitstream * bs,
		  const int16_t qcoeff[64],
		  const uint16_t * zigzag)
{
	uint32_t i, abs_level, run, prev_run, code, len;
	int32_t level, prev_level;

	i	=3D 1;
	run =3D 0;

	while (!(level =3D qcoeff[zigzag[i++]]))
		run++;

	prev_level =3D level;
	prev_run   =3D run;
	run =3D 0;

	while (i < 64)
	{
		if ((level =3D qcoeff[zigzag[i++]]) !=3D 0)
		{
			abs_level =3D ABS(prev_level);
			abs_level =3D abs_level < 64 ? abs_level : 0;
			code	  =3D coeff_VLC[1][0][abs_level][prev_run].code;
			len		  =3D coeff_VLC[1][0][abs_level][prev_run].len;
			if (len !=3D 128)
				code |=3D (prev_level < 0);
			else
			{
		        code =3D (ESCAPE3 << 21) | (prev_run << 14) | (1 << 13) | =
((prev_level & 0xfff) << 1) | 1;
				len  =3D 30;
			}
			BitstreamPutBits(bs, code, len);
			prev_level =3D level;
			prev_run   =3D run;
			run =3D 0;
		}
		else
			run++;
	}

	abs_level =3D ABS(prev_level);
	abs_level =3D abs_level < 64 ? abs_level : 0;
	code	  =3D coeff_VLC[1][1][abs_level][prev_run].code;
	len		  =3D coeff_VLC[1][1][abs_level][prev_run].len;
	if (len !=3D 128)
		code |=3D (prev_level < 0);
	else
	{
		code =3D (ESCAPE3 << 21) | (1 << 20) | (prev_run << 14) | (1 << 13) | =
((prev_level & 0xfff) << 1) | 1;
		len  =3D 30;
	}
	BitstreamPutBits(bs, code, len);
}

#endif

/************************************************************************=
*****
 * Local functions
 =
*************************************************************************=
***/

static void
CodeBlockIntra(const FRAMEINFO * frame,
			   const MACROBLOCK * pMB,
			   int16_t qcoeff[6 * 64],
			   Bitstream * bs,
			   Statistics * pStat)
{

	uint32_t i, mcbpc, cbpy, bits;

	cbpy =3D pMB->cbp >> 2;

	/* write mcbpc */
	if (frame->coding_type =3D=3D I_VOP) {
		mcbpc =3D ((pMB->mode >> 1) & 3) | ((pMB->cbp & 3) << 2);
		BitstreamPutBits(bs, mcbpc_intra_tab[mcbpc].code,
						 mcbpc_intra_tab[mcbpc].len);
	} else {
		mcbpc =3D (pMB->mode & 7) | ((pMB->cbp & 3) << 3);
		BitstreamPutBits(bs, mcbpc_inter_tab[mcbpc].code,
						 mcbpc_inter_tab[mcbpc].len);
	}

	/* ac prediction flag */
	if (pMB->acpred_directions[0])
		BitstreamPutBits(bs, 1, 1);
	else
		BitstreamPutBits(bs, 0, 1);

	/* write cbpy */
	BitstreamPutBits(bs, cbpy_tab[cbpy].code, cbpy_tab[cbpy].len);

	/* write dquant */
	if (pMB->mode =3D=3D MODE_INTRA_Q)
		BitstreamPutBits(bs, pMB->dquant, 2);

	/* write interlacing */
	if (frame->global_flags & XVID_INTERLACING) {
		BitstreamPutBit(bs, pMB->field_dct);
	}
	/* code block coeffs */
	for (i =3D 0; i < 6; i++) {
		if (i < 4)
			BitstreamPutBits(bs, dcy_tab[qcoeff[i * 64 + 0] + 255].code,
							 dcy_tab[qcoeff[i * 64 + 0] + 255].len);
		else
			BitstreamPutBits(bs, dcc_tab[qcoeff[i * 64 + 0] + 255].code,
							 dcc_tab[qcoeff[i * 64 + 0] + 255].len);

		if (pMB->cbp & (1 << (5 - i))) {
			bits =3D BitstreamPos(bs);

#ifdef _BIGLUT_
			CodeCoeff(bs, &qcoeff[i * 64], intra_table,
					  scan_tables[pMB->acpred_directions[i]], 1);
#else
			CodeCoeffIntra(bs, &qcoeff[i * 64], =
scan_tables[pMB->acpred_directions[i]]);
#endif
			bits =3D BitstreamPos(bs) - bits;
			pStat->iTextBits +=3D bits;
		}
	}

}


static void
CodeBlockInter(const FRAMEINFO * frame,
			   const MACROBLOCK * pMB,
			   int16_t qcoeff[6 * 64],
			   Bitstream * bs,
			   Statistics * pStat)
{

	int32_t i;
	uint32_t bits, mcbpc, cbpy;

	mcbpc =3D (pMB->mode & 7) | ((pMB->cbp & 3) << 3);
	cbpy =3D 15 - (pMB->cbp >> 2);

	/* write mcbpc */
	BitstreamPutBits(bs, mcbpc_inter_tab[mcbpc].code,
					 mcbpc_inter_tab[mcbpc].len);

	/* write cbpy */
	BitstreamPutBits(bs, cbpy_tab[cbpy].code, cbpy_tab[cbpy].len);

	/* write dquant */
	if (pMB->mode =3D=3D MODE_INTER_Q)
		BitstreamPutBits(bs, pMB->dquant, 2);

	/* interlacing */
	if (frame->global_flags & XVID_INTERLACING) {
		if (pMB->cbp) {
			BitstreamPutBit(bs, pMB->field_dct);
			DPRINTF(DPRINTF_DEBUG, "codep: field_dct: %d", pMB->field_dct);
		}

		/* if inter block, write field ME flag */
		if (pMB->mode =3D=3D MODE_INTER || pMB->mode =3D=3D MODE_INTER_Q) {
			BitstreamPutBit(bs, pMB->field_pred);
			DPRINTF(DPRINTF_DEBUG, "codep: field_pred: %d", pMB->field_pred);

			/* write field prediction references */
			if (pMB->field_pred) {
				BitstreamPutBit(bs, pMB->field_for_top);
				BitstreamPutBit(bs, pMB->field_for_bot);
			}
		}
	}
	/* code motion vector(s) */
	for (i =3D 0; i < (pMB->mode =3D=3D MODE_INTER4V ? 4 : 1); i++) {
		CodeVector(bs, pMB->pmvs[i].x, frame->fcode, pStat);
		CodeVector(bs, pMB->pmvs[i].y, frame->fcode, pStat);
	}

	bits =3D BitstreamPos(bs);

	/* code block coeffs */
	for (i =3D 0; i < 6; i++)
		if (pMB->cbp & (1 << (5 - i)))
#ifdef _BIGLUT_
			CodeCoeff(bs, &qcoeff[i * 64], inter_table, scan_tables[0], 0);
#else
			CodeCoeffInter(bs, &qcoeff[i * 64], scan_tables[0]);
#endif

	bits =3D BitstreamPos(bs) - bits;
	pStat->iTextBits +=3D bits;

}

/************************************************************************=
*****
 * Macro Block bitstream encoding functions
 =
*************************************************************************=
***/

void
MBCoding(const FRAMEINFO * frame,
		 MACROBLOCK * pMB,
		 int16_t qcoeff[6 * 64],
		 Bitstream * bs,
		 Statistics * pStat)
{

	if (frame->coding_type =3D=3D P_VOP) {
			BitstreamPutBit(bs, 0);	/* coded */
	}

	if (pMB->mode =3D=3D MODE_INTRA || pMB->mode =3D=3D MODE_INTRA_Q)
		CodeBlockIntra(frame, pMB, qcoeff, bs, pStat);
	else
		CodeBlockInter(frame, pMB, qcoeff, bs, pStat);

}


void
MBSkip(Bitstream * bs)
{
	BitstreamPutBit(bs, 1);	/* not coded */
	return;
}

/************************************************************************=
*****
 * decoding stuff starts here
 =
*************************************************************************=
***/

/*
 * For IVOP addbits =3D=3D 0
 * For PVOP addbits =3D=3D fcode - 1
 * For BVOP addbits =3D=3D max(fcode,bcode) - 1
 * returns true or false
 */

int=20
check_resync_marker(Bitstream * bs, int addbits)
{
	uint32_t nbits;
	uint32_t code;
	uint32_t nbitsresyncmarker =3D NUMBITS_VP_RESYNC_MARKER + addbits;

	nbits =3D BitstreamNumBitsToByteAlign(bs);
	code =3D BitstreamShowBits(bs, nbits);

	if (code =3D=3D (((uint32_t)1 << (nbits - 1)) - 1))
	{
		return BitstreamShowBitsFromByteAlign(bs, nbitsresyncmarker) =3D=3D =
RESYNC_MARKER;
	}

	return 0;
}



int
get_mcbpc_intra(Bitstream * bs)
{

	uint32_t index;

	index =3D BitstreamShowBits(bs, 9);
	index >>=3D 3;

	BitstreamSkip(bs, mcbpc_intra_table[index].len);

	return mcbpc_intra_table[index].code;

}

int
get_mcbpc_inter(Bitstream * bs)
{

	uint32_t index;
=09
	index =3D CLIP(BitstreamShowBits(bs, 9), 256);

	BitstreamSkip(bs, mcbpc_inter_table[index].len);

	return mcbpc_inter_table[index].code;

}

int
get_cbpy(Bitstream * bs,
		 int intra)
{

	int cbpy;
	uint32_t index =3D BitstreamShowBits(bs, 6);

	BitstreamSkip(bs, cbpy_table[index].len);
	cbpy =3D cbpy_table[index].code;

	if (!intra)
		cbpy =3D 15 - cbpy;

	return cbpy;

}

int
get_mv_data(Bitstream * bs)
{

	uint32_t index;

	if (BitstreamGetBit(bs))
		return 0;

	index =3D BitstreamShowBits(bs, 12);

	if (index >=3D 512) {
		index =3D (index >> 8) - 2;
		BitstreamSkip(bs, TMNMVtab0[index].len);
		return TMNMVtab0[index].code;
	}

	if (index >=3D 128) {
		index =3D (index >> 2) - 32;
		BitstreamSkip(bs, TMNMVtab1[index].len);
		return TMNMVtab1[index].code;
	}

	index -=3D 4;

	BitstreamSkip(bs, TMNMVtab2[index].len);
	return TMNMVtab2[index].code;

}

int
get_mv(Bitstream * bs,
	   int fcode)
{

	int data;
	int res;
	int mv;
	int scale_fac =3D 1 << (fcode - 1);

	data =3D get_mv_data(bs);

	if (scale_fac =3D=3D 1 || data =3D=3D 0)
		return data;

	res =3D BitstreamGetBits(bs, fcode - 1);
	mv =3D ((ABS(data) - 1) * scale_fac) + res + 1;

	return data < 0 ? -mv : mv;

}

int
get_dc_dif(Bitstream * bs,
		   uint32_t dc_size)
{

	int code =3D BitstreamGetBits(bs, dc_size);
	int msb =3D code >> (dc_size - 1);

	if (msb =3D=3D 0)
		return (-1 * (code ^ ((1 << dc_size) - 1)));

	return code;

}

int
get_dc_size_lum(Bitstream * bs)
{

	int code, i;

	code =3D BitstreamShowBits(bs, 11);

	for (i =3D 11; i > 3; i--) {
		if (code =3D=3D 1) {
			BitstreamSkip(bs, i);
			return i + 1;
		}
		code >>=3D 1;
	}

	BitstreamSkip(bs, dc_lum_tab[code].len);
	return dc_lum_tab[code].code;

}


int
get_dc_size_chrom(Bitstream * bs)
{

	uint32_t code, i;

	code =3D BitstreamShowBits(bs, 12);

	for (i =3D 12; i > 2; i--) {
		if (code =3D=3D 1) {
			BitstreamSkip(bs, i);
			return i;
		}
		code >>=3D 1;
	}

	return 3 - BitstreamGetBits(bs, 2);

}

/************************************************************************=
*****
 * 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;
	int32_t level;
	REVERSE_EVENT *reverse_event;

	if (short_video_header)		/* inter-VLCs will be used for both intra and =
inter blocks */
		intra =3D 0;

	if (BitstreamShowBits(bs, 7) !=3D ESCAPE) {
		reverse_event =3D &DCT3D[intra][BitstreamShowBits(bs, 12)];

		if ((level =3D reverse_event->event.level) =3D=3D 0)
			goto error;

		*last =3D reverse_event->event.last;
		*run  =3D reverse_event->event.run;

		BitstreamSkip(bs, reverse_event->len);

		return BitstreamGetBits(bs, 1) ? -level : level;
	}

	BitstreamSkip(bs, 7);

	if (short_video_header) {
		/* escape mode 4 - H.263 type, only used if short_video_header =3D 1  =
*/
		*last =3D BitstreamGetBit(bs);
		*run =3D BitstreamGetBits(bs, 6);
		level =3D BitstreamGetBits(bs, 8);

		if (level =3D=3D 0 || level =3D=3D 128)
			DPRINTF(DPRINTF_ERROR, "Illegal LEVEL for ESCAPE mode 4: %d", level);

		return (level << 24) >> 24;
	}

	mode =3D BitstreamShowBits(bs, 2);

	if (mode < 3) {
		BitstreamSkip(bs, (mode =3D=3D 2) ? 2 : 1);

		reverse_event =3D &DCT3D[intra][BitstreamShowBits(bs, 12)];

		if ((level =3D reverse_event->event.level) =3D=3D 0)
			goto error;

		*last =3D reverse_event->event.last;
		*run  =3D reverse_event->event.run;

		BitstreamSkip(bs, reverse_event->len);

		if (mode < 2)			/* first escape mode, level is offset */
			level +=3D max_level[intra][*last][*run];
		else					/* second escape mode, run is offset */
			*run +=3D max_run[intra][*last][level] + 1;

		return BitstreamGetBits(bs, 1) ? -level : level;
	}

	/* third escape mode - fixed length codes */
	BitstreamSkip(bs, 2);
	*last =3D BitstreamGetBits(bs, 1);
	*run =3D BitstreamGetBits(bs, 6);
	BitstreamSkip(bs, 1);		/* marker */
	level =3D BitstreamGetBits(bs, 12);
	BitstreamSkip(bs, 1);		/* marker */

	return (level << 20) >> 20;

  error:
	*run =3D VLC_ERROR;
	return 0;
}

/************************************************************************=
*****
 * MB reading functions
 =
*************************************************************************=
***/

void
get_intra_block(Bitstream * bs,
				int16_t * block,
				int direction,
				int coeff)
{

	const uint16_t *scan =3D scan_tables[direction];
	int level;
	int run;
	int last;

	do {
		level =3D get_coeff(bs, &run, &last, 1, 0);
		if (run =3D=3D -1) {
			DPRINTF(DPRINTF_DEBUG, "fatal: invalid run");
			break;
		}
		coeff +=3D run;
		block[scan[coeff]] =3D level;

		DPRINTF(DPRINTF_COEFF,"block[%i] %i", scan[coeff], level);
		/*DPRINTF(DPRINTF_COEFF,"block[%i] %i %08x", scan[coeff], level, =
BitstreamShowBits(bs, 32)); */

		if (level < -2047 || level > 2047) {
			DPRINTF(DPRINTF_DEBUG, "warning: intra_overflow: %d", level);
		}
		coeff++;
	} while (!last);

}

void
get_inter_block(Bitstream * bs,
				int16_t * block)
{

	const uint16_t *scan =3D scan_tables[0];
	int p;
	int level;
	int run;
	int last;

	p =3D 0;
	do {
		level =3D get_coeff(bs, &run, &last, 0, 0);
		if (run =3D=3D -1) {
			DPRINTF(DPRINTF_ERROR, "fatal: invalid run");
			break;
		}
		p +=3D run;

		block[scan[p]] =3D level;

		DPRINTF(DPRINTF_COEFF,"block[%i] %i", scan[p], level);

		if (level < -2047 || level > 2047) {
			DPRINTF(DPRINTF_DEBUG, "warning: inter_overflow: %d", level);
		}
		p++;
	} while (!last);

}

------=_NextPart_000_000C_01C2B579.2D833900--