/************************************************************************/
/*                                                                      */
/* This software module was originally developed by                     */
/*                                                                      */
/*  Ryuji Kitaura  (Sharp Corporation)                                  */
/*  Hisashi Saiga  (Sharp Corporation)                                  */
/*  Tomoko Aono    (Sharp Corporation)                                  */
/*  Hiroyuki Katata(Sharp Corporation)                                  */
/*                                                                      */
/* 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 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                    */
/*                                                                      */
/* SHARP Corporation partners retain full right to use the code for     */
/* their own purposes, 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)1997                                                    */
/*                                                                      */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mom_vo.h"
#include "mom_vol.h"
#include "mom_vop.h"
#include "mom_access.h"
#include "vm_vop_bound.h"
#include "io_generic.h"
#include "vm_config.h"
#include "vm_vop_code.h"

#include "do_bgc.h"
#include "enhance_vop.h"
#include "bgc.h"
#include "mot_padding.h"

/***********************************************************CommentBegin******
 *
 * -- BGCProcess
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
void BGCProcess(Float time,   Float ref_time,
		Int vo_id,    Int vol_id,
		VOConfig      *vo_config,
		VO            *next_rec_vo,
	        VO            *rec_vo_store,
		EncodeControl *enc_ctl,
		Vop           *base_vop_not_padding_for_bgc,
                Vop           *enh_vop[],
		Int           *enh_count,
	        Int           bgc_mode,
		Int           temporal_scalability,
		Vop	      *base_B_vop_TPS,
		Int           finish_base)  
{  
  Char      out_y_file[100], out_u_file[100], out_v_file[100], out_a_file[100];
  VolConfig *base_config         = NULL;
  VolConfig *enh_config          = NULL;
  VolConfig *layer_config        = NULL;
  Vol       *base_curr_vol       = NULL;
  Vol       *base_prev_vol       = NULL;
  Vol       *enh_vol     = NULL;
  Vop       *for_alpha_base_vop  = NULL;
  Vop       *back_alpha_base_vop = NULL;
  Int mode = 0;    /* 1: Base (first)                        */
                   /* 2: Base (except first frame)           */
                   /* 3: Enh (for_base_alpha exist : back_base_alpha  NOT exist) */
  Int ref_vol_id;
  Int curr_base_frame   = 0;
  Int enh_frame = 0;
  Int post_filter_disable;
       
  strcpy(out_y_file, GetEncodeControlDispYFile(enc_ctl));
  strcpy(out_u_file, GetEncodeControlDispUFile(enc_ctl)); 
  strcpy(out_v_file, GetEncodeControlDispVFile(enc_ctl));
  strcpy(out_a_file, GetEncodeControlDispYFile(enc_ctl));
  sprintf(out_a_file, "%s.a",GetEncodeControlDispYFile(enc_ctl));

  post_filter_disable = GetEncodeControlPostFilterType(enc_ctl);
  layer_config           = GetVolConfigById(GetVOConfigLayers(vo_config), vol_id);

  /* base */
  if(!GetVolConfigScalability(layer_config)){
       base_config        = layer_config;
       base_curr_vol      = GetVolById(GetVOLayers(next_rec_vo),  vol_id);
       base_prev_vol      = GetVolById(GetVOLayers(rec_vo_store), vol_id);
  }
  /* enh */
  else{
       enh_config         = layer_config;
       enh_vol            = GetVolById(GetVOLayers(next_rec_vo), vol_id);
       ref_vol_id         = GetVolConfigRefId(enh_config);
       base_config        = GetVolConfigById(GetVOConfigLayers(vo_config), ref_vol_id);
       base_curr_vol      = GetVolById(GetVOLayers(next_rec_vo),  ref_vol_id);
       if(temporal_scalability != 3)
	   base_prev_vol  = GetVolById(GetVOLayers(rec_vo_store), ref_vol_id);
  }
  mode = DecideModeWriteBGC(vo_config, 
			    layer_config,     base_config,      enh_config,
		            vo_id, vol_id,    temporal_scalability,
			    &curr_base_frame, &enh_frame, finish_base);
  if(mode == -1)
      return;
  
  if(temporal_scalability == 3){
      for_alpha_base_vop     = GetVopPrevTemp(base_vop_not_padding_for_bgc);
      back_alpha_base_vop    = GetVopNextTemp(base_vop_not_padding_for_bgc);
  }
  else{
      for_alpha_base_vop     = GetVopPrevTemp(base_vop_not_padding_for_bgc);
      back_alpha_base_vop    = GetVopNextTemp(base_vop_not_padding_for_bgc);
  }
 
  /* base */
  /* write base_vop for tps (first frame) */
  if(mode == 1)
      FirstBaseWrite(base_config,   layer_config,
	             base_curr_vol, for_alpha_base_vop,
	             out_y_file, out_u_file, out_v_file, out_a_file,
	             post_filter_disable, curr_base_frame,
		     CheckEnhancementType(vo_config));
  
  /* base (from 2nd frame to end) */
  else if(mode == 2){
      SecoundBaseWrite(vo_config,              base_config,
		       enh_config,             layer_config,
	               next_rec_vo,
		       base_prev_vol,          base_curr_vol,
		       for_alpha_base_vop,     back_alpha_base_vop,
		       enh_vop,
	               out_y_file, out_u_file, out_v_file, out_a_file,
	               time,
		       curr_base_frame,        enh_frame,
		       mode,                   bgc_mode,
		       enh_count,              post_filter_disable,
		       temporal_scalability);
	        
      FreeEnhanceVop(enh_vop, enh_count);
  }
  /* enh */
  else if(mode == 3)
      OnlyEnhanceWrite(base_config,            enh_config,
		       layer_config,
	               base_curr_vol,          enh_vol,	     
		       back_alpha_base_vop,    enh_vop,
	               out_y_file, out_u_file, out_v_file, out_a_file,
	               ref_time,               time,
		       mode,                   bgc_mode,
		       curr_base_frame,        enh_frame,
		       enh_count,          post_filter_disable);

  return;
} 
/***********************************************************CommentBegin******
 *
 * -- BackGroundComposition
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
void BackGroundComposition(Vop   *for_alpha_base_vop,
	                   Vop   *back_alpha_base_vop,
			   Vop   **old_enh_vop,
			   VolConfig *layer_config,
			   Vol   *layer_vol,
			   Float for_base_time,
	                   Float back_base_time,
			   Float enh_time,
			   Int   for_base_frame,
			   Int   back_base_frame,
			   Int   enh_frame,
			   Int   mode,
			   Int   bgc_mode,
			   Char  *out_y_file,
			   Char  *out_u_file,
			   Char  *out_v_file,
			   Char  *out_a_file)
{
  Vop *base_for_vop       = NULL;
  Vop *base_back_vop      = NULL;
  Vop *enh_vop_bb = NULL;
  Vop *display_vop        = NULL;

  if(mode ==2 || mode ==3){
      if(mode == 2){
          /* prepare enh_vop */
          enh_vop_bb = CloneVop(*old_enh_vop);
          CopyVopNonImageField_TPS(*old_enh_vop, enh_vop_bb);
	  /* prepare texture */
          base_for_vop  = CloneVop(for_alpha_base_vop);
          base_back_vop = CloneVop(back_alpha_base_vop);
       
          /*** 4/9 for TPS (SHARP) */     
          if(bgc_mode == 0){
	    PutVopBackComp(0, enh_vop_bb);
	    display_vop = AllocVop(GetVolWidth(layer_vol), GetVolHeight(layer_vol));
            PutVopQuantPrecision(GetVolQuantPrecision(layer_vol), display_vop);
	    PutVopBitsPerPixel(GetVolBitsPerPixel(layer_vol), display_vop);
            do_bgc(enh_vop_bb,
                   base_for_vop,                     
	           base_back_vop,                    
	           display_vop ,                 
	           enh_time, 
	           for_base_time,
	           back_base_time);
	  }
          else{
	    PutVopBackComp(1, enh_vop_bb);
            display_vop = AllocVop(GetVolWidth(layer_vol), GetVolHeight(layer_vol));
            PutVopQuantPrecision(GetVolQuantPrecision(layer_vol), display_vop);
	    PutVopBitsPerPixel(GetVolBitsPerPixel(layer_vol), display_vop);
	    do_bgc(enh_vop_bb,
	             base_for_vop,                     
	             base_back_vop,                    
	             display_vop ,                 
	             enh_time, 
	             for_base_time,
	             back_base_time);
	  }
      }    
      else if (mode == 3){
          /* prepare enh_vop */
	  enh_vop_bb = CloneVop(*old_enh_vop);
          CopyVopNonImageField_TPS(*old_enh_vop, enh_vop_bb);
	  /* prepare texture */
          base_for_vop = CloneVop(for_alpha_base_vop);

          if(bgc_mode == 0){
	    PutVopBackComp(0, enh_vop_bb);
	    display_vop = AllocVop(GetVolWidth(layer_vol), GetVolHeight(layer_vol));
            PutVopQuantPrecision(GetVolQuantPrecision(layer_vol), display_vop);
	    PutVopBitsPerPixel(GetVolBitsPerPixel(layer_vol), display_vop);
            do_bgc(enh_vop_bb,
	             base_for_vop,                     
	             base_for_vop,                    
	             display_vop ,                 
	             enh_time, 
	             for_base_time,
	             for_base_time);
	  }
          else{
	    PutVopBackComp(1, enh_vop_bb);
	    display_vop = AllocVop(GetVolWidth(layer_vol), GetVolHeight(layer_vol));
	    PutVopQuantPrecision(GetVolQuantPrecision(layer_vol), display_vop);
	    PutVopBitsPerPixel(GetVolBitsPerPixel(layer_vol), display_vop);
            do_bgc(enh_vop_bb,
	              base_for_vop,                     
	              base_for_vop,                    
	              display_vop ,                 
	              (Int)enh_time, 
	              (Int)for_base_time,
	              (Int)for_base_time);
	  }
      }

      /* write bgc image */
      WriteVopGeneric(display_vop,
		      out_y_file, out_u_file, out_v_file, out_a_file,
		      enh_frame, IO_FORMAT, IO_APPEND, FALSE);
      fprintf(stderr,"writed E[%3d]\n",enh_frame);
  
      /* Free */
      if(mode == 2)
          FreeVop(base_back_vop);
      FreeVop(base_for_vop);
      FreeVop(enh_vop_bb);
      FreeVop(display_vop);
  }
  return;
}



