ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/freemol/trunk/src/mpeg_encode/src/block.c
Revision: 22
Committed: Mon Jul 7 22:16:37 2008 UTC (11 years, 4 months ago) by wdelano
File size: 32775 byte(s)
Log Message:
initial checkin of mpeg_encode source
Line File contents
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 */