1 |
/*===========================================================================* |
2 |
* block.c * |
3 |
* * |
4 |
* Block routines * |
5 |
* * |
6 |
* EXPORTED PROCEDURES: * |
7 |
* ComputeDiffDCTBlock * |
8 |
* ComputeDiffDCTs * |
9 |
* ComputeMotionBlock * |
10 |
* ComputeMotionLumBlock * |
11 |
* LumBlockMAD * |
12 |
* LumMotionError * |
13 |
* LumMotionErrorSubSampled * |
14 |
* LumAddMotionError * |
15 |
* AddMotionBlock * |
16 |
* BlockToData * |
17 |
* BlockifyFrame * |
18 |
* * |
19 |
* NOTES: MAD = Mean Absolute Difference * |
20 |
* * |
21 |
*===========================================================================*/ |
22 |
|
23 |
/* |
24 |
* Copyright (c) 1995 The Regents of the University of California. |
25 |
* All rights reserved. |
26 |
* |
27 |
* Permission to use, copy, modify, and distribute this software and its |
28 |
* documentation for any purpose, without fee, and without written agreement is |
29 |
* hereby granted, provided that the above copyright notice and the following |
30 |
* two paragraphs appear in all copies of this software. |
31 |
* |
32 |
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
33 |
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
34 |
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
35 |
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 |
* |
37 |
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
38 |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
39 |
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
40 |
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO |
41 |
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
42 |
*/ |
43 |
|
44 |
/* |
45 |
* $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/block.c,v 1.16 1995/08/07 21:43:29 smoot Exp $ |
46 |
* $Log: block.c,v $ |
47 |
* Revision 1.16 1995/08/07 21:43:29 smoot |
48 |
* restructured lumdiff so it read better and used a switch instead of ifs |
49 |
* |
50 |
* Revision 1.15 1995/06/21 22:21:16 smoot |
51 |
* added TUNEing options |
52 |
* |
53 |
* Revision 1.14 1995/05/08 22:47:45 smoot |
54 |
* typechecking better |
55 |
* |
56 |
* Revision 1.13 1995/05/08 22:44:14 smoot |
57 |
* added prototypes (postdct.h) |
58 |
* |
59 |
* Revision 1.12 1995/05/02 21:44:07 smoot |
60 |
* added tuneing parameters |
61 |
* |
62 |
* Revision 1.11 1995/03/31 23:50:45 smoot |
63 |
* removed block bound (moved to opts.c) |
64 |
* |
65 |
* Revision 1.10 1995/03/29 20:12:39 smoot |
66 |
* added block_bound for TUNEing |
67 |
* |
68 |
* Revision 1.9 1995/02/01 21:43:55 smoot |
69 |
* cleanup |
70 |
* |
71 |
* Revision 1.8 1995/01/19 23:52:43 smoot |
72 |
* Made computeDiffDCTs able to rule out changes to the pattern (diff too small) |
73 |
* |
74 |
* Revision 1.7 1995/01/19 23:07:17 eyhung |
75 |
* Changed copyrights |
76 |
* |
77 |
* Revision 1.6 1994/11/12 02:11:44 keving |
78 |
* nothing |
79 |
* |
80 |
* Revision 1.5 1993/12/22 19:19:01 keving |
81 |
* nothing |
82 |
* |
83 |
* Revision 1.5 1993/12/22 19:19:01 keving |
84 |
* nothing |
85 |
* |
86 |
* Revision 1.4 1993/07/22 22:23:43 keving |
87 |
* nothing |
88 |
* |
89 |
* Revision 1.3 1993/06/30 20:06:09 keving |
90 |
* nothing |
91 |
* |
92 |
* Revision 1.2 1993/06/03 21:08:08 keving |
93 |
* nothing |
94 |
* |
95 |
* Revision 1.1 1993/04/08 21:31:59 keving |
96 |
* nothing |
97 |
* |
98 |
*/ |
99 |
|
100 |
|
101 |
/*==============* |
102 |
* HEADER FILES * |
103 |
*==============*/ |
104 |
|
105 |
#include "all.h" |
106 |
#include "mtypes.h" |
107 |
#include "frames.h" |
108 |
#include "bitio.h" |
109 |
#include "prototypes.h" |
110 |
#include "fsize.h" |
111 |
#include "opts.h" |
112 |
#include "postdct.h" |
113 |
|
114 |
#undef ABS |
115 |
#define ABS(x) ((x < 0) ? (-x) : x) |
116 |
|
117 |
#define TRUNCATE_UINT8(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) |
118 |
|
119 |
/*==================* |
120 |
* GLOBAL VARIABLES * |
121 |
*==================*/ |
122 |
|
123 |
|
124 |
extern Block **dct, **dctb, **dctr; |
125 |
|
126 |
/*===========================* |
127 |
* COMPUTE DCT OF DIFFERENCE * |
128 |
*===========================*/ |
129 |
|
130 |
/*===========================================================================* |
131 |
* |
132 |
* ComputeDiffDCTBlock |
133 |
* |
134 |
* compute current-motionBlock, take the DCT, and put the difference |
135 |
* back into current |
136 |
* |
137 |
* RETURNS: current block modified |
138 |
* |
139 |
* SIDE EFFECTS: none |
140 |
* |
141 |
*===========================================================================*/ |
142 |
boolean |
143 |
ComputeDiffDCTBlock(current, dest, motionBlock) |
144 |
Block current, dest, motionBlock; |
145 |
{ |
146 |
register int x, y, diff = 0; |
147 |
|
148 |
for ( y = 0; y < 8; y++ ) { |
149 |
for ( x = 0; x < 8; x++ ) { |
150 |
current[y][x] -= motionBlock[y][x]; |
151 |
diff += ABS(current[y][x]); |
152 |
} |
153 |
} |
154 |
/* Kill the block if change is too small */ |
155 |
/* (block_bound defaults to 128, see opts.c) */ |
156 |
if (diff < block_bound) return FALSE; |
157 |
|
158 |
mp_fwd_dct_block2(current, dest); |
159 |
|
160 |
return TRUE; |
161 |
} |
162 |
|
163 |
/*===========================================================================* |
164 |
* |
165 |
* ComputeDiffDCTs |
166 |
* |
167 |
* appropriate (according to pattern, the coded block pattern) blocks |
168 |
* of 'current' are diff'ed and DCT'd. |
169 |
* |
170 |
* RETURNS: current blocks modified |
171 |
* |
172 |
* SIDE EFFECTS: Can remove too-small difference blocks from pattern |
173 |
* |
174 |
* PRECONDITIONS: appropriate blocks of 'current' have not yet been |
175 |
* modified |
176 |
* |
177 |
*===========================================================================*/ |
178 |
void |
179 |
ComputeDiffDCTs(current, prev, by, bx, my, mx, pattern) |
180 |
MpegFrame *current; |
181 |
MpegFrame *prev; |
182 |
int by; |
183 |
int bx; |
184 |
int my; |
185 |
int mx; |
186 |
int *pattern; |
187 |
{ |
188 |
Block motionBlock; |
189 |
|
190 |
if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); |
191 |
if ( *pattern & 0x20 ) { |
192 |
ComputeMotionBlock(prev->ref_y, by, bx, my, mx, motionBlock); |
193 |
if (!ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock)) |
194 |
*pattern^=0x20; |
195 |
} |
196 |
|
197 |
if ( *pattern & 0x10 ) { |
198 |
ComputeMotionBlock(prev->ref_y, by, bx+1, my, mx, motionBlock); |
199 |
if (!ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock)) |
200 |
*pattern^=0x10; |
201 |
} |
202 |
|
203 |
if ( *pattern & 0x8 ) { |
204 |
ComputeMotionBlock(prev->ref_y, by+1, bx, my, mx, motionBlock); |
205 |
if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock)) |
206 |
*pattern^=0x8; |
207 |
} |
208 |
|
209 |
if ( *pattern & 0x4 ) { |
210 |
ComputeMotionBlock(prev->ref_y, by+1, bx+1, my, mx, motionBlock); |
211 |
if (!ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock)) |
212 |
*pattern^=0x4; |
213 |
} |
214 |
|
215 |
if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n"); |
216 |
if ( *pattern & 0x2 ) { |
217 |
ComputeMotionBlock(prev->ref_cb, by >> 1, bx >> 1, my/2, mx/2, motionBlock); |
218 |
if (!ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock)) |
219 |
*pattern^=0x2; |
220 |
} |
221 |
|
222 |
if ( *pattern & 0x1 ) { |
223 |
ComputeMotionBlock(prev->ref_cr, by >> 1, bx >> 1, my/2, mx/2, motionBlock); |
224 |
if (!ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock)) |
225 |
*pattern^=0x1; |
226 |
} |
227 |
} |
228 |
|
229 |
|
230 |
/*======================* |
231 |
* COMPUTE MOTION BLOCK * |
232 |
*======================*/ |
233 |
|
234 |
/*===========================================================================* |
235 |
* |
236 |
* ComputeMotionBlock |
237 |
* |
238 |
* compute the motion-compensated block |
239 |
* |
240 |
* RETURNS: motionBlock |
241 |
* |
242 |
* SIDE EFFECTS: none |
243 |
* |
244 |
* PRECONDITIONS: motion vector MUST be valid |
245 |
* |
246 |
* NOTE: could try to speed this up using halfX, halfY, halfBoth, |
247 |
* but then would have to compute for chrominance, and it's just |
248 |
* not worth the trouble (this procedure is not called relatively |
249 |
* often -- a constant number of times per macroblock) |
250 |
* |
251 |
*===========================================================================*/ |
252 |
void |
253 |
ComputeMotionBlock(prev, by, bx, my, mx, motionBlock) |
254 |
uint8 **prev; |
255 |
int by; |
256 |
int bx; |
257 |
int my; |
258 |
int mx; |
259 |
Block motionBlock; |
260 |
{ |
261 |
register int fy, fx; |
262 |
register int y; |
263 |
register int16 *destPtr; |
264 |
register uint8 *srcPtr; |
265 |
register uint8 *srcPtr2; |
266 |
boolean xHalf, yHalf; |
267 |
|
268 |
xHalf = (ABS(mx) % 2 == 1); |
269 |
yHalf = (ABS(my) % 2 == 1); |
270 |
|
271 |
MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx); |
272 |
|
273 |
if ( xHalf && yHalf ) { |
274 |
/* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and |
275 |
(fy-1)+y+1 = fy+y |
276 |
*/ |
277 |
if ( my < 0 ) { |
278 |
fy--; |
279 |
} |
280 |
if ( mx < 0 ) { |
281 |
fx--; |
282 |
} |
283 |
|
284 |
for ( y = 0; y < 8; y++ ) { |
285 |
destPtr = motionBlock[y]; |
286 |
srcPtr = &(prev[fy+y][fx]); |
287 |
srcPtr2 = &(prev[fy+y+1][fx]); |
288 |
|
289 |
destPtr[0] = (srcPtr[0]+srcPtr[1]+srcPtr2[0]+srcPtr2[1]+2)>>2; |
290 |
destPtr[1] = (srcPtr[1]+srcPtr[2]+srcPtr2[1]+srcPtr2[2]+2)>>2; |
291 |
destPtr[2] = (srcPtr[2]+srcPtr[3]+srcPtr2[2]+srcPtr2[3]+2)>>2; |
292 |
destPtr[3] = (srcPtr[3]+srcPtr[4]+srcPtr2[3]+srcPtr2[4]+2)>>2; |
293 |
destPtr[4] = (srcPtr[4]+srcPtr[5]+srcPtr2[4]+srcPtr2[5]+2)>>2; |
294 |
destPtr[5] = (srcPtr[5]+srcPtr[6]+srcPtr2[5]+srcPtr2[6]+2)>>2; |
295 |
destPtr[6] = (srcPtr[6]+srcPtr[7]+srcPtr2[6]+srcPtr2[7]+2)>>2; |
296 |
destPtr[7] = (srcPtr[7]+srcPtr[8]+srcPtr2[7]+srcPtr2[8]+2)>>2; |
297 |
} |
298 |
} else if ( xHalf ) { |
299 |
if ( mx < 0 ) { |
300 |
fx--; |
301 |
} |
302 |
|
303 |
for ( y = 0; y < 8; y++ ) { |
304 |
destPtr = motionBlock[y]; |
305 |
srcPtr = &(prev[fy+y][fx]); |
306 |
|
307 |
destPtr[0] = (srcPtr[0]+srcPtr[1]+1)>>1; |
308 |
destPtr[1] = (srcPtr[1]+srcPtr[2]+1)>>1; |
309 |
destPtr[2] = (srcPtr[2]+srcPtr[3]+1)>>1; |
310 |
destPtr[3] = (srcPtr[3]+srcPtr[4]+1)>>1; |
311 |
destPtr[4] = (srcPtr[4]+srcPtr[5]+1)>>1; |
312 |
destPtr[5] = (srcPtr[5]+srcPtr[6]+1)>>1; |
313 |
destPtr[6] = (srcPtr[6]+srcPtr[7]+1)>>1; |
314 |
destPtr[7] = (srcPtr[7]+srcPtr[8]+1)>>1; |
315 |
} |
316 |
} else if ( yHalf ) { |
317 |
if ( my < 0 ) { |
318 |
fy--; |
319 |
} |
320 |
|
321 |
for ( y = 0; y < 8; y++ ) { |
322 |
destPtr = motionBlock[y]; |
323 |
srcPtr = &(prev[fy+y][fx]); |
324 |
srcPtr2 = &(prev[fy+y+1][fx]); |
325 |
|
326 |
destPtr[0] = (srcPtr[0]+srcPtr2[0]+1)>>1; |
327 |
destPtr[1] = (srcPtr[1]+srcPtr2[1]+1)>>1; |
328 |
destPtr[2] = (srcPtr[2]+srcPtr2[2]+1)>>1; |
329 |
destPtr[3] = (srcPtr[3]+srcPtr2[3]+1)>>1; |
330 |
destPtr[4] = (srcPtr[4]+srcPtr2[4]+1)>>1; |
331 |
destPtr[5] = (srcPtr[5]+srcPtr2[5]+1)>>1; |
332 |
destPtr[6] = (srcPtr[6]+srcPtr2[6]+1)>>1; |
333 |
destPtr[7] = (srcPtr[7]+srcPtr2[7]+1)>>1; |
334 |
} |
335 |
} else { |
336 |
for ( y = 0; y < 8; y++ ) { |
337 |
destPtr = motionBlock[y]; |
338 |
srcPtr = &(prev[fy+y][fx]); |
339 |
|
340 |
destPtr[0] = (uint8) srcPtr[0]; |
341 |
destPtr[1] = (uint8) srcPtr[1]; |
342 |
destPtr[2] = (uint8) srcPtr[2]; |
343 |
destPtr[3] = (uint8) srcPtr[3]; |
344 |
destPtr[4] = (uint8) srcPtr[4]; |
345 |
destPtr[5] = (uint8) srcPtr[5]; |
346 |
destPtr[6] = (uint8) srcPtr[6]; |
347 |
destPtr[7] = (uint8) srcPtr[7]; |
348 |
} |
349 |
} |
350 |
} |
351 |
|
352 |
|
353 |
/*===========================================================================* |
354 |
* |
355 |
* ComputeMotionLumBlock |
356 |
* |
357 |
* compute the motion-compensated luminance block |
358 |
* |
359 |
* RETURNS: motionBlock |
360 |
* |
361 |
* SIDE EFFECTS: none |
362 |
* |
363 |
* PRECONDITIONS: motion vector MUST be valid |
364 |
* |
365 |
* NOTE: see ComputeMotionBlock |
366 |
* |
367 |
*===========================================================================*/ |
368 |
void |
369 |
ComputeMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock) |
370 |
MpegFrame *prevFrame; |
371 |
int by; |
372 |
int bx; |
373 |
int my; |
374 |
int mx; |
375 |
LumBlock motionBlock; |
376 |
{ |
377 |
register uint8 *across; |
378 |
register int32 *macross; |
379 |
register int y; |
380 |
uint8 **prev; |
381 |
int fy, fx; |
382 |
boolean xHalf, yHalf; |
383 |
|
384 |
xHalf = (ABS(mx) % 2 == 1); |
385 |
yHalf = (ABS(my) % 2 == 1); |
386 |
|
387 |
MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); |
388 |
|
389 |
if ( xHalf ) { |
390 |
if ( mx < 0 ) { |
391 |
fx--; |
392 |
} |
393 |
|
394 |
if ( yHalf ) { |
395 |
if ( my < 0 ) { |
396 |
fy--; |
397 |
} |
398 |
|
399 |
prev = prevFrame->halfBoth; |
400 |
} else { |
401 |
prev = prevFrame->halfX; |
402 |
} |
403 |
} else if ( yHalf ) { |
404 |
if ( my < 0 ) { |
405 |
fy--; |
406 |
} |
407 |
|
408 |
prev = prevFrame->halfY; |
409 |
} else { |
410 |
prev = prevFrame->ref_y; |
411 |
} |
412 |
|
413 |
for ( y = 0; y < 16; y++ ) { |
414 |
across = &(prev[fy+y][fx]); |
415 |
macross = motionBlock[y]; |
416 |
|
417 |
macross[0] = across[0]; |
418 |
macross[1] = across[1]; |
419 |
macross[2] = across[2]; |
420 |
macross[3] = across[3]; |
421 |
macross[4] = across[4]; |
422 |
macross[5] = across[5]; |
423 |
macross[6] = across[6]; |
424 |
macross[7] = across[7]; |
425 |
macross[8] = across[8]; |
426 |
macross[9] = across[9]; |
427 |
macross[10] = across[10]; |
428 |
macross[11] = across[11]; |
429 |
macross[12] = across[12]; |
430 |
macross[13]= across[13]; |
431 |
macross[14] = across[14]; |
432 |
macross[15] = across[15]; |
433 |
} |
434 |
|
435 |
/* this is what's really happening, in slow motion: |
436 |
* |
437 |
* for ( y = 0; y < 16; y++, py++ ) |
438 |
* for ( x = 0; x < 16; x++, px++ ) |
439 |
* motionBlock[y][x] = prev[fy+y][fx+x]; |
440 |
* |
441 |
*/ |
442 |
} |
443 |
|
444 |
|
445 |
/*=======================* |
446 |
* BASIC ERROR FUNCTIONS * |
447 |
*=======================*/ |
448 |
|
449 |
|
450 |
/*===========================================================================* |
451 |
* |
452 |
* LumBlockMAD |
453 |
* |
454 |
* return the MAD of two luminance blocks |
455 |
* |
456 |
* RETURNS: the MAD, if less than bestSoFar, or |
457 |
* some number bigger if not |
458 |
* |
459 |
* SIDE EFFECTS: none |
460 |
* |
461 |
*===========================================================================*/ |
462 |
int32 |
463 |
LumBlockMAD(currentBlock, motionBlock, bestSoFar) |
464 |
LumBlock currentBlock; |
465 |
LumBlock motionBlock; |
466 |
int32 bestSoFar; |
467 |
{ |
468 |
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ |
469 |
register int32 localDiff; |
470 |
register int y, x; |
471 |
|
472 |
for ( y = 0; y < 16; y++ ) { |
473 |
for ( x = 0; x < 16; x++ ) { |
474 |
localDiff = currentBlock[y][x] - motionBlock[y][x]; |
475 |
diff += ABS(localDiff); |
476 |
} |
477 |
|
478 |
if ( diff > bestSoFar ) { |
479 |
return diff; |
480 |
} |
481 |
} |
482 |
|
483 |
return (int32)diff; |
484 |
} |
485 |
|
486 |
|
487 |
/*===========================================================================* |
488 |
* |
489 |
* LumMotionError |
490 |
* |
491 |
* return the MAD of the currentBlock and the motion-compensated block |
492 |
* (without TUNEing) |
493 |
* |
494 |
* RETURNS: the MAD, if less than bestSoFar, or |
495 |
* some number bigger if not |
496 |
* |
497 |
* SIDE EFFECTS: none |
498 |
* |
499 |
* PRECONDITIONS: motion vector MUST be valid |
500 |
* |
501 |
* NOTES: this is the procedure that is called the most, and should therefore |
502 |
* be the most optimized!!! |
503 |
* |
504 |
*===========================================================================*/ |
505 |
int32 |
506 |
LumMotionError(currentBlock, prevFrame, by, bx, my, mx, bestSoFar) |
507 |
LumBlock currentBlock; |
508 |
MpegFrame *prevFrame; |
509 |
int by; |
510 |
int bx; |
511 |
int my; |
512 |
int mx; |
513 |
int32 bestSoFar; |
514 |
{ |
515 |
register int32 adiff = 0, diff = 0; /* max value of diff is 255*256 = 65280 */ |
516 |
register int32 localDiff; |
517 |
register uint8 *across; |
518 |
register int32 *cacross; |
519 |
register int y; |
520 |
uint8 **prev; |
521 |
int fy, fx; |
522 |
boolean xHalf, yHalf; |
523 |
|
524 |
xHalf = (ABS(mx) % 2 == 1); |
525 |
yHalf = (ABS(my) % 2 == 1); |
526 |
|
527 |
MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); |
528 |
|
529 |
if ( xHalf ) { |
530 |
if ( mx < 0 ) { |
531 |
fx--; |
532 |
} |
533 |
|
534 |
if ( yHalf ) { |
535 |
if ( my < 0 ) { |
536 |
fy--; |
537 |
} |
538 |
|
539 |
prev = prevFrame->halfBoth; |
540 |
} else { |
541 |
prev = prevFrame->halfX; |
542 |
} |
543 |
} else if ( yHalf ) { |
544 |
if ( my < 0 ) { |
545 |
fy--; |
546 |
} |
547 |
|
548 |
prev = prevFrame->halfY; |
549 |
} else { |
550 |
prev = prevFrame->ref_y; |
551 |
} |
552 |
|
553 |
switch (SearchCompareMode) { |
554 |
case DEFAULT_SEARCH: /* Default. */ |
555 |
/* this is what's happening: |
556 |
* ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock); |
557 |
* for ( y = 0; y < 16; y++ ) |
558 |
* for ( x = 0; x < 16; x++ ) |
559 |
* { |
560 |
* localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; |
561 |
* diff += ABS(localDiff); |
562 |
* } |
563 |
*/ |
564 |
for ( y = 0; y < 16; y++ ) { |
565 |
across = &(prev[fy+y][fx]); |
566 |
cacross = currentBlock[y]; |
567 |
|
568 |
localDiff = across[0]-cacross[0]; diff += ABS(localDiff); |
569 |
localDiff = across[1]-cacross[1]; diff += ABS(localDiff); |
570 |
localDiff = across[2]-cacross[2]; diff += ABS(localDiff); |
571 |
localDiff = across[3]-cacross[3]; diff += ABS(localDiff); |
572 |
localDiff = across[4]-cacross[4]; diff += ABS(localDiff); |
573 |
localDiff = across[5]-cacross[5]; diff += ABS(localDiff); |
574 |
localDiff = across[6]-cacross[6]; diff += ABS(localDiff); |
575 |
localDiff = across[7]-cacross[7]; diff += ABS(localDiff); |
576 |
localDiff = across[8]-cacross[8]; diff += ABS(localDiff); |
577 |
localDiff = across[9]-cacross[9]; diff += ABS(localDiff); |
578 |
localDiff = across[10]-cacross[10]; diff += ABS(localDiff); |
579 |
localDiff = across[11]-cacross[11]; diff += ABS(localDiff); |
580 |
localDiff = across[12]-cacross[12]; diff += ABS(localDiff); |
581 |
localDiff = across[13]-cacross[13]; diff += ABS(localDiff); |
582 |
localDiff = across[14]-cacross[14]; diff += ABS(localDiff); |
583 |
localDiff = across[15]-cacross[15]; diff += ABS(localDiff); |
584 |
|
585 |
if ( diff > bestSoFar ) { |
586 |
return diff; |
587 |
} |
588 |
} |
589 |
break; |
590 |
|
591 |
case LOCAL_DCT: { |
592 |
Block dctdiff[4], dctquant[4]; |
593 |
FlatBlock quant; |
594 |
int x, i, tmp; |
595 |
int distortion=0, datarate=0; |
596 |
int pq = GetPQScale(); |
597 |
|
598 |
for (y = 0; y < 16; y++) { |
599 |
across = &(prev[fy+y][fx]); |
600 |
cacross = currentBlock[y]; |
601 |
for (x = 0; x < 16; x++) { |
602 |
dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x]; |
603 |
}} |
604 |
|
605 |
/* Calculate rate */ |
606 |
for (i = 0; i < 4; i++) { |
607 |
mp_fwd_dct_block2(dctdiff[i], dctdiff[i]); |
608 |
if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == MPOST_ZERO) { |
609 |
/* no sense in continuing */ |
610 |
memset((char *)dctquant[i], 0, sizeof(Block)); |
611 |
} else { |
612 |
Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE); |
613 |
mpeg_jrevdct((int16 *)dctquant[i]); |
614 |
datarate += CalcRLEHuffLength(quant); |
615 |
} |
616 |
} |
617 |
|
618 |
/* Calculate distortion */ |
619 |
for (y = 0; y < 16; y++) { |
620 |
across = &(prev[fy+y][fx]); |
621 |
cacross = currentBlock[y]; |
622 |
for (x = 0; x < 16; x++) { |
623 |
tmp = across[x] - cacross[x] + dctquant[(x>7)+2*(y>7)][y%8][x%8]; |
624 |
distortion += tmp*tmp; |
625 |
}} |
626 |
distortion /= 256; |
627 |
distortion *= LocalDCTDistortScale; |
628 |
datarate *= LocalDCTRateScale; |
629 |
diff = (int) sqrt(distortion*distortion + datarate*datarate); |
630 |
break; |
631 |
} |
632 |
|
633 |
case NO_DC_SEARCH: { |
634 |
extern int32 niqtable[]; |
635 |
int pq = niqtable[0]*GetPQScale(); |
636 |
|
637 |
for ( y = 0; y < 16; y++ ) { |
638 |
across = &(prev[fy+y][fx]); |
639 |
cacross = currentBlock[y]; |
640 |
|
641 |
localDiff = across[0]-cacross[0]; diff += localDiff; adiff += ABS(localDiff); |
642 |
localDiff = across[1]-cacross[1]; diff += localDiff; adiff += ABS(localDiff); |
643 |
localDiff = across[2]-cacross[2]; diff += localDiff; adiff += ABS(localDiff); |
644 |
localDiff = across[3]-cacross[3]; diff += localDiff; adiff += ABS(localDiff); |
645 |
localDiff = across[4]-cacross[4]; diff += localDiff; adiff += ABS(localDiff); |
646 |
localDiff = across[5]-cacross[5]; diff += localDiff; adiff += ABS(localDiff); |
647 |
localDiff = across[6]-cacross[6]; diff += localDiff; adiff += ABS(localDiff); |
648 |
localDiff = across[7]-cacross[7]; diff += localDiff; adiff += ABS(localDiff); |
649 |
localDiff = across[8]-cacross[8]; diff += localDiff; adiff += ABS(localDiff); |
650 |
localDiff = across[9]-cacross[9]; diff += localDiff; adiff += ABS(localDiff); |
651 |
localDiff = across[10]-cacross[10]; diff += localDiff; adiff += ABS(localDiff); |
652 |
localDiff = across[11]-cacross[11]; diff += localDiff; adiff += ABS(localDiff); |
653 |
localDiff = across[12]-cacross[12]; diff += localDiff; adiff += ABS(localDiff); |
654 |
localDiff = across[13]-cacross[13]; diff += localDiff; adiff += ABS(localDiff); |
655 |
localDiff = across[14]-cacross[14]; diff += localDiff; adiff += ABS(localDiff); |
656 |
localDiff = across[15]-cacross[15]; diff += localDiff; adiff += ABS(localDiff); |
657 |
|
658 |
} |
659 |
|
660 |
diff /= 64*pq; /* diff is now the DC difference (with QSCALE 1) */ |
661 |
adiff -= 64*pq*ABS(diff); |
662 |
diff = adiff; |
663 |
} |
664 |
break; |
665 |
|
666 |
case DO_Mean_Squared_Distortion: |
667 |
for ( y = 0; y < 16; y++ ) { |
668 |
across = &(prev[fy+y][fx]); |
669 |
cacross = currentBlock[y]; |
670 |
|
671 |
localDiff = across[0]-cacross[0]; diff += localDiff*localDiff; |
672 |
localDiff = across[1]-cacross[1]; diff += localDiff*localDiff; |
673 |
localDiff = across[2]-cacross[2]; diff += localDiff*localDiff; |
674 |
localDiff = across[3]-cacross[3]; diff += localDiff*localDiff; |
675 |
localDiff = across[4]-cacross[4]; diff += localDiff*localDiff; |
676 |
localDiff = across[5]-cacross[5]; diff += localDiff*localDiff; |
677 |
localDiff = across[6]-cacross[6]; diff += localDiff*localDiff; |
678 |
localDiff = across[7]-cacross[7]; diff += localDiff*localDiff; |
679 |
localDiff = across[8]-cacross[8]; diff += localDiff*localDiff; |
680 |
localDiff = across[9]-cacross[9]; diff += localDiff*localDiff; |
681 |
localDiff = across[10]-cacross[10]; diff += localDiff*localDiff; |
682 |
localDiff = across[11]-cacross[11]; diff += localDiff*localDiff; |
683 |
localDiff = across[12]-cacross[12]; diff += localDiff*localDiff; |
684 |
localDiff = across[13]-cacross[13]; diff += localDiff*localDiff; |
685 |
localDiff = across[14]-cacross[14]; diff += localDiff*localDiff; |
686 |
localDiff = across[15]-cacross[15]; diff += localDiff*localDiff; |
687 |
|
688 |
if ( diff > bestSoFar ) { |
689 |
return diff; |
690 |
} |
691 |
} |
692 |
break; |
693 |
} /* End of Switch */ |
694 |
|
695 |
return diff; |
696 |
} |
697 |
|
698 |
|
699 |
/*===========================================================================* |
700 |
* |
701 |
* LumAddMotionError |
702 |
* |
703 |
* return the MAD of the currentBlock and the average of the blockSoFar |
704 |
* and the motion-compensated block (this is used for B-frame searches) |
705 |
* |
706 |
* RETURNS: the MAD, if less than bestSoFar, or |
707 |
* some number bigger if not |
708 |
* |
709 |
* SIDE EFFECTS: none |
710 |
* |
711 |
* PRECONDITIONS: motion vector MUST be valid |
712 |
* |
713 |
*===========================================================================*/ |
714 |
int32 |
715 |
LumAddMotionError(currentBlock, blockSoFar, prevFrame, by, bx, my, mx, |
716 |
bestSoFar) |
717 |
LumBlock currentBlock; |
718 |
LumBlock blockSoFar; |
719 |
MpegFrame *prevFrame; |
720 |
int by; |
721 |
int bx; |
722 |
int my; |
723 |
int mx; |
724 |
int32 bestSoFar; |
725 |
{ |
726 |
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ |
727 |
register int32 localDiff; |
728 |
register uint8 *across; |
729 |
register int32 *bacross; |
730 |
register int32 *cacross; |
731 |
register int y; |
732 |
uint8 **prev; |
733 |
int fy, fx; |
734 |
boolean xHalf, yHalf; |
735 |
|
736 |
xHalf = (ABS(mx) % 2 == 1); |
737 |
yHalf = (ABS(my) % 2 == 1); |
738 |
|
739 |
MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); |
740 |
|
741 |
if ( xHalf ) { |
742 |
if ( mx < 0 ) { |
743 |
fx--; |
744 |
} |
745 |
|
746 |
if ( yHalf ) { |
747 |
if ( my < 0 ) { |
748 |
fy--; |
749 |
} |
750 |
|
751 |
prev = prevFrame->halfBoth; |
752 |
} else { |
753 |
prev = prevFrame->halfX; |
754 |
} |
755 |
} else if ( yHalf ) { |
756 |
if ( my < 0 ) { |
757 |
fy--; |
758 |
} |
759 |
|
760 |
prev = prevFrame->halfY; |
761 |
} else { |
762 |
prev = prevFrame->ref_y; |
763 |
} |
764 |
|
765 |
/* do we add 1 before dividing by two? Yes -- see MPEG-1 doc page 46 */ |
766 |
|
767 |
#define ADD_ADD_DIFF(d,l,a,b,c,i) \ |
768 |
l = ((a[i]+b[i]+1)>>1)-c[i]; \ |
769 |
d += ABS(l) |
770 |
|
771 |
for ( y = 0; y < 16; y++ ) { |
772 |
across = &(prev[fy+y][fx]); |
773 |
bacross = blockSoFar[y]; |
774 |
cacross = currentBlock[y]; |
775 |
|
776 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,0); |
777 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,1); |
778 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,2); |
779 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,3); |
780 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,4); |
781 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,5); |
782 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,6); |
783 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,7); |
784 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,8); |
785 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,9); |
786 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,10); |
787 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,11); |
788 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,12); |
789 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,13); |
790 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,14); |
791 |
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,15); |
792 |
|
793 |
if ( diff > bestSoFar ) { |
794 |
return diff; |
795 |
} |
796 |
} |
797 |
|
798 |
/* this is what's happening: |
799 |
* |
800 |
* ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock); |
801 |
* |
802 |
* for ( y = 0; y < 16; y++ ) |
803 |
* for ( x = 0; x < 16; x++ ) |
804 |
* { |
805 |
* localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; |
806 |
* diff += ABS(localDiff); |
807 |
* } |
808 |
* |
809 |
*/ |
810 |
|
811 |
return diff; |
812 |
} |
813 |
|
814 |
|
815 |
/*===========================================================================* |
816 |
* |
817 |
* AddMotionBlock |
818 |
* |
819 |
* adds the motion-compensated block to the given block |
820 |
* |
821 |
* RETURNS: block modified |
822 |
* |
823 |
* SIDE EFFECTS: none |
824 |
* |
825 |
* PRECONDITIONS: motion vector MUST be valid |
826 |
* |
827 |
*===========================================================================*/ |
828 |
void |
829 |
AddMotionBlock(block, prev, by, bx, my, mx) |
830 |
Block block; |
831 |
uint8 **prev; |
832 |
int by; |
833 |
int bx; |
834 |
int my; |
835 |
int mx; |
836 |
{ |
837 |
int fy, fx; |
838 |
int x, y; |
839 |
boolean xHalf, yHalf; |
840 |
|
841 |
xHalf = (ABS(mx) % 2 == 1); |
842 |
yHalf = (ABS(my) % 2 == 1); |
843 |
|
844 |
MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx); |
845 |
|
846 |
if ( xHalf && yHalf ) { |
847 |
/* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and |
848 |
(fy-1)+y+1 = fy+y |
849 |
*/ |
850 |
if ( my < 0 ) { |
851 |
fy--; |
852 |
} |
853 |
if ( mx < 0 ) { |
854 |
fx--; |
855 |
} |
856 |
|
857 |
for ( y = 0; y < 8; y++ ) { |
858 |
for ( x = 0; x < 8; x++ ) { |
859 |
block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+ |
860 |
prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2; |
861 |
} |
862 |
} |
863 |
} else if ( xHalf ) { |
864 |
if ( mx < 0 ) { |
865 |
fx--; |
866 |
} |
867 |
|
868 |
for ( y = 0; y < 8; y++ ) { |
869 |
for ( x = 0; x < 8; x++ ) { |
870 |
block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1; |
871 |
} |
872 |
} |
873 |
} else if ( yHalf ) { |
874 |
if ( my < 0 ) { |
875 |
fy--; |
876 |
} |
877 |
|
878 |
for ( y = 0; y < 8; y++ ) { |
879 |
for ( x = 0; x < 8; x++ ) { |
880 |
block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1; |
881 |
} |
882 |
} |
883 |
} else { |
884 |
for ( y = 0; y < 8; y++ ) { |
885 |
for ( x = 0; x < 8; x++ ) { |
886 |
block[y][x] += (int16)prev[fy+y][fx+x]; |
887 |
} |
888 |
} |
889 |
} |
890 |
} |
891 |
|
892 |
|
893 |
/*===========================================================================* |
894 |
* |
895 |
* AddBMotionBlock |
896 |
* |
897 |
* adds the motion-compensated B-frame block to the given block |
898 |
* |
899 |
* RETURNS: block modified |
900 |
* |
901 |
* SIDE EFFECTS: none |
902 |
* |
903 |
* PRECONDITIONS: motion vectors MUST be valid |
904 |
* |
905 |
*===========================================================================*/ |
906 |
void |
907 |
AddBMotionBlock(block, prev, next, by, bx, mode, fmy, fmx, bmy, bmx) |
908 |
Block block; |
909 |
uint8 **prev; |
910 |
uint8 **next; |
911 |
int by; |
912 |
int bx; |
913 |
int mode; |
914 |
int fmy; |
915 |
int fmx; |
916 |
int bmy; |
917 |
int bmx; |
918 |
{ |
919 |
int x, y; |
920 |
Block prevBlock, nextBlock; |
921 |
|
922 |
if ( mode == MOTION_FORWARD ) { |
923 |
AddMotionBlock(block, prev, by, bx, fmy, fmx); |
924 |
} else if ( mode == MOTION_BACKWARD ) { |
925 |
AddMotionBlock(block, next, by, bx, bmy, bmx); |
926 |
} else { |
927 |
ComputeMotionBlock(prev, by, bx, fmy, fmx, prevBlock); |
928 |
ComputeMotionBlock(next, by, bx, bmy, bmx, nextBlock); |
929 |
|
930 |
for ( y = 0; y < 8; y++ ) { |
931 |
for ( x = 0; x < 8; x++ ) { |
932 |
block[y][x] += (prevBlock[y][x]+nextBlock[y][x]+1)/2; |
933 |
} |
934 |
} |
935 |
} |
936 |
} |
937 |
|
938 |
|
939 |
/*===========================================================================* |
940 |
* |
941 |
* BlockToData |
942 |
* |
943 |
* copies the given block into the appropriate data area |
944 |
* |
945 |
* RETURNS: data modified |
946 |
* |
947 |
* SIDE EFFECTS: none |
948 |
* |
949 |
*===========================================================================*/ |
950 |
void |
951 |
BlockToData(data, block, by, bx) |
952 |
uint8 **data; |
953 |
Block block; |
954 |
int by; |
955 |
int bx; |
956 |
{ |
957 |
register int x, y; |
958 |
register int fy, fx; |
959 |
register int16 blockItem; |
960 |
|
961 |
BLOCK_TO_FRAME_COORD(by, bx, fy, fx); |
962 |
|
963 |
for ( y = 0; y < 8; y++ ) { |
964 |
for ( x = 0; x < 8; x++ ) { |
965 |
blockItem = block[y][x]; |
966 |
data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem); |
967 |
} |
968 |
} |
969 |
} |
970 |
|
971 |
|
972 |
/*===========================================================================* |
973 |
* |
974 |
* BlockifyFrame |
975 |
* |
976 |
* copies data into appropriate blocks |
977 |
* |
978 |
* RETURNS: mf modified |
979 |
* |
980 |
* SIDE EFFECTS: none |
981 |
* |
982 |
* NOTES: probably shouldn't be in this file |
983 |
* |
984 |
*===========================================================================*/ |
985 |
void |
986 |
BlockifyFrame(framePtr) |
987 |
MpegFrame *framePtr; |
988 |
{ |
989 |
register int dctx, dcty; |
990 |
register int x, y; |
991 |
register int bx, by; |
992 |
register int fy, fx; |
993 |
register int16 *destPtr; |
994 |
register uint8 *srcPtr; |
995 |
register int16 *destPtr2; |
996 |
register uint8 *srcPtr2; |
997 |
Block *blockPtr; |
998 |
Block *blockPtr2; |
999 |
|
1000 |
dctx = Fsize_x / DCTSIZE; |
1001 |
dcty = Fsize_y / DCTSIZE; |
1002 |
|
1003 |
/* |
1004 |
* copy y data into y_blocks |
1005 |
*/ |
1006 |
for (by = 0; by < dcty; by++) { |
1007 |
fy = by*DCTSIZE; |
1008 |
for (bx = 0; bx < dctx; bx++) { |
1009 |
fx = bx*DCTSIZE; |
1010 |
blockPtr = (Block *) &(framePtr->y_blocks[by][bx][0][0]); |
1011 |
for (y = 0; y < DCTSIZE; y++) { |
1012 |
destPtr = &((*blockPtr)[y][0]); |
1013 |
srcPtr = &(framePtr->orig_y[fy+y][fx]); |
1014 |
for (x = 0; x < DCTSIZE; x++) { |
1015 |
destPtr[x] = srcPtr[x]; |
1016 |
} |
1017 |
} |
1018 |
} |
1019 |
} |
1020 |
|
1021 |
/* |
1022 |
* copy cr/cb data into cr/cb_blocks |
1023 |
*/ |
1024 |
for (by = 0; by < (dcty >> 1); by++) { |
1025 |
fy = by*DCTSIZE; |
1026 |
for (bx = 0; bx < (dctx >> 1); bx++) { |
1027 |
fx = bx*DCTSIZE; |
1028 |
blockPtr = (Block *) &(framePtr->cr_blocks[by][bx][0][0]); |
1029 |
blockPtr2 = (Block *) &(framePtr->cb_blocks[by][bx][0][0]); |
1030 |
for (y = 0; y < DCTSIZE; y++) { |
1031 |
destPtr = &((*blockPtr)[y][0]); |
1032 |
srcPtr = &(framePtr->orig_cr[fy+y][fx]); |
1033 |
destPtr2 = &((*blockPtr2)[y][0]); |
1034 |
srcPtr2 = &(framePtr->orig_cb[fy+y][fx]); |
1035 |
for (x = 0; x < DCTSIZE; x++) { |
1036 |
destPtr[x] = srcPtr[x]; |
1037 |
destPtr2[x] = srcPtr2[x]; |
1038 |
} |
1039 |
} |
1040 |
} |
1041 |
} |
1042 |
} |
1043 |
|
1044 |
|
1045 |
/*===========================================================================* |
1046 |
* * |
1047 |
* UNUSED PROCEDURES * |
1048 |
* * |
1049 |
* The following procedures are all unused by the encoder * |
1050 |
* * |
1051 |
* They are listed here for your convenience. You might want to use * |
1052 |
* them if you experiment with different search techniques * |
1053 |
* * |
1054 |
*===========================================================================*/ |
1055 |
|
1056 |
#ifdef UNUSED_PROCEDURES |
1057 |
|
1058 |
/* this procedure calculates the subsampled motion block (obviously) |
1059 |
* |
1060 |
* for speed, this procedure is probably not called anywhere (it is |
1061 |
* incorporated directly into LumDiffA, LumDiffB, etc. |
1062 |
* |
1063 |
* but leave it here anyway for clarity |
1064 |
* |
1065 |
* (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D |
1066 |
* |
1067 |
*/ |
1068 |
void |
1069 |
ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock, |
1070 |
startY, startX) |
1071 |
MpegFrame *prevFrame; |
1072 |
int by; |
1073 |
int bx; |
1074 |
int my; |
1075 |
int mx; |
1076 |
LumBlock motionBlock; |
1077 |
int startY; |
1078 |
int startX; |
1079 |
{ |
1080 |
register uint8 *across; |
1081 |
register int32 *macross; |
1082 |
register int32 *lastx; |
1083 |
register int y; |
1084 |
uint8 **prev; |
1085 |
int fy, fx; |
1086 |
boolean xHalf, yHalf; |
1087 |
|
1088 |
xHalf = (ABS(mx) % 2 == 1); |
1089 |
yHalf = (ABS(my) % 2 == 1); |
1090 |
|
1091 |
MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); |
1092 |
|
1093 |
if ( xHalf ) { |
1094 |
if ( mx < 0 ) { |
1095 |
fx--; |
1096 |
} |
1097 |
|
1098 |
if ( yHalf ) { |
1099 |
if ( my < 0 ) { |
1100 |
fy--; |
1101 |
} |
1102 |
|
1103 |
prev = prevFrame->halfBoth; |
1104 |
} else { |
1105 |
prev = prevFrame->halfX; |
1106 |
} |
1107 |
} else if ( yHalf ) { |
1108 |
if ( my < 0 ) { |
1109 |
fy--; |
1110 |
} |
1111 |
|
1112 |
prev = prevFrame->halfY; |
1113 |
} else { |
1114 |
prev = prevFrame->ref_y; |
1115 |
} |
1116 |
|
1117 |
for ( y = startY; y < 16; y += 2 ) { |
1118 |
across = &(prev[fy+y][fx+startX]); |
1119 |
macross = &(motionBlock[y][startX]); |
1120 |
lastx = &(motionBlock[y][16]); |
1121 |
while ( macross < lastx ) { |
1122 |
(*macross) = (*across); |
1123 |
across += 2; |
1124 |
macross += 2; |
1125 |
} |
1126 |
} |
1127 |
|
1128 |
/* this is what's really going on in slow motion: |
1129 |
* |
1130 |
* for ( y = startY; y < 16; y += 2 ) |
1131 |
* for ( x = startX; x < 16; x += 2 ) |
1132 |
* motionBlock[y][x] = prev[fy+y][fx+x]; |
1133 |
* |
1134 |
*/ |
1135 |
} |
1136 |
|
1137 |
|
1138 |
/*===========================================================================* |
1139 |
* |
1140 |
* LumMotionErrorSubSampled |
1141 |
* |
1142 |
* return the MAD of the currentBlock and the motion-compensated block, |
1143 |
* subsampled 4:1 with given starting coordinates (startY, startX) |
1144 |
* |
1145 |
* RETURNS: the MAD |
1146 |
* |
1147 |
* SIDE EFFECTS: none |
1148 |
* |
1149 |
* PRECONDITIONS: motion vector MUST be valid |
1150 |
* |
1151 |
* NOTES: this procedure is never called. Instead, see subsample.c. This |
1152 |
* procedure is provided only for possible use in extensions |
1153 |
* |
1154 |
*===========================================================================*/ |
1155 |
int32 |
1156 |
LumMotionErrorSubSampled(currentBlock, prevFrame, by, bx, my, mx, startY, |
1157 |
startX) |
1158 |
LumBlock currentBlock; |
1159 |
MpegFrame *prevFrame; |
1160 |
int by; |
1161 |
int bx; |
1162 |
int my; |
1163 |
int mx; |
1164 |
int startY; |
1165 |
int startX; |
1166 |
{ |
1167 |
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */ |
1168 |
register int32 localDiff; |
1169 |
register int32 *cacross; |
1170 |
register uint8 *macross; |
1171 |
register int32 *lastx; |
1172 |
register int y; |
1173 |
uint8 **prev; |
1174 |
int fy, fx; |
1175 |
boolean xHalf, yHalf; |
1176 |
|
1177 |
xHalf = (ABS(mx) % 2 == 1); |
1178 |
yHalf = (ABS(my) % 2 == 1); |
1179 |
|
1180 |
MOTION_TO_FRAME_COORD(by, bx, my/2, mx/2, fy, fx); |
1181 |
|
1182 |
if ( xHalf ) { |
1183 |
if ( mx < 0 ) { |
1184 |
fx--; |
1185 |
} |
1186 |
|
1187 |
if ( yHalf ) { |
1188 |
if ( my < 0 ) { |
1189 |
fy--; |
1190 |
} |
1191 |
|
1192 |
prev = prevFrame->halfBoth; |
1193 |
} else { |
1194 |
prev = prevFrame->halfX; |
1195 |
} |
1196 |
} else if ( yHalf ) { |
1197 |
if ( my < 0 ) { |
1198 |
fy--; |
1199 |
} |
1200 |
|
1201 |
prev = prevFrame->halfY; |
1202 |
} else { |
1203 |
prev = prevFrame->ref_y; |
1204 |
} |
1205 |
|
1206 |
for ( y = startY; y < 16; y += 2 ) { |
1207 |
macross = &(prev[fy+y][fx+startX]); |
1208 |
cacross = &(currentBlock[y][startX]); |
1209 |
lastx = &(currentBlock[y][16]); |
1210 |
while ( cacross < lastx ) { |
1211 |
localDiff = (*cacross)-(*macross); |
1212 |
diff += ABS(localDiff); |
1213 |
macross += 2; |
1214 |
cacross += 2; |
1215 |
} |
1216 |
} |
1217 |
|
1218 |
/* this is what's really happening: |
1219 |
* |
1220 |
* ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, |
1221 |
* lumMotionBlock, startY, startX); |
1222 |
* |
1223 |
* for ( y = startY; y < 16; y += 2 ) |
1224 |
* for ( x = startX; x < 16; x += 2 ) |
1225 |
* { |
1226 |
* localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; |
1227 |
* diff += ABS(localDiff); |
1228 |
* } |
1229 |
* |
1230 |
*/ |
1231 |
|
1232 |
return (int32)diff; |
1233 |
} |
1234 |
|
1235 |
|
1236 |
#endif /* UNUSED_PROCEDURES */ |