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