/*****************************************************************************
 "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_dec_mom.c
 *
 * Author:	TOSHIBA + Noel Brady Teltec Irl.
 * Created:	11-04-97
 *                                                                         
 * Description: Contains high level functions for binary shape decoding.
 *
 *
 *                                 
 ***********************************************************HeaderEnd*********/

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

#include<stdio.h>
#ifndef WIN32
#include<values.h>
#endif


#include <string.h>
#include "momusys.h"
#include "mom_structs.h"
#include "mom_bitstream_d.h"
#include "vm_dec_defs.h"
#include "alp_common_def.h"
#include "alp_dec_mom.h"
#include "alp_dec_header.h"
#include "alp_dec_cae.h"
#include "alp_dec_mc.h"
#include "alp_common_cae.h"

#define _DECODE_DEBUG
#define _DECODED_SIGNAL_DEBUG

Image		*alpha_rec_packet = NULL,		
				*alpha_mode_packet=NULL;

 				
/***********************************************************CommentBegin******
 *
 * -- VopShapeDecode -- decodes all the binary shape fields 
 *										(except first_shape_code)  for a given VOP 
 *											,used only in separate mode decoding
 *
 * Author :		TOSHIBA
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					stream - the bitstream
 *					rec_prev - previously reconstructed VOP
 *					mb_type - the decoded BAB modes
 *					mvda - the decoded flags indicting whether MVDs=0 or not.
 *					vo_id - 
 *					vol_id - 
 *
 * Arguments In/Out:
 *					rec_curr - reconstructed VOP
 *
 * Arguments Out:
 *
 * Return values :
 *
 * Side effects :	
 *
 * Description : As per VM7
 *
 * See also :
 *
 *
 ***********************************************************CommentEnd********/

Void
VopShapeDecode(
	       Vop *rec_curr,
	       Vop *rec_prev,
					Int vo_id,
					Int vol_id,
	       Int *mb_type,
				 Int *mvda,
	       Bitstream *stream,
				Trace *trace
	       )
{
  Image *modeA2; /* the flag of current alpha block is inter coded or not */
  Image *motA2_x; /* the x compornent of shape MV */
  Image *motA2_y; /* the y compornent of shape MV */
  Int i, j, width, height, vop_type;

  /* Allocate shape ME/MC */
  modeA2 = AllocImage(GetVopWidth(rec_curr)/MB_SIZE,
		      GetVopHeight(rec_curr)/MB_SIZE,SHORT_TYPE);
  motA2_x = AllocImage(GetVopWidth(rec_curr)/MB_SIZE,
		       GetVopHeight(rec_curr)/MB_SIZE,SHORT_TYPE);
  motA2_y = AllocImage(GetVopWidth(rec_curr)/MB_SIZE,
		       GetVopHeight(rec_curr)/MB_SIZE,SHORT_TYPE);

  if(GetVopPredictionType(rec_curr) == INTRA_VOP) vop_type = 0;
  else                                            vop_type = 1;
  width = GetVopWidth(rec_curr)/MB_SIZE;
  height = GetVopHeight(rec_curr)/MB_SIZE;

  for(i=0; i<height; i++)
    for(j=0; j<width; j++)
      (Void)AlphaDecodeMB(rec_curr,
			  rec_prev,
				vo_id,
				vol_id,
			  i,
			  j,
			  &mb_type[i*width+j],
				&mvda[i*width+j],
			  vop_type,
				(Image *)NULL,
			  (Image *)NULL,
			  (Image *)NULL,
			  (Image *)NULL,
			  modeA2,
			  motA2_x,
			  motA2_y,
				0,
			  stream,
				trace,
			  (Int *)NULL
			  );
  /* Free shape ME/MC */
  FreeImage(modeA2);
  FreeImage(motA2_x);
  FreeImage(motA2_y);
}


/***********************************************************CommentBegin******
 *
 * -- DecodeFirst -- decodes first_shape_codes for single BAB
 *
 * Author :		TOSHIBA/Noel Brady (TELTEC IRELAND)
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					stream - the bitstream
 *					vo_id - 
 *					vol_id - 
 *					adr_i,adr_j - address of BAB in BAB units
 *					vop_type - 0=I_VOP, 1=P-VOP/B_VOP
 *
 * Arguments In/Out:
 *
 * Arguments Out:
 *					mb_type - the decoded BAB modes
 *					mvda - the decoded flags indicting whether MVDs=0 or not.
 *
 * Return values :
 *
 * Side effects :	
 *
 * Description : As per VM7
 *
 * See also :
 *
 *
 *
 ***********************************************************CommentEnd********/
