/*****************************************************************************
 *                                                                          
 * This software module was originally developed by 
 *
 * Martina Eckert (UPM-GTI / ACTS-MoMuSys)
 *
 * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
 * This software module is an implementation of a part of one or more MPEG-4 
 * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC 
 * 14496-2) standard. 
 *
 * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free 
 * license to this software module or modifications thereof for use in hardware
 * or software products claiming conformance to the MPEG-4 Video (ISO/IEC 
 * 14496-2) standard. 
 *
 * Those intending to use this software module in hardware or software products
 * are advised that its use may infringe existing patents. The original 
 * developer of this software module and his/her company, the subsequent 
 * editors and their companies, and ISO/IEC have no liability for use of this 
 * software module or modifications thereof in an implementation. Copyright is 
 * not released for non MPEG-4 Video (ISO/IEC 14496-2) Standard conforming 
 * products. 
 *
 * ACTS-MoMuSys partners retain full right to use the code for his/her own 
 * purpose, assign or donate the code to a third party and to inhibit third 
 * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) Standard
 * conforming products. This copyright notice must be included in all copies or
 * derivative works. 
 *
 * Copyright (c) 1997
 *
 *****************************************************************************/

/***********************************************************HeaderBegin*******
 *                                                                         
 * File:        rc_upm_model.c
 *
 * Author:      Martina Eckert, UPM-GTI
 * Created:     18-06-97
 *                                                                         
 * Description: UPM prediction model functions
 *
 * Notes:       
 *
 * Flags:       -D_RC_DEBUG_  -  RC debugging   
 *
 * Modified:
 *      11.11.97  M. Eckert: Headers, comments, cleaning
 *      03.12.97  M. Eckert: Include model improvement from jir        
 *      05.12.97  M. Eckert: Restructuration of files:
 *                  - static RC_HIST declaration ---> rc_upm1.c, rc_upm2.c
 *                  - history access functions rch_* ---> rc_hist.c
 *                  - use of pass_rc_hist()
 *
 ***********************************************************HeaderEnd*********/

/************************    INCLUDE FILES    ********************************/

#include "rc.h"
#include "momusys.h"
#include "mom_vop.h"
#include "vm_config.h"
#include "mom_vol.h"
#include "mom_structs.h"
#include "vm_enc_defs.h"

static RC_UPM_DATA rc_upm_model_data[MAX_NUM_VOS][MAX_NUM_VOLS];   /* UPM data of each VOL */


/***********************************************************CommentBegin******
 *
 * -- RC_UPM_init --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Initialization of global rate control, select prediction model.
 * 
 * Arguments in :       
 *      VOConfig *list         - List of VO-Configurations  
 *      Int      rc_rate_model - Switch to select rate prediction model
 *      Int      rc_dist_model - Switch to select dist. prediction model
 *      Int      rc_algorithm  - Switch to access
 *
 * Modified :           
 *      05.12.97 M.Eckert: Rename of function, introduce rc_algorithm for 
 *               access to history data
 *
 ***********************************************************CommentEnd********/

void RC_UPM_init(
		 VOConfig *list, 
		 Int      rc_rate_model,
		 Int      rc_dist_model,
		 Int      rc_algorithm,
		 Int      bits_frame
		 )
{

   VOConfig  *vo_config;
   VolConfig *vol_config;
   RC_HIST   *rch = NULL;
   RC_CFG_PARAM  *rc_cfg = NULL;
   Int  qp_first[3], num_vols=0, vo_id, vol_id;
   Int frame_type=0;

   vo_config = list;


   while (vo_config != NULL)
   {
      vol_config = GetVOConfigLayers(vo_config);
      while (vol_config != NULL)
      {
	 num_vols++;
         vol_config = GetVolConfigNext(vol_config);
      }
      vo_config = GetVOConfigNext(vo_config);
   }

   vo_config = list;
   while (vo_config != NULL)
   {
      vo_id = GetVOConfigId(vo_config);
      vol_config = GetVOConfigLayers(vo_config);
      while (vol_config != NULL)
	{
	  vol_id = GetVolConfigId(vol_config);

#ifdef _RC_DEBUG_
	  fprintf(stdout, "RC: ----->RC_UPM_init_global: vo_id = %d vol_id = %d\n",
		  vo_id, vol_id);
	  fprintf(stdout, "RC: StartFrame= %d\n",
		  GetVolConfigStartFrame(vol_config));
	  fprintf(stdout, "RC: EndFrame= %d\n",
		  GetVolConfigEndFrame(vol_config));
	  fprintf(stdout, "RC: FrameSkip= %d\n",
		  GetVolConfigFrameSkip(vol_config));
	  fprintf(stdout, "RC: Bitrate= %d\n",
		  GetVolConfigBitrate(vol_config));

#endif /* _RC_DEBUG_ */

	  qp_first[0] = GetVolConfigIntraQuantizer(vol_config);
	  qp_first[1] = GetVolConfigQuantizer(vol_config);
	  qp_first[2] = GetVolConfigBQuantizer(vol_config);
	  
	  switch (rc_algorithm)
	    {
	    case RC_ALGORITHM_UPM1: 
	      rch = get_rch_upm1(vo_id, vol_id, frame_type); 
	      rc_cfg = get_rc_cfg_upm1(vo_id, vol_id);
	      break;
	    case RC_ALGORITHM_UPM2: 
	      rch = get_rch_upm2(vo_id, vol_id, frame_type);
	      rc_cfg = get_rc_cfg_upm2(vo_id, vol_id);
	      break;
	    default:
	      error_exit("RC_UPM_init: Error: Mode not supported\n");
	    }


         switch (rc_rate_model) 
            {
	    case RC_MODEL_UPM1:
	      rch_init(rch, MAX_SLIDING_WINDOW);
	      rcd_init(&rc_upm_model_data[vo_id][vol_id],
		       rc_cfg, vol_config, bits_frame/num_vols,
		       qp_first, rc_algorithm);
               break;
#ifdef _RC_UPM2_
	    case RC_MODEL_UPM2:
	      rch_init(rch, MAX_SLIDING_WINDOW);
	      rcd_init(&rc_upm_model_data[vo_id][vol_id],
		       rc_cfg, vol_config, bits_frame/num_vols, 
		       qp_first, rc_algorithm);
	      break;
#endif
            default:
	      error_exit("RC_UPM_init_global: Error: Model for UPM \
Control Algorithm not supported\n");
            }

         switch (rc_dist_model) 
            {
            case RC_MODEL_UPM1:
	      /* if not yet initiallized and for not initiallizing twice */
	      if (rc_rate_model != RC_MODEL_UPM1 && 
		  rc_rate_model != RC_MODEL_UPM2) 
		{
                  rch_init(rch, MAX_SLIDING_WINDOW);
                  rcd_init(&rc_upm_model_data[vo_id][vol_id],
			   rc_cfg, vol_config, bits_frame/num_vols, 
			   qp_first, rc_algorithm);
		}
	      break;
#ifdef _RC_UPM2_
	    case RC_MODEL_UPM2:
	      if (rc_rate_model != RC_MODEL_UPM1 && 
		  rc_rate_model != RC_MODEL_UPM2)
		{
                  rch_init(rch, MAX_SLIDING_WINDOW);
                  rcd_init(&rc_upm_model_data[vo_id][vol_id],
			   rc_cfg, vol_config, bits_frame/num_vols, 
			   qp_first, rc_algorithm);
		}
	      break;
#endif
            default:
	      error_exit("RC_UPM_init_global: Error: Model for UPM \
Control Algorithm not supported\n");
            }
         
         vol_config = GetVolConfigNext(vol_config);
      }
      vo_config = GetVOConfigNext(vo_config);
   }


}

/***********************************************************CommentBegin******
 *
 * -- RC_UPM_Free --
 *
 * Purpose :
 *      Free reserved memory for RC
 * 
 * Arguments in :       
 *	     VOConfig  *vo_list      - List of VOs
 *	     Int       rc_algorithm  - type of algorithm
 *
 * Created : 
 *      19.02.98   
 *
 *
 ***********************************************************CommentEnd********/

