/************************************************************************/
/*                                                                      */
/* 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 and ACTS-MoMuSys 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                                                    */
/*                                                                      */
/************************************************************************/

/************************************************************************
 * Modified:
 *     07.07.97 Martina Eckert: Introduction of global rate control 
 *              functions and parameters
 *     25.07.97 Ulrike Pestel: Incrementation of frame number removed.
 *     30.07.97 Fernando Jaureguizar: deleted some old_and_commented_out
 *              code concerning Rate Control (labelled as "RC2: comented out")
 *     02.12.97 M. Eckert: Changes for independent frame type rate control
 *     16.01.98 M. Eckert: Changes depending on parameter-ctl-string 
 *
 ************************************************************************/




/***********************************************************CommentBegin******
 All functions in this file were written or modified by 
 Hisashi Saiga & Ryuji Kitaura of Sharp Corporation, 1997
 utilizing existing subroutines and data structures. 
 ***********************************************************CommentEnd********/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vm_config.h"
#include "momusys.h"
#include "mom_vol.h"
#include "mom_putbits.h"
#include "mom_structs.h"
#include "vm_vop_code.h"
#include "vm_vop_bound.h"
#include "mot_comp.h"
#include "mot_util.h"
#include "rc.h"
#include "vm_common_defs.h"
#include "vm_stats.h"
#include "vm_enc_main.h"
#include "alp_code_grey.h"
#include "alp_code_mom.h"
#include "alp_code_header.h"
#include "mot_padding.h"
#include "io_generic.h"
#include "do_bgc.h"
#include "mot_padding.h"
#include "enhance_vop.h"
#include "io_sharp.h"

Image                *for_first_shape_code_bitstream,   
                     *for_shape_bitstream,          
                     *back_first_shape_code_bitstream,   
                     *back_shape_bitstream;
Int   	             first_flag = 1;
Int	             back_base_exist;
Int	             comp_image_counter;
Int                  need_for_back_shape = 0;

extern Int           for_shape_width ,
                     for_shape_height ,
                     for_shape_hor_spat_ref ,
                     for_shape_ver_spat_ref,
                     back_shape_width ,
                     back_shape_height ,
                     back_shape_hor_spat_ref ,
                     back_shape_ver_spat_ref;

/***********************************************************CommentBegin******
 *
 * -- CodeEnhancementVol
 *
 ***********************************************************CommentEnd********/
Void
CodeEnhancementVol(Vol	         *enhancement_layer,
                   VOConfig      *vo_config, 
                   Int	         frame,
                   Float         time,
                   VO            *prev_vo,     
                   VO            *rec_vo,      
                   VO            *next_vo,     
                   VO            *next_rec_vo, 
                   Int           TRB,
                   Int           TRD,  
                   Int           vo_id,    
                   VOConfig      *vo_config_list, /* UPM Global RC */
                   Int           rc_type,         /* UPM Global RC */
                   Int           rc_algorithm,         /* hjlee */
                   Int           *frame_type,     /* UPM Global RC */
                   BitCount      num_bits[MAX_NUM_VOS][MAX_NUM_VOLS],
                   Vol           *B_vol_store,
                   EncodeControl *enc_ctl,
                   Vop           *base_vop_not_padding_for_bgc,
                   Vop           *enhance_vop[],
                   Int           *enhance_count,
                   Int           bgc_mode,
                   Int           temporal_scalability,
                   Vop           *original_prev_base_vop,
                   Int   	 finish_base) 
{
 VolConfig *layer_config,
           *ref_layer_config;
 Vol       *next_vol_store,
                  *next_rec_vol_store,
           *prev_vol,
           *rec_vol;
 Vop	   *curr_vop_in         = NULL,
    	   *curr_vop_bb         = NULL,
    	   *prev_vop            = NULL,
    	   *rec_vop             = NULL,
    	   *rec_curr            = NULL,
           *no_padding_vop      = NULL,
           *next_vop            = NULL,
           *next_rec_vop        = NULL,
           *for_alpha_base_vop  = NULL,
           *back_alpha_base_vop = NULL;
 Int 	   shape,
    	   vop_has_content,
    	   vol_id,
    	   vop_type,
    	   output_frame,
           vop_quantizer,
    	   temp_ref,
    	   target_bitrate,
    	   end_time,
           count,
           ref_vol_id,
           back_base_frame,
           for_base_frame,
           ref_mode,
           for_shape_exist       = 0,
           last_enhancement_mode = 0;
 
 for_alpha_base_vop  = GetVopPrevTemp(base_vop_not_padding_for_bgc);
 back_alpha_base_vop = GetVopNextTemp(base_vop_not_padding_for_bgc);
 ref_vol_id          = GetVolRefId(enhancement_layer);
 vol_id              = GetVolId(enhancement_layer);
 ref_layer_config    = GetVolConfigById(GetVOConfigLayers(vo_config),  ref_vol_id);
 layer_config        = (GetVolConfigById(GetVOConfigLayers(vo_config), vol_id));

 SetRefVop_TPS(vo_config,
               layer_config,           ref_layer_config, 
               next_vo,                next_rec_vo,
               prev_vo,                rec_vo,
               &next_vol_store,        &next_rec_vol_store,
               &next_vop,              &next_rec_vop,
               &prev_vol,              &rec_vol,
               &rec_vop,               &prev_vop,
               &for_alpha_base_vop,    &back_alpha_base_vop,
               original_prev_base_vop, base_vop_not_padding_for_bgc,
               vo_id, ref_vol_id,      vol_id,
               frame, &for_base_frame, &back_base_frame,
               &ref_mode,              &need_for_back_shape,
               &back_base_exist,       &last_enhancement_mode,
               temporal_scalability,   finish_base);
       

 /* Put some text for user (DISPLAY and STATS FILE) */
#ifndef NLSSTATS
 PrintVolTimeStartStat(num_bits,vo_id,vol_id,frame,DISPLAY);
 PrintVolTimeStartStat(num_bits,vo_id,vol_id,frame,STATS_FILE);
#endif

 curr_vop_in = GetVolVop(enhancement_layer);
 ReadVopGeneric(GetVolConfigY(layer_config),
   GetVolConfigU(layer_config),
   GetVolConfigV(layer_config),
   GetVolConfigA(layer_config),
   frame,
   IO_FORMAT,
   curr_vop_in);

 /* Disable shape coding if required */
 shape = GetVolConfigShape(layer_config);

 PutVopShape(shape,curr_vop_in);
 if (shape == RECTANGULAR)
  SetConstantImage(GetVopA(curr_vop_in),BINARY_ALPHA);	
 else
  if(shape == GREY_SCALE)
   PutVopBinaryShape(!BINARY,curr_vop_in);
  else
   PutVopBinaryShape(BINARY,curr_vop_in);



  /* Need to extract bounded vop from vop read in from disk */
  /* Calc. width, height, horizontal/vertical spatial
     reference, shape of vop (REACTANGLE or ARBITRARY),
     and the type of alpha map (BINARY or NON-BINARY).
     Also extract relevant image data */

 curr_vop_bb = GetVopBounded(curr_vop_in,1,1,&vop_has_content);

 /* Get RateControl type */
 /* Changed to GetEncodeControlRCType(enc_ctl) in Main: */
 /* rc_type = GetVolConfigRateControl(layer_config);*/


 /*** TPS palameter setting to the vop ***/
 if( bgc_mode && vop_has_content){
   if(need_for_back_shape == 0)
     need_for_back_shape = 1;
   if (first_flag && for_alpha_base_vop != NULL)
     for_shape_exist = 1;
   else
     for_shape_exist = 0;
 }
 /*** Setting for curr_vop_bb  ***/
 SetCurrVop_TPS(layer_config, enhancement_layer,
                curr_vop_bb,
		rec_vop,
		next_rec_vop,
		vo_id,
                vol_id,          ref_vol_id,
                ref_mode,        for_shape_exist,
                first_flag,      bgc_mode,
                vop_has_content, temporal_scalability,
                finish_base,     &need_for_back_shape);


 /*** shape for BGC encoding  ***/
 if ( vop_has_content && GetVolConfigEnhanceType( layer_config ) && bgc_mode == 1 ){
     if ( for_shape_exist )
         ProcessForShape( ref_layer_config, layer_config ,
                          for_base_frame,   frame,
                          vo_id ,           num_bits ,          
                          for_alpha_base_vop );
     if (!back_base_exist){
       if (!for_shape_exist && temporal_scalability != 2)
         ProcessChangeShape(for_shape_exist ,    ref_layer_config ,
                            layer_config ,       for_alpha_base_vop,
                            back_alpha_base_vop, temporal_scalability );
         ProcessBackShape( ref_layer_config,    layer_config ,
             back_base_frame,     frame,
             vo_id ,              num_bits ,
             back_alpha_base_vop );
     }
 }
    if (vop_has_content)
          no_padding_vop = AllocVop(GetVopWidth(curr_vop_bb),GetVopHeight(curr_vop_bb));

    /* decide PredictionType */
    if(temporal_scalability == 3 ||
       temporal_scalability == 4||
       temporal_scalability == 5)
                 PutVopPredictionType(P_VOP,curr_vop_bb);
           else if(temporal_scalability == 1 ||
     temporal_scalability == 2)
                 PutVopPredictionType(B_VOP,curr_vop_bb);

     rec_curr = VopProcess(curr_vop_bb,
     prev_vop,
     rec_vop,
     next_vop,
     next_rec_vop,
     time,
     layer_config,
     vop_has_content,
     vo_id,TRB,TRD, 
     vo_config_list, /* UPM Global RC */
     rc_type,        /* UPM Global RC */
     rc_algorithm,        /* hjlee */
     num_bits,
     no_padding_vop,
     temporal_scalability);

 count          = *enhance_count;     
 count++;
 *enhance_count = count;
 *frame_type    = GetVopPredictionType(curr_vop_bb); /* RC-BIP */

 if (vop_has_content) {  /* added Minhua Zhou 15-05-97 */
   enhance_vop[count - 1] = CloneVop(no_padding_vop);
   CopyVopNonImageField_TPS(curr_vop_bb, enhance_vop[count - 1]);
   PrintEncodeProcess_TPS(GetVopScalability(curr_vop_bb),
                          GetVopPredictionType(curr_vop_bb),
                          GetVolConfigFrameBack(layer_config),0);
   if (rc_type == VM5_RATE_CONTROL)
   {
     if ((prev_vop==NULL)||(GetVopWidth(prev_vop)==0)) /* Minhua Zhou 15-05-97 */
       RC_ExcludeIFrame(vo_id, vol_id, num_bits[vo_id][vol_id].vop);
     /* UPM Global RC */
     else
     {
       Int num_bits_header;	       /* ME - 26.09.97 */

       num_bits_header = num_bits[vo_id][vol_id].vop
                       - num_bits[vo_id][vol_id].mot_shape_text;

       RC_UpdateModel(vo_id, vol_id,
                      num_bits[vo_id][vol_id].vop,
                      num_bits_header,
                      num_bits[vo_id][vol_id].psnr_y,
                      GetVopPredictionType(curr_vop_bb));
     }
#if 0
     /* RC2: adding combined mode rate control */
       DSRC_Update2OrderModel(vo_id, vol_id,
           num_bits[vol_id][vol_id].vop, 0,	1);
#endif
   }
 }

 /* Update the VOL stores with coded vop and the original vop */
 if (vop_has_content){	
   /* Write the coded vop to disk if required */
   if (GetVolConfigWriteCoded(layer_config))
     WriteCodedVopToDisk(rec_curr,
                         GetVolConfigCodedY(layer_config),
                         GetVolConfigCodedU(layer_config),
                         GetVolConfigCodedV(layer_config),
                         GetVolConfigCodedA(layer_config),
                         frame,
                         GetVolConfigDiskSeqX(layer_config),
                         GetVolConfigDiskSeqY(layer_config),
                         GetVolConfigShape(layer_config),
                         vop_has_content);
    
   if (B_vol_store==NULL) {
     /* if use I_VOP or P_VOP : TPS */
     if(temporal_scalability != 5 &&
        (frame + GetVolConfigFrameSkip(layer_config) == back_base_frame ||
        frame == GetVolConfigEndFrame(layer_config)) ){
       FreeVop(curr_vop_bb);
       FreeVop(rec_curr);
     }
     else{
       UpdateVolStore(curr_vop_bb, vol_id, next_vol_store);
       UpdateVolStore(rec_curr,    vol_id, next_rec_vol_store);
     }
   }
   else {
              /* if use B_VOP : TPS */
               if(temporal_scalability == 1){
                  FreeVop(curr_vop_bb);
                  FreeVop(rec_curr);
              }
              else if(temporal_scalability == 2){
                  UpdateVolStore(curr_vop_bb, vol_id, next_vol_store);
                  UpdateVolStore(rec_curr,    vol_id, next_rec_vol_store);
              }
               else if(temporal_scalability !=3 && 
               (frame + GetVolConfigFrameSkip(layer_config ) == back_base_frame))
                FreeVop(rec_curr);
              else 
           UpdateVolStore(rec_curr, vol_id, B_vol_store);
            }
        }

 /* If the VOP is empty but the previous VOP exists, then the VO
     has disappeared. In this case the VOL stores are updated with
     a NULL VOP so that the disappearing VO is not composited
       onto the ouput display image - NOC 14/01/97 */
 else if((!vop_has_content) && (prev_vop != NULL)){
            if (B_vol_store==NULL) {
  UpdateVolStore(NULL, vol_id, next_vol_store);
  UpdateVolStore(NULL ,vol_id, next_rec_vol_store);
            }
     else
         UpdateVolStore(NULL, vol_id, B_vol_store);
   }

 output_frame = (Int) (time*GetVolConfigFrameRate(layer_config)/1000. + .5);

 if ((rc_type == VM4_RATE_CONTROL)&&(vop_has_content)) /* modified by Minhua Zhou 15-05-97
 */	
  {
  end_time = GetVolConfigEndTime(layer_config);

  if (((time - GetVolConfigStartTime(layer_config)) != 0) &&
   (time < end_time))
   {

   vop_quantizer = GetVolConfigQuantizer(layer_config);
   target_bitrate = GetVolConfigBitrate(layer_config);
   temp_ref = 1000 / GetVolConfigFrameRate(layer_config);

   QuantAdjust (target_bitrate,
     temp_ref,
     end_time,
     time,
     num_bits[vo_id][vol_id].average,
     num_bits[vo_id][vol_id].vop,
     &vop_quantizer);
   fprintf(stdout, ">>>>> New quantizer= %d\n", (int)vop_quantizer);

   PutVolConfigQuantizer(vop_quantizer,layer_config);
   }
  }


 /* Put some text for user */
 vop_type = GetVopPredictionType(curr_vop_bb);

#ifndef NLSSTATS
 PrintVolTimeEndStat(num_bits,vo_id,vol_id,vop_type,DISPLAY);
 PrintVolTimeEndStat(num_bits,vo_id,vol_id,vop_type,STATS_FILE);
#endif

 /* Reset bit counts for the next time this VOL is coded */
 num_bits[vo_id][vol_id].syntax = 0;
 num_bits[vo_id][vol_id].shape = 0;
 num_bits[vo_id][vol_id].texture = 0;
 num_bits[vo_id][vol_id].motion = 0;
 num_bits[vo_id][vol_id].mot_shape_text = 0;
 num_bits[vo_id][vol_id].vop = 0;

 /* Increment occurrence counter for this VOL */
 num_bits[vo_id][vol_id].occurrence++;

 if (vop_has_content && GetVopLoadBackShape(curr_vop_bb))
          first_flag = 0;
 if(last_enhancement_mode == 1 && need_for_back_shape == 0)/*qqq*/
          first_flag = 1;
 /* if use B_VOP or I_VOP or P_VOP(ref_mode): TPS */
 /* FreeVop */
 if (temporal_scalability !=2){
     if(ref_mode == 1 || temporal_scalability == 1){ 
                if(GetVolVop(rec_vol)  != NULL) PutVopShape( 0 , prev_vop );
         if(GetVolVop(prev_vol) != NULL) PutVopShape( 0 , rec_vop );
         if(rec_vop             != NULL) FreeVop(rec_vop);
         if(prev_vop            != NULL) FreeVop(prev_vop);
     }
 }
 if(temporal_scalability == 2 || temporal_scalability == 1){
     if(next_vop != NULL)
         FreeVop(next_vop);
     if(next_rec_vop != NULL)
         FreeVop(next_rec_vop);
 }
 if(no_padding_vop != NULL)
     FreeVop(no_padding_vop);
 
 return;
}

