/*****************************************************************************
 *
 * This software module was originally developed by
 *
 *   Paulo Nunes (IST / ACTS-MoMuSyS)
 *   Robert Danielsen (Telenor / ACTS-MoMuSyS)
 *
 * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
 * This software module is an implementation of a part of one or more MPEG-4
 * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
 * 14496-2) standard.
 *
 * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
 * license to this software module or modifications thereof for use in hardware
 * or software products claiming conformance to the MPEG-4 Video (ISO/IEC
 * 14496-2) standard.
 *
 * Those intending to use this software module in hardware or software products
 * are advised that its use may infringe existing patents. The original
 * developer of this software module and his/her company, the subsequent
 * editors and their companies, and ISO/IEC have no liability for use of this
 * software module or modifications thereof in an implementation. Copyright is
 * not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming
 * products.
 *
 * ACTS-MoMuSys partners retain full right to use the code for his/her own
 * purpose, assign or donate the code to a third party and to inhibit third
 * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
 * conforming products. This copyright notice must be included in all copies or
 * derivative works.
 *
 * Copyright (c) 1996
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:	vm_vlc_dec.c
 *
 * Author:	Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
 * Created:	1-Mar-96
 *                                                                         
 * Description: This file contains the VLC functions needed to decode a
 *		bitstream. 
 *
 * Notes: 	
 *		The functions contained in this file were adapted from
 *		tmndecode
 * 		Written by Karl Olav Lillevold <kol@nta.no>,
 *		1995 Telenor R&D.
 * 		Donated to the Momusys-project as background code by
 *		Telenor. 
 *
 *		based on mpeg2decode, (C) 1994, MPEG Software Simulation Group
 *		and mpeg2play, (C) 1994 Stefan Eckart
 *					<stefan@lis.e-technik.tu-muenchen.de>
 *
 *
 * Modified:	9-May-96 Paulo Nunes: Reformatted. New headers.
 *              17-Jan-97 Jan De Lameillieure (HHI) : corrected in 
 *                            VlcDecCBPY() the trace file output
 *              01.05.97 Luis Ducla-Soares: added RvlcDecTCOEF() to allow decoding
 *                                          of Reversible VLCs.
 *		09.03.98 Paulo Nunes: Cleaning.
 *
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/

#include "vm_vlc_dec.h"
#include "vm_vlc_dec_tab.h"
#include "max_level.h"

#define QUIET			0

/***********************************************************CommentBegin******
 *
 * -- VlcDecMV -- Decodes the value of a VLC coded motion vector.
 *
 * Author :		
 *	Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
 *
 * Created :		
 *	1-Mar-96
 *
 * Purpose :		
 *	To decode the value of a VLC coded motion vector.
 *
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid motion
 *					vector code. 
 *
 *
 * Return values :	
 *	The value of the motion vector difference multiplied by 2.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	14-May-96 Paulo Nunes: Deal with new VLC table for MVD (index 64),
 *			       according to VM2.1.
 *
 *      8-January-97 Luis Ducla-Soares: changed  test  if((code-=4)<0) to if(temp<0) 
 *                                      because code is UInt and therefore can never 
 *                                      be negative.
 *
 ***********************************************************CommentEnd********/

Int
VlcDecMV (Bitstream * stream, Int * error_flag, Trace *trace)

{
  UInt                code;
  Int                 temp;
  


  if (BitstreamReadBits (stream, 1, "motion_code", trace, CODE))
    {
      return 0;			/* Vector difference = 0 */
    }

  if ((code = BitstreamShowBits (stream, 12)) >= 512)
    {
      code = (code >> 8) - 2;
      BitstreamFlushBits (stream, TMNMVtab0[code].len);
      BitstreamTraceVLC(TMNMVtab0[code] , "MV", trace);      
      
      return TMNMVtab0[code].val;
    }

  if (code >= 128)
    {
      code = (code >> 2) - 32;
      BitstreamFlushBits (stream, TMNMVtab1[code].len);
      BitstreamTraceVLC(TMNMVtab1[code] , "MV", trace);      


      return TMNMVtab1[code].val;
    }


  temp = code - 4;
  
  if (temp < 0)
    {
      if (!QUIET)
	fprintf (stderr, "Invalid motion_vector code\n");
      *error_flag = 1;
      return -1;
    }

  code -= 4;

  BitstreamFlushBits (stream, TMNMVtab2[code].len);
  BitstreamTraceVLC( TMNMVtab2[code] , "MV", trace);      


  return TMNMVtab2[code].val;

}				/* VlcDecMV */

/***********************************************************CommentBegin******
 *
 * -- VlcDecMCBPC_com_inter -- Decodes the "Macroblock type & Coded block pattern for chrominance"
 *
 * Author :		
 *	Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
 *
 * Created :		
 *	1-Mar-96
 *
 * Purpose :		
 *	To decode the "Macroblock type & Coded block pattern for
 *	 chrominance".
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	 Int * error_flag,		flag to signal an invalid MCBPC code.
 *
 *
 * Return values :	
 *	The value of the MCBPC or -1 for bit stuffing.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	09.11.96 Robert Danielsen: Changed the name
 *	09.03.98 Paulo Nunes: Cleaning.
 *
 ***********************************************************CommentEnd********/

Int
VlcDecMCBPC_com_inter(Bitstream * stream, Int * error_flag, Trace *trace)

{
  UInt                code;

  code = BitstreamShowBits (stream, 9);

  if (code == 1)
    {
     /* macroblock stuffing */
      BitstreamFlushBits (stream, 9);
      BitstreamTrace( "000000001" , "MCBPC STUFFING", trace);      
      return -1;
    }

  if (code == 0)
    {
      if (!QUIET)
	fprintf (stderr, "Invalid MCBPC code\n");
      *error_flag = 1;
      return -1;
    }

  if (code >= 256)
    {
      BitstreamFlushBits (stream, 1);
      BitstreamTrace( "1" , "MCBPC", trace);      
      return 0;
    }

  BitstreamFlushBits (stream, MCBPCtab[code].len);
  BitstreamTrace( btos((code>>(9-MCBPCtab[code].len)), MCBPCtab[code].len)  , "MCBPC_com_inter", trace);

  return MCBPCtab[code].val;

}
				/* VlcDecMCBPC */
/***********************************************************CommentBegin******
 *
 * -- VlcDecMCBPC_com_sprite -- Decodes the "Macroblock type & Coded block pattern for chrominance"
 *
 * Author :		
 *	Cecile Dufour (Philips/LEP) - dufour@lep.research.philips.com
 *
 * Created :		
 *	21-Mar-97
 *
 * Purpose :		
 *	To decode the "Macroblock type & Coded block pattern for
 *	 chrominance" in case of a sprite vop
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	 Int * error_flag,		flag to signal an invalid MCBPC code.
 *
 *
 * Return values :	
 *	The value of the MCBPC or -1 for bit stuffing.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	09.03.98 Paulo Nunes: Cleaning.
 *
 ***********************************************************CommentEnd********/

Int
VlcDecMCBPC_com_sprite(Bitstream * stream, Int * error_flag, Trace *trace)

{
  UInt                code;

  code = BitstreamShowBits (stream, 9);

  if (code == 1)
    {
     /* macroblock stuffing */
      BitstreamFlushBits (stream, 9);
      BitstreamTrace( "000000001" , "MCBPC SPRITE STUFFING", trace);      
      return -1;
    }
    
  code = BitstreamShowBits (stream, 12);
  
  if (code<8)	/* these are 12 bits code */
    {
      BitstreamFlushBits (stream, 12);
      BitstreamTrace( btos(code,MCBPCspritetab[code+256].len )  , 
      						"MCBPC_com_sprite", trace);
      return MCBPCspritetab[code+256].val;
      }
  
  code >>=3;
  
  if (code == 0)
    {
      if (!QUIET)
	fprintf (stderr, "Invalid MCBPC SPRITE code\n");
      *error_flag = 1;
      return -1;
    }

  if (code >= 256)
    {
      BitstreamFlushBits (stream, 1);
      BitstreamTrace( "1" , "MCBPC", trace);      
      return 0;
    }

  BitstreamFlushBits (stream, MCBPCspritetab[code].len);
  BitstreamTrace( btos((code>>(9-MCBPCspritetab[code].len)), 
  			MCBPCspritetab[code].len)  , "MCBPC_com_sprite", trace);

  return MCBPCspritetab[code].val;

}				/* VlcDecMCBPC */

/***********************************************************CommentBegin******
 *
 * -- VlcDecMCBPC_com_intra -- Decodes the "Macroblock type & Coded block pattern for chrominance" (INTRA mode).
 *
 * Author :		
 *	Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
 *
 * Created :		
 *	1-Mar-96
 *
 * Purpose :		
 *	To decode the "Macroblock type & Coded block pattern for
 *	chrominance" (INTRA mode). 
 * 
 *
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid MCBPC
 *					code.
 *
 *
 * Return values :	
 *	The value of the MCBPC or -1 for bit stuffing.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	09.11.96 Robert Danielsen: Changed the name
 *	09.03.98 Paulo Nunes: Cleaning.
 *
 ***********************************************************CommentEnd********/

Int
VlcDecMCBPC_com_intra(Bitstream * stream, Int * error_flag, Trace *trace)

{
  UInt                code;

  code = BitstreamShowBits (stream, 9);

  if (code == 1)
    {
     /* macroblock stuffing */
      BitstreamFlushBits (stream, 9);
      BitstreamTrace( "000000001" , "MCBPCintra STUFFING", trace);      
      return -1;
    }

  if (code < 8)
    {
      if (!QUIET)
	fprintf (stderr, "Invalid MCBPCintra code\n");
      *error_flag = 1;
      return -1;
    }

  code >>= 3;

  if (code >= 32)
    {
      BitstreamFlushBits (stream, 1);
      BitstreamTrace("1" , "MCBPCintra", trace);
      return 3;
    }

  BitstreamFlushBits (stream, MCBPCtabintra[code].len);
  BitstreamTrace( btos((code>>(6-MCBPCtabintra[code].len)), MCBPCtabintra[code].len)  , "MCBPC_com_intra", trace);

  return MCBPCtabintra[code].val;

}				/* VlcDecMCBPCintra */

/***********************************************************CommentBegin******
 *
 * -- VlcDecMCBPC_sep -- Decodes DQUANT & Coded block pattern for chrominance
 *			for separate mode
 *
 * Author :		
 *	Robert Danielsen, Telenor R&D
 *	Basically the same as VlcDecMCBPCintra() by Paulo (see above).
 *
 * Created :		
 *	06.11.96
 *
 * Purpose :
 *	Decodes DQUANT & Coded block pattern for chrominance
 *			for separate mode
 *
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 * Arguments in/out :	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid MCBPC
 *					code.
 *
 * Return values :	
 *	The value of the MCBPC or -1 for bit stuffing.
 *
 * Side effects :	
 *	
 * Description :	
 *	
 * See also :
 *	
 * Modified :		
 *	09.03.98 Paulo Nunes: Cleaning.
 *	
 ***********************************************************CommentEnd********/

Int
VlcDecMCBPC_sep(Bitstream * stream, Int * error_flag, Trace *trace)
{
    UInt code;

    code = BitstreamShowBits(stream, 9);

    if (code == 1)
    {
	/* macroblock stuffing */
	BitstreamFlushBits(stream, 9);
	BitstreamTrace("000000001" , "MCBPCsep STUFFING", trace);      
	return -1;
    }

    if (code < 8)
    {
	if (!QUIET)
	    fprintf (stderr, "Invalid MCBPCsep code\n");
	*error_flag = 1;
	return -1;
    }

    code >>= 3;

    if (code >= 32)
    {
	BitstreamFlushBits (stream, 1);
	BitstreamTrace("1" , "MCBPCsep", trace);
	return 0;
    }

    BitstreamFlushBits (stream, MCBPCtab_sep[code].len);
    BitstreamTrace( btos((code>>(6-MCBPCtab_sep[code].len)), MCBPCtab_sep[code].len)  , "MCBPCsep", trace);

    return MCBPCtab_sep[code].val;

}				/* VlcDecMCBPCsep */

