/******************************************************************************
 *                                                                           
 * This software module was originally developed by 
 *
 * Cor Quist (KPN / ACTS-MoMuSys).     			              	
 *
 * and edited by 
 *
 * Robert Danielsen (Telenor / ACTS-MoMuSys). 	    	              	
 * Jan De Lameillieure (HHI / ACTS-MoMuSys).     	              	
 * Fernando Jaureguizar (UPM / ACTS-MoMuSys).   	              	
 * Ferran  Marques (UPC / ACTS-MoMuSys).   	  	               	
 * Minhua Zhou (HHI / ACTS-MoMuSys).   	  	 	              	
 * J. Ignacio Ronda (UPM / ACTS-MoMuSys).   	  	              	
 * Noel Brady (TELTEC IRELAND / ACTS-MoMuSys).                   	
 * Ulrike Pestel (TUH / ACTS-MoMuSys).   	  	              	
 * Cecile Dufour (LEP / ACTS-MoMuSys).     		              	
 * Martina Eckert (UPM / ACTS-MoMuSys).   
 * Bob Eifrig (NextLevel Systems)
 * Claudia Billotet-Hoffmann (T-Berkom / 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) 1997
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                          
 * File:        text_code.c
 *
 * Author:      Cor Quist
 * Created:     March 6-96
 *                                                                          
 * Description: 
 *
 * Notes: 
 *
 * Modified:
 *     11.04.96 Cor Quist
 *     16.04.96 Cor Quist
 *     21.04.96 Robert Danielsen: Reformatted. New headers.
 *     07.06.96 Robert Danielsen: Changed from using Encode to Putxxx
 *              instead, based on new VLC encoding scheme.
 *     13.06.96 Cor Quist: Bug fixes for combined encoding
 *     03.09.96 Cor Quist, Jan de Lameillieure and Fernando (UPM):
 *              - remove OLDINTRADC, use variable intra_dcpred_disable
 *              - use new padding functions
 *              - add combined shape motion texture coding
 *     18.09.96 Fernando Jaureguizar: Now new B_TRANSP and MB_TRANSP defines
 *              are in mot_util.h.
 *     23.10.96 Robert Danielsen: Added DC/AC prediction.
 *              Two new functions: doDCACprediction() and nullfill().
 *     28.11.96 Ferran Marques: modifications to allow both block-based and 
 *              macroblock-based subsampling of the alpha plane (22.10.96)
 *     17-Jan-97 Jan De Lameillieure: correction in Bits_CountMB_combined(): no
 *              ACpred_flag in combined mode when intra_acdc_pred_disable
 *              is true 
 *     18-Jan-97 Jan De Lameillieure: PutRestMMR() and CodeGreyLevelAlphaAB()
 *              moved after Bits_CountMB_combined() in
 *              VopCodeShapeTextIntraCom() 
 *     22-Jan-97 Jan De Lameillieure (HHI) : copied the mot. comp. of alpha
 *              plane from separate mode encoder
 *     03-Feb-97 Aasmund Sandvand: updates caused by moving deblocking filter 
 *              out of loop
 *     04.02.97 Noel O'Connor: removed all calls to assert()
 *     11.02.97 J. Ignacio Ronda: modifications to allow VM5 rate control
 *     21.03.97 C. Dufour: online sprite modifications
 *     21-APR-97 Jan De Lameillieure : called grey level alpha coding with the 
 *              grey level (GL) quantiser
 *     27.04.97 Luis Ducla-Soares: Added MBShapeMotTextErrRes(), 
 *                                 MBCodeShapeTextIntraComErrRes() and 
 *                                 Bits_CountMB_combined_ErrRes().
 *     07.07.97 Noel Brady: VM7 shape coding modifications
 *     14.05.97 F. Jaureguizar: new commentaries about new enlarged
 *             f_code range according to VM7.0
 *             Modification in send_vector() function to cope with
 *             enlarged f_code range.
 *     15.05.97 Luis Ducla-Soares: corrected the remultiplexing of the DCT data
 *                                  in the combined error resilient mode with 
 *                                  data partitioning.
 *     16.06.97 Angel Pacheco: unified the TRANSPARENT modes, added some calls
 *              to subsample_alpha_with modes.
 *     07.07.97 Martina Eckert: Introduction of global rate control 
 *              functions and parameters
 *     17.07.97 Ulrike Pestel: for spatial scal
 *     30.07.97 Fernando Jaureguizar: modifications for spatial scal (SpSc)
 *     04.08.97 Minhua Zhou: renamed advanced_prediction_disable
 *     04.08.97 Minhua Zhou: added switching between DC intra VLC and AC intra
 *                           VLC for Intra DC Coefficient 
 *     12.08.97 Minhua Zhou: added PSEDUO_RATE_CONTROL in combined mode
 *     27.11.97 M. Eckert: Changes for independent frame type rate control
 *     27.01.98 M. Eckert and F Jaureguizar: Updated the RC_QuantAdjust() call.
 *              Some _RC_DEBUG_ printing.
 *              New vol_config parameter in VopCodeTextInter()
 *     7. 3. 98 C.Billotet-Hoffmann: cleaning
 *
 ***********************************************************HeaderEnd*********/

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

#include <stdlib.h>

#include "momusys.h"
#include "vm_config.h"
#include "text_defs.h"
#include "text_util.h"
#include "mot_comp.h"
#include "mom_access.h"
#include "mom_bitstream_i.h"
#include "putvlc.h"
#include "mot_util.h"
#include "mom_vop.h"
#include "mot_padding.h"
#include "mot_est.h"
#include "text_code_mb.h"
#include "text_code.h"
#include "alp_code_grey.h"
#include "rc.h"
#include "rc_mvo.h"
#include "alp_code_mom.h"
#include "vlc.h"
#include "io_generic.h"
#include "tm5rc.h"
#include "meitca_wrapper.h"
#include "sait_rc.h"

#define SKIPP 		6
#define VM5_DEBUG_
#ifdef _PRINT_FILES_
#include "io_generic.h"
#endif


/* inserted by Mistubishi & SAMSUNG AIT */
extern Int FirstInterFrame;
extern Int QSTEP[20];
/* inserted by Mistubishi & SAMSUNG AIT */

/***********************************************************CommentBegin******
 *
 * -- VopCodeShapeTextIntraCom --Intra texture encoding of one vop,
 *                          Combined shape/(motion)/texture mode
 *
 * Author :  Cor Quist (KPN)		
 *	     Jan De Lameillieure (HHI)
 *
 * Created :	11-June-1996	
 *	
 *
 * Purpose :		
 *	Intra texture encoding of one vop (combined shape/(mot)/text mode)
 * 
 * Arguments in : 	
 *	    Vop curr : the current vop to be coded
 *      Int intra_dcpred_disable : disable intradc prediction
 *      Image* AB_SizeConversionDecisions: 
 *      Image* AB_first_MMR_values 
 *      VolConfig *vol_config : configuration information
 *      Int rc_type : rate control type:
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	    Vop *rec_curr : the reconstructed current vop
 * 	    Image *texture_bitstream : the output bitstream
 *      Bits : statistics information
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	This function performs Intra texture encoding of one vop.
 *
 * See also :
 *	
 *
 * Modified :		
 *	23.08.96 Robert Danielsen: Removed coding of transparent blocks
 * 	03.09.96 Cor Quist: improved padding, adding MMR codes
 * 	04.09.96 Cor Quist: added intra_dcpred_disable
 *	23.10.96 Robert Danielsen: Removed passing of intra_dcpred_disable,
 *		   	using parameter in Vop-structure instead.
 *			   Added DC/AC prediction.
 *	05-Nov-96 Jan De Lameillieure : PutRestMMR should have curr and not
 *	         rec_curr as argument
 *	28.11.96 Robert Danielsen: Updating CBP in DCACpred().
 * 	18-Jan-97 Jan De Lameillieure : PutRestMMR() and CodeGreyLevelAlphaAB()
 *          moved after Bits_CountMB_combined()
 * 	10.02.97 Fernando Jaureguizar: error corrected: GetVopIntraQuantizer()
 *          instead of GetVopQuantizer()
 * 	21-APR-97 Jan De Lameillieure : called grey level alpha coding with the 
 *          grey level (GL) quantiser
 * 	07.07.97 Noel Brady : mods to write VM7 shape coding elements to the 
 *			      bitstream.
 * 	06.08.97 Noel Brady : mods added for BINARY_SHAPE_ONLY mode
 *      04.11.97 Minhua Zhou: updated DC/AC prediction
 * 	11.12.97 Bob Eifrig: support for interlaced video coding
 *
 ***********************************************************CommentEnd********/

Void VopCodeShapeTextIntraCom(Vop *curr, 
			      Image **First_stream,
			      Image **Shape_stream,
			      Image *GreyLevelAlpha,
			      Image *MotionCompensatedGreyLevelAlpha,
			      Image *ReconstructedGreyLevelAlpha,
			      Vop *rec_curr, Image *mottext_bitstream,
			      Bits *bits,
			      Int rc_type, 
			      Int vo_id, /* hjlee */
			      VolConfig *vol_config)
{
  Int QP = GetVopIntraQuantizer(curr);
  Int Mode = MODE_INTRA;
  Macroblock* mblock; 
  Int* qcoeff;
  SInt p;
  SInt *ptr;
  SInt *alpha_rec;
  SInt *alpha_sub;
  Int i, j;
  Int CBP, COD;
  Int CBPY, CBPC;
  Int num_pixels = GetImageSizeX(GetVopY(curr));
  Int num_lines = GetImageSizeY(GetVopY(curr));
  Int vop_type;
  Image *MB_decisions;
  Image *alpha_decisions;
  Int MB_transp_pattern[4];
  Int ***DC_store;
  Int MB_width = num_pixels / MB_SIZE;
  Int MB_height = num_lines / MB_SIZE;
  Int m, n;
  Int ACpred_flag=-1;
  Int direction[6];
  Int block;
  SInt *QP_store;
  Int switched=0;
  Int DQUANT =0;
  Int	FieldDCT;
  /* For Low latency SPRITE PIECES */	
  Int	*tab_transmit	= GetVopSpriteTabTransmit(curr); 
  Int	numblocks_x	= GetVopSpriteHdim(curr)/16;
  SInt	*tab_QP_store	= GetVopSpriteTabQPStore(curr);
  Int	*tab_DQUANT_store = GetVopSpriteTabDQUANTStore(curr);
  Int	QP_prev;

#ifdef _RC_DEBUG_
  printf("RC - VopCodeShapeTextIntraCom(): ---> CODING WITH: %d \n",QP);
#endif

  QP_store = (SInt *) GetImageData(GetVopQP(rec_curr));
  QP_prev = QP;

  for (i = 0; i < 6; i++) 
    direction[i] = 0;

  /* allocate space for 3D matrix to keep track of prediction values
     for DC/AC prediction */
    
  DC_store = (Int ***)calloc(MB_width*MB_height, sizeof(Int **));
  for (i = 0; i < MB_width*MB_height; i++)
    {
      DC_store[i] = (Int **)calloc(6, sizeof(Int *));
      for (j = 0; j < 6; j++)
	DC_store[i][j] = (Int *)calloc(15, sizeof(Int));
    }
  mblock = (Macroblock *) malloc (sizeof (Macroblock));
  
  alpha_decisions = AllocImage(num_pixels/8,num_lines/8,SHORT_TYPE);
  MB_decisions  = AllocImage(num_pixels/16, num_lines/16, SHORT_TYPE);
    
  Bits_Reset (bits);
  vop_type = PCT_INTRA;

  alpha_rec = (SInt *) GetImageData(GetVopA(rec_curr));

  FillMB_decisions(alpha_rec, num_pixels, num_lines, MB_decisions,
		   alpha_decisions);
  if (GetVopArbitraryShape(curr))
    {
      TexturePadding(rec_curr, alpha_decisions, MB_decisions, curr);
    }

  ptr = (SInt *) GetImageData(MB_decisions);

  /* Angel Pacheco (UPM) : correct dimensions */
  alpha_sub = (SInt *) malloc (num_pixels/B_SIZE * num_lines/B_SIZE * 
			       sizeof (SInt));
  /* Angel Pacheco (UPM) 10.06.97: subsampled alpha plane updated wit the right modes */
  subsamp_alpha_with_modes (alpha_rec, ptr, num_pixels, num_lines, alpha_sub);
     
  for (j = 0; j < num_lines/MB_SIZE; j++) /* Macro Block loop */
    {
      for (i = 0; i < num_pixels/MB_SIZE; i++)
	{
	  switched=0;
	  if (GetVopArbitraryShape(curr) )
	    {
	      if (GetVopSpriteUsage(curr)!=STATIC_SPRITE||
		  GetVopLowLatencySpriteEnable(curr)==0 ||
		  (GetVopLowLatencySpriteEnable(curr)&&
		     tab_transmit[j*numblocks_x+i] == 1))
		{
		  /* write the first_shape_code for this Macroblock to the bit stream */
		  BitstreamAppend(First_stream[j*(num_pixels/MB_SIZE)+i],
				  mottext_bitstream);
		  /* shape data (except first_shape_code) */
		  BitstreamAppend(Shape_stream[j*(num_pixels/MB_SIZE)+i],
				  mottext_bitstream);
		}
	    }
	  p = *ptr;
	  ptr++;

	  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
	    QP = GetMBQuant(vo_id, j*MB_width+i); 

	  if (GetVopShape(curr) != BINARY_SHAPE_ONLY) /* BSO_NOEL */
	    {				
	      /* Store the QP value for later use in AC prediction */
	      QP_store[j*MB_width+i] = (SInt) QP;
		
	      GetTranspPattern (alpha_sub, num_pixels, num_lines,
				i, j, MB_transp_pattern);

	      if ( p == 2)	/* transparent macroblock */
		{
		  CBP = 0;	/* no texture data */
		  /* Fill DC_store with default coeff values */
		  for (m = 0; m < 6; m++)
		    {
		      DC_store[j*MB_width+i][m][0] = GetVopMidGrey(curr)*8;
		      for (n = 1; n < 15; n++)
			DC_store[j*MB_width+i][m][n] = 0;
		    }
		}
	      else		/* normal macroblock */
		{
		  if ((rc_type >= TM5_RATE_CONTROL) && (vol_config != NULL)) { 
                    DQUANT = tm5rc_calc_mquant(j*MB_width+i, mottext_bitstream->x, vol_config->rcdata) - QP;
                    if (DQUANT >  2) DQUANT =  2;
                    if (DQUANT < -2) DQUANT = -2;
		  } else
		    if ((i==0)&&(j==0)) DQUANT=0;
		    else DQUANT =cal_DQuant(QP,I_VOP); 


		  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS)
		    DQUANT = GetDquant(QP, QP_prev, I_VOP);

		  if (GetVopSpriteUsage(curr)==STATIC_SPRITE &&
		  	GetVopLowLatencySpriteEnable(curr) )
		    if (tab_transmit[j*numblocks_x+i] > 1)
		      /* one mimics how the block was encoded in a previous object piece */
		      /* to get DC_store correctly*/
		      {
			QP_prev = QP;
			QP = tab_QP_store[j*numblocks_x+i];
			DQUANT = tab_DQUANT_store[j*numblocks_x+i];
		      }	     

		  QP_store[j*MB_width+i] = (SInt) (QP+DQUANT);

		  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
		    QP_store[j*MB_width+i] = (SInt) (QP_prev+DQUANT); 

		  if (GetVopSpriteUsage(curr)==STATIC_SPRITE &&
		  	GetVopLowLatencySpriteEnable(curr))
		    if (tab_transmit[j*numblocks_x+i]== 1)
		    {
		      tab_QP_store[j*numblocks_x+i] = (SInt) QP;
		      tab_DQUANT_store[j*numblocks_x+i] = DQUANT;
		    }

		  COD = 0;
		  bits->no_intra++;

		  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
		    qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
				     num_pixels, QP_prev+DQUANT, MODE_INTRA, MB_transp_pattern,
				     &FieldDCT);
		  else
		    qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
				     num_pixels, QP+DQUANT, MODE_INTRA, MB_transp_pattern,
				     &FieldDCT);
 
#ifdef DEBUG_COMBINED
		  /* test print for JDL 18-Jan-97 */
		  printf("qcoeff of MB (%d,%d)    MB_transp_pattern = (%d,%d,%d,%d)\n",i,j,
			 MB_transp_pattern[0], MB_transp_pattern[1], MB_transp_pattern[2], MB_transp_pattern[3]);
		  for (m=0;m<6;m++) {
		    for (n=0;n<64;n++) {
		      printf(" %3d", qcoeff[m*64+n]);
		      if ((n+1)%8 ==0) printf("\n");
		    }
		    printf("\n");
		  }
#endif

		  /* Store the qcoeff-values needed later for prediction */
		  m =0;

		  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) { 
		    DC_store[j*MB_width+i][0][m] = qcoeff[m]*cal_dc_scaler(QP_prev+DQUANT,1);
		    DC_store[j*MB_width+i][1][m] = qcoeff[m+64]*cal_dc_scaler(QP_prev+DQUANT,1);
		    DC_store[j*MB_width+i][2][m] = qcoeff[m+128]*cal_dc_scaler(QP_prev+DQUANT,1);
		    DC_store[j*MB_width+i][3][m] = qcoeff[m+192]*cal_dc_scaler(QP_prev+DQUANT,1);
		    DC_store[j*MB_width+i][4][m] = qcoeff[m+256]*cal_dc_scaler(QP_prev+DQUANT,2);
		    DC_store[j*MB_width+i][5][m] = qcoeff[m+320]*cal_dc_scaler(QP_prev+DQUANT,2);
		  }
		  else 


		    {
		      DC_store[j*MB_width+i][0][m] = qcoeff[m]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_width+i][1][m] = qcoeff[m+64]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_width+i][2][m] = qcoeff[m+128]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_width+i][3][m] = qcoeff[m+192]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_width+i][4][m] = qcoeff[m+256]*cal_dc_scaler(QP+DQUANT,2);
		      DC_store[j*MB_width+i][5][m] = qcoeff[m+320]*cal_dc_scaler(QP+DQUANT,2);
		    }
		  for (m = 1; m < 8; m++)
		    {
		      DC_store[j*MB_width+i][0][m] = qcoeff[m];
		      DC_store[j*MB_width+i][1][m] = qcoeff[m+64];
		      DC_store[j*MB_width+i][2][m] = qcoeff[m+128];
		      DC_store[j*MB_width+i][3][m] = qcoeff[m+192];
		      DC_store[j*MB_width+i][4][m] = qcoeff[m+256];
		      DC_store[j*MB_width+i][5][m] = qcoeff[m+320];
		    }
		  for (m = 0; m < 7; m++)
		    {
		      DC_store[j*MB_width+i][0][m+8] = qcoeff[(m+1)*8];
		      DC_store[j*MB_width+i][1][m+8] = qcoeff[(m+1)*8+64];
		      DC_store[j*MB_width+i][2][m+8] = qcoeff[(m+1)*8+128];
		      DC_store[j*MB_width+i][3][m+8] = qcoeff[(m+1)*8+192];
		      DC_store[j*MB_width+i][4][m+8] = qcoeff[(m+1)*8+256];
		      DC_store[j*MB_width+i][5][m+8] = qcoeff[(m+1)*8+320];
		    }
		    
		  /* overwrite the DC_store with QDC = 128 for transparent
		     blocks, Noel Brady (Dec 13 1996) */ 

		  for (block=0;block<4;block++) 
		    if (MB_transp_pattern[block])
		      DC_store[j*MB_width+i][block][0] = GetVopMidGrey(curr)*8;

		  CBP = FindCBP(qcoeff,Mode,64);
	      
		  /* Do the DC/AC prediction, changing the qcoeff values as
		     appropriate */
		  if (GetVopIntraACDCPredDisable(curr) == 0) {

		    if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
		      ACpred_flag = doDCACpred(qcoeff, &CBP, 64, i, j, DC_store,
					       QP_store, QP_prev+DQUANT, MB_width, 
					       direction,GetVopMidGrey(curr));
		    else
		      ACpred_flag = doDCACpred(qcoeff, &CBP, 64, i, j, DC_store,
					       QP_store, QP+DQUANT, MB_width,
					       direction,GetVopMidGrey(curr));
		  }
		  else
		    ACpred_flag = -1; 
  
		  /* added by Minhua Zhou 04.08.97 */
		  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
		    switched = IntraDCSwitch_Decision(Mode,
						      GetVopIntraDCVlcThr(curr),
						      QP_prev+DQUANT); 
		  else

		    switched = IntraDCSwitch_Decision(Mode,
						      GetVopIntraDCVlcThr(curr),
						      QP);
		  if (switched) 
		    CBP = FindCBP(qcoeff,MODE_INTER,64);
		  if (DQUANT) Mode=MODE_INTRA_Q;else Mode=MODE_INTRA;

		  if (GetVopSpriteUsage(curr)==STATIC_SPRITE &&
		  	GetVopLowLatencySpriteEnable(curr) )
		    if (tab_transmit[j*numblocks_x+i] > 1)
		      {
			/* Dont modify the Quant if a block already transmitted is encountered */
			QP = QP_prev;
			DQUANT = 0;
		      }


		  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS)
		    QP_prev = QP_prev+DQUANT; 
		  else
		    QP+=DQUANT;
                     
		  CBPY = CBP >> 2;
		  CBPY = CBPY & 15; /* last 4 bits */
		  CBPC = CBP & 3; /* last 2 bits */

	          if (GetVopSpriteUsage(curr)!=STATIC_SPRITE||
		      GetVopLowLatencySpriteEnable(curr)==0 ||
		      (GetVopLowLatencySpriteEnable(curr)&&
		        tab_transmit[j*numblocks_x+i] == 1))
		    {
		      Bits_CountMB_combined (DQUANT, Mode, COD, ACpred_flag, CBP, 
					     vop_type, 
					     bits, mottext_bitstream,MB_transp_pattern);
		      if (curr->interlaced) {
			bits->fieldDCT += FieldDCT;
			BitstreamPutBits(mottext_bitstream, FieldDCT, 1);
			bits->interlaced++;
		      }
		    }				     
				     

		  if (GetVopArbitraryShape(curr) )
		    {
		      if (!GetVopBinaryShape(curr) )
			CodeGreyLevelAlphaAB(curr,i,j,
					     GetVopGLQuantizer(curr), /* correction JDL 21-APR-97 */
					     MB_decisions,
					     GreyLevelAlpha,
					     MotionCompensatedGreyLevelAlpha,
					     ReconstructedGreyLevelAlpha,
					     mottext_bitstream);
		    }

		  /* added the variable intra_dcpred_diable */

	          if (GetVopSpriteUsage(curr)!=STATIC_SPRITE||
		      GetVopLowLatencySpriteEnable(curr)==0 ||
		      (GetVopLowLatencySpriteEnable(curr)&&
		        tab_transmit[j*numblocks_x+i] == 1))
		    {
		      MB_CodeCoeff(bits, qcoeff, Mode, CBP, 64,
				   GetVopIntraACDCPredDisable(curr),
				   NULL, mottext_bitstream,
				   MB_transp_pattern, direction, 
				   GetVopErrorResDisable(curr),
				   GetVopReverseVlc(curr),switched,
				   curr->alternate_scan);
		    }

		  free ((Char*)qcoeff);
		} /* BSO_NOEL */
	    }
	}
    }

  /* Free allocated memory for 3D matrix */
    
  for (i = 0; i < MB_width*MB_height; i++)
    {
      for (j = 0; j < 6; j++)
	free(DC_store[i][j]);
      free(DC_store[i]);
    }
  free(DC_store);

  free((Char*)mblock);
  FreeImage(alpha_decisions);
  FreeImage(MB_decisions);
  free((Char*)alpha_sub);
}

