From 1fd361a1ea06e44286c213ca1f814f49306fdc43 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 19 Aug 2006 03:12:28 +0000 Subject: Create Subversion repository git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/ppm/ppmtompeg/block.c | 1045 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1045 insertions(+) create mode 100644 converter/ppm/ppmtompeg/block.c (limited to 'converter/ppm/ppmtompeg/block.c') diff --git a/converter/ppm/ppmtompeg/block.c b/converter/ppm/ppmtompeg/block.c new file mode 100644 index 00000000..913518c4 --- /dev/null +++ b/converter/ppm/ppmtompeg/block.c @@ -0,0 +1,1045 @@ +/*===========================================================================* + * block.c + * + * Block routines + * + * NOTES: MAD = Mean Absolute Difference + *===========================================================================*/ + +/* Copyright information is at end of file */ + +#include + +#include "pm_c_util.h" +#include "all.h" +#include "mtypes.h" +#include "frames.h" +#include "bitio.h" +#include "prototypes.h" +#include "fsize.h" +#include "opts.h" +#include "postdct.h" + +#include "block.h" + +#define TRUNCATE_UINT8(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + + +extern Block **dct, **dctb, **dctr; + + +static vector +halfVector(vector const v) { + vector half; + + half.y = v.y/2; + half.x = v.x/2; + + return half; +} + +/*===========================* + * COMPUTE DCT OF DIFFERENCE * + *===========================*/ + +/*===========================================================================* + * + * compute current-motionBlock, take the DCT, and put the difference + * back into current + * + * RETURNS: current block modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +ComputeDiffDCTBlock(Block current, + Block dest, + Block motionBlock, + boolean * const significantDifferenceP) { + + unsigned int y; + int diff; + + diff = 0; /* initial value */ + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + current[y][x] -= motionBlock[y][x]; + diff += ABS(current[y][x]); + } + } + /* Kill the block if change is too small */ + /* (block_bound defaults to 128, see opts.c) */ + if (diff < block_bound) + *significantDifferenceP = FALSE; + else { + mp_fwd_dct_block2(current, dest); + *significantDifferenceP = TRUE; + } +} + + + +/*===========================================================================* + * + * appropriate (according to pattern, the coded block pattern) blocks + * of 'current' are diff'ed and DCT'd. + * + * RETURNS: current blocks modified + * + * SIDE EFFECTS: Can remove too-small difference blocks from pattern + * + * PRECONDITIONS: appropriate blocks of 'current' have not yet been + * modified + * + *===========================================================================*/ +void +ComputeDiffDCTs(MpegFrame * const current, + MpegFrame * const prev, + int const by, + int const bx, + vector const m, + int * const patternP) { + + Block motionBlock; + + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "l\n"); + if (*patternP & 0x20) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by, bx, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x20; + } + + if (*patternP & 0x10) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by, bx+1, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x10; + } + + if (*patternP & 0x8) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by+1, bx, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x8; + } + + if (*patternP & 0x4) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_y, by+1, bx+1, m, &motionBlock); + ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], + motionBlock, &significantDiff); + if (!significantDiff) + *patternP ^= 0x4; + } + + if (collect_quant && (collect_quant_detailed & 1)) + fprintf(collect_quant_fp, "c\n"); + + if (*patternP & 0x2) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_cb, by/2, bx/2, halfVector(m), + &motionBlock); + ComputeDiffDCTBlock(current->cb_blocks[by/2][bx/2], + dctb[by/2][bx/2], motionBlock, + &significantDiff); + if (!significantDiff) + *patternP ^= 0x2; + } + + if (*patternP & 0x1) { + boolean significantDiff; + ComputeMotionBlock(prev->ref_cr, by/2, bx/2, halfVector(m), + &motionBlock); + ComputeDiffDCTBlock(current->cr_blocks[by/2][bx/2], + dctr[by/2][bx/2], motionBlock, + &significantDiff); + if (!significantDiff) + *patternP ^= 0x1; + } +} + + + +static void +computePrevFyFx(MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + uint8 *** const prevP, + int * const fyP, + int * const fxP) { + + boolean const xHalf = (ABS(m.x) % 2 == 1); + boolean const yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, m.y/2, m.x/2, fyP, fxP); + + assert(*fyP >= 0); assert(*fxP >= 0); + + /* C integer arithmetic rounds toward zero. But what we need is a + "floor" -- i.e. round down. So we adjust now for where the dividend + in the above divide by two was negative. + */ + + if (xHalf) { + if (m.x < 0) + --*fxP; + + if (yHalf) { + if (m.y < 0) + --*fyP; + + *prevP = prevFrame->halfBoth; + } else + *prevP = prevFrame->halfX; + } else if (yHalf) { + if (m.y < 0) + --*fyP; + + *prevP = prevFrame->halfY; + } else + *prevP = prevFrame->ref_y; +} + + + +/*======================* + * COMPUTE MOTION BLOCK * + *======================*/ + +/*===========================================================================* + * + * compute the motion-compensated block + * + * RETURNS: motionBlock + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTE: could try to speed this up using halfX, halfY, halfBoth, + * but then would have to compute for chrominance, and it's just + * not worth the trouble (this procedure is not called relatively + * often -- a constant number of times per macroblock) + * + *===========================================================================*/ +void +ComputeMotionBlock(uint8 ** const prev, + int const by, + int const bx, + vector const m, + Block * const motionBlockP) { + + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(m.x) % 2 == 1); + yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, m.y/2, m.x/2, &fy, &fx); + + if (xHalf && yHalf) { + unsigned int y; + /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and + (fy-1)+y+1 = fy+y + */ + if (m.y < 0) + --fy; + + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + uint8 * const srcPtr2 = &(prev[fy+y+1][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = + (srcPtr[x]+srcPtr[x+1]+srcPtr2[x]+srcPtr2[x+1]+2) >> 2; + } + } else if (xHalf) { + unsigned int y; + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = (srcPtr[x]+srcPtr[x+1]+1) >> 1; + } + } else if (yHalf) { + unsigned int y; + if ( m.y < 0 ) + fy--; + + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + uint8 * const srcPtr2 = &(prev[fy+y+1][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = (srcPtr[x]+srcPtr2[x]+1) >> 1; + } + } else { + unsigned int y; + for (y = 0; y < 8; ++y) { + int16 * const destPtr = (*motionBlockP)[y]; + uint8 * const srcPtr = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 8; ++x) + destPtr[x] = srcPtr[x]; + } + } +} + + + +/*===========================================================================* + * + * compute the motion-compensated luminance block + * + * RETURNS: motionBlock + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTE: see ComputeMotionBlock + * + *===========================================================================*/ +void +ComputeMotionLumBlock(MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + LumBlock * const motionBlockP) { + + unsigned int y; + uint8 ** prev; + int fy, fx; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + for (y = 0; y < 16; ++y) { + uint8 * const across = &(prev[fy+y][fx]); + int32 * const macross = motionBlockP->l[y]; + unsigned int x; + + for (x = 0; x < 16; ++x) + macross[x] = across[x]; + } + + /* this is what's really happening, in slow motion: + * + * for (y = 0; y < 16; ++y, ++py) + * for (x = 0; x < 16; ++x, ++px) + * motionBlock[y][x] = prev[fy+y][fx+x]; + * + */ +} + + +/*=======================* + * BASIC ERROR FUNCTIONS * + *=======================*/ + + +/*===========================================================================* + * + * return the MAD of two luminance blocks + * + * RETURNS: the MAD, if less than bestSoFar, or some number bigger if not + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +int32 +LumBlockMAD(const LumBlock * const currentBlockP, + const LumBlock * const motionBlockP, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + unsigned int y; + + diff = 0; /* initial value */ + + for (y = 0; y < 16; ++y) { + const int32 * const currentRow = currentBlockP->l[y]; + const int32 * const motionRow = motionBlockP->l[y]; + unsigned int x; + for (x = 0; x < 16; ++x) + diff += ABS(currentRow[x] - motionRow[x]); + + if (diff > bestSoFar) + /* We already know the MAD won't be less than bestSoFar; + Caller doesn't care by how much we missed, so just return + this. + */ + return diff; + } + /* Return the actual MAD */ + return diff; +} + + + +/*===========================================================================* + * + * return the MAD of the currentBlock and the motion-compensated block + * (without TUNEing) + * + * (by, bx) is the location of the block in the frame + * (block number coordinates). 'm' is the motion of the block in pixels. + * The moved block must be wholly within the frame. + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTES: this is the procedure that is called the most, and should therefore + * be the most optimized!!! + * + *===========================================================================*/ +int32 +LumMotionError(const LumBlock * const currentBlockP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 adiff; + int32 diff; /* max value of diff is 255*256 = 65280 */ + int y; + uint8 **prev; + int fy, fx; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + assert(fy >= 0); assert(fx >= 0); + + adiff = 0; /* initial value */ + diff = 0; /* initial value */ + + switch (SearchCompareMode) { + case DEFAULT_SEARCH: /* Default. */ + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &prev[fy+y][fx]; + unsigned int x; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = across[x]-cacross[x]; + diff += ABS(localDiff); + } + if (diff > bestSoFar) + return diff; + } + break; + + case LOCAL_DCT: { + Block dctdiff[4], dctquant[4]; + FlatBlock quant; + int x, i, tmp; + int distortion=0, datarate=0; + int pq = GetPQScale(); + + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + for (x = 0; x < 16; ++x) { + dctdiff[(x>7)+2*(y>7)][y%8][x%8] = cacross[x]-across[x]; + }} + + /* Calculate rate */ + for (i = 0; i < 4; ++i) { + mp_fwd_dct_block2(dctdiff[i], dctdiff[i]); + if (Mpost_QuantZigBlock(dctdiff[i], quant, pq, FALSE) == + MPOST_ZERO) { + /* no sense in continuing */ + memset((char *)dctquant[i], 0, sizeof(Block)); + } else { + Mpost_UnQuantZigBlock(quant, dctquant[i], pq, FALSE); + mpeg_jrevdct((int16 *)dctquant[i]); + datarate += CalcRLEHuffLength(quant); + } + } + + /* Calculate distortion */ + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + for (x = 0; x < 16; ++x) { + tmp = across[x] - cacross[x] + + dctquant[(x>7)+2*(y>7)][y%8][x%8]; + distortion += tmp*tmp; + }} + distortion /= 256; + distortion *= LocalDCTDistortScale; + datarate *= LocalDCTRateScale; + diff = (int) sqrt(distortion*distortion + datarate*datarate); + break; + } + + case NO_DC_SEARCH: { + extern int32 niqtable[]; + int pq = niqtable[0]*GetPQScale(); + unsigned int y; + + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = across[x]-cacross[x]; + diff += localDiff; + adiff += ABS(localDiff); + } + } + + diff /= 64*pq; /* diff is now the DC difference (with QSCALE 1) */ + adiff -= 64*pq*ABS(diff); + diff = adiff; + } + break; + + case DO_Mean_Squared_Distortion: + for (y = 0; y < 16; ++y) { + const int32 * const cacross = currentBlockP->l[y]; + uint8 * const across = &(prev[fy+y][fx]); + unsigned int x; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = across[x] - cacross[x]; + diff += localDiff * localDiff; + } + if (diff > bestSoFar) + return diff; + } + break; + } /* End of Switch */ + + return diff; +} + + + +/*===========================================================================* + * + * return the MAD of the currentBlock and the average of the blockSoFar + * and the motion-compensated block (this is used for B-frame searches) + * + * RETURNS: the MAD, if less than bestSoFar, or + * some number bigger if not + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + *===========================================================================*/ +int32 +LumAddMotionError(const LumBlock * const currentBlockP, + const LumBlock * const blockSoFarP, + MpegFrame * const prevFrame, + int const by, + int const bx, + vector const m, + int32 const bestSoFar) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + int y; + uint8 **prev; + int fy, fx; + + computePrevFyFx(prevFrame, by, bx, m, &prev, &fy, &fx); + + diff = 0; /* initial value */ + + /* do we add 1 before dividing by two? Yes -- see MPEG-1 doc page 46 */ + + for (y = 0; y < 16; ++y) { + unsigned int x; + const uint8 * const across = &prev[fy+y][fx]; + const int32 * const bacross = blockSoFarP->l[y]; + const int32 * const cacross = currentBlockP->l[y]; + + for (x = 0; x < 16; ++x) { + int32 const localDiff = + ((across[x] + bacross[x] + 1) / 2) - cacross[x]; + diff += ABS(localDiff); + } + + if (diff > bestSoFar) + return diff; + } + + /* This is what's happening: + * + * ComputeMotionLumBlock(prevFrame, by, bx, my, mx, lumMotionBlock); + * + * for (y = 0; y < 16; ++y) + * for (x = 0; x < 16; ++x) { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + */ + + return diff; +} + + + +/*===========================================================================* + * + * adds the motion-compensated block to the given block + * + * RETURNS: block modified + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + *===========================================================================*/ +void +AddMotionBlock(Block block, + uint8 ** const prev, + int const by, + int const bx, + vector const m) { + + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(m.x) % 2 == 1); + yHalf = (ABS(m.y) % 2 == 1); + + MotionToFrameCoord(by, bx, (m.y/2), (m.x/2), &fy, &fx); + + if (xHalf && yHalf) { + unsigned int y; + /* really should be fy+y-1 and fy+y so do (fy-1)+y = fy+y-1 and + (fy-1)+y+1 = fy+y + */ + if (m.y < 0) + --fy; + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+ + prev[fy+y+1][fx+x]+prev[fy+y+1][fx+x+1]+2)>>2; + } + } else if (xHalf) { + unsigned int y; + if (m.x < 0) + --fx; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y][fx+x+1]+1)>>1; + } + } + } else if ( yHalf ) { + unsigned int y; + if (m.y < 0) + --fy; + + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1; + } + } + } else { + unsigned int y; + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (int16)prev[fy+y][fx+x]; + } + } + } +} + + +/*===========================================================================* + * + * adds the motion-compensated B-frame block to the given block + * + * RETURNS: block modified + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vectors MUST be valid + * + *===========================================================================*/ +void +AddBMotionBlock(Block block, + uint8 ** const prev, + uint8 ** const next, + int const by, + int const bx, + int const mode, + motion const motion) { + + unsigned int y; + Block prevBlock, nextBlock; + + switch (mode) { + case MOTION_FORWARD: + AddMotionBlock(block, prev, by, bx, motion.fwd); + break; + case MOTION_BACKWARD: + AddMotionBlock(block, next, by, bx, motion.bwd); + break; + default: + ComputeMotionBlock(prev, by, bx, motion.fwd, &prevBlock); + ComputeMotionBlock(next, by, bx, motion.bwd, &nextBlock); + } + for (y = 0; y < 8; ++y) { + unsigned int x; + for (x = 0; x < 8; ++x) { + block[y][x] += (prevBlock[y][x] + nextBlock[y][x] + 1) / 2; + } + } +} + + +/*===========================================================================* + * + * copies the given block into the appropriate data area + * + * RETURNS: data modified + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +void +BlockToData(uint8 ** const data, + Block block, + int const by, + int const bx) { + + int x, y; + int fy, fx; + int16 blockItem; + + BLOCK_TO_FRAME_COORD(by, bx, fy, fx); + + for ( y = 0; y < 8; y++ ) { + for ( x = 0; x < 8; x++ ) { + blockItem = block[y][x]; + data[fy+y][fx+x] = TRUNCATE_UINT8(blockItem); + } + } +} + + +/*===========================================================================* + * + * copies data into appropriate blocks + * + * RETURNS: mf modified + * + * SIDE EFFECTS: none + * + * NOTES: probably shouldn't be in this file + * + *===========================================================================*/ +void +BlockifyFrame(MpegFrame * const frameP) { + + int dctx, dcty; + int x, y; + int bx, by; + int fy, fx; + int16 *destPtr; + uint8 *srcPtr; + int16 *destPtr2; + uint8 *srcPtr2; + Block *blockPtr; + Block *blockPtr2; + + dctx = Fsize_x / DCTSIZE; + dcty = Fsize_y / DCTSIZE; + + /* + * copy y data into y_blocks + */ + for (by = 0; by < dcty; by++) { + fy = by*DCTSIZE; + for (bx = 0; bx < dctx; bx++) { + fx = bx*DCTSIZE; + blockPtr = (Block *) &(frameP->y_blocks[by][bx][0][0]); + for (y = 0; y < DCTSIZE; y++) { + destPtr = &((*blockPtr)[y][0]); + srcPtr = &(frameP->orig_y[fy+y][fx]); + for (x = 0; x < DCTSIZE; x++) { + destPtr[x] = srcPtr[x]; + } + } + } + } + + /* + * copy cr/cb data into cr/cb_blocks + */ + for (by = 0; by < (dcty >> 1); by++) { + fy = by*DCTSIZE; + for (bx = 0; bx < (dctx >> 1); bx++) { + fx = bx*DCTSIZE; + blockPtr = (Block *) &(frameP->cr_blocks[by][bx][0][0]); + blockPtr2 = (Block *) &(frameP->cb_blocks[by][bx][0][0]); + for (y = 0; y < DCTSIZE; y++) { + destPtr = &((*blockPtr)[y][0]); + srcPtr = &(frameP->orig_cr[fy+y][fx]); + destPtr2 = &((*blockPtr2)[y][0]); + srcPtr2 = &(frameP->orig_cb[fy+y][fx]); + for (x = 0; x < DCTSIZE; x++) { + destPtr[x] = srcPtr[x]; + destPtr2[x] = srcPtr2[x]; + } + } + } + } +} + + +/*===========================================================================* + * * + * UNUSED PROCEDURES * + * * + * The following procedures are all unused by the encoder * + * * + * They are listed here for your convenience. You might want to use * + * them if you experiment with different search techniques * + * * + *===========================================================================*/ + +#ifdef UNUSED_PROCEDURES + +/* this procedure calculates the subsampled motion block (obviously) + * + * for speed, this procedure is probably not called anywhere (it is + * incorporated directly into LumDiffA, LumDiffB, etc. + * + * but leave it here anyway for clarity + * + * (startY, startX) = (0,0) for A....(0,1) for B...(1,0) for C...(1,1) for D + * + */ +void +ComputeSubSampledMotionLumBlock(MpegFrame * const prevFrame, + int const by, + int const bx, + int const my, + int const mx, + LumBlock const motionBlock, + int const startY, + int const startX) { + + uint8 *across; + int32 *macross; + int32 *lastx; + int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + MotionToFrameCoord(by, bx, my/2, mx/2, &fy, &fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + for ( y = startY; y < 16; y += 2 ) { + across = &(prev[fy+y][fx+startX]); + macross = &(motionBlock[y][startX]); + lastx = &(motionBlock[y][16]); + while ( macross < lastx ) { + (*macross) = (*across); + across += 2; + macross += 2; + } + } + + /* this is what's really going on in slow motion: + * + * for ( y = startY; y < 16; y += 2 ) + * for ( x = startX; x < 16; x += 2 ) + * motionBlock[y][x] = prev[fy+y][fx+x]; + * + */ +} + + +/*===========================================================================* + * + * return the MAD of the currentBlock and the motion-compensated block, + * subsampled 4:1 with given starting coordinates (startY, startX) + * + * RETURNS: the MAD + * + * SIDE EFFECTS: none + * + * PRECONDITIONS: motion vector MUST be valid + * + * NOTES: this procedure is never called. Instead, see subsample.c. This + * procedure is provided only for possible use in extensions + * + *===========================================================================*/ +int32 +LumMotionErrorSubSampled(LumBlock const currentBlock, + MpegFrame * const prevFrame, + int const by, + int const bx, + int const my, + int const mx, + int const startY, + int const startX) { + + int32 diff; /* max value of diff is 255*256 = 65280 */ + int32 localDiff; + int32 *cacross; + uint8 *macross; + int32 *lastx; + int y; + uint8 **prev; + int fy, fx; + boolean xHalf, yHalf; + + xHalf = (ABS(mx) % 2 == 1); + yHalf = (ABS(my) % 2 == 1); + + motionToFrameCoord(by, bx, my/2, mx/2, &fy, &fx); + + if ( xHalf ) { + if ( mx < 0 ) { + fx--; + } + + if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfBoth; + } else { + prev = prevFrame->halfX; + } + } else if ( yHalf ) { + if ( my < 0 ) { + fy--; + } + + prev = prevFrame->halfY; + } else { + prev = prevFrame->ref_y; + } + + diff = 0; /* initial value */ + + for ( y = startY; y < 16; y += 2 ) { + macross = &(prev[fy+y][fx+startX]); + cacross = &(currentBlock[y][startX]); + lastx = &(currentBlock[y][16]); + while ( cacross < lastx ) { + localDiff = (*cacross)-(*macross); + diff += ABS(localDiff); + macross += 2; + cacross += 2; + } + } + + /* this is what's really happening: + * + * ComputeSubSampledMotionLumBlock(prevFrame, by, bx, my, mx, + * lumMotionBlock, startY, startX); + * + * for ( y = startY; y < 16; y += 2 ) + * for ( x = startX; x < 16; x += 2 ) + * { + * localDiff = currentBlock[y][x] - lumMotionBlock[y][x]; + * diff += ABS(localDiff); + * } + * + */ + + return (int32)diff; +} + + +#endif /* UNUSED_PROCEDURES */ +/* + * Copyright (c) 1995 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + -- cgit 1.4.1