int FrameCodeP(Encoder * pEnc,Bitstream * bs) { int bits = BitstreamPos(bs); int iLimit,x,y; int bIntra=0, skip_possible; FRAMEINFO *const current = pEnc->current; /*当前编码帧*/ FRAMEINFO *const reference = pEnc->reference; /*重建参考帧*/ MBParam * const pParam = &pEnc->mbParam; /*宏块编码结构信息*/ const uint32_t mb_width = pParam->mb_width; /*宏块宽度*/ const uint32_t mb_height = pParam->mb_height; /*宏块高度*/ const uint32_t edged_width = pParam->edged_width; /*扩展图像宽度*/ DECLARE_ALIGNED_MATRIX(dct_coeff , 6, 64, int16_t, CACHE_LINE); /*DCT系数*/ DECLARE_ALIGNED_MATRIX(qnt_coeff , 6, 64, int16_t, CACHE_LINE); /*DCT系数量化结果*/ pParam->m_rounding_type = 1 - pParam->m_rounding_type; current->rounding_type = pParam->m_rounding_type; current->fcode = pParam->m_fcode; current->coding_type = P_VOP; pEnc->current->mbs[0].quant = pEnc->current->quant; SetMacroblockQuants(&pEnc->mbParam, current); /*初始化宏块量化步长*/ /*运动估计模块,把当前图像与上一帧的重建帧做最佳匹配,根据SAD抉择*/ iLimit = (mb_width * mb_height)>>1; /*当Intra块超过宏块的50%时,强制I帧编码*/ bIntra = MotionEstimation(&pEnc->mbParam, current, reference,iLimit); if (bIntra == 1) return FrameCodeI(pEnc, bs);/* bIntra为1则执行I帧编码,如场景切换*/ set_timecodes(current,reference,pParam->fbase); /*写VOP头信息到码流*/ BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 1, current->mbs[0].quant); /*初始化状态统计变量*/ current->sStat.iTextBits = current->sStat. iMvSum = current->sStat.iMvCount = current->sStat.kblks = current->sStat.mblks = current->sStat.ublks = 0; /*以宏块为单位循环编码*/ for (y = 0; y < mb_height; y++) { for (x = 0; x < mb_width; x++) { MACROBLOCK *pMB = ¤t->mbs[x + y * mb_width]; bIntra = (pMB->mode == MODE_INTRA); if (bIntra){ /*Intra块编码,即I帧编码的核心函数*/ CodeIntraMB(pEnc, pMB); MBTransQuantIntra(&pEnc->mbParam, current, pMB, x, y, dct_coeff, qnt_coeff); MBPrediction(current, x, y, mb_width, qnt_coeff); MBCoding(current, pMB, qnt_coeff, bs, ¤t->sStat); continue; } /*运动补偿,根据运动向量确定具体的宏块参考位置, 并做差值计算,结果存放dct_coeff中*/ MBMotionCompensation(pMB, x, y, pRef, pCur, dct_coeff, pParam-> edged_width); /*差值做DCT、量化、反量化、IDCT,并更新到当前图像*/ if (pMB->mode != MODE_NOT_CODED) /*差值编码,即差值不全为零*/ pMB->cbp =MBTransQuantInter(&pEnc->mbParam, current,
pMB, x, y, dct_coeff, qnt_coeff); skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER); if (current->coding_type == P_VOP) skip_possible &= ( (pMB->mvs[0].x == 0) && (pMB->mvs[0].y == 0) ); /*宏块没有编码,跳过该宏块,继续编码*/ if ( (pMB->mode == MODE_NOT_CODED) || (skip_possible)) { pMB->mode = MODE_NOT_CODED; MBSkip(bs); continue; } /*宏块编码,即差值的DCT系数量化值做VLC编码*/ MBCoding(current, pMB, qnt_coeff, bs, &pEnc->current->sStat); } } pParam->m_fcode = 1; /*运动估计ME搜索窗口*/ pEnc->current->is_edged = 0; /*没有做扩展*/ BitstreamPadAlways(bs); /*填充编码后的比特流*/ current->length = (BitstreamPos(bs) - bits) / 8; /*编码后的码流长度*/ return 0;
|