1 /*===========================================================================* 2 * frames.h * 3 * * 4 * stuff dealing with frames * 5 * * 6 *===========================================================================*/ 7 8 /* 9 * Copyright (c) 1995 The Regents of the University of California. 10 * All rights reserved. 11 * 12 * Permission to use, copy, modify, and distribute this software and its 13 * documentation for any purpose, without fee, and without written agreement is 14 * hereby granted, provided that the above copyright notice and the following 15 * two paragraphs appear in all copies of this software. 16 * 17 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR 18 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT 19 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF 20 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 * 22 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 24 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 25 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO 26 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 27 */ 28 29 /* 30 * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/headers/RCS/frames.h,v 1.13 1995/08/15 23:43:04 smoot Exp $ 31 * $Log: frames.h,v $ 32 * Revision 1.13 1995/08/15 23:43:04 smoot 33 * *** empty log message *** 34 * 35 * Revision 1.12 1995/04/14 23:13:18 smoot 36 * Reorganized for better rate control. Added overflow in DCT values 37 * handling. 38 * 39 * Revision 1.11 1995/01/19 23:54:46 smoot 40 * allow computediffdcts to un-assert parts of the pattern 41 * 42 * Revision 1.10 1995/01/16 07:43:10 eyhung 43 * Added realQuiet 44 * 45 * Revision 1.9 1995/01/10 23:15:28 smoot 46 * Fixed searchRange lack of def 47 * 48 * Revision 1.8 1994/11/15 00:55:36 smoot 49 * added printMSE 50 * 51 * Revision 1.7 1994/11/14 22:51:02 smoot 52 * added specifics flag. Added BlockComputeSNR parameters 53 * 54 * Revision 1.6 1994/11/01 05:07:23 darryl 55 * with rate control changes added 56 * 57 * Revision 1.1 1994/09/27 01:02:55 darryl 58 * Initial revision 59 * 60 * Revision 1.5 1993/07/22 22:24:23 keving 61 * nothing 62 * 63 * Revision 1.4 1993/07/09 00:17:23 keving 64 * nothing 65 * 66 * Revision 1.3 1993/06/03 21:08:53 keving 67 * nothing 68 * 69 * Revision 1.2 1993/03/02 19:00:27 keving 70 * nothing 71 * 72 * Revision 1.1 1993/02/19 20:15:51 keving 73 * nothing 74 * 75 */ 76 77 78 #ifndef FRAMES_INCLUDED 79 #define FRAMES_INCLUDED 80 81 /*==============* 82 * HEADER FILES * 83 *==============*/ 84 85 #include "ansi.h" 86 #include "mtypes.h" 87 #include "mheaders.h" 88 #include "frame.h" 89 90 91 /*===========* 92 * CONSTANTS * 93 *===========*/ 94 95 #define I_FRAME 1 96 #define P_FRAME 2 97 #define B_FRAME 3 98 99 #define LUM_BLOCK 0 100 #define CHROM_BLOCK 1 101 #define CR_BLOCK 2 102 #define CB_BLOCK 3 103 104 #define MOTION_FORWARD 0 105 #define MOTION_BACKWARD 1 106 #define MOTION_INTERPOLATE 2 107 108 109 #define USE_HALF 0 110 #define USE_FULL 1 111 112 /* motion vector stuff */ 113 #define FORW_F_CODE fCode /* from picture header */ 114 #define BACK_F_CODE fCode 115 #define FORW_F (1 << (FORW_F_CODE - 1)) 116 #define BACK_F (1 << (BACK_F_CODE - 1)) 117 #define RANGE_NEG (-(1 << (3 + FORW_F_CODE))) 118 #define RANGE_POS ((1 << (3 + FORW_F_CODE))-1) 119 #define MODULUS (1 << (4 + FORW_F_CODE)) 120 121 #define ORIGINAL_FRAME 0 122 #define DECODED_FRAME 1 123 124 125 /*=======================* 126 * STRUCTURE DEFINITIONS * 127 *=======================*/ 128 129 typedef struct FrameTableStruct { 130 /* the following are all initted once and never changed */ 131 /* (they depend only on the pattern */ 132 char typ; 133 struct FrameTableStruct *next; 134 struct FrameTableStruct *prev; 135 136 /* nextOutput is a pointer to next frame table entry to output */ 137 struct FrameTableStruct *nextOutput; 138 139 boolean freeNow; /* TRUE iff no frames point back to this */ 140 141 int number; 142 143 int bFrameNumber; /* actual frame number, if a b-frame */ 144 145 } FrameTable; 146 147 148 /*==================* 149 * TYPE DEFINITIONS * 150 *==================*/ 151 152 typedef struct dct_data_tye_struct { 153 char useMotion; 154 char pattern, mode; 155 int fmotionX, fmotionY, bmotionX, bmotionY; 156 } dct_data_type; 157 158 void EncodeYDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb)); 159 void EncodeCDC _ANSI_ARGS_((int32 dc_term, int32 *pred_term, BitBucket *bb)); 160 161 162 /*========* 163 * MACROS * 164 *========*/ 165 166 #define FRAME_TYPE(num) framePattern[num % framePatternLen] 167 168 /* return ceiling(a/b) where a, b are ints, using temp value c */ 169 #define int_ceil_div(a,b,c) ((b*(c = a/b) < a) ? (c+1) : c) 170 #define int_floor_div(a,b,c) ((b*(c = a/b) > a) ? (c-1) : c) 171 172 /* assumes many things: 173 * block indices are (y,x) 174 * variables y_dc_pred, cr_dc_pred, and cb_dc_pred 175 * flat block fb exists 176 */ 177 #define GEN_I_BLOCK(frameType, frame, bb, mbAI, qscale) { \ 178 boolean overflow, overflowChange=FALSE; \ 179 int overflowValue = 0; \ 180 do { \ 181 overflow = Mpost_QuantZigBlock(dct[y][x], fb[0], \ 182 qscale, TRUE)==MPOST_OVERFLOW; \ 183 overflow |= Mpost_QuantZigBlock(dct[y][x+1], fb[1], \ 184 qscale, TRUE)==MPOST_OVERFLOW; \ 185 overflow |= Mpost_QuantZigBlock(dct[y+1][x], fb[2], \ 186 qscale, TRUE)==MPOST_OVERFLOW; \ 187 overflow |= Mpost_QuantZigBlock(dct[y+1][x+1], fb[3], \ 188 qscale, TRUE)==MPOST_OVERFLOW; \ 189 overflow |= Mpost_QuantZigBlock(dctb[y >> 1][x >> 1], \ 190 fb[4], qscale, TRUE)==MPOST_OVERFLOW; \ 191 overflow |= Mpost_QuantZigBlock(dctr[y >> 1][x >> 1], \ 192 fb[5], qscale, TRUE)==MPOST_OVERFLOW; \ 193 if ((overflow) && (qscale!=31)) { \ 194 overflowChange = TRUE; overflowValue++; \ 195 qscale++; \ 196 } else overflow = FALSE; \ 197 } while (overflow); \ 198 Mhead_GenMBHeader(bb, \ 199 frameType /* pict_code_type */, mbAI /* addr_incr */, \ 200 qscale /* q_scale */, \ 201 0 /* forw_f_code */, 0 /* back_f_code */, \ 202 0 /* horiz_forw_r */, 0 /* vert_forw_r */, \ 203 0 /* horiz_back_r */, 0 /* vert_back_r */, \ 204 0 /* motion_forw */, 0 /* m_horiz_forw */, \ 205 0 /* m_vert_forw */, 0 /* motion_back */, \ 206 0 /* m_horiz_back */, 0 /* m_vert_back */, \ 207 0 /* mb_pattern */, TRUE /* mb_intra */); \ 208 \ 209 /* Y blocks */ \ 210 EncodeYDC(fb[0][0], &y_dc_pred, bb); \ 211 Mpost_RLEHuffIBlock(fb[0], bb); \ 212 EncodeYDC(fb[1][0], &y_dc_pred, bb); \ 213 Mpost_RLEHuffIBlock(fb[1], bb); \ 214 EncodeYDC(fb[2][0], &y_dc_pred, bb); \ 215 Mpost_RLEHuffIBlock(fb[2], bb); \ 216 EncodeYDC(fb[3][0], &y_dc_pred, bb); \ 217 Mpost_RLEHuffIBlock(fb[3], bb); \ 218 \ 219 /* CB block */ \ 220 EncodeCDC(fb[4][0], &cb_dc_pred, bb); \ 221 Mpost_RLEHuffIBlock(fb[4], bb); \ 222 \ 223 /* CR block */ \ 224 EncodeCDC(fb[5][0], &cr_dc_pred, bb); \ 225 Mpost_RLEHuffIBlock(fb[5], bb); \ 226 if (overflowChange) qscale -= overflowValue; \ 227 } 228 229 #define BLOCK_TO_FRAME_COORD(bx1, bx2, x1, x2) { \ 230 x1 = (bx1)*DCTSIZE; \ 231 x2 = (bx2)*DCTSIZE; \ 232 } 233 234 #define MOTION_TO_FRAME_COORD(bx1, bx2, mx1, mx2, x1, x2) { \ 235 x1 = (bx1)*DCTSIZE+(mx1); \ 236 x2 = (bx2)*DCTSIZE+(mx2); \ 237 } 238 239 #define COORD_IN_FRAME(fy,fx, type) \ 240 ((type == LUM_BLOCK) ? \ 241 ((fy >= 0) && (fx >= 0) && (fy < Fsize_y) && (fx < Fsize_x)) : \ 242 ((fy >= 0) && (fx >= 0) && (fy < (Fsize_y>>1)) && (fx < (Fsize_x>>1)))) 243 244 #define ENCODE_MOTION_VECTOR(x,y,xq, yq, xr, yr, f) { \ 245 int tempC; \ 246 \ 247 if ( x < RANGE_NEG ) tempX = x + MODULUS; \ 248 else if ( x > RANGE_POS ) tempX = x - MODULUS; \ 249 else tempX = x; \ 250 \ 251 if ( y < RANGE_NEG ) tempY = y + MODULUS; \ 252 else if ( y > RANGE_POS ) tempY = y - MODULUS; \ 253 else tempY = y; \ 254 \ 255 if ( tempX >= 0 ) { \ 256 xq = int_ceil_div(tempX, f, tempC); \ 257 xr = f - 1 + tempX - xq*f; \ 258 } else { \ 259 xq = int_floor_div(tempX, f, tempC); \ 260 xr = f - 1 - tempX + xq*f; \ 261 } \ 262 \ 263 if ( tempY >= 0 ) { \ 264 yq = int_ceil_div(tempY, f, tempC); \ 265 yr = f - 1 + tempY - yq*f; \ 266 } else { \ 267 yq = int_floor_div(tempY, f, tempC); \ 268 yr = f - 1 - tempY + yq*f; \ 269 } \ 270 } 271 272 273 #define DoQuant(bit, src, dest) \ 274 if (pattern & bit) { \ 275 switch (Mpost_QuantZigBlock(src, dest, QScale, FALSE)) { \ 276 case MPOST_NON_ZERO: \ 277 break; \ 278 case MPOST_ZERO: \ 279 pattern ^= bit; \ 280 break; \ 281 case MPOST_OVERFLOW: \ 282 if (QScale != 31) { \ 283 QScale++; \ 284 overflowChange = TRUE; \ 285 overflowValue++; \ 286 goto calc_blocks; \ 287 } \ 288 break; \ 289 } \ 290 } 291 292 /*===============================* 293 * EXTERNAL PROCEDURE prototypes * 294 *===============================*/ 295 296 void ComputeBMotionLumBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next, 297 int by, int bx, int mode, int fmy, int fmx, 298 int bmy, int bmx, LumBlock motionBlock)); 299 int BMotionSearch _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, MpegFrame *next, 300 int by, int bx, int *fmy, int *fmx, int *bmy, int *bmx, int oldMode)); 301 302 303 void ComputeDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, int by, int bx, 304 int my, int mx, int *pattern)); 305 int ComputeDiffDCTBlock _ANSI_ARGS_((Block current, Block dest, Block motionBlock)); 306 void ComputeMotionBlock _ANSI_ARGS_((uint8 **prev, int by, int bx, int my, int mx, 307 Block motionBlock)); 308 void ComputeMotionLumBlock _ANSI_ARGS_((MpegFrame *prevFrame, int by, 309 int bx, int my, int mx, 310 LumBlock motionBlock)); 311 int32 ComputeBlockMAD _ANSI_ARGS_((Block current, Block prev)); 312 313 void GenIFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *mf)); 314 void GenPFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *current, MpegFrame *prev)); 315 void GenBFrame _ANSI_ARGS_((BitBucket *bb, MpegFrame *curr, MpegFrame *prev, MpegFrame *next)); 316 void AllocDctBlocks _ANSI_ARGS_((void )); 317 318 float ShowIFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer)); 319 float ShowPFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer)); 320 float ShowBFrameSummary _ANSI_ARGS_((int inputFrameBits, int32 totalBits, FILE *fpointer)); 321 322 323 /* DIFFERENCE FUNCTIONS */ 324 325 int32 LumBlockMAD _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar)); 326 int32 LumBlockMSE _ANSI_ARGS_((LumBlock currentBlock, LumBlock motionBlock, int32 bestSoFar)); 327 int32 LumMotionError _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev, 328 int by, int bx, int my, int mx, 329 int32 bestSoFar)); 330 int32 LumAddMotionError _ANSI_ARGS_((LumBlock currentBlock, 331 LumBlock blockSoFar, MpegFrame *prev, 332 int by, int bx, int my, int mx, 333 int32 bestSoFar)); 334 int32 LumMotionErrorA _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, 335 int by, int bx, int my, int mx, 336 int32 bestSoFar)); 337 int32 LumMotionErrorB _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, 338 int by, int bx, int my, int mx, 339 int32 bestSoFar)); 340 int32 LumMotionErrorC _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, 341 int by, int bx, int my, int mx, 342 int32 bestSoFar)); 343 int32 LumMotionErrorD _ANSI_ARGS_((LumBlock current, MpegFrame *prevFrame, 344 int by, int bx, int my, int mx, 345 int32 bestSoFar)); 346 int32 LumMotionErrorSubSampled _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prevFrame, 347 int by, int bx, int my, int mx, 348 int startY, int startX)); 349 void BlockComputeSNR _ANSI_ARGS_((MpegFrame *current, 350 float *snr, float *psnr)); 351 int32 time_elapsed _ANSI_ARGS_((void)); 352 void AllocDctBlocks _ANSI_ARGS_((void)); 353 354 /*==================* 355 * GLOBAL VARIABLES * 356 *==================*/ 357 358 extern int pixelFullSearch; 359 extern int searchRangeP,searchRangeB; 360 extern int qscaleI; 361 extern int gopSize; 362 extern int slicesPerFrame; 363 extern int blocksPerSlice; 364 extern int referenceFrame; 365 extern int specificsOn; 366 extern int quietTime; /* shut up for at least quietTime seconds; 367 * negative means shut up forever 368 */ 369 extern boolean realQuiet; /* TRUE = no messages to stdout */ 370 371 extern boolean frameSummary; /* TRUE = frame summaries should be printed */ 372 extern boolean printSNR; 373 extern boolean printMSE; 374 extern boolean decodeRefFrames; /* TRUE = should decode I and P frames */ 375 extern int fCodeI,fCodeP,fCodeB; 376 extern boolean forceEncodeLast; 377 extern int TIME_RATE; 378 379 #endif /* FRAMES_INCLUDED */ 380