/*****************************************************************************
 "This software module was originally developed by:
	
	Noboru Yamaguchi (TOSHIBA CORPORATION), Takashi Ida (TOSHIBA CORPORATION) 

	and edited by:

	 	Toshiaki Watanabe (TOSHIBA CORPORATION), 
		Yoshihiro Kikuchi (TOSHIBA CORPORATION), 
		Noel Brady (TELTEC IRELAND)
	
	in the course of development of the <MPEG-4 Video(ISO/IEC 14496-2)>. 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)
  >. ISO/IEC gives users of the <MPEG-4 Video(ISO/IEC 14496-2)> 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
  )>. 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)>
  conforming products. TOSHIBA CORPORATION retains 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)> conforming products. This copyright notice must be included in
  all copies or derivative works. Copyright (c)1996".
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:	alp_code_mom.c
 *
 * Author:	TOSHIBA + Noel Brady Teltec Irl.
 * Created:	11-04-97
 *                                                                         
 * Description: Contains high level functions implementing binary shape coding
 *							as per VM7
 *
 * Modified:
 *
 *    16.06.97 Angel Pacheco: unified the TRANSPARENT modes.
 *		06.08.97 Noel Brady: Added mods for BINARY_SHAPE_ONLY
 *                                 
 ***********************************************************HeaderEnd*********/


/********* header ********/

#include<stdio.h>
#ifndef WIN32
#include<values.h>
#endif
#include <string.h>
#include "momusys.h"
#include "mom_structs.h"
#include "mom_access.h"
#include "vm_enc_defs.h"
#include "vm_config.h"					/* BSO_NOEL */
#include "alp_common_def.h"
#include "mot_est.h"
#include "alp_common_cae.h"
#include "alp_common_util.h"
#include "alp_code_mom.h"
#include "alp_code_header.h"
#include "alp_code_decisions.h"
#include "alp_code_cae.h"
#include "alp_code_mc.h"

extern Int 	total_first_bits[3],
						total_second_bits[3],
						total_amv_bits[3],
						total_cae_bits[3],
						total_cae_intra_bits[3],
						total_cae_inter_bits[3],
						total_coded_mbs[3],
						total_coded_intra_mbs[3],
						total_coded_inter_mbs[3],
						curr_first_bits,
						curr_second_bits,
						curr_amv_bits,
						curr_cae_bits,
						curr_cae_intra_bits,
						curr_cae_inter_bits,
						curr_coded_mbs,
						curr_coded_intra_mbs,
						curr_coded_inter_mbs;

Image 	*alpha_rec_packet = NULL,
				*alpha_mode_packet = NULL;

/***********************************************************CommentBegin******
 *
 * -- VopShapeCode -- Produces all the bitstream elements for all
 *											BABs in a given Vop and produces the reconstructed
 *											alpha map..
 *
 * Author :		
 *	Noel Brady Teltec Irl.
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					curr - the input vop containing the binary
 *									alpha map
 *					rec_prev - the previously reconstructed VOP
 *					x,y - the top-left pixel coordinate of the BAB
 *					thresh - alpha threshold
 *					mot_x,mot_y - motion vector field used for texture MC
 *					MB_decisions - the coding modes for all texture MBs
 *
 * Arguments In/Out:
 *
 * Arguments Out:
 *					rec_curr - the reconstructed VOP with coded alpha map.
 *					alpha_decisions - the blockwise transparancy decisons 
 *					First_stream - contains all first_shape_codes
 *					Shape_stream - contains all the rest of the shape related codes
 *
 * Return values :
 *					the number of bits generated.
 *
 * Side effects :	
 *	-
 *
 * Description : As per VM7
 *
 * See also :
 * Modified: 
 *     06.08.97 Minhua Zhou: set the motion vectors to zero 
 *                           for MBs changing from non-transparent
 *                           to transparent after shape coding. This setting
 *                           is essential
 *                           for B-VOPs which utilize vectors of I-, P-VOPs
 *                           during coding
 *		19.11.97 Noel Brady: ShapeCodeMB computes the reconstructed values for
 *													the Auv blocks also.
 *		19.11.97 Noel Brady: conditions fro use of ModifyModesandMVs() is changed
 *
 ***********************************************************CommentEnd********/
Int
VopShapeCode(Vop *curr,
						Vop *rec_curr,
						Vop *rec_prev,
						Int vo_id,
						Int thresh,
						Image *mot_x,
						Image *mot_y,
						Image *MB_decisions,
						Image *alpha_decisions,
						Image **First_stream,
						Image **Shape_stream
	     )
{
  Image *modeA; /* the flag of current alpha block is inter coded or not */
  Image *motA_x; /* the x compornent of shape MV */
  Image *motA_y; /* the y compornent of shape MV */
  Int first_bits, shape_bits, total_shape_bits = 0;
  Int i, j, k;
  UChar first_stream[7], shape_stream[4096];

  /* Allocate shape ME/MC */
  modeA = AllocImage(GetVopWidth(curr)/MB_SIZE,
		     GetVopHeight(curr)/MB_SIZE,SHORT_TYPE);
  motA_x = AllocImage(GetVopWidth(curr)/MB_SIZE,
		      GetVopHeight(curr)/MB_SIZE,SHORT_TYPE);
  motA_y = AllocImage(GetVopWidth(curr)/MB_SIZE,
		      GetVopHeight(curr)/MB_SIZE,SHORT_TYPE);

  for(i=0; i<GetVopHeight(curr)/MB_SIZE; i++) {
    for(j=0; j<GetVopWidth(curr)/MB_SIZE; j++) {
      k = i*(GetVopWidth(curr)/MB_SIZE)+j;
      shape_bits = ShapeCodeMB(curr,
								rec_curr,
								rec_prev,
								vo_id,
								i,
								j,
								thresh,
								modeA,
								mot_x,
								mot_y,
								motA_x,
								motA_y,
								MB_decisions,
								alpha_decisions,
								&first_bits,
								first_stream,
								shape_stream,
								0
			       );
      BitstreamAppendTtoM(First_stream[k], first_stream, first_bits);
      BitstreamAppendTtoM(Shape_stream[k], shape_stream, shape_bits);
			total_shape_bits += shape_bits + first_bits;
    }
}
				
  /* Free shape ME/MC */
  FreeImage(modeA);
  FreeImage(motA_x);
  FreeImage(motA_y);
	return total_shape_bits;
}