/***********************************************************CommentBegin******
 *
 * -- MBCodeShapeTextIntraComErrRes --Intra texture encoding of one MB,
 *                          Combined error resilient shape/(motion)/texture mode
 *
 * Author : Luis Ducla-Soares (IST) - lds@lx.it.pt
 *	    
 *
 * Created :	27.04.97	
 *	
 *
 * Purpose :		
 *	Intra texture encoding of one MB (error resilient combined shape/(mot)/text mode)
 * 
 * Arguments in : 	
 *	Vop curr : the current vop to be coded
 *      Int intra_dcpred_disable : disable intradc prediction
 *      Image* AB_SizeConversionDecisions: 
 *      Image* AB_first_MMR_values :
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Vop *rec_curr : the reconstructed current vop
 * 	Image *texture_bitstream : the output bitstream
 *  Bits *bits : coding statistics
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	This function performs Intra texture encoding of one MB. This
 *      function is based on VopCodeShapeTextIntraCom()
 *
 * See also :
 *	
 *
 * Modified :		
 *      15.05.97 Luis Ducla Soares: corrected the remultiplexing of the DCT  data 
 *                                  in the combined error resilient mode with data 
 *                                  partitioning.
 *
 *      04.11.97 Minhua Zhou: updated DC/AC prediction
 *	08.11.97 Noel Brady: Corrected operation for shape info. and added
 *			     support for binary_shape_only mode.
 *      11.12.97 Bob Eifrig: support for interlaced video coding
 *
 ***********************************************************CommentEnd********/

Void MBCodeShapeTextIntraComErrRes(Vop *curr, 
				   Image **First_stream,
				   Image **Shape_stream,
				   Image *GreyLevelAlpha,
				   Image *MotionCompensatedGreyLevelAlpha,
				   Image *ReconstructedGreyLevelAlpha,
				   Vop *rec_curr,
				   Image *motion_comb_bitstream,
				   Image *text_header_comb_bitstream,
				   Image *text_data_comb_bitstream,
				   Int i, Int j, Int *num_bits_MB_ptr,
				   Int ***DC_store,
				   Int **slice_nb,
				   Bits *bits)
{
  Int QP = GetVopIntraQuantizer(curr);
  Int Mode = MODE_INTRA;
  Macroblock* mblock; 
  Int* qcoeff;
  SInt p;
  SInt *ptr;
  SInt *alpha_rec;
  SInt *alpha_sub;
  Int k;
  Int CBP, COD;
  Int CBPY, CBPC;
  Int num_pixels = GetImageSizeX(GetVopY(curr));
  Int num_lines = GetImageSizeY(GetVopY(curr));
  Int vop_type;
  Image *MB_decisions;
  Image *alpha_decisions;
  Int MB_transp_pattern[4];
  /*Int ***DC_store;*/
  Int MB_width = num_pixels / MB_SIZE;
  Int m, n;
  Int ACpred_flag=-1;
  Int direction[6];
  Int block;
  SInt *QP_store;
  Int switched=0;
  Int shape_bits=0,
  tmp_bits;

#ifdef _RC_DEBUG_
  printf("RC - MBCodeShapeTextIntraComErrRes(): ---> CODING WITH: %d \n",QP);
#endif
  
  QP_store = (SInt *) GetImageData(GetVopQP(rec_curr));
  for (k = 0; k < 6; k++) 
    direction[k] = 0;
  
  mblock = (Macroblock *) malloc (sizeof (Macroblock));
  
  alpha_decisions = AllocImage(num_pixels/8,num_lines/8,SHORT_TYPE);
  MB_decisions  = AllocImage(num_pixels/16, num_lines/16, SHORT_TYPE);
  
  Bits_Reset (bits);
  vop_type = PCT_INTRA;
  
  alpha_rec = (SInt *) GetImageData(GetVopA(rec_curr));
  
  FillMB_decisions(alpha_rec, num_pixels, num_lines, MB_decisions,
		   alpha_decisions);
  if (GetVopArbitraryShape(curr))
    {
      TexturePadding(rec_curr, alpha_decisions, MB_decisions, curr);
    }
  
  ptr = (SInt *) GetImageData(MB_decisions);
  
  /* Angel Pacheco (UPM) : correct dimensions */
  alpha_sub = (SInt *) malloc (num_pixels /B_SIZE * num_lines/B_SIZE  * 
			       sizeof (SInt));
  /* Angel Pacheco (UPM) 10.06.97: subsampled alpha plane updated wit the right modes */
  subsamp_alpha_with_modes (alpha_rec, ptr, num_pixels, num_lines, alpha_sub);
  


  if (GetVopArbitraryShape(curr) )
    {
      tmp_bits = GetImageSizeX(motion_comb_bitstream);
      /* write the first_shape_code for this Macroblock to the bit stream */
      BitstreamAppend(First_stream[j*(num_pixels/MB_SIZE)+i],
		      motion_comb_bitstream);
      /* shape data (except first_shape_code) */
      BitstreamAppend(Shape_stream[j*(num_pixels/MB_SIZE)+i],
		      motion_comb_bitstream);
      shape_bits += GetImageSizeX(motion_comb_bitstream) - tmp_bits;
    }

  if (GetVopShape(curr) != BINARY_SHAPE_ONLY) /* BSO_NOEL */
    {				
      p = *(ptr + (j*MB_width+i));

      /* Store the QP value for later use in AC prediction */
      QP_store[j*MB_width+i] = (SInt) QP;
	  
      GetTranspPattern (alpha_sub, num_pixels, num_lines,
			i, j, MB_transp_pattern);
	  
      if ( p == 2)		/* transparent macroblock */
	{
	  CBP = 0;		/* no texture data */
	  /* Fill DC_store with default coeff values */
	  for (m = 0; m < 6; m++)
	    {
	      DC_store[j*MB_width+i][m][0] = GetVopMidGrey(curr)*8;
	      for (n = 1; n < 15; n++)
		DC_store[j*MB_width+i][m][n] = 0;
	    }
	}
      else			/* normal macroblock */
	{
	  COD = 0;
	  bits->no_intra++;
	  qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
			   num_pixels, QP, Mode, MB_transp_pattern, NULL);
	      
#ifdef DEBUG_COMBINED
	  /* test print for JDL 18-Jan-97 */
	  printf("qcoeff of MB (%d,%d)    MB_transp_pattern = (%d,%d,%d,%d)\n",i,j,
		 MB_transp_pattern[0], MB_transp_pattern[1], MB_transp_pattern[2], MB_transp_pattern[3]);
	  for (m=0;m<6;m++) {
	    for (n=0;n<64;n++) {
	      printf(" %3d", qcoeff[m*64+n]);
	      if ((n+1)%8 ==0) printf("\n");
	    }
	    printf("\n");
	  }
#endif
	      
	  /* Store the qcoeff-values needed later for prediction */
	  m =0;
	  DC_store[j*MB_width+i][0][m] = qcoeff[m]*cal_dc_scaler(QP,1);
	  DC_store[j*MB_width+i][1][m] = qcoeff[m+64]*cal_dc_scaler(QP,1);
	  DC_store[j*MB_width+i][2][m] = qcoeff[m+128]*cal_dc_scaler(QP,1);
	  DC_store[j*MB_width+i][3][m] = qcoeff[m+192]*cal_dc_scaler(QP,1);
	  DC_store[j*MB_width+i][4][m] = qcoeff[m+256]*cal_dc_scaler(QP,2);
	  DC_store[j*MB_width+i][5][m] = qcoeff[m+320]*cal_dc_scaler(QP,2);

	  for (m = 1; m < 8; m++)
	    {
	      DC_store[j*MB_width+i][0][m] = qcoeff[m];
	      DC_store[j*MB_width+i][1][m] = qcoeff[m+64];
	      DC_store[j*MB_width+i][2][m] = qcoeff[m+128];
	      DC_store[j*MB_width+i][3][m] = qcoeff[m+192];
	      DC_store[j*MB_width+i][4][m] = qcoeff[m+256];
	      DC_store[j*MB_width+i][5][m] = qcoeff[m+320];
	    }
	  for (m = 0; m < 7; m++)
	    {
	      DC_store[j*MB_width+i][0][m+8] = qcoeff[(m+1)*8];
	      DC_store[j*MB_width+i][1][m+8] = qcoeff[(m+1)*8+64];
	      DC_store[j*MB_width+i][2][m+8] = qcoeff[(m+1)*8+128];
	      DC_store[j*MB_width+i][3][m+8] = qcoeff[(m+1)*8+192];
	      DC_store[j*MB_width+i][4][m+8] = qcoeff[(m+1)*8+256];
	      DC_store[j*MB_width+i][5][m+8] = qcoeff[(m+1)*8+320];
	    }
	      
	  /* overwrite the DC_store with QDC = 128 for transparent
	     blocks, Noel Brady (Dec 13 1996) */ 
	      
	  for (block=0;block<4;block++) 
	    if (MB_transp_pattern[block])
	      DC_store[j*MB_width+i][block][0] = GetVopMidGrey(curr)*8;
	      
	  CBP = FindCBP(qcoeff,Mode,64);
	      
	  /* Do the DC/AC prediction, changing the qcoeff values as
	     appropriate */
	  if (GetVopIntraACDCPredDisable(curr) == 0)
	    ACpred_flag = doDCACpredErrRes(qcoeff, &CBP, 64, i, j, DC_store,
					   QP_store, QP, MB_width,
					   direction, slice_nb,GetVopMidGrey(curr));
	  else
	    ACpred_flag = -1; 
	  /* added by Minhua Zhou 04.08.97 */
	  switched = IntraDCSwitch_Decision(Mode,
					    GetVopIntraDCVlcThr(curr),
					    QP);
	  if (switched) 
	    CBP = FindCBP(qcoeff,MODE_INTER,64);
	      
	  CBPY = CBP >> 2;
	  CBPY = CBPY & 15;	/* last 4 bits */
	  CBPC = CBP & 3;	/* last 2 bits */
	      
	  Bits_CountMB_combined_ErrRes (Mode, COD, ACpred_flag, CBP, 
					vop_type, bits,
					motion_comb_bitstream, 
					text_header_comb_bitstream,
					MB_transp_pattern);
	      
	      
	  if (GetVopArbitraryShape(curr) )
	    {
	      if (!GetVopBinaryShape(curr) )
		CodeGreyLevelAlphaAB(curr,i,j,
				     GetVopGLQuantizer(curr), /* correction JDL 21-APR-97 */
				     MB_decisions,
				     GreyLevelAlpha,
				     MotionCompensatedGreyLevelAlpha,
				     ReconstructedGreyLevelAlpha,
				     motion_comb_bitstream);
	    }
	      
	  /* added the variable intra_dcpred_diable */
	      
	  MB_CodeCoeff(bits, qcoeff, Mode, CBP, 64,
		       GetVopIntraACDCPredDisable(curr),
		       motion_comb_bitstream, 
		       text_data_comb_bitstream,
		       MB_transp_pattern, direction, 
		       GetVopErrorResDisable(curr),
		       GetVopReverseVlc(curr),switched, 0);
	      
	  free ((Char*)qcoeff);
	}
    } /* BSO_ONLY */ 

  *num_bits_MB_ptr = shape_bits + bits->COD + bits->MCBPC + bits->CBPY +
    bits->ACpred_flag + bits->DQUANT + bits->Y + bits->C;

  free((Char*)mblock);
  FreeImage(alpha_decisions);
  FreeImage(MB_decisions);
  free((Char*)alpha_sub);
}