/***********************************************************CommentBegin******
 *
 * -- SearchRefConfig
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Int SearchRefConfig(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol;
  Int           scalability_flag;
  Int           vol_id;

  curr_vo = vo_config;
  
  while(curr_vo != NULL){
	curr_vol = GetVOConfigLayers(curr_vo);
	while(curr_vol != NULL){
	      scalability_flag = GetVolConfigScalability(curr_vol);
	      if (scalability_flag == 1){
		    vol_id = GetVolConfigId(curr_vol);
	            return(vol_id);
	      }
	      curr_vol = GetVolConfigNext(curr_vol);
	}
	curr_vo = GetVOConfigNext(curr_vo);
  }
  return(-1);
}
/***********************************************************CommentBegin******
 *
 * -- FirstBaseWrite
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Void
FirstBaseWrite(VolConfig *base_config,
	       VolConfig *layer_config,
	       Vol       *base_curr_vol,
	       Vop       *for_alpha_base_vop,
	       Char      out_y_file[],
	       Char      out_u_file[],
	       Char      out_v_file[],
	       Char      out_a_file[],
	       Int       post_filter_disable,
	       Int       base_frame,
	       Int       enh_type)
{
  Vop *local_for_vop = NULL;
  Int shape          = 0;
  
  if(GetVolVop(base_curr_vol) != NULL){
        local_for_vop = PostFilter_TPS(for_alpha_base_vop, post_filter_disable,
				    GetVolConfigDiskSeqX(layer_config),
				    GetVolConfigDiskSeqY(layer_config));
	/* for Type2 */
	if(enh_type == 0){
            shape         = GetVolConfigShape(base_config);
	    WriteVopGeneric(local_for_vop, 
			    out_y_file,out_u_file,out_v_file,out_a_file,
			    base_frame, IO_FORMAT, IO_APPEND,  shape);
	}
	/* for Type1 */
	else
            WriteVopGeneric(local_for_vop, 
			    out_y_file,out_u_file,out_v_file,out_a_file,
			    base_frame, IO_FORMAT, IO_APPEND,  FALSE);
	FreeVop(local_for_vop);
        fprintf(stderr,"writed B[%3d]\n",base_frame);
  }
  return;
}

/***********************************************************CommentBegin******
 *
 * --SecoundBaseWrite 
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Void
SecoundBaseWrite(VOConfig  *vo_config,
		 VolConfig *base_config,
	         VolConfig *enh_config,
	         VolConfig *layer_config,
	         VO        *next_rec_vo,
		 Vol       *base_prev_vol,
		 Vol       *base_curr_vol,
		 Vop       *for_alpha_base_vop,
	         Vop       *back_alpha_base_vop,
		 Vop       *enh_vop[],
	         Char      out_y_file[],
	         Char      out_u_file[],
	         Char      out_v_file[],
	         Char      out_a_file[],
	         Float     time,
	         Int       curr_base_frame,
		 Int       enh_frame,
		 Int       mode,
		 Int       bgc_mode,
		 Int       *enh_count,
		 Int       post_filter_disable,
		 Int       temporal_scalability)
	        
{
  Vol *enh_vol        = NULL;
  Vop *local_for_vop  = NULL,
      *local_back_vop = NULL,
      *local_enh_vop  = NULL;
  Int shape           = 0,
      i               = 0,
      enh_type,
      base_skip,
      enh_skip,
      enh_start_frame,
      enh_end_frame,
      enh_vol_id;
      
  Float for_base_time,
        back_base_time,
        enh_time;
  
  enh_vol_id      = SearchRefConfig(vo_config);
  enh_config      = GetVolConfigById(GetVOConfigLayers(vo_config), enh_vol_id);
  base_skip       = GetVolConfigFrameSkip(base_config);
  enh_skip        = GetVolConfigFrameSkip(enh_config);
  enh_start_frame = GetVolConfigStartFrame(enh_config);
  enh_end_frame   = GetVolConfigEndFrame(enh_config);
  enh_type        = GetVolConfigEnhanceType(enh_config);
  shape           = GetVolConfigShape(enh_config);

  for_base_time   = time - GetVolConfigTimeInc(base_config);
  enh_time        = time - GetVolConfigTimeInc(base_config) + GetVolConfigTimeInc(enh_config);
  back_base_time  = time;
   
  if(temporal_scalability != 3){
       for_base_time  = for_base_time  + GetVolConfigTimeInc(enh_config);
       enh_time       = enh_time       + GetVolConfigTimeInc(enh_config);
       back_base_time = back_base_time + GetVolConfigTimeInc(enh_config);
  }
  
  if(for_alpha_base_vop != NULL){
      local_for_vop  = PostFilter_TPS(for_alpha_base_vop, post_filter_disable,
				   GetVolConfigDiskSeqX(layer_config),
				   GetVolConfigDiskSeqY(layer_config));
  }
      
  
  if(GetVolVop(base_curr_vol) != NULL)
    local_back_vop = PostFilter_TPS(back_alpha_base_vop, post_filter_disable,
				   GetVolConfigDiskSeqX(layer_config),
				   GetVolConfigDiskSeqY(layer_config));
    
  /* enh_frame write */
  for(enh_frame = (curr_base_frame - base_skip) + enh_skip; 
      enh_frame < curr_base_frame;enh_frame += enh_skip){
      if(enh_start_frame <= enh_frame && enh_frame <= enh_end_frame ){
          if(enh_vop[i] != NULL){

	      
	      local_enh_vop = PostFilter_TPS(enh_vop[i], post_filter_disable,
			                  GetVolConfigDiskSeqX(layer_config),
			                  GetVolConfigDiskSeqY(layer_config));
	      
	      enh_vol = GetVolById(GetVOLayers(next_rec_vo), enh_vol_id);
	      /* for Type2 */
	      if(enh_type == 0){
      	          WriteVopGeneric(local_enh_vop, /* for deblock */
				  out_y_file,out_u_file,out_v_file,out_a_file,
				  enh_frame, IO_FORMAT, IO_APPEND, shape);
		  fprintf(stderr,"writed E[%3d]\n",enh_frame);
	      }
	      /* for Type1 */
	      else{
		  BackGroundComposition(local_for_vop,  
					local_back_vop, 
					&local_enh_vop,
					enh_config,
					base_curr_vol,
					for_base_time,  
					back_base_time, enh_time,
					curr_base_frame - GetVolConfigFrameSkip(base_config),
					curr_base_frame, enh_frame,
					mode,       bgc_mode,
					out_y_file, out_u_file, out_v_file, out_a_file); 
					
	      }
	      FreeVop(local_enh_vop);
	  } 
	  i++;
      }
      enh_time = enh_time + GetVolConfigTimeInc(enh_config);
  }/* for roop end. write base_vop for tps (except first frame) */

  /* curr_base_frame write */
  if(local_back_vop != NULL){
      if(enh_type == 0){
          shape = GetVolConfigShape(base_config);
          WriteVopGeneric(local_back_vop, 
		      out_y_file,out_u_file,out_v_file,out_a_file,
		      curr_base_frame, IO_FORMAT, IO_APPEND, shape);
      }
      else
          WriteVopGeneric(local_back_vop, 
		      out_y_file,out_u_file,out_v_file,out_a_file,
		      curr_base_frame, IO_FORMAT, IO_APPEND, FALSE);
      fprintf(stderr,"writed B[%3d]\n",curr_base_frame);
  }

  /* Free */
  if(local_back_vop != NULL)
      FreeVop(local_back_vop);	    
  if(local_for_vop != NULL)
      FreeVop(local_for_vop);
            

  return;
}

/***********************************************************CommentBegin******
 *
 * -- OnlyEnhanceWrite
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Void
OnlyEnhanceWrite(VolConfig *base_config,
	         VolConfig *enh_config, 
	         VolConfig *layer_config,
	         Vol       *base_curr_vol,
		 Vol       *enh_vol,	     
		 Vop       *alpha_base_vop,
	         Vop       *enh_vop[],
	         Char      out_y_file[],
	         Char      out_u_file[],
	         Char      out_v_file[],
	         Char      out_a_file[],
	         Float     ref_time,
		 Float     time,
		 Int       mode,
		 Int       bgc_mode,
		 Int       curr_base_frame,
		 Int       enh_frame,
		 Int       *enh_count,
	         Int       post_filter_disable)
{
  Int shape = 0, enh_type = 0;
  Vop *local_enh_vop  = NULL;
  Vop *local_vop  = NULL;
  Float enh_time;
  Float for_base_time;

  for_base_time = ref_time;
  enh_time      = time;
    
  if(enh_frame != curr_base_frame && 
     curr_base_frame   + GetVolConfigFrameSkip(base_config) >=
     enh_frame + GetVolConfigFrameSkip(enh_config)){
      enh_type = GetVolConfigEnhanceType(enh_config);
      shape            = GetVolConfigShape(enh_config);

      if(enh_vop[0] != NULL){
	  local_enh_vop = PostFilter_TPS(enh_vop[0], post_filter_disable,
		       	              GetVolConfigDiskSeqX(layer_config),
				      GetVolConfigDiskSeqY(layer_config));
	  if(GetVolVop(base_curr_vol) != NULL)
	     local_vop = PostFilter_TPS(alpha_base_vop, post_filter_disable,
		       	              GetVolConfigDiskSeqX(layer_config),
				      GetVolConfigDiskSeqY(layer_config));
	  /* for type2 */
	  if(enh_type == 0){
	      WriteVopGeneric(local_enh_vop, /* for deblock */
			      out_y_file,out_u_file,out_v_file,out_a_file,
			      enh_frame, IO_FORMAT, IO_APPEND, shape); 
	      fprintf(stderr,"writed E[%3d]\n",enh_frame);
	  }
          /* for type1 */
	  else{
	      BackGroundComposition(local_vop,  
				    NULL, 
				    &local_enh_vop,
				    base_config,
				    base_curr_vol,
				    for_base_time, for_base_time, 
				    enh_time,
			            curr_base_frame, curr_base_frame, enh_frame,
				    mode,       bgc_mode,
				    out_y_file, out_u_file, out_v_file, out_a_file);
	  }

	  if(local_vop != NULL)
	      FreeVop(local_vop);
	  FreeVop(local_enh_vop);
      }
  }
  if(enh_vop[0]!= NULL){
      FreeVop(enh_vop[0]);
      enh_vop[0] = NULL;
  }
  *enh_count = 0;

  return;
}
/***********************************************************CommentBegin******
 *
 * -- test_malloc
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Int
test_malloc()
{
        UChar   *pointer;

        pointer = ( UChar * )malloc( 0x10000 );
        if ( pointer == NULL ) {
                printf( "error in malloc()\n" );
                return( 1 );
        }
        else printf( "pointer = %x\n" , (int)pointer );
        free( pointer );

        return( 0 );
}

/***********************************************************CommentBegin******
 *
 * -- SaveBaseImage_BGC
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/

Void
SaveBaseImage_BGC(VolConfig *layer_config,
		  Vop *curr_vop,
		  Vop *base_vop_not_padding_for_bgc,
		  Vop *rec_vop,
		  Int enh_type,
		  Int prediction_type,
		  Vop *curr_vop_bb,
		  Vop **base_B_vop_TPS,
     /* 4/19 changed by SHARP */
		  Int temporal_scalability)
     /* 4/19 changed by SHARP */
{
  Int curr_frame,
      frame_skip,
      start_frame,
      end_frame;
  
  Vop *tmp_vop          = NULL,
      *tmp_vop2         = NULL,
      *needs_alpha_for  = NULL,
      *needs_alpha_back = NULL,
      *tmp_b            = NULL;
	  
  frame_skip  = GetVolConfigFrameSkip(layer_config);
  start_frame = GetVolConfigStartFrame(layer_config);
  end_frame   = GetVolConfigEndFrame(layer_config);
  curr_frame  = GetVolConfigFrameBack(layer_config);
  
  /* first */
  if(curr_frame == start_frame){
      tmp_vop = CloneVop(curr_vop);
      CopyVopNonImageField_TPS(curr_vop, tmp_vop);
      PutVopPrevTemp(tmp_vop, base_vop_not_padding_for_bgc);
      
      tmp_vop2 = CloneVop(curr_vop);
      CopyVopNonImageField_TPS(curr_vop, tmp_vop2);
      PutVopNextTemp(tmp_vop2, base_vop_not_padding_for_bgc);
  }
  /* only 1 picture */
  else if(start_frame + frame_skip > end_frame){
      tmp_vop = CloneVop(curr_vop);
      CopyVopNonImageField_TPS(curr_vop, tmp_vop);
      PutVopNextTemp(tmp_vop, base_vop_not_padding_for_bgc);
  }
  /* secound */
  else{
      if(prediction_type != B_VOP){
          if(rec_vop != NULL){
	      if(enh_type == 1){
		  if(base_vop_not_padding_for_bgc != NULL){
		      if(GetVopPrevTemp(base_vop_not_padding_for_bgc) != NULL){
	                  needs_alpha_for  = CloneVop(GetVopPrevTemp(base_vop_not_padding_for_bgc));
		          CopyVopNonImageField_TPS(GetVopPrevTemp(base_vop_not_padding_for_bgc), needs_alpha_for);
		      }
      
	              if(GetVopNextTemp(base_vop_not_padding_for_bgc) != NULL){
	                  needs_alpha_back = CloneVop(GetVopNextTemp(base_vop_not_padding_for_bgc));
		          CopyVopNonImageField_TPS(GetVopNextTemp(base_vop_not_padding_for_bgc),needs_alpha_back);
		      }
	          }
	      }
	      
              FreeVop(GetVopPrevTemp(base_vop_not_padding_for_bgc));
              PutVopPrevTemp(NULL, base_vop_not_padding_for_bgc);
	  
              tmp_vop = CloneVop(GetVopNextTemp(base_vop_not_padding_for_bgc));
	      CopyVopNonImageField_TPS(GetVopNextTemp(base_vop_not_padding_for_bgc),tmp_vop);
	      if(enh_type == 1){
	          CopyAlpha(needs_alpha_for, tmp_vop);
		  FreeVop(needs_alpha_for);
	      }
	      PutVopPrevTemp(tmp_vop, base_vop_not_padding_for_bgc);
	      
              FreeVop(GetVopNextTemp(base_vop_not_padding_for_bgc));
	      PutVopNextTemp(NULL, base_vop_not_padding_for_bgc);
	      
	      tmp_vop2 = CloneVop(curr_vop);
	      CopyVopNonImageField_TPS(curr_vop,tmp_vop2);
	      if(enh_type == 1){
	          CopyAlpha(needs_alpha_back, tmp_vop2);
		  FreeVop(needs_alpha_back);
	      }
	      PutVopNextTemp(tmp_vop2, base_vop_not_padding_for_bgc);
         }
          else{
	      tmp_vop = CloneVop(curr_vop);
              CopyVopNonImageField_TPS(curr_vop,tmp_vop);
	      PutVopPrevTemp(tmp_vop, base_vop_not_padding_for_bgc);
              tmp_vop2 = CloneVop(curr_vop);
              CopyVopNonImageField_TPS(curr_vop,tmp_vop2);
	      PutVopNextTemp(tmp_vop2, base_vop_not_padding_for_bgc);
          }
      }
      /* for B_VOP (base) */
      else{ 
          if(*base_B_vop_TPS != NULL){
	      /* free */
	      if(GetVopNextTemp(*base_B_vop_TPS) != NULL){
	          FreeVop(GetVopNextTemp(*base_B_vop_TPS));
	          PutVopNextTemp(NULL, *base_B_vop_TPS);
	      }
	      FreeVop(*base_B_vop_TPS);
	      *base_B_vop_TPS = NULL;
	  }
	      
	  /* save rec and prev */
	  *base_B_vop_TPS = CloneVop(curr_vop);  /* rec_vop save */
	  CopyVopNonImageField_TPS(curr_vop, *base_B_vop_TPS);
/* 4/19 changed by SHARP */
	  if(temporal_scalability == 2)
	    tmp_b           = CloneVop_TMP(curr_vop_bb);
	  else
	    tmp_b           = CloneVop(curr_vop_bb);
/* 4/19 changed by SHARP */
	  
	  CopyVopNonImageField_TPS(curr_vop_bb, tmp_b);
	  PutVopNextTemp(tmp_b, *base_B_vop_TPS);/* prev_vop save */
     }/* B_VOP end */
  }/* secound end */

 return;
}
/***********************************************************CommentBegin******
 *
 * -- FreeEnhanceVop
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Void
FreeEnhanceVop(Vop *enh_vop[], Int *enh_count)
{
  Int count;
  Int i;

  count = *enh_count;
  for(i = 0; i < count; i++){
      if(enh_vop[i] != NULL){
           FreeVop(enh_vop[i]);
	   enh_vop[i] = NULL;
      }
  }
  *enh_count = 0;
  return;
}
/***********************************************************CommentBegin******
 *
 * -- DecideModeWriteBGC
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Int  
DecideModeWriteBGC(VOConfig  *vo_config,
		   VolConfig *layer_config,
		   VolConfig *base_config,
		   VolConfig *enh_config,       
		   Int       vo_id,
		   Int       vol_id,
		   Int       temporal_scalability,
		   Int       *curr_base_frame,
		   Int       *enh_frame,
		   Int       finish_base)
{
  Int mode       = -9;
  Int base_skip  = GetVolConfigFrameSkip(base_config);
  Int base_start = GetVolConfigStartFrame(base_config);
  Int base_end   = GetVolConfigEndFrame(base_config);
  Int enh_skip;
  Int enh_start;

  *curr_base_frame  = GetVolConfigFrameBack(base_config);

  
  if((temporal_scalability == 5 ||
      temporal_scalability == 2    ) &&
     GetVolConfigScalability( layer_config ) &&
     CheckEnhanceMode_TPS_B_type2(vo_config, vo_id, vol_id, finish_base) == 1)
      *curr_base_frame -= GetVolConfigFrameSkip(base_config);
  
  
  /* base */
  if(!GetVolConfigScalability(layer_config)){
      if(temporal_scalability == 3){
	  if(*curr_base_frame == base_start)
              mode = 1;   /* first base write */
          else
	      mode = 2;   /* enh write and secound base write */
      }
      /* B MODE */
      else {
	  if(*curr_base_frame == base_start)
	      mode = 1;   /* first base write */
	  else
	      mode = -1;
      }
  }
  /* enh */
  else{
      enh_skip    = GetVolConfigFrameSkip(enh_config);
      enh_start   = GetVolConfigStartFrame(enh_config);
      *enh_frame  = GetVolConfigFrameBack(enh_config);
      if(temporal_scalability == 3){
	  if(*curr_base_frame != *enh_frame &&
	     !(*enh_frame <= base_end && *curr_base_frame + base_skip <= base_end))
	      mode = 3;   /* only enh write */
	  else
	      mode = -1;  /* not write */
      }
      /* B MODE */      
      else{
	  if(*curr_base_frame / (*enh_frame + enh_skip) == 1 &&
	     *curr_base_frame % (*enh_frame + enh_skip) == 0 &&
	     *enh_frame + enh_skip <= base_end)
	      mode = 2;  /* E ... B write */
	  else if(*enh_frame > *curr_base_frame)
	      mode = 3;  /* E write */
	  else
	      mode = -2;/* not write */
      }
  }
  
  if(mode == -2)
      mode = -1;
  
  return(mode);
}

/***********************************************************CommentBegin******
 *
 * -- ChangeBaseImage_BGC
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/

Void
ChangeBaseImage_BGC(VOConfig  *vo_config,
		    Vop       *vop_for_bgc,
		    Vop       **base_B_vop_TPS,
		    Int       vo_id,
		    Int       vol_id,
		    Int       frame,
		    Vop       **original_prev_base_vop,
		    Int       finish_base)
{
  Int mode      = 0;
  Vop *save_vop = NULL;

  Vop *original = NULL;

  mode     = CheckEnhanceMode_TPS_B_type2(vo_config, vo_id, vol_id, finish_base);
 
  if(mode == 1){
      /*** for original image ***/
      /* free next (original) */
      if(*original_prev_base_vop != NULL){
	  if(GetVopNextTemp(*original_prev_base_vop) != NULL){
              FreeVop(GetVopNextTemp(*original_prev_base_vop));
              PutVopNextTemp(NULL, *original_prev_base_vop);
	  }
      }
      /* put next (original) */
      if(*base_B_vop_TPS != NULL){
	  if(GetVopNextTemp(*base_B_vop_TPS) != NULL) {
	      original = CloneVop(GetVopNextTemp(*base_B_vop_TPS));
              PutVopNextTemp(original, *original_prev_base_vop);
	  }
      }
      /*** bgc image ***/
      if(vop_for_bgc != NULL){
	  /* save & free next (bgc) */
          if(GetVopNextTemp(vop_for_bgc) != NULL){
              save_vop = CloneVop(GetVopNextTemp(vop_for_bgc));
              FreeVop(GetVopNextTemp(vop_for_bgc));
              PutVopNextTemp(NULL, vop_for_bgc);
	  }
          /* put next (bgc) */
          if(*base_B_vop_TPS != NULL){
	      PutVopNextTemp(CloneVop(*base_B_vop_TPS), vop_for_bgc);
              if(GetVopNextTemp(*base_B_vop_TPS) != NULL){
	           FreeVop(GetVopNextTemp(*base_B_vop_TPS));
	           PutVopNextTemp(NULL, *base_B_vop_TPS);
	      }
	      FreeVop(*base_B_vop_TPS);
	      *base_B_vop_TPS = NULL;
	  }
	  if(save_vop != NULL){
              *base_B_vop_TPS = CloneVop(save_vop);
              FreeVop(save_vop);
	  }
      }
  }
  else if(mode == 2){
      /*** for original image ***/
      if(*original_prev_base_vop != NULL){
          if(GetVopNextTemp(*original_prev_base_vop) != NULL){
              original = CloneVop(GetVopNextTemp(*original_prev_base_vop));
              /* free next */
              FreeVop(GetVopNextTemp(*original_prev_base_vop));
              PutVopNextTemp(NULL, *original_prev_base_vop);
	  }
          /* free vop */
          FreeVop(*original_prev_base_vop);
	  *original_prev_base_vop = NULL;
	  if(original != NULL)
	      *original_prev_base_vop = original;
      }
      /*** for original image ***/
      if(vop_for_bgc != NULL){
          if(GetVopPrevTemp(vop_for_bgc) != NULL){
              FreeVop(GetVopPrevTemp(vop_for_bgc));
	      PutVopPrevTemp(NULL,vop_for_bgc);
          }
          if(GetVopNextTemp(vop_for_bgc) != NULL){
              PutVopPrevTemp(CloneVop(GetVopNextTemp(vop_for_bgc)), vop_for_bgc);
              FreeVop(GetVopNextTemp(vop_for_bgc));
	      PutVopNextTemp(NULL, vop_for_bgc);
          }
          if(*base_B_vop_TPS != NULL)
              PutVopNextTemp(CloneVop(*base_B_vop_TPS), vop_for_bgc);
      }
      /* free vop */
      if(*base_B_vop_TPS != NULL){
	  FreeVop(*base_B_vop_TPS);
          *base_B_vop_TPS = NULL;
      }
	  
  }
  return;
}