Int
ShapeCodeMB(Vop *curr,
	    Vop *rec_curr,
	    Vop *rec_prev,
			Int vo_id,
	    Int adr_i,
	    Int adr_j,
	    Int thresh,
	    Image *modeA,
	    Image *mot_x,
	    Image *mot_y,
	    Image *motA_x,
	    Image *motA_y,
	    Image *MB_decisions,
			Image *alpha_decisions,
	    Int *first_bits,
	    UChar *first_stream,
	    UChar *shape_stream,
			Int start_of_packet
	    )
{
  /* SAIT begin */
  Image
    *tmp,
    *bordered_smb_data,
    *top_border_data = AllocImage(MB_SIZE+4,2,SHORT_TYPE),
    *left_border_data = AllocImage(2,MB_SIZE,SHORT_TYPE);
 
  SInt *p;
  Int   j;
  /* SAIT end */

  Int vol_id = GetVopId(curr);

  Image 
    *mblock,
    *mblock_rec,
		*block_rec,
		*rec_prev_alpha,
		*rec_alpha;

  SInt	pred[MB_SIZE][MB_SIZE],
				*a_mb,
				*a_mb_rec,
				*a_b_rec;

  Int
		error_res_disable,
    width=GetVopWidth(curr),
    second_bits=0,
    cae_bits=0,
    amvbits=0,
    mb_bits=0,
    mvda,
    shape_inter,
    mb_type,
    i,
    x,y,
    h,v;

  Int flag,
			send_cr;

  UChar
    alpha_mb[MB_SIZE*MB_SIZE],
    alpha_mb_comp[MB_SIZE*MB_SIZE],
    alpha_smb[MB_SIZE*MB_SIZE],
    first_shape_code[7],
    second_code[2],
    cae_stream[4096],
    mv_stream[32];

  Int 	ox=0,oy=0;


  for (x=0;x<MB_SIZE;x++)
    for (y=0;y<MB_SIZE;y++) 
       pred[x][y]=0;

  if (GetVopPredictionType(curr) != I_VOP 
			&& GetVopShapeCodingType(curr) ) flag = 1;
  else flag = 0;
			
  error_res_disable = GetVopErrorResDisable(curr);

  if ( (!error_res_disable) && (start_of_packet == 1)) 
  {
	SetConstantImage(alpha_rec_packet,0);
	if (!flag) SetConstantImage(alpha_mode_packet,0);
	else SetConstantImage(modeA,0);
  }

  mblock           = AllocImage(16,16,SHORT_TYPE);
  mblock_rec       = AllocImage(16,16,SHORT_TYPE);

  a_mb = (SInt *) GetImageData(mblock);
  a_mb_rec = (SInt *) GetImageData(mblock_rec);

  x = adr_j * MB_SIZE;
  y = adr_i * MB_SIZE;	

  amvbits=ShapeInterMB(curr,
						rec_prev,
						pred,
						modeA,
						mot_x,
						mot_y,
						motA_x,
						motA_y,
						MB_decisions,
						alpha_decisions,
						&mvda,
						&shape_inter,
						mv_stream,
						thresh,
						width,
						adr_i,
						adr_j
		       );
			
	/* mvda = 1 means mvds=0 */

  GetSubImage(GetVopA(curr),mblock,x,y);
	  
  for( v=0; v<MB_SIZE; v++) for( h=0; h<MB_SIZE; h++ ) {
    alpha_mb[v*MB_SIZE+h] = BINARISE((UChar)a_mb[v*MB_SIZE+h]);
    alpha_mb_comp[v*MB_SIZE+h] = (UChar)pred[v][h];
  }
			
  /* Detect shape_mode */

  mb_type=AlphaModeDecision( alpha_mb, alpha_mb_comp, shape_inter, mvda, thresh);


  if( mb_type == 2) 	/* in the case of a coded BAB */
  {
    	for( v=0; v<MB_SIZE; v++ ) 
	for( h=0; h<MB_SIZE; h++ )
      		alpha_mb[h*MB_SIZE+v] = f1bit(alpha_mb[h*MB_SIZE+v]);	

	/* get the subsampled and reconstructed MBs */

      /*** SAIT begin ***/
      if (error_res_disable)
      {
     	if (y>1) GetSubImage(GetVopA(rec_curr),top_border_data,x-2,y-2);
      	else SetConstantImage(top_border_data,0);
      	if (x>1) GetSubImage(GetVopA(rec_curr),left_border_data,x-2,y);
      	else SetConstantImage(left_border_data,0);
      } else 
      {
     	if (y>1) GetSubImage(alpha_rec_packet,top_border_data,x-2,y-2);
      	else SetConstantImage(top_border_data,0);
      	if (x>1) GetSubImage(alpha_rec_packet,left_border_data,x-2,y);
      	else SetConstantImage(left_border_data,0);
      }

      BinariseImage(top_border_data);
      BinariseImage(left_border_data);
 
      bordered_smb_data = AllocImage(MB_SIZE+4,MB_SIZE+4,SHORT_TYPE);
      /*** SAIT end ***/


	if (GetVopChangeCRDisable(curr)) 
	{
		send_cr = 0;
#ifndef _VM7_FILTER_
   		for(i=0;i<MB_SIZE*MB_SIZE;i++) alpha_smb[i]=alpha_mb[i];
#else
    		ChangeSamplingRate( alpha_mb, alpha_smb, MB_SIZE, MB_SIZE, MB_SIZE, MB_SIZE );
#endif

          /*** SAIT begin ***/
          PutSubImage(bordered_smb_data,top_border_data,0,0);
          PutSubImage(bordered_smb_data,left_border_data,0,2);
/* Free displaced to the end of the file : for leakage problem: Dufour 15.04.98 */
/*
          FreeImage(top_border_data);
          FreeImage(left_border_data);
*/
          p = (SInt *) GetImageData(bordered_smb_data)
            + 2*GetImageSizeX(bordered_smb_data) + 2;
          for( i=0; i<MB_SIZE; i++)
            for( j=0; j<MB_SIZE; j++) {
              p[GetImageSizeX(bordered_smb_data)*i+j]
                = (SInt) alpha_smb[i*MB_SIZE+j];
            }
          tmp = AllocImage(2,1,SHORT_TYPE);
          GetSubImage(bordered_smb_data,tmp,0,MB_SIZE+1);
          PutSubImage(bordered_smb_data,tmp,0,MB_SIZE+2);
          PutSubImage(bordered_smb_data,tmp,0,MB_SIZE+3);
          FreeImage(tmp);
          /*** SAIT end ***/

	}
	else 
	{
	  /* SAIT begin */
	  	/******* comment out
		if (error_res_disable) rec_alpha = GetVopA(rec_curr);
		else rec_alpha = alpha_rec_packet;
		mb_type = DetectCR( rec_alpha, x, y, alpha_mb, alpha_smb, thresh );
	  	*********************/
	  if (error_res_disable) rec_alpha = GetVopA(rec_curr);
	  else rec_alpha = alpha_rec_packet;

          mb_type = DetectCR( rec_alpha, x, y, alpha_mb, alpha_smb, thresh,
                             bordered_smb_data,
                             top_border_data, left_border_data);
/* Free displaced to the end of the file : for leakage problem: Dufour 15.04.98 */
/*
          FreeImage(top_border_data);
          FreeImage(left_border_data);
*/
	  /* SAIT end */

		send_cr = 1;

	}
 
 	/* encode the BAB using CAE*/

   	if( mb_type >= 2 && mb_type <= 4 )
	{
		if (flag == 1) 
		{
			rec_prev_alpha = GetVopA(rec_prev);
  			ox = GetVopHorSpatRef(curr) - GetVopHorSpatRef(rec_prev);
 			oy = GetVopVerSpatRef(curr) - GetVopVerSpatRef(rec_prev);
		}
		else rec_prev_alpha = NULL;

					cae_bits=CAE_MB(rec_prev,
							bordered_smb_data, /*SAIT*/
								alpha_mb_comp,
								x,
								y,
								ox,
								oy,
								GetVopA(rec_curr),
								rec_prev_alpha,
								alpha_rec_packet,
								motA_x,
								motA_y,
								shape_inter,
								mvda,
								amvbits,
								send_cr,
								&mb_type,
								cae_stream,	
								vo_id,
								vol_id,
								error_res_disable);

    	}
	else
	{
      		cae_bits=0;
    	}

	if (mb_type==5) mb_type+=mvda; /* inter and coded */

  	}
	else cae_bits=0;

	if( (mb_type == -1) || (mb_type >= 5)) 
		{
			*((SInt *)GetImageData(modeA)+adr_i*(width/MB_SIZE)+adr_j) = 1;
		}

	if( mb_type >= 0 && mb_type <= 4 ) amvbits = 0;

  if( mb_type == -1 )
    for( v=0; v<MB_SIZE; v++ ) for( h=0; h<MB_SIZE; h++ )
      alpha_mb[v*MB_SIZE+h] = BINARISE(alpha_mb_comp[v*MB_SIZE+h]);
  else
		{
    	for( v=0; v<MB_SIZE; v++ ) for( h=0; h<MB_SIZE; h++ )
      	alpha_mb[v*MB_SIZE+h] = f8bit(alpha_mb[v*MB_SIZE+h]);
		}

	/* Encode the first_shape_code */

	MakeMBtype( mb_type, mvda, adr_i, adr_j, rec_curr);
	
	if( flag == 1 ) 
		{
			*first_bits = CodeInterMBtype( adr_i, adr_j, first_shape_code,rec_curr,rec_prev);
		}
	else
		{
			if (!error_res_disable)
				*first_bits = CodeIntraMBtype_ER( first_shape_code, mb_type, 
												adr_i, adr_j, rec_curr, 
 												alpha_mode_packet);
			else
				*first_bits = CodeIntraMBtype( first_shape_code, mb_type, 
												adr_i, adr_j, rec_curr);
		}

  /* update the decoded alpha image */
  for( v=0; v<MB_SIZE; v++ ) for( h=0; h<MB_SIZE; h++ ) {
    a_mb_rec[v*MB_SIZE+h] = (SInt)alpha_mb[v*MB_SIZE+h];
  }

  if(shape_inter==0 && mb_type==-1){
    printf(" Error: shape_inter=%d however mb_type=%d\n",
	    shape_inter,mb_type);
    exit(0);
  }

	/* do all bitstream book-keeping */

  /* first_shape_code bit stream */
  for(i=0; i<*first_bits; i++)
    first_stream[i] = first_shape_code[i];

	total_first_bits[vol_id] += *first_bits;
	curr_first_bits += *first_bits;

  /* second_code bit stream */
  mb_bits+=second_bits;
  for(i=0; i<second_bits; i++)
    shape_stream[i] = second_code[i];
  shape_stream+=second_bits;

	total_second_bits[vol_id] += second_bits;

  /* mv bit stream */
  mb_bits+=amvbits;
  for(i=0; i<amvbits; i++)
    shape_stream[i] = mv_stream[i];
  shape_stream+=amvbits;

	total_amv_bits[vol_id] += amvbits;
	curr_amv_bits += amvbits;

  /* cae bit stream */
  mb_bits+=cae_bits;

  for(i=0; i<cae_bits; i++)
    shape_stream[i] = cae_stream[i];
  shape_stream+=cae_bits;

	if (cae_bits>0) 
		{
			total_coded_mbs[vol_id]++;
			curr_coded_mbs++;
			total_cae_bits[vol_id] += cae_bits;
			curr_cae_bits += cae_bits;
			if (mb_type>=2 && mb_type<=4)
				{
					total_coded_intra_mbs[vol_id]++;
					curr_coded_intra_mbs++;
					total_cae_intra_bits[vol_id] += cae_bits;
					curr_cae_intra_bits += cae_bits;
				}
			else
				{
					total_coded_inter_mbs[vol_id]++;
					curr_coded_inter_mbs++;
					total_cae_inter_bits[vol_id] += cae_bits;
					curr_cae_inter_bits += cae_bits;
				}
		}

	/* write the coded BAB to the reconstructed VOP */

  PutSubImage(GetVopA(rec_curr),mblock_rec,x,y);
	if (!error_res_disable)
  	PutSubImage(alpha_rec_packet,mblock_rec,x,y);

  block_rec = AllocImage(8,8,SHORT_TYPE);				
  a_b_rec = (SInt *) GetImageData(block_rec);
  for( v=0; v<8; v++ ) for( h=0; h<8; h++ )
		{
			Int index = (v+v)*MB_SIZE+h+h;   
			a_b_rec[v*8+h] = (a_mb_rec[index]
														||a_mb_rec[index+1]
														||a_mb_rec[index+MB_SIZE]
														||a_mb_rec[index+MB_SIZE+1])?255:0;
		}

  PutSubImage(GetVopAuv(rec_curr),block_rec,x/2,y/2);
  FreeImage (block_rec);

	/* modify the modes and MVs based on coded shape */
	
	if ((GetVopPredictionType(curr) != I_VOP) &&						 (GetVopShape(curr)!=BINARY_SHAPE_ONLY))  /* BSO_NOEL */
		ModifyModesAndMVs(GetVopPredictionType(curr),
                                  mblock_rec,MB_decisions,alpha_decisions,
				  mot_x,mot_y,adr_j,adr_i);

  FreeImage (mblock);
  FreeImage (mblock_rec);
/* Free displaced here : for leakage problem: Dufour 15.04.98 */
FreeImage(top_border_data);
FreeImage(left_border_data);

  return mb_bits;
}


