/*****************************************************************************
 *                                                                          
 * This software module was originally developed by 
 *
 * J. Ignacio Ronda (UPM-GTI / ACTS-MoMuSys)
 *                                                                      
 * and edited 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_upmdata.c
 *
 * Author:      J. Ignacio Ronda, UPM-GTI
 * Created:     18-06-97
 *                                                                         
 * Description: Functions of UPM data type
 *
 * Flags:       -D_RC_DEBUG_  -  RC debugging   
 *
 * Modified:
 *      13.11.97  Martina Eckert: Headers, comments, cleaning
 *		18.11.97 M.Wollborn: include unistd only for non-PC
 *
 ***********************************************************HeaderEnd*********/

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

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#if !defined(WIN32)
#  include <unistd.h>
#endif

#include <ctype.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"

#include "rc.h"


/***********************************************************CommentBegin******
 *
 * -- rcd_print --
 *
 * Author : 
 *      J. Ignacio Ronda, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Type printing function
 *
 * Arguments in :       
 *      RCQ2_DATA   *rcc     -  Q2 RC data
 *      FILE        *file    -  Output file
 *      char        *prefix  -  Prefix for printouts
 *
 * Modified : 
 *
 *
 ***********************************************************CommentEnd********/

Void rcd_print(
               RC_UPM_DATA *rcd, 
               FILE        *file, 
               char        *prefix
               )
{
  Int i;

  for (i=0; i<3; i++)
  {
    fprintf(file, "%s propC[%d]=   %f\n", prefix, i, rcd->propC[i]);
    fprintf(file, "%s meanB[%d]=   %f\n", prefix, i, rcd->meanB[i]);
    fprintf(file, "%s X1[%d]=   %f\n", prefix, i, rcd->X1[i]);
    fprintf(file, "%s X2[%d]=   %f\n", prefix, i, rcd->X2[i]);
    fprintf(file, "%s X3[%d]=   %f\n", prefix, i, rcd->X3[i]);
    fprintf(file, "%s Y1[%d]=   %f\n", prefix, i, rcd->Y1[i]);
    fprintf(file, "%s Y2[%d]=   %f\n", prefix, i, rcd->Y2[i]);
    fprintf(file, "%s Y3[%d]=   %f\n", prefix, i, rcd->Y3[i]);
    fprintf(file, "\n");  
  }

  fprintf(file, "%s total_skipped=   %d\n", prefix, rcd->total_skipped);
}

/***********************************************************CommentBegin******
 *
 * -- rcd_init --
 *
 * Author : 
 *      J. Ignacio Ronda, UPM-GTI     
 *
 * Created :            
 *      18-06-97
 *
 * Purpose :
 *      Initialization
 *
 * Arguments in :       
 *      RC_UPM_DATA   *rcd         -  UPM RC data
 *      Char          *rc_string   -  Parameter string from .cfg file
 *
 * Modified : 
 *      15.12.97  M.Eckert: RC parameters now in RC_CFG_PARAM
 *                          Initialization by extraction from string from
 *                          .cfg file
 *
 ***********************************************************CommentEnd********/

