📄 iframe.c
字号:
}/*===========================================================================* * * GenIFrame * * generate an I-frame; appends result to bb * * RETURNS: I-frame appended to bb * * SIDE EFFECTS: none * *===========================================================================*/voidGenIFrame(BitBucket * const bb, MpegFrame * const current) { int x, y; int index; FlatBlock fb[6]; Block dec[6]; int32 y_dc_pred, cr_dc_pred, cb_dc_pred; int totalBits; int totalFrameBits; int32 startTime, endTime; float snr[3], psnr[3]; int mbAddress; int QScale; BlockMV *info; /* Not used in Iframes, but nice to pass in anyway */ int bitstreamMode, newQScale; int rc_blockStart=0; if (dct==NULL) AllocDctBlocks(); if (collect_quant) {fprintf(collect_quant_fp, "# I\n");} /* set-up for statistics */ numFrames++; totalFrameBits = bb->cumulativeBits; if ( showBitRatePerFrame ) { if ( lastNumBits == 0 ) { lastNumBits = bb->cumulativeBits; lastIFrame = current->id; } else { /* ASSUMES 30 FRAMES PER SECOND */ if (! realQuiet) { fprintf(stdout, "I-to-I (frames %5d to %5d) bitrate: %8d\n", lastIFrame, current->id-1, ((bb->cumulativeBits-lastNumBits)*30)/ (current->id-lastIFrame)); } fprintf(bitRateFile, "I-to-I (frames %5d to %5d) bitrate: %8d\n", lastIFrame, current->id-1, ((bb->cumulativeBits-lastNumBits)*30)/ (current->id-lastIFrame)); lastNumBits = bb->cumulativeBits; lastIFrame = current->id; } } startTime = time_elapsed(); Frame_AllocBlocks(current); BlockifyFrame(current); DBG_PRINT(("Generating iframe\n")); QScale = GetIQScale(); /* Allocate bits for this frame for rate control purposes */ bitstreamMode = getRateMode(); if (bitstreamMode == FIXED_RATE) { targetRateControl(current); } Mhead_GenPictureHeader(bb, I_FRAME, current->id, fCodeI); /* Check for Qscale change */ if (specificsOn) { newQScale = SpecLookup(current->id, 0, 0 /* junk */, &info, QScale); if (newQScale != -1) { QScale = newQScale; } /* check for slice */ newQScale = SpecLookup(current->id, 1, 1, &info, QScale); if (newQScale != -1) { QScale = newQScale; } } Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); if ( referenceFrame == DECODED_FRAME ) { Frame_AllocDecoded(current, TRUE); } else if ( printSNR ) { Frame_AllocDecoded(current, FALSE); } y_dc_pred = cr_dc_pred = cb_dc_pred = 128; totalBits = bb->cumulativeBits; mbAddress = 0; /* DCT the macroblocks */ for (y = 0; y < (Fsize_y >> 3); y += 2) { for (x = 0; x < (Fsize_x >> 3); x += 2) { if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); if (DoLaplace) {LaplaceCnum = 0;} 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"); if (DoLaplace) {LaplaceCnum = 1;} mp_fwd_dct_block2(current->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]); if (DoLaplace) {LaplaceCnum = 2;} mp_fwd_dct_block2(current->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]); } } if (DoLaplace) CalcLambdas(); for (y = 0; y < (Fsize_y >> 3); y += 2) { for (x = 0; x < (Fsize_x >> 3); x += 2) { /* Check for Qscale change */ if (specificsOn) { newQScale = SpecLookup(current->id, 2, mbAddress, &info, QScale); if (newQScale != -1) { QScale = newQScale; } } /* Determine if new Qscale needed for Rate Control purposes */ if (bitstreamMode == FIXED_RATE) { rc_blockStart = bb->cumulativeBits; newQScale = needQScaleChange(qscaleI, current->y_blocks[y][x], current->y_blocks[y][x+1], current->y_blocks[y+1][x], current->y_blocks[y+1][x+1]); if (newQScale > 0) { QScale = newQScale; } } if ( (mbAddress % blocksPerSlice == 0) && (mbAddress != 0) ) { /* create a new slice */ if (specificsOn) { /* Make sure no slice Qscale change */ newQScale = SpecLookup(current->id, 1, mbAddress/blocksPerSlice, &info, QScale); if (newQScale != -1) QScale = newQScale; } Mhead_GenSliceEnder(bb); Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0); y_dc_pred = cr_dc_pred = cb_dc_pred = 128; GEN_I_BLOCK(I_FRAME, current, bb, 1+(x>>1), QScale); } else { GEN_I_BLOCK(I_FRAME, current, bb, 1, QScale); } if (WriteDistortionNumbers) { CalcDistortion(current, y, x); } if ( decodeRefFrames ) { /* now, reverse the DCT transform */ LaplaceCnum = 0; for ( index = 0; index < 6; index++ ) { if (!DoLaplace) { Mpost_UnQuantZigBlock(fb[index], dec[index], QScale, TRUE); } else { if (index == 4) {LaplaceCnum = 1;} if (index == 5) {LaplaceCnum = 2;} Mpost_UnQuantZigBlockLaplace(fb[index], dec[index], QScale, TRUE); } mpeg_jrevdct((int16 *)dec[index]); } /* now, unblockify */ BlockToData(current->decoded_y, dec[0], y, x); BlockToData(current->decoded_y, dec[1], y, x+1); BlockToData(current->decoded_y, dec[2], y+1, x); BlockToData(current->decoded_y, dec[3], y+1, x+1); BlockToData(current->decoded_cb, dec[4], y>>1, x>>1); BlockToData(current->decoded_cr, dec[5], y>>1, x>>1); } numBlocks++; mbAddress++; /* Rate Control */ if (bitstreamMode == FIXED_RATE) { incMacroBlockBits(bb->cumulativeBits - rc_blockStart); rc_blockStart = bb->cumulativeBits; MB_RateOut(TYPE_IFRAME); } } } if ( printSNR ) { BlockComputeSNR(current,snr,psnr); totalSNR += snr[0]; totalPSNR += psnr[0]; } numBits += (bb->cumulativeBits-totalBits); DBG_PRINT(("End of frame\n")); Mhead_GenSliceEnder(bb); /* Rate Control */ if (bitstreamMode == FIXED_RATE) { updateRateControl(TYPE_IFRAME); } endTime = time_elapsed(); totalTime += (endTime-startTime); numFrameBits += (bb->cumulativeBits-totalFrameBits); if ( showBitRatePerFrame ) { /* ASSUMES 30 FRAMES PER SECOND */ fprintf(bitRateFile, "%5d\t%8d\n", current->id, 30*(bb->cumulativeBits-totalFrameBits)); } if ( frameSummary && !realQuiet ) { /* ASSUMES 30 FRAMES PER SECOND */ fprintf(stdout, "FRAME %d (I): %ld seconds (%d bits/s output)\n", current->id, (long)((endTime-startTime)/TIME_RATE), 30*(bb->cumulativeBits-totalFrameBits)); if ( printSNR ) { fprintf(stdout, "FRAME %d: SNR: %.1f\t%.1f\t%.1f\t" "PSNR: %.1f\t%.1f\t%.1f\n", current->id, snr[0], snr[1], snr[2], psnr[0], psnr[1], psnr[2]); } }}/*===========================================================================* * * ResetIFrameStats * * reset the I-frame statistics * * RETURNS: nothing * * SIDE EFFECTS: none * *===========================================================================*/voidResetIFrameStats(){ numBlocks = 0; numBits = 0; numFrames = 0; numFrameBits = 0; totalTime = 0;}floatIFrameTotalTime(void) { return (float)totalTime/(float)TIME_RATE;}voidShowIFrameSummary(unsigned int const inputFrameBits, unsigned int const totalBits, FILE * const fpointer) {/*---------------------------------------------------------------------------- Print out statistics on all I frames.-----------------------------------------------------------------------------*/ if (numFrames > 0) { fprintf(fpointer, "-------------------------\n"); fprintf(fpointer, "*****I FRAME SUMMARY*****\n"); fprintf(fpointer, "-------------------------\n"); fprintf(fpointer, " Blocks: %5d (%6d bits) (%5d bpb)\n", numBlocks, numBits, numBits/numBlocks); fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf)" "(%2.1f%% of total)\n", numFrames, numFrameBits, numFrameBits/numFrames, 100.0*(float)numFrameBits/(float)totalBits); fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n", numFrames*inputFrameBits/numFrameBits, 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits)); if ( printSNR ) fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n", totalSNR/(float)numFrames, totalPSNR/(float)numFrames); if ( totalTime == 0 ) { fprintf(fpointer, " Seconds: NONE\n"); } else { fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) " "(%9ld mps)\n", (long)(totalTime/TIME_RATE), (float)((float)(TIME_RATE*numFrames)/(float)totalTime), (long)((float)TIME_RATE * (float)numFrames * (float)inputFrameBits/(24.0*(float)totalTime)), (long)((float)TIME_RATE*(float)numFrames * (float)inputFrameBits/(256.0*24.0 * (float)totalTime))); } }}/*===========================================================================* * * EstimateSecondsPerIFrame * * estimates the number of seconds required per I-frame * * RETURNS: seconds (floating point value) * * SIDE EFFECTS: none * *===========================================================================*/floatEstimateSecondsPerIFrame(){ return (float)totalTime/((float)TIME_RATE*(float)numFrames);}/*===========================================================================* * * EncodeYDC * * Encode the DC portion of a DCT of a luminance block * * RETURNS: result appended to bb * * SIDE EFFECTS: updates pred_term * *===========================================================================*/voidEncodeYDC(dc_term, pred_term, bb) int32 dc_term; int32 *pred_term; BitBucket *bb;{ /* see Table B.5a -- MPEG-I doc */ static int codes[9] = { 0x4, 0x0, 0x1, 0x5, 0x6, 0xe, 0x1e, 0x3e, 0x7e }; static int codeLengths[9] = { 3, 2, 2, 3, 3, 4, 5, 6, 7 }; int ydiff, ydiff_abs; int length; ydiff = (dc_term - (*pred_term)); if (ydiff > 255) {#ifdef BLEAH fprintf(stdout, "TRUNCATED\n");#endif ydiff = 255; } else if (ydiff < -255) {#ifdef BLEAH fprintf(stdout, "TRUNCATED\n");#endif ydiff = -255; } ydiff_abs = ABS(ydiff); length = lengths[ydiff_abs]; Bitio_Write(bb, codes[length], codeLengths[length]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -