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