/******************************************************************************
 *                                                                          
 * This software module was originally developed by 
 *
 *   Cecile Dufour (LEP / 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: sprite_dec_piece.c
 *
 * Author :		
 *	Cecile Dufour, (Philips LEP/ dufour@lep.research.philips.com)
 *
 * Created :		
 *	10-08.97
 *                                                                         
 * Description: routines for the encoding of sprite_pieces
 * -- InitForDecodeLowLatencyStaticSprite
 * -- DecodeBasicSprite -- Decode as I_VOP a basic static sprite
 * -- DecodeSpritePiece -- Decode as I/P_VOP pieces of a low latency static sprite
 * Notes:  
 *
 * Modified:
 *
 *                          
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/
#include "momusys.h"
#include "mom_bitstream_d.h"
#include "text_decode.h"
#include "combined_decode.h"
#include "vm_dec_main.h"
#include "mom_vol.h"
#include "mom_access.h"
#include "mom_vo.h"
#include "vm_common_defs.h"
#include "sprite_util.h"
#include "sprite_dec_util.h"
#include "sprite_dec_piece.h"
#include "mot_padding.h"
#include "alp_dec_header.h"
#include "io_generic.h"


/***********************************************************CommentBegin******
 *
 * -- InitForDecodeLowLatencyStaticSprite -- initilizations for  LL static sprite
 *
 * Author :		
 *	Cecile Dufour, (Philips LEP/ dufour@lep.research.philips.com)
 *
 * Created :		
 *	10-08.97
 *
 * Purpose :		
 *	This function:  * calls the reading of a sprite piece vop header
 *				(calls DecodeVopVopHeader)
 *			* Decode as I_VOP the first piece of a static sprite
 *				(calls DecodeVopNonScalable)	
 * 
 * Arguments in : 
 *	stream: 
 *	curr_vol: current VOL
 *	vo_id: Object identification
 *	trace: trace files
 *	readen_bits:
 *
 * Arguments in/out :
 *	rec_sprite: the sprite attached to the vol is updated	
 *
 * Arguments out :	
 *
 * Return values :	
 *
 * Side effects :	
 *
 *
 * Description :	
 *	The piece vop header (start_code, vop_ID, etc.) is first
 *	read, then DecodeVopScalable for I_VOP decoding
 *
 * See also :
 *	InitEncodeSpritePiece (encoder side)
 *
 * Modified :		
 *
 ***********************************************************CommentEnd********/
Void 
InitForDecodeLowLatencyStaticSprite(Vol *curr_vol)

{
  Int 	*tab_transmit;
  Int 	*tab_amb_type;
  Int	*tab_mvda;
  Int 	***tab_DC_store;
  SInt	*tab_QP_store;
  Int	numblocks_x, numblocks_y, mb_x, mb_y;
  Int	i,j;
  

numblocks_x = GetVolSpriteHdim(curr_vol)/16;
numblocks_y = GetVolSpriteVdim(curr_vol)/16;

tab_transmit = (Int   *)calloc(numblocks_x*numblocks_y, sizeof(Int));
tab_amb_type = (Int   *)calloc(numblocks_x*numblocks_y, sizeof(Int));
tab_mvda     = (Int   *)calloc(numblocks_x*numblocks_y, sizeof(Int));
tab_QP_store = (SInt  *)calloc(numblocks_x*numblocks_y, sizeof(SInt));
tab_DC_store = (Int ***)calloc(numblocks_x*numblocks_y, sizeof(Int **));
for (i = 0; i < numblocks_x*numblocks_y; i++)
	{
	tab_DC_store[i] = (Int **)calloc(6, sizeof(Int *));
	for (j = 0; j < 6; j++)
		tab_DC_store[i][j] = (Int *)calloc(15, sizeof(Int));
	}
	

PutVolSpriteTabTransmit(tab_transmit, curr_vol);
PutVolSpriteTabAmbType(tab_amb_type, curr_vol);
PutVolSpriteTabMvda(tab_mvda, curr_vol);
PutVolSpriteTabDCStore(tab_DC_store, curr_vol);
PutVolSpriteTabQPStore(tab_QP_store, curr_vol);

for (mb_y=0 ; mb_y<numblocks_y ; mb_y++ )
for (mb_x=0 ; mb_x<numblocks_x ; mb_x++ )
	tab_transmit[mb_y*numblocks_x+mb_x]=NON_TRANSMIT_BLOCK;

}


/***********************************************************CommentBegin******
 *
 * -- DecodeBasicSprite -- Decode as I_VOP a basic static sprite
 *
 * Author :		
 *	Cecile Dufour, (Philips LEP/ dufour@lep.research.philips.com)
 *
 * Created :		
 *	10-08.97
 *
 * Purpose :		
 *	This function:  * calls the reading of a sprite piece vop header
 *				(calls DecodeVopVopHeader)
 *			* Decode as I_VOP the first piece of a static sprite
 *				(calls DecodeVopNonScalable)	
 * 
 * Arguments in : 
 *	stream: 
 *	curr_vol: current VOL
 *	vo_id: Object identification
 *	trace: trace files
 *	readen_bits:
 *
 * Arguments in/out :
 *	rec_sprite: the sprite attached to the vol is updated	
 *
 * Arguments out :	
 *
 * Return values :	
 *
 * Side effects :	
 *
 *
 * Description :	
 *	The piece vop header (start_code, vop_ID, etc.) is first
 *	read, then DecodeVopScalable for I_VOP decoding
 *
 * See also :
 *	InitEncodeSpritePiece (encoder side)
 *
 * Modified :		
 *
 ***********************************************************CommentEnd********/