Void ModifyModesAndMVs(Int vop_type,Image *mblock_rec ,Image *MB_decisions, 
			Image *alpha_decisions, Image *mot_x, Image *mot_y, 
			Int mb_x, Int mb_y)
{
	Int	x,y;

	SInt 	*ps = (SInt *) GetImageData(mblock_rec),
				*p;

	Int opaque1,
			opaque2,
			opaque3,
			opaque4,
			opaque,
			pos1,
			pos2,
			width = GetImageSizeX(alpha_decisions);

	SInt *mode_ptr = (SInt *) GetImageData(MB_decisions),
				mode;

	SInt *alpdec_ptr = (SInt *) GetImageData(alpha_decisions);

	Float *px = (Float *) GetImageData(mot_x),
				*py = (Float *) GetImageData(mot_y);

	pos1 = mb_y * GetImageSizeX(MB_decisions) + mb_x;
	pos2 = 2*mb_y * GetImageSizeX(alpha_decisions) + 2*mb_x;

	mode = mode_ptr[pos1];

	/* Block 1 */
	opaque1 = 0;
	for (y=0,p=ps;y<MB_SIZE/2;y++,p+=MB_SIZE/2)
		for (x=0;x<MB_SIZE/2;x++,p++)
			opaque1 |= (*p)&1;
	
	if (opaque1) alpdec_ptr[pos2] = 1;
	else alpdec_ptr[pos2] = MBM_TRANSPARENT;


	/* Block 2 */
	opaque2 = 0;
	for (y=0,p=ps+8;y<MB_SIZE/2;y++,p+=MB_SIZE/2)
		for (x=0;x<MB_SIZE/2;x++,p++)
			opaque2 |= (*p)&1;

	if (opaque2) alpdec_ptr[pos2+1] = 1;
	else alpdec_ptr[pos2+1] = MBM_TRANSPARENT;


       /* Block 3 */
	opaque3 = 0;
	for (y=0,p=ps+8*MB_SIZE;y<MB_SIZE/2;y++,p+=MB_SIZE/2)
		for (x=0;x<MB_SIZE/2;x++,p++)
			opaque3 |= (*p)&1;
	
	if (opaque3) alpdec_ptr[pos2+width] = 1;
	else alpdec_ptr[pos2+width] = MBM_TRANSPARENT;


      	/* Block 4 */
	opaque4 = 0;
	for (y=0,p=ps+8*MB_SIZE+8;y<MB_SIZE/2;y++,p+=MB_SIZE/2)
		for (x=0;x<MB_SIZE/2;x++,p++)
			opaque4 |= (*p)&1;
   
	if (opaque4) alpdec_ptr[pos2+width+1] = 1;
	else alpdec_ptr[pos2+width+1] = MBM_TRANSPARENT;

         opaque = opaque1 || opaque2 || opaque3 || opaque4;	

        if (vop_type==B_VOP) {
            if (!opaque) mode_ptr[pos1] = -1; /* transparent */
        } else {

          if (!opaque) {
		mode_ptr[pos1] = MBM_TRANSPARENT;
                px[pos2] = px[pos2+1]=px[pos2+width]=px[pos2+width+1]=0.0; 	
                py[pos2] = py[pos2+1]=py[pos2+width]=py[pos2+width+1]=0.0; 		
	   } else {	
                 if ((opaque1+opaque2+opaque3+opaque4==1)&&(mode == MODE_INTER4V)) {
                    mode_ptr[pos1] = MODE_INTER; 
                 }
             if (mode !=MODE_INTRA) {
                    /* vector padding Minhua Zhou 08.10.1997*/
                 if (!opaque1) {
                    px[pos2]=(opaque2)?px[pos2+1]:((opaque3)?px[pos2+width]:px[pos2+width+1]);
                    py[pos2]=(opaque2)?py[pos2+1]:((opaque3)?py[pos2+width]:py[pos2+width+1]);
                 }
                if (!opaque2) {
                    px[pos2+1]=(opaque1)?px[pos2]:((opaque4)?px[pos2+width+1]:px[pos2+width]);
                    py[pos2+1]=(opaque1)?py[pos2]:((opaque4)?py[pos2+width+1]:py[pos2+width]);
                 }

               if (!opaque3) {
                    px[pos2+width]=(opaque4)?px[pos2+width+1]:((opaque1)?px[pos2]:px[pos2+1]);
                    py[pos2+width]=(opaque4)?py[pos2+width+1]:((opaque1)?py[pos2]:py[pos2+1]);
                 }
              if (!opaque4) {
                    px[pos2+width+1]=(opaque3)?px[pos2+width]:((opaque2)?px[pos2+1]:px[pos2]);
                    py[pos2+width+1]=(opaque3)?py[pos2+width]:((opaque2)?py[pos2+1]:py[pos2]);
                 }
             } /* MODE_INTRA */
          }
      }

		
}

Void CopyVopABlock(Vop *vop1, Vop *vop2, Int x, Int y)  
{
	Image *block = AllocImage(16,16,SHORT_TYPE);

	GetSubImage(GetVopA(vop1), block, x, y);
	PutSubImage(GetVopA(vop2), block, x, y);
	FreeImage(block);
}

Void CopyVopAuvBlock(Vop *vop1, Vop *vop2, Int x, Int y)
{
	Image *block = AllocImage(8,8,SHORT_TYPE);

	GetSubImage(GetVopAuv(vop1), block, x, y);
	PutSubImage(GetVopAuv(vop2), block, x, y);
	FreeImage(block);
}



Int
ShapeInterMB(Vop *curr,
	     Vop *rec_prev,
	     SInt pred[MB_SIZE][MB_SIZE],
	     Image *modeA,
	     Image *mot_x,
	     Image *mot_y,
	     Image *motA_x,
	     Image *motA_y,
	     Image *MB_decisions,
	     Image *alpha_decisions,
	     Int *mvda,
	     Int *shape_inter,
	     UChar *alphaMV_stream,
	     Int thresh,
	     Int width,
	     Int i,
	     Int j
	     )
{
  Image
    *mblock;

  SInt
    *a_mb;

  Int
		ox,oy,
    x, y,
    mb_size=MB_SIZE,
    amvbits=0;

  Int
    motDA_x[4], motDA_y[4];

  mblock = AllocImage(16,16,SHORT_TYPE);
  a_mb = (SInt *) GetImageData(mblock);

  if (GetVopPredictionType(curr) == I_VOP || (GetVopShapeCodingType(curr)==0)) 
		{
    	*shape_inter = 0;
  	} 
	else 
		{
    	*shape_inter = 1;
  	}
  x = j * mb_size;
  y = i * mb_size;
  *mvda = 1;

  if (*shape_inter )
		{

      GetSubImage(GetVopA(curr),mblock,x,y);
  		ox = GetVopHorSpatRef(curr) - GetVopHorSpatRef(rec_prev);
 			oy = GetVopVerSpatRef(curr) - GetVopVerSpatRef(rec_prev);
      amvbits = FindPredAlphaAndMVmei (curr,
								x,y,
								ox,oy,
								mot_x,mot_y,
								motA_x,motA_y,
								MB_decisions,
								alpha_decisions,
								modeA,
								(SInt *)GetImageData(GetVopA(rec_prev)),
								(SInt *)pred,
								a_mb,
								width,
								GetImageSizeX(GetVopA(rec_prev)),
								GetImageSizeY(GetVopA(rec_prev)),
								mb_size,
								thresh,
								motDA_x,motDA_y,
								mvda,
								alphaMV_stream);
		}

  FreeImage (mblock);
  return amvbits;
}


void
BitstreamAppendTtoM(Image *bitstream, UChar *stream, UInt nbits)
{
  UInt i;
  SInt bits;

  /* it should be 1 <= nbits <= 32 */

  if (nbits > 0)
    {
      for ( i=0; i<nbits; i++ ) {
	bits = (SInt)(*(stream++));
        BitstreamPutBit(bitstream, bits);
      }
    }
}

void
PutFirstCodes(
	      Image **First_stream,
	      Image *first_shape_code_bitstream,
	      Int width,
	      Int height
	      )
{
  Int i,j;

  for(i=0; i<height; i++)
    for(j=0; j<width; j++)
      BitstreamAppend(First_stream[i*width+j], first_shape_code_bitstream);
}
				
void
PutShapeCodes(
	      Image **Shape_stream,
	      Image *shape_bitstream,
	      Int width,
	      Int height
	      )
{
  Int i,j;

  for(i=0; i<height; i++)
    for(j=0; j<width; j++)
      BitstreamAppend(Shape_stream[i*width+j], shape_bitstream);
}


Void AllocShapePacket(Vop *vop)
{
	Int 	width = GetVopWidth(vop)/MB_SIZE,
				height = GetVopHeight(vop)/MB_SIZE;

	alpha_rec_packet = AllocSameImage(GetVopA(vop));
	alpha_mode_packet = AllocImage(width,height,SHORT_TYPE);
}

Void FreeShapePacket()
{
	FreeImage(alpha_rec_packet);
	FreeImage(alpha_mode_packet);
}