Void RC_UPM_Free(
		 VOConfig *vo_list,
		 Int      rc_algorithm
		 )
{
  VolConfig *vol_list;
  RC_HIST   *rch = NULL;
  RC_CFG_PARAM  *rc_cfg = NULL;
  Int frame_type=0;
  
  while (vo_list != NULL)
  {
    Int vo_id = GetVOConfigId(vo_list);
    vol_list = GetVOConfigLayers(vo_list);
    while (vol_list != NULL)
    {
      Int vol_id = GetVolConfigId(vol_list);

      switch (rc_algorithm)
	{
	case RC_ALGORITHM_UPM1: 
	  rch = get_rch_upm1(vo_id, vol_id, frame_type);
	  rc_cfg = get_rc_cfg_upm1(vo_id, vol_id);
	  break;
	case RC_ALGORITHM_UPM2: 
	  rch = get_rch_upm2(vo_id, vol_id, frame_type);
	  rc_cfg = get_rc_cfg_upm2(vo_id, vol_id); 
	  break;
	default:
	  error_exit("RC_free: Error: Mode not supported\n");
	}
 
      rch_free(rch);
      rcd_free(&rc_upm_model_data[vo_id][vol_id], rc_cfg);

      vol_list = GetVolConfigNext(vol_list);
    }
    vo_list = GetVOConfigNext(vo_list);

  }
}

/***********************************************************CommentBegin******
 *
 * --  RC_UPM_pred_bits --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Estimation of average number of bits per pixel under condition of 
 *      the mean absolute difference (MAD) and the quantization parameter q. 
 *      The parameters p1, p2, p3 base on history events. 
 * 
 * Arguments in :       
 *      RC_HIST  *rch       -  History data 
 *      Int      vo_id      -  VO Id
 *      Int      vol_id     -  VOL Id
 *      Int      q          -  QP
 *      Double   mad        -  Mean absolute difference
 *	Int      frame_type -  I=0, P=1, B=2
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      - 
 *
 * Return values :      
 *      Int   rate     -  Predicted amount of bits needed for coding 
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *
 *
 * Modified : 03.12.97  M.Eckert: Include model improvement from jir        
 *            05.12.97  M.Eckert: Introduce input argument rch
 *            03.03.97  M.Eckert: Change function from UInt to Int to
 *                                make negative values valid.
 *
 *
 ***********************************************************CommentEnd********/

Int RC_UPM_pred_bits(
		     RC_HIST *rch,
		     Int     vo_id, 
		     Int     vol_id, 
		     Int     q,
		     Double  mad,
		     Int     frame_type
		     )
{ 

   RC_UPM_DATA *rcd = &rc_upm_model_data[vo_id][vol_id];
   Double      rate, num_pels;
   Double      p1, p2, p3;

   /* If VOP has already been coded, get number of bits: */

   if (!rch_proc_stat(rch)) 
      return rch_get_last_bits_vop(rch);

   /* Else use prediction: */

   if (rch_proc_stat(rch) == 1)
      /* Current VO in process -> get current number of pixels */
      num_pels = (Double) rch_get_curr_pixels(rch);
   else
      /* Current VO not yet processed -> get previous nr. of pel for pred. */
      num_pels = rch_get_last_pixels(rch); 

   p1 = rcd_get_X1(rcd, frame_type);
   p2 = rcd_get_X2(rcd, frame_type);
   p3 = rcd_get_X3(rcd, frame_type);
      
   if (rch_proc_stat(rch) == 2) 
      mad = rch_get_last_mad_text(rch);
  
   rate = p1/q + p2/(q*q) + p3;
   rate *= mad;
   rate *= num_pels; 

   /* JIR
   if (rate < 0) rate = 0;
   */
   rate += rch_get_last_bits_nottex(rch);

   /* Add prediction error of previous frame: */
   /*rate += (rch_get_last_bits_vop(rch) - rch_get_pred(rch));*/

   return (Int)(rate+0.5);
}

/***********************************************************CommentBegin******
 *
 * --  RC_UPM_pred_dist --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Estimation of average distortion per pixel under condition of the mean
 *      absolute difference (MAD) and the quantization parameter q. 
 *      The parameters p1, p2 base on history events. 
 * 
 * Arguments in :       
 *      RC_HIST  *rch       -  History data 
 *      Int      vo_id      -  VO Id
 *      Int      vol_id     -  VOL Id
 *      Int      q          -  QP
 *	Int      mode       -  mode = 0: pixel distortion, 
 *                             mode = 1: total distortion 
 *	Int      frame_type -  I=0, P=1, B=2
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      Double dist     -  Predicted distortion caused by quantization
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *
 *
 * Modified : 03.12.97  M.Eckert: Include model improvement from jir        
 *            05.12.97  M.Eckert: Introduce input argument rch
 *            12.02.98  M.Eckert: Remove unnecessary passing of mad,
 *                                new parameters mode, frame_type
 *
 ***********************************************************CommentEnd********/

