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 */ |