Int
DecodeFirst(Bitstream *stream,
			Int vo_id,
			Int vol_id,
	    Int adr_i,
	    Int adr_j,
	    Int *mb_type,
			Int *mvda,
	    Int vop_type,
			Int start_of_packet,
			Vop *vop,
                        Vop *ref_vop,
			Trace *trace
	    )
{
   Int
    mb_bits,
    flag,
		width = GetVopWidth(vop)/MB_SIZE,
		error_res_disable = GetVopErrorResDisable(vop);

  if( vop_type == 1 && GetVopShapeCodingType(vop)) flag = 1;
  else flag = 0;

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

	if( flag == 1 )
		{
			mb_bits = DecodeInterMBtype( mb_type, mvda, 
										adr_i, adr_j, stream, vop, ref_vop, trace);
		}
	else 
		{
			if (error_res_disable)
				mb_bits = DecodeIntraMBtype( stream, mb_type, adr_i, adr_j,
																					 width, vop, trace);
			else
				mb_bits = DecodeIntraMBtype_ER( stream, mb_type, adr_i, adr_j,
																					 width, vop, 
																					alpha_mode_packet, trace);
	    MakeMBtype2( *mb_type, adr_i, adr_j, vop);
    }
	
  return mb_bits;
}

/***********************************************************CommentBegin******
 *
 * -- VopShapeDecode -- decodes all the binary shape fields 
 *										(except first_shape_code)  for a given BAB 
 *
 * Author :		TOSHIBA/Noel Brady(TELTEC IRELAND)
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					stream - the bitstream
 *					rec_prev - previously reconstructed VOP
 *					vo_id - 
 *					vol_id - 
 *					adr_i,adr_j - address of BAB in BAB units
 *					vop_type - 0=I_VOP, 1=P-VOP/B_VOP
 *					mb_type - the decoded BAB mode
 *					mvda - the decoded flag indicting whether MVDs=0 or not.
 *					mot_X,mot_Y - texture motion vectors
 *					modeA2 - the modes indicating whether the BABs are encoded INTRA
 *										or INTER
 *					motA2_x,motA2_y - the shape motion vectors
 *
 * Arguments In/Out:
 *					rec_curr - reconstructed VOP
 *
 * Arguments Out:
 *
 * Return values :
 *
 * Side effects :	
 *
 * Description : As per VM7
 *
 * See also :
 * Modified: 26.05.97, Minhua Zhou: added down_sampled alpha 
 *           10.12.97 Luis Ducla-Soares: added 'Int *error_flag' to the
 *                                       arguments list.
 *
 ***********************************************************CommentEnd********/
