/*****************************************************************************
 *                                                                          
 * This software module was originally developed by 
 *
 * J. Ignacio Ronda (UPM-GTI / ACTS-MoMuSys)
 *                                                                      
 * and edited by                                                        
 *
 * Fernando Jaureguizar (UPM-GTI / ACTS-MoMuSys)
 * Martina Eckert       (UPM-GTI / ACTS-MoMuSys)
 * Jordi Ribas          (Sharp Labs of America)
 *
 * 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.h
 *
 * Author:      J. Ignacio Ronda, UPM-GTI
 *
 * Created:     18-06-97
 *                                                                         
 * Description: Rate control data types and generic interface
 *              Header for all rate control files
 *
 * Notes:       
 *
 * Modified:
 *      13.11.97  Martina Eckert: Headers, comments, cleaning
 *      27.11.97  M. Eckert: Changes for independent frame type control
 *      11.12.97  M. Eckert: New structs:  RC_CTL_PARAM, RC_CFG_PARAM for
 *                           reading RC parameter from string
 *      27.01.98  M. Eckert: New rc_upm_get_QPfirst() MACRO, and new qp_first
 *                array in RC_CFG_PARAM struct.
 *      19.02.98  Jordi Ribas: Added data structure RCQ2_MB_DATA and constants
 *                for VM8 macroblock layer rate control
 *      06.03.98  M. Eckert: Cleanig: #include "meitca_wrapper.p" 
 *                           for Sharp MB-RC
 *
 ************************************************************HeaderEnd*******/

#ifndef RC_INC
#define RC_INC

#include "momusys.h"
#include "vm_config.h"
#include "vm_stats.h"


/* ------------------------------------------------------------------------
   RC_HIST: Data structure to store the history of a VOL
   ------------------------------------------------------------------------ */

#define RC_WINDOW_LENGTH 200

typedef struct
   {
   Int  size;           /* Storage capacity */
      
   Int  n;              /* Number of actually stored values */
   Int  prev;           /* 1 if first set of data already stored */
   Int  ptr;            /* Position where next data are going to be stored */
   Int  proc_stat;      /* Flag for process status:
                                 0 = processed
			         1 = currently in process 
                                 2 = not yet processed */
   Int    *bits_text;   /* Bits for texture */
   Int    *pixels;      /* Number of coded pixels */
   Double *mad_text;    /* Mean average prediction error for texture */
   Double *dist;        /* Distortion for texture */
   Int    *bits_vop;    /* Total bits */ 
   Int    *qp;          /* Employed QP */

   Double  total_dist;      /* Total texture distortion */
   Int     total_bits_text; /* Total bits texture */
   Int     total_bits;      /* Total bits */
   Int     total_frames;    /* Total frames */

   Int     last_pred_bits_text;   /* Predicted bits for texture */

   } RC_HIST;

#define rch_get_size(rch)       ((rch)->size)
#define rch_get_n(rch)          ((rch)->n)
#define rch_get_ptr(rch)        ((rch)->ptr)
#define rch_proc_stat(rch)      ((rch)->proc_stat)

#define rch_get_bits_text(rch)  ((rch)->bits_text)
#define rch_get_pixels(rch)     ((rch)->pixels)
#define rch_get_mad_text(rch)   ((rch)->mad_text)
#define rch_get_dist(rch)       ((rch)->dist)
#define rch_get_bits_total(rch) ((rch)->bits_vop) 
#define rch_get_qp(rch)         ((rch)->qp)

#define rch_get_total_bits(rch) ((rch)->total_bits) 
#define rch_get_total_frames(rch) ((rch)->total_frames) 

#define rch_first(rch)         ((rch)->n==0)

#define rch_get_pred(rch)  ((rch)->last_pred_bits_text)
#define rch_get_beta(rch)  ((rch)->beta)

 /* ------------------------------------------------------------------------
   RCQ2_DATA: Q2 algorithm data and parameters
   ------------------------------------------------------------------------ */

#define START_RATE_CONTROL     5    /* Unused */
#define START_MODEL_UPDATING   1
/* #define START_OUTLIER_REMOVING 3 */    /* According to the VM should be 1! */
#define START_OUTLIER_REMOVING 1    /* According to the VM should be 1! */
#define MAX_SLIDING_WINDOW     20
#define PAST_PERCENT           0.05
#define SAFETY_MARGIN          0.10
#define SKIP_MARGIN            0.8  /* 80% of VBV (Modif. UPM-GTI) */
#define MAX_QUANT              31
#define MIN_QUANT              1
#define DISCOUNT_NTB           0    /* If 1, not-texture bits of the previous
                                       frame are discounted to compute QP */

/* VOL-level parameters
*/
typedef struct
   {
      Int     bit_rate; /* in bits/second */
      Int     numFrame; /* # of frames remaining of each type in this GOP */
      Int     num_I_Frame; /* # of I frames remaining in this GOP */
      Int     num_B_Frame; /* # of B frames remaining in this GOP */
      Int     num_P_Frame; /* # of P frames remaining in this GOP */
      Double  alpha_I;  /* factor for bit amount provided in relation to P frame */
      Double  alpha_B;  /* factor for bit amount provided in relation to P frame */
      Double  bits_P_ave;  /* average bit amount for P frames */
      Int     T;        /* target # of bits for the next frame of each type */
      Int     R;        /* remaining number of bits assigned to the GOP. */
      Double  Bpp;      /* bit_rate / picture_rate */
      Int     VBV_size;
      Int     VBV_fullness;    /* buffer occupancy */
      Double  *X1;       /* second order complexity measure */
      Double  *X2;       /* second order complexity measure */
      Int     skip;
      Int     totalskipped;
      Int     codedFr;
      Int     dataNumber;
      Int     headerBitCount;
      Int     *QPfirst;  
   } RCQ2_DATA;

#define rcQ2_get_QPfirst(rcc, n)         ((rcc)->QPfirst[n])

/* --------------------------------- */
/* SHARP_start                       */


#define Q2MB_ACTIVE    1        /* used to make Q2 macroblock rate control active       */
#define Q2MB_INACTIVE  0        /* used to make Q2 macroblock rate control inactive     */
#define Q2MB_CHECK     2        /* used to check whether Q2 macroblock is active        */
#define Q2MB_MODE_THR  0.085    /* bits per pixel to decide whether mode 1 or 2 is used */
#define Q2MB_N         20       /* number of data points used for linear regression     */

/* structure for Q2 Macroblock-layer Rate Control */
typedef struct
   {
     Int       active;         /* 1: Q2 macroblock rate control selected, 0: not selected       */
     Int       active_vop;     /* 1: Q2 macroblock rate control active in vop, 0: not active    */
     Int       mode;           /* 1: higher bit rate, 2: lower bit rate */
     Int       MB_v;           /* number of macroblocks along vertical   axis in VOP */
     Int       MB_h;           /* number of macroblocks along horizontal axis in VOP */
     Int       MB_skip;        /* counter of number of skipped macroblocks in VOP */ 
     Float     A1;             /* model parameter for higher bit rate */ 
     Float     A1_prev;        /* value of A1 at the end of previous VOP   */
     Float     A1_curr;        /* average of A1 values in current VOP */
     Float     A2;             /* model parameter for lower bit rate  */
     Float     A3;             /* model parameter for lower bit rate  */
     Double    X_ls[Q2MB_N][2];/* parameter used for linear regression in mode = 2 */  
     Double    Y_ls[Q2MB_N];   /* parameter used for linear regression in mode = 2 */
     Float     **mad;          /* array of MADs for the macroblocks in the VOP */
     Float     **weight;       /* array of perceptual weights Ws for the macroblocks in VOP */ 
     Float     energy_S;       /* sum of product of W*MAD's for the VOP */
     Float     sum_mad;        /* sum of MADs for the VOP */
     Float     bits_prev;      /* number of bits used for the previous VOP */
     Float     T_bits;         /* Target number of bits for VOP */
     Float     T_text;         /* Target number of bits left for texture of VOP */
     Float     T_sms;          /* number of bits for shape, motion and syntax in previous VOP,
                                  T_text= T_bits-T_sms at the beginning of a VOP */
     Float     X11;            /* VM5 first order fall back coefficient */
} RCQ2_MB_DATA;

#include "meitca_wrapper.p" 

/* SHARP_end                        */
/* -------------------------------  */



/* ------------------------------------------------------------------------
   UPM algorithm data and parameters
   ------------------------------------------------------------------------ */

#define QP_INC 5 /* Range (+-) within qp can change */


/* Formerly been in VolConfig struct: */
typedef struct
   {
     Float   *rc_param;  /* 3 RC parameter. 
			    For UPM1: weights for I,B,P vops (I=0, P=1, B=2)
			    For UPM2: ordinal number for priority list and
			              minimal PSNR value for best VOL 
				      (3. param. not used) */
     Int     *qp_first;  /* Initial qp's for I,B,P vops (I=0, P=1, B=2)*/
   } RC_CFG_PARAM;

#define rc_get_RCParam(rc_cfg, n)        ((rc_cfg)->rc_param[n])
#define rc_upm_get_QPfirst(rc_cfg, n)    ((rc_cfg)->qp_first[n])

typedef struct
   {
     Double  *propC;    /* Proporcion de cuadros de tipos B,I,P (I=0, P=1, B=2)*/
     Double  *meanB;    /* Average number of bits used for B,I,P (I=0, P=1, B=2)*/
     Double  *X1;       /* second order complexity measure - rate */
     Double  *X2;       /* second order complexity measure - rate */
     Double  *X3;       /* second order complexity measure - rate */
     Double  *Y1;       /* second order complexity measure - distortion */
     Double  *Y2;       /* second order complexity measure - distortion */
     Double  *Y3;       /* second order complexity measure - distortion */
     Int     total_skipped;   /* Count of skipped frames */
     Int     total_frames;    /* Total frames */
     Int     total_bits;      /* Total bits */
   } RC_UPM_DATA;

#define rcd_get_propC(rcd, n)      ((rcd)->propC[n])
#define rcd_get_meanB(rcd, n)      ((rcd)->meanB[n])
#define rcd_get_X1(rcd, n)      ((rcd)->X1[n])
#define rcd_get_X2(rcd, n)      ((rcd)->X2[n])
#define rcd_get_X3(rcd, n)      ((rcd)->X3[n])
#define rcd_get_Y1(rcd, n)      ((rcd)->Y1[n])
#define rcd_get_Y2(rcd, n)      ((rcd)->Y2[n])
#define rcd_get_Y3(rcd, n)      ((rcd)->Y3[n])
#define rcd_get_total_frames(rcd)      ((rcd)->total_frames)

/* For translation of aleatoric id's into a consecutive list: */

typedef struct
   { 
   Int vo_id;         /* vo_id of list element */
   Int vol_id;        /* vol_id of list element */
   } LIST;

#include "rc_hist.p"
#include "rc_upmdata.p"

#include "rc_upm_model.p"

#ifdef _RC_UPM2_
#include "rc_upm_model2.p"
#endif


/* ------------------------------------------------------------------------
   Q2 rate control functions
   ------------------------------------------------------------------------ */

#include "rc_q2data.p"
#include "rc_q2.p"

/* ------------------------------------------------------------------------
   UPM rate control functions
   ------------------------------------------------------------------------ */

#include "rc_upm1.p"
#include "rc_upm2.p"

/* ------------------------------------------------------------------------
   Generic rate control interface
   ------------------------------------------------------------------------ */

#include "rc_if.p"


/* Algorithms */
#define RC_ALGORITHM_Q2   0
#define RC_ALGORITHM_UPM1 1 /* Minimization of sum alpha_i D_i */
#define RC_ALGORITHM_UPM2 2 /* Supporting priority list of VOPs */
#define RC_ALGORITHM_UPM3 3 /* Fixed D_i/D_0 ratios */
                            /* with D_i = distortio of VOP i, 
                               alpha_i = weights permitted by the user */

#define Q2_MULTIPLE_VO_RC 5 /* Mistubishi & SAMSUNG RC for Multiple VOs */


/* Statistical models */
#define RC_MODEL_Q2      0  /* Second order estimation function */
#define RC_MODEL_UPM1    1  /* Variable order estimation function */
#define RC_MODEL_UPM2    2  /* Variable order estimation function */


/* ------------------------------------------------------------------------
   Buffer control 
   ------------------------------------------------------------------------ */

/* Data type BUFFER to simulate the channel adaptation buffer */

typedef struct 
   {
   Int size;
   Int occup;
   Int frame_bit_rate;
   } BUFFER;

#define buffer_get_occup(buffer) ((buffer)->occup)

#include "rc_buffer.p"

/* ------------------------------------------------------------------------
   Target bit control 
   ------------------------------------------------------------------------ */

/* Parameter struct for decisions of the total number of bits 
   for the next frame */

typedef struct 
   {
     Int target_level;
     Int buffer_size;
     Int bits_frame;
     Int N;
    } RC_TB_PARS;

#include "rc_total_bits_upm.p"


/* ------------------------------------------------------------------------
   Auxiliary functions
   ------------------------------------------------------------------------ */

#include "rc_util.p"
#ifdef _RC_UPM2_
#include "rc_util2.p"
#endif

#define CUAD(x) ((x)*(x))

/* ------------------------------------------------------------------------
   File print macros
   ------------------------------------------------------------------------ */

#define WRITE_INT_INT(file_name, frame_nr, int_data) \
{ FILE *script_file; \
  if ((script_file = fopen(file_name, "a")) == NULL) { \
      fprintf(stdout,"Error opening %s ?\n",file_name);\
      exit(1); } \
  fprintf(script_file,"%d, %d \n",frame_nr, int_data); \
  fclose(script_file); \
}

#define WRITE_INT_FLOAT(file_name, frame_nr, float_data) \
{ FILE *script_file; \
  if ((script_file = fopen(file_name, "a")) == NULL) { \
      fprintf(stdout,"Error opening %s ?\n",file_name);\
      exit(1); } \
  fprintf(script_file,"%d, %f \n",frame_nr, float_data); \
  fclose(script_file); \
}

#define WRITE_INT(file_name, int_data) \
{ FILE *script_file; \
  if ((script_file = fopen(file_name, "a")) == NULL) { \
      fprintf(stdout,"Error opening %s ?\n",file_name);\
      exit(1); } \
  fprintf(script_file,"%d \n", int_data); \
  fclose(script_file); \
}

#define WRITE_FLOAT(file_name, float_data) \
{ FILE *script_file; \
  if ((script_file = fopen(file_name, "a")) == NULL) { \
      fprintf(stdout,"Error opening %s ?\n",file_name);\
      exit(1); } \
  fprintf(script_file,"%f \n", float_data); \
  fclose(script_file); \
}




#endif
/*********************************************************** End of file ***/