/***********************************************************CommentBegin******
 *
 * -- VopCodeShapeMotTextInter -- Combined inter texture/motion encoding of one Vop
 *
 * Author : Cor Quist (KPN)		
 *	
 *
 * Created :		
 *	
 *
 * Purpose :		
 *	Combined inter texture/motion encoding of one Vop.
 * 
 * Arguments in : 	
 *	Vop *curr : the current vop to be encoded
 *      Image* AB_SizeConversionDecisions: 
 *      Image* AB_first_MMR_values :
 * 	Vop *rec_prev: the previous reconstructed vop
 * 	Image *mot_x : the x-coordinates of the motion vectors
 * 	Image *mot_y : the y-coordinates of the motion vectors
 * 	Image *alpha_sub_pad : ?
 * 	Image *alpha_decisions : ?
 *	Int alpha_th : threshold for lossy alpha coding (0-lossless)
 * 	Image *MB_decisions: Contains for each macroblock the encoding mode
 *      Int   f_code_for: MV search range 1/2 pel: 1=32,2=64,...,7=2048
 *      Int intra_dcpred_disable : disable the intradc prediction
 *	VOConfig *vo_config_list : VO configuration list
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Vop *rec_curr : the reconstructed current vop
 * 	Image *mottext_bitstream : the output texture/motion bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :
 *	03.09.96 Cor Quist: Added shape to the function name and plot_buf_test

 *                          Added function to write the shape codewords
 *      04.09.96 Cor Quist: Added intra_dcpred_disable
 *	23.10.96 Robert Danielsen: Removed intra_dcpred_disable, get it
 *			from Vop-structure instead.
 *      06-Nov-96 Jan De Lameillieure : added alpha_th as argument
 *      06-Nov-96 Jan De Lameillieure : removed clamping after motion
 *		compensated prediction of alpha plane (obsolete since VM4.0)
 *      22-Jan-97 Jan De Lameillieure (HHI) : copied the mot. comp. of alpha plane
 *              from separate mode encoder
 *      25-Jan-97 Jan De Lameillieure (HHI) : added debug statements for inter shape coding
 *      21.03.97 C. Dufour: online sprite modifications
 *      07.07.97 Martina Eckert: Introduction of global rate control 
 *               functions and parameters
 *			06.08.97 Noel Brady: Added mods for BINARY_SHAPE_ONLY
 *      04.11.97 Minhua Zhou: updated DC/AC prediction
 *      27.11.97 M. Eckert: Changes for independent frame rate type control
 *      11.12.97 Bob Eifrig: support for interlaced video coding
 *
 ***********************************************************CommentEnd********/
 
Void VopCodeShapeMotTextInter(Vop *curr, Image **First_stream,
			      Image **Shape_stream,
			      Image *GreyLevelAlpha,
			      Image *MotionCompensatedGreyLevelAlpha,
			      Image *ReconstructedGreyLevelAlpha,
			      Vop *rec_prev, Vop *next_rec,
			      Image *mot_x, Image *mot_y, 
			      Image *mot_x_P,Image *mot_y_P,
                              Image *MB_decisions_P,
			      Int TRB, Int TRD, 
			      Image *alpha_sub_pad, 
			      Image *alpha_decisions, Image *MB_decisions,
			      Int f_code_for, Int f_code_back,
			      /* RC2 */Int vo_id, Int vol_id, Int rc_type, 
			      VOConfig *vo_config_list, /* UPM Global RC */
			      Vop *rec_curr,
			      /* RC2 */Int *vop_quantizer,
			      Image *mottext_bitstream,
			      Bits *bits,
			      VolConfig *vol_config)
{	
  Vop *error_vop, *comp=NULL, *rec_error=NULL;
  Vop *rec_sprite = NULL;

  UInt num_pixels, num_lines;
  /* RC2: variable mad */
  Float mad=0;
  UInt  num_pels_vop;		/* UPM Global RC - Number of pixels of current VOP */
#ifdef _DEBUG_SPSC2_
  static Int tmp_cnt = 0;
#endif
  Int temp_quantizer=1;

  num_pixels = GetImageSizeX(GetVopY(curr));
  num_lines = GetImageSizeY(GetVopY(curr));
	
  error_vop = AllocVop(num_pixels, num_lines);
  /* Need some fields of current vop when coding error vop
     (specifically the quantizer) */
  CopyVopNonImageField(curr,error_vop);

  if (GetVopShape(curr) != BINARY_SHAPE_ONLY) /* BSO_NOEL */
    {
      comp = CloneVop(rec_curr);
      rec_error = AllocVop(num_pixels, num_lines);

      if (GetVopSpriteUsage(curr)!=SPRITE_NOT_USED)
    	{
	  rec_sprite = GetVopSprite(curr);
    	}

#if 0
      printf("MB_modes\n");
      PrintTextImage(MB_decisions);
      printf("alpha_decisions\n");
      PrintTextImage(alpha_decisions);

      printf("Motion field X\n");
      PrintTextImageF(mot_x);
      printf("Motion field Y\n");
      printf("MB_modes\n");
      PrintTextImageF(mot_y);
#endif


      if (GetVopPredictionType(curr)!=B_VOP) {
	VopMotionCompensate(rec_prev, mot_x, mot_y, MB_decisions, 
			    alpha_decisions, comp,
			    GetVopOBMCDisable(curr),
			    rec_sprite); 

#ifdef _DEBUG_SPSC2_
	if(GetVopScalability(curr)) {
	  /* this part is available at only one enhancement layer */
	  if(tmp_cnt==0 ){    
	    WriteVopGeneric (comp, "Ecomp_vop", "Ecomp_vop", "Ecomp_vop",
			     "up_vop.shape",0, IO_FORMAT, IO_OVERWRITE, 0);
	  }else{
	    WriteVopGeneric (comp, "Ecomp_vop", "Ecomp_vop", "Ecomp_vop",
			     "up_vop.shape",tmp_cnt, IO_FORMAT, IO_APPEND, 0);
	  }
	}
#endif
       
      }
      else  {
        B_VopMotionCompensation(curr,rec_prev,next_rec,
				mot_x, mot_y,
				mot_x_P,mot_y_P,MB_decisions_P,
				MB_decisions,
				alpha_decisions, TRB,TRD, comp);

#ifdef _DEBUG_SPSC2_
	if(GetVopScalability(curr)) {
	  if(tmp_cnt==0 ){    
	    WriteVopGeneric (comp, "Ecomp_vop","Ecomp_vop","Ecomp_vop",
			     "up_vop.shape",0, IO_FORMAT, IO_OVERWRITE, 0);
	  }else{
	    WriteVopGeneric (comp,
			     "Ecomp_vop","Ecomp_vop","Ecomp_vop",
			     "up_vop.shape",tmp_cnt, IO_FORMAT, IO_APPEND, 0);
	  }
	}
#endif

      }

      SubImage(curr->y_chan, comp->y_chan, error_vop->y_chan);
      SubImage(curr->u_chan, comp->u_chan, error_vop->u_chan);
      SubImage(curr->v_chan, comp->v_chan, error_vop->v_chan);

      CopyImage(rec_curr->a_chan, error_vop->a_chan);
      CopyImage(rec_curr->a_chan, rec_error->a_chan);
      CopyImage(rec_curr->a_uv_chan, error_vop->a_uv_chan);
      CopyImage(rec_curr->a_uv_chan, rec_error->a_uv_chan);


      if (GetVopArbitraryShape(curr)) 
	{
	  TexturePadding(error_vop, alpha_sub_pad, MB_decisions, error_vop);
	}


      /* RC2: adding combined mode VM5.0 Rate Control */
      if (rc_type == VM5_RATE_CONTROL)
	{

	  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_ENABLED)
	    ;
	  else {
	    /* ------------------------------------------ */
	    /* SHARP_start                                */
		    
	    temp_quantizer= 0;
	    if (Q2MB_ACTIVE == RCQ2_MB_active(Q2MB_CHECK))
	      {
		/* if the Q2 macroblock rate control is used,
		   must initialize parameters in MB data structure Q2_mb
		   and compute the first QP for the VOP layers */
		temp_quantizer= RCQ2_MB_init(error_vop, 
					     vo_id, vol_id, 
					     num_pixels/MB_SIZE, 
					     num_lines/MB_SIZE);
		if (temp_quantizer != 0)
		  {
		    *vop_quantizer= temp_quantizer;
		    PutVopQuantizer(*vop_quantizer, curr);
		    PutVopQuantizer(*vop_quantizer, error_vop);
		    PutVolConfigQuantizer(*vop_quantizer, vol_config);
		  }
	      }             
		    
	    if (temp_quantizer == 0) /* if no quantizer from Q2
					VM8 macroblock layer rate control
					do default VM5 rate control */
	      {
		/* SHARP_end                                  */
		/* ------------------------------------------ */           
		mad = (Float) DSRC_compute_MAD(error_vop, &num_pels_vop);
	      }
	  }
		  

#ifdef _RC_DEBUG_
	  fprintf(stdout, "RC: combined mode >>>>> mad= %f\n", mad);
#endif


	  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_ENABLED) 
	    /* inserted by Mistubishi & SAMSUNG AIT */
	    {
	      RCQ2_MVO_PreEncoding(error_vop, vo_id);
	      if(FirstInterFrame != 1)
		{
		  *vop_quantizer = QSTEP[vo_id];
		  PutVopQuantizer(*vop_quantizer, error_vop);
		}
	      else {
		*vop_quantizer = 15;  
		PutVopQuantizer(*vop_quantizer, error_vop);
	      }

	      fprintf(stdout,"\t\tInter Quantizer : %d\n", (int)*vop_quantizer);
	    }
	  else
	    {
	      if (temp_quantizer == 0) {
		*vop_quantizer = RC_QuantAdjust(vo_id, vol_id, 
						vo_config_list, 
						vol_config, 
						(Float)mad, 
						curr, 
						error_vop, 
						num_pels_vop,
						GetVopPredictionType(curr));
	      }
		  
	    }
		
		
	  /* RC2 */
	  fprintf(stdout,"\t\tInter Quantizer : %d\n", (int)*vop_quantizer);

#ifdef _RC_DEBUG_
	  fprintf(stdout, "RC: >>>>> New quantizer= %d\n", *vop_quantizer);
#endif
	}
    } /* BSO_NOEL */




  if (GetVopPredictionType(curr)!=B_VOP) {
    /* modified by Mistubishi & SAMSUNG AIT */
    VopShapeMotText(error_vop, alpha_decisions, MB_decisions, 
		    mot_x, mot_y, f_code_for, First_stream, 
		    Shape_stream, GreyLevelAlpha,
		    MotionCompensatedGreyLevelAlpha,
		    ReconstructedGreyLevelAlpha,
		    GetVopIntraACDCPredDisable(curr),rec_error, 
		    mottext_bitstream, bits, vo_id, rc_type, vol_config);
    /* modified by Mistubishi & SAMSUNG AIT */


#ifdef _DEBUG_SPSC2_
    if(GetVopScalability(curr)){
      if(tmp_cnt==0 ){    
        WriteVopGeneric (rec_error, "Erec_vop","Erec_vop","Erec_vop",
                         "up_vop.shape",0, IO_FORMAT, IO_OVERWRITE, 0);
      }else{
        WriteVopGeneric (rec_error,
                         "Erec_vop","Erec_vop","Erec_vop",
                         "up_vop.shape",tmp_cnt, IO_FORMAT, IO_APPEND, 0);
      }
      tmp_cnt++;
    }
#endif

  } else {
    B_VopShapeMotText(error_vop,alpha_decisions, MB_decisions,
		      mot_x, mot_y, f_code_for,f_code_back,
		      First_stream, 
		      Shape_stream, GreyLevelAlpha,
		      MotionCompensatedGreyLevelAlpha,
		      ReconstructedGreyLevelAlpha,rec_error, 
		      mottext_bitstream, bits);

#ifdef _DEBUG_SPSC2_
    if(GetVopScalability(curr)){
      if(tmp_cnt==0 ){    
	WriteVopGeneric (rec_error, "Erec_vop","Erec_vop","Erec_vop",
			 "up_vop.shape",0, IO_FORMAT, IO_OVERWRITE, 0);
      }else{
	WriteVopGeneric (rec_error,
			 "Erec_vop","Erec_vop","Erec_vop",
			 "up_vop.shape",tmp_cnt, IO_FORMAT, IO_APPEND, 0);
      }
      tmp_cnt++;
    }
#endif
  }
  if (GetVopShape(curr) != BINARY_SHAPE_ONLY) /* BSO_NOEL */
    {
	
      AddImage(comp->y_chan, rec_error->y_chan, rec_curr->y_chan);
      AddImage(comp->u_chan, rec_error->u_chan, rec_curr->u_chan);
      AddImage(comp->v_chan, rec_error->v_chan, rec_curr->v_chan);
	
      CopyImage(GetVopQP(rec_error), GetVopQP(rec_curr));
	
      ClipImage (rec_curr->y_chan,GetVopBrightWhite(curr));
      ClipImage (rec_curr->u_chan,GetVopBrightWhite(curr));
      ClipImage (rec_curr->v_chan,GetVopBrightWhite(curr));
	
      FreeVop(comp);
      FreeVop(rec_error);
    } /* BSO_NOEL */

  FreeVop(error_vop);
}

/***********************************************************CommentBegin******
 *
 * -- VopShapeMotText -- Combined Inter encoding of shape motion and texture
 *
 * Author : Cor Quist (KPN)		
 *	
 *
 * Created :		
 *	
 *
 * Purpose :		
 *	Combined Inter encoding of texture and motion.
 * 	Used by VopCodeMotTextInter
 * 
 * Arguments in : 	
 *	Vop *curr : the current vop to be encoded
 * 	Vop *rec_prev: the previous reconstructed vop
 * 	Image *mot_x : the x-coordinates of the motion vectors
 * 	Image *mot_y : the y-coordinates of the motion vectors
 * 	Image *alpha_decisions : ?
 * 	Image *MB_decisions: Contains for each macroblock the encoding mode
 *	Int	f_code_for: MV search range 1/2 pel: 1=32,2=64,...,7=2048
 *      Image* AB_SizeConversionDecisions: 
 *      Image* AB_first_MMR_values :
 *      Int intra_dcpred_disable : disable the intra dc prediction
 *      VolConfig *vol_config : configuration information
 *      Int rc_type : rate control type
 *
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *rec_curr : the reconstructed current vop
 * 	Image *mottext_bitstream : the output texture/motion bitstream
 *  Bits *bits : Coding statistics
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	23.08.96 Robert Danielsen: Removed clearing of block in case of
 *			transparent blocks
 *      03.09.96 Cor Quist: renamed the function, added shape coding
 *      04.09.96 Cor Quist: added intra_dcpred_disable
 *	23.10.96 Robert Danielsen: Added DC/AC prediction.
 *      05-Nov-96 Jan De Lameillieure : PutRestMMR should have curr and not
 *			rec_curr as argument
 *	28.11.96 Robert Danielsen: Updating CBP in DCACpred().
 *	15.01.97 Robert Danielsen: Corrected exit(0) to exit(1) in one case.
 *			Solution from Paulo Nunes.
 * 21-APR-97 Jan De Lameillieure : called grey level alpha coding with the 
 *          grey level (GL) quantiser
 *      29.04.97 Luis Ducla-Soares: added argument to function call Bits_CountMB_Motion()
 *	07.05.97 Noel Brady: Rearranged shape syntax a la VM7
 *	06.08.97 Noel Brady: added mods for BINARY_SHAPE_ONLY
 *
 *  04.11.97 Minhua Zhou: updated DC/AC prediction
 *  11.12.97 Bob Eifrig: support for interlaced video
 ***********************************************************CommentEnd********/