/***********************************************************CommentBegin******
 *
 * -- VlcDecCBPY -- Decodes the "Coded block pattern for luminance"
 *
 * Author :		
 *	
 *
 * Created :		
 *	
 *
 * Purpose :		
 *	To decode the "Coded block pattern for luminance".
 *
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid CBPY
 *					 code.
 *
 *
 * Return values :	
 *	The value of the CBPY or -1 for bit stuffing.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	17-Jan-97 : Jan De Lameillieure (HHI) : correction of the CBPY 
 *                        line in the trace file
 *      13-05-97  : Minhua Zhou: added "MB_transp_pattern" and "intra"
 *	09.03.98 Paulo Nunes: Cleaning.
 *
 ***********************************************************CommentEnd********/

Int
VlcDecCBPY (Bitstream * stream, Char intra, Int *MB_transp_pattern, Int * error_flag, Trace *trace)

{
  UInt                code;
  Int                 val,i,CBPY=0,ptr,mask;
  UInt                nb_transparent_blk=0;
  
  nb_transparent_blk =  MB_transp_pattern[0]+MB_transp_pattern[1]+
                        MB_transp_pattern[2]+MB_transp_pattern[3];

  for (i=0;i<4;i++)
    if ( MB_transp_pattern[i]>1) 
      printf("errror in MB_transp_pattern\n");
  
  
  if  (nb_transparent_blk==0) {
  
    code = BitstreamShowBits (stream, 6);

    if (code < 2)
      {
	if (!QUIET)
	  fprintf (stderr, "Invalid CBPY4 code\n");
	*error_flag = 1;
	return -1;
      }

    if (code >= 48)
      {
	BitstreamFlushBits (stream, 2);
	BitstreamTrace("11" , "CBPY4", trace);
	CBPY =15;
      }  else {

	BitstreamFlushBits (stream, CBPYtab[code].len);
	BitstreamTrace(btos((code>>(6-CBPYtab[code].len)), CBPYtab[code].len)  , "CBPY4", trace);
	CBPY=CBPYtab[code].val;
      }

  }

  else if (nb_transparent_blk==1) {
    /* one transparent blocks */
    code = BitstreamShowBits (stream, 6);
    BitstreamFlushBits (stream, CBPYtab3[code].len); 
    BitstreamTrace(btos((code>>(6-CBPYtab3[code].len)), CBPYtab3[code].len)  , "CBPY3", trace);             				
    val=CBPYtab3[code].val;ptr=0;
    for (i=0;i<4;i++)
      if (MB_transp_pattern[i]==0) {
	CBPY += ((val>>(2-ptr))&0x1)?(1<<(3-i)):0;
	ptr++;
      }  
  } else if (nb_transparent_blk==2) {


    /* two transparent blocks */
    code = BitstreamShowBits (stream, 4);
    BitstreamFlushBits (stream, CBPYtab2[code].len); 
    BitstreamTrace(btos((code>>(4-CBPYtab2[code].len)), CBPYtab2[code].len)  , "CBPY2", trace);
    val=CBPYtab2[code].val;ptr=0;
    for (i=0;i<4;i++)
      if (MB_transp_pattern[i]==0) {
	CBPY += ((val>>(1-ptr))&0x1)?(1<<(3-i)):0;
	ptr++;
      }  
  } else if (nb_transparent_blk==3) {

    code = BitstreamShowBits (stream, 2);
    if (code==1) {
     BitstreamFlushBits (stream,2);
     BitstreamTrace("01" , "CBPY1", trace); 
     code =0;
    } else {
     BitstreamFlushBits (stream,1);
     BitstreamTrace("1" , "CBPY1", trace); 
     code =1;
    } 
       for (i=0;i<4;i++)
      if (MB_transp_pattern[i]==0) {
	CBPY += (code)?(1<<(3-i)):0;
      }  
  }


  if ((intra==0)&&(nb_transparent_blk!=3)) CBPY = 15-CBPY;
  mask = 15-MB_transp_pattern[0]*8-MB_transp_pattern[1]*4
           -MB_transp_pattern[2]*2-MB_transp_pattern[3];     
  CBPY = CBPY&mask;
  return CBPY;

}				

/* VlcDecCBPY */

/***********************************************************CommentBegin******
 *
 * -- VlcDecCBPC -- Decodes the "Coded block pattern for chrominance"
 *
 * Author :		
 *	Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
 *
 * Created :		
 *	1-Mar-96
 *
 * Purpose :		
 *	To decode the "Coded block pattern for chrominance".
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid CBPY
 *					code.
 *
 *
 * Return values :	
 *	The value of the CBPC or -1 for bit stuffing.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/

Int
VlcDecCBPC (Bitstream * stream, Int * error_flag, Trace *trace)

{
  UInt                code;

  code = BitstreamShowBits (stream, 1);
  if (code == 1)
    {
      BitstreamFlushBits (stream, 1);
      BitstreamTrace("1" , "CBPC", trace);

      return 0;
    }
  else
    {
      code = BitstreamShowBits (stream, 3);
      BitstreamFlushBits (stream, 3);
      BitstreamTrace(btos(code,3) , "CBPC", trace);
      return code;
    }


}				/* VlcDecCBPC */

/***********************************************************CommentBegin******
 *
 * -- VlcDecTCOEF -- Decodes a VLC coded DCT transform coefficient
 *
 * Author :		
 *	Paulo Nunes (IST) - Paulo.Nunes@lx.it.pt
 *
 * Created :		
 *	1-Mar-96
 *
 * Purpose :		
 *	To decode a VLC coded DCT transform coefficient.
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *	Int intra_luma			flag to indicate table to use
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid TCOEF
 *					code.
 *
 * Return values :	
 *	A structure containing the values of LAST, RUN, and LEVEL.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	04.11.96 Robert Danielsen: Added tables for Intra luminance
 *			coefficients (VM 4.0)
 *      27.07.97 C.S. Boon : Add in 3-mode escape (VM8.0)
 *      04.08.97 Minhua Zhou: added intra_dc_vlc_thr 
 *	09.03.98 Paulo Nunes: Cleaning. 
 *
 ***********************************************************CommentEnd********/

Tcoef
VlcDecTCOEF(Bitstream *stream, Int *error_flag, Trace *trace,
		  Int intra)
{
    UInt                code;
    VLCtab             *tab;
    Tcoef               tcoef =
    {0, 0, 0};

    code = BitstreamShowBits (stream, 12);

    if (code >= 512)
	if (intra == 0)
	    tab = &DCT3Dtab0[(code >> 5) - 16];
	else
	    tab = &DCT3Dtab3[(code >> 5) - 16];
    else if (code >= 128)
	if (intra == 0)
	    tab = &DCT3Dtab1[(code >> 2) - 32];
	else
	    tab = &DCT3Dtab4[(code >> 2) - 32];
    else if (code >= 8)
	if (intra == 0)
	    tab = &DCT3Dtab2[(code >> 0) - 8];
	else
	    tab = &DCT3Dtab5[(code >> 0) - 8];
    else
    {
	if (!QUIET)
	    fprintf (stderr, "Invalid Huffman code in VlcDecTCOEF().\n");
	*error_flag = 1;
	return tcoef;
    }

    BitstreamFlushBits (stream, tab->len);
    BitstreamTraceVLC(*tab , "VLC 3D", trace);

    if (intra == 0) {		
	tcoef.run = (tab->val >> 4) & 255;
	tcoef.level = tab->val & 15;
	tcoef.last = (tab->val >> 12) & 1;
    }
    else {
	tcoef.run = (tab->val >> 8) & 255;
	tcoef.level = tab->val & 255;
	tcoef.last = (tab->val >> 16) & 1;
    }      


    /* the following is modified for 3-mode escape -- boon */
    if (tab->val == ESCAPE)	/* ESCAPE */
    {
      int level_offset;
      level_offset = BitstreamReadBits (stream, 1, "ESC level offset", trace, NUM);

      if (!level_offset) {
	/* first escape mode. level is offset */

	code = BitstreamShowBits (stream, 12);

	if (code >= 512)
	  if (intra == 0)
	    tab = &DCT3Dtab0[(code >> 5) - 16];
	  else
	    tab = &DCT3Dtab3[(code >> 5) - 16];
	else if (code >= 128)
	  if (intra == 0)
	    tab = &DCT3Dtab1[(code >> 2) - 32];
	  else
	    tab = &DCT3Dtab4[(code >> 2) - 32];
	else if (code >= 8)
	  if (intra == 0)
	    tab = &DCT3Dtab2[(code >> 0) - 8];
	  else
	    tab = &DCT3Dtab5[(code >> 0) - 8];
	else
	  {
	    if (!QUIET)
	      fprintf (stderr, "Invalid Huffman code in VlcDecTCOEF()2.\n");
	    *error_flag = 1;
	    return tcoef;
	  }

	BitstreamFlushBits (stream, tab->len);
	BitstreamTraceVLC(*tab , "VLC 3D", trace);

	if (intra == 0) {		
	  tcoef.run = (tab->val >> 4) & 255;
	  tcoef.level = tab->val & 15;
	  tcoef.last = (tab->val >> 12) & 1;
	}
	else {
	  tcoef.run = (tab->val >> 8) & 255;
	  tcoef.level = tab->val & 255;
	  tcoef.last = (tab->val >> 16) & 1;
	}      

	/* need to add back the max level */
	if (intra)
	  tcoef.level = tcoef.level + intra_max_level[tcoef.last][tcoef.run];
	else
	  tcoef.level = tcoef.level + inter_max_level[tcoef.last][tcoef.run];
	
	/* sign bit */
        tcoef.sign = BitstreamReadBits (stream, 1, "SIGN", trace, CODE);        
        if(trace->trace)
	  fprintf(trace->fp_trace, "  >> Run: %3d -- Level: %- 4d\n", tcoef.run, tcoef.level*(1 - 2*tcoef.sign));

      } else {
	
	int run_offset;
	run_offset = BitstreamReadBits (stream, 1, "ESC run offset", trace, NUM);
	
	if (!run_offset) {

	  /* second escape mode. run is offset */

	  code = BitstreamShowBits (stream, 12);

	  if (code >= 512)
	    if (intra == 0)
	      tab = &DCT3Dtab0[(code >> 5) - 16];
	    else
	      tab = &DCT3Dtab3[(code >> 5) - 16];
	  else if (code >= 128)
	    if (intra == 0)
	      tab = &DCT3Dtab1[(code >> 2) - 32];
	    else
	      tab = &DCT3Dtab4[(code >> 2) - 32];
	  else if (code >= 8)
	    if (intra == 0)
	      tab = &DCT3Dtab2[(code >> 0) - 8];
	    else
	      tab = &DCT3Dtab5[(code >> 0) - 8];
	  else
	    {
	      if (!QUIET)
		fprintf (stderr, "Invalid Huffman code in VlcDecTCOEF()2.\n");
	      *error_flag = 1;
	      return tcoef;
	    }

	  BitstreamFlushBits (stream, tab->len);
	  BitstreamTraceVLC(*tab , "VLC 3D", trace);
	  
	  if (intra == 0) {		
	    tcoef.run = (tab->val >> 4) & 255;
	    tcoef.level = tab->val & 15;
	    tcoef.last = (tab->val >> 12) & 1;
	  }
	  else {
	    tcoef.run = (tab->val >> 8) & 255;
	    tcoef.level = tab->val & 255;
	    tcoef.last = (tab->val >> 16) & 1;
	  }      
	  
	  /* need to add back the max run */
	  if (intra) {
	    if (tcoef.last)
	      tcoef.run = tcoef.run + intra_max_run1[tcoef.level]+1;
	    else
	      tcoef.run = tcoef.run + intra_max_run0[tcoef.level]+1;
	  } else {
	    if (tcoef.last)
	      tcoef.run = tcoef.run + inter_max_run1[tcoef.level]+1;
	    else
	      tcoef.run = tcoef.run + inter_max_run0[tcoef.level]+1;
	  }
	
	  /* sign bit */
	  tcoef.sign = BitstreamReadBits (stream, 1, "SIGN", trace, CODE);        
	  if(trace->trace)
	    fprintf(trace->fp_trace, "  >> Run: %3d -- Level: %- 4d\n", tcoef.run, tcoef.level*(1 - 2*tcoef.sign));

	} else {

	  /* third escape mode. flc */

	  /* Modified due to N2171 Cl. 2.2.14 MW 25-MAR-1998 */
	  /* tcoef.last = BitstreamReadBits (stream, 1, "LAST", trace, MARK); */
	  /* tcoef.run = BitstreamReadBits (stream, 6, "RUN", trace, NUM); */
	  /* tcoef.level = BitstreamReadBits (stream, 8, "LEVEL", trace, NUM); */
	  /* if (tcoef.level >= 128) */
	  /*   { */
	  /*     tcoef.sign = 1; */
	  /*     tcoef.level = 256 - tcoef.level; */
	  /*   } */
	  /* else */
	  /*   { */
	  /*     tcoef.sign = 0; */
	  /*   } */
	  tcoef.last = BitstreamReadBits (stream, 1, "LAST", trace, MARK);
	  tcoef.run = BitstreamReadBits (stream, 6, "RUN", trace, NUM);
	  tcoef.level = BitstreamReadBits (stream, 12, "LEVEL", trace, NUM);
	  if (tcoef.level >= 2048)
	    {
	      tcoef.sign = 1;
	      tcoef.level = 4096 - tcoef.level;
	    }
	  else
	    {
	      tcoef.sign = 0;
	    }

	} /* flc */
      } 
    }
    else
    {
        tcoef.sign = BitstreamReadBits (stream, 1, "SIGN", trace, CODE);        
        if(trace->trace)
            fprintf(trace->fp_trace, "  >> Run: %3d -- Level: %- 4d\n", tcoef.run, tcoef.level*(1 - 2*tcoef.sign));
    }

    if(trace->trace)
	if(tcoef.last)
	    fprintf(trace->fp_trace, "----------\n");
  

    return tcoef;

}				/* VlcDecTCOEF */


