/*****************************************************************************
 "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_header.c
 *
 * Author:	TOSHIBA + Noel Brady Teltec Irl.
 * Created:	11-04-97
 *                                                                         
 * Description: 
 *				Functions for decoding first_shape_code in I/P/B VOps
 *
 *                                 
 ***********************************************************HeaderEnd*********/


#include<stdio.h>
#ifndef WIN32
#include<values.h>
#endif
#include <string.h>
#include "momusys.h"
#include "vm_dec_defs.h"
#include "mom_bitstream_d.h"
#include "alp_common_def.h"
#include "alp_dec_util.h"
#include "alp_mode_tables.h"
#include "alp_dec_header.h"

#define _DECODE_DEBUG_FIRST
#define _MB_TYPE_DEBUG


/***********************************************************CommentBegin******
 *
 * -- DecodeIntraMbtype -- decodes first_shape_code for a BAB in I-VOP
 *
 * Author :		
 *	Noel Brady Teltec Irl.
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					stream - the bitstream
 *					i,j - the BAB coordinate
 *					width - number of BABs per row of VOP
 *					vo_id - 
 *					vol_id - 
 *
 * Arguments In/Out:
 *
 * Arguments Out:
 *					mb_type - the decoded BAB mode
 *
 * Return values :
 *					number of bits in first_shape_code
 *
 * Side effects :	
 *
 * Description : As per VM7
 *
 * See also :
 *
 ***********************************************************CommentEnd********/

Int DecodeIntraMBtype(Bitstream *stream, Int *mb_type, Int i,
	Int j, Int width, Vop *vop, Trace *trace)
{
	Int 	context;
        Int  ret=0, k;
	Int		a=3,b=3,c=3,d=3;
	Int last_col = width - 1;
	Int i1,j1,len;
        SInt *cur_shape_mode = (SInt *)GetImageData(GetVopShapeMode(vop));
        Int  hsize = GetImageSizeX(GetVopShapeMode(vop));

	if (i>0)
		{
			if (j>0) a = cur_shape_mode[(i-1)*hsize+j-1]+1;
			b = cur_shape_mode[(i-1)*hsize+j]+1;
			if (j<last_col)	c = cur_shape_mode[(i-1)*hsize+j+1]+1;
		}
	if (j>0) d = cur_shape_mode[i*hsize+j-1]+1;
	
	context = 27*(a-3) +	9*(b-3) +	3*(c-3) + d-3;
	
	k=0;
	do 
	  {
	    len = strlen(IMB_TYPE[context][k]);
	    i1 = BitstreamShowBits(stream, len);
	    j1 = ConvertStoI(IMB_TYPE[context][k],len);
	    
	    if (i1==j1) 
	      {  
		ret = len;
		switch (k)
		  {
		  case 0: *mb_type = 1;
		    break;
		  case 1:	*mb_type = 0;
		    break;
		  case 2:	*mb_type = 2;
		    break;
		  default: exit(-1);
		  }
	      }
	    k++;
	  }
	while (k<3);
	
	if (ret == 0) 
	  {
	    printf("Illegal VLC for INTRA shape mode\n");
	    exit(-1);
	  }
	else 
	  {
	    BitstreamReadBits(stream,ret,"first_shape_code",trace,CODE);
	  }
	
	if (trace->trace) 
	  switch (*mb_type)
	    {
	    case 0: fprintf(trace->fp_trace, "bab_type = all_opaque\n");
	      break;
	    case 1: fprintf(trace->fp_trace, "bab_type = all_transparent\n");
	      break;
	    case 2: fprintf(trace->fp_trace, "bab_type = intra_coded\n");
	      break;
	    }
	
	return ret;
}


Int DecodeIntraMBtype_ER(Bitstream *stream, Int *mb_type, Int i,
	Int j, Int width, Vop *vop, Image *alpha_mode_packet,
	Trace *trace)
{
	Int 	context;
  Int  ret=0, k;
	Int		a=3,b=3,c=3,d=3;
	Int last_col = width - 1;
	Int i1,j1,len;
	Int w = GetImageSizeX(alpha_mode_packet);
	SInt *p = (SInt *)GetImageData(alpha_mode_packet);
        SInt *cur_shape_mode = (SInt *)GetImageData(GetVopShapeMode(vop));
        Int  hsize = GetImageSizeX(GetVopShapeMode(vop));


	if (i>0)
	  {
	    if (j>0 && p[(i-1)*w+j-1]) a = cur_shape_mode[(i-1)*hsize+j-1]+1;
	    if (p[(i-1)*w+j]) b = cur_shape_mode[(i-1)*hsize+j]+1;
	    if (j<last_col && p[(i-1)*w+j+1])	c = cur_shape_mode[(i-1)*hsize+j+1]+1;
	  }
	if (j>0 && p[i*w+j-1]) d = cur_shape_mode[i*hsize+j-1]+1;
	
	p[i*w+j] = 1;
	
	context = 27*(a-3) +	9*(b-3) +	3*(c-3) + d-3;
	
	k=0;
	do 
	  {
	    len = strlen(IMB_TYPE[context][k]);
	    i1 = BitstreamShowBits(stream, len);
	    j1 = ConvertStoI(IMB_TYPE[context][k],len);
	    
	    if (i1==j1) 
	      {  
		ret = len;
		switch (k)
		  {
		  case 0: *mb_type = 1;
		    break;
		  case 1:	*mb_type = 0;
		    break;
		  case 2:	*mb_type = 2;
		    break;
		  default: exit(-1);
		  }
	      }
	    k++;
	  }
	while (k<3);
	
	if (ret == 0) 
	  {
	    printf("Illegal VLC for INTRA shape mode\n");
	    exit(-1);
	  }
	else 
	  {
	    BitstreamReadBits(stream,ret,"first_shape_code",trace,CODE);
	  }
	
	if (trace->trace) 
	  switch (*mb_type)
	    {
	    case 0: fprintf(trace->fp_trace, "bab_type = all_opaque\n");
	      break;
	    case 1: fprintf(trace->fp_trace, "bab_type = all_transparent\n");
	      break;
	    case 2: fprintf(trace->fp_trace, "bab_type = intra_coded\n");
	      break;
	    }
	
	return ret;
}


/***********************************************************CommentBegin******
 *
 * -- DecodeInterMbtype -- decodes first_shape_code for a BAB in P/B-VOP
 *
 * Author :		
 *	Noel Brady Teltec Irl.
 *
 * Created :		
 *	11-04-97
 * 
 * Arguments In: 	
 *					stream - the bitstream
 *					i,j - the BAB coordinate
 *					vo_id - 
 *					vol_id - 
 *
 * Arguments In/Out:
 *
 * Arguments Out:
 *					mb_type - the decoded BAB mode
 *					mvda - flag indicating whether the MVDs == 0 or not
 *
 * Return values :
 *					number of bits in first_shape_code
 *
 * Side effects :	
 *
 * Description : As per VM7
 *
 * See also :
 *
 ***********************************************************CommentEnd********/
