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