Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

bframe.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * bframe.c                                                                  *
00003  *                                                                           *
00004  *      Procedures concerned with the B-frame encoding                       *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      GenBFrame                                                            *
00008  *      ResetBFrameStats                                                     *
00009  *      ShowBFrameSummary                                                    *
00010  *      EstimateSecondsPerBFrame                                             *
00011  *      ComputeBMotionLumBlock                                               *
00012  *      SetBQScale                                                           *
00013  *      GetBQScale                                                           *
00014  *                                                                           *
00015  *===========================================================================*/
00016 
00017 /*
00018  * Copyright (c) 1995 The Regents of the University of California.
00019  * All rights reserved.
00020  *
00021  * Permission to use, copy, modify, and distribute this software and its
00022  * documentation for any purpose, without fee, and without written agreement is
00023  * hereby granted, provided that the above copyright notice and the following
00024  * two paragraphs appear in all copies of this software.
00025  *
00026  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00027  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00028  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00029  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  *
00031  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00032  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00033  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00034  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00035  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00036  */
00037 
00038 /*  
00039  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/bframe.c,v 1.4 2004/04/02 15:12:39 rwcox Exp $
00040  *  $Log: bframe.c,v $
00041  *  Revision 1.4  2004/04/02 15:12:39  rwcox
00042  *  Cput
00043  *
00044  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00045  *  Cput
00046  *
00047  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00048  *  Cput
00049  *
00050  *  Revision 1.1  2001/12/17 16:11:53  rwcox
00051  *  Cadd
00052  *
00053  *  Revision 1.20  1995/08/14 22:28:11  smoot
00054  *  renamed index to idx
00055  *  added option to not skip in B frames
00056  *
00057  *  Revision 1.19  1995/08/07 21:52:11  smoot
00058  *  added Color to skip routine
00059  *  fixed full/half bug in intial loop
00060  *  added comments
00061  *  removed buggy "extra skips" code
00062  *
00063  *  Revision 1.18  1995/06/21 22:22:24  smoot
00064  *  generalized time checking, fixed bug in specifics filesm
00065  *  and added TUNEing stuff
00066  *
00067  * Revision 1.17  1995/04/14  23:08:02  smoot
00068  * reorganized to ease rate control experimentation
00069  *
00070  * Revision 1.16  1995/02/24  23:49:10  smoot
00071  * added Spec version 2
00072  *
00073  * Revision 1.15  1995/01/30  19:45:45  smoot
00074  * Fixed a cr/cb screwup
00075  *
00076  * Revision 1.14  1995/01/23  02:46:43  darryl
00077  * initialized variable
00078  *
00079  * Revision 1.13  1995/01/19  23:07:12  eyhung
00080  * Changed copyrights
00081  *
00082  * Revision 1.12  1995/01/16  07:44:11  eyhung
00083  * Added realQuiet
00084  *
00085  * Revision 1.11  1994/12/07  00:40:36  smoot
00086  * Added seperate P and B search ranges
00087  *
00088  * Revision 1.10  1994/11/24  00:35:47  smoot
00089  * fixed bug (divide by 0) in B fram statsitics
00090  *
00091  * Revision 1.9  1994/11/14  22:26:48  smoot
00092  * Merged specifics and rate control.
00093  *
00094  * Revision 1.8  1994/11/01  05:01:16  darryl
00095  *  with rate control changes added
00096  *
00097  * Revision 2.0  1994/10/24  02:38:51  darryl
00098  * will be adding the experiment code
00099  *
00100  * Revision 1.1  1994/09/27  00:16:04  darryl
00101  * Initial revision
00102  *
00103  * Revision 1.7  1994/03/15  00:27:11  keving
00104  * nothing
00105  *
00106  * Revision 1.6  1993/12/22  19:19:01  keving
00107  * nothing
00108  *
00109  * Revision 1.5  1993/07/30  19:24:04  keving
00110  * nothing
00111  *
00112  * Revision 1.4  1993/07/22  22:23:43  keving
00113  * nothing
00114  *
00115  * Revision 1.3  1993/06/30  20:06:09  keving
00116  * nothing
00117  *
00118  * Revision 1.2  1993/06/03  21:08:08  keving
00119  * nothing
00120  *
00121  * Revision 1.1  1993/02/19  19:14:28  keving
00122  * nothing
00123  *
00124  */
00125 
00126 
00127 /*==============*
00128  * HEADER FILES *
00129  *==============*/
00130 
00131 #include "all.h"
00132 #include <sys/param.h>
00133 #include <assert.h>
00134 #include "mtypes.h"
00135 #include "bitio.h"
00136 #include "frames.h"
00137 #include "prototypes.h"
00138 #include "fsize.h"
00139 #include "param.h"
00140 #include "mheaders.h"
00141 #include "postdct.h"
00142 #include "rate.h"
00143 #include "opts.h"
00144 
00145 /*==================*
00146  * STATIC VARIABLES *
00147  *==================*/
00148 
00149 static int numBIBlocks = 0;
00150 static int numBBBlocks = 0;
00151 static int numBSkipped = 0;
00152 static int numBIBits = 0;
00153 static int numBBBits = 0;
00154 static int numFrames = 0;
00155 static int numFrameBits = 0;
00156 static int32 totalTime = 0;
00157 static int qscaleB;
00158 static float    totalSNR = 0.0;
00159 static float    totalPSNR = 0.0;
00160 
00161 static int numBFOBlocks = 0;    /* forward only */
00162 static int numBBABlocks = 0;    /* backward only */
00163 static int numBINBlocks = 0;    /* interpolate */
00164 static int numBFOBits = 0;
00165 static int numBBABits = 0;
00166 static int numBINBits = 0;
00167 
00168 /*====================*
00169  * EXTERNAL VARIABLES *
00170  *====================*/
00171 
00172 extern Block **dct, **dctr, **dctb;
00173 extern dct_data_type **dct_data;
00174 #define NO_MOTION 0
00175 #define MOTION 1
00176 #define SKIP 2  /* used in useMotion in dct_data */
00177 
00178 /*===============================*
00179  * INTERNAL PROCEDURE prototypes *
00180  *===============================*/
00181 
00182 static boolean  MotionSufficient _ANSI_ARGS_((MpegFrame *curr, LumBlock currBlock, MpegFrame *prev, MpegFrame *next,
00183                          int by, int bx, int mode, int fmy, int fmx,
00184                          int bmy, int bmx));
00185 static void     ComputeBMotionBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next,
00186                                int by, int bx, int mode, int fmy, int fmx,
00187                                int bmy, int bmx, Block motionBlock, int type));
00188 static void     ComputeBDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next,
00189                          int by, int bx, int mode, int fmy, int fmx, 
00190                          int bmy, int bmx, int *pattern));
00191 static boolean  DoBIntraCode _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next,
00192                      int by, int bx, int mode, int fmy, int fmx, int bmy,
00193                      int bmx));
00194 
00195 static int ComputeBlockColorDiff _ANSI_ARGS_((Block current, Block motionBlock));
00196 
00197 /*=====================*
00198  * EXPORTED PROCEDURES *
00199  *=====================*/
00200 
00201 /*===========================================================================*
00202  *
00203  * GenBFrame
00204  *
00205  *      generate a B-frame from previous and next frames, adding the result
00206  *      to the given bit bucket
00207  *
00208  * RETURNS:     frame appended to bb
00209  *
00210  * SIDE EFFECTS:    none
00211  *
00212  *===========================================================================*/
00213 void
00214 GenBFrame(bb, curr, prev, next)
00215     BitBucket *bb;
00216     MpegFrame *curr;
00217     MpegFrame *prev;
00218     MpegFrame *next;
00219 {
00220     extern int **bfmvHistogram;
00221     extern int **bbmvHistogram;
00222     FlatBlock fba[6], fb[6];
00223     Block     dec[6];
00224     int32 y_dc_pred, cr_dc_pred, cb_dc_pred;
00225     int x, y;
00226     int fMotionX = 0, fMotionY = 0;
00227     int bMotionX = 0, bMotionY = 0;
00228     int oldFMotionX = 0, oldFMotionY = 0;
00229     int oldBMotionX = 0, oldBMotionY = 0;
00230     int oldMode = MOTION_FORWARD;
00231     int mode = MOTION_FORWARD;
00232     int offsetX, offsetY;
00233     int tempX, tempY;
00234     int fMotionXrem = 0, fMotionXquot = 0;
00235     int fMotionYrem = 0, fMotionYquot = 0;
00236     int bMotionXrem = 0, bMotionXquot = 0;
00237     int bMotionYrem = 0, bMotionYquot = 0;
00238     int pattern;
00239     int numIBlocks = 0, numBBlocks = 0;
00240     int numSkipped = 0, totalBits;
00241     int numIBits = 0,   numBBits = 0;
00242     boolean     lastIntra = TRUE;
00243     boolean    motionForward, motionBackward;
00244     int     totalFrameBits;
00245     int32    startTime, endTime;
00246     int lastX, lastY;
00247     int lastBlockX, lastBlockY;
00248     register int ix, iy;
00249     LumBlock currentBlock;
00250     int         fy, fx;
00251     boolean     make_skip_block;
00252     int mbAddrInc = 1;
00253     int mbAddress;
00254     int     slicePos;
00255     float   snr[3], psnr[3];
00256     int     idx;
00257     int     QScale;
00258     BlockMV *info;
00259     int     bitstreamMode, newQScale;
00260     int     rc_blockStart=0;
00261     boolean overflowChange=FALSE;
00262     int overflowValue = 0;
00263 
00264     if (collect_quant) {fprintf(collect_quant_fp, "# B\n");}
00265     if (dct == NULL) AllocDctBlocks();
00266     numFrames++;
00267     totalFrameBits = bb->cumulativeBits;
00268     startTime = time_elapsed();
00269 
00270     /*   Rate Control */
00271     bitstreamMode = getRateMode();
00272     if (bitstreamMode == FIXED_RATE) {
00273       targetRateControl(curr);
00274     }
00275  
00276     QScale = GetBQScale();
00277     Mhead_GenPictureHeader(bb, B_FRAME, curr->id, fCodeB);
00278     /* Check for Qscale change */
00279     if (specificsOn) {
00280       newQScale = SpecLookup(curr->id, 0, 0 /* junk */, &info, QScale);
00281       if (newQScale != -1) {
00282         QScale = newQScale;
00283       }
00284       /* check for slice */
00285       newQScale = SpecLookup(curr->id, 1, 1, &info, QScale);
00286       if (newQScale != -1) {
00287         QScale = newQScale;
00288       }
00289     }
00290 
00291     Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0);
00292 
00293     Frame_AllocBlocks(curr);
00294     BlockifyFrame(curr);
00295 
00296     if ( printSNR ) {
00297         Frame_AllocDecoded(curr, FALSE);
00298     }
00299 
00300     /* for I-blocks */
00301     y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00302 
00303     totalBits = bb->cumulativeBits;
00304 
00305     if ( ! pixelFullSearch ) {
00306         if ( ! prev->halfComputed && (prev != NULL)) {
00307             ComputeHalfPixelData(prev);
00308         }
00309 
00310         if ( ! next->halfComputed ) {
00311             ComputeHalfPixelData(next);
00312         }
00313     }
00314 
00315     lastBlockX = Fsize_x>>3;
00316     lastBlockY = Fsize_y>>3;
00317     lastX = lastBlockX-2;
00318     lastY = lastBlockY-2;
00319     mbAddress = 0;
00320 
00321     /* find motion vectors and do dcts */
00322     /* In this first loop, all MVs are in half-pixel scope, (if FULL is set
00323        then they will be multiples of 2).  This is not true in the second loop. */
00324     for (y = 0;  y < lastBlockY;  y += 2) {
00325       for (x = 0;  x < lastBlockX;  x += 2) {
00326         slicePos = (mbAddress % blocksPerSlice);
00327 
00328         /* compute currentBlock */
00329         BLOCK_TO_FRAME_COORD(y, x, fy, fx);
00330         for ( iy = 0; iy < 16; iy++ ) {
00331           for ( ix = 0; ix < 16; ix++ ) {
00332             currentBlock[iy][ix] = (int16)curr->orig_y[fy+iy][fx+ix];
00333           }
00334         }
00335             
00336         if (slicePos == 0) {
00337           oldFMotionX = 0;      oldFMotionY = 0;
00338           oldBMotionX = 0;      oldBMotionY = 0;
00339           oldMode = MOTION_FORWARD;
00340           lastIntra = TRUE;
00341         }
00342 
00343         /* STEP 1:  Select Forward, Backward, or Interpolated motion vectors */
00344         /* see if old motion is good enough */
00345         /* but force last block to be non-skipped */
00346         /* can only skip if:
00347          *     1)  not the last block in frame
00348          *     2)  not the last block in slice
00349          *     3)  not the first block in slice
00350          *     4)  previous block was not intra-coded
00351          */
00352         if ( ((y < lastY) || (x < lastX)) &&
00353             (slicePos+1 != blocksPerSlice) &&
00354             (slicePos != 0) &&
00355             (! lastIntra) &&
00356             (BSkipBlocks) ) {
00357           make_skip_block = MotionSufficient(curr, currentBlock, prev, next, y, x, oldMode,
00358                                              oldFMotionY, oldFMotionX,
00359                                              oldBMotionY, oldBMotionX);
00360         } else {
00361           make_skip_block = FALSE;
00362         }
00363 
00364         if ( make_skip_block ) {
00365         skip_it:
00366           /* skipped macro block */
00367           dct_data[y][x].useMotion = SKIP;
00368         } else {
00369           if (specificsOn) {
00370             (void) SpecLookup(curr->id, 2, mbAddress, &info, QScale);
00371             if (info == (BlockMV*)NULL) goto gosearch;
00372             else {
00373               switch (info->typ) {
00374               case TYP_SKIP:
00375                 goto skip_it;
00376               case TYP_FORW:
00377                 fMotionX = info->fx;
00378                 fMotionY = info->fy;
00379                 mode = MOTION_FORWARD;
00380                 break;
00381               case TYP_BACK:
00382                 bMotionX = info->bx;
00383                 bMotionY = info->by;
00384                 mode = MOTION_BACKWARD;
00385                 break;
00386               case TYP_BOTH:
00387                 fMotionX = info->fx;
00388                 fMotionY = info->fy;
00389                 bMotionX = info->bx;
00390                 bMotionY = info->by;
00391                 mode = MOTION_INTERPOLATE;
00392                 break;
00393               default:
00394                 fprintf(stderr,"Unreachable code in GenBFrame!\n");
00395                 goto gosearch;
00396               }
00397               goto skipsearch;
00398             }}
00399         gosearch:               /* do bsearch */
00400           mode = BMotionSearch(currentBlock, prev, next, y, x, &fMotionY,
00401                                &fMotionX, &bMotionY, &bMotionX, mode);
00402         skipsearch:           
00403               
00404           /* STEP 2:  INTRA OR NON-INTRA CODING */
00405           if ( IntraPBAllowed && DoBIntraCode(curr, prev, next, y, x, mode, fMotionY,
00406                             fMotionX, bMotionY, bMotionX) ) {
00407             /* output I-block inside a B-frame */
00408             numIBlocks++;
00409             oldFMotionX = 0;    oldFMotionY = 0;
00410             oldBMotionX = 0;    oldBMotionY = 0;
00411             lastIntra = TRUE;
00412             dct_data[y][x].useMotion = NO_MOTION;
00413             oldMode = MOTION_FORWARD;
00414             /* calculate forward dct's */
00415             if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n");
00416             mp_fwd_dct_block2(curr->y_blocks[y][x], dct[y][x]);
00417             mp_fwd_dct_block2(curr->y_blocks[y][x+1], dct[y][x+1]);
00418             mp_fwd_dct_block2(curr->y_blocks[y+1][x], dct[y+1][x]);
00419             mp_fwd_dct_block2(curr->y_blocks[y+1][x+1], dct[y+1][x+1]);
00420             if (collect_quant && (collect_quant_detailed & 1)) {fprintf(collect_quant_fp, "c\n");}
00421             mp_fwd_dct_block2(curr->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]);
00422             mp_fwd_dct_block2(curr->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]);
00423 
00424           } else { /* dct P/Bi/B block */
00425 
00426             pattern = 63;
00427             lastIntra = FALSE;
00428             numBBlocks++;
00429             dct_data[y][x].mode = mode;
00430             oldMode = mode;
00431             dct_data[y][x].fmotionX = fMotionX;
00432             dct_data[y][x].fmotionY = fMotionY;
00433             dct_data[y][x].bmotionX = bMotionX;
00434             dct_data[y][x].bmotionY = bMotionY;
00435             switch (mode) {
00436             case MOTION_FORWARD:
00437               numBFOBlocks++;
00438               oldFMotionX = fMotionX;           oldFMotionY = fMotionY;
00439               break;
00440             case MOTION_BACKWARD:
00441               numBBABlocks++;
00442               oldBMotionX = bMotionX;           oldBMotionY = bMotionY;
00443               break;
00444             case MOTION_INTERPOLATE:
00445               numBINBlocks++;
00446               oldFMotionX = fMotionX;           oldFMotionY = fMotionY;
00447               oldBMotionX = bMotionX;           oldBMotionY = bMotionY;
00448               break;
00449             default:
00450               fprintf(stderr, "PROGRAMMER ERROR:  Illegal mode: %d\n", mode);
00451               exit(1);
00452             }
00453             
00454             ComputeBDiffDCTs(curr, prev, next, y, x, mode, fMotionY,
00455                              fMotionX, bMotionY, bMotionX, &pattern);
00456             
00457             dct_data[y][x].pattern = pattern;
00458             dct_data[y][x].useMotion = MOTION;
00459             if ( computeMVHist ) {
00460               assert(fMotionX+searchRangeB+1 >= 0);
00461               assert(fMotionY+searchRangeB+1 >= 0);
00462               assert(fMotionX+searchRangeB+1 <= 2*searchRangeB+2);
00463               assert(fMotionY+searchRangeB+1 <= 2*searchRangeB+2);
00464               assert(bMotionX+searchRangeB+1 >= 0);
00465               assert(bMotionY+searchRangeB+1 >= 0);
00466               assert(bMotionX+searchRangeB+1 <= 2*searchRangeB+2);
00467               assert(bMotionY+searchRangeB+1 <= 2*searchRangeB+2);
00468 
00469               bfmvHistogram[fMotionX+searchRangeB+1][fMotionY+searchRangeB+1]++;
00470               bbmvHistogram[bMotionX+searchRangeB+1][bMotionY+searchRangeB+1]++;
00471             }
00472           } /* motion-block */
00473         } /* not skipped */
00474         mbAddress++;
00475       }}
00476 
00477     /* reset everything */
00478     oldFMotionX = 0;    oldFMotionY = 0;
00479     oldBMotionX = 0;    oldBMotionY = 0;
00480     oldMode = MOTION_FORWARD;
00481     lastIntra = TRUE;
00482     y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00483     mbAddress = 0;
00484 
00485     /* Now generate the frame */
00486     for (y = 0; y < lastBlockY; y += 2) {
00487       for (x = 0; x < lastBlockX; x += 2) {
00488         slicePos = (mbAddress % blocksPerSlice);
00489 
00490         if ( (slicePos == 0) && (mbAddress != 0) ) {
00491           if (specificsOn) {
00492             /* Make sure no slice Qscale change */
00493             newQScale = SpecLookup(curr->id,1,mbAddress/blocksPerSlice, &info, QScale);
00494             if (newQScale != -1) QScale = newQScale;
00495           }
00496           Mhead_GenSliceEnder(bb);
00497           Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0);
00498 
00499           /* reset everything */
00500           oldFMotionX = 0;      oldFMotionY = 0;
00501           oldBMotionX = 0;      oldBMotionY = 0;
00502           oldMode = MOTION_FORWARD;
00503           lastIntra = TRUE;
00504           y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00505 
00506           mbAddrInc = 1+(x>>1);
00507         }
00508 
00509         /*  Determine if new Qscale needed for Rate Control purposes */
00510         if (bitstreamMode == FIXED_RATE) {
00511           rc_blockStart =  bb->cumulativeBits;
00512           newQScale = needQScaleChange(QScale,
00513                                        curr->y_blocks[y][x],
00514                                        curr->y_blocks[y][x+1],
00515                                        curr->y_blocks[y+1][x],
00516                                        curr->y_blocks[y+1][x+1]);
00517           if (newQScale > 0) {
00518             QScale = newQScale;
00519           }
00520         }
00521  
00522         if (specificsOn) {
00523           newQScale = SpecLookup(curr->id, 2, mbAddress, &info, QScale);
00524           if (newQScale != -1) {
00525             QScale = newQScale;
00526           }}
00527 
00528         if (dct_data[y][x].useMotion == NO_MOTION) {
00529 
00530           GEN_I_BLOCK(B_FRAME, curr, bb, mbAddrInc, QScale);
00531           mbAddrInc = 1;
00532           numIBits += (bb->cumulativeBits-totalBits);
00533           totalBits = bb->cumulativeBits;
00534               
00535           /* reset because intra-coded */
00536           oldFMotionX = 0;              oldFMotionY = 0;
00537           oldBMotionX = 0;              oldBMotionY = 0;
00538           oldMode = MOTION_FORWARD;
00539           lastIntra = TRUE;
00540               
00541           if ( printSNR ) {
00542             /* need to decode block we just encoded */
00543             /* and reverse the DCT transform */
00544             for ( idx = 0; idx < 6; idx++ ) {
00545               Mpost_UnQuantZigBlock(fb[idx], dec[idx], QScale, TRUE);
00546               mpeg_jrevdct((int16 *)dec[idx]);
00547             }
00548 
00549             /* now, unblockify */
00550             BlockToData(curr->decoded_y, dec[0], y, x);
00551             BlockToData(curr->decoded_y, dec[1], y, x+1);
00552             BlockToData(curr->decoded_y, dec[2], y+1, x);
00553             BlockToData(curr->decoded_y, dec[3], y+1, x+1);
00554             BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1);
00555             BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1);
00556           }
00557         } else if (dct_data[y][x].useMotion == SKIP) {
00558         skip_block:
00559           numSkipped++;
00560           mbAddrInc++;
00561               
00562           /* decode skipped block */
00563           if ( printSNR ) {
00564             int fmy, fmx, bmy, bmx;
00565                 
00566             for ( idx = 0; idx < 6; idx++ ) {
00567               memset((char *)dec[idx], 0, sizeof(Block)); 
00568             }
00569             
00570             if ( pixelFullSearch ) {
00571               fmy = 2*oldFMotionY;
00572               fmx = 2*oldFMotionX;
00573               bmy = 2*oldBMotionY;
00574               bmx = 2*oldBMotionX;
00575             } else {
00576               fmy = oldFMotionY;
00577               fmx = oldFMotionX;
00578               bmy = oldBMotionY;
00579               bmx = oldBMotionX;
00580             }
00581             
00582             /* now add the motion block */
00583             AddBMotionBlock(dec[0], prev->decoded_y,
00584                             next->decoded_y, y, x, mode,
00585                             fmy, fmx, bmy, bmx);
00586             AddBMotionBlock(dec[1], prev->decoded_y,
00587                             next->decoded_y, y, x+1, mode,
00588                             fmy, fmx, bmy, bmx);
00589             AddBMotionBlock(dec[2], prev->decoded_y,
00590                             next->decoded_y, y+1, x, mode,
00591                             fmy, fmx, bmy, bmx);
00592             AddBMotionBlock(dec[3], prev->decoded_y,
00593                             next->decoded_y, y+1, x+1, mode,
00594                             fmy, fmx, bmy, bmx);
00595             AddBMotionBlock(dec[4], prev->decoded_cb,
00596                             next->decoded_cb, y>>1, x>>1, mode,
00597                             fmy/2, fmx/2,
00598                             bmy/2, bmx/2);
00599             AddBMotionBlock(dec[5], prev->decoded_cr,
00600                             next->decoded_cr, y>>1, x>>1, mode,
00601                             fmy/2, fmx/2,
00602                             bmy/2, bmx/2);
00603             
00604             /* now, unblockify */
00605             BlockToData(curr->decoded_y, dec[0], y, x);
00606             BlockToData(curr->decoded_y, dec[1], y, x+1);
00607             BlockToData(curr->decoded_y, dec[2], y+1, x);
00608             BlockToData(curr->decoded_y, dec[3], y+1, x+1);
00609             BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1);
00610             BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1);
00611           }
00612         } else   /* B block */ {
00613           int fCode = fCodeB;   
00614 
00615           pattern = dct_data[y][x].pattern;
00616           fMotionX = dct_data[y][x].fmotionX;
00617           fMotionY = dct_data[y][x].fmotionY;
00618           bMotionX = dct_data[y][x].bmotionX;
00619           bMotionY = dct_data[y][x].bmotionY;
00620 
00621           if ( pixelFullSearch ) {
00622             fMotionX /= 2;          fMotionY /= 2;
00623             bMotionX /= 2;          bMotionY /= 2;
00624           }
00625               
00626           /* create flat blocks and update pattern if necessary */
00627         calc_blocks:
00628         /* Note DoQuant references QScale, overflowChange, overflowValue,
00629            pattern, and the calc_blocks label                 */
00630           DoQuant(0x20, dct[y][x], fba[0]);
00631           DoQuant(0x10, dct[y][x+1], fba[1]);
00632           DoQuant(0x08, dct[y+1][x], fba[2]);
00633           DoQuant(0x04, dct[y+1][x+1], fba[3]);
00634           DoQuant(0x02, dctb[y>>1][x>>1], fba[4]);
00635           DoQuant(0x01, dctr[y>>1][x>>1], fba[5]);
00636 
00637           motionForward  = (dct_data[y][x].mode != MOTION_BACKWARD);
00638           motionBackward = (dct_data[y][x].mode != MOTION_FORWARD);
00639 
00640 #ifdef BUGGY_CODE
00641           /*
00642           send us mail if you can tell me why this code
00643           doesnt work.  Generates some bad vectors.
00644           I suspect 'cuz oldMode/motions aren't being set right,
00645           but am unsure.
00646           */
00647           /* Check to see if we should have skipped */
00648           if ((pattern == 0) &&
00649               ((y < lastY) || (x < lastX)) &&
00650               (slicePos+1 != blocksPerSlice) &&
00651               (slicePos != 0) &&
00652               (!lastIntra) &&
00653               ( (!motionForward) || 
00654                (motionForward && 
00655                 fMotionX == oldFMotionX && fMotionY == oldFMotionY)) &&
00656               ( (!motionBackward) || 
00657                (motionBackward && 
00658                 bMotionX == oldBMotionX && bMotionY == oldBMotionY))
00659               ) {
00660             /* Now *thats* an if statement! */
00661             goto skip_block; 
00662           }
00663 #endif
00664           /* Encode Vectors */
00665           if ( motionForward ) {
00666             /* transform the fMotion vector into the appropriate values */
00667             offsetX = fMotionX - oldFMotionX;
00668             offsetY = fMotionY - oldFMotionY;
00669 
00670             ENCODE_MOTION_VECTOR(offsetX, offsetY, fMotionXquot,
00671                                  fMotionYquot, fMotionXrem, fMotionYrem,
00672                                  FORW_F);
00673             oldFMotionX = fMotionX;             oldFMotionY = fMotionY;
00674           }
00675               
00676           if ( motionBackward ) {
00677             /* transform the bMotion vector into the appropriate values */
00678             offsetX = bMotionX - oldBMotionX;
00679             offsetY = bMotionY - oldBMotionY;
00680             ENCODE_MOTION_VECTOR(offsetX, offsetY, bMotionXquot,
00681                                  bMotionYquot, bMotionXrem, bMotionYrem,
00682                                  BACK_F);
00683             oldBMotionX = bMotionX;             oldBMotionY = bMotionY;
00684           }
00685               
00686           oldMode = dct_data[y][x].mode;
00687               
00688           if ( printSNR ) { /* Need to decode */
00689             if ( pixelFullSearch ) {
00690               fMotionX *= 2;    fMotionY *= 2;
00691               bMotionX *= 2;    bMotionY *= 2;
00692             }
00693             for ( idx = 0; idx < 6; idx++ ) {
00694               if ( pattern & (1 << (5-idx)) ) {
00695                 Mpost_UnQuantZigBlock(fba[idx], dec[idx], QScale, FALSE);
00696                 mpeg_jrevdct((int16 *)dec[idx]);
00697               } else {
00698                 memset((char *)dec[idx], 0, sizeof(Block));
00699               }
00700             }
00701 
00702             /* now add the motion block */
00703             AddBMotionBlock(dec[0], prev->decoded_y,
00704                             next->decoded_y, y, x, mode,
00705                             fMotionY, fMotionX, bMotionY, bMotionX);
00706             AddBMotionBlock(dec[1], prev->decoded_y,
00707                             next->decoded_y, y, x+1, mode,
00708                             fMotionY, fMotionX, bMotionY, bMotionX);
00709             AddBMotionBlock(dec[2], prev->decoded_y,
00710                             next->decoded_y, y+1, x, mode,
00711                             fMotionY, fMotionX, bMotionY, bMotionX);
00712             AddBMotionBlock(dec[3], prev->decoded_y,
00713                             next->decoded_y, y+1, x+1, mode,
00714                             fMotionY, fMotionX, bMotionY, bMotionX);
00715             AddBMotionBlock(dec[4], prev->decoded_cb,
00716                             next->decoded_cb, y>>1, x>>1, mode,
00717                             fMotionY/2, fMotionX/2,
00718                             bMotionY/2, bMotionX/2);
00719             AddBMotionBlock(dec[5], prev->decoded_cr,
00720                             next->decoded_cr, y>>1, x>>1, mode,
00721                             fMotionY/2, fMotionX/2,
00722                             bMotionY/2, bMotionX/2);
00723 
00724             /* now, unblockify */
00725             BlockToData(curr->decoded_y,  dec[0], y,    x);
00726             BlockToData(curr->decoded_y,  dec[1], y,    x+1);
00727             BlockToData(curr->decoded_y,  dec[2], y+1,  x);
00728             BlockToData(curr->decoded_y,  dec[3], y+1,  x+1);
00729             BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1);
00730             BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1);
00731           }
00732 
00733           /* reset because non-intra-coded */
00734           y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00735           lastIntra = FALSE;
00736           mode = dct_data[y][x].mode;
00737 
00738           /*      DBG_PRINT(("MB Header(%d,%d)\n", x, y));  */
00739           Mhead_GenMBHeader(bb, 3 /* pict_code_type */, mbAddrInc /* addr_incr */,
00740             QScale /* q_scale */,
00741             fCodeB /* forw_f_code */, fCodeB /* back_f_code */,
00742             fMotionXrem /* horiz_forw_r */, fMotionYrem /* vert_forw_r */,
00743             bMotionXrem /* horiz_back_r */, bMotionYrem /* vert_back_r */,
00744             motionForward /* motion_forw */, fMotionXquot /* m_horiz_forw */,
00745             fMotionYquot /* m_vert_forw */, motionBackward /* motion_back */,
00746             bMotionXquot /* m_horiz_back */, bMotionYquot /* m_vert_back */,
00747             pattern /* mb_pattern */, FALSE /* mb_intra */);
00748           mbAddrInc = 1;
00749               
00750           /* now output the difference */
00751           for ( tempX = 0; tempX < 6; tempX++ ) {
00752             if ( GET_ITH_BIT(pattern, 5-tempX) ) {
00753               Mpost_RLEHuffPBlock(fba[tempX], bb);
00754             }
00755           }
00756               
00757           
00758           switch (mode) {
00759           case MOTION_FORWARD:
00760             numBFOBits += (bb->cumulativeBits-totalBits);
00761             break;
00762           case MOTION_BACKWARD:
00763             numBBABits += (bb->cumulativeBits-totalBits);
00764             break;
00765           case MOTION_INTERPOLATE:
00766             numBINBits += (bb->cumulativeBits-totalBits);
00767             break;
00768           default:
00769             fprintf(stderr, "PROGRAMMER ERROR:  Illegal mode: %d\n",
00770                     mode);
00771             exit(1);
00772           }
00773           
00774           numBBits += (bb->cumulativeBits-totalBits);
00775           totalBits = bb->cumulativeBits;
00776         
00777           if (overflowChange) {
00778             /* undo an overflow-caused Qscale change */
00779             overflowChange = FALSE;
00780             QScale -= overflowValue;
00781             overflowValue = 0;
00782           }
00783         } /* if I-block, skip, or B */
00784 
00785         mbAddress++;
00786         /*   Rate Control  */
00787         if (bitstreamMode == FIXED_RATE) {
00788           incMacroBlockBits( bb->cumulativeBits - rc_blockStart);
00789           rc_blockStart = bb->cumulativeBits;
00790           MB_RateOut(TYPE_BFRAME);
00791         }
00792         
00793       }
00794     }
00795 
00796     if ( printSNR ) {
00797       BlockComputeSNR(curr,snr,psnr);
00798       totalSNR += snr[0];
00799       totalPSNR += psnr[0];
00800     }
00801     
00802     Mhead_GenSliceEnder(bb);
00803     /*   Rate Control  */
00804     if (bitstreamMode == FIXED_RATE) {
00805       updateRateControl(TYPE_BFRAME);
00806     }
00807     
00808     endTime = time_elapsed();
00809     totalTime += (endTime-startTime);
00810     
00811     if ( ( ! childProcess) && showBitRatePerFrame ) {
00812       /* ASSUMES 30 FRAMES PER SECOND */
00813       fprintf(bitRateFile, "%5d\t%8d\n", curr->id,
00814               30*(bb->cumulativeBits-totalFrameBits));
00815     }
00816     
00817     if ( (! childProcess) && frameSummary && !realQuiet) {
00818       fprintf(stdout, "FRAME %d (B):  I BLOCKS:  %d;  B BLOCKS:  %d   SKIPPED:  %d (%ld seconds)\n",
00819               curr->id, numIBlocks, numBBlocks, numSkipped, (long)((endTime-startTime)/TIME_RATE));
00820       if ( printSNR )
00821         fprintf(stdout, "FRAME %d:  SNR:  %.1f\t%.1f\t%.1f\tPSNR:  %.1f\t%.1f\t%.1f\n",
00822                 curr->id, snr[0], snr[1], snr[2],
00823                 psnr[0], psnr[1], psnr[2]);
00824     }
00825     
00826     numFrameBits += (bb->cumulativeBits-totalFrameBits);
00827     numBIBlocks += numIBlocks;
00828     numBBBlocks += numBBlocks;
00829     numBSkipped += numSkipped;
00830     numBIBits += numIBits;
00831     numBBBits += numBBits;
00832   }
00833 
00834 
00835 /*===========================================================================*
00836  *
00837  * SetBQScale
00838  *
00839  *      set the B-frame Q-scale
00840  *
00841  * RETURNS:     nothing
00842  *
00843  * SIDE EFFECTS:    qscaleB
00844  *
00845  *===========================================================================*/
00846 void
00847 SetBQScale(qB)
00848     int qB;
00849 {
00850     qscaleB = qB;
00851 }
00852 
00853 
00854 /*===========================================================================*
00855  *
00856  * GetBQScale
00857  *
00858  *      get the B-frame Q-scale
00859  *
00860  * RETURNS:     the Q-scale
00861  *
00862  * SIDE EFFECTS:    none
00863  *
00864  *===========================================================================*/
00865 int
00866 GetBQScale()
00867 {
00868     return qscaleB;
00869 }
00870 
00871 
00872 /*===========================================================================*
00873  *
00874  * ResetBFrameStats
00875  *
00876  *      reset the B-frame stats
00877  *
00878  * RETURNS:     nothing
00879  *
00880  * SIDE EFFECTS:    none
00881  *
00882  *===========================================================================*/
00883 void
00884 ResetBFrameStats()
00885 {
00886     numBIBlocks = 0;
00887     numBBBlocks = 0;
00888     numBSkipped = 0;
00889     numBIBits = 0;
00890     numBBBits = 0;
00891     numFrames = 0;
00892     numFrameBits = 0;
00893     totalTime = 0;
00894 }
00895 
00896 
00897 /*===========================================================================*
00898  *
00899  * ShowBFrameSummary
00900  *
00901  *      print out statistics on all B-frames
00902  *
00903  * RETURNS:     time taken for B-frames (in seconds)
00904  *
00905  * SIDE EFFECTS:    none
00906  *
00907  *===========================================================================*/
00908 float
00909 ShowBFrameSummary(inputFrameBits, totalBits, fpointer)
00910     int inputFrameBits;
00911     int32 totalBits;
00912     FILE *fpointer;
00913 {
00914     if ( numFrames == 0 ) {
00915         return 0.0;
00916     }
00917 
00918     fprintf(fpointer, "-------------------------\n");
00919     fprintf(fpointer, "*****B FRAME SUMMARY*****\n");
00920     fprintf(fpointer, "-------------------------\n");
00921 
00922     if ( numBIBlocks != 0 ) {
00923         fprintf(fpointer, "  I Blocks:  %5d     (%6d bits)     (%5d bpb)\n",
00924                 numBIBlocks, numBIBits, numBIBits/numBIBlocks);
00925     } else {
00926         fprintf(fpointer, "  I Blocks:  %5d\n", 0);
00927     }
00928 
00929     if ( numBBBlocks != 0 ) {
00930         fprintf(fpointer, "  B Blocks:  %5d     (%6d bits)     (%5d bpb)\n",
00931                 numBBBlocks, numBBBits, numBBBits/numBBBlocks);
00932         fprintf(fpointer, "  B types:   %5d     (%4d bpb) forw  %5d (%4d bpb) back   %5d (%4d bpb) bi\n",
00933                 numBFOBlocks, (numBFOBlocks==0)?0:numBFOBits/numBFOBlocks,
00934                 numBBABlocks, (numBBABlocks==0)?0:numBBABits/numBBABlocks,
00935                 numBINBlocks, (numBINBlocks==0)?0:numBINBits/numBINBlocks);
00936     } else {
00937         fprintf(fpointer, "  B Blocks:  %5d\n", 0);
00938     }
00939 
00940     fprintf(fpointer, "  Skipped:   %5d\n", numBSkipped);
00941 
00942     fprintf(fpointer, "  Frames:    %5d     (%6d bits)     (%5d bpf)     (%2.1f%% of total)\n",
00943             numFrames, numFrameBits, numFrameBits/numFrames,
00944             100.0*(float)numFrameBits/(float)totalBits);            
00945     fprintf(fpointer, "  Compression:  %3d:1     (%9.4f bpp)\n",
00946             numFrames*inputFrameBits/numFrameBits,
00947             24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits));
00948     if ( printSNR )
00949         fprintf(fpointer, "  Avg Y SNR/PSNR:  %.1f     %.1f\n",
00950                 totalSNR/(float)numFrames, totalPSNR/(float)numFrames);
00951     if ( totalTime == 0 ) {
00952         fprintf(fpointer, "  Seconds:  NONE\n");
00953     } else {
00954         fprintf(fpointer, "  Seconds:  %9ld     (%9.4f fps)  (%9ld pps)  (%9ld mps)\n",
00955                 (long)(totalTime/TIME_RATE),
00956                 (float)((float)(TIME_RATE*numFrames)/(float)totalTime),
00957                 (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(24.0*(float)totalTime)),
00958                 (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(256.0*24.0*(float)totalTime)));
00959     }
00960 
00961     return (float)totalTime/TIME_RATE;
00962 }
00963 
00964 
00965 /*===========================================================================*
00966  *
00967  * ComputeBMotionLumBlock
00968  *
00969  *      compute the luminance block resulting from motion compensation
00970  *
00971  * RETURNS:     motionBlock modified
00972  *
00973  * SIDE EFFECTS:    none
00974  *
00975  * PRECONDITION:        the motion vectors must be valid!
00976  *
00977  *===========================================================================*/
00978 void
00979 ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx, bmy, bmx, motionBlock)
00980     MpegFrame *prev;
00981     MpegFrame *next;
00982     int by;
00983     int bx;
00984     int mode;
00985     int fmy;
00986     int fmx;
00987     int bmy;
00988     int bmx;
00989     LumBlock motionBlock;
00990 {
00991     LumBlock    prevBlock, nextBlock;
00992     register int        y, x;
00993 
00994     switch(mode) {
00995     case MOTION_FORWARD:
00996       ComputeMotionLumBlock(prev, by, bx, fmy, fmx, motionBlock);
00997       break;
00998     case MOTION_BACKWARD:
00999       ComputeMotionLumBlock(next, by, bx, bmy, bmx, motionBlock);
01000       break;
01001     case MOTION_INTERPOLATE:
01002       ComputeMotionLumBlock(prev, by, bx, fmy, fmx, prevBlock);
01003       ComputeMotionLumBlock(next, by, bx, bmy, bmx, nextBlock);
01004       
01005       for ( y = 0; y < 16; y++ ) {
01006         for ( x = 0; x < 16; x++ ) {
01007           motionBlock[y][x] = (prevBlock[y][x]+nextBlock[y][x]+1)/2;
01008         }
01009       }
01010       break;
01011     default:
01012       fprintf(stderr, "Bad mode!\nProgrammer error!\n");
01013       break;
01014       
01015     }
01016 }
01017 
01018 
01019 /*===========================================================================*
01020  *
01021  * EstimateSecondsPerBFrame
01022  *
01023  *      estimate the seconds to compute a B-frame
01024  *
01025  * RETURNS:     the time, in seconds
01026  *
01027  * SIDE EFFECTS:    none
01028  *
01029  *===========================================================================*/
01030 float
01031 EstimateSecondsPerBFrame()
01032 {
01033     if ( numFrames == 0 ) {
01034         return 20.0;
01035     } else {
01036         return (float)totalTime/((float)TIME_RATE*(float)numFrames);
01037     }
01038 }
01039 
01040 
01041 /*=====================*
01042  * INTERNAL PROCEDURES *
01043  *=====================*/
01044 
01045 /*===========================================================================*
01046  *
01047  * ComputeBMotionBlock
01048  *
01049  *      compute the block resulting from motion compensation
01050  *
01051  * RETURNS:     motionBlock is modified
01052  *
01053  * SIDE EFFECTS:    none
01054  *
01055  * PRECONDITION:        the motion vectors must be valid!
01056  *
01057  *===========================================================================*/
01058 static void
01059 ComputeBMotionBlock(prev, next, by, bx, mode, fmy, fmx, bmy, bmx, motionBlock, type)
01060     MpegFrame *prev;
01061     MpegFrame *next;
01062     int by;
01063     int bx;
01064     int mode;
01065     int fmy;
01066     int fmx;
01067     int bmy;
01068     int bmx;
01069     Block motionBlock;
01070     int type;
01071 {
01072     Block       prevBlock, nextBlock;
01073     register int        y, x;
01074 
01075     switch(mode) {
01076         case MOTION_FORWARD:
01077             if ( type == LUM_BLOCK ) {
01078                 ComputeMotionBlock(prev->ref_y, by, bx, fmy, fmx, motionBlock);
01079             } else if ( type == CB_BLOCK ) {
01080                 ComputeMotionBlock(prev->ref_cb, by, bx, fmy, fmx, motionBlock);
01081             } else if ( type == CR_BLOCK ) {
01082                 ComputeMotionBlock(prev->ref_cr, by, bx, fmy, fmx, motionBlock);
01083             }
01084             break;
01085         case MOTION_BACKWARD:
01086             if ( type == LUM_BLOCK ) {
01087                 ComputeMotionBlock(next->ref_y, by, bx, bmy, bmx, motionBlock);
01088             } else if ( type == CB_BLOCK ) {
01089                 ComputeMotionBlock(next->ref_cb, by, bx, bmy, bmx, motionBlock);
01090             } else if ( type == CR_BLOCK ) {
01091                 ComputeMotionBlock(next->ref_cr, by, bx, bmy, bmx, motionBlock);
01092             }
01093             break;
01094         case MOTION_INTERPOLATE:
01095             if ( type == LUM_BLOCK ) {
01096                 ComputeMotionBlock(prev->ref_y, by, bx, fmy, fmx, prevBlock);
01097                 ComputeMotionBlock(next->ref_y, by, bx, bmy, bmx, nextBlock);
01098             } else if ( type == CB_BLOCK ) {
01099                 ComputeMotionBlock(prev->ref_cb, by, bx, fmy, fmx, prevBlock);
01100                 ComputeMotionBlock(next->ref_cb, by, bx, bmy, bmx, nextBlock);
01101             } else if ( type == CR_BLOCK ) {
01102                 ComputeMotionBlock(prev->ref_cr, by, bx, fmy, fmx, prevBlock);
01103                 ComputeMotionBlock(next->ref_cr, by, bx, bmy, bmx, nextBlock);
01104             }
01105 
01106             for ( y = 0; y < 8; y++ ) {
01107                 for ( x = 0; x < 8; x++ ) {
01108                     motionBlock[y][x] = (prevBlock[y][x]+nextBlock[y][x]+1)/2;
01109                 }
01110             }
01111             break;
01112     }
01113 }
01114 
01115 
01116 /*===========================================================================*
01117  *
01118  * ComputeBDiffDCTs
01119  *
01120  *      compute the DCT of the error term
01121  *
01122  * RETURNS:     appropriate blocks of current will contain the DCTs
01123  *
01124  * SIDE EFFECTS:    none
01125  *
01126  * PRECONDITION:        the motion vectors must be valid!
01127  *
01128  *===========================================================================*/
01129 static void
01130 ComputeBDiffDCTs(current, prev, next, by, bx, mode, fmy, fmx, bmy, bmx, pattern)
01131     MpegFrame *current;
01132     MpegFrame *prev;
01133     MpegFrame *next;
01134     int by;
01135     int bx;
01136     int mode;
01137     int fmy;
01138     int fmx;
01139     int bmy;
01140     int bmx;
01141     int *pattern;
01142 {
01143     Block   motionBlock;
01144 
01145     if ( *pattern & 0x20 ) {
01146         ComputeBMotionBlock(prev, next, by, bx, mode, fmy, fmx,
01147                             bmy, bmx, motionBlock, LUM_BLOCK);
01148         if (! ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock)) {
01149           *pattern ^=  0x20;
01150         }
01151     }
01152 
01153     if ( *pattern & 0x10 ) {
01154         ComputeBMotionBlock(prev, next, by, bx+1, mode, fmy, fmx,
01155                             bmy, bmx, motionBlock, LUM_BLOCK);
01156         if (! ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock)) {
01157           *pattern ^=  0x10;
01158         }
01159     }
01160 
01161     if ( *pattern & 0x8 ) {
01162         ComputeBMotionBlock(prev, next, by+1, bx, mode, fmy, fmx,
01163                             bmy, bmx, motionBlock, LUM_BLOCK);
01164         if (! ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock)) {
01165           *pattern ^= 0x8;
01166         }
01167     }
01168 
01169     if ( *pattern & 0x4 ) {
01170         ComputeBMotionBlock(prev, next, by+1, bx+1, mode, fmy, fmx,
01171                             bmy, bmx, motionBlock, LUM_BLOCK);
01172         if (! ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock)) {
01173           *pattern ^= 0x4;
01174         }
01175     }
01176 
01177     if ( *pattern & 0x2 ) {
01178         ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2,
01179                             bmy/2, bmx/2, motionBlock, CB_BLOCK);
01180         if (! ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock)) {
01181           *pattern ^= 0x2;
01182         }
01183     }
01184 
01185     if ( *pattern & 0x1 ) {
01186         ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2,
01187                             bmy/2, bmx/2, motionBlock, CR_BLOCK);
01188         if (! ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock)) {
01189           *pattern ^= 0x1;
01190         }
01191     }
01192 }
01193 
01194 
01195 /*===========================================================================*
01196  *
01197  *                          USER-MODIFIABLE
01198  *
01199  * DoBIntraCode
01200  *
01201  *      decides if this block should be coded as intra-block
01202  *
01203  * RETURNS:     TRUE if intra-coding should be used; FALSE otherwise
01204  *
01205  * SIDE EFFECTS:    none
01206  *
01207  * PRECONDITION:        the motion vectors must be valid!
01208  *
01209  *===========================================================================*/
01210 static boolean
01211 DoBIntraCode(current, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
01212     MpegFrame *current;
01213     MpegFrame *prev;
01214     MpegFrame *next;
01215     int by;
01216     int bx;
01217     int mode;
01218     int fmy;
01219     int fmx;
01220     int bmy;
01221     int bmx;
01222 {
01223     int     x, y;
01224     int32 sum = 0, vard = 0, varc = 0, dif;
01225     int32 currPixel, prevPixel;
01226     LumBlock    motionBlock;
01227     int     fy, fx;
01228 
01229     ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx,
01230                            bmy, bmx, motionBlock);
01231 
01232     MOTION_TO_FRAME_COORD(by, bx, 0, 0, fy, fx);
01233 
01234     for ( y = 0; y < 16; y++ ) {
01235         for ( x = 0; x < 16; x++ ) {
01236             currPixel = current->orig_y[fy+y][fx+x];
01237             prevPixel = motionBlock[y][x];
01238 
01239             sum += currPixel;
01240             varc += currPixel*currPixel;
01241 
01242             dif = currPixel - prevPixel;
01243             vard += dif*dif;
01244         }
01245     }
01246 
01247     vard >>= 8;         /* divide by 256; assumes mean is close to zero */
01248     varc = (varc>>8) - (sum>>8)*(sum>>8);
01249 
01250     if ( vard <= 64 ) {
01251         return FALSE;
01252     } else if ( vard < varc ) {
01253         return FALSE;
01254     } else {
01255         return TRUE;
01256     }
01257 }
01258 
01259 static int
01260 ComputeBlockColorDiff(current, motionBlock)
01261     Block current, motionBlock;
01262 {
01263   register int x, y, diff_total = 0, diff_tmp;
01264   
01265   for ( y = 0; y < 8; y++ ) {
01266     for ( x = 0; x < 8; x++ ) {
01267       diff_tmp = current[y][x] - motionBlock[y][x];
01268       diff_total += ABS(diff_tmp);
01269     }
01270   }
01271   return diff_total;
01272 }
01273 
01274 /*===========================================================================*
01275  *
01276  *                          USER-MODIFIABLE
01277  *
01278  * MotionSufficient
01279  *
01280  *      decides if this motion vector is sufficient without DCT coding
01281  *
01282  * RETURNS:     TRUE if no DCT is needed; FALSE otherwise
01283  *
01284  * SIDE EFFECTS:    none
01285  *
01286  * PRECONDITION:        the motion vectors must be valid!
01287  *
01288  *===========================================================================*/
01289 static boolean
01290 MotionSufficient(curr, currBlock, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
01291     MpegFrame *curr;
01292     LumBlock currBlock;
01293     MpegFrame *prev;
01294     MpegFrame *next;
01295     int by, bx;
01296     int mode;
01297     int fmy, fmx;
01298     int bmy, bmx;
01299 {
01300     LumBlock   mLumBlock;
01301     Block mColorBlock;
01302     int lumErr, colorErr;
01303 
01304     /* check bounds */
01305     if ( mode != MOTION_BACKWARD ) {
01306         if ( (by*DCTSIZE+(fmy-1)/2 < 0) || ((by+2)*DCTSIZE+(fmy+1)/2-1 >= Fsize_y) ) {
01307             return FALSE;
01308         }
01309         if ( (bx*DCTSIZE+(fmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(fmx+1)/2-1 >= Fsize_x) ) {
01310             return FALSE;
01311         }
01312     }
01313 
01314     if ( mode != MOTION_FORWARD ) {
01315         if ( (by*DCTSIZE+(bmy-1)/2 < 0) || ((by+2)*DCTSIZE+(bmy+1)/2-1 >= Fsize_y) ) {
01316             return FALSE;
01317         }
01318         if ( (bx*DCTSIZE+(bmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(bmx+1)/2-1 >= Fsize_x) ) {
01319             return FALSE;
01320         }
01321     }
01322 
01323     /* check Lum */
01324     ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx,
01325                            bmy, bmx, mLumBlock);
01326     lumErr =  LumBlockMAD(currBlock, mLumBlock, 0x7fffffff);
01327     if (lumErr > 512) {
01328       return FALSE;
01329     }
01330 
01331     /* check color */
01332     ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2, 
01333                         bmy/2, bmx/2, mColorBlock, CR_BLOCK);
01334     colorErr = ComputeBlockColorDiff(curr->cr_blocks[by >> 1][bx >> 1], mColorBlock);
01335     ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2, 
01336                         bmy/2, bmx/2, mColorBlock, CB_BLOCK);
01337     colorErr += ComputeBlockColorDiff(curr->cr_blocks[by >> 1][bx >> 1], mColorBlock);
01338     
01339     return (colorErr < 256); /* lumErr checked above */
01340 }
01341 
01342 
 

Powered by Plone

This site conforms to the following standards: