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