Int
AlphaDecodeMB(Vop *rec_curr,
	      Vop *rec_prev,
				Int vo_id,
				Int vol_id,
	      Int adr_i,
	      Int adr_j,
	      Int *mb_type,
				Int *mvdA,
	      Int vop_type,
	      Image *MB_decisions,
				Image *alpha_decisions,
	      Image *mot_x,
	      Image *mot_y,
	      Image *modeA2,
	      Image *motA2_x,
	      Image *motA2_y,
				Int start_of_packet,
	      Bitstream *stream,
				Trace *trace,
	      Int *error_flag
				)
{
  Image *mblock_rec,*block_rec;

	Image *rec_curr_alpha,
				*rec_prev_alpha;

  SInt *a_mb_rec,*a_b_rec;

  Int
    mb_bits=0,
    tmp_bits,
    width = GetVopWidth(rec_curr),
		mvda=1,
    flag,
    x,y,
    h,v;

  UChar
    alpha_mb_comp[MB_SIZE*MB_SIZE],
    alpha_dmb[MB_SIZE*MB_SIZE];

  SInt pred[MB_SIZE][MB_SIZE];
      
	Int fixed_cr;

	Int 	ox,oy,
				error_res_disable = GetVopErrorResDisable(rec_curr);

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

  if( vop_type == 1 && GetVopShapeCodingType(rec_curr) ) flag = 1;
  else flag = 0;

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

  x = adr_j * MB_SIZE;
  y = adr_i * MB_SIZE;
 
	fixed_cr = GetVopChangeCRDisable(rec_curr);

  mblock_rec = AllocImage(16,16,SHORT_TYPE);
  a_mb_rec = (SInt *) GetImageData(mblock_rec);


	if (flag) mvda = *mvdA;

  if( *mb_type<=4 )
		{
   		 /* inter or all0 or all255 or MMR */
			if(*mb_type==-1) 
				{
					*((SInt *)GetImageData(modeA2)+adr_i*(width/MB_SIZE)+adr_j) = 1;

					ox = GetVopHorSpatRef(rec_curr) - GetVopHorSpatRef(rec_prev);
					oy = GetVopVerSpatRef(rec_curr) - GetVopVerSpatRef(rec_prev);
					tmp_bits = DecodeAlphaAndMVmei (rec_curr,x,y,ox,oy,mot_x,mot_y,
																	motA2_x,motA2_y,
																	MB_decisions,alpha_decisions,modeA2,
																	(SInt *)GetImageData(GetVopA(rec_prev)),
																	(SInt *)pred,mvda,width,
																	GetImageSizeX(GetVopA(rec_prev)),
																	GetImageSizeY(GetVopA(rec_prev)),
																	MB_SIZE,stream,trace);
					mb_bits += tmp_bits;
      	} 
 
     	for( v=0; v<MB_SIZE; v++ ) for( h=0; h<MB_SIZE; h++ ) 
				{
					alpha_mb_comp[v*MB_SIZE+h] = (UChar)pred[v][h];
      	}

			rec_curr_alpha = GetVopA(rec_curr);
			mb_bits += ShapeDecodingCAE(stream, 
						    alpha_dmb, 
						    alpha_mb_comp,
						    rec_curr_alpha,
						    alpha_rec_packet,
						    x,
						    y,
						    fixed_cr,
						    mb_type,
						    error_res_disable,
						    trace,
						    error_flag);
													
  	}
	else
		{
			*((SInt *)GetImageData(modeA2)+adr_i*(width/MB_SIZE)+adr_j) = 1;

			ox = GetVopHorSpatRef(rec_curr) - GetVopHorSpatRef(rec_prev);
			oy = GetVopVerSpatRef(rec_curr) - GetVopVerSpatRef(rec_prev);
      tmp_bits = DecodeAlphaAndMVmei (rec_curr,x,y,ox,oy,
																				mot_x,mot_y, motA2_x,motA2_y,
                                        MB_decisions, alpha_decisions, modeA2,
                                        (SInt *)GetImageData(GetVopA(rec_prev)),
                                        (SInt *)pred,mvda,width,
                                        GetImageSizeX(GetVopA(rec_prev)),
                                        GetImageSizeY(GetVopA(rec_prev)),
                                        MB_SIZE,stream,trace);
			mb_bits += tmp_bits;

      for( v=0; v<MB_SIZE; v++ ) for( h=0; h<MB_SIZE; h++ ) 
				{
        	alpha_mb_comp[v*MB_SIZE+h] = (UChar)pred[v][h];
      	}

			rec_curr_alpha = GetVopA(rec_curr);
			if (GetVopPredictionType(rec_curr) != INTRA_VOP)
				rec_prev_alpha = GetVopA(rec_prev);
			else rec_prev_alpha = NULL;
			ox = GetVopHorSpatRef(rec_curr) - GetVopHorSpatRef(rec_prev);
			oy = GetVopVerSpatRef(rec_curr) - GetVopVerSpatRef(rec_prev);
			mb_bits += ShapeDecodingInterCAE(stream, 
							 alpha_dmb, 
							 alpha_mb_comp,
							 rec_curr_alpha,
							 rec_prev_alpha,
							 alpha_rec_packet,
							 motA2_x,
							 motA2_y,
							 x,
							 y,
							 ox,
							 oy,
							 fixed_cr,
							 mb_type,
							 error_res_disable,
							 trace,
							 error_flag);
		}

  for( v=0; v<MB_SIZE; v++ ) for( h=0; h<MB_SIZE; h++ ) {
    a_mb_rec[v*MB_SIZE+h] = (SInt)alpha_dmb[v*MB_SIZE+h];
  }

  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 (mblock_rec);
  FreeImage (block_rec);
  return mb_bits;
}


Void
BitstreamReadMtoT(Bitstream *stream, UChar *shape_stream, Int nbits)
{
  UInt i, code=0;

  if (nbits > 0)
    {
      code = BitstreamShowBits(stream, nbits);
    }
  for (i = 0; i < nbits; i++)
    shape_stream[i] = (UChar)((code >> (nbits - 1 - i)) & 1);

}


Void AllocShapePacket2(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 FreeShapePacket2()
{
	FreeImage(alpha_rec_packet);
	FreeImage(alpha_mode_packet);
}
