/*===========================================================================* * * Tune_Init * * Do any setup needed before coding stream * * RETURNS: nothing * * SIDE EFFECTS: varies * *===========================================================================*/ void Tune_Init() { int i; /* Just check for each, and do whats needed */ if (collect_quant) { if (!pureDCT) { pureDCT = TRUE; init_idctref(); init_fdct(); } fprintf(collect_quant_fp, "# %s\n", outputFileName); fprintf(collect_quant_fp, "#"); for (i=0; i<64; i++) fprintf(collect_quant_fp, " %d", qtable[i]); fprintf(collect_quant_fp, "\n#"); for (i=0; i<64; i++) fprintf(collect_quant_fp, " %d", niqtable[i]); fprintf(collect_quant_fp, "\n# %d %d %d\n\n", GetIQScale(), GetPQScale(), GetBQScale()); } if (DoLaplace) { if (!pureDCT) { pureDCT = TRUE; init_idctref(); init_fdct(); } decodeRefFrames = TRUE; printSNR = TRUE; } }
/*===========================================================================* * * GenPFrame * * generate a P-frame from previous frame, adding the result to the * given bit bucket * * RETURNS: frame appended to bb * * SIDE EFFECTS: none * *===========================================================================*/ void GenPFrame(BitBucket *bb, MpegFrame *current, MpegFrame *prev) { extern int **pmvHistogram; FlatBlock fba[6], fb[6]; Block dec[6]; int32 y_dc_pred, cr_dc_pred, cb_dc_pred; int x, y; int motionX = 0, motionY = 0; int oldMotionX = 0, oldMotionY = 0; int offsetX, offsetY; int tempX, tempY; int motionXrem, motionXquot; int motionYrem, motionYquot; int pattern; int mbAddrInc = 1; boolean useMotion; int numIBlocks = 0; int numPBlocks = 0; int numSkipped = 0; int numIBits = 0; int numPBits = 0; int totalBits; int totalFrameBits; int32 startTime, endTime; int lastBlockX, lastBlockY; int lastX, lastY; int fy, fx; LumBlock currentBlock; register int ix, iy; int mbAddress; int slicePos; register int index; float snr[3], psnr[3]; int QScale; BlockMV *info; int bitstreamMode, newQScale; int rc_blockStart = 0; boolean overflowChange = FALSE; int overflowValue = 0; if (collect_quant) {fprintf(collect_quant_fp, "# P\n");} if (dct==NULL) AllocDctBlocks(); numFrames++; totalFrameBits = bb->cumulativeBits; startTime = time_elapsed(); DBG_PRINT(("Generating pframe\n")); QScale = GetPQScale(); /* bit allocation for rate control purposes */ bitstreamMode = getRateMode(); if (bitstreamMode == FIXED_RATE) { targetRateControl(current); } Mhead_GenPictureHeader(bb, P_FRAME, current->id, fCodeP); /* Check for Qscale change */ if (specificsOn) { /* Set a Qscale for this frame? */ newQScale = SpecLookup(current->id, 0, 0 /* junk */, &info /*junk*/, QScale); if (newQScale != -1) { QScale = newQScale; } /* Set for slice? */ newQScale = SpecLookup(current->id, 1, 1, &info /*junk*/, QScale); if (newQScale != -1) { QScale = newQScale; } } DBG_PRINT(("Slice Header\n")); Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); if ( referenceFrame == DECODED_FRAME ) { Frame_AllocDecoded(current, TRUE); } else if ( printSNR ) { Frame_AllocDecoded(current, FALSE); } /* don't do dct on blocks yet */ Frame_AllocBlocks(current); BlockifyFrame(current); /* for I-blocks */ y_dc_pred = cr_dc_pred = cb_dc_pred = 128; totalBits = bb->cumulativeBits; if ( (! pixelFullSearch) && (! prev->halfComputed) ) { ComputeHalfPixelData(prev); } lastBlockX = Fsize_x>>3; lastBlockY = Fsize_y>>3; lastX = lastBlockX-2; lastY = lastBlockY-2; mbAddress = 0; /* First loop though finding motion/not and DCTing */ for (y = 0; y < lastBlockY; y += 2) { for (x = 0; x < lastBlockX; x += 2) { /* compute currentBlock */ BLOCK_TO_FRAME_COORD(y, x, fy, fx); for ( iy = 0; iy < 16; iy++ ) { for ( ix = 0; ix < 16; ix++ ) { currentBlock[iy][ix] = (int16)current->orig_y[fy+iy][fx+ix]; } } /* See if we have a cached answer */ if (specificsOn) { (void) SpecLookup(current->id, 2, mbAddress, &info, QScale); if (info != (BlockMV*)NULL) { if (info->typ == TYP_SKIP) { motionX = motionY = 0; useMotion = TRUE; goto no_search; } else { /* assume P, since we're a P frame.... */ motionX = info->fx; motionY = info->fy; useMotion = TRUE; goto no_search; }} /* if unspecified, just look */ } /* see if we should use motion vectors, and if so, what those * vectors should be */ if ( ZeroMotionSufficient(currentBlock, prev, y, x) ) { motionX = 0; motionY = 0; useMotion = TRUE; } else { useMotion = PMotionSearch(currentBlock, prev, y, x, &motionY, &motionX); if ( useMotion ) { if ( ZeroMotionBetter(currentBlock, prev, y, x, motionY, motionX) ) { motionX = 0; motionY = 0; } if (IntraPBAllowed) useMotion = (! DoIntraCode(currentBlock, prev, y, x, motionY, motionX)); } } no_search: dct_data[y][x].useMotion = useMotion; if ( ! useMotion ) { /* output I-block inside a P-frame */ numIBlocks++; /* 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]); } else { /* USE MOTION VECTORS */ numPBlocks++; pattern = 63; ComputeDiffDCTs(current, prev, y, x, motionY, motionX, &pattern); assert(motionX+searchRangeP+1 >= 0); assert(motionY+searchRangeP+1 >= 0); #ifdef BLEAH if ( motionX+searchRangeP+1 > 2*searchRangeP+2 ) { fprintf(stdout, "motionX = %d, searchRangeP = %d\n", motionX, searchRangeP); } #endif if ( computeMVHist ) { assert(motionX+searchRangeP+1 <= 2*searchRangeP+2); assert(motionY+searchRangeP+1 <= 2*searchRangeP+2); pmvHistogram[motionX+searchRangeP+1][motionY+searchRangeP+1]++; } /* Save specs for next loops */ dct_data[y][x].pattern = pattern; dct_data[y][x].fmotionX = motionX; dct_data[y][x].fmotionY = motionY; } mbAddress++; }}