00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 #ifndef FRAMES_INCLUDED
00094 #define FRAMES_INCLUDED
00095 
00096 
00097 
00098 
00099 
00100 #include "ansi.h"
00101 #include "mtypes.h"
00102 #include "mheaders.h"
00103 #include "frame.h"
00104 
00105 
00106 
00107 
00108 
00109 
00110 #define I_FRAME 1
00111 #define P_FRAME 2
00112 #define B_FRAME 3
00113 
00114 #define LUM_BLOCK   0
00115 #define CHROM_BLOCK 1
00116 #define CR_BLOCK    2
00117 #define CB_BLOCK    3
00118 
00119 #define MOTION_FORWARD      0
00120 #define MOTION_BACKWARD     1
00121 #define MOTION_INTERPOLATE  2
00122 
00123 
00124 #define USE_HALF    0
00125 #define USE_FULL    1
00126 
00127     
00128 #define FORW_F_CODE fCode           
00129 #define BACK_F_CODE fCode
00130 #define FORW_F  (1 << (FORW_F_CODE - 1))
00131 #define BACK_F  (1 << (BACK_F_CODE - 1))
00132 #define RANGE_NEG       (-(1 << (3 + FORW_F_CODE)))
00133 #define RANGE_POS       ((1 << (3 + FORW_F_CODE))-1)
00134 #define MODULUS         (1 << (4 + FORW_F_CODE))
00135 
00136 #define ORIGINAL_FRAME  0
00137 #define DECODED_FRAME   1
00138 
00139 
00140 
00141 
00142 
00143 
00144 typedef struct FrameTableStruct {
00145     
00146     
00147     char typ;
00148     struct FrameTableStruct *next;
00149     struct FrameTableStruct *prev;
00150 
00151     
00152     struct FrameTableStruct *nextOutput;
00153 
00154     boolean     freeNow;        
00155 
00156     int number;
00157 
00158     int bFrameNumber;           
00159     
00160 } FrameTable;
00161 
00162 
00163 
00164 
00165 
00166 
00167 typedef struct dct_data_tye_struct {
00168   char useMotion;
00169   char pattern, mode;
00170   int fmotionX, fmotionY, bmotionX, bmotionY;
00171 } dct_data_type;
00172 
00173 void    EncodeYDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb));
00174 void EncodeCDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb));
00175 
00176 
00177 
00178 
00179 
00180 
00181 #define FRAME_TYPE(num)     framePattern[num % framePatternLen]
00182 
00183 
00184 #define int_ceil_div(a,b,c)     ((b*(c = a/b) < a) ? (c+1) : c)
00185 #define int_floor_div(a,b,c)    ((b*(c = a/b) > a) ? (c-1) : c)
00186 
00187 
00188 
00189 
00190 
00191 
00192 #define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) {                   \
00193         boolean overflow, overflowChange=FALSE;                             \
00194         int overflowValue = 0;                                              \
00195         do {                                                                \
00196           overflow =  Mpost_QuantZigBlock(dct[y][x], fb[0],                 \
00197                          qscale, TRUE)==MPOST_OVERFLOW;                     \
00198           overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1],               \
00199                          qscale, TRUE)==MPOST_OVERFLOW;                     \
00200           overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2],               \
00201                          qscale, TRUE)==MPOST_OVERFLOW;                     \
00202           overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3],             \
00203                          qscale, TRUE)==MPOST_OVERFLOW;                     \
00204           overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1],             \
00205                          fb[4], qscale, TRUE)==MPOST_OVERFLOW;              \
00206           overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1],             \
00207                          fb[5], qscale, TRUE)==MPOST_OVERFLOW;              \
00208           if ((overflow) && (qscale!=31)) {                                 \
00209            overflowChange = TRUE; overflowValue++;                          \
00210            qscale++;                                                        \
00211            } else overflow = FALSE;                                         \
00212         } while (overflow);                                                 \
00213         Mhead_GenMBHeader(bb,                                               \
00214                     frameType , mbAI ,   \
00215                     qscale ,                                   \
00216                     0 , 0 ,               \
00217                     0 , 0 ,              \
00218                     0 , 0 ,              \
00219                     0 , 0 ,              \
00220                     0 , 0 ,               \
00221                     0 , 0 ,              \
00222                     0 , TRUE );               \
00223                                                                             \
00224                                                               \
00225         EncodeYDC(fb[0][0], &y_dc_pred, bb);                                \
00226         Mpost_RLEHuffIBlock(fb[0], bb);                                     \
00227         EncodeYDC(fb[1][0], &y_dc_pred, bb);                                \
00228         Mpost_RLEHuffIBlock(fb[1], bb);                                     \
00229         EncodeYDC(fb[2][0], &y_dc_pred, bb);                                \
00230         Mpost_RLEHuffIBlock(fb[2], bb);                                     \
00231         EncodeYDC(fb[3][0], &y_dc_pred, bb);                                \
00232         Mpost_RLEHuffIBlock(fb[3], bb);                                     \
00233                                                                             \
00234                                                               \
00235         EncodeCDC(fb[4][0], &cb_dc_pred, bb);                               \
00236         Mpost_RLEHuffIBlock(fb[4], bb);                                     \
00237                                                                             \
00238                                                               \
00239         EncodeCDC(fb[5][0], &cr_dc_pred, bb);                               \
00240         Mpost_RLEHuffIBlock(fb[5], bb);                                     \
00241         if (overflowChange) qscale -= overflowValue;                        \
00242     }
00243 
00244 #define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) {    \
00245         x1 = (bx1)*DCTSIZE;                         \
00246         x2 = (bx2)*DCTSIZE;                         \
00247     }
00248 
00249 #define MOTION_TO_FRAME_COORD(bx1, bx2, mx1, mx2, x1, x2) { \
00250         x1 = (bx1)*DCTSIZE+(mx1);                           \
00251         x2 = (bx2)*DCTSIZE+(mx2);                           \
00252     }
00253 
00254 #define COORD_IN_FRAME(fy,fx, type)                                     \
00255     ((type == LUM_BLOCK) ?                                              \
00256      ((fy >= 0) && (fx >= 0) && (fy < Fsize_y) && (fx < Fsize_x)) :     \
00257      ((fy >= 0) && (fx >= 0) && (fy < (Fsize_y>>1)) && (fx < (Fsize_x>>1))))
00258 
00259 #define ENCODE_MOTION_VECTOR(x,y,xq, yq, xr, yr, f) {                   \
00260         int     tempC;                                                  \
00261                                                                         \
00262         if ( x < RANGE_NEG )        tempX = x + MODULUS;                \
00263         else if ( x > RANGE_POS ) tempX = x - MODULUS;                  \
00264         else                                tempX = x;                  \
00265                                                                         \
00266         if ( y < RANGE_NEG )        tempY = y + MODULUS;                \
00267         else if ( y > RANGE_POS ) tempY = y - MODULUS;                  \
00268         else                                tempY = y;                  \
00269                                                                         \
00270         if ( tempX >= 0 ) {                                             \
00271             xq = int_ceil_div(tempX, f, tempC);                         \
00272             xr = f - 1 + tempX - xq*f;                                  \
00273         } else {                                                        \
00274             xq = int_floor_div(tempX, f, tempC);                        \
00275             xr = f - 1 - tempX + xq*f;                                  \
00276         }                                                               \
00277                                                                         \
00278         if ( tempY >= 0 ) {                                             \
00279             yq = int_ceil_div(tempY, f, tempC);                         \
00280             yr = f - 1 + tempY - yq*f;                                  \
00281         } else {                                                        \
00282             yq = int_floor_div(tempY, f, tempC);                        \
00283             yr = f - 1 - tempY + yq*f;                                  \
00284         }                                                               \
00285     }
00286 
00287 
00288 #define DoQuant(bit, src, dest)                                         \
00289   if (pattern & bit) {                                                  \
00290     switch (Mpost_QuantZigBlock(src, dest, QScale, FALSE)) {            \
00291     case MPOST_NON_ZERO:                                                \
00292       break;                                                            \
00293     case MPOST_ZERO:                                                    \
00294       pattern ^= bit;                                                   \
00295       break;                                                            \
00296     case MPOST_OVERFLOW:                                                \
00297       if (QScale != 31) {                                               \
00298         QScale++;                                                       \
00299         overflowChange = TRUE;                                          \
00300         overflowValue++;                                                \
00301         goto calc_blocks;                                               \
00302       }                                                                 \
00303       break;                                                            \
00304     }                                                                   \
00305   }
00306 
00307 
00308 
00309 
00310 
00311 void    ComputeBMotionLumBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next,
00312                                int by, int bx, int mode, int fmy, int fmx,
00313                                int bmy, int bmx, LumBlock motionBlock));
00314 int     BMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, MpegFrame *next,
00315                       int by, int bx, int *fmy, int *fmx, int *bmy, int *bmx, int oldMode));
00316 
00317 
00318 void    ComputeDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, int by, int bx,
00319                         int my, int mx, int *pattern));
00320 int     ComputeDiffDCTBlock _ANSI_ARGS_((Block current, Block dest, Block motionBlock));
00321 void    ComputeMotionBlock _ANSI_ARGS_((uint8 **prev, int by, int bx, int my, int mx,
00322                            Block motionBlock));
00323 void    ComputeMotionLumBlock _ANSI_ARGS_((MpegFrame *prevFrame, int by,
00324                                            int bx, int my, int mx,
00325                                            LumBlock motionBlock));
00326 int32   ComputeBlockMAD _ANSI_ARGS_((Block current, Block prev));
00327 
00328 void    GenIFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *mf));
00329 void    GenPFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *current, MpegFrame *prev));
00330 void    GenBFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *curr, MpegFrame *prev, MpegFrame *next));
00331 void    AllocDctBlocks _ANSI_ARGS_((void ));
00332 
00333 float   ShowIFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer));
00334 float   ShowPFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer));
00335 float   ShowBFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer));
00336 
00337 
00338 
00339 
00340 int32    LumBlockMAD _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar));
00341 int32    LumBlockMSE _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar));
00342 int32   LumMotionError _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
00343                                     int by, int bx, int my, int mx,
00344                                     int32 bestSoFar));
00345 int32   LumAddMotionError _ANSI_ARGS_((LumBlock currentBlock,
00346                                        LumBlock blockSoFar, MpegFrame *prev,
00347                                        int by, int bx, int my, int mx,
00348                                        int32 bestSoFar));
00349 int32   LumMotionErrorA _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,
00350                                      int by, int bx, int my, int mx,
00351                                      int32 bestSoFar));
00352 int32   LumMotionErrorB _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,
00353                                      int by, int bx, int my, int mx,
00354                                      int32 bestSoFar));
00355 int32   LumMotionErrorC _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,
00356                                      int by, int bx, int my, int mx,
00357                                      int32 bestSoFar));
00358 int32   LumMotionErrorD _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame,
00359                                      int by, int bx, int my, int mx,
00360                                      int32 bestSoFar));
00361 int32   LumMotionErrorSubSampled _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prevFrame,
00362                           int by, int bx, int my, int mx,
00363                           int startY, int startX));
00364 void    BlockComputeSNR _ANSI_ARGS_((MpegFrame *current,
00365                                 float *snr, float *psnr));
00366 int32   time_elapsed _ANSI_ARGS_((void));
00367 void    AllocDctBlocks _ANSI_ARGS_((void));
00368 
00369 
00370 
00371 
00372 
00373 extern int pixelFullSearch;
00374 extern int searchRangeP,searchRangeB;
00375 extern int qscaleI;
00376 extern int gopSize;
00377 extern int slicesPerFrame;
00378 extern int blocksPerSlice;
00379 extern int referenceFrame;
00380 extern int specificsOn;
00381 extern int quietTime;           
00382 
00383 
00384 extern boolean realQuiet;       
00385 
00386 extern boolean frameSummary;    
00387 extern boolean  printSNR;
00388 extern boolean  printMSE;
00389 extern boolean  decodeRefFrames;    
00390 extern int      fCodeI,fCodeP,fCodeB;
00391 extern boolean    forceEncodeLast;
00392 extern int TIME_RATE;
00393 
00394 #endif