/***********************************************************CommentBegin******
 *
 * -- ProcessForShape -- Base layer's shape coding for BackGroundComposition
 *
 ***********************************************************CommentEnd********/
Void
ProcessForShape(VolConfig *ref_layer_config  ,
  VolConfig *layer_config ,
  Int       for_base_frame ,
  Int       frame,
  Int       vo_id ,
  BitCount  num_bits[MAX_NUM_VOS][MAX_NUM_VOLS] ,
  Vop       *for_alpha_base_vop)
{
 Vop     *rec_for_alpha_vop = NULL;
 Vop	*original_for_alpha_vop = NULL;

 for_first_shape_code_bitstream  = BitstreamInit();   
 for_shape_bitstream             = BitstreamInit();
 original_for_alpha_vop = AllocVop( GetVolConfigDiskSeqX( ref_layer_config ) ,
                                    GetVolConfigDiskSeqY( ref_layer_config ) );

         ReadVopGeneric( GetVolConfigY( ref_layer_config ) ,
          GetVolConfigU( ref_layer_config ) ,
          GetVolConfigV( ref_layer_config ) ,
          GetVolConfigA( ref_layer_config ) ,
          for_base_frame ,
          IO_FORMAT,
          original_for_alpha_vop );
  PutVopShape( 1 , original_for_alpha_vop );
  rec_for_alpha_vop = CodeBaseAlpha(original_for_alpha_vop ,
       vo_id ,
       layer_config,
       for_base_frame ,
       num_bits,
       GetVopShape( original_for_alpha_vop ) ,
       for_first_shape_code_bitstream,
       for_shape_bitstream,
       &for_shape_width ,        &for_shape_height ,
       &for_shape_hor_spat_ref , &for_shape_ver_spat_ref );
                CopyAlpha(rec_for_alpha_vop,for_alpha_base_vop);

                FreeVop(original_for_alpha_vop);
         FreeVop(rec_for_alpha_vop);
         return;
}

/***********************************************************CommentBegin******
 *
 * -- ProcessChangeShape -- Base layer's shape coding for BackGroundComposition
 *
 ***********************************************************CommentEnd********/
Void ProcessChangeShape(Int       for_shape_exist ,
   VolConfig *ref_layer_config  ,
   VolConfig *layer_config ,
   Vop       *for_alpha_base_vop,
                        Vop       *back_alpha_base_vop,
   Int       temporal_scalability)
{
        Int enh_skip   = GetVolConfigFrameSkip( layer_config );
        Int enh_frame  = GetVolConfigFrameBack( layer_config );
 Int base_frame = GetVolConfigFrameBack( ref_layer_config );
 Int base_skip  = GetVolConfigFrameSkip( ref_layer_config );


 if(temporal_scalability != 3)
     base_frame -= base_skip;
 if(!for_shape_exist && enh_frame == base_frame + enh_skip )
     CopyAlpha(back_alpha_base_vop, for_alpha_base_vop);
 return;
}

/***********************************************************CommentBegin******
 *
 * -- ProcessBackShape -- Base layer's shape coding for BackGroundComposition
 *
 ***********************************************************CommentEnd********/