Void 
DecodeBasicSprite(Bitstream *stream, Vol *curr_vol, Int vo_id, Trace *trace,  
							Int *readen_bits)

{
  Vop	*rec_sprite_piece=NULL, *rec_sprite;
  Int	SpriteSpatHorRef, SpriteSpatVerRef;
  Int	SpriteWidth, SpriteHeight;
  


rec_sprite = GetVolSprite(curr_vol);

  /*****
   *
   *    Set trace level for VOP header
   *
   *****/
  if(trace->full_trace_period < 0)
    trace->trace = 1;
  else
    trace->trace = trace->VOP_header_def;

  TraceBreakLine(trace);
  

rec_sprite_piece = SallocVop();

CopyVopNonImageField(rec_sprite, rec_sprite_piece);

trace->trace=1;
	
DecodeVopHeader(stream, vo_id, trace, rec_sprite_piece, readen_bits);

SpriteSpatHorRef = GetVopHorSpatRef(rec_sprite);
SpriteSpatVerRef = GetVopHorSpatRef(rec_sprite);
SpriteWidth = GetVopWidth(rec_sprite);
SpriteHeight = GetVopHeight(rec_sprite);
CopyVopNonImageField(rec_sprite_piece, rec_sprite);
PutVopWidth(SpriteWidth, rec_sprite);
PutVopHeight(SpriteHeight, rec_sprite);
PutVopHorSpatRef(SpriteSpatHorRef, rec_sprite);
PutVopVerSpatRef(SpriteSpatVerRef, rec_sprite);

	
AllocVopChannels (rec_sprite_piece, 
		GetVopWidth(rec_sprite_piece),
		GetVopHeight(rec_sprite_piece));

	
TraceBreakLine(trace);

DecodeVopNonScalable(stream,vo_id,trace,rec_sprite_piece);
	
PutSpritePieceInSprite(rec_sprite_piece, rec_sprite, 
	GetVopHorSpatRef(rec_sprite_piece), GetVopVerSpatRef(rec_sprite_piece));


FreeVop(rec_sprite_piece);
BitstreamByteAlign(stream);

}
/***********************************************************CommentBegin******
 *
 * -- DecodeSpritePiece -- Decode as I_VOP pieces of a static sprite
 *
 * Author :		
 *	Cecile Dufour, (Philips LEP/ dufour@lep.research.philips.com)
 *
 * Created :		
 *	10-08.97
 *
 * Purpose :		
 *	This function:  * first reads 5 arguments relative to sprite pieces
 *			* calls the writing of a sprite piece header syntax
 *				(calls BitstreamPutSpritePieceHeader)
 *			* decode as I_or P_VOP the different pieces of a static sprite
 * 
 * Arguments in : 
 *	stream: 
 *	curr_vop: current SPRITE_VOP
 *	vo_id: Object identification
 *	trace: trace files
 *	readen_bits:
 *
 * Arguments in/out :
 *	rec_sprite: the sprite attached to the vol is updated	
 *
 * Arguments out :	
 *
 * Return values :	
 *
 * Side effects :	
 *
 * Description :	
 *	The piece vop header (5 parameters) is first
 *	read, then DecodeVopScalable for I_VOP decoding, addressing
 *	different mode: update or piece, which are distinguished by:
 *		* no shape encoding for update
 *		* quantization of I_VOP for piece, P_VOP for update
 *
 * See also :
 *	EncodeSpritePiece (encoder side)
 *
 * Modified :		
 *
 ***********************************************************CommentEnd********/

Void 
DecodeSpritePiece(Bitstream *stream, Vop *curr_vop, Int vo_id, 
					Trace *trace,  Int *readen_bits)

{
  Vop	*rec_sprite_piece=NULL, *rec_sprite, *prev_sprite_piece=NULL;
  Int	piece_width, piece_height, piece_xoffset, piece_yoffset;
  Int 	*tab_transmit, *tab_piece_transmit;
  Int 	*tab_amb_type, *tab_piece_amb_type;
  Int	*tab_mvda, *tab_piece_mvda;
  Int 	***tab_DC_store, ***tab_piece_DC_store;
  SInt	*tab_QP_store, *tab_piece_QP_store;
  Int	numblocks_x, numblocks_y, mb_x, mb_y;
  Int	piece_quant;
  
  
  tab_transmit = GetVopSpriteTabTransmit(curr_vop);
  tab_amb_type = GetVopSpriteTabAmbType(curr_vop);
  tab_mvda     = GetVopSpriteTabMvda(curr_vop);
  tab_DC_store = GetVopSpriteTabDCStore(curr_vop);
  tab_QP_store = GetVopSpriteTabQPStore(curr_vop);
  numblocks_x = GetVopSpriteHdim(curr_vop)/16;
  numblocks_y = GetVopSpriteVdim(curr_vop)/16;
  rec_sprite = GetVopSprite(curr_vop);

  /*****
   *
   *    Set trace level for VOP header
   *
   *****/
  if(trace->full_trace_period < 0)
    trace->trace = 1;
  else
    trace->trace = trace->VOP_header_def;

  TraceBreakLine(trace);

 
  piece_quant = (Int) BitstreamReadBits(stream, 5, "vop_quant",trace,NUM);
  *readen_bits += 5;
  piece_width = (Int) BitstreamReadBits(stream, 9, "piece_width",trace,NUM);
  *readen_bits += 9;
  piece_height = (Int) BitstreamReadBits(stream, 9, "piece_height",trace,NUM);
  *readen_bits += 9;
  BitstreamReadBits(stream,1,"marker_bit",trace,FLAG);
  *readen_bits += 1;
  piece_xoffset = (Int) BitstreamReadBits(stream, 9, "piece_xoffset",trace,NUM);
  *readen_bits += 9;
  piece_yoffset = (Int) BitstreamReadBits(stream, 9, "piece_yoffset",trace,NUM);
  *readen_bits += 9;

rec_sprite_piece = AllocVop(piece_width*16, piece_height*16);
CopyVopNonImageField(curr_vop, rec_sprite_piece);
PutVopShape(GetVopShape(rec_sprite), rec_sprite_piece);
PutVopBinaryShape(GetVopBinaryShape(rec_sprite), rec_sprite_piece);
PutVopQuantizer(piece_quant, rec_sprite_piece);

if (GetVopSpriteTransmitMode(curr_vop)==PIECE)
	PutVopPredictionType(0/*I_VOP*/, rec_sprite_piece);
else
if (GetVopSpriteTransmitMode(curr_vop)==UPDATE)
	PutVopPredictionType(1/*P_VOP*/, rec_sprite_piece);

PutVopWidth (piece_width*16,  rec_sprite_piece);
PutVopHeight(piece_height*16, rec_sprite_piece);
PutVopHorSpatRef(0, rec_sprite_piece);
PutVopVerSpatRef(0, rec_sprite_piece);


tab_piece_transmit = tab_transmit + piece_yoffset*numblocks_x+piece_xoffset;
tab_piece_amb_type = tab_amb_type + piece_yoffset*numblocks_x+piece_xoffset;
tab_piece_mvda     = tab_mvda     + piece_yoffset*numblocks_x+piece_xoffset;
tab_piece_QP_store = tab_QP_store + piece_yoffset*numblocks_x+piece_xoffset;
tab_piece_DC_store = tab_DC_store + piece_yoffset*numblocks_x+piece_xoffset;
PutVopSpriteTabTransmit(tab_piece_transmit, rec_sprite_piece);
PutVopSpriteTabAmbType (tab_piece_amb_type, rec_sprite_piece);
PutVopSpriteTabMvda    (tab_piece_mvda,     rec_sprite_piece);
PutVopSpriteTabQPStore (tab_piece_QP_store, rec_sprite_piece);
PutVopSpriteTabDCStore (tab_piece_DC_store, rec_sprite_piece);

GetSpritePieceInSprite(rec_sprite_piece, rec_sprite, piece_xoffset*16, piece_yoffset*16);

trace->trace=1;	


if (GetVopPredictionType(rec_sprite_piece)==P_VOP)
	{ 
  	prev_sprite_piece = AllocVop(piece_width*16, piece_height*16);
  	PutVopHorSpatRef(0, prev_sprite_piece);
  	PutVopVerSpatRef(0, prev_sprite_piece);
  	PutVopShape(GetVopShape(rec_sprite_piece), prev_sprite_piece);
  	PutVopBinaryShape(GetVopBinaryShape(rec_sprite_piece),prev_sprite_piece);
	GetSpritePieceInSprite( prev_sprite_piece, rec_sprite, 
			piece_xoffset*16, piece_yoffset*16);
  	VopPadding(prev_sprite_piece);
  	PutVopNextTemp(prev_sprite_piece,rec_sprite_piece);
	}
	
TraceBreakLine(trace);
DecodeVopNonScalable(stream,vo_id,trace,rec_sprite_piece);

PutSpritePieceInSprite2( rec_sprite_piece, rec_sprite, 
		piece_xoffset*16, piece_yoffset*16, 

		tab_transmit, GetVopPredictionType(rec_sprite_piece));


for (mb_y = 0 ; mb_y < numblocks_y ; mb_y++)
	{
for (mb_x = 0 ; mb_x < numblocks_x ; mb_x++)
	if (tab_transmit[mb_y*numblocks_x+mb_x]>1) 
		tab_transmit[mb_y*numblocks_x+mb_x]=1;
	}


if (GetVopPredictionType(rec_sprite_piece)==P_VOP)
	FreeVop(prev_sprite_piece);
FreeVop(rec_sprite_piece);
}

