📄 picture.cc
字号:
************************************************************************/void Picture::Adjust2ndField(){ secondfield = true; gop_start = false; if( pict_struct == TOP_FIELD ) pict_struct = BOTTOM_FIELD; else pict_struct = TOP_FIELD; if( pict_type == I_TYPE ) { ipflag = 1; pict_type = P_TYPE; forw_hor_f_code = encparams.motion_data[0].forw_hor_f_code; forw_vert_f_code = encparams.motion_data[0].forw_vert_f_code; back_hor_f_code = 15; back_vert_f_code = 15; sxf = encparams.motion_data[0].sxf; syf = encparams.motion_data[0].syf; }}void Picture::EncodeMacroBlocks(){ vector<MacroBlock>::iterator mbi = mbinfo.begin(); for( mbi = mbinfo.begin(); mbi < mbinfo.end(); ++mbi) { mbi->Encode(); }}void Picture::IQuantize(){ int k; for (k=0; k<encparams.mb_per_pict; k++) { mbinfo[k].IQuantize( quantizer ); }}void Picture::ActivityMeasures( double &act_sum, double &var_sum){ int i,j,k,l; double actj,sum; double varsum; int blksum; sum = 0.0; varsum = 0.0; k = 0; for (j=0; j<encparams.enc_height2; j+=16) for (i=0; i<encparams.enc_width; i+=16) { /* A.Stevens Jul 2000 Luminance variance *has* to be a rotten measure of how active a block in terms of bits needed to code a lossless DCT. E.g. a half-white half-black block has a maximal variance but pretty small DCT coefficients. So.... instead of luminance variance as used in the original we use the absolute sum of DCT coefficients as our block activity measure. */ varsum += (double)mbinfo[k].final_me.var; if( mbinfo[k].final_me.mb_type & MB_INTRA ) { /* Compensate for the wholly disproprotionate weight of the DC coefficients. Shold produce more sensible results... yes... it *is* an mostly empirically derived fudge factor ;-) */ blksum = -80*COEFFSUM_SCALE; for( l = 0; l < 6; ++l ) blksum += quantizer.WeightCoeffIntra( mbinfo[k].RawDCTblocks()[l] ) ; } else { blksum = 0; for( l = 0; l < 6; ++l ) blksum += quantizer.WeightCoeffInter( mbinfo[k].RawDCTblocks()[l] ) ; } /* It takes some bits to code even an entirely zero block... It also makes a lot of calculations a lot better conditioned if it can be guaranteed that activity is always distinctly non-zero. */ actj = (double)blksum / (double)COEFFSUM_SCALE; if( actj < 12.0 ) actj = 12.0; mbinfo[k].act = (double)actj; sum += (double)actj; ++k; } act_sum = sum; var_sum = varsum;}/* inverse transform prediction error and add prediction */void Picture::ITransform(){ vector<MacroBlock>::iterator mbi; for( mbi = mbinfo.begin(); mbi < mbinfo.end(); ++mbi) { mbi->ITransform(); }}void Picture::MotionSubSampledLum( ){ int linestride; EncoderParams &eparams = encparams; /* In an interlaced field the "next" line is 2 width's down rather than 1 width down . TODO: Shoudn't we be treating the frame as interlaced for frame based interlaced encoding too... or at least for the interlaced ME modes? */ if (!eparams.fieldpic) { linestride = eparams.phy_width; } else { linestride = 2*eparams.phy_width; } psubsample_image( org_img[0], linestride, org_img[0]+eparams.fsubsample_offset, org_img[0]+eparams.qsubsample_offset );}/* ************************************************ * * QuantiseAndEncode - Quantise and Encode a picture. * * NOTE: It may seem perverse to quantise at the same time as * coding-> However, actually makes (limited) sense * - feedback from the *actual* bit-allocation may be used to adjust * quantisation "on the fly". This is good for fast 1-pass no-look-ahead coding-> * - The coded result is in any even only buffered not actually written * out. We can back off and try again with a different quantisation * easily. * - The alternative is calculating size and generating actual codes seperately. * The poorer cache coherence of this latter probably makes the performance gain * modest. * * *********************************************** */void Picture::QuantiseAndEncode(RateCtl &ratectl){ InitRateControl( ratectl ); PutHeaders(); /* Now the actual quantisation and encoding->.. */ int i, j, k; int MBAinc; MacroBlock *cur_mb = 0; int mquant_pred = ratectl.InitialMacroBlockQuant(*this); k = 0; /* TODO: We're currently hard-wiring each macroblock row as a slice. For MPEG-2 we could do this better and reduce slice start code coverhead... */ for (j=0; j<encparams.mb_height2; j++) { PutSliceHdr(j, mquant_pred); Reset_DC_DCT_Pred(); Reset_MV_Pred(); MBAinc = 1; /* first MBAinc denotes absolute position */ /* Slice macroblocks... */ for (i=0; i<encparams.mb_width; i++) { prev_mb = cur_mb; cur_mb = &mbinfo[k]; int suggested_mquant = ratectl.MacroBlockQuant( *cur_mb ); cur_mb->mquant = suggested_mquant; /* Quantize macroblock : N.b. the MB_PATTERN bit may be set as a side-effect of this call. */ cur_mb->Quantize( quantizer); /* Output mquant and update prediction if it changed in this macroblock */ if( cur_mb->cbp && suggested_mquant != mquant_pred ) { mquant_pred = suggested_mquant; cur_mb->final_me.mb_type |= MB_QUANT; } /* Check to see if Macroblock is skippable, this may set the MB_FORWARD bit... */ bool slice_begin_or_end = (i==0 || i==encparams.mb_width-1); cur_mb->SkippedCoding(slice_begin_or_end); if( cur_mb->skipped ) { ++MBAinc; } else { coding->PutAddrInc(MBAinc); /* macroblock_address_increment */ MBAinc = 1; coding->PutMBType(pict_type,cur_mb->final_me.mb_type); /* macroblock type */ if ( (cur_mb->final_me.mb_type & (MB_FORWARD|MB_BACKWARD)) && !frame_pred_dct) coding->PutBits(cur_mb->final_me.motion_type,2); if (pict_struct==FRAME_PICTURE && cur_mb->cbp && !frame_pred_dct) coding->PutBits(cur_mb->field_dct,1); if (cur_mb->final_me.mb_type & MB_QUANT) { coding->PutBits(q_scale_type ? map_non_linear_mquant[cur_mb->mquant] : cur_mb->mquant>>1,5); } if (cur_mb->final_me.mb_type & MB_FORWARD) { /* forward motion vectors, update predictors */ PutMVs( cur_mb->final_me, false ); } if (cur_mb->final_me.mb_type & MB_BACKWARD) { /* backward motion vectors, update predictors */ PutMVs( cur_mb->final_me, true ); } if (cur_mb->final_me.mb_type & MB_PATTERN) { coding->PutCPB((cur_mb->cbp >> (BLOCK_COUNT-6)) & 63); } /* Output VLC DCT Blocks for Macroblock */ cur_mb->PutBlocks( ); /* reset predictors */ if (!(cur_mb->final_me.mb_type & MB_INTRA)) Reset_DC_DCT_Pred(); if (cur_mb->final_me.mb_type & MB_INTRA || (pict_type==P_TYPE && !(cur_mb->final_me.mb_type & MB_FORWARD))) { Reset_MV_Pred(); } } ++k; } /* Slice MB loop */ } /* Slice loop */ int padding_needed; bool recoding_suggested; ratectl.UpdatePict( *this, padding_needed); coding->AlignBits(); if( padding_needed > 0 ) { mjpeg_debug( "Padding coded picture to size: %d extra bytes", padding_needed ); for( i = 0; i < padding_needed; ++i ) { coding->PutBits(0, 8); } } /* Handle splitting of output stream into sequences of desired size */ if( end_seq ) { coding->PutSeqEnd(); } }/* ***************** * * InitRateControl - Setup rate controller new current picture / GOP/ Sequence * ******************/void Picture::InitRateControl( RateCtl &ratecontrol ){ /* Handle splitting of output stream into sequences of desired size */ if( new_seq ) { ratecontrol.InitSeq(true); } /* Handle start of GOP stuff: We've reach a new GOP so we emit what we coded for the previous one as (for the moment) and mark the resulting coder state for eventual backup. Currently, we never backup more that to the start of the current GOP. */ if( gop_start ) { ratecontrol.InitGOP( np, nb); } ratecontrol.CalcVbvDelay(*this); ratecontrol.InitNewPict(*this); /* set up rate control */}int Picture::SizeCodedMacroBlocks() const{ return coding->ByteCount() * 8; }double Picture::IntraCodedBlocks() const{ vector<MacroBlock>::const_iterator mbi = mbinfo.begin(); int intra = 0; for( mbi = mbinfo.begin(); mbi < mbinfo.end(); ++mbi) { if( mbi->final_me.mb_type&MB_INTRA ) ++intra; } return static_cast<double>(intra) / mbinfo.size();}/* ********************* * * Commit - Commit to the current encoding of the frame * flush the coder buffer content to the elementary stream output. * * *********************/ void Picture::Commit() { coding->FlushBuffer(); }/* * Local variables: * c-file-style: "stroustrup" * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -