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