Void VopShapeMotText (Vop *curr, Image *alpha_decisions, 
		      Image *MB_decisions, Image *mot_x, Image *mot_y,
		      Int f_code_for,
		      Image **First_stream,
		      Image **Shape_stream,
		      Image *GreyLevelAlpha,
		      Image *MotionCompensatedGreyLevelAlpha,
		      Image *ReconstructedGreyLevelAlpha,
		      Int intra_acdc_pred_disable,
		      Vop *rec_curr,
              Image *mottext_bitstream,
              Bits *bits,
		      Int vo_id, /* modified by SAMSUNG AIT */
              Int rc_type,
		      VolConfig *vol_config)
{
    Int Mode=0;
    Int QP=1;
    Macroblock* mblock=NULL; 
    Int* qcoeff;
    Int i, j;
    Int CBP;
    Int COD;
    Int CBPY, CBPC;
    Int MB_in_width, MB_in_height, B_in_width, mbnum, boff;
    SInt p;
    SInt *ptr=NULL, *alpha_decis_ptr=NULL;
    Float *motx_ptr=NULL, *moty_ptr=NULL;
    Int num_pixels;
    Int num_lines;
    Int vop_type=PCT_INTER;
    SInt *alpha_rec=NULL;
    SInt *alpha_sub=NULL;
    Int MB_transp_pattern[4];
    Int ***DC_store=NULL;
    Int m, n;
    Int ACpred_flag=-1;
    Int direction[6];
    SInt *QP_store=NULL;
    Int switched=0;
    Int DQUANT=0;
    Int fieldDCT = 0;
  /* SPRITE PIECES for Low Latency STATIC SPRITE */
  /* Note: the case STATIC_SPRITE only CONCERNS LOW-LATENCY SPRITES */
  /* BASIC STATIC SPRITES ARE ONLY CONCERNED WITH I_VOP not handled here */	
    Int	*tab_transmit	= GetVopSpriteTabTransmit(curr);
    Int	numblocks_x	= GetVopSpriteHdim(curr)/16;

    Int temp_bits,bits_for_cae=0,bits_for_mode=0,bits_for_mv=0,
      bits_for_dct=0;
    Int  prev_bits_dct=0, bits_mb_dct=0;
    Int QP_prev=0; 

    num_pixels = GetImageSizeX(GetVopY(curr));
    num_lines = GetImageSizeY(GetVopY(curr));
    MB_in_width = num_pixels / MB_SIZE;
    MB_in_height = num_lines / MB_SIZE;
    B_in_width = 2 * MB_in_width;


  

	if (GetVopShape(curr) != BINARY_SHAPE_ONLY)    /* BSO_NOEL */
		{

    for (i = 0; i < 6; i++) {
      direction[i] = 0;
    }
    
    QP_store = (SInt *) GetImageData(GetVopQP(rec_curr));
    
    QP = GetVopQuantizer(curr);

    if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
      QP_prev = QP;  

    mblock = (Macroblock *) malloc (sizeof (Macroblock));

#ifdef _RC_DEBUG_
  printf("RC - VopShapeMotText(): ---> CODING WITH: %d \n",QP);
#endif
  
    /* allocate space for 3D matrix to keep track of prediction values
       for DC/AC prediction */
    
    DC_store = (Int ***)calloc(MB_in_width*MB_in_height,
				       sizeof(Int **));
    for (i = 0; i < MB_in_width*MB_in_height; i++)
      {
	DC_store[i] = (Int **)calloc(6, sizeof(Int *));
	for (j = 0; j < 6; j++)
	  DC_store[i][j] = (Int *)calloc(15, sizeof(Int));
      }
    
      
    Bits_Reset (bits);
    
    vop_type = PCT_INTER;
    if ((GetVopSpriteUsage(curr)==ONLINE_SPRITE) ||
	(GetVopSpriteUsage(curr)==GMC_SPRITE))
      vop_type = PCT_SPRITE;

    ptr = (SInt *) GetImageData(MB_decisions);
    alpha_decis_ptr = (SInt *) GetImageData(alpha_decisions);
    motx_ptr = (Float *) GetImageData(mot_x);
    moty_ptr = (Float *) GetImageData(mot_y);

    alpha_rec = (SInt *) GetImageData(GetVopA(curr));
    alpha_sub = (SInt *) malloc (num_pixels * num_lines * 
				 sizeof (SInt));
    subsamp_alpha_with_modes (alpha_rec, ptr, num_pixels, num_lines, alpha_sub);
	}
				/* BSO_NOEL */
 
        /* ------------------------------------ */
        /* SHARP_start                          */

#ifdef _RC_DEBUG_
        if (Q2MB_ACTIVE == RCQ2_MB_active(Q2MB_CHECK)) 
          fprintf(stdout,"QPs from VM8 macroblock rate control: ");
#endif                            
 
    for (j = 0; j < num_lines/MB_SIZE; j++)
      {
#ifdef _RC_DEBUG_
        if (Q2MB_ACTIVE == RCQ2_MB_active(Q2MB_CHECK)) 
          fprintf(stdout,"\n");
#endif                            
        /* SHARP_end                            */
        /* ------------------------------------ */

	for (i = 0; i < MB_in_width; i++)
	  {
        switched=0;
	    temp_bits = GetImageSizeX(mottext_bitstream);
	    if (GetVopArbitraryShape(curr) )
		{
	      if (GetVopSpriteUsage(curr)!=STATIC_SPRITE) /* no shape for update pieces */		 
		  {
            /* write the first_shape_code for this Macroblock to the bit stream */
 	        BitstreamAppend(First_stream[j*MB_in_width+i],
				mottext_bitstream);
            /* shape data (except first_shape_code) */
            BitstreamAppend(Shape_stream[j*MB_in_width+i],
				mottext_bitstream);
		  }
	    }
	    bits_for_cae += GetImageSizeX(mottext_bitstream) - temp_bits;
	
        if (GetVopShape(curr) != BINARY_SHAPE_ONLY)    /* BSO_NOEL */
				{
    
	    GetTranspPattern (alpha_sub, num_pixels, num_lines,
			      i, j, MB_transp_pattern);


	    if ((RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) && FirstInterFrame==1)  
            	QP = GetMBQuant(vo_id, j*MB_in_width+i); 

            p = *ptr;
            DQUANT = 0;
            if(p != MBM_TRANSPARENT) {


	      if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
		DQUANT =GetDquant(QP,QP_prev,P_VOP); 
	      else 
	      {
                /* MPEG-2 TM-5 Rate Control */
                if(rc_type >= TM5_RATE_CONTROL) {
                    m = (Int)tm5rc_calc_mquant(j*MB_in_width+i, mottext_bitstream->x, vol_config->rcdata);
         
                    if (m >= (QP + 2)) DQUANT = 2;
                    if (m <= (QP - 2)) DQUANT = -2;
                }
                /* ------------------------------------------ */
                /* SHARP_start                                */
                if (Q2MB_ACTIVE == RCQ2_MB_active(Q2MB_CHECK))
                  {
                    prev_bits_dct= bits_for_dct;

                    m= RCQ2_MB_compute_QP(j,i);
                    if (m >= (QP + 2)) DQUANT = 2;
                    else 
                      if (m <= (QP - 2)) DQUANT = -2;
                      else
                        DQUANT= m-QP;
                  }                                 
                /* SHARP_end                                  */
                /* ------------------------------------------ */
	      }

            }

	    if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS)
	      QP_store[j*MB_in_width+i] =(SInt)(QP_prev+DQUANT); 
	    else
	      QP_store[j*MB_in_width+i] = (SInt) (QP + DQUANT);
            switch (p) {

            case MBM_INTER16:
            case MBM_TRANSPARENT:
            case MBM_INTER8:
            case MBM_SPRITE:
            case MBM_FIELD00:
            case MBM_FIELD01:
            case MBM_FIELD10:
            case MBM_FIELD11:
                /* Fill DC_store with default coeff values */
                for (m = 0; m < 6; m++) {
                    DC_store[j*MB_in_width+i][m][0] = GetVopMidGrey(curr)*8;
                  for (n = 1; n < 15; n++)
                    DC_store[j*MB_in_width+i][m][n] = 0;
                }
                break;
            }
            switch (p) {

            case MBM_INTRA:
                Mode = (DQUANT == 0) ? MODE_INTRA : MODE_INTRA_Q;
                bits->no_intra++;
                break;
     
            case MBM_FIELD00:
            case MBM_FIELD01:
            case MBM_FIELD10:
            case MBM_FIELD11:
                Mode = (DQUANT == 0) ? MODE_INTER : MODE_INTER_Q;
                bits->no_field++;
                break;
     
            case MBM_INTER16:
                Mode = (DQUANT == 0) ? MODE_INTER : MODE_INTER_Q;
                bits->no_inter++;
                break;
     
            case MBM_INTER8:
                Mode = MODE_INTER4V;
                bits->no_inter4v++;
                DQUANT = 0;       /* Can't change QP for 8x8 mode */
                break;

            case MBM_TRANSPARENT:
                break;

            case MBM_SPRITE:
                Mode = (DQUANT == 0) ? MODE_DYN_SP : MODE_DYN_SP_Q;
                break;
     
            default:
                printf("invalid MB_decision value :%d\n", p);
                exit(0);
            }
     
			if (p != MBM_TRANSPARENT) {

			  if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
			    qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
					     num_pixels, QP_prev + DQUANT, Mode, MB_transp_pattern, 
					     &fieldDCT);
			  else

			    qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
					     num_pixels, QP + DQUANT, Mode, MB_transp_pattern,
					     &fieldDCT);
		
		mbnum  = j*MB_in_width + i;
		boff = (2 * (mbnum  / MB_in_width) * B_in_width
			+ 2 * (mbnum % MB_in_width)); 
		
		CBP = FindCBP(qcoeff,Mode,64);
		
		if (p==MBM_SPRITE) /* CASE DYNAMIC SPRITES */
		  {
		    if (CBP == 0)
		      {
			COD = 1;	/* skipped macroblock */
			BitstreamPutBits(mottext_bitstream, (long) (COD), 1L);
			bits->COD ++;
			*ptr = SKIPP;
				}
		    else 
		      {
			COD = 0; /* coded macroblock */
		      }
		  }
		else
		  if (((CBP == 0) && (p == 1) && (*(motx_ptr +boff) == 0.0)
		      && (*(moty_ptr +boff) == 0.0) && (vop_type!=PCT_SPRITE))||
		      (GetVopSpriteUsage(curr)==STATIC_SPRITE&&
				tab_transmit[j*numblocks_x+i] !=2))
		    {
		      COD = 1;	/* skipped macroblock */
		      BitstreamPutBits(mottext_bitstream, (long) (COD), 1L);
		      bits->COD ++;
		      
		    /*  printf("MB_skipped :%d\n", mbnum); */
		      *ptr = SKIPP;
		      Mode = MODE_INTER;
		      if (GetVopSpriteUsage(curr)==STATIC_SPRITE&&
				tab_transmit[j*numblocks_x+i] ==2)
			tab_transmit[j*numblocks_x+i]=3;
		    }
		  else 
		    {
		      COD = 0; /* coded macroblock */
		    }
		
	if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) { 
	  if (COD) 
	    QP_store[j*MB_in_width+i] =(SInt)(QP_prev+DQUANT);
	}
	else 

	{
	  if (COD) 
	    QP_store[j*MB_in_width+i] =(SInt)(QP);
	}
	  
		if (COD == 0)
		  {
            if ((Mode == MODE_INTRA) || (Mode == MODE_INTRA_Q)) {

		      /* Store the qcoeff-values needed later for prediction */
                    m =0;
		    if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) { 
		      DC_store[j*MB_in_width+i][0][m] = qcoeff[m]*cal_dc_scaler(QP_prev+DQUANT,1);
		      DC_store[j*MB_in_width+i][1][m] = qcoeff[m+64]*cal_dc_scaler(QP_prev+DQUANT,1);
		      DC_store[j*MB_in_width+i][2][m] = qcoeff[m+128]*cal_dc_scaler(QP_prev+DQUANT,1);
		      DC_store[j*MB_in_width+i][3][m] = qcoeff[m+192]*cal_dc_scaler(QP_prev+DQUANT,1);
		      DC_store[j*MB_in_width+i][4][m] = qcoeff[m+256]*cal_dc_scaler(QP_prev+DQUANT,2);
		      DC_store[j*MB_in_width+i][5][m] = qcoeff[m+320]*cal_dc_scaler(QP_prev+DQUANT,2);
		    }
		    else 

		    {
		      DC_store[j*MB_in_width+i][0][m] = qcoeff[m]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_in_width+i][1][m] = qcoeff[m+64]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_in_width+i][2][m] = qcoeff[m+128]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_in_width+i][3][m] = qcoeff[m+192]*cal_dc_scaler(QP+DQUANT,1);
		      DC_store[j*MB_in_width+i][4][m] = qcoeff[m+256]*cal_dc_scaler(QP+DQUANT,2);
		      DC_store[j*MB_in_width+i][5][m] = qcoeff[m+320]*cal_dc_scaler(QP+DQUANT,2);
		    }

		      for (m = 1; m < 8; m++) {
			DC_store[j*MB_in_width+i][0][m] = qcoeff[m];
			DC_store[j*MB_in_width+i][1][m] = qcoeff[m+64];
			DC_store[j*MB_in_width+i][2][m] = qcoeff[m+128];
			DC_store[j*MB_in_width+i][3][m] = qcoeff[m+192];
			DC_store[j*MB_in_width+i][4][m] = qcoeff[m+256];
			DC_store[j*MB_in_width+i][5][m] = qcoeff[m+320];
		      }
		      for (m = 0; m < 7; m++) {
			DC_store[j*MB_in_width+i][0][m+8] = qcoeff[(m+1)*8];
			DC_store[j*MB_in_width+i][1][m+8] = qcoeff[(m+1)*8+64];
			DC_store[j*MB_in_width+i][2][m+8] = qcoeff[(m+1)*8+128];
			DC_store[j*MB_in_width+i][3][m+8] = qcoeff[(m+1)*8+192];
			DC_store[j*MB_in_width+i][4][m+8] = qcoeff[(m+1)*8+256];
			DC_store[j*MB_in_width+i][5][m+8] = qcoeff[(m+1)*8+320];
		      }
		      
          /* overwrite the DC_store with QDC = 128 for
			 transparent blocks, M.Wollborn (24-MAR-1997) */
		      
		      for (m=0;m<4;m++)
			if (MB_transp_pattern[m])
			  DC_store[j*MB_in_width+i][m][0] = GetVopMidGrey(curr)*8;
		      
		      
		  /* Do the DC/AC prediction, changing the qcoeff values as
			 appropriate */
		      if (intra_acdc_pred_disable == 0)

			if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
			  ACpred_flag = doDCACpred(qcoeff, &CBP, 64, i, j,
						   DC_store,
						   QP_store, QP_prev+DQUANT, MB_in_width,
						   direction,GetVopMidGrey(curr));
			else

			  ACpred_flag = doDCACpred(qcoeff, &CBP, 64, i, j,
						   DC_store,
						   QP_store, QP+DQUANT, MB_in_width,
						   direction,GetVopMidGrey(curr));
		      else
			ACpred_flag = -1; /* Not to go into bitstream */
	            }
		    else {
		      /* Fill DC_store with default coeff values */
		      for (m = 0; m < 6; m++) {
			DC_store[j*MB_in_width+i][m][0] = GetVopMidGrey(curr)*8;
			for (n = 1; n < 15; n++)
			  DC_store[j*MB_in_width+i][m][n] = 0;
		      }
		    }	
                /* added by Minhua Zhou 04.08.97 */

	    if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS)  
	      switched = IntraDCSwitch_Decision(Mode,
						GetVopIntraDCVlcThr(curr),
						QP_prev+DQUANT);
            else

                switched = IntraDCSwitch_Decision(Mode,
                                                  GetVopIntraDCVlcThr(curr),
                                                  QP);
                  if (switched) 
                   CBP = FindCBP(qcoeff,MODE_INTER,64);
		    
		    CBPY = CBP >> 2;
		    CBPY = CBPY & 15; /* last 4 bits */
		    CBPC = CBP & 3; /* last 2 bits */

	    if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
	      QP_prev = QP_prev + DQUANT;

            if ((p == MBM_INTRA) || CBP) {
 
	      if (RCQ2_MVO_CHECK() >= RCQ2_MVO_HVS) 
                QP = QP_prev;
	      else

		QP += DQUANT;
	    }
            else {
                 QP_store[j*MB_in_width+i] = (SInt)(QP);
			     DQUANT = 0;
                 switch (Mode) {
                     case MODE_INTRA_Q:  Mode = MODE_INTRA;  break;
                     case MODE_INTER_Q:  Mode = MODE_INTER;  break;
                     case MODE_DYN_SP_Q: Mode = MODE_DYN_SP; break;
                 }
            } 
            temp_bits = GetImageSizeX(mottext_bitstream);
		    Bits_CountMB_combined (DQUANT, Mode, COD, ACpred_flag, CBP, 
					   vop_type, bits,
					   mottext_bitstream,MB_transp_pattern);

            if (GetVopInterlaced(curr)) {
                if ((p == MBM_INTRA) || (CBP != 0)) {
                    if (fieldDCT)
                        bits->fieldDCT++;
                    BitstreamPutBits(mottext_bitstream, fieldDCT, 1);
                    bits->interlaced++;
                }
                switch (p) {

                case MBM_INTER16:
                    BitstreamPutBits(mottext_bitstream, 0, 1);
                    bits->interlaced++;
                    break;
        
                case MBM_FIELD00:
                case MBM_FIELD10:
                case MBM_FIELD01:
                case MBM_FIELD11:
                    BitstreamPutBits(mottext_bitstream,
                        4 | (p - MBM_FIELD00), 3);
                    bits->interlaced += 3;
                    break;
                    }
                }
		    bits_for_mode += GetImageSizeX(mottext_bitstream) - temp_bits; 
		    
		  }
		
		if (GetVopArbitraryShape(curr) )
		  {
		    if (!GetVopBinaryShape(curr) )
		      CodeGreyLevelAlphaAB(curr,i,j,
					   GetVopGLQuantizer(curr),		/* correction JDL 21-APR-97 */
					   MB_decisions,
					   GreyLevelAlpha,
					   MotionCompensatedGreyLevelAlpha,
					   ReconstructedGreyLevelAlpha,
					   mottext_bitstream);
		  }
		
		
		if (COD == 0)
		  {
		    /* for Spatial scal P-VOPS: MV==0 (UPS)*/
		    if(!(GetVopScalability(curr) == 1 
			 &&GetVopPredictionType(curr) == P_VOP
			 &&GetVopRefSelCode(curr)==3))
		      {
			temp_bits = GetImageSizeX(mottext_bitstream);
		if (GetVopSpriteUsage(curr)!=STATIC_SPRITE) /* No motion for updatepieces */
			{
#ifdef NLSSTATS
            bits->vec += 
#endif
			Bits_CountMB_Motion( mot_x, mot_y, alpha_decisions,
					     MB_decisions, i, j, f_code_for,
					     mottext_bitstream,
					     GetVopErrorResDisable(curr), 0,
					     (Int **)NULL,GetVopShape(curr));
			}
			bits_for_mv += GetImageSizeX(mottext_bitstream) - temp_bits; 
			
		      }
		    
		    temp_bits = GetImageSizeX(mottext_bitstream);
		    MB_CodeCoeff(bits, qcoeff, Mode, CBP, 64, 
				 intra_acdc_pred_disable,
				 NULL, mottext_bitstream,
				 MB_transp_pattern, direction,
				 GetVopErrorResDisable(curr),
				 GetVopReverseVlc(curr),switched,
                 curr->alternate_scan);
		    bits_for_dct += GetImageSizeX(mottext_bitstream) - temp_bits; 
		  }
		free ((Char*)qcoeff);
	      }
	    ptr++;

		}  								/* BSO_NOEL */
#ifdef _COUNT_BITS_ 
	    printf("Bits Used: ");
	    printf("\tShape: %d\n",bits_for_cae);
	    printf("\tMode: %d\n",bits_for_mode);
	    printf("\tMV: %d\n",bits_for_mv);
	    printf("\tDCT: %d\n",bits_for_dct);
	    getchar();
#endif

            /* ------------------------------------------ */
            /* SHARP_start                                */
            if (Q2MB_ACTIVE == RCQ2_MB_active(Q2MB_CHECK))
              {
#ifdef _RC_DEBUG_
                fprintf(stdout,"%4d ", QP);
#endif                            
                bits_mb_dct= bits_for_dct - prev_bits_dct;
                
                RCQ2_MB_update((Float) bits_mb_dct, 
                               (Float) (bits_for_cae + bits_for_mode + bits_for_mv),
                               (Float) QP, j, i);
              }
            /* SHARP_end                                  */
            /* ------------------------------------------ */

		
	  }
      }

	if (GetVopShape(curr) != BINARY_SHAPE_ONLY)    /* BSO_NOEL */
		{    
		  /* Free allocated memory for 3D matrix */
		  
		  for (i = 0; i < MB_in_width*MB_in_height; i++) {
		    
		    for (j = 0; j < 6; j++)
		      free(DC_store[i][j]);
		    free(DC_store[i]);
		  }
		}
    free(DC_store);
    
    free ((Char*)mblock);
    free((Char*)alpha_sub);



}

/***********************************************************CommentBegin******
 *
 * -- MBShapeMotTextErrRes -- Combined Inter encoding of shape motion and
 *                             texture of one MB. Used in error resilient mode.
 *
 *
 * Author : Luis Ducla-Soares (IST) - lds@lx.it.pt		
 *	
 *
 * Created :	27.04.97	
 *	
 *
 * Purpose :		
 *	Combined Inter encoding of texture and motion.
 * 
 * Arguments in : 	
 *	Vop *curr : the current vop to be encoded
 * 	Vop *rec_prev: the previous reconstructed vop
 * 	Image *mot_x : the x-coordinates of the motion vectors
 * 	Image *mot_y : the y-coordinates of the motion vectors
 * 	Image *alpha_decisions : ?
 * 	Image *MB_decisions: Contains for each macroblock the encoding mode
 *	Int	f_code_for: MV search range 1/2 pel: 1=32,2=64,...,7=2048
 *      Image* AB_SizeConversionDecisions: 
 *      Image* AB_first_MMR_values :
 *      Int intra_dcpred_disable : disable the intra dc prediction
 *
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *rec_curr : the reconstructed current vop
 * 	Image *mottext_bitstream : the output texture/motion bitstream
 *  Bits *bits : Coding statistics
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description : This function was based on VopShapeMotText().	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *    15.05.97 Luis Ducla-Soares: corrected the remultiplexing of the DCT data
 *                                in the combined error resilient mode with data 
 *                                partitioning.
 *    04.11.97 Minhua Zhou: updated DC/AC prediction
 *    11.12.97 Bob Eifrig: support for interlaced video coding
 *
 ***********************************************************CommentEnd********/

Void MBShapeMotTextErrRes (Vop *curr, Image *alpha_decisions, 
			   Image *MB_decisions, Image *mot_x, Image *mot_y,
			   Int f_code_for,
			   Image **First_stream,
			   Image **Shape_stream,
			   Image *GreyLevelAlpha,
			   Image *MotionCompensatedGreyLevelAlpha,
			   Image *ReconstructedGreyLevelAlpha,
			   Int intra_acdc_pred_disable,
			   Int data_partitioning,
			   Vop *rec_curr,
			   Image *motion_comb_bitstream,
			   Image *text_header_comb_bitstream,
			   Image *text_data_comb_bitstream,
			   Int i, Int j, Int *num_bits_MB_ptr,
			   Int after_marker,
			   Int ***DC_store,
			   Int **slice_nb,
			   Bits *bits)
{
  Int Mode;
  Int QP;
  Macroblock* mblock; 
  Int* qcoeff;
  Int k;
  Int CBP;
  Int COD;
  Int CBPY, CBPC;
  Int MB_in_width, MB_in_height, B_in_width, mbnum, boff;
  SInt p;
  SInt *ptr, *alpha_decis_ptr, *pp;
  Float *motx_ptr, *moty_ptr;
  Int num_pixels;
  Int num_lines;
  Int vop_type;
  SInt *alpha_rec;
  SInt *alpha_sub;
  Int MB_transp_pattern[4];
  Int m, n;
  Int ACpred_flag=-1;
  Int direction[6];
  SInt *QP_store;
  Int switched=0;
  Int shape_bits=0,
  tmp_bits;

   

  for (k = 0; k < 6; k++) {
    direction[k] = 0;
  }

  QP_store = (SInt *) GetImageData(GetVopQP(rec_curr));
  num_pixels = GetImageSizeX(GetVopY(curr));
  num_lines = GetImageSizeY(GetVopY(curr));

  QP = GetVopQuantizer(curr);
  MB_in_width = num_pixels / MB_SIZE;
  MB_in_height = num_lines / MB_SIZE;
  B_in_width = 2 * MB_in_width;
  
#ifdef _RC_DEBUG_
  printf("RC - MBShapeMotTextErrRes(): ---> CODING WITH: %d \n",QP);
#endif

  mblock = (Macroblock *) malloc (sizeof (Macroblock));
    
  Bits_Reset (bits);

  vop_type = PCT_INTER;
  if ((GetVopSpriteUsage(curr)==ONLINE_SPRITE) ||
      (GetVopSpriteUsage(curr)==GMC_SPRITE))
    vop_type = PCT_SPRITE;

  ptr = (SInt *) GetImageData(MB_decisions);
  alpha_decis_ptr = (SInt *) GetImageData(alpha_decisions);
  motx_ptr = (Float *) GetImageData(mot_x);
  moty_ptr = (Float *) GetImageData(mot_y);

  alpha_rec = (SInt *) GetImageData(GetVopA(curr));
  alpha_sub = (SInt *) malloc (num_pixels * num_lines * 
			       sizeof (SInt));
  subsamp_alpha_with_modes (alpha_rec, ptr, num_pixels, num_lines, alpha_sub);
     

  if (GetVopArbitraryShape(curr) )
    {
				
#if 0
      printf("\n\nMB: %d,%d (%d)\n",i,j,j*MB_in_width+i);
#endif
      tmp_bits = GetImageSizeX(motion_comb_bitstream);
      /* write the first_shape_code for this Macroblock to the bit stream */
      BitstreamAppend(First_stream[j*MB_in_width+i],
		      motion_comb_bitstream);

#if 0
{
  SInt *p = (SInt *)GetImageData(First_stream[j*MB_in_width+i]);
  for (m=0;m<GetImageSizeX(First_stream[j*MB_in_width+i]);m++,p++)
    printf("%d",*p);
  printf("\n");
}
#endif
      /* shape data (except first_shape_code) */
      BitstreamAppend(Shape_stream[j*MB_in_width+i],
		      motion_comb_bitstream);

#if 0
{
  SInt *p = (SInt *)GetImageData(Shape_stream[j*MB_in_width+i]);
  for (m=0;m<GetImageSizeX(Shape_stream[j*MB_in_width+i]);m++,p++)
    printf("%d",*p);
  printf("\n");
}
#endif
      shape_bits = GetImageSizeX(motion_comb_bitstream)-tmp_bits;
    }

  if (GetVopShape(curr) != BINARY_SHAPE_ONLY) /* BSO_ONLY */
    {
      GetTranspPattern (alpha_sub, num_pixels, num_lines,
			i, j, MB_transp_pattern);

#if 0
      printf("transp pattern: %d %d %d %d\n",
	     MB_transp_pattern[0],
	     MB_transp_pattern[1],
	     MB_transp_pattern[2],
	     MB_transp_pattern[3]);
#endif

      /* Store the QP value for later use in AC prediction */
      QP_store[j*MB_in_width+i] = (SInt) QP;
		
      pp = ptr + (j*MB_in_width+i);
      p = *pp;
	
      if (p == 1 || p == 2 || p == 4 || p == 3) {
	/* Fill DC_store with default coeff values */
	for (m = 0; m < 6; m++) {
	  DC_store[j*MB_in_width+i][m][0] = GetVopMidGrey(curr)*8;
	  for (n = 1; n < 15; n++)
	    DC_store[j*MB_in_width+i][m][n] = 0;
	}
      }
      if ( p == 2 )
	;
      else
	{ 
	  if ( p == 0 ) Mode = MODE_INTRA;
	  else if ( p == 1 ) Mode = MODE_INTER;
	  else if ( p == 4) Mode = MODE_INTER4V;
	  else if ( p == 3) Mode = MODE_DYN_SP;
	  else
	    {
	      printf("invalid MB_decision value :%d\n", p);
	      exit(1);
	    }
	  qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
			   num_pixels, QP, Mode, MB_transp_pattern, NULL);


	  mbnum  = j*MB_in_width + i;
	  boff = (2 * (mbnum  / MB_in_width) * B_in_width
		  + 2 * (mbnum % MB_in_width)); 
	    
	  CBP = FindCBP(qcoeff,Mode,64);

	  if (p==3)		/* CASE DYNAMIC SPRITES */
	    {
	      if (CBP == 0)
		{
		  COD = 1;	/* skipped macroblock */
		  BitstreamPutBits(motion_comb_bitstream, (long) (COD), 1L);
		  bits->COD ++;
		  *ptr = SKIPP;
		}
	      else 
		{
		  COD = 0;	/* coded macroblock */
		}
	    }
	  else
	    if ((CBP == 0) && (p == 1) && (*(motx_ptr +boff) == 0.0)
		&& (*(moty_ptr +boff) == 0.0) && (vop_type!=PCT_SPRITE))
	      {
		COD = 1;	/* skipped macroblock */
		BitstreamPutBits(motion_comb_bitstream, (long) (COD), 1L);
		bits->COD ++;

		*pp = SKIPP;
		Mode = MODE_INTER;
	      }
	    else 
	      {
		COD = 0;	/* coded macroblock */
	      }

	  if (COD == 0)
	    {		 
	      bits->no_intra++;

	      if (Mode == MODE_INTRA) {
		/* Store the qcoeff-values needed later for prediction */
		m =0;
		DC_store[j*MB_in_width+i][0][m] = qcoeff[m]*cal_dc_scaler(QP,1);
		DC_store[j*MB_in_width+i][1][m] = qcoeff[m+64]*cal_dc_scaler(QP,1);
		DC_store[j*MB_in_width+i][2][m] = qcoeff[m+128]*cal_dc_scaler(QP,1);
		DC_store[j*MB_in_width+i][3][m] = qcoeff[m+192]*cal_dc_scaler(QP,1);
		DC_store[j*MB_in_width+i][4][m] = qcoeff[m+256]*cal_dc_scaler(QP,2);
		DC_store[j*MB_in_width+i][5][m] = qcoeff[m+320]*cal_dc_scaler(QP,2);

		for (m = 1; m < 8; m++) {
		  DC_store[j*MB_in_width+i][0][m] = qcoeff[m];
		  DC_store[j*MB_in_width+i][1][m] = qcoeff[m+64];
		  DC_store[j*MB_in_width+i][2][m] = qcoeff[m+128];
		  DC_store[j*MB_in_width+i][3][m] = qcoeff[m+192];
		  DC_store[j*MB_in_width+i][4][m] = qcoeff[m+256];
		  DC_store[j*MB_in_width+i][5][m] = qcoeff[m+320];
		}
		for (m = 0; m < 7; m++) {
		  DC_store[j*MB_in_width+i][0][m+8] = qcoeff[(m+1)*8];
		  DC_store[j*MB_in_width+i][1][m+8] = qcoeff[(m+1)*8+64];
		  DC_store[j*MB_in_width+i][2][m+8] = qcoeff[(m+1)*8+128];
		  DC_store[j*MB_in_width+i][3][m+8] = qcoeff[(m+1)*8+192];
		  DC_store[j*MB_in_width+i][4][m+8] = qcoeff[(m+1)*8+256];
		  DC_store[j*MB_in_width+i][5][m+8] = qcoeff[(m+1)*8+320];
		}

		/* overwrite the DC_store with QDC = 128 for
		   transparent blocks, M.Wollborn (24-MAR-1997) */

		for (m=0;m<4;m++)
		  if (MB_transp_pattern[m])
		    DC_store[j*MB_in_width+i][m][0] = GetVopMidGrey(curr)*8;


		/* Do the DC/AC prediction, changing the qcoeff values as
		   appropriate */
		if (intra_acdc_pred_disable == 0)
		  ACpred_flag = doDCACpredErrRes(qcoeff, &CBP, 64, i, j,
						 DC_store,
						 QP_store, QP, MB_in_width,
						 direction, slice_nb,GetVopMidGrey(curr));
		else
		  ACpred_flag = -1; /* Not to go into bitstream */
	      }
	      else {
		/* Fill DC_store with default coeff values */
		for (m = 0; m < 6; m++) {
		  DC_store[j*MB_in_width+i][m][0] = GetVopMidGrey(curr)*8;
		  for (n = 1; n < 15; n++)
		    DC_store[j*MB_in_width+i][m][n] = 0;
		}
	      }		    
	      /* added by Minhua Zhou 04.08.97 */
	      switched = IntraDCSwitch_Decision(Mode,
						GetVopIntraDCVlcThr(curr),
						QP);
	      if (switched) 
		CBP = FindCBP(qcoeff,MODE_INTER,64);

	      CBPY = CBP >> 2;
	      CBPY = CBPY & 15; /* last 4 bits */
	      CBPC = CBP & 3;	/* last 2 bits */
#if 0
	      printf("ACpred_flag : %d\n",ACpred_flag);
	      printf("CBP: %d\n",CBP);
#endif
	      Bits_CountMB_combined_ErrRes (Mode, COD, ACpred_flag, CBP, 
					    vop_type, bits,
					    motion_comb_bitstream,
					    text_header_comb_bitstream,
					    MB_transp_pattern);
					


	    }

	  if (GetVopArbitraryShape(curr) )
	    {

	      if (!GetVopBinaryShape(curr) )
		CodeGreyLevelAlphaAB(curr,i,j,
				     GetVopGLQuantizer(curr), /* correction JDL 21-APR-97 */
				     MB_decisions,
				     GreyLevelAlpha,
				     MotionCompensatedGreyLevelAlpha,
				     ReconstructedGreyLevelAlpha,
				     motion_comb_bitstream);
	    }


	  if (COD == 0)
	    {
	      bits->vec = Bits_CountMB_Motion( mot_x, mot_y, alpha_decisions,
					      MB_decisions, i, j, f_code_for,
					      motion_comb_bitstream,
					      GetVopErrorResDisable(curr),
					      after_marker, slice_nb,GetVopShape(curr));
		  
	      if (data_partitioning)
		MB_CodeCoeff(bits, qcoeff, Mode, CBP, 64, 
			     intra_acdc_pred_disable,
			     text_header_comb_bitstream,
			     text_data_comb_bitstream,
			     MB_transp_pattern, direction,
			     GetVopErrorResDisable(curr),
			     GetVopReverseVlc(curr),switched, 0);
	      else
		MB_CodeCoeff(bits, qcoeff, Mode, CBP, 64, 
			     intra_acdc_pred_disable,
			     motion_comb_bitstream,
			     text_data_comb_bitstream,
			     MB_transp_pattern, direction,
			     GetVopErrorResDisable(curr),
			     GetVopReverseVlc(curr),switched, 0);
	    }
	  free ((Char*)qcoeff);
	}
    } /* BSO_ONLY */ 


  *num_bits_MB_ptr = shape_bits+bits->COD + bits->MCBPC + bits->CBPY +
    bits->ACpred_flag + bits->DQUANT + bits->Y + bits->C + bits->vec;

  free ((Char*)mblock);
  free((Char*)alpha_sub);
}



/***********************************************************CommentBegin******
 *
 * -- Bits_CountMB_combined -- texture encoding for combined texture/motion
 *
 * Author : Cor Quist (KPN)		
 *	
 *
 * Created :		
 *	
 *
 * Purpose :		
 *	Used for texture encoding in case of combined texture/motion
 * 		encoding. This function encodes the :
 *		- COD flag
 *		- MCBPC flag
 *		- CBPY flag
 *		- CBPC flag 
 *		- DQUANT information 
 * 
 * Arguments in : 	
 *	SInt Mode : The macroblock encoding mode
 * 	Int CBP : Coded block pattern information
 * 	Int COD : Indicates whether this macroblock is coded or not
 *	Int ACpred_flag
 * 	Int vop_type : indicates the picture coding type
 *		(Intra,Inter)
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Bits* bits : a structure counting the number of bits
 * 	Image *bitstream : output texture bit stream * 
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	07.06.96: Robert Danielsen: Changed from using Encode to Putxxx
 *		instead, based on new VLC encoding scheme.
 *	11.06.96: Cor Quist: Added support for I-VOP's.
 *	25.10.96 Robert Danielsen: Added writing of ACpred_flag.
 *	15.01.97 Robert Danielsen: Corrected exit(0) to exit(1) in one case.
 *			Solution from Paulo Nunes.
 *      17-Jan-97 Jan De Lameillieure : correction : no ACpred_flag in combined
 *                                      mode when intra_acdc_pred_disable is true
 *      13-05-97 Minhua Zhou: added: MB_transp_pattern for CBPY coding
 *      11-08.97 Minhua Zhou: added DQUANT
 *
 ***********************************************************CommentEnd********/

Void Bits_CountMB_combined(Int DQUANT, Int Mode, Int COD, Int ACpred_flag,
			   Int CBP, Int vop_type,
			   Bits* bits, Image *mottext_bitstream,Int *MB_transp_pattern)
{
  Int 	cbpy ,cbpc, length;
  Int   MBtype=-1;
  
  
  if ( Mode == MODE_INTRA ) MBtype = 3;
  if ( Mode == MODE_INTER ) MBtype = 0;
  if ( Mode == MODE_INTRA_Q) MBtype = 4;
  if ( Mode == MODE_INTER_Q) MBtype = 1;
  if ( Mode == MODE_INTER4V) MBtype = 2;
  
  if ( Mode == MODE_DYN_SP) MBtype = 0;
  if ( Mode == MODE_DYN_SP_Q) MBtype = 1;
  
  
  cbpc = CBP & 3;
  cbpy = CBP>>2;  
  
  /* COD */
  
  if (vop_type != PCT_INTRA )
    {
      if (COD)
	{	
	  printf("COD = 1 in Bits_CountMB_combined \n");
	  printf("This function should not be used if COD is '1' \n");
	  exit(1);
	}

      BitstreamPutBits(mottext_bitstream, (long)(COD), 1L); /* write COD */
      bits->COD++;
    }
  
  /* MCBPC */
  
  if (vop_type == PCT_INTRA)
    length = PutMCBPC_Intra (cbpc, MBtype, mottext_bitstream);
  else
    length = PutMCBPC_Inter (cbpc, MBtype, mottext_bitstream);
  
  bits->MCBPC += length;
  
  /* MCSEL syntax */
  if (((Mode == MODE_INTER) || (Mode == MODE_INTER_Q) || (Mode == MODE_DYN_SP) || (Mode == MODE_DYN_SP_Q))  && (vop_type == PCT_SPRITE))
    {
      if ((Mode == MODE_INTER) || (Mode == MODE_INTER_Q))
	BitstreamPutBits(mottext_bitstream, (long) 0, 1L);
      if ((Mode == MODE_DYN_SP) || (Mode == MODE_DYN_SP_Q))
	BitstreamPutBits(mottext_bitstream, (long) 1, 1L);

      bits->MCBPC += 1;
    }
  
  /* ACpred_flag */
  /* 17-Jan-97 JDL : correction no ACpred_flag in combined mode when intra_acdc_pred_disable is true */
  if ((Mode == MODE_INTRA || Mode==MODE_INTRA_Q) && ACpred_flag != -1)
    {
      BitstreamPutBits(mottext_bitstream, (long)ACpred_flag, 1L);
      bits->ACpred_flag += 1;
    }
  
  /* CBPY */
  
  
  length = PutCBPY (cbpy, (Char)(Mode==MODE_INTRA||Mode==MODE_INTRA_Q),MB_transp_pattern,mottext_bitstream);
  
  bits->CBPY += length;
  
  /* DQUANT */
  
  
  if ((Mode == MODE_INTER_Q) || (Mode == MODE_INTRA_Q)|| (Mode == MODE_DYN_SP_Q))
    {
      switch (DQUANT)
	{
	case -1:
	  BitstreamPutBits(mottext_bitstream, 0L, 2L);
	  break;
	case -2:
	  BitstreamPutBits(mottext_bitstream, 1L, 2L);
	  break;
	case 1:
	  BitstreamPutBits(mottext_bitstream, 2L, 2L);
	  break;
	case 2:
	  BitstreamPutBits(mottext_bitstream, 3L, 2L);
	  break;
	default:
	  fprintf(stderr,"Invalid DQUANT\n");
	  exit(1);
	}
      bits->DQUANT += 2;
    }
}

/***********************************************************CommentBegin******
 *
 * -- Bits_CountMB_combined_ErrRes -- texture encoding for combined texture/motion
 *
 * Author : Luis Ducla (IST) - lds@lx.it.pt		
 *	
 *
 * Created :		
 *	27.04.97
 *
 * Purpose :		
 *	Used for texture encoding in case of combined texture/motion
 * 		encoding. This function encodes the :
 *		- COD flag
 *		- MCBPC flag
 *		- CBPY flag
 *		- CBPC flag 
 *		- DQUANT information (not used in this implementation)
 * 
 * Arguments in : 	
 *	SInt Mode : The macroblock encoding mode
 * 	Int CBP : Coded block pattern information
 * 	Int COD : Indicates whether this macroblock is coded or not
 *	Int ACpred_flag
 * 	Int vop_type : indicates the picture coding type
 *		(Intra,Inter)
 *
 * Arguments in/out :	
 *	
 *
 * Arguments out :	
 *	Bits* bits : a structure counting the number of bits
 * 	Image *motion_comb_bitstream : output motion bitstream * 
 *      Image *texture_comb_bitstream: output texture bitstream *
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *     13.05.97 Minhua Zhou :added MB_transp_pattern for CBPY coding
 *
 ***********************************************************CommentEnd********/

Void Bits_CountMB_combined_ErrRes(Int Mode, Int COD, Int ACpred_flag,
				  Int CBP, Int vop_type,
				  Bits* bits, Image *motion_comb_bitstream, 
				  Image *texture_comb_bitstream,Int *MB_transp_pattern)
{
  Int 	cbpy ,cbpc, length;
  Int   DQUANT = 0;		/* not used */
  Int   MBtype=-1;


  if ( Mode == MODE_INTRA ) MBtype = 3;
  if ( Mode == MODE_INTER ) MBtype = 0;
  if ( Mode == MODE_INTRA_Q) MBtype = 4;
  if ( Mode == MODE_INTER_Q) MBtype = 1;
  if ( Mode == MODE_INTER4V) MBtype = 2;

  if ( Mode == MODE_DYN_SP) MBtype = 0;
  if ( Mode == MODE_DYN_SP_Q) MBtype = 1;


  cbpc = CBP & 3;
  cbpy = CBP>>2;  
   
  /* COD */
  
  if (vop_type != PCT_INTRA )
    {
      if (COD)
	{	
	  printf("COD = 1 in Bits_CountMB_combined \n");
	  printf("This function should not be used if COD is '1' \n");
	  exit(1);
	}

      BitstreamPutBits(motion_comb_bitstream, (long)(COD), 1L); /* write COD */
      bits->COD++;
    }
  
  /* MCBPC */
  
  if (vop_type == PCT_INTRA)
    length = PutMCBPC_Intra (cbpc, MBtype, motion_comb_bitstream);
  else
    length = PutMCBPC_Inter (cbpc, MBtype, motion_comb_bitstream);

  bits->MCBPC += length;

  /* MCSEL syntax */
  if (((Mode == MODE_INTER) || (Mode == MODE_INTER_Q) || (Mode == MODE_DYN_SP) || (Mode == MODE_DYN_SP_Q))  && (vop_type == PCT_SPRITE))
    {
      if ((Mode == MODE_INTER) || (Mode == MODE_INTER_Q))
	BitstreamPutBits(motion_comb_bitstream, (long) 0, 1L);
      if ((Mode == MODE_DYN_SP) || (Mode == MODE_DYN_SP_Q))
	BitstreamPutBits(motion_comb_bitstream, (long) 1, 1L);

      bits->MCBPC += 1;
    }

  /* ACpred_flag */
  /* 17-Jan-97 JDL : correction no ACpred_flag in combined mode when intra_acdc_pred_disable is true */
  if (Mode == MODE_INTRA && ACpred_flag != -1)
    {
      BitstreamPutBits(texture_comb_bitstream, (long)ACpred_flag, 1L);
      bits->ACpred_flag += 1;
    }

  /* CBPY */
  	  
   
  length = PutCBPY (cbpy, (Char)(Mode==MODE_INTRA||Mode==MODE_INTRA_Q),MB_transp_pattern,texture_comb_bitstream);

  bits->CBPY += length;
  
  /* DQUANT */
  
  /* This is not supported in the current implementation */
  
  if ((Mode == MODE_INTER_Q) || (Mode == MODE_INTRA_Q)|| (Mode == MODE_DYN_SP_Q))
    {
      switch (DQUANT)
	{
	case -1:
	  BitstreamPutBits(texture_comb_bitstream, 0L, 2L);
	  break;
	case -2:
	  BitstreamPutBits(texture_comb_bitstream, 1L, 2L);
	  break;
	case 1:
	  BitstreamPutBits(texture_comb_bitstream, 2L, 2L);
	  break;
	case 2:
	  BitstreamPutBits(texture_comb_bitstream, 3L, 2L);
	  break;
	default:
	  fprintf(stderr,"Invalid DQUANT\n");
	  exit(1);
	}
      bits->DQUANT += 2;
    }
}


/***********************************************************CommentBegin******
 *
 * -- doDCACpred -- Does DC/AC prediction. Changes qcoeff values as
 *		    appropriate.
 *
 * Author :		
 *	Robert Danielsen, Telenor <Robert.Danielsen@nta.no>
 *
 * Created :		
 *	23.10.96
 *
 * Purpose :		
 *	Does DC/AC prediction. Changes qcoeff values as appropriate. 
 * 
 * Arguments in : 	
 *	Int CBP
 *	Int ncoeffs
 *	Int x_pos
 *	Int y_pos
 *	Int DC_store[][6][15]  	Stores coefficient values per MB for
 *			       	prediction (for one Vop)
 *	SInt *QP_store		Stores QP values for MBs (for one Vop)
 *	Int QP			QP value for this MB
 *	Int MB_width
 *
 * Arguments in/out :	
 *	Int *qcoeff
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	Int	The ACpred_flag, which is to be put into the bitstream
 *
 * Side effects :	
 *	Modifies qcoeff if needed for the prediction.
 *
 * Description :	
 *	
 * See also :
 *	
 * Modified : 15.08.97 Minhua Zhou: AC prediction is disabled when the 
 *            resulting ACs are outside of [-127:127] 	
 *            04.11.97 Minhua Zhou: updated DC/AC prediction
 *	      25.03.98 M.Wollborn: Modifications due to N2171 Cl. 2.2.14	
 *	
 ***********************************************************CommentEnd********/

Int doDCACpred(Int *qcoeff, Int *CBP, Int ncoeffs, Int x_pos, Int y_pos,
	       Int ***DC_store, SInt *QP_store, Int QP, Int MB_width,
	       Int direction[], Int mid_grey )
{
  Int i, m;
  Int block_A, block_B, block_C;
  Int Xpos[6] = {-1, 0, -1, 0, -1, -1};
  Int Ypos[6] = {-1, -1, 0, 0, -1, -1};
  Int Xtab[6] = {1, 0, 3, 2, 4, 5};
  Int Ytab[6] = {2, 3, 0, 1, 4, 5};
  Int Ztab[6] = {3, 2, 1, 0, 4, 5};
  Int grad_hor, grad_ver, DC_pred;
  Int pred_A[15], pred_C[15];
  Int S = 0, S1, S2;
  Int diff;
  Int pcoeff[384];
  Int ACpred_flag=-1;

  /* Copy qcoeff to the prediction array pcoeff */
  for (i = 0; i < (6*ncoeffs); i++) {
    pcoeff[i] = qcoeff[i];
  }

  for (i = 0; i < 6; i++) {
    if ((x_pos == 0) && y_pos == 0) { /* top left corner */
      block_A = (i == 1 || i == 3) ? DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0] : mid_grey*8;
      block_B = (i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0] : mid_grey*8;
      block_C = (i == 2 || i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0] : mid_grey*8;
    }
    else if (x_pos == 0) {	/* left edge */
      block_A = (i == 1 || i == 3) ? DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0] : mid_grey*8;
      block_B = (i == 1 || i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0] : mid_grey*8;
      block_C = DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0];
    }
    else if (y_pos == 0) {	/* top row */
      block_A = DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0];
      block_B = (i == 2 || i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0] : mid_grey*8;
      block_C = (i == 2 || i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0] : mid_grey*8;
    }
    else {
      block_A = DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0];
      block_B = (DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])]
		 [Ztab[i]][0]);
      block_C = DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0];
    }
    grad_hor = block_B - block_C;
    grad_ver = block_A - block_B;

    if ((ABS(grad_ver)) < (ABS(grad_hor))) {
      DC_pred = block_C;
      direction[i] = 2;
    }
    else {
      DC_pred = block_A;
      direction[i] = 1;
    }

    pcoeff[i*ncoeffs] = qcoeff[i*ncoeffs] - (DC_pred+cal_dc_scaler(QP,(i<4)?1:2)/2)/cal_dc_scaler(QP,(i<4)?1:2);

    /* Find AC predictions */
    if ((x_pos == 0) && y_pos == 0) { /* top left corner */
      if (i == 1 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      else
	nullfill(pred_A,mid_grey);
      if (i == 2 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_C[m] = Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) * (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      else
	nullfill(pred_C,mid_grey);
    }
    else if (x_pos == 0) {	/* left edge */
      if (i == 1 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      else
	nullfill(pred_A,mid_grey);
      for (m = 0; m < 15; m++) 
	pred_C[m] = Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) * (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
    }
    else if (y_pos == 0) {	/* top row */
      for (m = 0; m < 15; m++) 
	pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      if (i == 2 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_C[m] = Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) * (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      else
	nullfill(pred_C,mid_grey);
    }
    else {
      for (m = 0; m < 15; m++) {
	pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
	pred_C[m] = Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) * (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      }
    }

#if 1				/* I think it should be like this, 14-NOV-1996 MW */
    S1 = 0;
    S2 = 0;
    /* Now decide on AC prediction */
    if (direction[i] == 1) {	/* Horizontal, left COLUMN of block A */
      for (m = 0; m < 7; m++) {
	S1 += ABS(qcoeff[i*ncoeffs+(m+1)*8]);
	diff = pcoeff[i*ncoeffs+(m+1)*8] 
	  = qcoeff[i*ncoeffs+(m+1)*8] - pred_A[m+8];
	S2 += ABS(diff);
      }
    }
    else {			/* Vertical, top ROW of block C */
      for (m = 1; m < 8; m++) {
	S1 += ABS(qcoeff[i*ncoeffs+m]);
	diff = pcoeff[i*ncoeffs+m] 
	  = qcoeff[i*ncoeffs+m] - pred_C[m];
	S2 += ABS(diff);
      }
    }
    S += (S1 - S2);
#endif
  }
  /* Now change qcoeff for DC pred or DC/AC pred */
  if (S >=0) {
    for (i=0;i<ncoeffs*6; i++)
      /* Modified due to N2171 Cl. 2.2.14 MW 25-MAR-1998 */
      /* if ((i%64)&&(abs(pcoeff[i])>127)) { */
      if ((i%64)&&(abs(pcoeff[i])>2047)) {
	printf("predicted AC out of range");
	S=-1;break;
      }
  }
  if (S >= 0) {			/* Both DC and AC prediction */
    ACpred_flag = 1;
    for (i = 0; i < ncoeffs*6; i++) {
      qcoeff[i] = pcoeff[i];
    }
    /* Update CBP for predicted coeffs. */
    *CBP = FindCBP(qcoeff, MODE_INTRA, 64);
  }
  else {			/* Only DC prediction */
    ACpred_flag = 0;
    for (i = 0; i < 6; i++) {
      qcoeff[i*ncoeffs] = pcoeff[i*ncoeffs];
      direction[i] = 0;
    }
  }
  return ACpred_flag;		/* To be put into bitstream */
}

/***********************************************************CommentBegin******
 *
 * -- doDCACpredErrRes -- Does DC/AC prediction. Changes qcoeff values as
 *		    appropriate.
 *
 * Author :		
 *	Luis Ducla Soares (IST) - lds@lx.it.pt
 *
 * Created :		
 *	22.09.97
 *
 * Purpose :		
 *	Does DC/AC prediction in the error resilient mode. Changes qcoeff values as appropriate. 
 * 
 * Arguments in : 	
 *	Int CBP
 *	Int ncoeffs
 *	Int x_pos
 *	Int y_pos
 *	Int DC_store[][6][15]  	Stores coefficient values per MB for
 *			       	prediction (for one Vop)
 *	SInt *QP_store		Stores QP values for MBs (for one Vop)
 *	Int QP			QP value for this MB
 *	Int MB_width
 *      Int **slice_nb  stores the number of the slice a given MB belongs to.
 *
 * Arguments in/out :	
 *	Int *qcoeff
 *
 * Arguments out :	
 *	
 *
 * Return values :	
 *	Int	The ACpred_flag, which is to be put into the bitstream
 *
 * Side effects :	
 *	Modifies qcoeff if needed for the prediction.
 *
 * Description :	
 *	
 * See also :
 *	
 * Modified : 15.08.97 Minhua Zhou: AC prediction is disabled when the 
 *            resulting ACs are outside of [-127:127] 		
 *	      25.03.98 M.Wollborn: Modifications due to N2171 Cl. 2.2.14	
 *	
 ***********************************************************CommentEnd********/

Int doDCACpredErrRes(Int *qcoeff, Int *CBP, Int ncoeffs, Int x_pos, Int y_pos,
		     Int ***DC_store, SInt *QP_store, Int QP, Int MB_width,
		     Int direction[], Int **slice_nb, Int mid_grey)
{
  Int i, m;
  Int block_A, block_B, block_C;
  Int Xpos[6] = {-1, 0, -1, 0, -1, -1};
  Int Ypos[6] = {-1, -1, 0, 0, -1, -1};
  Int Xtab[6] = {1, 0, 3, 2, 4, 5};
  Int Ytab[6] = {2, 3, 0, 1, 4, 5};
  Int Ztab[6] = {3, 2, 1, 0, 4, 5};
  Int grad_hor, grad_ver, DC_pred;
  Int pred_A[15], pred_C[15];
  Int S = 0, S1, S2;
  Int diff;
  Int pcoeff[384];
  Int ACpred_flag=-1;

  /* Copy qcoeff to the prediction array pcoeff */
  for (i = 0; i < (6*ncoeffs); i++) {
    pcoeff[i] = qcoeff[i];
  }

  for (i = 0; i < 6; i++) {
    if ((x_pos == 0) && y_pos == 0) { /* top left corner */
      block_A = (i == 1 || i == 3) ? DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0] : mid_grey*8;
      block_B = (i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0] : mid_grey*8;
      block_C = (i == 2 || i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0] : mid_grey*8;
    }
    else if (x_pos == 0) {	/* left edge */
      block_A = (i == 1 || i == 3) ? DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0] : mid_grey*8;
      block_B = ((i == 1  && slice_nb[x_pos][y_pos] == slice_nb[x_pos][y_pos-1]) || i == 3) ? 
	DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0] : mid_grey*8;
      block_C = (i == 2 || i == 3 || ((i == 0 || i == 1 || i == 4 || i == 5) &&
				      slice_nb[x_pos][y_pos] == slice_nb[x_pos][y_pos-1])) ? 
					DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0] : mid_grey*8;
    }
    else if (y_pos == 0) {	/* top row */
      block_A = (i == 1 || i == 3 || ((i == 0 || i == 2 || i == 4 || i == 5) && 
				      slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos])) ? 
					DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0] : mid_grey*8;
      block_B = ((i == 2 && slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos]) || i == 3) ? 
	DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0] : mid_grey*8;
      block_C = (i == 2 || i == 3) ? DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0] : mid_grey*8;
    }
    else {
      block_A = (i == 1 || i == 3 || ((i == 0 || i == 2 || i == 4 || i == 5) && 
				      slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos])) ?
					DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][0] : mid_grey*8;
      block_B = (((i == 0 || i == 4 || i == 5) && slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos-1]) ||
		 (i == 1 && slice_nb[x_pos][y_pos] == slice_nb[x_pos][y_pos-1]) ||
		 (i == 2 && slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos]) || (i == 3)) ?
		   (DC_store[(y_pos+Ypos[i])*MB_width+(x_pos+Xpos[i])][Ztab[i]][0]) : mid_grey*8;
      block_C = (i == 2 || i == 3 || ((i == 0 || i == 1 || i == 4 || i == 5) && 
				      slice_nb[x_pos][y_pos] == slice_nb[x_pos][y_pos-1])) ?
					DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][0] : mid_grey*8;
    }
    grad_hor = block_B - block_C;
    grad_ver = block_A - block_B;

    if ((ABS(grad_ver)) < (ABS(grad_hor))) {
      DC_pred = block_C;
      direction[i] = 2;
    }
    else {
      DC_pred = block_A;
      direction[i] = 1;
    }

    pcoeff[i*ncoeffs] = qcoeff[i*ncoeffs] - (DC_pred+cal_dc_scaler(QP,(i<4)?1:2)/2)/cal_dc_scaler(QP,(i<4)?1:2);

    /* Find AC predictions */
    if ((x_pos == 0) && y_pos == 0) { /* top left corner */
      if (i == 1 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      else
	nullfill(pred_A,mid_grey);
      if (i == 2 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_C[m] = Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) * (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      else
	nullfill(pred_C,mid_grey);
    }
    else if (x_pos == 0) {	/* left edge */
      if (i == 1 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      else
	nullfill(pred_A,mid_grey);
      if (((i == 0 || i == 1 || i == 4 || i == 5) && slice_nb[x_pos][y_pos] == slice_nb[x_pos][y_pos-1]) || i == 2 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_C[m] =
	    Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) *
	      (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      else
	nullfill(pred_C,mid_grey);
    }
    else if (y_pos == 0) {	/* top row */
      if (((i == 0 || i == 2 || i == 4 || i == 5) && slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos]) || i == 1 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_A[m] =
	    Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) *
	      (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      else
	nullfill(pred_A,mid_grey);
      if (i == 2 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_C[m] = Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) * (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      else
	nullfill(pred_C,mid_grey);
    }
    else {
      if (((i == 0 || i == 2 || i == 4 || i == 5) && slice_nb[x_pos][y_pos] == slice_nb[x_pos-1][y_pos]) || i == 1 || i == 3)
	for (m = 0; m < 15; m++) 
	  pred_A[m] = Idir_c(((DC_store[y_pos*MB_width+(x_pos+Xpos[i])][Xtab[i]][m]) * (QP_store[y_pos*MB_width+(x_pos+Xpos[i])])*2) , 2*QP);
      else
	nullfill(pred_A,mid_grey);
      if (((i == 0 || i == 1 || i == 4 || i == 5) && slice_nb[x_pos][y_pos] == slice_nb[x_pos][y_pos-1]) || i == 2 || i == 3) 
	for (m = 0; m < 15; m++)
	  pred_C[m] =
	    Idir_c(((DC_store[(y_pos+Ypos[i])*MB_width+x_pos][Ytab[i]][m]) *
	      (QP_store[(y_pos+Ypos[i])*MB_width+x_pos])*2) , 2*QP);
      else
	nullfill(pred_C,mid_grey);
		
    }

#if 1				/* I think it should be like this, 14-NOV-1996 MW */
    S1 = 0;
    S2 = 0;
    /* Now decide on AC prediction */
    /* 	if ((i==0 && CBP&32) || (i==1 && CBP&16) || */
    /* 	    (i==2 && CBP&8) || (i==3 && CBP&4) || */
    /* 	    (i==4 && CBP&2) || (i==5 && CBP&1)) { */
    if (direction[i] == 1) {	/* Horizontal, left COLUMN of block A */
      for (m = 0; m < 7; m++) {
	S1 += ABS(qcoeff[i*ncoeffs+(m+1)*8]);
	diff = pcoeff[i*ncoeffs+(m+1)*8] 
	  = qcoeff[i*ncoeffs+(m+1)*8] - pred_A[m+8];
	S2 += ABS(diff);
      }
    }
    else {			/* Vertical, top ROW of block C */
      for (m = 1; m < 8; m++) {
	S1 += ABS(qcoeff[i*ncoeffs+m]);
	diff = pcoeff[i*ncoeffs+m] 
	  = qcoeff[i*ncoeffs+m] - pred_C[m];
	S2 += ABS(diff);
      }
    }
    S += (S1 - S2);
    /* 	} */
#endif
  }
  /* Now change qcoeff for DC pred or DC/AC pred */
  if (S >=0) {
    for (i=0;i<ncoeffs*6; i++)
      /* Modified due to N2171 Cl. 2.2.14 MW 25-MAR-1998 */
      /* if ((i%64)&&(abs(pcoeff[i])>127)) { */
      if ((i%64)&&(abs(pcoeff[i])>2047)) {
	printf("predicted AC out of range");
	S=-1;break;
      }
  }
  if (S >= 0) {			/* Both DC and AC prediction */
    ACpred_flag = 1;
    for (i = 0; i < ncoeffs*6; i++) {
      qcoeff[i] = pcoeff[i];
    }
    /* Update CBP for predicted coeffs. */
    *CBP = FindCBP(qcoeff, MODE_INTRA, 64);
  }
  else {			/* Only DC prediction */
    ACpred_flag = 0;
    for (i = 0; i < 6; i++) {
      qcoeff[i*ncoeffs] = pcoeff[i*ncoeffs];
      direction[i] = 0;
    }
  }
  return ACpred_flag;		/* To be put into bitstream */
}


/**
 * Small routine to fill default prediction values into a DC_store entry
 *
 * Author: 	Robert Danielsen
 * Created: 	23.10.96
 */

Void nullfill(Int pred[], Int mid_grey)
{
  Int i;

  pred[0] = mid_grey*8;
  for (i = 1; i < 15; i++) {
    pred[i] = 0;
  }
}    




/**  Following are programs for Combined motion_texture_shape coding mode
     for B-VOPs */


/***********************************************************CommentBegin******
 *
 * -- B_VopShapeMotText -- Combined motion_shape_texture coding for B-VOPs
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *	Combined Inter encoding of texture and motion.
 * 	Used by VopCodeMotTextInter for B_VOPs
 * 
 * Arguments in : 	
 *   curr, 			current VOP to be encoded		
 *   Image *alpha_decisions, 	sub_sampled alpha_plane 
 *   Image *MB_decisions, 	prediction modes of MBs
 *   Image *mot_x, 		horizontal vector field
 *   Image *mot_y,		vertical vector field
 *   Int f_code_for, 		forward f_code
 *   Int f_code_back,		backward f_code
 *
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *rec_curr : the reconstructed current vop
 * 	Image *mottext_bitstream : the output texture/motion bitstream
 *  Bits *bits : Coding statistics
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *   21-APR-97 Jan De Lameillieure : called grey level alpha coding with the 
 *          grey level (GL) quantiser
 *   31.07.97 Fernando Jaureguizar: added the scalability condition to
 *            be a spatial scalable B-VOP (SpSc)
 *   11.12.97 Support for interlaced video coding
 *
 ***********************************************************CommentEnd********/

Void B_VopShapeMotText (Vop *curr, 
		        Image *alpha_decisions,
		        Image *MB_decisions, 
                        Image *mot_x, 
                        Image *mot_y,
		        Int f_code_for, 
                        Int f_code_back,
     	                Image **First_stream,
		        Image **Shape_stream,
		        Image *GreyLevelAlpha,
		        Image *MotionCompensatedGreyLevelAlpha,
		        Image *ReconstructedGreyLevelAlpha,
		        Vop *rec_curr,
			Image *mottext_bitstream,
			Bits *bits)
{
  Int QP;
  Macroblock* mblock; 
  Int* qcoeff;
  Int i, j,k,l;
  Int CBP;
  Int COD;
  Int MB_in_width, MB_in_height, B_in_width, mbnum, boff;
  SInt p;
  SInt *ptr, *alpha_decis_ptr;
  Float *motx_ptr, *moty_ptr;
  Int num_pixels;
  Int num_lines;
  Int vop_type;
  SInt *alpha_rec;
  Int MB_transp_pattern[4];
  Int DQUANT =0;
  SInt *QP_store;
  Int vop_spat_scal=0;		/*UPS*/

  QP_store = (SInt *) GetImageData(GetVopQP(rec_curr));
  num_pixels = GetImageSizeX(GetVopY(curr));
  num_lines = GetImageSizeY(GetVopY(curr));

  QP = GetVopBQuantizer(curr);

#ifdef _RC_DEBUG_
  printf("RC - B_VopShapeMotText(): ---> CODING WITH: %d \n",QP);
#endif

  /* 10/27 TPS ***/

  MB_in_width = num_pixels / MB_SIZE;
  MB_in_height = num_lines / MB_SIZE;
  B_in_width = 2 * MB_in_width;
  
  mblock = (Macroblock *) malloc (sizeof (Macroblock));
    
  Bits_Reset (bits);

  vop_type = PCT_INTER;

  /* for spat scal (UPS)*/

  if(GetVopScalability(curr) == 1 && /*SpSc*/
     GetVopPredictionType(curr)==B_VOP &&
     GetVopRefSelCode(curr) ==0)
    vop_spat_scal=1;		/* end of ssp (UPS)*/  

  ptr = (SInt *) GetImageData(MB_decisions);
  alpha_decis_ptr = (SInt *) GetImageData(alpha_decisions);
  motx_ptr = (Float *) GetImageData(mot_x);
  moty_ptr = (Float *) GetImageData(mot_y);

  alpha_rec = (SInt *) GetImageData(GetVopA(rec_curr));
  
     
  for (j = 0; j < num_lines/MB_SIZE; j++)
    {
      for (i = 0; i < MB_in_width; i++)
	{
	  if (GetVopArbitraryShape(curr) )
	    {
	      /* write the first_shape_code for this Macroblock to the bit stream */
	      BitstreamAppend(First_stream[j*MB_in_width+i],
			      mottext_bitstream);
	      /* shape data (except first_shape_code) */
	      BitstreamAppend(Shape_stream[j*MB_in_width+i],
			      mottext_bitstream);


	    }
	  if (GetVopShape(curr)==0)
	    MB_transp_pattern[0]=MB_transp_pattern[1]=
	      MB_transp_pattern[2]=MB_transp_pattern[3]=0;
	  else {
	    for (k=0;k<4;k++) MB_transp_pattern[k]=1;
             
	    for(k=0;k<B_SIZE;k++)
	      for(l=0;l<B_SIZE;l++)
		if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
			      (i * MB_SIZE) +l] != 0)
		  MB_transp_pattern[0]=0;
	
	    for(k=0;k<B_SIZE;k++)		
	      for(l=B_SIZE;l<2*B_SIZE;l++)
		if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
			      (i * MB_SIZE) +l] != 0)
		  MB_transp_pattern[1]=0;
	      
	    for(k=B_SIZE;k<2*B_SIZE;k++)
	      for(l=0;l<B_SIZE;l++)
		if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
			      (i * MB_SIZE) +l] != 0)
		  MB_transp_pattern[2]=0;
	      
	    for(k=B_SIZE;k<2*B_SIZE;k++)
	      for(l=B_SIZE;l<2*B_SIZE;l++)
		if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
			      (i * MB_SIZE) +l] != 0)
		  MB_transp_pattern[3]=0;
	  }
 



	  /* Store the QP value for later use in AC prediction */
	  QP_store[j*MB_in_width+i] = (SInt) QP;
	  if (*ptr==-1) {
	    if ((MB_transp_pattern[0]==0)||(MB_transp_pattern[1]==0)||
                (MB_transp_pattern[2]==0)||(MB_transp_pattern[3]==0)) 
	      printf("ERROR!!!!\n");
                               
	  }

	  if ((MB_transp_pattern[0]!=0)&&(MB_transp_pattern[1]!=0)&&
	      (MB_transp_pattern[2]!=0)&&(MB_transp_pattern[3]!=0))
	    *ptr = -1; 
	  COD =1;
	  p = *ptr;		/* p= -1 <---> MB  transparent */
    	   
	  if (p!=-1) { 
	    if ((i==0)&&(j==0)) DQUANT=0;
	    else if (p!=3) 
	      DQUANT = cal_DQuant(QP,B_VOP);
	    else DQUANT=0;

	    qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
			     num_pixels, QP+DQUANT, (p==4)?4:MODE_INTER,
			     MB_transp_pattern, NULL);
   
	    mbnum  = j*MB_in_width + i;
	    boff = (2*j+1)*B_in_width+ i +i+1 ; 
	    CBP = FindCBP(qcoeff,MODE_INTER,64);
	    /*** 10/27 TPS */              
	    if ((((CBP == 0) && (p == 3) && (*(motx_ptr +boff) == 0.0)
		  && (*(moty_ptr +boff) == 0.0))||
		 (p == 4) ||
		 ((CBP == 0) && (p == 0) && (*(motx_ptr +boff-B_in_width-1) == 0.0)
		  && (*(moty_ptr +boff-B_in_width-1) == 0.0)&&(vop_spat_scal)))     &&
		(GetVopRefSelCode(curr) != 1 && GetVopRefSelCode(curr) != 2))    
	      /* 10/27 TPS ***/                   
	      {
		COD = 1;	/* skipped macroblock */
		if (p!=4) {
		  BitstreamPutBits(mottext_bitstream,  0L, 1L);
		  bits->MODB ++;
		} 

	      }
	    else 
	      COD = 0;		/* coded macroblock */

	    if (COD == 0)
	      {		 
		bits->no_intra++; 
		send_MODB_MTYPE(p,CBP,
				vop_spat_scal, /*SpSc*/
				bits,mottext_bitstream);
	      }

	    if (GetVopArbitraryShape(curr) )
	      {
		if (!GetVopBinaryShape(curr) )
		  CodeGreyLevelAlphaAB(curr,i,j,
				       GetVopGLQuantizer(curr),	/* correction JDL 21-APR-97 */
				       MB_decisions,
				       GreyLevelAlpha,
				       MotionCompensatedGreyLevelAlpha,
				       ReconstructedGreyLevelAlpha,
				       mottext_bitstream);
	      }


	    if (COD == 0)
	      {   if (CBP)
                    send_CBPB(MB_transp_pattern,
                              CBP, bits, 
                              mottext_bitstream);
                    /* send DQUANT */
                    if (CBP)  {
		      send_B_DQUANT(p,DQUANT,bits,mottext_bitstream);
		      QP+=DQUANT;          
		      QP_store[j*MB_in_width+i] = (SInt) QP;
                    }
                    send_B_Motion_Vector(mot_x,mot_y, MB_decisions,
                                         i, j, f_code_for, f_code_back,
					 vop_spat_scal,	/*UPS*/
					 bits, mottext_bitstream,
					 GetVopErrorResDisable(curr),
					 0);         
 		   
		    MB_CodeCoeff(bits, qcoeff, MODE_INTER, CBP, 64, 
				 1,
				 NULL, mottext_bitstream,
				 MB_transp_pattern, NULL,
				 GetVopErrorResDisable(curr),
				 GetVopReverseVlc(curr), 0, 0);
		  }
	    free ((Char*)qcoeff);
	  }

	  ptr++;
	}
    }
    
  free ((Char*)mblock);
}

/***********************************************************CommentBegin******
 *
 * -- B_MBShapeMotTextErrRes -- Combined motion_shape_texture coding for B-VOPs
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *	Combined Inter encoding of texture and motion.
 * 	Used by VopCodeMotTextInter for B_VOPs
 * 
 * Arguments in : 	
 *   curr, 			current VOP to be encoded		
 *   Image *alpha_decisions, 	sub_sampled alpha_plane 
 *   Image *MB_decisions, 	prediction modes of MBs
 *   Image *mot_x, 		horizontal vector field
 *   Image *mot_y,		vertical vector field
 *   Int f_code_for, 		forward f_code
 *   Int f_code_back,		backward f_code
 *
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *rec_curr : the reconstructed current vop
 * 	Image *mottext_bitstream : the output texture/motion bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *   21-APR-97 Jan De Lameillieure : called grey level alpha coding with the 
 *          grey level (GL) quantiser
 *   31.07.97 Fernando Jaureguizar: added the scalability condition to
 *            be a spatial scalable B-VOP (SpSc)
 *	 13.01.98 Noel Brady: mods to allow proper motion vector prediction in 
 *							error resilient mode
 *
 ***********************************************************CommentEnd********/

Void B_MBShapeMotTextErrRes (Vop *curr, 
			     Image *alpha_decisions,
			     Image *MB_decisions, 
			     Image *mot_x, 
			     Image *mot_y,
			     Int f_code_for, 
			     Int f_code_back,
			     Image **First_stream,
			     Image **Shape_stream,
			     Image *GreyLevelAlpha,
			     Image *MotionCompensatedGreyLevelAlpha,
			     Image *ReconstructedGreyLevelAlpha,
			     Vop *rec_curr,
			     Image *mottext_bitstream,
			     Int i,
			     Int j,
			     Int *num_bits_MB_ptr,
			     Int **slice_nb,
			     Bits *bits)
{
  Int QP;
  Macroblock* mblock; 
  Int* qcoeff;
  Int k,l;
  Int CBP;
  Int COD;
  Int MB_in_width, MB_in_height, B_in_width, mbnum, boff;
  SInt p;
  SInt *ptr, *alpha_decis_ptr, *pp;
  Float *motx_ptr, *moty_ptr;
  Int num_pixels;
  Int num_lines;
  Int vop_type;
  SInt *alpha_rec;
  Int MB_transp_pattern[4];
  Int DQUANT =0;
  SInt *QP_store;
  Int vop_spat_scal=0;		/*UPS*/

  Int shape_bits=0,
  tmp_bits;

  static Int init_mvp;

  if (i>0 && (slice_nb[i][j] != slice_nb[i-1][j])) init_mvp = 1;

  QP_store = (SInt *) GetImageData(GetVopQP(rec_curr));
  num_pixels = GetImageSizeX(GetVopY(curr));
  num_lines = GetImageSizeY(GetVopY(curr));

  QP = GetVopBQuantizer(curr);

#ifdef _RC_DEBUG_
  printf("RC - B_MBShapeMotTextErrRes(): ---> CODING WITH: %d \n",QP);
#endif

  /* 10/27 TPS ***/

  MB_in_width = num_pixels / MB_SIZE;
  MB_in_height = num_lines / MB_SIZE;
  B_in_width = 2 * MB_in_width;
  
  mblock = (Macroblock *) malloc (sizeof (Macroblock));
    
  Bits_Reset (bits);

  vop_type = PCT_INTER;

  /* for spat scal (UPS)*/

  if(GetVopScalability(curr) == 1 && /*SpSc*/
     GetVopPredictionType(curr)==B_VOP &&
     GetVopRefSelCode(curr) ==0)
    vop_spat_scal=1;		/*end of ssp (UPS)*/  

  ptr = (SInt *) GetImageData(MB_decisions);
  alpha_decis_ptr = (SInt *) GetImageData(alpha_decisions);
  motx_ptr = (Float *) GetImageData(mot_x);
  moty_ptr = (Float *) GetImageData(mot_y);

  alpha_rec = (SInt *) GetImageData(GetVopA(rec_curr));
  
     
  if (GetVopArbitraryShape(curr) )
    {
      tmp_bits = GetImageSizeX(mottext_bitstream);
	      
      /* write the first_shape_code for this Macroblock to the bit stream */
      BitstreamAppend(First_stream[j*MB_in_width+i],
		      mottext_bitstream);
      /* shape data (except first_shape_code) */
      BitstreamAppend(Shape_stream[j*MB_in_width+i],
		      mottext_bitstream);
	      
      shape_bits = GetImageSizeX(mottext_bitstream)-tmp_bits;
    }
            
  if (GetVopShape(curr)==0)
    MB_transp_pattern[0]=MB_transp_pattern[1]=
      MB_transp_pattern[2]=MB_transp_pattern[3]=0;
  else {
    for (k=0;k<4;k++) MB_transp_pattern[k]=1;
             
    for(k=0;k<B_SIZE;k++)
      for(l=0;l<B_SIZE;l++)
	if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
		      (i * MB_SIZE) +l] != 0)
	  MB_transp_pattern[0]=0;
	
    for(k=0;k<B_SIZE;k++)		
      for(l=B_SIZE;l<2*B_SIZE;l++)
	if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
		      (i * MB_SIZE) +l] != 0)
	  MB_transp_pattern[1]=0;
	      
    for(k=B_SIZE;k<2*B_SIZE;k++)
      for(l=0;l<B_SIZE;l++)
	if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
		      (i * MB_SIZE) +l] != 0)
	  MB_transp_pattern[2]=0;
	      
    for(k=B_SIZE;k<2*B_SIZE;k++)
      for(l=B_SIZE;l<2*B_SIZE;l++)
	if (alpha_rec[((j * MB_SIZE) +k)*num_pixels + 
		      (i * MB_SIZE) +l] != 0)
	  MB_transp_pattern[3]=0;
  }
 



  /* Store the QP value for later use in AC prediction */
  QP_store[j*MB_in_width+i] = (SInt) QP;

  pp = ptr + (j*MB_in_width+i);
  p = *pp;			/* p= -1 <---> MB  transparent */
    	   
  if (*pp==-1) {
    if ((MB_transp_pattern[0]==0)||(MB_transp_pattern[1]==0)||
	(MB_transp_pattern[2]==0)||(MB_transp_pattern[3]==0)) 
      printf("ERROR!!!!\n");
                               
  }

  if ((MB_transp_pattern[0]!=0)&&(MB_transp_pattern[1]!=0)&&
      (MB_transp_pattern[2]!=0)&&(MB_transp_pattern[3]!=0))
    *pp = -1; 
  COD =1;
    	   
  if (p!=-1) { 
    if ((i==0)&&(j==0)) DQUANT=0;
    else if (p!=3) 
      DQUANT = cal_DQuant(QP,B_VOP);
    else DQUANT=0;

    qcoeff = CodeMB (curr, rec_curr, i*MB_SIZE, j*MB_SIZE,
		     num_pixels, QP+DQUANT, (p==4)?4:MODE_INTER, MB_transp_pattern, NULL);
   
    mbnum  = j*MB_in_width + i;
    boff = (2*j+1)*B_in_width+ i +i+1 ; 
    CBP = FindCBP(qcoeff,MODE_INTER,64);
    /*** 10/27 TPS */              
    if ((((CBP == 0) && (p == 3) && (*(motx_ptr +boff) == 0.0)
	  && (*(moty_ptr +boff) == 0.0))||
	 (p == 4) ||
	 ((CBP == 0) && (p == 0) && (*(motx_ptr +boff-B_in_width-1) == 0.0)
	  && (*(moty_ptr +boff-B_in_width-1) == 0.0)&&(vop_spat_scal)))     &&
	(GetVopRefSelCode(curr) != 1 && GetVopRefSelCode(curr) != 2))    
      /* 10/27 TPS ***/                   
      {
	COD = 1;		/* skipped macroblock */
	if (p!=4) {
	  BitstreamPutBits(mottext_bitstream,  0L, 1L);
	  bits->MODB ++;
	} 

      }
    else 
      COD = 0;			/* coded macroblock */

    if (COD == 0)
      {		 
	bits->no_intra++; 
	send_MODB_MTYPE(p,CBP,
			vop_spat_scal, /*SpSc*/
			bits,mottext_bitstream);
      }

    if (GetVopArbitraryShape(curr) )
      {
	if (!GetVopBinaryShape(curr) )
	  CodeGreyLevelAlphaAB(curr,i,j,
			       GetVopGLQuantizer(curr),	/* correction JDL 21-APR-97 */
			       MB_decisions,
			       GreyLevelAlpha,
			       MotionCompensatedGreyLevelAlpha,
			       ReconstructedGreyLevelAlpha,
			       mottext_bitstream);
      }


    if (COD == 0)
      {   if (CBP)
	    send_CBPB(MB_transp_pattern,
		      CBP, bits, 
		      mottext_bitstream);
	    /* send DQUANT */
	    if (CBP)  {
	      send_B_DQUANT(p,DQUANT,bits,mottext_bitstream);
	      QP+=DQUANT;          
	      QP_store[j*MB_in_width+i] = (SInt) QP;
	    }

	    send_B_Motion_Vector(mot_x,mot_y, MB_decisions,
				 i, j, f_code_for, f_code_back,
				 vop_spat_scal,	/*UPS*/
				 bits, mottext_bitstream,
				 GetVopErrorResDisable(curr),
					 
				 init_mvp
				 );
	    init_mvp=0;         
 		   
	    MB_CodeCoeff(bits, qcoeff, MODE_INTER, CBP, 64, 
			 1,
			 NULL, mottext_bitstream,
			 MB_transp_pattern, NULL,
			 GetVopErrorResDisable(curr),
			 GetVopReverseVlc(curr), 0, 0);
	  }
    free ((Char*)qcoeff);
  }


    
  *num_bits_MB_ptr = shape_bits + bits->MODB + bits->MBTYPE +
    bits->CBPB + bits->DQUANT + bits->Y + bits->C + bits->vec;

  free ((Char*)mblock);
}



/***********************************************************CommentBegin******
 *
 * -- send_MODB_MTYPE -- Encode MODB and MTYPE for B-VOPs
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *
 * 
 * Arguments in : 	
 *    Int Mode, 		Prediction mode of a B-MB
 *    Int CBPB, 			Coded block pattern
 *    Int scal, 			Spatial scalability flag (SpSc)
 *
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *bits :		number of bits
 * 	Image *bitstream : 	the output bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	  30.07.97 Fernando Jaureguizar: Modifications to allow Spat. Scal. (SpSc)
 *
 ***********************************************************CommentEnd********/
Void  send_MODB_MTYPE(Int Mode, 
                      Int CBPB, 
                      Int scal, /*SpSc*/
                      Bits* bits, 
                      Image *bitstream)
{                   
  /* send MODB  */
  if (CBPB==0) 
    BitstreamPutBits(bitstream, 2L, 2L);
  else 
    BitstreamPutBits(bitstream,3L, 2L);
  bits->MODB +=2;

  /* send MBTYPE */
  if (Mode==3) {		/* direct mode */
    BitstreamPutBits(bitstream, 1L, 1L);
    bits->MBTYPE++;
    /*>SpSc*/
    if(scal)
      {
	fprintf(stderr,
		"ERROR: Direct Mode not allowed in B-Vop with Spat. Scal.\n");
	exit(-1);
      }
    /*SpSc<*/
  }
  else if (Mode==2) {		/* interploate */
    BitstreamPutBits(bitstream, 1L, 2L);
    bits->MBTYPE+=2;
  }
  else if (Mode==1) {		/* backward */
    BitstreamPutBits(bitstream, 1L, 3L);
    bits->MBTYPE+=3;
  }
  else {			/* forward */
    /*>SpSc*/
    if(scal)
      {
	BitstreamPutBits(bitstream, 1L, 1L);
	bits->MBTYPE++;
      }
    else
      /*SpSc<*/
      {
	BitstreamPutBits(bitstream, 1L, 4L);
	bits->MBTYPE+=4;
      }
  }
}

/***********************************************************CommentBegin******
 *
 * -- send_CBPB -- Encode CBPB for B-VOPs
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *
 * 
 * Arguments in : 	
 *    Int *MB_transp_pattern 	Block-transparencies of MB  
 *    Int CBPB, 		Coded block pattern

 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *bits :		number of bits
 * 	Image *bitstream : 	the output bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/


Void  send_CBPB(Int *MB_transp_pattern,
		Int CBPB, 
		Bits *bits, 
		Image *bitstream)
{
  Int k;
  static Int mask[6]={32,16,8,4,2,1};
  
  for (k=0;k<6;k++) 
    if ((k < 4 && MB_transp_pattern[k] != 1) || (k > 3)) {
      BitstreamPutBits(bitstream, (CBPB&mask[k])?1L:0L, 1L);
      bits->CBPB++;
    }
}

/***********************************************************CommentBegin******
 *
 * -- send_B_DQUANT -- Encode DQUANT for B-VOPs
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *
 * 
 * Arguments in : 	
 *    Int Mode 			Prediction mode  
 *    Int DQUANT, 		Differential MQUANT

 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *bits :		number of bits
 * 	Image *bitstream : 	the output bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	
 *
 ***********************************************************CommentEnd********/

Void send_B_DQUANT(Int Mode, 
                   Int DQUANT,
                   Bits *bits, 
                   Image *bitstream) {
  if (Mode!=3) {		/* there is no DQUANT for direct mode */
    if (DQUANT==0) {
      BitstreamPutBits(bitstream, 0L, 1L);
      bits->DQUANT++;
    } else if (DQUANT==-2) {
      BitstreamPutBits(bitstream, 2L, 2L);
      bits->DQUANT+=2;
    } else if (DQUANT==2) {
      BitstreamPutBits(bitstream, 3L, 2L);
      bits->DQUANT+=2;
    } else {
      fprintf(stdout,"Invaild DQUANT in B-VOPs");
    }
  } 
}



/***********************************************************CommentBegin******
 *
 * -- send_B_Motion_Vector -- Encode Motion vector of a B-MB
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *
 * 
 * Arguments in : 	
 *	 Image *mot_x,		horizontal vector field	
 *       Image *mot_y, 		vertical vector field
 *       Image *modes,		prediction modes
 *       Int i, Int j, 		macroblock address
 *       Int f_code_for,	forward f_code	
 *	 Int f_code_back, 	backward f_code
 *       Int scal,              spatial-scalability-flag (UPS)   
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *bits :		number of bits
 * 	Image *bitstream : 	the output bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *   30.07.97 Fernando Jaureguizar: Modifications to allow Spat. Scal. (SpSc)
 *   09.12.97 Luis Ducla-Soares: modifications to allow the error resilient mode.
 *		13.1.98 Noel Brady: added parameter init_mvp in order to allow 
 *					error resilient B_VOPs with shape.
 *
 ***********************************************************CommentEnd********/


Void  send_B_Motion_Vector(Image *mot_x, 
			   Image *mot_y, 
			   Image *modes,
			   Int i, Int j, 
			   Int f_code_for, Int f_code_back,
			   Int scal, /*UPS*/
			   Bits *bits, 
			   Image *bitstream,
			   Int error_res_disable,
			   Int init_mvp) {
  Int     MB_num_x;		/* Dimensions in macroblocks */
  Float   *mv_x, *mv_y;		/* Motion vectors            */
  SInt    *pred_m;		/* Modes                     */
  Int     B_num_x,index,Mode,Mode_prevs;
  SInt vx,vy;
  static SInt Px_for,Py_for,Px_back,Py_back;
  static Int  prev_j = -1;
  if (prev_j != j){
    Px_for  = Py_for  = 0;
    Px_back = Py_back = 0;
    prev_j = j;
  }
  
  if (!error_res_disable)
    {
      if (i != 0)
	{
	  if (init_mvp)
	    {
	      Px_for  = Py_for  = 0;
	      Px_back = Py_back = 0;
	    }
	}
    }
  
  MB_num_x=(Int)GetImageSizeX(modes);
  mv_x=(Float*)GetImageData(mot_x);
  mv_y=(Float*)GetImageData(mot_y);
  pred_m=(SInt*)GetImageData(modes);
  B_num_x=2*MB_num_x; 
  index = (j+j)*B_num_x+i+i;
  Mode = pred_m[j*MB_num_x+i];
  if (i>0)
    Mode_prevs =  pred_m[j*MB_num_x+i-1];
  else Mode_prevs = 2;
  
  if ((Mode==0)||(Mode==2)) {	/* forward + interplo. */
    vx = (SInt)(2.0*mv_x[index]); vy= (SInt)(2.0*mv_y[index]);
    send_vector(vx,vy,Px_for,Py_for,
		f_code_for,f_code_for,bits,bitstream);
    Px_for = vx; Py_for  = vy;
               
  } 
  if ((Mode==1)||(Mode==2)) {	/* backward + interplo. */
    vx = (SInt)(2.0*mv_x[index+1]); vy= (SInt)(2.0*mv_y[index+1]);
              
    if(!scal)			/*SpSc: spatial scal B-Vop => no BW MV */ {
      send_vector(vx,vy,Px_back,Py_back,
		  f_code_back,f_code_back,bits,bitstream);
      Px_back = vx; Py_back = vy;
    }
  }  
  if (Mode==3) {		/* direct mode */
    vx = (SInt)(2.0*mv_x[index+1+B_num_x]);
    vy= (SInt)(2.0*mv_y[index+1+B_num_x]);
    send_vector(vx,vy,0,0,1,1,bits,bitstream); 
  }
}

 
/***********************************************************CommentBegin******
 *
 * -- send_vector -- Encode a single motion vector
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.03.97		
 *	
 *
 * Purpose :		
 *
 * 
 * Arguments in : 	
 *		SInt vx, SInt vy, 		vector to be coded	
 *              SInt Px, SInt Py, 		vector predictor
 *              Int f_code_horizontal,		horizontal f_code
 *              Int f_code_vertical, 		vertical f_code
 * Arguments in/out :	
 *	
 * Arguments out :	
 *	Vop *bits :		number of bits
 * 	Image *bitstream : 	the output bitstream
 *
 * Return values :	
 *	
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 *	   14.05.97 F. Jaureguizar: Modifications to cope with enlarged f_code
 *       range (VM7.0).
 *
 ***********************************************************CommentEnd********/


  
Void send_vector ( SInt vx, SInt vy, 
		  SInt Px, SInt Py, 
		  Int f_code_horizontal,
		  Int f_code_vertical,
		  Bits *bits, 
		  Image *bitstream) 
{
  Int diff_vector,residual,vlc_code_magnitude;
  Int f_code,i,sign;
  static Int range[7]={32,64,128,256,512,1024,2048}; /* 2*range*/
  static Int scale_factor[7]={1,2,4,8,16,32,64};
 
  for (i=0;i<2;i++) {
    if (i==0) { 
      diff_vector=vx-Px;
      f_code=f_code_horizontal-1;
    } else {
      diff_vector=vy-Py;
      f_code=f_code_vertical-1;
    }
 
    if (diff_vector<-range[f_code]) 
      diff_vector+=range[f_code]+range[f_code];
    else  if (diff_vector>range[f_code]-1)
      diff_vector-=range[f_code]+range[f_code];
    sign=((diff_vector<0)?1:0);
    if (diff_vector==0) {
      residual=0;
      vlc_code_magnitude=0;
    } else {
      if (diff_vector<0) diff_vector=-diff_vector; 
      residual=(diff_vector-1)%scale_factor[f_code];
      vlc_code_magnitude=(diff_vector-residual)/scale_factor[f_code];
      if (scale_factor[f_code]!=1) vlc_code_magnitude++;  
    }
    BitstreamPutBits (bitstream, mvtab[vlc_code_magnitude].code, mvtab[vlc_code_magnitude].len);
    if (bits!=NULL) bits->vec+=mvtab[vlc_code_magnitude].len; 
    if (vlc_code_magnitude) {
      BitstreamPutBits (bitstream, (Int)sign, 1L);
      if (bits!=NULL)  bits->vec++;
    }    
    if ((vlc_code_magnitude<-32)||(vlc_code_magnitude>32)) printf("error!!!\n");
    if ((diff_vector)&&(f_code)) {      
      BitstreamPutBits (bitstream,(Int) residual, (Int) f_code);
      if (bits!=NULL) bits->vec+=f_code;
    }
  }
}


/***********************************************************CommentBegin******
 *
 * -- cal_DQuant -- generate a pseduo DQUANT
 *
 * Author : Minhua Zhou 		
 *	
 *
 * Created : 12.08.97		
 *	
 *
 * Purpose :		
 *
 * 
 * Arguments in : 	
 *   Int Qp,Int pred_type 
 * Arguments in/out :	
 *	
 * Arguments out :	
 *
 * Return values :	
 *	 DQUANT
 *
 * Side effects :	
 *	
 *
 * Description :	
 *	
 *
 * See also :
 *	
 *
 * Modified :		
 ***********************************************************CommentEnd********/


Int cal_DQuant(Int Qp,Int pred_type) {
  Int DQ=0;
 #ifdef _PSEDUO_RATE_CONTROL_ 
  if (pred_type==B_VOP) 
    DQ = (rand()%3-1)*2;
  else DQ= rand()%5-2;
  
  if (Qp+DQ<6) DQ=0; 
  else if (Qp+DQ>31) DQ=0;
  #endif
  return DQ;
}  


   
/* hjlee */
Int GetDquant(Int Qp,Int PreQp, Int pred_type) 
{
  Int DQ=0;
  DQ = Qp - PreQp;
  if(pred_type==B_VOP)
    {
      if(DQ>2) DQ = 2;
      else if(DQ==1) DQ = 0;
      else if(DQ==-1) DQ = 0;
      else if(DQ<-2) DQ = -2;
    }
  else
    {
      if(DQ>2) DQ = 2;
      else if(DQ<-2) DQ = -2;
    }
  return DQ;
}


Int Idir_c(Int val, Int QP) {

   if (val<0) return (val-QP/2)/QP;
     else return (val+QP/2)/QP;
}