Void
ProcessBackShape(VolConfig *ref_layer_config  ,
   VolConfig *layer_config ,
   Int       back_base_frame ,
   Int       frame,
   Int       vo_id ,
   BitCount  num_bits[MAX_NUM_VOS][MAX_NUM_VOLS] ,
   Vop       *back_alpha_base_vop)
{
 Vop     *rec_back_alpha_vop      = NULL;
        Vop	*original_back_alpha_vop = NULL; 


 /* back alpha */
 back_first_shape_code_bitstream = BitstreamInit();   
 back_shape_bitstream            = BitstreamInit();
 original_back_alpha_vop = AllocVop( GetVolConfigDiskSeqX( ref_layer_config ) ,
                       GetVolConfigDiskSeqY( ref_layer_config ) );
 ReadVopGeneric(GetVolConfigY( ref_layer_config ) ,
          GetVolConfigU( ref_layer_config ),
          GetVolConfigV( ref_layer_config ),
          GetVolConfigA( ref_layer_config ),
          back_base_frame ,
          IO_FORMAT,
          original_back_alpha_vop );
 PutVopShape( 1 , original_back_alpha_vop );
 rec_back_alpha_vop = CodeBaseAlpha( original_back_alpha_vop ,
          vo_id,
          layer_config,
          back_base_frame ,
          num_bits,
          GetVopShape( original_back_alpha_vop ) ,
          back_first_shape_code_bitstream,
          back_shape_bitstream,
          &back_shape_width ,        &back_shape_height ,
          &back_shape_hor_spat_ref , &back_shape_ver_spat_ref );
 CopyAlpha(rec_back_alpha_vop, back_alpha_base_vop);
 FreeVop(original_back_alpha_vop);
 FreeVop(rec_back_alpha_vop);
 return;
}      
/***********************************************************CommentBegin******
 *
 * -- CodeBaseAlpha -- Base layer's shape coding for BackGroundComposition
 *
 ***********************************************************CommentEnd********/
Vop *  
CodeBaseAlpha(Vop       *alpha_vop,
       Int       vo_id,
       VolConfig *layer_config,
       Int	frame,
              BitCount  num_bits[MAX_NUM_VOS][MAX_NUM_VOLS],
       Int       shape,
       Image     *first_shape_code_bitstream,
              Image     *shape_bitstream,
         Int	*shape_width ,
       Int	*shape_height ,
       Int	*shape_hor_spat_ref ,
       Int	*shape_ver_spat_ref)
{
 Vop	*alpha_vop_bb;
 Vop     *rec_curr;
 Int	vop_has_content;

 if(shape == RECTANGULAR)
         SetConstantImage(GetVopA(alpha_vop),BINARY_ALPHA);
 else{
  if(shape == GREY_SCALE)
       PutVopBinaryShape(!BINARY,alpha_vop);
  else
       PutVopBinaryShape(BINARY, alpha_vop);
 }

        alpha_vop_bb = GetVopBounded(alpha_vop,1,1,&vop_has_content);
 rec_curr     = BaseAlphaProcess(alpha_vop_bb,
           layer_config,     
           vop_has_content,
           num_bits,
           first_shape_code_bitstream,
           shape_bitstream ,
           vo_id );
 if ( rec_curr == NULL ) {
  *shape_width        = 0;
  *shape_height       = 0;
  *shape_hor_spat_ref = 0;
  *shape_ver_spat_ref = 0;
  rec_curr            = CloneVop(alpha_vop);
  CopyVopNonImageField_TPS(alpha_vop,rec_curr);

 }
 else {
  *shape_width        = GetVopWidth( alpha_vop_bb );
  *shape_height       = GetVopHeight( alpha_vop_bb );
  *shape_hor_spat_ref = GetVopHorSpatRef( alpha_vop_bb );
  *shape_ver_spat_ref = GetVopVerSpatRef( alpha_vop_bb );	
 }
 FreeVop(alpha_vop_bb);
 return( rec_curr ); 
}
/***********************************************************CommentBegin******
 *
 * -- BaseAlphaProcess -- Base layer's shape coding for BackGroundComposition
 *
 ***********************************************************CommentEnd********/
Vop
*BaseAlphaProcess(Vop        *alpha_vop_bb,
    VolConfig  *vol_config,
    Int        vop_has_content,
    BitCount   num_bits[MAX_NUM_VOS][MAX_NUM_VOLS],
           Image      *first_shape_code_bitstream,
                  Image      *shape_bitstream ,
    Int	     vo_id )
{
 Vop *rec_curr = NULL;			
 Int alpha_th;

 if(vop_has_content){
    PutVopPredictionType(I_VOP, alpha_vop_bb);
  rec_curr = SetUpRecVop(alpha_vop_bb);
  alpha_th = GetVolConfigAlphaTh(vol_config);
         PutVopShape(BINARY_SHAPE_ONLY, alpha_vop_bb);
                PutVopChangeCRDisable(GetVolConfigChangeCRDisable(vol_config),
                alpha_vop_bb); PutVopShapeEffects(GetVolConfigShapeEffects(vol_config),
                alpha_vop_bb);
         PutVopErrorResDisable(GetVolConfigErrorResDisable(vol_config),alpha_vop_bb);
  BaseAlphaCode(alpha_vop_bb,
                rec_curr,
                (Vop *)NULL,
                alpha_th,
                num_bits,
                first_shape_code_bitstream,
                shape_bitstream ,
         vo_id );
   }
 return(rec_curr);
}
/***********************************************************CommentBegin******
 *
 * -- BaseAlphaCode -- Base layer's shape coding for BackGroundComposition
 *
 ***********************************************************CommentEnd*******/
Void BaseAlphaCode(Vop     *curr_base_alpha, 
           Vop      *rec_curr_base_alpha,  
           Vop      *rec_prev_alpha,
                  Int      alpha_th,
           BitCount num_bits[MAX_NUM_VOS][MAX_NUM_VOLS],
           Image    *first_shape_code_bitstream,
                  Image    *shape_bitstream ,
    Int	   vo_id )
{
 ImageF	        *mot_x=NULL, *mot_y=NULL;
 Image		*gray_shape_bitstream;
 Image		**Shape_stream, **First_stream;
 Image	        *MB_decisions=NULL, *alpha_decisions=NULL;
 Image		*GreyLevelAlpha=NULL;
 Image  		*MotionCompensatedGreyLevelAlpha=NULL;
 Image 	        *ReconstructedGreyLevelAlpha=NULL;
 Int		i, shape_bits;
 
 /* Initialise the integer level intermediate bitstreams */
 gray_shape_bitstream     = BitstreamInit();

 /* Allocate shape stream */
 First_stream = (Image **)calloc((GetVopWidth(curr_base_alpha)  / MB_SIZE)*
     (GetVopHeight(curr_base_alpha) / MB_SIZE), sizeof(Image *));
 Shape_stream = (Image **)calloc((GetVopWidth(curr_base_alpha)  / MB_SIZE)*
     (GetVopHeight(curr_base_alpha) / MB_SIZE), sizeof(Image *));

 for(i = 0; i<(GetVopWidth(curr_base_alpha) / MB_SIZE) * (GetVopHeight(curr_base_alpha) /
 MB_SIZE); i++){
  First_stream[i] = BitstreamInit();
  Shape_stream[i] = BitstreamInit();
 }

 if (GetVopShape(curr_base_alpha) == GREY_SCALE){
         GreyLevelAlpha = AllocImage(GetImageSizeX(curr_base_alpha->a_chan),
                GetImageSizeY(curr_base_alpha->a_chan),SHORT_TYPE);
                CopyImage(curr_base_alpha->a_chan,GreyLevelAlpha);
                ObtainSupport(curr_base_alpha->a_chan);
                ReconstructedGreyLevelAlpha =
                AllocImage(GetImageSizeX(curr_base_alpha->a_chan),
                      GetImageSizeY(curr_base_alpha->a_chan),SHORT_TYPE);
 }


 /* Decide what coding (INTRA/INTER) to perform on vop */
        if (GetVopPredictionType(curr_base_alpha) == I_VOP){

  if ((GetVopShape(curr_base_alpha) == BINARY) ||
      (GetVopShape(curr_base_alpha) == GREY_SCALE) ||
      (GetVopShape(curr_base_alpha) == BINARY_SHAPE_ONLY)){

   fprintf(stdout,"\t\tPerforming shape coding\n");

   /*ce_bits_for_shape[vol_id] = ce_bits_for_vop = ce_coded_frames[vol_id] = 0; */
                        shape_bits = VopShapeCode(curr_base_alpha,
         rec_curr_base_alpha,
         (Vop *)NULL,
         vo_id ,
         alpha_th,
         (Image *)NULL,
         (Image *)NULL,
         (Image *)NULL,
         (Image *)NULL,
         First_stream,
         Shape_stream);
  }
  else{	
   fprintf(stdout,"\t\tNo shape coding required\n");
   CopyImage(GetVopA(curr_base_alpha), GetVopA(rec_curr_base_alpha)); 
  }
  /* Put some text for user */
          fprintf(stdout,"\t\tCoding INTRA Shape\n\n");

                /* Base Alpha coding is separate mode  */
  if ((GetVopShape(curr_base_alpha) == BINARY) ||
  (GetVopShape(curr_base_alpha)==GREY_SCALE)){
         PutFirstCodes(First_stream, first_shape_code_bitstream,
         (GetVopWidth(curr_base_alpha)/MB_SIZE), (GetVopHeight(curr_base_alpha)/MB_SIZE));
         PutShapeCodes(Shape_stream, shape_bitstream,
         (GetVopWidth(curr_base_alpha)/MB_SIZE), (GetVopHeight(curr_base_alpha)/MB_SIZE));
         if (GetVopShape(curr_base_alpha) == GREY_SCALE)
     CodeGreyLevelAlpha(curr_base_alpha, GreyLevelAlpha,
          MotionCompensatedGreyLevelAlpha,
          ReconstructedGreyLevelAlpha,
          GetVopQuantizer(curr_base_alpha),
          MB_decisions, gray_shape_bitstream);
  }
  else if (GetVopShape(curr_base_alpha)==BINARY_SHAPE_ONLY) {
    VopCodeShapeTextIntraCom(curr_base_alpha, First_stream,
        Shape_stream, GreyLevelAlpha,
        MotionCompensatedGreyLevelAlpha,
        ReconstructedGreyLevelAlpha,
        rec_curr_base_alpha,
        first_shape_code_bitstream,
                       &num_bits[vo_id][curr_base_alpha->ident].text_bits,
                       0,
         vo_id, /* hjlee */
                       NULL);       /* will not use TM5 */
  }
 }
 else{/* P or B */
     if ((GetVopShape(curr_base_alpha) == BINARY) || (GetVopShape(curr_base_alpha) ==
     GREY_SCALE)){
  if (GetVopShape(curr_base_alpha) == GREY_SCALE)
       MotionCompensatedGreyLevelAlpha = AllocImage(GetImageSizeX(curr_base_alpha->a_chan),
                 GetImageSizeY(curr_base_alpha->a_chan),SHORT_TYPE);
  /* Put some text for user */
  fprintf(stdout,"\t\tPerforming INTER Shape Coding\n");
  /* Code shape */
  shape_bits = VopShapeCode(curr_base_alpha,
                     rec_curr_base_alpha,
                     rec_prev_alpha,
                     vo_id,
                     alpha_th,
                     mot_x,
                     mot_y,
                     MB_decisions,  /* to be changed for B-VOPs*/
                     alpha_decisions,
                     First_stream,
                     Shape_stream);
         subsamp_alpha((SInt*)GetImageData(GetVopA(rec_curr_base_alpha)),
         GetVopWidth(rec_curr_base_alpha), GetVopHeight(rec_curr_base_alpha),
         1, (SInt*)GetImageData(alpha_decisions));
              if (GetVopShape(curr_base_alpha) == GREY_SCALE)
  ImageMotionCompensate(rec_prev_alpha->a_chan, mot_x, mot_y, MB_decisions,alpha_decisions,
          MotionCompensatedGreyLevelAlpha);
     }
     /* Base Alpha coding is separate mode  */
     if ((GetVopShape(curr_base_alpha) == BINARY) ||
     (GetVopShape(curr_base_alpha)==GREY_SCALE)){
      PutFirstCodes(First_stream, first_shape_code_bitstream,
      (GetVopWidth(curr_base_alpha)/MB_SIZE),(GetVopHeight(curr_base_alpha)/MB_SIZE));
      PutShapeCodes(Shape_stream, shape_bitstream,
      (GetVopWidth(curr_base_alpha)/MB_SIZE),(GetVopHeight(curr_base_alpha)/MB_SIZE));
     }
     if (GetVopShape(curr_base_alpha) == GREY_SCALE)
    CodeGreyLevelAlpha(curr_base_alpha,GreyLevelAlpha,
         MotionCompensatedGreyLevelAlpha,
         ReconstructedGreyLevelAlpha,
         GetVopGLQuantizer(curr_base_alpha),				/* correction JDL 21-APR-97 */
         MB_decisions,
         gray_shape_bitstream);
            FreeImage(MB_decisions);
     FreeImage(alpha_decisions);
     if (GetVopShape(curr_base_alpha) == GREY_SCALE)
       FreeImage(MotionCompensatedGreyLevelAlpha);
 }/* Shape P Frame */

 if (GetVopShape(curr_base_alpha) == GREY_SCALE){
   FreeImage(GreyLevelAlpha);
   CopyReconstructedGreyLevelAlphaToVop(ReconstructedGreyLevelAlpha,
       rec_curr_base_alpha->a_chan);
   FreeImage(ReconstructedGreyLevelAlpha);
  }


 BitstreamFree(gray_shape_bitstream);

 for(i=0; i<(GetVopWidth(curr_base_alpha)/MB_SIZE)*(GetVopHeight(curr_base_alpha)/MB_SIZE);
 i++){
  BitstreamFree(First_stream[i]);
  BitstreamFree(Shape_stream[i]);
 }
 free(First_stream);
 free(Shape_stream);

} 