Double RC_UPM_pred_dist(
			RC_HIST *rch,
			Int     vo_id,
                        Int     vol_id,
                        Int     q,
			Int     mode,
			Int     frame_type
                        )
{

   RC_UPM_DATA *rcd = &rc_upm_model_data[vo_id][vol_id];
   Double      p1, p2, p3, dist, num_pels;


   /* If VOP has already been coded, get distortion: */

   if (!rch_proc_stat(rch)) 
      return (Double) rch_get_last_dist(rch);

   /* Else use prediction model: */
   
   if (rch_proc_stat(rch) == 1)  
      /* Current VO in process -> get current number of pixels */
      num_pels = (Double) rch_get_curr_pixels(rch);
   else
      /* Current VO not yet processed -> get previous nr. of pel for pred. */
      num_pels = rch_get_last_pixels(rch); 

   p1 = rcd_get_Y1(rcd, frame_type);
   p2 = rcd_get_Y2(rcd, frame_type);
   p3 = rcd_get_Y3(rcd, frame_type);
      
   dist =  p1 * q + p2 * q*q + p3;

   if (mode == 1)
      dist *= num_pels;
  
   /* if (dist < 0) dist *= -1.; */
   /* JIR
   if (dist < 0) dist = 0;
   */
   
   return dist;
}

/***********************************************************CommentBegin******
 *
 * -- rc_update_UPM_model --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Update of UPM model. Different for rate and distortion. 
 * 
 * Arguments in :       
 *      RC_HIST *rch    Static history struct
 *      Int     type    rate or distortion parameters 
 *
 * Arguments in/out :   
 *      Double  *p1 <-> Params for prediction
 *      Double  *p2      
 *      Double  *p3      
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      -
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *
 *
 * Modified : 
 *            05.12.97 M.Eckert: Rename function
 *
 *
 ***********************************************************CommentEnd********/

