/*****************************************************************************
 *
 *  XVID MPEG-4 VIDEO CODEC
 *  - Global definitions  -
 *
 *  Copyright(C) 2002 Michael Militzer <isibaar@xvid.org>
 *
 *  This program is free software ; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation ; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program ; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * $Id: global.h,v 1.1 2005/01/04 13:44:37 jeanlf Exp $
 *
 ****************************************************************************/

#ifndef _GLOBAL_H_
#define _GLOBAL_H_

#include "xvid.h"
#include "portab.h"

//----------------------------

void MemSet(void *dst, byte c, dword len);
int MemCmp(const void *mem1, const void *mem2, dword len);
void MemCpy(void *dst, const void *src, dword len);

template<class T>
inline void Swap(T &l, T &r){ T tmp = r; r = l; l = tmp; }

#ifndef __SYMBIAN32__

enum TLeave{ ELeave };
void *operator new(size_t sz, TLeave);
inline void operator delete(void *vp, TLeave){ operator delete(vp); }

#endif

//----------------------------
// Fatal error - display message, and exit program immediately.
void Fatal(const char *msg, dword code = 0);

//----------------------------
#ifndef assert

#ifdef NDEBUG
#define assert(exp) ((void)0)
#else

#define assert(exp) if(!(exp)){\
   Fatal(#exp, __LINE__); }

#endif
#endif

//----------------------------
/* --- macroblock modes --- */

#define MODE_INTER      0
#define MODE_INTER_Q 1
#define MODE_INTER4V 2
#define  MODE_INTRA     3
#define MODE_INTRA_Q 4
#define MODE_NOT_CODED  16
#define MODE_NOT_CODED_GMC 17

/* --- bframe specific --- */

#define MODE_DIRECT        0
#define MODE_INTERPOLATE   1
#define MODE_BACKWARD      2
#define MODE_FORWARD    3
#define MODE_DIRECT_NONE_MV   4
#define MODE_DIRECT_NO4V   5


/*
 * vop coding types
 * intra, prediction, backward, sprite, not_coded
 */
#define I_VOP  0
#define P_VOP  1
#define B_VOP  2
#define S_VOP  3
#define N_VOP  4

//----------------------------
// convert mpeg-4 coding type i/p/b/s_VOP to XVID_TYPE_xxx
inline int coding2type(int coding_type){
   return coding_type + 1;
}

//----------------------------
// convert XVID_TYPE_xxx to bitstream coding type i/p/b/s_VOP
inline int type2coding(int xvid_type){
   return xvid_type - 1;
}


typedef struct
{
   int x;
   int y;
}
VECTOR;



typedef struct
{
   VECTOR duv[3];
}
WARPPOINTS;

/* save all warping parameters for GMC once and for all, instead of
   recalculating for every block. This is needed for encoding&decoding
   When switching to incremental calculations, this will get much shorter
*/

/* we don't include WARPPOINTS wp   here, but in FRAMEINFO itself */

struct GMC_DATA{
   int num_wp;    /* [input]: 0=none, 1=translation, 2,3 = warping */
                     /* a value of -1 means: "structure not initialized!" */
   int s;               /* [input]: calc is done with 1/s pel resolution */

   int W;
   int H;

   int ss;
   int smask;
   int sigma;

   int r;
   int rho;

   int i0s;
   int j0s;
   int i1s;
   int j1s;
   int i2s;
   int j2s;

   int i1ss;
   int j1ss;
   int i2ss;
   int j2ss;

   int alpha;
   int beta;
   int Ws;
   int Hs;

   int dxF, dyF, dxG, dyG;
   int Fo, Go;
   int cFo, cGo;

   GMC_DATA(){
      MemSet(this, 0, sizeof(GMC_DATA));
   }
};

struct NEW_GMC_DATA{
   /*  0=none, 1=translation, 2,3 = warping
   *  a value of -1 means: "structure not initialized!" */
   int num_wp;

   /* {0,1,2,3}  =>   {1/2,1/4,1/8,1/16} pel */
   int accuracy;

   /* sprite size * 16 */
   int sW, sH;

   /* gradient, calculated from warp points */
   int dU[2], dV[2], Uo, Vo, Uco, Vco;

   void (*predict_16x16)(const NEW_GMC_DATA * const This,
                    byte *dst, const byte *src,
                    int dststride, int srcstride, int x, int y, int rounding);
   void (*predict_8x8)  (const NEW_GMC_DATA * const This,
                    byte *uDst, const byte *uSrc,
                    byte *vDst, const byte *vSrc,
                    int dststride, int srcstride, int x, int y, int rounding);
   void (*get_average_mv)(const NEW_GMC_DATA * const Dsp, VECTOR * const mv,
                     int x, int y, int qpel);

   NEW_GMC_DATA(){
      MemSet(this, 0, sizeof(NEW_GMC_DATA));
   }
};

//----------------------------

struct IMAGE: public C_xvid_image{
private:
   void draw_num(const int stride, const int height, const char * font, const int x, const int y);
public:
   void Print(int edged_width, int height, int x, int y, const char *fmt);
   void Swap(IMAGE *image2);
   void Copy(const IMAGE * image2, dword edged_width, dword height);
   void Clear(int width, int height, int edged_width, int y, int u, int v);
   void deblock_rrv(int edged_width, const struct MACROBLOCK * mbs, int mb_width, int mb_height, int mb_stride, int block, int flags);

   inline void Null(){
      y = u = v = 0;
   }
};

//----------------------------

struct Bitstream{
   dword bufa;
   dword bufb;
   dword buf;
   dword pos;                //bit position in currently cached 2 dwords (0-31)
   dword *tail;
   dword *start;
   dword length;
   dword initpos;

   void Init(const void *bitstream, dword length);
   dword ShowBits(dword bits);
   void get_matrix(byte *matrix);
   void Skip(dword bits);

//----------------------------
// number of bits to next byte alignment
   inline dword NumBitsToByteAlign() const{
      dword n = (32 - pos) & 7;
      return n == 0 ? 8 : n;
   }
   dword ShowBitsFromByteAlign(int bits);

//----------------------------
// move forward to the next byte boundary
   void ByteAlign(){
      dword remainder = pos & 7;
      if (remainder) {
         Skip(8 - remainder);
      }
   }

//----------------------------
// bitstream length (unit bits)
   inline dword Pos() const{
      return((dword)(8*((dword)tail - (dword)start) + pos - initpos));
   }

   dword GetBits(const dword n);

//----------------------------
// read single bit from bitstream
   inline dword GetBit(){
      return GetBits(1);
   }

//----------------------------

   int GetMcbpcInter();
   int GetCbpy(int intra);
   int GetMoveVector(int fcode);

//----------------------------

   int check_resync_marker(int addbits);
   int bs_get_spritetrajectory();
   int get_mcbpc_intra();
   int get_dc_dif(dword dc_size);
   int get_dc_size_lum();
   int get_dc_size_chrom();
};


#define MBPRED_SIZE  15


struct MACROBLOCK{
   /* decoder/encoder */
   VECTOR mvs[4];

   int pred_values[6][MBPRED_SIZE];
   int acpred_directions[6];

   int mode;
   int quant;              /* absolute quant */

   int field_dct;
   int field_pred;
   int field_for_top;
   int field_for_bot;

   /* encoder specific */

   VECTOR mv16;
   VECTOR pmvs[4];
   VECTOR qmvs[4];            /* mvs in quarter pixel resolution */

   int sad8[4];        /* SAD values for inter4v-VECTORs */
   int sad16;          /* SAD value for inter-VECTOR */

   int dquant;
   int cbp;

   /* bframe stuff */

   VECTOR b_mvs[4];
   VECTOR b_qmvs[4];

   int mb_type;

   /*
    * stuff for block based ME (needed for Qpel ME)
    * backup of last integer ME vectors/sad
    */

   VECTOR amv; /* average motion vectors from GMC  */
   int mcsel;

/* This structure has become way to big! What to do? Split it up?   */

};

//----------------------------

inline dword log2bin(dword value){
   int n = 0;

   while (value) {
      value >>= 1;
      n++;
   }
   return n;
}

//----------------------------

/* useful macros */

#define MIN(X, Y) ((X)<(Y)?(X):(Y))
#define MAX(X, Y) ((X)>(Y)?(X):(Y))
#define ABS(X)    (((X)>0)?(X):-(X))
#define SIGN(X)   (((X)>0)?1:-1)
#define CLIP(X,AMIN,AMAX)   (((X)<(AMIN)) ? (AMIN) : ((X)>(AMAX)) ? (AMAX) : (X))

#endif                     /* _GLOBAL_H_ */