/***********************************************************CommentBegin******
 *
 * -- RvlcDecTCOEF -- Decodes a RVLC coded DCT transform coefficient
 *
 * Author :		
 *	Luis Ducla-Soares (IST) - lds@lx.it.pt
 *
 * Created :		
 *	01.05.97
 *
 * Purpose :		
 *	To decode a VLC coded DCT transform coefficient.
 * 
 * Arguments in : 	
 *	Bitstream * stream,		input bitstream.
 *	Int intra_luma			flag to indicate table to use
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Int * error_flag,		flag to signal an invalid TCOEF
 *					code.
 *
 * Return values :	
 *	A structure containing the values of LAST, RUN, and LEVEL.
 *
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *
 ***********************************************************CommentEnd********/

Tcoef
RvlcDecTCOEF(Bitstream *stream, Int *error_flag, Trace *trace,
		  Int intra_luma)
{
    UInt                code, mask;
    VLCtab             *tab;
    Tcoef               tcoef =
    {0, 0, 0};

    Int count, len;
     

    mask = 0x4000;      /* mask  100000000000000   */
    code = BitstreamShowBits (stream, 15);
    len = 1;
     
 
    if (code & mask) {
      count = 1;
      while (count > 0) {
	mask = mask >> 1;
	if (code & mask) 
	  count--;
	len++;
      }
    }
    else {
      count = 2;
      while (count > 0) {
	mask = mask >> 1;
	if (!(code & mask))
	  count--;
	len++;
      }
    }
    
    code = code & 0x7fff;
    code = code >> (15 - (len + 1));
    
    switch(code) {
 
    case 0x0:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[169];
      else
	tab = &RvlcDCT3Dtab1[169];
      break;
      
    case 0x1: 
      if (intra_luma)
        tab = &RvlcDCT3Dtab0[27];
      else
        tab = &RvlcDCT3Dtab1[1];
      break;
    
    case 0x4: 
      if (intra_luma)
        tab = &RvlcDCT3Dtab0[40];
      else
     	tab = &RvlcDCT3Dtab1[2];
       break;
    
    case 0x5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[51];
      else
	tab = &RvlcDCT3Dtab1[36];
      break;
      
    case 0x6:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[0];
      else
	tab = &RvlcDCT3Dtab1[0];
      break;
      
    case 0x7:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[1];
      else
	tab = &RvlcDCT3Dtab1[19];
      break;
      
    case 0x8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[28];
      else
	tab = &RvlcDCT3Dtab1[43];
      break;
      
    case 0x9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[3];
      else
	tab = &RvlcDCT3Dtab1[48];
      break;
      
    case 0xa:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[2];
      else
	tab = &RvlcDCT3Dtab1[29];
      break;
      
    case 0xb:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[103];
      else
	tab = &RvlcDCT3Dtab1[103];
      break;
      
    case 0xc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[60];
      else
	tab = &RvlcDCT3Dtab1[20];
      break;
      
    case 0xd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[66];
      else
	tab = &RvlcDCT3Dtab1[52];
      break;
      
    case 0x12:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[108];
      else
	tab = &RvlcDCT3Dtab1[108];
      break;
      
    case 0x13:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[113];
      else
	tab = &RvlcDCT3Dtab1[113];
      break;
      
    case 0x14:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[4];
      else
	tab = &RvlcDCT3Dtab1[56];
      break;
      
    case 0x15:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[5];
      else
	tab = &RvlcDCT3Dtab1[60];
      break;
      
    case 0x18:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[116];
      else
	tab = &RvlcDCT3Dtab1[116];
      break;
      
    case 0x19:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[118];
      else
	tab = &RvlcDCT3Dtab1[118];
      break;
      
    case 0x1c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[72];
      else
	tab = &RvlcDCT3Dtab1[3];
      break;
      
    case 0x1d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[77];
      else
	tab = &RvlcDCT3Dtab1[30];
      break;
      
    case 0x22:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[120];
      else
	tab = &RvlcDCT3Dtab1[120];
      break;
      
    case 0x23:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[122];
      else
	tab = &RvlcDCT3Dtab1[122];
      break;
      
    case 0x2c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[41];
      else
	tab = &RvlcDCT3Dtab1[63];
      break;
      
    case 0x2d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[29];
      else
	tab = &RvlcDCT3Dtab1[66];
      break;
      
    case 0x34:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[6];
      else
	tab = &RvlcDCT3Dtab1[68];
      break;
      
    case 0x35:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[124];
      else
	tab = &RvlcDCT3Dtab1[124];
      break;
      
    case 0x38:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[126];
      else
	tab = &RvlcDCT3Dtab1[126];
      break;
      
    case 0x39:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[128];
      else
	tab = &RvlcDCT3Dtab1[128];
      break;
      
    case 0x3c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[82];
      else
	tab = &RvlcDCT3Dtab1[4];
      break;
      
    case 0x3d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[86];
      else
	tab = &RvlcDCT3Dtab1[5];
      break;
      
    case 0x42:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[130];
      else
	tab = &RvlcDCT3Dtab1[130];
      break;
      
    case 0x43:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[132];
      else
	tab = &RvlcDCT3Dtab1[132];
      break;
      
    case 0x5c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[52];
      else
	tab = &RvlcDCT3Dtab1[21];
      break;
      
    case 0x5d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[61];
      else
	tab = &RvlcDCT3Dtab1[37];
      break;
      
    case 0x6c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[30];
      else
	tab = &RvlcDCT3Dtab1[44];
      break;
      
    case 0x6d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[31];
      else
	tab = &RvlcDCT3Dtab1[70];
      break;
      
    case 0x74:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[7];
      else
	tab = &RvlcDCT3Dtab1[72];
      break;
      
    case 0x75:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[8];
      else
	tab = &RvlcDCT3Dtab1[74];
      break;
      
    case 0x78:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[104];
      else
	tab = &RvlcDCT3Dtab1[104];
      break;
      
    case 0x79:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[134];
      else
	tab = &RvlcDCT3Dtab1[134];
      break;
      
    case 0x7c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[90];
      else
	tab = &RvlcDCT3Dtab1[6];
      break;
      
    case 0x7d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[67];
      else
	tab = &RvlcDCT3Dtab1[22];
      break;
      
    case 0x82:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[136];
      else
	tab = &RvlcDCT3Dtab1[136];
      break;
      
    case 0x83:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[138];
      else
	tab = &RvlcDCT3Dtab1[138];
      break;
      
    case 0xbc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[42];
      else
	tab = &RvlcDCT3Dtab1[31];
      break;
      
    case 0xbd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[53];
      else
	tab = &RvlcDCT3Dtab1[49];
      break;
      
    case 0xdc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[32];
      else
	tab = &RvlcDCT3Dtab1[76];
      break;
      
    case 0xdd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[9];
      else
	tab = &RvlcDCT3Dtab1[78];
      break;
      
    case 0xec:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[10];
      else
	tab = &RvlcDCT3Dtab1[80];
      break;
      
    case 0xed:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[109];
      else
	tab = &RvlcDCT3Dtab1[109];
      break;
      
    case 0xf4:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[139];
      else
	tab = &RvlcDCT3Dtab1[139];
      break;
      
    case 0xf5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[140];
      else
	tab = &RvlcDCT3Dtab1[140];
      break;
      
    case 0xf8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[141];
      else
	tab = &RvlcDCT3Dtab1[141];
      break;
      
    case 0xf9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[142];
      else
	tab = &RvlcDCT3Dtab1[142];
      break;
      
    case 0xfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[92];
      else
	tab = &RvlcDCT3Dtab1[7];
      break;
      
    case 0xfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[94];
      else
	tab = &RvlcDCT3Dtab1[8];
      break;
      
    case 0x102:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[143];
      else
	tab = &RvlcDCT3Dtab1[143];
      break;
      
    case 0x103:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[144];
      else
	tab = &RvlcDCT3Dtab1[144];
      break;
      
    case 0x17c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[73];
      else
	tab = &RvlcDCT3Dtab1[23];
      break;
      
    case 0x17d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[78];
      else
	tab = &RvlcDCT3Dtab1[38];
      break;
      
    case 0x1bc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[83];
      else
	tab = &RvlcDCT3Dtab1[53];
      break;
      
    case 0x1bd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[62];
      else
	tab = &RvlcDCT3Dtab1[57];
      break;
      
    case 0x1dc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[43];
      else
	tab = &RvlcDCT3Dtab1[61];
      break;
      
    case 0x1dd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[33];
      else
	tab = &RvlcDCT3Dtab1[64];
      break;
      
    case 0x1ec:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[11];
      else
	tab = &RvlcDCT3Dtab1[82];
      break;
      
    case 0x1ed:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[12];
      else
	tab = &RvlcDCT3Dtab1[83];
      break;
      
    case 0x1f4:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[13];
      else
	tab = &RvlcDCT3Dtab1[84];
      break;
      
    case 0x1f5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[145];
      else
	tab = &RvlcDCT3Dtab1[145];
      break;
      
    case 0x1f8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[146];
      else
	tab = &RvlcDCT3Dtab1[146];
      break;
      
    case 0x1f9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[147];
      else
	tab = &RvlcDCT3Dtab1[147];
      break;
      
    case 0x1fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[96];
      else
	tab = &RvlcDCT3Dtab1[9];
      break;
      
    case 0x1fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[87];
      else
	tab = &RvlcDCT3Dtab1[10];
      break;
      
    case 0x202:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[148];
      else
	tab = &RvlcDCT3Dtab1[148];
      break;
      
    case 0x203:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[149];
      else
	tab = &RvlcDCT3Dtab1[149];
      break;
      
    case 0x2fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[68];
      else
	tab = &RvlcDCT3Dtab1[24];
      break;
      
    case 0x2fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[74];
      else
	tab = &RvlcDCT3Dtab1[32];
      break;
      
    case 0x37c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[79];
      else
	tab = &RvlcDCT3Dtab1[45];
      break;
      
    case 0x37d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[54];
      else
	tab = &RvlcDCT3Dtab1[50];
      break;
      
    case 0x3bc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[44];
      else
	tab = &RvlcDCT3Dtab1[67];
      break;
      
    case 0x3bd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[45];
      else
	tab = &RvlcDCT3Dtab1[85];
      break;
      
    case 0x3dc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[34];
      else
	tab = &RvlcDCT3Dtab1[86];
      break;
      
    case 0x3dd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[35];
      else
	tab = &RvlcDCT3Dtab1[87];
      break;
      
    case 0x3ec:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[14];
      else
	tab = &RvlcDCT3Dtab1[88];
      break;
      
    case 0x3ed:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[15];
      else
	tab = &RvlcDCT3Dtab1[89];
      break;
      
    case 0x3f4:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[16];
      else
	tab = &RvlcDCT3Dtab1[90];
      break;
      
    case 0x3f5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[105];
      else
	tab = &RvlcDCT3Dtab1[105];
      break;
      
    case 0x3f8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[114];
      else
	tab = &RvlcDCT3Dtab1[114];
      break;
      
    case 0x3f9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[150];
      else
	tab = &RvlcDCT3Dtab1[150];
      break;
      
    case 0x3fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[91];
      else
	tab = &RvlcDCT3Dtab1[11];
      break;
      
    case 0x3fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[63];
      else
	tab = &RvlcDCT3Dtab1[25];
      break;
      
    case 0x402:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[151];
      else
	tab = &RvlcDCT3Dtab1[151];
      break;
      
    case 0x403:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[152];
      else
	tab = &RvlcDCT3Dtab1[152];
      break;
      
    case 0x5fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[69];
      else
	tab = &RvlcDCT3Dtab1[33];
      break;
      
    case 0x5fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[75];
      else
	tab = &RvlcDCT3Dtab1[39];
      break;
      
    case 0x6fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[55];
      else
	tab = &RvlcDCT3Dtab1[54];
      break;
      
    case 0x6fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[64];
      else
	tab = &RvlcDCT3Dtab1[58];
      break;
      
    case 0x77c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[36];
      else
	tab = &RvlcDCT3Dtab1[69];
      break;
      
    case 0x77d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[17];
      else
	tab = &RvlcDCT3Dtab1[91];
      break;
      
    case 0x7bc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[18];
      else
	tab = &RvlcDCT3Dtab1[92];
      break;
      
    case 0x7bd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[21];
      else
	tab = &RvlcDCT3Dtab1[93];
      break;
      
    case 0x7dc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[110];
      else
	tab = &RvlcDCT3Dtab1[110];
      break;
      
    case 0x7dd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[117];
      else
	tab = &RvlcDCT3Dtab1[117];
      break;
      
    case 0x7ec:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[119];
      else
	tab = &RvlcDCT3Dtab1[119];
      break;
      
    case 0x7ed:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[153];
      else
	tab = &RvlcDCT3Dtab1[153];
      break;
      
    case 0x7f4:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[154];
      else
	tab = &RvlcDCT3Dtab1[154];
      break;
      
    case 0x7f5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[155];
      else
	tab = &RvlcDCT3Dtab1[155];
      break;
      
    case 0x7f8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[156];
      else
	tab = &RvlcDCT3Dtab1[156];
      break;
      
    case 0x7f9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[157];
      else
	tab = &RvlcDCT3Dtab1[157];
      break;
      
    case 0x7fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[97];
      else
	tab = &RvlcDCT3Dtab1[12];
      break;
      
    case 0x7fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[98];
      else
	tab = &RvlcDCT3Dtab1[13];
      break;
      
    case 0x802:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[158];
      else
	tab = &RvlcDCT3Dtab1[158];
      break;
      
    case 0x803:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[159];
      else
	tab = &RvlcDCT3Dtab1[159];
      break;
      
    case 0xbfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[93];
      else
	tab = &RvlcDCT3Dtab1[14];
      break;
      
    case 0xbfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[84];
      else
	tab = &RvlcDCT3Dtab1[15];
      break;
      
    case 0xdfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[88];
      else
	tab = &RvlcDCT3Dtab1[26];
      break;
      
    case 0xdfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[80];
      else
	tab = &RvlcDCT3Dtab1[40];
      break;
      
    case 0xefc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[56];
      else
	tab = &RvlcDCT3Dtab1[46];
      break;
      
    case 0xefd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[46];
      else
	tab = &RvlcDCT3Dtab1[51];
      break;
      
    case 0xf7c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[47];
      else
	tab = &RvlcDCT3Dtab1[62];
      break;
      
    case 0xf7d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[48];
      else
	tab = &RvlcDCT3Dtab1[71];
      break;
      
    case 0xfbc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[37];
      else
	tab = &RvlcDCT3Dtab1[94];
      break;
      
    case 0xfbd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[19];
      else
	tab = &RvlcDCT3Dtab1[95];
      break;
      
    case 0xfdc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[20];
      else
	tab = &RvlcDCT3Dtab1[96];
      break;
      
    case 0xfdd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[22];
      else
	tab = &RvlcDCT3Dtab1[97];
      break;
      
    case 0xfec:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[106];
      else
	tab = &RvlcDCT3Dtab1[106];
      break;
      
    case 0xfed:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[121];
      else
	tab = &RvlcDCT3Dtab1[121];
      break;
      
    case 0xff4:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[123];
      else
	tab = &RvlcDCT3Dtab1[123];
      break;
      
    case 0xff5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[125];
      else
	tab = &RvlcDCT3Dtab1[125];
      break;
      
    case 0xff8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[127];
      else
	tab = &RvlcDCT3Dtab1[127];
      break;
      
    case 0xff9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[129];
      else
	tab = &RvlcDCT3Dtab1[129];
      break;
      
    case 0xffc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[99];
      else
	tab = &RvlcDCT3Dtab1[16];
      break;
      
    case 0xffd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[100];
      else
	tab = &RvlcDCT3Dtab1[17];
      break;
      
    case 0x1002:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[160];
      else
	tab = &RvlcDCT3Dtab1[160];
      break;
      
    case 0x1003:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[161];
      else
	tab = &RvlcDCT3Dtab1[161];
      break;
      
    case 0x17fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[101];
      else
	tab = &RvlcDCT3Dtab1[27];
      break;
      
    case 0x17fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[85];
      else
	tab = &RvlcDCT3Dtab1[28];
      break;
      
    case 0x1bfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[70];
      else
	tab = &RvlcDCT3Dtab1[34];
      break;
      
    case 0x1bfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[65];
      else
	tab = &RvlcDCT3Dtab1[35];
      break;
      
    case 0x1dfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[71];
      else
	tab = &RvlcDCT3Dtab1[41];
      break;
      
    case 0x1dfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[57];
      else
	tab = &RvlcDCT3Dtab1[55];
      break;
      
    case 0x1efc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[58];
      else
	tab = &RvlcDCT3Dtab1[65];
      break;
      
    case 0x1efd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[49];
      else
	tab = &RvlcDCT3Dtab1[73];
      break;
      
    case 0x1f7c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[50];
      else
	tab = &RvlcDCT3Dtab1[75];
      break;
      
    case 0x1f7d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[38];
      else
	tab = &RvlcDCT3Dtab1[77];
      break;
      
    case 0x1fbc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[39];
      else
	tab = &RvlcDCT3Dtab1[79];
      break;
      
    case 0x1fbd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[23];
      else
	tab = &RvlcDCT3Dtab1[98];
      break;
      
    case 0x1fdc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[24];
      else
	tab = &RvlcDCT3Dtab1[99];
      break;
      
    case 0x1fdd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[25];
      else
	tab = &RvlcDCT3Dtab1[100];
      break;
      
    case 0x1fec:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[107];
      else
	tab = &RvlcDCT3Dtab1[107];
      break;
      
    case 0x1fed:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[111];
      else
	tab = &RvlcDCT3Dtab1[111];
      break;
      
    case 0x1ff4:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[131];
      else
	tab = &RvlcDCT3Dtab1[131];
      break;
      
    case 0x1ff5:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[133];
      else
	tab = &RvlcDCT3Dtab1[133];
      break;
      
    case 0x1ff8:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[135];
      else
	tab = &RvlcDCT3Dtab1[135];
      break;
      
    case 0x1ff9:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[162];
      else
	tab = &RvlcDCT3Dtab1[162];
      break;
      
    case 0x1ffc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[26];
      else
	tab = &RvlcDCT3Dtab1[18];
      break;
      
    case 0x1ffd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[59];
      else
	tab = &RvlcDCT3Dtab1[42];
      break;
      
    case 0x2002:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[163];
      else
	tab = &RvlcDCT3Dtab1[163];
      break;
      
    case 0x2003:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[164];
      else
	tab = &RvlcDCT3Dtab1[164];
      break;
      
    case 0x2ffc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[76];
      else
	tab = &RvlcDCT3Dtab1[47];
      break;
      
    case 0x2ffd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[81];
      else
	tab = &RvlcDCT3Dtab1[59];
      break;
      
    case 0x37fc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[89];
      else
	tab = &RvlcDCT3Dtab1[81];
      break;
      
    case 0x37fd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[95];
      else
	tab = &RvlcDCT3Dtab1[101];
      break;
      
    case 0x3bfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[102];
      else
	tab = &RvlcDCT3Dtab1[102];
      break;
      
    case 0x3bfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[112];
      else
	tab = &RvlcDCT3Dtab1[112];
      break;
      
    case 0x3dfc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[115];
      else
	tab = &RvlcDCT3Dtab1[115];
      break;
      
    case 0x3dfd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[137];
      else
	tab = &RvlcDCT3Dtab1[137];
      break;
      
    case 0x3efc:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[165];
      else
	tab = &RvlcDCT3Dtab1[165];
      break;
      
    case 0x3efd:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[166];
      else
	tab = &RvlcDCT3Dtab1[166];
      break;
      
    case 0x3f7c:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[167];
      else
	tab = &RvlcDCT3Dtab1[167];
      break;
      
    case 0x3f7d:
      if (intra_luma)
	tab = &RvlcDCT3Dtab0[168];
      else
	tab = &RvlcDCT3Dtab1[168];
      break;

    default:  
      if (!QUIET)
        fprintf (stderr, "Invalid Huffman code in RvlcDecTCOEF().\n");
      *error_flag = 1;
      return tcoef;
      break;
    }



    BitstreamFlushBits (stream, tab->len);
    BitstreamTraceVLC(*tab , "VLC 3D", trace);

    if (intra_luma == 0) {		
	tcoef.run = (tab->val >> 8) & 255;
	tcoef.level = tab->val & 255;
	tcoef.last = (tab->val >> 16) & 1;
    }
    else {
	tcoef.run = (tab->val >> 8) & 255;
	tcoef.level = tab->val & 255;
	tcoef.last = (tab->val >> 16) & 1;
    }      


    if (tab->val == ESCAPE)	/* ESCAPE */
    {
      
        BitstreamFlushBits(stream, 1);
        tcoef.last = BitstreamReadBits (stream, 1, "LAST", trace, MARK);
	tcoef.run = BitstreamReadBits (stream, 6, "RUN", trace, NUM);
	tcoef.level = BitstreamReadBits (stream, 7, "LEVEL", trace, NUM);
	tcoef.sign = BitstreamReadBits (stream, 5, "SIGN", trace, CODE);
	
    }
    else
    {
        tcoef.sign = BitstreamReadBits (stream, 1, "SIGN", trace, CODE);        
        if(trace->trace)
            fprintf(trace->fp_trace, "  >> Run: %3d -- Level: %- 4d\n", tcoef.run, tcoef.level*(1 - 2*tcoef.sign));
    }

    if(trace->trace)
	if(tcoef.last)
	    fprintf(trace->fp_trace, "----------\n");
  
    
 
    return tcoef;

}				/* RvlcDecTCOEF */