static void rc_update_UPM_model(
				RC_HIST     *rch,
				Double      *p1,   
				Double      *p2,   
				Double      *p3,   
				Int         type   
				)
{

   Double E[MAX_SLIDING_WINDOW];   /* R/E or D/E data */
   Double QP[MAX_SLIDING_WINDOW];  /* Rate pred.: inverse QP, dist. pred.: QP */
   Double QP2[MAX_SLIDING_WINDOW]; /* Rate pred.: inverse QP^2, dist. pred.: QP^2 */

   Int    n;                   /* Number of data to employ */
   Int    i, count,  model_ok=0;
   Double x1=99., x2=99., x3=99.;


   if (rch_get_n(rch)<2)
      return;


#ifdef _RC_DEBUG_
   fprintf(stdout, "RC: RC_UPM: --> rc_update_UPM_model\n");
   fflush(stdout);
   rch_print(rch, stdout, "rc_update_UPM_model");
#endif

   /* Computation of number of data to employ */

   n = MIN(rch_get_n(rch), MAX_SLIDING_WINDOW);

   /* Array initialization */

   for (i = rch_dec_mod(rch,rch_get_ptr(rch)), count = 0; count < n; count++, 
           i = rch_dec_mod(rch,i))
   {
      Int    *bits_text = rch_get_bits_text(rch);
      Double *dist      = rch_get_dist(rch);
      Double *mad_text  = rch_get_mad_text(rch);
      Int    *num_pel   = rch_get_pixels(rch);
      Int    *qp        = rch_get_qp(rch);

      switch (type) 
         {
         case 1: /* rate */
            E[count]  = (Double)bits_text[i] / ( mad_text[i] * num_pel[i] ); 
            QP[count]  = 1./(Double)qp[i];
            QP2[count] = QP[count] * QP[count];
            break;
         case 2: /* distortion */
            E[count]  = 255./pow(10., dist[i] / 20.);
            QP[count]  = (Double)qp[i];
            QP2[count] = QP[count] * QP[count];
            break;
         default:
            error_exit("RC_update_UPM_model: Error: Mode not supported\n");
         }
      
   }

#ifdef _RC_DEBUG_
   fprintf(stdout, "Computation of prediction parameters \n");
#endif
   
   /* LS computation */

   rc_2ls_comp_upm(E, QP, QP2, n, &x1, &x2);

#ifdef _RC_DEBUG_
   fprintf(stdout, "RC: RC_UPM: <-- rc_update_2ls_comp: p1= %f  p2= %f \n", 
           x1, x2);
#endif

   /* Outlier removing (arrays reinitialization) */

   rc_2ls_remove_out(E, QP, QP2, &n, &x1, &x2);

   /* LS recomputation */

   rc_2ls_comp_upm(E, QP, QP2, n, &x1, &x2);

#ifdef _RC_DEBUG_
   fprintf(stdout, "RC: RC_UPM: <-- rc_update_2ls_comp: p1= %f  p2= %f \n", 
           x1, x2);
#endif
       
   if (x1 == 99. && x2 == 99. && x3 == 99.)
   {
#ifdef _RC_DEBUG_
      fprintf(stdout,"RC: Model not changed! \n"); fflush(stdout);
      fprintf(stdout, "RC: RC_UPM: <-- rc_update_2ls_comp: p1= %f, p2= %f, p3= %f \n", 
              p1, p2, p3);
#endif
      return;
   }

   x3 = 0;

   switch (type)
      {
      case 1:
        model_ok = rc_decide(x1, x2, 1./31., 1.);
        break;
      case 2:
        model_ok = rc_decide(x1, x2, 1., 31.);
        break;
      default:
        error_exit("RC_update_UPM_model: Error: Mode not supported\n");
      }
 
   if (!model_ok)
   {
      if (n > 1)
      {
         rc_linear(E, QP, QP2, n, &x1, &x2, &x3);
#ifdef _RC_DEBUG_
         fprintf(stdout, "RC: RC_UPM: <-- rc_update_2ls_comp: p1= %f, p2= %f, p3= %f \n", 
                 x1, x2, x3);
#endif
      }
      if (n <= 1 || x1 <= 0)
      {
#ifdef _RC_DEBUG_
         fprintf(stdout,"RC: Model not changed! \n"); fflush(stdout);
         fprintf(stdout, "RC: RC_UPM: <-- rc_update_2ls_comp: p1= %f, p2= %f, p3= %f \n", 
                 *p1, *p2, *p3);
#endif
         return;
      }
   }

   *p1 = x1;
   *p2 = x2;
   *p3 = x3;



#ifdef _RC_DEBUG_
   
   fprintf(stdout, "RC: RC_UPM: <-- rc_update_2ls_comp: p1= %f, p2= %f, p3= %f \n", 
           *p1, *p2, *p3);
           
#endif

}


/***********************************************************CommentBegin******
 *
 * -- RC_UPM_UpdateModel --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Update selected estimation model 
 * 
 * Arguments in :       
 *      Int    vo_id     -  VO Id
 *      Int    vol_id    -  VOL Id
 *      Int    vopbits   -  Total number of bits 
 *      Int    vopheader -  Total minus texture 
 *      Double dist      -  Distortion of texture 
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      -
 *
 * Side effects :       
 *      -
 *
 * Description :        
 *
 *
 * See also :
 *
 *
 * Modified :           
 *            05.12.97  M.Eckert: Introduce input argument rch
 *
 *
 ***********************************************************CommentEnd********/