/***********************************************************CommentBegin******
 *
 * -- WriteCodedAlphaToDisk -- 
 *
 ***********************************************************CommentEnd********/
Void
WriteCodedAlphaToDisk(Vop *vop,
                      Char *a_file,
                      Int time,
                      Int disk_vop_width,
                      Int disk_vop_height,
                      Int shape,
        Int vop_has_content)
{
      Vop   *disk_vop;
      Image *y_in,
            *a_in,        *a_out;
      Int   x,            y,
            hor_ref,      ver_ref,
            dim_x,        dim_y,
            pel_in,       pel_out,
            alpha_active=0;
      SInt *ptr_in_2,     *ptr_out_2;

      /* SInt *ptr_alp;*/

    disk_vop = AllocVop(disk_vop_width,disk_vop_height);

    if(vop_has_content){
     y_in      = GetVopY(vop);
 dim_x     = GetImageSizeX(y_in);
     dim_y     = GetImageSizeY(y_in);
     hor_ref   = GetVopHorSpatRef(vop);
     ver_ref   = GetVopVerSpatRef(vop);
 a_in      = GetVopA(vop);
     a_out     = GetVopA(disk_vop);
 ptr_in_2  = (SInt *)GetImageData(a_in);
     ptr_out_2 = (SInt *)GetImageData(a_out);
 pel_in    = 0;
 for(y=ver_ref;y<ver_ref + dim_y; y++){
            for(x=hor_ref;x<hor_ref + dim_x; x++){
                if(ValidCoordinate(x,y,disk_vop_width,disk_vop_height)){
                     if(ptr_in_2[pel_in]){
                         pel_out = y * disk_vop_width + x;
                         ptr_out_2[pel_out] = ptr_in_2[pel_in];
                     }
  }
                pel_in++; 
     }
        }
 if(shape == RECTANGULAR) alpha_active = FALSE;
     else                     alpha_active = TRUE;	
    }
    if(time == 0)
        WriteAlpha(disk_vop,   a_file,        time,
     IO_FORMAT,  IO_OVERWRITE,  alpha_active);
    else
        WriteAlpha(disk_vop,   a_file,        time,
     IO_FORMAT,  IO_OVERWRITE,  alpha_active);
    FreeVop(disk_vop);
    return;
}
/***********************************************************CommentBegin******
 *
 * -- GetVolConfigFrameNoInc -- 
 *
 ***********************************************************CommentEnd********/
Int
GetVolConfigFrameNoInc( VolConfig *cfg )
{
 return( cfg -> frame );
}

/***********************************************************CommentBegin******
 *
 * -- WriteBGCAlphaBitstream -- 
 *
 ***********************************************************CommentEnd********/
Void
WriteBGCAlphaBitstream(Vop *curr,
         Int vo_id,
                Int vol_id,
         BitCount num_bits[MAX_NUM_VOS][MAX_NUM_VOLS],
                Int back_base_exist)    
{
      Int             back_first_bits = 0, back_shape_bits = 0, back_total_bits = 0,
               for_first_bits  = 0, for_shape_bits  = 0, for_total_bits  = 0,
                      syntax_bits     = 0;

    if ( back_base_exist == 1 )
       PutVopLoadBackShape( 0 , curr );
    if ( GetVopEnhanceType( curr ) ) {
       PutBits(1, GetVopLoadBackShape(curr), vo_id, vol_id);
       syntax_bits += 1;		      
       if ( GetVopLoadBackShape( curr ) ) {
        PutBits(13, back_shape_width,          vo_id, vol_id);
        PutBits(13, back_shape_height,         vo_id, vol_id);
        PutBits(13, back_shape_hor_spat_ref,   vo_id, vol_id);
        PutBits(1,  1,                         vo_id, vol_id );
        PutBits(13, back_shape_ver_spat_ref,   vo_id, vol_id);
        syntax_bits += 41;
        back_first_bits = BitstreamPut(back_first_shape_code_bitstream,vo_id, vol_id); 
        back_shape_bits = BitstreamPut(back_shape_bitstream,vo_id, vol_id);
        PutBits(1, GetVopLoadForShape(curr), vo_id, vol_id);
        syntax_bits += 1;
        BitstreamFree(back_first_shape_code_bitstream);
        BitstreamFree(back_shape_bitstream);

        if ( GetVopLoadForShape( curr ) ) {
         PutBits(13, for_shape_width,        vo_id, vol_id);
         PutBits(13, for_shape_height,       vo_id, vol_id);
         PutBits(13, for_shape_hor_spat_ref, vo_id, vol_id);
         PutBits(1,  1,                      vo_id, vol_id);
         PutBits(13,  for_shape_ver_spat_ref, vo_id, vol_id);
         syntax_bits += 41;
         for_first_bits = BitstreamPut(for_first_shape_code_bitstream,vo_id, vol_id); 
         for_shape_bits = BitstreamPut(for_shape_bitstream,vo_id, vol_id);
         BitstreamFree(for_first_shape_code_bitstream);
         BitstreamFree(for_shape_bitstream);
        }
       }
      }
      PutBits(2 , GetVopRefSelCode(curr), vo_id, vol_id);
      syntax_bits += 2;		      

      for_total_bits  = for_first_bits  + for_shape_bits;
      back_total_bits = back_first_bits + back_shape_bits;
#ifndef NLSSTATS       		      	      
      if(for_total_bits != 0){
     PrintVolTimeEndStatShape(for_shape_bits,  vo_id, vol_id, DISPLAY,    4, num_bits);
            PrintVolTimeEndStatShape(for_shape_bits,  vo_id, vol_id, STATS_FILE, 4,
            num_bits); PrintVolTimeEndStatShape(for_first_bits,  vo_id, vol_id, DISPLAY,   
            0, num_bits); PrintVolTimeEndStatShape(for_first_bits,  vo_id, vol_id,
            STATS_FILE, 0, num_bits); PrintVolTimeEndStatShape(for_shape_bits,  vo_id,
            vol_id, DISPLAY,    1, num_bits); PrintVolTimeEndStatShape(for_shape_bits, 
            vo_id, vol_id, STATS_FILE, 1, num_bits);
            PrintVolTimeEndStatShape(for_shape_bits,  vo_id, vol_id, DISPLAY,    4,
            num_bits); PrintVolTimeEndStatShape(for_shape_bits,  vo_id, vol_id, STATS_FILE,
            4, num_bits);
      }
      if(back_total_bits != 0){
     if(for_total_bits == 0){
           PrintVolTimeEndStatShape(for_shape_bits,  vo_id, vol_id, DISPLAY,    4,
           num_bits);
                  PrintVolTimeEndStatShape(for_shape_bits,  vo_id, vol_id, STATS_FILE, 4,
                  num_bits);
            }
     PrintVolTimeEndStatShape(back_first_bits, vo_id, vol_id, DISPLAY,    2, num_bits);
            PrintVolTimeEndStatShape(back_first_bits, vo_id, vol_id, STATS_FILE, 2,
            num_bits); PrintVolTimeEndStatShape(back_shape_bits, vo_id, vol_id, DISPLAY,   
            3, num_bits); PrintVolTimeEndStatShape(back_shape_bits, vo_id, vol_id,
            STATS_FILE, 3, num_bits); PrintVolTimeEndStatShape(for_shape_bits,  vo_id,
            vol_id, DISPLAY,    4, num_bits); PrintVolTimeEndStatShape(for_shape_bits, 
            vo_id, vol_id, STATS_FILE, 4, num_bits);
      }
#endif


      num_bits[vo_id][ vol_id ].syntax += syntax_bits;
      num_bits[vo_id][vol_id].shape    += back_total_bits;
      num_bits[vo_id][vol_id].shape    += for_total_bits;

} 
/***********************************************************CommentBegin******
 *
 * -- UpdateVolConfigNextCodingTimeEnhancement -- 
 *
 ***********************************************************CommentEnd********/