Int
DecodeInterMBtype(
		  Int *mb_type,
		  Int *mvda,
		  Int i,
		  Int j,
		  Bitstream *stream,
                                Vop *vop,
                                Vop *ref_vop,
		  			Trace *trace)
{
  Int
    prei,
    prej,
    bits=0;
  Int
    prev_mode,
    decoded,
    k;

  Char **vlc_table;
  
	Int 	i1,j1,len;
 SInt *cur_shape_mode = (SInt *)GetImageData(GetVopShapeMode(vop));
  Int  hsize = GetImageSizeX(GetVopShapeMode(vop));
  SInt *ref_shape_mode = (SInt *)GetImageData(GetVopShapeMode(ref_vop));
  Int  hsize_ref = GetImageSizeX(GetVopShapeMode(ref_vop));
  Int  vsize_ref = GetImageSizeY(GetVopShapeMode(ref_vop));


  if(i<vsize_ref) prei=i;   else prei=vsize_ref-1;

  if(j<hsize_ref) prej=j;  else prej=hsize_ref-1;

	prev_mode = ref_shape_mode[prei*hsize_ref+prej];

	switch (prev_mode)
		{
			case 0: vlc_table = MMB_TYPE0;	
							break;
			case 1: vlc_table = MMB_TYPE1;	
							break;
			case 2: vlc_table = MMB_TYPE2;	
							break;
			case 3: vlc_table = MMB_TYPE3;	
							break;
			case 4: vlc_table = MMB_TYPE4;	
							break;
			case 5: vlc_table = MMB_TYPE5;	
							break;
			case 6: vlc_table = MMB_TYPE6;	
							break;
			default: printf("Error in PRE_MB_TYPE\n");
							 exit(-1);
		}

	decoded = 0; k = 0; *mvda = 1;
	do 
		{
			len = strlen(vlc_table[k]);
			i1 = BitstreamShowBits(stream, len);
			j1 = ConvertStoI(vlc_table[k],len);

  		if(i1==j1)
				{
					cur_shape_mode[i*hsize+j] = k;
					switch (k)
						{
							case 0:	*mb_type = -1;  /* not coded && mvds == 0 */
											*mvda = 1;
											break;
							case 1:	*mb_type = -1;  /* not coded && mvds !=0 */
											*mvda = 0;
											break;
							case 2:	*mb_type = 1;  	/* all_0 */
											break;
							case 3:	*mb_type = 0;	 	/* all_255*/
											break;
							case 4:	*mb_type = 2;		/* INTRA coded */
											break;
							case 5:	*mb_type = 6;  /* INTER coded && mvds==0 */
											*mvda = 1;
											break;
							case 6:	*mb_type = 5; 	/* INTER coded && mvds!=0 */
											*mvda = 0;
											break;							
							default: 	printf("Error decoding first_shape_code\n");
												exit(-1);
						}
					decoded = 1;
					bits = len;
				}
			k++;
		} while	(k<7 && !decoded);

	if (!decoded) 
		{
			printf("Error decoding first_shape_code\n");
			exit(-1);
		}
	else 
		{
			BitstreamReadBits(stream,bits,"first_shape_code",trace,CODE);
		}
		
	if (trace->trace) 
		{	
			switch (*mb_type)
				{
					case 0: fprintf(trace->fp_trace, "bab_type = all_opaque\n");
									break;
					case 1: fprintf(trace->fp_trace, "bab_type = all_transparent\n");
								break;
					case 2: fprintf(trace->fp_trace, "bab_type = intra_coded\n");
								break;
					case -1: 	if (*mvda)
											fprintf(trace->fp_trace, "bab_type = inter_not_coded (mvds==0)\n");
										else 
											fprintf(trace->fp_trace, "bab_type = inter_not_coded (mvds!=0)\n");
											
									break;
					case 6: fprintf(trace->fp_trace, "bab_type = inter_coded (mvds==0)\n");
								break;
					case 5: fprintf(trace->fp_trace, "bab_type = inter_coded (mvds!=0)\n");
							break;
				}
		}

  return bits;
}


Void
MakeMBtype2(
	    Int mb_type,
	    Int i,
	    Int j,
            Vop *vop)
{      
  SInt *cur_shape_mode = (SInt *)GetImageData(GetVopShapeMode(vop));
  Int  hsize = GetImageSizeX(GetVopShapeMode(vop));

  if(mb_type==0){
    /* all255 */
    cur_shape_mode[i*hsize+j]=3;
  }else if(mb_type==1){
    /* all0  */
    cur_shape_mode[i*hsize+j]=2;
  }else if(mb_type>=2 && mb_type<=6){
    /* MMR */
    cur_shape_mode[i*hsize+j]=4;
  }else{
    printf("wrong mb_type=%d: i j=%d %d\n",mb_type,i,j);
    exit(0);
  }

}







