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