Float
UpdateVolConfigNextCodingTimeEnhancement(VOConfig *vo_config,
      Int vol_id,
      Int temporal_scalability)
{
  Int       ref_vol_id;
  Float     next_coding_time;
  VolConfig *ref_vol_config;
  VolConfig *enhancement_layer_config;
  Int       frame, ref_frame;
  Int       ref_skip;
  Int       enh_start;

  enhancement_layer_config = GetVolConfigById(GetVOConfigLayers(vo_config), vol_id);
  next_coding_time = GetVolConfigNextCodingTime(enhancement_layer_config);
  ref_vol_id       = GetVolConfigRefId(enhancement_layer_config);
  ref_vol_config   = GetVolConfigById(GetVOConfigLayers(vo_config), ref_vol_id);
  frame            = GetVolConfigFrameNoInc(enhancement_layer_config);
  ref_frame        = GetVolConfigFrameNoInc(ref_vol_config);
  ref_skip         = GetVolConfigFrameSkip(ref_vol_config);
  enh_start        = GetVolConfigStartFrame(enhancement_layer_config);

  if(temporal_scalability != 3)
      ref_frame -= GetVolConfigM(ref_vol_config) * ref_skip;

  if(frame == 0 || frame == enh_start || ref_frame == frame || ref_frame - ref_skip ==
  frame){
      frame = GetVolConfigFrame(enhancement_layer_config);
      next_coding_time += GetVolConfigTimeInc(enhancement_layer_config);
      PutVolConfigNextCodingTime((Float)next_coding_time, enhancement_layer_config);
  }
  return(next_coding_time);  
}
/***********************************************************CommentBegin******
 *
 * -- CheckScalability
 *
 ***********************************************************CommentEnd********/
Int CheckScalability(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol;
  Int           scalability_flag;

  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)
             return(scalability_flag);
       curr_vol = GetVolConfigNext(curr_vol);
 }
 curr_vo = GetVOConfigNext(curr_vo);
  }
  return(0);
}

/***********************************************************CommentBegin******
 *
 * -- CheckEnhancementType
 *
 ***********************************************************CommentEnd********/
Int CheckEnhancementType(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol;
  Int           scalability_flag;
  Int           enhancement_flag;

  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){
        enhancement_flag = GetVolConfigEnhanceType(curr_vol);
	if(GetVolConfigEnhanceType(curr_vol)==2)
          PutVolConfigEnhanceType(1, curr_vol);
        return(enhancement_flag);
      }
      curr_vol = GetVolConfigNext(curr_vol);
    }
    curr_vo = GetVOConfigNext(curr_vo);
  }
  return(-1);
}
/***********************************************************CommentBegin******
 *
 * -- CheckScalType
 *
 ***********************************************************CommentEnd********/
Int CheckScalType(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol;
  Int           scalability_flag;
  Int           scal_type_flag=-1;

  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)
 scal_type_flag = ((scal_type_flag > GetVolConfigScalType(curr_vol))?
      scal_type_flag : GetVolConfigScalType(curr_vol));

      curr_vol = GetVolConfigNext(curr_vol);
    }
    curr_vo = GetVOConfigNext(curr_vo);
  }
  return(scal_type_flag);
}

/***********************************************************CommentBegin******
 *
 * -- CalcEnhancementTime
 *
 ***********************************************************CommentEnd********/
Float CalcEnhancementTime(Float time_instant,VolConfig *vol_config, Int vol_id)
{
  Float new_time;

  new_time = time_instant;
  new_time -= GetVolConfigTimeInc(GetVolConfigById(vol_config,vol_id));
  return(new_time);

}

/***********************************************************CommentBegin******
 *
 * -- GetScalabilityVolId
 *
 ***********************************************************CommentEnd********/
Int GetScalabilityVolId(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol;
  Int           scalability_flag;

  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)
        return(GetVolConfigId(curr_vol));
      curr_vol = GetVolConfigNext(curr_vol);
    }
    curr_vo = GetVOConfigNext(curr_vo);
  }
  fprintf(stderr,"Error\n");
  exit(-1);
}


/***********************************************************CommentBegin******
 *
 * -- DoPrintVolTimeEndStatShape
 *
 ***********************************************************CommentEnd********/

Void
DoPrintVolTimeEndStatShape(Int shape_bits, FILE *file, Int shape_type)
{

 if(shape_type == 0)
       fprintf(file,"\t#Bits shape_header (for)  : %d\n",(int)shape_bits);
 else if(shape_type == 1)
       fprintf(file,"\t#Bits shape        (for)  : %d\n",(int)shape_bits);
 else if(shape_type == 2)
       fprintf(file,"\t#Bits shape_header (back) : %d\n",(int)shape_bits);
 else if(shape_type == 3)
       fprintf(file,"\t#Bits shape        (back) : %d\n",(int)shape_bits);
 else if(shape_type == 4)
       fprintf(file,"\t==================================\n");

 return;
}

/***********************************************************CommentBegin******
 *
 * -- PrintVolTimeEndStatShape
 *
 ***********************************************************CommentEnd********/
Void
PrintVolTimeEndStatShape(Int shape_bits, Int vo_id, Int vol_id,
    Int mode,       Int shape_type, BitCount num_bits[MAX_NUM_VOS][MAX_NUM_VOLS])
{
 FILE *file;

 if(mode == DISPLAY)
  DoPrintVolTimeEndStatShape(shape_bits, stdout, shape_type);
 else
 {
  if((file = fopen(num_bits[vo_id][vol_id].stats_file,"a")) == NULL)
  {
   fprintf(stdout,"ERROR(PrintTimeEndStat) : could not open stats file\n");
   exit(1);
  }
  DoPrintVolTimeEndStatShape(shape_bits, file, shape_type);
  fclose(file);
 }

 return;
}

/***********************************************************CommentBegin******
 *
 * -- SkipVop -- 
 *
 ***********************************************************CommentEnd********/
Int
SkipVop( Vol *vol, VOConfig	*vo_config, Int temporal_scalability)
{
      VolConfig	*vol_config;
      VolConfig	*ref_vol_config;
      Int		frame;
      Int		ref_frame;

      if (GetVolScalability(vol)) {
   vol_config     = GetVolConfigById( GetVOConfigLayers( vo_config ) , GetVolId( vol ));
   frame          = GetVolConfigFrameBack( vol_config );
   ref_vol_config = GetVolConfigById( GetVOConfigLayers( vo_config ) , GetVolRefId( vol ));
   ref_frame      = GetVolConfigFrameBack( ref_vol_config );

   if(temporal_scalability != 3)
         ref_frame -= GetVolConfigFrameSkip(ref_vol_config);
          if( frame == ref_frame )
                return( 1 );
   else
         return( 0 );
      }
      else
   return( 0 );
}
/***********************************************************CommentBegin******
 *
 * -- CloneVopTPS
 *
 ***********************************************************CommentEnd********/
Vop *
CloneVopTPS(Vop *vop_in)
{
  Int		x,y;

  Image	*image_data;

  Vop		*vop_out;

  image_data = GetVopA(vop_in);
  x = GetImageSizeX(image_data);
  y = GetImageSizeY(image_data);

  vop_out = AllocVop(x,y);

  CopyVop(vop_in,vop_out);

  return(vop_out);
}


/***********************************************************CommentBegin******
 *
 * -- MBtype_type1
 *
 ***********************************************************CommentEnd********/
/*** 4/19 changed by SHARP */
Void
MBtype_type1(Vop *vop)
{
  int	j, i, x, y;
  SInt *shape_mode;
  
  x          = GetImageSizeX(GetVopShapeMode(vop));
  y          = GetImageSizeY(GetVopShapeMode(vop));
  shape_mode = (SInt *)GetImageData(GetVopShapeMode(vop));
  
  for ( j = 0 ; j < y; j++ )
    for ( i = 0 ; i < x; i++ )
      shape_mode[i + j * x] = 3;
}
/* 4/19 changed by SHARP ***/

/***********************************************************CommentBegin******
 *
 * -- NotUpdateVolStore
 *
 ***********************************************************CommentEnd********/

Void
NotUpdateVolStore(Vop *update_vop,Int layer_id,Vol *vol_store)
{
  Vol *replace_vol = NULL;
  Vop *replace_vop = NULL;

  replace_vol = GetVolById(vol_store, layer_id);
  replace_vop = GetVolVop(replace_vol);

  if(replace_vop != NULL){
      FreeVop(replace_vop);
      PutVolVop(NULL, replace_vol);
  }
  return;
}

/***********************************************************CommentBegin******
 *
 * -- DecideEnhanceEncodingMode
 *
 ***********************************************************CommentEnd********/
