📄 pframe.c
字号:
/*===========================================================================* * pframe.c * * Procedures concerned with generation of P-frames * * EXPORTED PROCEDURES: * GenPFrame * ResetPFrameStats * ShowPFrameSummary * EstimateSecondsPerPFrame * ComputeHalfPixelData * SetPQScale * GetPQScale * * NOTE: when motion vectors are passed as arguments, they are passed as * twice their value. In other words, a motion vector of (3,4) will * be passed as (6,8). This allows half-pixel motion vectors to be * passed as integers. This is true throughout the program. * *===========================================================================*//*==============* * HEADER FILES * *==============*/#include <assert.h>#include <sys/param.h>#include "pm.h"#include "all.h"#include "mtypes.h"#include "bitio.h"#include "frames.h"#include "motion_search.h"#include "prototypes.h"#include "param.h"#include "mheaders.h"#include "fsize.h"#include "postdct.h"#include "mpeg.h"#include "parallel.h"#include "rate.h"#include "opts.h"#include "specifics.h"/*==================* * STATIC VARIABLES * *==================*/static int32 zeroDiff;static int numPIBlocks = 0;static int numPPBlocks = 0;static int numPSkipped = 0;static int numPIBits = 0;static int numPPBits = 0;static int numFrames = 0;static int numFrameBits = 0;static int32 totalTime = 0;static int qscaleP;static float totalSNR = 0.0;static float totalPSNR = 0.0;extern Block **dct, **dctr, **dctb;extern dct_data_type **dct_data;/*=====================* * INTERNAL PROCEDURES * *=====================*//*===========================================================================* * * USER-MODIFIABLE * * ZeroMotionBetter * * decide if (0,0) motion is better than the given motion vector * * RETURNS: TRUE if (0,0) is better, FALSE if (my,mx) is better * * SIDE EFFECTS: none * * PRECONDITIONS: The relevant block in 'current' is valid (it has not * been dct'd). 'zeroDiff' has already been computed * as the LumMotionError() with (0,0) motion * * NOTES: This procedure follows the algorithm described on * page D-48 of the MPEG-1 specification * *===========================================================================*/static booleanZeroMotionBetter(currentBlock, prev, by, bx, my, mx) LumBlock currentBlock; MpegFrame *prev; int by; int bx; int my; int mx;{ int bestDiff; int CompareMode; /* Junk needed to adapt for TUNEing */ CompareMode = SearchCompareMode; SearchCompareMode = DEFAULT_SEARCH; bestDiff = LumMotionError(currentBlock, prev, by, bx, my, mx, 0x7fffffff); SearchCompareMode = CompareMode; if ( zeroDiff < 256*3 ) { if ( 2*bestDiff >= zeroDiff ) { return TRUE; } } else { if ( 11*bestDiff >= 10*zeroDiff ) { return TRUE; } } return FALSE;}/*===========================================================================* * * USER-MODIFIABLE * * DoIntraCode * * decide if intra coding is necessary * * RETURNS: TRUE if intra-block coding is better; FALSE if not * * SIDE EFFECTS: none * * PRECONDITIONS: The relevant block in 'current' is valid (it has not * been dct'd). * * NOTES: This procedure follows the algorithm described on * page D-49 of the MPEG-1 specification * *===========================================================================*/static booleanDoIntraCode(currentBlock, prev, by, bx, motionY, motionX) LumBlock currentBlock; MpegFrame *prev; int by; int bx; int motionY; int motionX;{ int x, y; int32 sum = 0, vard = 0, varc = 0, dif; int32 currPixel, prevPixel; LumBlock motionBlock; ComputeMotionLumBlock(prev, by, bx, motionY, motionX, motionBlock); for ( y = 0; y < 16; y++ ) { for ( x = 0; x < 16; x++ ) { currPixel = currentBlock[y][x]; prevPixel = motionBlock[y][x]; sum += currPixel; varc += currPixel*currPixel; dif = currPixel - prevPixel; vard += dif*dif; } } vard >>= 8; /* divide by 256; assumes mean is close to zero */ varc = (varc>>8) - (sum>>8)*(sum>>8); if ( vard <= 64 ) { return FALSE; } else if ( vard < varc ) { return FALSE; } else { return TRUE; }}/*===========================================================================* * * USER-MODIFIABLE * * ZeroMotionSufficient * * decide if zero motion is sufficient without DCT correction * * RETURNS: TRUE no DCT required; FALSE otherwise * * SIDE EFFECTS: none * * PRECONDITIONS: The relevant block in 'current' is raw YCC data * *===========================================================================*/static booleanZeroMotionSufficient(currentBlock, prev, by, bx) LumBlock currentBlock; MpegFrame *prev; int by; int bx;{ LumBlock motionBlock; register int fy, fx; register int x, y; fy = by*DCTSIZE; fx = bx*DCTSIZE; for ( y = 0; y < 16; y++ ) { for ( x = 0; x < 16; x++ ) { motionBlock[y][x] = prev->ref_y[fy+y][fx+x]; } } zeroDiff = LumBlockMAD(currentBlock, motionBlock, 0x7fffffff); return (zeroDiff <= 256);} #ifdef UNUSED_PROCEDURESstatic voidComputeAndPrintPframeMAD(currentBlock, prev, by, bx, my, mbx, numBlock) LumBlock currentBlock; MpegFrame *prev; int by; int bx; int my; int mx; int numBlock;{ LumBlock lumMotionBlock; int32 mad; ComputeMotionLumBlock(prev, by, bx, my, mx, lumMotionBlock); mad = LumBlockMAD(currentBlock, lumMotionBlock, 0x7fffffff); if (! realQuiet) { fprintf(stdout, "%d %d\n", numBlock, mad); }}#endifstatic void computeCurrentBlock(MpegFrame * const current, int const y, int const x, LumBlock currentBlock) { int fy, fx; int iy; BLOCK_TO_FRAME_COORD(y, x, fy, fx); for ( iy = 0; iy < 16; iy++ ) { int ix; for ( ix = 0; ix < 16; ix++ ) { currentBlock[iy][ix] = (int16)current->orig_y[fy+iy][fx+ix]; } }}static voidcomputeMotionVectors(bool const specificsOn, bool const IntraPBAllowed, MpegFrame * const current, MpegFrame * const prev, int const mbAddress, BlockMV ** const infoP, int const QScale, LumBlock currentBlock, int const y, int const x, bool * const useMotionP, int * const motionYP, int * const motionXP) { bool useCached; BlockMV * info; /* See if we have a cached answer */ if (specificsOn) { SpecLookup(current->id, 2, mbAddress, &info, QScale); if (info != (BlockMV*)NULL) useCached = TRUE; else useCached = FALSE; } else useCached = FALSE; if (useCached) { if (info->typ == TYP_SKIP) { *motionXP = *motionYP = 0; *useMotionP = TRUE; } else { /* assume P, since we're a P frame.... */ *motionXP = info->fx; *motionYP = info->fy; *useMotionP = TRUE; } } else { /* see if we should use motion vectors, and if so, what those * vectors should be */ if (ZeroMotionSufficient(currentBlock, prev, y, x)) { *motionXP = 0; *motionYP = 0; *useMotionP = TRUE; } else { int motionY, motionX; motionY = 0; motionX = 0; /* initial values */ PMotionSearch(currentBlock, prev, y, x, &motionY, &motionX); if (ZeroMotionBetter(currentBlock, prev, y, x, motionY, motionX)) { *motionYP = 0; *motionXP = 0; } else { *motionYP = motionY; *motionXP = motionX; } if (IntraPBAllowed) *useMotionP = (! DoIntraCode(currentBlock, prev, y, x, motionY, motionX)); else *useMotionP = TRUE; } } *infoP = info;}static voidcalculateForwardDcts(MpegFrame * const current, int const y, int const x, Block ** const dct) { /* calculate forward dct's */ if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); mp_fwd_dct_block2(current->y_blocks[y][x], dct[y][x]); mp_fwd_dct_block2(current->y_blocks[y][x+1], dct[y][x+1]); mp_fwd_dct_block2(current->y_blocks[y+1][x], dct[y+1][x]); mp_fwd_dct_block2(current->y_blocks[y+1][x+1], dct[y+1][x+1]); if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "c\n"); mp_fwd_dct_block2(current->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]); mp_fwd_dct_block2(current->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]);}static voidcomputeMotionAndDct(int const lastBlockY, int const lastBlockX, bool const specificsOn, bool const IntraPBAllowed, MpegFrame * const current, MpegFrame * const prev, BlockMV ** const infoP, int const QScale, int const searchRangeP, Block ** const dct, int * const numPBlocksP, int * const numIBlocksP, int ** const pmvHistogram) {/*---------------------------------------------------------------------------- Loop through the frame finding motion/not and DCTing-----------------------------------------------------------------------------*/ int mbAddress; int y; mbAddress = 0; for (y = 0; y < lastBlockY; y += 2) { int x; for (x = 0; x < lastBlockX; x += 2) { LumBlock currentBlock; int motionY, motionX; bool useMotion; computeCurrentBlock(current, y, x, currentBlock); computeMotionVectors(specificsOn, IntraPBAllowed, current, prev, mbAddress, infoP, QScale, currentBlock, y, x, &useMotion, &motionY, &motionX); dct_data[y][x].useMotion = useMotion; if (useMotion) { int pattern; (*numPBlocksP)++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -