home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 9
/
CD_ASCQ_09_1193.iso
/
news
/
4441
/
mpegcode
/
src
/
block.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-27
|
28KB
|
1,082 lines
/*===========================================================================*
* block.c *
* *
* Block routines *
* *
* EXPORTED PROCEDURES: *
* ComputeDiffDCTBlock *
* ComputeDiffDCTs *
* ComputeMotionBlock *
* ComputeMotionLumBlock *
* LumBlockMAD *
* LumMotionError *
* LumMotionErrorSubSampled *
* LumAddMotionError *
* AddMotionBlock *
* BlockToData *
* BlockifyFrame *
* *
* NOTES: MAD = Mean Absolute Difference *
* *
*===========================================================================*/
/*
* Copyright (c) 1993 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.
*/
/*
* $Header: /n/picasso/users/keving/encode/src/RCS/block.c,v 1.4 1993/07/22 22:23:43 keving Exp keving $
* $Log: block.c,v $
* Revision 1.4 1993/07/22 22:23:43 keving
* nothing
*
* Revision 1.3 1993/06/30 20:06:09 keving
* nothing
*
* Revision 1.2 1993/06/03 21:08:08 keving
* nothing
*
* Revision 1.1 1993/04/08 21:31:59 keving
* nothing
*
*/
/*==============*
* HEADER FILES *
*==============*/
#include "all.h"
#include "mtypes.h"
#include "frames.h"
#include "bitio.h"
#include "prototypes.h"
#include "fsize.h"
#undef ABS
#define ABS(x) ((x < 0) ? (-x) : x)
#define TRUNCATE_UINT8(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x))
/*==========================*
* INITIALIZATION FUNCTIONS *
*==========================*/
/*===========================*
* COMPUTE DCT OF DIFFERENCE *
*===========================*/
/*===========================================================================*
*
* ComputeDiffDCTBlock
*
* compute current-motionBlock, take the DCT, and put the difference
* back into current
*
* RETURNS: current block modified
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
ComputeDiffDCTBlock(current, motionBlock)
Block current;
Block motionBlock;
{
register int x, y;
for ( y = 0; y < 8; y++ ) {
for ( x = 0; x < 8; x++ ) {
current[y][x] -= motionBlock[y][x];
}
}
mp_fwd_dct_block(current);
return /* nothing */;
}
/*===========================================================================*
*
* ComputeDiffDCTs
*
* appropriate (according to pattern, the coded block pattern) blocks
* of 'current' are diff'ed and DCT'd.
*
* RETURNS: current blocks modified
*
* SIDE EFFECTS: none
*
* PRECONDITIONS: appropriate blocks of 'current' have not yet been
* modified
*
*===========================================================================*/
void
ComputeDiffDCTs(current, prev, by, bx, my, mx, pattern)
MpegFrame *current;
MpegFrame *prev;
int by;
int bx;
int my;
int mx;
int pattern;
{
Block motionBlock;
if ( pattern & 0x20 ) {
ComputeMotionBlock(prev->ref_y, by, bx, my, mx, motionBlock);
ComputeDiffDCTBlock(current->y_blocks[by][bx], motionBlock);
}
if ( pattern & 0x10 ) {
ComputeMotionBlock(prev->ref_y, by, bx+1, my, mx, motionBlock);
ComputeDiffDCTBlock(current->y_blocks[by][bx+1], motionBlock);
}
if ( pattern & 0x8 ) {
ComputeMotionBlock(prev->ref_y, by+1, bx, my, mx, motionBlock);
ComputeDiffDCTBlock(current->y_blocks[by+1][bx], motionBlock);
}
if ( pattern & 0x4 ) {
ComputeMotionBlock(prev->ref_y, by+1, bx+1, my, mx, motionBlock);
ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], motionBlock);
}
if ( pattern & 0x2 ) {
ComputeMotionBlock(prev->ref_cb, by >> 1, bx >> 1, my/2, mx/2, motionBlock);
ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], motionBlock);
}
if ( pattern & 0x1 ) {
ComputeMotionBlock(prev->ref_cr, by >> 1, bx >> 1, my/2, mx/2, motionBlock);
ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], motionBlock);
}
}
/*======================*
* COMPUTE MOTION BLOCK *
*======================*/
/*===========================================================================*
*
* ComputeMotionBlock
*
* 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(prev, by, bx, my, mx, motionBlock)
uint8 **prev;
int by;
int bx;
int my;
int mx;
Block motionBlock;
{
register int fy, fx;
register int y;
register int16 *destPtr;
register uint8 *srcPtr;
register uint8 *srcPtr2;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);
if ( xHalf && yHalf ) {
/* 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 ( my < 0 ) {
fy--;
}
if ( mx < 0 ) {
fx--;
}
for ( y = 0; y < 8; y++ ) {
destPtr = motionBlock[y];
srcPtr = &(prev[fy+y][fx]);
srcPtr2 = &(prev[fy+y+1][fx]);
destPtr[0] = (srcPtr[0]+srcPtr[1]+srcPtr2[0]+srcPtr2[1]+2)>>2;
destPtr[1] = (srcPtr[1]+srcPtr[2]+srcPtr2[1]+srcPtr2[2]+2)>>2;
destPtr[2] = (srcPtr[2]+srcPtr[3]+srcPtr2[2]+srcPtr2[3]+2)>>2;
destPtr[3] = (srcPtr[3]+srcPtr[4]+srcPtr2[3]+srcPtr2[4]+2)>>2;
destPtr[4] = (srcPtr[4]+srcPtr[5]+srcPtr2[4]+srcPtr2[5]+2)>>2;
destPtr[5] = (srcPtr[5]+srcPtr[6]+srcPtr2[5]+srcPtr2[6]+2)>>2;
destPtr[6] = (srcPtr[6]+srcPtr[7]+srcPtr2[6]+srcPtr2[7]+2)>>2;
destPtr[7] = (srcPtr[7]+srcPtr[8]+srcPtr2[7]+srcPtr2[8]+2)>>2;
}
} else if ( xHalf ) {
if ( mx < 0 ) {
fx--;
}
for ( y = 0; y < 8; y++ ) {
destPtr = motionBlock[y];
srcPtr = &(prev[fy+y][fx]);
destPtr[0] = (srcPtr[0]+srcPtr[1]+1)>>1;
destPtr[1] = (srcPtr[1]+srcPtr[2]+1)>>1;
destPtr[2] = (srcPtr[2]+srcPtr[3]+1)>>1;
destPtr[3] = (srcPtr[3]+srcPtr[4]+1)>>1;
destPtr[4] = (srcPtr[4]+srcPtr[5]+1)>>1;
destPtr[5] = (srcPtr[5]+srcPtr[6]+1)>>1;
destPtr[6] = (srcPtr[6]+srcPtr[7]+1)>>1;
destPtr[7] = (srcPtr[7]+srcPtr[8]+1)>>1;
}
} else if ( yHalf ) {
if ( my < 0 ) {
fy--;
}
for ( y = 0; y < 8; y++ ) {
destPtr = motionBlock[y];
srcPtr = &(prev[fy+y][fx]);
srcPtr2 = &(prev[fy+y+1][fx]);
destPtr[0] = (srcPtr[0]+srcPtr2[0]+1)>>1;
destPtr[1] = (srcPtr[1]+srcPtr2[1]+1)>>1;
destPtr[2] = (srcPtr[2]+srcPtr2[2]+1)>>1;
destPtr[3] = (srcPtr[3]+srcPtr2[3]+1)>>1;
destPtr[4] = (srcPtr[4]+srcPtr2[4]+1)>>1;
destPtr[5] = (srcPtr[5]+srcPtr2[5]+1)>>1;
destPtr[6] = (srcPtr[6]+srcPtr2[6]+1)>>1;
destPtr[7] = (srcPtr[7]+srcPtr2[7]+1)>>1;
}
} else {
for ( y = 0; y < 8; y++ ) {
destPtr = motionBlock[y];
srcPtr = &(prev[fy+y][fx]);
destPtr[0] = srcPtr[0];
destPtr[1] = srcPtr[1];
destPtr[2] = srcPtr[2];
destPtr[3] = srcPtr[3];
destPtr[4] = srcPtr[4];
destPtr[5] = srcPtr[5];
destPtr[6] = srcPtr[6];
destPtr[7] = srcPtr[7];
}
}
}
/*===========================================================================*
*
* ComputeMotionLumBlock
*
* compute the motion-compensated luminance block
*
* RETURNS: motionBlock
*
* SIDE EFFECTS: none
*
* PRECONDITIONS: motion vector MUST be valid
*
* NOTE: see ComputeMotionBlock
*
*===========================================================================*/
void
ComputeMotionLumBlock(prevFrame, by, bx, my, mx, motionBlock)
MpegFrame *prevFrame;
int by;
int bx;
int my;
int mx;
LumBlock motionBlock;
{
register uint8 *across;
register int32 *macross;
register int y;
uint8 **prev;
int fy, fx;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(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 = 0; y < 16; y++ ) {
across = &(prev[fy+y][fx]);
macross = motionBlock[y];
macross[0] = across[0];
macross[1] = across[1];
macross[2] = across[2];
macross[3] = across[3];
macross[4] = across[4];
macross[5] = across[5];
macross[6] = across[6];
macross[7] = across[7];
macross[8] = across[8];
macross[9] = across[9];
macross[10] = across[10];
macross[11] = across[11];
macross[12] = across[12];
macross[13]= across[13];
macross[14] = across[14];
macross[15] = across[15];
}
/* 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 *
*=======================*/
/*===========================================================================*
*
* LumBlockMAD
*
* 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(currentBlock, motionBlock, bestSoFar)
LumBlock currentBlock;
LumBlock motionBlock;
int32 bestSoFar;
{
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */
register int32 localDiff;
register int y, x;
for ( y = 0; y < 16; y++ ) {
for ( x = 0; x < 16; x++ ) {
localDiff = currentBlock[y][x] - motionBlock[y][x];
diff += ABS(localDiff);
}
if ( diff > bestSoFar ) {
return diff;
}
}
return (int32)diff;
}
/*===========================================================================*
*
* LumMotionError
*
* return the MAD of the currentBlock and the motion-compensated block
*
* 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(currentBlock, prevFrame, by, bx, my, mx, bestSoFar)
LumBlock currentBlock;
MpegFrame *prevFrame;
int by;
int bx;
int my;
int mx;
int32 bestSoFar;
{
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */
register int32 localDiff;
register uint8 *across;
register int32 *cacross;
register int y;
uint8 **prev;
int fy, fx;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(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 = 0; y < 16; y++ ) {
across = &(prev[fy+y][fx]);
cacross = currentBlock[y];
localDiff = across[0]-cacross[0]; diff += ABS(localDiff);
localDiff = across[1]-cacross[1]; diff += ABS(localDiff);
localDiff = across[2]-cacross[2]; diff += ABS(localDiff);
localDiff = across[3]-cacross[3]; diff += ABS(localDiff);
localDiff = across[4]-cacross[4]; diff += ABS(localDiff);
localDiff = across[5]-cacross[5]; diff += ABS(localDiff);
localDiff = across[6]-cacross[6]; diff += ABS(localDiff);
localDiff = across[7]-cacross[7]; diff += ABS(localDiff);
localDiff = across[8]-cacross[8]; diff += ABS(localDiff);
localDiff = across[9]-cacross[9]; diff += ABS(localDiff);
localDiff = across[10]-cacross[10]; diff += ABS(localDiff);
localDiff = across[11]-cacross[11]; diff += ABS(localDiff);
localDiff = across[12]-cacross[12]; diff += ABS(localDiff);
localDiff = across[13]-cacross[13]; diff += ABS(localDiff);
localDiff = across[14]-cacross[14]; diff += ABS(localDiff);
localDiff = across[15]-cacross[15]; 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;
}
/*===========================================================================*
*
* LumAddMotionError
*
* 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(currentBlock, blockSoFar, prevFrame, by, bx, my, mx,
bestSoFar)
LumBlock currentBlock;
LumBlock blockSoFar;
MpegFrame *prevFrame;
int by;
int bx;
int my;
int mx;
int32 bestSoFar;
{
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */
register int32 localDiff;
register uint8 *across;
register int32 *bacross;
register int32 *cacross;
register int y;
uint8 **prev;
int fy, fx;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(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;
}
/* do we add 1 before dividing by two? Yes -- see MPEG-1 doc page 46 */
#define ADD_ADD_DIFF(d,l,a,b,c,i) \
l = ((a[i]+b[i]+1)>>1)-c[i]; \
d += ABS(l)
for ( y = 0; y < 16; y++ ) {
across = &(prev[fy+y][fx]);
bacross = blockSoFar[y];
cacross = currentBlock[y];
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,0);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,1);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,2);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,3);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,4);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,5);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,6);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,7);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,8);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,9);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,10);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,11);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,12);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,13);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,14);
ADD_ADD_DIFF(diff,localDiff,across,bacross,cacross,15);
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;
}
/*===========================================================================*
*
* AddMotionBlock
*
* adds the motion-compensated block to the given block
*
* RETURNS: block modified
*
* SIDE EFFECTS: none
*
* PRECONDITIONS: motion vector MUST be valid
*
*===========================================================================*/
void
AddMotionBlock(block, prev, by, bx, my, mx)
Block block;
uint8 **prev;
int by;
int bx;
int my;
int mx;
{
int fy, fx;
int x, y;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(by, bx, (my/2), (mx/2), fy, fx);
if ( xHalf && yHalf ) {
/* 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 ( my < 0 ) {
fy--;
}
if ( mx < 0 ) {
fx--;
}
for ( y = 0; y < 8; y++ ) {
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 ) {
if ( mx < 0 ) {
fx--;
}
for ( y = 0; y < 8; y++ ) {
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 ) {
if ( my < 0 ) {
fy--;
}
for ( y = 0; y < 8; y++ ) {
for ( x = 0; x < 8; x++ ) {
block[y][x] += (prev[fy+y][fx+x]+prev[fy+y+1][fx+x]+1)>>1;
}
}
} else {
for ( y = 0; y < 8; y++ ) {
for ( x = 0; x < 8; x++ ) {
block[y][x] += (int32)prev[fy+y][fx+x];
}
}
}
}
/*===========================================================================*
*
* AddBMotionBlock
*
* 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, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
Block block;
uint8 **prev;
uint8 **next;
int by;
int bx;
int mode;
int fmy;
int fmx;
int bmy;
int bmx;
{
int x, y;
Block prevBlock, nextBlock;
if ( mode == MOTION_FORWARD ) {
AddMotionBlock(block, prev, by, bx, fmy, fmx);
} else if ( mode == MOTION_BACKWARD ) {
AddMotionBlock(block, next, by, bx, bmy, bmx);
} else {
ComputeMotionBlock(prev, by, bx, fmy, fmx, prevBlock);
ComputeMotionBlock(next, by, bx, bmy, bmx, nextBlock);
for ( y = 0; y < 8; y++ ) {
for ( x = 0; x < 8; x++ ) {
block[y][x] += (prevBlock[y][x]+nextBlock[y][x]+1)/2;
}
}
}
}
/*===========================================================================*
*
* BlockToData
*
* copies the given block into the appropriate data area
*
* RETURNS: data modified
*
* SIDE EFFECTS: none
*
*===========================================================================*/
void
BlockToData(data, block, by, bx)
uint8 **data;
Block block;
int by;
int bx;
{
register int x, y;
register int fy, fx;
register 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);
}
}
}
/*===========================================================================*
*
* BlockifyFrame
*
* copies data into appropriate blocks
*
* RETURNS: mf modified
*
* SIDE EFFECTS: none
*
* NOTES: probably shouldn't be in this file
*
*===========================================================================*/
void
BlockifyFrame(framePtr)
MpegFrame *framePtr;
{
register int dctx, dcty;
register int x, y;
register int bx, by;
register int fy, fx;
register int16 *destPtr;
register uint8 *srcPtr;
register int16 *destPtr2;
register 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 = &framePtr->y_blocks[by][bx];
for (y = 0; y < DCTSIZE; y++) {
destPtr = &((*blockPtr)[y][0]);
srcPtr = &(framePtr->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 / 2; by++) {
fy = by*DCTSIZE;
for (bx = 0; bx < dctx / 2; bx++) {
fx = bx*DCTSIZE;
blockPtr = &framePtr->cr_blocks[by][bx];
blockPtr2 = &framePtr->cb_blocks[by][bx];
for (y = 0; y < DCTSIZE; y++) {
destPtr = &((*blockPtr)[y][0]);
srcPtr = &(framePtr->orig_cr[fy+y][fx]);
destPtr2 = &((*blockPtr2)[y][0]);
srcPtr2 = &(framePtr->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(prevFrame, by, bx, my, mx, motionBlock,
startY, startX)
MpegFrame *prevFrame;
int by;
int bx;
int my;
int mx;
LumBlock motionBlock;
int startY;
int startX;
{
register uint8 *across;
register int32 *macross;
register int32 *lastx;
register int y;
uint8 **prev;
int fy, fx;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(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];
*
*/
}
/*===========================================================================*
*
* LumMotionErrorSubSampled
*
* 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(currentBlock, prevFrame, by, bx, my, mx, startY,
startX)
LumBlock currentBlock;
MpegFrame *prevFrame;
int by;
int bx;
int my;
int mx;
int startY;
int startX;
{
register int32 diff = 0; /* max value of diff is 255*256 = 65280 */
register int32 localDiff;
register int32 *cacross;
register uint8 *macross;
register int32 *lastx;
register int y;
uint8 **prev;
int fy, fx;
boolean xHalf, yHalf;
xHalf = (ABS(mx) % 2 == 1);
yHalf = (ABS(my) % 2 == 1);
MOTION_TO_FRAME_COORD(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 ) {
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