Void
DecideEnhanceEncodingMode(Int curr_frame,
     Int for_base_frame,
     Int back_base_frame,
     Int curr_skip,
     Int base_skip,
     Int base_end,
     Int *ref_mode,
                   Int *last_enhancement_mode,
                   Int *back_base_exist,
     Int *need_for_back_shape,
     Int temporal_scalability,
     Int finish_base)

{
  /* if use I_VOP or P_VOP or B_VOP_TYPE1 : TPS */
  if(temporal_scalability == 3 || finish_base != FINISHED){
      if ( (( curr_frame - curr_skip - for_base_frame )% base_skip) == 0 )
          *ref_mode    = 1;
      else
   *ref_mode    = 0;
      if(curr_frame + curr_skip == back_base_frame)
          *last_enhancement_mode = 1;
      if ( back_base_frame > base_end)
   *back_base_exist = 1;
      else
   *back_base_exist = 0;  
  }
  /* if use P_VOP in B_VOP_TYPE1 : TPS */
  else{
      if ( (( curr_frame - curr_skip - for_base_frame )% base_skip) == 0 )
          *ref_mode    = 1;
      else
   *ref_mode    = 0;
      if(curr_frame + curr_skip > base_end)
          *last_enhancement_mode = 1;
      *back_base_exist = 1;/* back_base not exist */
  }
  if(*ref_mode)
      *need_for_back_shape = 0;
  return;
}
/***********************************************************CommentBegin******
 *
 * -- SetRefVopForEnhance
 *
 ***********************************************************CommentEnd********/
Vop
*SetRefVopForEnhance_TPS(Int ref_mode, Vol *vol, Int enhance_type, Int shape)

{
  Vop *vop = NULL;

  if(ref_mode){
      if(GetVolVop(vol) != NULL){
   vop  = CloneVop_TMP(GetVolVop(vol));
   CopyVopNonImageField_TPS(GetVolVop(vol),vop);
   if(enhance_type){/* type 1 */
       SetConstantImage(GetVopA(vop),BINARY_ALPHA);
       PutVopShape(1, vop);
   }
   else/* type 2 */
       PutVopShape(shape, vop);
   VopPadding(vop);
      }
  }
  else if(GetVolVop(vol) != NULL)/* E -> E */
      vop  = GetVolVop(vol);

  return(vop);
}
/***********************************************************CommentBegin******
 *
 * -- SetRefVopForEnhance_B_TPS
 *
 ***********************************************************CommentEnd********/
Vop
*SetRefVopForEnhance_B_TPS(Vol *vol, Vop *base_vop,
      Int enhance_type,
      Int shape,
      Int finish_base,
      Int mode)

{
  Vop *vop = NULL;

  if(mode != 2){
    if(mode == 1 && base_vop != NULL){
      vop  = CloneVop(base_vop);
      CopyVopNonImageField_TPS(base_vop,vop);
    }

    else if(GetVolVop(vol) != NULL){
      vop  = CloneVop_TMP(GetVolVop(vol));
      CopyVopNonImageField_TPS(GetVolVop(vol),vop);
    }
    if(vop != NULL){
      /* type 1 */
      if(enhance_type == 1){
          SetConstantImage(GetVopA(vop),BINARY_ALPHA);	
          PutVopShape(1, vop);
      }
      /* type 2 */
      else
          PutVopShape(shape, vop);
      VopPadding(vop);
    }
  }
  else
    vop = GetVolVop(vol);
  return(vop);
}
/***********************************************************CommentBegin******
 *
 * -- GetNextCodedVO_TPS
 *
 ***********************************************************CommentEnd********/
Float
GetNextCodedVO_TPS(VOConfig *list,
                        Int *vo_id,
                        Int *vol_id,
                        Int *finish,
          Int *finish_base,
          Int *finish_enhance,
          Int temporal_scalability)
{
  VOConfig  *curr_vo;
  VolConfig *curr_vol_config,
            *base_config,
            *enh_config;
  Float     next_coding_time,
            time_to_end,
            end_time,
            min_time     = 0,
            max_end_time = -1;
  Int       first_pass   =  1;
  Int       skipchecktime = 0;

  Int       ref_vol_id;
  Int       base_frame;
  Int       base_skip;
  Int       base_start;
  Int       base_end;
  Int       enh_frame;
  Int       enh_skip;
  Int       enh_start;
  Int       enh_end;
  curr_vo   = list;

  while( curr_vo != NULL ){
      curr_vol_config = GetVOConfigLayers(curr_vo);
      while(curr_vol_config != NULL){

   if(*finish_base == FINISHED    && !GetVolConfigScalability( curr_vol_config ))
       skipchecktime = 1;
   if(*finish_enhance == FINISHED &&  GetVolConfigScalability( curr_vol_config ))
       skipchecktime = 1;
   /* if use B_VOP_TYPE1 P_VOP in B_VOP_TYPE1 or B_VOP_TYPE2 :TPS */
          if(!skipchecktime && temporal_scalability != 3 && GetVolConfigScalability(
          curr_vol_config )){
       /* enhance */
       enh_config       = curr_vol_config;
       ref_vol_id       = GetVolConfigRefId(enh_config);
              base_config      = GetVolConfigById(GetVOConfigLayers(curr_vo), ref_vol_id);

       base_frame       = GetVolConfigFrameBack(base_config); 
       enh_frame        = GetVolConfigFrameBack(enh_config);  

       base_skip        = GetVolConfigFrameSkip(base_config);
       base_start       = GetVolConfigStartFrame(base_config);
       base_end         = GetVolConfigEndFrame(base_config);
       enh_skip         = GetVolConfigFrameSkip(enh_config);
       enh_start        = GetVolConfigStartFrame(enh_config);
       enh_end          = GetVolConfigEndFrame(enh_config);

       if(enh_frame  < enh_start)  enh_frame  = enh_start;
       if(base_frame < base_start) base_frame = base_start;

       /* Enhance vop is skipped to encode next Base vop */
              if(enh_frame == base_frame ||
   (base_frame + base_skip <= base_end && enh_frame >= base_frame))
    skipchecktime = 1;

       if(*finish_base != FINISHED && enh_frame >= base_frame &&
   base_frame + base_skip > base_end){
   fprintf(stderr,"<<< base FINISHED >>>\n");
   *finish_base = FINISHED;
       }


       if(*finish_enhance != FINISHED && enh_frame + enh_skip > enh_end){
   fprintf(stderr,"<<< enhance FINISHED >>>\n");
   *finish_enhance = FINISHED;
       }
   }
   if(!skipchecktime){
              next_coding_time = GetVolConfigNextCodingTime(curr_vol_config);
              end_time = GetVolConfigEndTime(curr_vol_config);
              if (first_pass){
                  *vo_id = GetVOConfigId(curr_vo);         
                  *vol_id = GetVolConfigId(curr_vol_config);      
                  min_time = next_coding_time;
                  if(next_coding_time <= end_time)
                      first_pass = 0;
              }
              if(max_end_time < end_time)
                  max_end_time = end_time;
              if(next_coding_time < min_time){
                  if(next_coding_time <= end_time){
                      *vo_id = GetVOConfigId(curr_vo);
                      *vol_id = GetVolConfigId(curr_vol_config);
                      min_time = next_coding_time;
                  }
                  else{
                      time_to_end = next_coding_time - end_time;
                      if(time_to_end < 0.001){
                          *vo_id = GetVOConfigId(curr_vo);
                          *vol_id = GetVolConfigId(curr_vol_config);
                          min_time = next_coding_time;
                      }
                  }
              }
 }/* skipchecktime end */
  skipchecktime = 0;
        curr_vol_config = GetVolConfigNext(curr_vol_config);
      }
      curr_vo = GetVOConfigNext(curr_vo);
  }

  if(*vol_id == CheckScalabilityVolId(list))
      min_time = UpdateVolConfigNextCodingTimeEnhancement(list, *vol_id,
      temporal_scalability);

  /* finish */
  if(!(*finish_base == FINISHED && *finish_enhance== FINISHED) &&
     min_time > max_end_time)
      FinishCheck(list, &(*vol_id), &(*finish_base), &(*finish_enhance), &min_time);

  if(*finish_base == FINISHED && *finish_enhance == FINISHED)
      *finish = FINISHED;
  else 
      *finish = 0;

  return(min_time);
}

/***********************************************************CommentBegin******
 *
 * -- CheckScalabilityVolId
 *
 ***********************************************************CommentEnd********/
Int
CheckScalabilityVolId(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol_config;
  Int           scalability_flag;
  Int           vol_id = -1;

  curr_vo = vo_config;

  while(curr_vo != NULL){
 curr_vol_config = GetVOConfigLayers(curr_vo);
 while(curr_vol_config != NULL){
       scalability_flag = GetVolConfigScalability(curr_vol_config);
       if (scalability_flag == 1){
      vol_id = GetVolConfigId(curr_vol_config);
             return(vol_id);
       }
       curr_vol_config = GetVolConfigNext(curr_vol_config);
 }
 curr_vo = GetVOConfigNext(curr_vo);
  }
  return(vol_id);
}

/***********************************************************CommentBegin******
 *
 * -- FinishCheck
 *
 ***********************************************************CommentEnd********/