void RC_UPM_UpdateModel(
			Int vo_id,
                        Int vol_id,
                        Int vopbits,   /* Total number of bits */
                        Int vopheader, /* Total minus texture */
                        Double dist,    /* Distortion of texture */
			Int rc_algorithm,
			Int rc_model,
			Int type, /* Update of rate (1) or distortion (2) */
			Int frame_type
                        )
{

   RC_UPM_DATA *rcd = &rc_upm_model_data[vo_id][vol_id];
   RC_HIST *rch = NULL;


#ifdef _RC_DEBUG_

   Char p1rI_file_name[15], p2rI_file_name[15], p3rI_file_name[15], 
        p1dI_file_name[15], p2dI_file_name[15], p3dI_file_name[15];
   Char p1rP_file_name[15], p2rP_file_name[15], p3rP_file_name[15], 
        p1dP_file_name[15], p2dP_file_name[15], p3dP_file_name[15];
   Char p1rB_file_name[15], p2rB_file_name[15], p3rB_file_name[15], 
        p1dB_file_name[15], p2dB_file_name[15], p3dB_file_name[15];
 
   /* Save parameters for graphic plots */

#endif

   switch (rc_algorithm)
     {
     case RC_ALGORITHM_UPM1:
	rch = get_rch_upm1(vo_id, vol_id, frame_type);
        break;
     case RC_ALGORITHM_UPM2:
 	rch = get_rch_upm2(vo_id, vol_id, frame_type);
       break;
     default:
        error_exit("RC_UPM_Update_model: Error: Mode not supported\n");
     }



   /* Update rate or distortion parameters: (RC_UPM2 flag for 
      internal model which uses numerical recipes functions) */

   switch (type)
     {
     case 1: /* Update rate parameters */

#ifdef _RC_DEBUG_
	sprintf(p1rI_file_name,"p1_rate_%d_%d_I",vo_id,vol_id);
	sprintf(p2rI_file_name,"p2_rate_%d_%d_I",vo_id,vol_id);
	sprintf(p3rI_file_name,"p3_rate_%d_%d_I",vo_id,vol_id);
	sprintf(p1rP_file_name,"p1_rate_%d_%d_P",vo_id,vol_id);
	sprintf(p2rP_file_name,"p2_rate_%d_%d_P",vo_id,vol_id);
	sprintf(p3rP_file_name,"p3_rate_%d_%d_P",vo_id,vol_id);
	sprintf(p1rB_file_name,"p1_rate_%d_%d_B",vo_id,vol_id);
	sprintf(p2rB_file_name,"p2_rate_%d_%d_B",vo_id,vol_id);
	sprintf(p3rB_file_name,"p3_rate_%d_%d_B",vo_id,vol_id);
#endif

	rch_store_after(rch, vopbits-vopheader, vopbits, dist);


	/* Special "store after" for all frame types: */

	rcd->total_bits += vopbits;
	rcd->total_frames++;


	switch (rc_model)
	   {
	   case RC_MODEL_UPM1:	
	      rc_update_UPM_model(rch, 
				  &rcd->X1[frame_type], 
				  &rcd->X2[frame_type], 
				  &rcd->X3[frame_type], 1); 
	      break;
#ifdef _RC_UPM2_
	   case RC_MODEL_UPM2:	
	      fprintf(stdout,">>>>>>>>>>>> Update rate with UPM2 model!\n");
	      rc_update_UPM_model2(rch, 
				   &rcd->X1[frame_type], 
				   &rcd->X2[frame_type], 
				   &rcd->X3[frame_type], 1); 
	      break;
#endif
	   default:
	      error_exit("RC_UPM_Update_model: Error: Mode not supported\n");
	   }

#ifdef _RC_DEBUG_
	if(frame_type == 0)
	{
	  WRITE_FLOAT(p1rI_file_name, rcd_get_X1(rcd, frame_type));
	  WRITE_FLOAT(p2rI_file_name, rcd_get_X2(rcd, frame_type));
	  WRITE_FLOAT(p3rI_file_name, rcd_get_X3(rcd, frame_type));
	}
	else if(frame_type == 1)
	{
	  WRITE_FLOAT(p1rP_file_name, rcd_get_X1(rcd, frame_type));
	  WRITE_FLOAT(p2rP_file_name, rcd_get_X2(rcd, frame_type));
	  WRITE_FLOAT(p3rP_file_name, rcd_get_X3(rcd, frame_type));
	}
	else if(frame_type == 2)
	{
	  WRITE_FLOAT(p1rB_file_name, rcd_get_X1(rcd, frame_type));
	  WRITE_FLOAT(p2rB_file_name, rcd_get_X2(rcd, frame_type));
	  WRITE_FLOAT(p3rB_file_name, rcd_get_X3(rcd, frame_type));
	}
	else
	  error_exit("RC_UPM_UpdateModel: Unknown frame type \n");

#endif

	break;
     case 2: /* Update distortion parameters */

#ifdef _RC_DEBUG_
	sprintf(p1dI_file_name,"p1_dist_%d_%d_I",vo_id,vol_id);
	sprintf(p2dI_file_name,"p2_dist_%d_%d_I",vo_id,vol_id);
	sprintf(p3dI_file_name,"p3_dist_%d_%d_I",vo_id,vol_id);
	sprintf(p1dP_file_name,"p1_dist_%d_%d_P",vo_id,vol_id);
	sprintf(p2dP_file_name,"p2_dist_%d_%d_P",vo_id,vol_id);
	sprintf(p3dP_file_name,"p3_dist_%d_%d_P",vo_id,vol_id);
	sprintf(p1dB_file_name,"p1_dist_%d_%d_B",vo_id,vol_id);
	sprintf(p2dB_file_name,"p2_dist_%d_%d_B",vo_id,vol_id);
	sprintf(p3dB_file_name,"p3_dist_%d_%d_B",vo_id,vol_id);
#endif
	
	switch (rc_model)
	   {
	   case RC_MODEL_UPM1:	
	      rc_update_UPM_model(rch, 
				  &rcd->Y1[frame_type], 
				  &rcd->Y2[frame_type], 
				  &rcd->Y3[frame_type], 2); 
	      break;
#ifdef _RC_UPM2_
	   case RC_MODEL_UPM2:	
	      fprintf(stdout,">>>>>>>>>>>> Update distortion with UPM2 model!\n");
	      rc_update_UPM_model2(rch, 
				   &rcd->Y1[frame_type], 
				   &rcd->Y2[frame_type], 
				   &rcd->Y3[frame_type], 2); 
	      break;
#endif
	   default:
	      error_exit("RC_UPM_Update_model: Error: Mode not supported\n");
	   }

#ifdef _RC_DEBUG_
	if(frame_type == 0)
	{
	  WRITE_FLOAT(p1dI_file_name, rcd_get_Y1(rcd, frame_type));
	  WRITE_FLOAT(p2dI_file_name, rcd_get_Y2(rcd, frame_type));
	  WRITE_FLOAT(p3dI_file_name, rcd_get_Y3(rcd, frame_type));
	}
	else if (frame_type == 1)
	{
	  WRITE_FLOAT(p1dP_file_name, rcd_get_Y1(rcd, frame_type));
	  WRITE_FLOAT(p2dP_file_name, rcd_get_Y2(rcd, frame_type));
	  WRITE_FLOAT(p3dP_file_name, rcd_get_Y3(rcd, frame_type));
	}
	else if (frame_type == 2)
	{
	  WRITE_FLOAT(p1dB_file_name, rcd_get_Y1(rcd, frame_type));
	  WRITE_FLOAT(p2dB_file_name, rcd_get_Y2(rcd, frame_type));
	  WRITE_FLOAT(p3dB_file_name, rcd_get_Y3(rcd, frame_type));
	}
	else
	  error_exit("RC_UPM_UpdateModel: Unknown frame type \n");
#endif

	break;
     default:
        error_exit("RC_UPM_Update_model: Error: Type not supported\n");
     }

   /* Update of rate calculation parameters: */
   rcd_update(rcd, rch, frame_type);


}

/***********************************************************CommentBegin******
 *
 * -- rcd_inc_skipped --
 *
 * Purpose :
 *      Increment number of skipped frames
 * 
 * Arguments in :       
 *      RC_UPM_DATA  *rcd       -  UPM data 
 *
 * Modified : 
 *      05.12.97  M. Eckert: Change site and input parameters
 *      05.02.98  M. Eckert: Moved from RC_HIST to RC_UPM_DATA
 *
 *
 ***********************************************************CommentEnd********/

Void rcd_inc_skipped(
		     Int vo_id,
		     Int vol_id
                     )
{
  RC_UPM_DATA *rcd = &rc_upm_model_data[vo_id][vol_id];

  rcd->total_skipped++;

}
/***********************************************************CommentBegin******
 *
 * -- get_rcd --
 *
 * Author : 
 *      Martina Eckert, UPM-GTI     
 *
 * Created :            
 *      06.12.97
 *
 * Purpose :
 *      Access to UPM data from other files
 *
 * Arguments in :       
 *      Int    vo_id   -  VO Id
 *      Int    vol_id  -  VOL Id
 *
 * Arguments in/out :   
 *      -
 *
 * Arguments out :      
 *      -
 *
 * Return values :      
 *      RC_UPM_DATA  *rcd  - UPM data array  
 *
 *
 * Modified : 
 *
 *
 ***********************************************************CommentEnd********/

RC_UPM_DATA *get_rcd(
		      Int  vo_id,
		      Int  vol_id
		      )
{

return &rc_upm_model_data[vo_id][vol_id];

}

/*********************************************************** End of file ***/