Void rcd_init(
              RC_UPM_DATA  *rcd,
	      RC_CFG_PARAM *rc_cfg,
	      VolConfig    *vol_config,
	      Int          bits_vol,
	      Int          *qp_first,
	      Int          rc_algorithm
              )
{
   Char *string[3], sep_char[1], 
        *rc_string = GetVolConfigRCParam(vol_config);
   Int  i, p, num_frames[3], tot_frames;

   sep_char[0]='|';

   /**** Initialisation of rcd (data): ****/

   /* Estimation parameters: */

   if ((rcd->X1=(Double *)calloc(sizeof(Double),3))==0)
     error_exit("RC: ERROR: calloc rcd->X1\n");
   if ((rcd->X2=(Double *)calloc(sizeof(Double),3))==0)
     error_exit("RC: ERROR: calloc rcd->X2\n");
   if ((rcd->X3=(Double *)calloc(sizeof(Double),3))==0)
     error_exit("RC: ERROR: calloc rcd->X3\n");

   if ((rcd->Y1=(Double *)calloc(sizeof(Double),3))==0)
     error_exit("RC: ERROR: calloc rcd->Y1\n");
   if ((rcd->Y2=(Double *)calloc(sizeof(Double),3))==0)
     error_exit("RC: ERROR: calloc rcd->Y2\n");
   if ((rcd->Y3=(Double *)calloc(sizeof(Double),3))==0)
     error_exit("RC: ERROR: calloc rcd->Y3\n");


   for (i=0; i<3; i++){
      rcd->X1[i] = 0.4711;
      rcd->X2[i] = 0.;
      rcd->X3[i] = 0.;
      rcd->Y1[i] = 0.4711;
      rcd->Y2[i] = 0.;
      rcd->Y3[i] = 0.;
   }


   /* Count proportions of B,I,P frames: */

   if ((rcd->propC = (Double *)calloc(sizeof(Double),3))==0)
      error_exit("RC: ERROR: calloc rcd->propC\n");
   rc_count_frames(vol_config, num_frames, &tot_frames);
   for (i=0; i<3; i++)
     rcd->propC[i] = (Double) num_frames[i] / tot_frames;


   /* Initialize mean number of Bits for B,I,P frames: */

   if ((rcd->meanB = (Double *)calloc(sizeof(Double),3))==0)
      error_exit("RC: ERROR: calloc rcd->meanB\n");
   rcd->meanB[0] = 3 * bits_vol;
   rcd->meanB[1] = bits_vol;
   rcd->meanB[2] = 0.5 * bits_vol;


   rcd->total_skipped=0;

#ifdef _RC_DEBUG_
   rcd_print(rcd, stdout, "RC: RC_UPM_INIT");
#endif

   /**** Initialisation of rc_cfg (parameter of configuration): ****/

   /* Initialization of RC Parameter from input string: */

   if ((rc_cfg->rc_param=(Float *)calloc(sizeof(Float),3))==0)
     error_exit("RC: ERROR: calloc rc_cfg->rc_param\n");

#ifdef _RC_DEBUG_
   printf("input string: %s \n",rc_string);
#endif

   /*** Read first parameter: ***/

   if ((string[0] = strtok(rc_string, sep_char)) == NULL)
     error_exit("ERROR rc_get_ctl_parameters: No parameters for RC selected! \n");
#ifdef _RC_DEBUG_
   printf("string[%d]= %s\n",0,string[0]);
#endif

   /*** Read rest in loop: ***/

   for (p = 1; p < 3; p++)
   {
     if ((string[p] = strtok(NULL, sep_char)) == NULL)
       string[p] = "*";
#ifdef _RC_DEBUG_
     printf("string[%d]= %s\n",p,string[p]);
#endif
  }

   /*** Evaluate parameters: ***/
   if (*string[0] == '*'){
     rc_cfg->rc_param[0] = 1.;
     fprintf(stdout,"RC - WARNING: No first RC parameter selected, set to %f \n",rc_cfg->rc_param[0]);
   }
   else
     sscanf(string[0],"%f", &rc_cfg->rc_param[0]);

   if (*string[1] == '*'){
     if (rc_algorithm == RC_ALGORITHM_UPM1)
       rc_cfg->rc_param[1] = 1.;
     else if  (rc_algorithm == RC_ALGORITHM_UPM2)
       rc_cfg->rc_param[1] = 35.;
     else
       error_exit("ERROR rc_get_ctl_parameters: Unsupported RC algorithm type! \n");
     fprintf(stdout,"RC - WARNING: No second RC parameter selected, set to %f \n",rc_cfg->rc_param[1]);
   }
   else
     sscanf(string[1],"%f", &rc_cfg->rc_param[1]);

   if (*string[2] == '*'){
     rc_cfg->rc_param[2] = 1.;
     if (rc_algorithm == RC_ALGORITHM_UPM1)
       fprintf(stdout,"RC - WARNING: No third parameter selected, set to %f \n",rc_cfg->rc_param[2]);
   }
   else
     sscanf(string[2],"%f", &rc_cfg->rc_param[2]);

#ifdef _RC_DEBUG_
   if (rc_algorithm == RC_ALGORITHM_UPM1)
     fprintf(stdout,"alpha(I) = %f, alpha(P) = %f, alpha(B) = %f \n",rc_cfg->rc_param[0], 
	     rc_cfg->rc_param[1], rc_cfg->rc_param[2]);
   else if  (rc_algorithm == RC_ALGORITHM_UPM2)
     fprintf(stdout,"Priority = %f, max. distortion = %f dB \n",
	     rc_cfg->rc_param[0], rc_cfg->rc_param[1]);
#endif


   /* First QP: */

   if ((rc_cfg->qp_first = (Int *)calloc(sizeof(Int),3))==0)
      error_exit("RC: ERROR: calloc rcd->qp_first\n");
   for (i=0; i<3; i++)
      rc_cfg->qp_first[i] = qp_first[i];  


}

/***********************************************************CommentBegin******
 *
 * -- rcd_update --
 *
 * Author : 
 *      M. Eckert, UPM-GTI     
 *
 * Created :            
 *      06-02-98
 *
 * Purpose :
 *      Update of parameters meanB and propC for calculation of 
 *      target bit rate
 *
 * Arguments in :       
 *	RC_UPM_DATA *rcd        - UPM data
 *	RC_HIST     *rch        - History data
 *	Int         frame_type  - I, P or B frame
 *
 * Modified : 
 *
 ***********************************************************CommentEnd********/

Void rcd_update(
		RC_UPM_DATA *rcd,
		RC_HIST     *rch,
		Int         frame_type
		)
{
printf("rcd_update: \n");

  /* meanB: sum bits for this frame_type /
            number of bits for all frames */

  /*  rcd->meanB[frame_type] = rch->total_bits / rcd->total_bits;*/

  /* meanB: sum bits for this frame_type /
            number of frames for this frame_type */
  rcd->meanB[frame_type] = rch->total_bits / rch->total_frames;

printf("New propC[%d] = %f, meanB[%d]=%f \n",
       frame_type, rcd->propC[frame_type],frame_type, rcd->meanB[frame_type]);

return;

}

/***********************************************************CommentBegin******
 *
 * -- rcd_free --
 *
 * Author : 
 *      M. Eckert, UPM-GTI     
 *
 * Created :            
 *      03-02-98
 *
 * Purpose :
 *      Free of Memory
 *
 * Arguments in :       
 *      RC_CFG_PARAM *rc_cfg
 *
 * Modified : 
 *
 ***********************************************************CommentEnd********/

Void rcd_free(
              RC_UPM_DATA  *rcd,
	      RC_CFG_PARAM *rc_cfg
              )
{


   free(rcd->X1);
   free(rcd->X2);
   free(rcd->X3);
   free(rcd->Y1);
   free(rcd->Y2);
   free(rcd->Y3);
   free(rc_cfg->qp_first);

}


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