Void
FinishCheck(VOConfig *vo_config,
     Int *vol_id,
     Int *finish_base,
     Int *finish_enhance,
     Float *min_time)
{
  VolConfig *base_config,
            *enh_config;
  Int end_time;

      if(!GetVolConfigScalability(GetVolConfigById(GetVOConfigLayers(vo_config),
      *vol_id))){/* Base */
          if(*finish_base != FINISHED){
       *finish_base = FINISHED;
       fprintf(stderr,"<<< base FINISHED >>>\n");
   }
   if(*finish_enhance != FINISHED){
       base_config      = GetVolConfigById(GetVOConfigLayers(vo_config), *vol_id);
       *vol_id          = CheckScalabilityVolId(vo_config);
       enh_config       = GetVolConfigById(GetVOConfigLayers(vo_config), *vol_id);
              *min_time         = GetVolConfigNextCodingTime(enh_config);
              end_time         = GetVolConfigEndTime(enh_config);
              if(*min_time > end_time)
                  *finish_base = FINISHED;
   }
      }
      else{/* Enh */
   if(*finish_enhance != FINISHED){
       *finish_enhance = FINISHED;
       fprintf(stderr,"<<< enh  FINISHED >>>\n");
   }
   if(*finish_base != FINISHED){
       enh_config       = GetVolConfigById(GetVOConfigLayers(vo_config), *vol_id);
       *vol_id          = GetVolConfigRefId(enh_config);
              base_config      = GetVolConfigById(GetVOConfigLayers(vo_config), *vol_id);
              *min_time        = GetVolConfigNextCodingTime(base_config); end_time         =
              GetVolConfigEndTime(base_config); if(*min_time > end_time)
                  *finish_base = FINISHED;
   }
 }
}

/***********************************************************CommentBegin******
 *
 * -- SetCurrVop_TPS
 *
 ***********************************************************CommentEnd********/
Void
SetCurrVop_TPS(VolConfig *layer_config,
       Vol *enhancement_layer,
       Vop *curr_vop_bb,
       Vop *rec_vop,
       Vop *next_rec_vop,
       Int vo_id,
       Int vol_id,
       Int ref_vol_id,
       Int ref_mode,
       Int for_shape_exist,
       Int first_flag,
       Int bgc_mode,
       Int vop_has_content,
       Int temporal_scalability,
       Int finish_base,
       Int *need_for_back_shape)
{
  /*** put LoadForShape, LoadBackShape flag and PRE_MB_TYPE ***/
  if (*need_for_back_shape == 1) {
      *need_for_back_shape = 2;
      if (for_shape_exist == 1)
          PutVopLoadForShape( 1 , curr_vop_bb );
      else 
          PutVopLoadForShape( 0 , curr_vop_bb );
      PutVopLoadBackShape(    1 , curr_vop_bb );

/*** 4/19 changed by SHARP */
      /* ref_vop is Base vop */
      if(ref_mode == 1 && GetVolEnhanceType(enhancement_layer)){
	if(temporal_scalability != 2){
	  MBtype_type1(rec_vop);
	  if(temporal_scalability == 1)
	    MBtype_type1(next_rec_vop);
	}
	else{
	  MBtype_type1(next_rec_vop);
	}
      }
  }
  else{
      /* if use B_VOP or I_VOP or P_VOP(ref_mode): TPS */
      if(GetVolEnhanceType(enhancement_layer) &&
         (ref_mode || (temporal_scalability == 1 &&finish_base !=FINISHED)) ){
	   if(temporal_scalability != 2){
  	     MBtype_type1(rec_vop);
	     if(temporal_scalability == 1)
	       MBtype_type1(next_rec_vop);
	   }
	   else
	     MBtype_type1(next_rec_vop);
      }
/* 4/19 changed by SHARP ***/
      
      PutVopLoadForShape(   0 , curr_vop_bb );
      PutVopLoadBackShape(  0 , curr_vop_bb );
  }

  /***************************************
   <<<   temporal_scalability usage   >>>
   ***************************************
    temporal_scalability = 1  : B_TYPE(1)
    temporal_scalability = 2  : B_TYPE(2)
    temporal_scalability = 3  : ONLY I or P
    temporal_scalability = 4  : B_TYPE(1) -> P_VOP

    prediction_type = P_VOP(temporal_scalability = 3 )
       temporal_scalability = 3,4 -> RefSelCode = 0 : forward (from E frame)
                              RefSelCode = 1 : forward (from B frame) 
                              RefSelCode = 2 : backward(from E frame)
    prediction_type = B_VOP
       temporal_scalability = 1 -> RefSelCode = 3 : B_TYPE(1)
       temporal_scalability = 2 -> RefSelCode = 1 : B_TYPE(2)
       temporal_scalability = 5 -> RefSelCode = 2 : B_TYPE(3)
  **********************************************************************/

  /*** Put  RefSelCode ***/
  /* if use I_VOP or P_VOP or P_VOP in B_VOP_TYPE1: TPS */
  if (temporal_scalability == 3 ||
      temporal_scalability == 4||
      temporal_scalability == 5){
      if(ref_mode)
   PutVopRefSelCode( 1 , curr_vop_bb );
      else
   PutVopRefSelCode( 0 , curr_vop_bb );
  }
  /* if use B_VOP_TYPE1 or B_VOP_TYPE2: TPS */

  else{
      if (temporal_scalability == 1)
          PutVopRefSelCode( 3 , curr_vop_bb );
      else if(temporal_scalability == 2)
   PutVopRefSelCode( 1 , curr_vop_bb );
  }

  /*** put BackComp Flag ***/
  if( bgc_mode ) PutVopBackComp( 1 , curr_vop_bb );
  else           PutVopBackComp( 0 , curr_vop_bb );

  /*** put EnhanceType Flag ***/
  PutVopEnhanceType( GetVolConfigEnhanceType( layer_config ) , curr_vop_bb );

  /*** put Scalability Flag ***/
  PutVopScalability( 1 , curr_vop_bb );

 return;

}
/***********************************************************CommentBegin******
 *
 * -- SetRefVop_TPS
 *
 ***********************************************************CommentEnd********/
Void
SetRefVop_TPS(VOConfig  *vo_config,
       VolConfig *layer_config,
       VolConfig *ref_layer_config,
       VO  *next_vo,
       VO  *next_rec_vo,
       VO  *prev_vo,
       VO  *rec_vo,
       Vol **next_vol_store,
       Vol **next_rec_vol_store,
       Vop **next_vop,
       Vop **next_rec_vop,
       Vol **prev_vol,
       Vol **rec_vol,
       Vop **rec_vop,
       Vop **prev_vop,
       Vop **for_alpha_base_vop,
       Vop **back_alpha_base_vop,
       Vop *original_prev_base_vop,
       Vop *base_vop_not_padding_for_bgc,
       Int vo_id,
       Int ref_vol_id,
       Int vol_id,
       Int frame,
       Int *for_base_frame,
       Int *back_base_frame,
       Int *ref_mode,
       Int *need_for_back_shape,
       Int *back_base_exist,
       Int *last_enhancement_mode,
       Int temporal_scalability,
       Int finish_base)
{
  Vop *prev_vop_TPS_B = NULL;
  Int mode = -1;


  /* if use I_VOP or P_VOP : TPS */
  /******************** temporal_scalability == 3 (for I or P picture) ********************/

  if(temporal_scalability == 3){
     *for_base_frame      = GetVolConfigFrameBack(  ref_layer_config );
     *back_base_frame     = GetVolConfigFrameNoInc( ref_layer_config );
     *for_alpha_base_vop  = GetVopPrevTemp(base_vop_not_padding_for_bgc);
     *back_alpha_base_vop = GetVopNextTemp(base_vop_not_padding_for_bgc);
     DecideEnhanceEncodingMode(frame,  *for_base_frame,  *back_base_frame,
                               GetVolConfigFrameSkip( layer_config ),
                               GetVolConfigFrameSkip( ref_layer_config ),
                               GetVolConfigEndFrame(  ref_layer_config ),
                               &*ref_mode, &*last_enhancement_mode,
                               &*back_base_exist,
                               &*need_for_back_shape,
                               temporal_scalability,
                               finish_base);
     if( *ref_mode ){
       *prev_vol       = GetVolById(GetVOLayers(next_vo),     ref_vol_id);
       *rec_vol        = GetVolById(GetVOLayers(next_rec_vo), ref_vol_id);
     }
     else{
       *prev_vol       = GetVolById(GetVOLayers(prev_vo),     vol_id);
       *rec_vol        = GetVolById(GetVOLayers(rec_vo),      vol_id);
     }

     *next_vol_store     = GetVolById(GetVOLayers(next_vo),     vol_id);
     *next_rec_vol_store = GetVolById(GetVOLayers(next_rec_vo), vol_id);

     *rec_vop            = SetRefVopForEnhance_TPS(*ref_mode, *rec_vol,
            GetVolConfigEnhanceType(layer_config),
            GetVolConfigShape(ref_layer_config));
     *prev_vop           = SetRefVopForEnhance_TPS(*ref_mode, *prev_vol,
            GetVolConfigEnhanceType(layer_config),
            GetVolConfigShape(ref_layer_config));
     *next_vop          = GetVolVop(*next_vol_store);
     *next_rec_vop      = GetVolVop(*next_rec_vol_store);

  }
  /******************** temporal_scalability == 3 (for I or P picture) end
  ********************/

  /******************** temporal_scalability == 1 for B picture
                 temporal_scalability == 2 for B picture
                 temporal_scalability == 4 for P picture
                 temporal_scalability == 5 for P picture ********************/

  else if(temporal_scalability == 1 ||
   temporal_scalability == 2 ||
   temporal_scalability == 4 ||
   temporal_scalability == 5){

    /****************** I_TYPE or P_TYPE or B_TYPE(1) : TPS ******************/
    if(temporal_scalability != 2){
      /* B -> E -> E-> B */
      if(finish_base != FINISHED){
        *for_base_frame  = GetVolConfigFrameBack(ref_layer_config)
                         - GetVolConfigFrameSkip(ref_layer_config);
        *back_base_frame = GetVolConfigFrameBack(ref_layer_config);
        if(temporal_scalability == 5){
          *for_base_frame  -= GetVolConfigFrameSkip(ref_layer_config);
          *back_base_frame -= GetVolConfigFrameSkip(ref_layer_config);
        }
        *for_alpha_base_vop  = GetVopPrevTemp(base_vop_not_padding_for_bgc);
        *back_alpha_base_vop = GetVopNextTemp(base_vop_not_padding_for_bgc);
        if(original_prev_base_vop != NULL){
          prev_vop_TPS_B = CloneVop(original_prev_base_vop);
          CopyVopNonImageField_TPS(original_prev_base_vop,prev_vop_TPS_B);
        }
      }
      /* B -> E -> E-> end */
      else{
        *for_base_frame      = GetVolConfigFrameBack(ref_layer_config);
        *for_alpha_base_vop  = GetVopNextTemp(base_vop_not_padding_for_bgc);
        if(GetVolVop(GetVolById(GetVOLayers(next_vo),ref_vol_id)) != NULL){
          prev_vop_TPS_B = CloneVop_TMP(GetVolVop(GetVolById(GetVOLayers(next_vo),ref_vol_id)));
          CopyVopNonImageField_TPS(GetVolVop(GetVolById(GetVOLayers(next_vo),ref_vol_id)), prev_vop_TPS_B);
        }
      }
    }
    /****************** I_TYPE or P_TYPE or B_TYPE(1) : TPS end ******************/
    /****************** B_TYPE(2) : TPS ******************/
    else{
      /* B -> E -> E-> B */
      if(finish_base != FINISHED){
        *for_base_frame      = GetVolConfigFrameBack(ref_layer_config)
                             - GetVolConfigFrameSkip(ref_layer_config);
	*back_base_frame     = GetVolConfigFrameBack(ref_layer_config);
	*for_base_frame     -= GetVolConfigFrameSkip(ref_layer_config);
	*back_base_frame    -= GetVolConfigFrameSkip(ref_layer_config);
	*for_alpha_base_vop  = GetVopPrevTemp(base_vop_not_padding_for_bgc);
	*back_alpha_base_vop = GetVopNextTemp(base_vop_not_padding_for_bgc);
	if(original_prev_base_vop != NULL){
          prev_vop_TPS_B = CloneVop(original_prev_base_vop);
          CopyVopNonImageField_TPS(original_prev_base_vop,prev_vop_TPS_B);
        }
     }
     /* B -> E -> E-> end */
     else{
         *for_base_frame      = GetVolConfigFrameBack(ref_layer_config);

                *for_alpha_base_vop  = GetVopNextTemp(base_vop_not_padding_for_bgc);

  if(GetVolVop(GetVolById(GetVOLayers(next_vo),ref_vol_id)) != NULL){
      prev_vop_TPS_B = CloneVop_TMP(GetVolVop(GetVolById(
         GetVOLayers(next_vo),ref_vol_id)));
      CopyVopNonImageField_TPS(GetVolVop(GetVolById(
     GetVOLayers(next_vo),ref_vol_id)), prev_vop_TPS_B);
  }

            }
       }
       /****************** B_TYPE(2) : TPS end ******************/
         DecideEnhanceEncodingMode(frame,  *for_base_frame,  *back_base_frame,
          GetVolConfigFrameSkip( layer_config ),
          GetVolConfigFrameSkip( ref_layer_config ),
                               GetVolConfigEndFrame(  ref_layer_config ),
                               &*ref_mode, &*last_enhancement_mode,
          &*back_base_exist,
          &*need_for_back_shape,
                 temporal_scalability,
          finish_base);

  /*** B_TYPE(1) : TPS ***/
         if(temporal_scalability == 1){
         *prev_vol           = GetVolById(GetVOLayers(next_vo),     ref_vol_id);
                *rec_vol            = GetVolById(GetVOLayers(next_rec_vo), ref_vol_id);

          *next_vol_store     = GetVolById(GetVOLayers(next_vo),     ref_vol_id);
                *next_rec_vol_store = GetVolById(GetVOLayers(next_rec_vo), ref_vol_id);
  if(finish_base != FINISHED && *for_alpha_base_vop != NULL)
      mode = 1;
  }
  /*** B_TYPE(2) : TPS ***/
         else if(temporal_scalability == 2){
         *prev_vol           = GetVolById(GetVOLayers(prev_vo),     vol_id);
                *rec_vol            = GetVolById(GetVOLayers(rec_vo),      vol_id);
          *next_vol_store     = GetVolById(GetVOLayers(next_vo),     vol_id);
                *next_rec_vol_store = GetVolById(GetVOLayers(next_rec_vo), vol_id);
  }
         /*** P_VOP in B_TYPE(1) : TPS ***/
         else if(temporal_scalability == 4 || 
                 temporal_scalability == 5){
         if( *ref_mode ){
                    *prev_vol       = GetVolById(GetVOLayers(next_vo),     ref_vol_id);
                    *rec_vol        = GetVolById(GetVOLayers(next_rec_vo), ref_vol_id);
                }
                else{
                    *prev_vol       = GetVolById(GetVOLayers(prev_vo),     vol_id);
                    *rec_vol        = GetVolById(GetVOLayers(rec_vo),      vol_id);
                }
         *next_vol_store     = GetVolById(GetVOLayers(next_vo),     vol_id);
                *next_rec_vol_store = GetVolById(GetVOLayers(next_rec_vo), vol_id);
  }

  /*** I_VOP or P_VOP(*ref_mode) or B_VOP(case1) : TPS ***/
         if(temporal_scalability != 2 && *ref_mode && *for_alpha_base_vop != NULL)
             mode = 1;/* use base_vop */
         else if(temporal_scalability == 2 ||
   ((temporal_scalability == 3 || temporal_scalability == 4) && !*ref_mode))
             mode = 2;/* use enhance */

  *rec_vop =  SetRefVopForEnhance_B_TPS(*rec_vol,      *for_alpha_base_vop,
            GetVolConfigEnhanceType(layer_config),
            GetVolConfigShape(ref_layer_config),
            finish_base,   mode);

  *prev_vop = SetRefVopForEnhance_B_TPS(*prev_vol,     prev_vop_TPS_B,
            GetVolConfigEnhanceType(layer_config),
            GetVolConfigShape(ref_layer_config),
            finish_base,   mode);


         /*** B_VOP(case 2) : TPS ***/
         mode = -1;
         if(temporal_scalability == 2)
      mode = 1;/* use base_vop */

         *next_rec_vop = SetRefVopForEnhance_B_TPS(*next_rec_vol_store, *for_alpha_base_vop,
                GetVolConfigEnhanceType(layer_config),
                GetVolConfigShape(ref_layer_config),
                finish_base,         mode);
         *next_vop     = SetRefVopForEnhance_B_TPS(*next_vol_store,     prev_vop_TPS_B,
                GetVolConfigEnhanceType(layer_config),
                GetVolConfigShape(ref_layer_config),
                finish_base,         mode);
  }
  /*** free ***/
  if(prev_vop_TPS_B != NULL){
      FreeVop(prev_vop_TPS_B);
      prev_vop_TPS_B = NULL;
  }
  return;
}

/***********************************************************CommentBegin******
 *
 * -- GetVolConfigFrameBack
 *
 ***********************************************************CommentEnd********/
Int
GetVolConfigFrameBack(VolConfig *cfg)
{
  Int	frame, M;

  M = GetVolConfigM(cfg);
  if(GetVolConfigScalability(cfg) && M != 1)
       M = 1;
  frame = cfg->frame - (M * cfg->frame_skip);
  return(frame);
}

  /***********************************************************CommentBegin******
 *
 * -- PrintEncodeProcess_TPS
 *
 ***********************************************************CommentEnd********/
Void
PrintEncodeProcess_TPS(Int scalability,
         Int prediction_type,
         Int frame,
         Int frameskip)

{
  if(!scalability){
    if(prediction_type != B_VOP)
      fprintf(stderr,"encode B[%3d]",frame);
    else
      fprintf(stderr,"encode B[%3d]",frame - frameskip);
  }
  else
      fprintf(stderr,"encode E[%3d]",frame);

  if(prediction_type == I_VOP)
     fprintf(stderr,"( I picture )");
  else if(prediction_type == P_VOP)
     fprintf(stderr,"( P picture )");
  else if(prediction_type == B_VOP)
     fprintf(stderr,"( B picture )");
  else{
     fprintf(stderr,"\n- ERROR - (? picture = %d)\n",prediction_type);
     exit(-1);
  }
  fprintf(stderr,"end\n");
}

/***********************************************************CommentBegin******
 *
 * -- CheckEnhanceMode_TPS_B_type2
 * Author :  Ryuji Kitaura (sharp)
 *
 ***********************************************************CommentEnd********/
Int
CheckEnhanceMode_TPS_B_type2(VOConfig  *vo_config,
        Int       vo_id,
        Int       vol_id,
        Int       finish_base)

{
  Int base_frame,
      base_skip,
      enh_frame,
      enh_skip,
      mode         = 0;
  Int ref_vol_id;

  VolConfig *vol_config     = NULL;
  VolConfig *ref_vol_config = NULL;

  vol_config     = GetVolConfigById(GetVOConfigLayers(vo_config),vol_id);
  ref_vol_id     = GetVolConfigRefId(vol_config);
  ref_vol_config = GetVolConfigById(GetVOConfigLayers(vo_config),ref_vol_id);

  base_frame = GetVolConfigFrameBack(ref_vol_config);
  base_skip  = GetVolConfigFrameSkip(ref_vol_config);
  enh_frame  = GetVolConfigFrameNoInc( vol_config);
  enh_skip   = GetVolConfigFrameSkip(  vol_config);


  if(finish_base != FINISHED){
      if(base_frame - base_skip == enh_frame + enh_skip || base_frame - base_skip ==
      enh_frame)
          mode = 1;          /* preview base frame */
      else if(base_frame == enh_frame + enh_skip || base_frame == enh_frame)
          mode = 2;
 }
  else
      mode = 3;

  return(mode);
}

/***********************************************************CommentBegin******
 *
 * -- CheckArbitraryShape
 *
 ***********************************************************CommentEnd********/
Int CheckArbitraryShape(VOConfig *vo_config)
{
  VOConfig	*curr_vo;
  VolConfig	*curr_vol;
  Int           shape_flag;

  curr_vo = vo_config;

  while(curr_vo != NULL){
 curr_vol = GetVOConfigLayers(curr_vo);
 while(curr_vol != NULL){
       shape_flag = GetVolConfigShape(curr_vol);
       if(shape_flag == 1)
           return(1);
       curr_vol = GetVolConfigNext(curr_vol);
 }
 curr_vo = GetVOConfigNext(curr_vo);
  }
  return(0);
}

