--- encoder.c 2003/01/13 14:33:24 1.76.2.37 +++ encoder.c 2003/02/17 23:45:21 1.93 @@ -26,20 +26,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - ****************************************************************************/ - -/***************************************************************************** - * - * History - * - * 10.07.2002 added BFRAMES_DEC_DEBUG support - * MinChen - * 20.06.2002 bframe patch - * 08.05.2002 fix some problem in DEBUG mode; - * MinChen - * 14.04.2002 added FrameCodeB() - * - * $Id: encoder.c,v 1.76.2.37 2003/01/13 14:33:24 chl Exp $ + * $Id: encoder.c,v 1.93 2003/02/17 23:45:21 edgomez Exp $ * ****************************************************************************/ @@ -229,7 +216,7 @@ pEnc->bitrate = pParam->rc_bitrate; - pEnc->iFrameNum = 0; + pEnc->iFrameNum = -1; pEnc->mbParam.iMaxKeyInterval = pParam->max_key_interval; /* try to allocate frame memory */ @@ -254,9 +241,8 @@ /* try to allocate image memory */ -#ifdef _DEBUG_PSNR - image_null(&pEnc->sOriginal); -#endif + if (pParam->global & XVID_GLOBAL_EXTRASTATS) + image_null(&pEnc->sOriginal); image_null(&pEnc->f_refh); image_null(&pEnc->f_refv); @@ -270,12 +256,12 @@ image_null(&pEnc->vInterHV); image_null(&pEnc->vInterHVf); -#ifdef _DEBUG_PSNR - if (image_create - (&pEnc->sOriginal, pEnc->mbParam.edged_width, - pEnc->mbParam.edged_height) < 0) - goto xvid_err_memory3; -#endif + if (pParam->global & XVID_GLOBAL_EXTRASTATS) + { if (image_create + (&pEnc->sOriginal, pEnc->mbParam.edged_width, + pEnc->mbParam.edged_height) < 0) + goto xvid_err_memory3; + } if (image_create (&pEnc->f_refh, pEnc->mbParam.edged_width, @@ -326,9 +312,10 @@ goto xvid_err_memory3; - /* B Frames specific init */ pEnc->mbParam.global = pParam->global; + + /* B Frames specific init */ pEnc->mbParam.max_bframes = pParam->max_bframes; pEnc->mbParam.bquant_ratio = pParam->bquant_ratio; pEnc->mbParam.bquant_offset = pParam->bquant_offset; @@ -464,10 +451,11 @@ } xvid_err_memory3: -#ifdef _DEBUG_PSNR - image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, - pEnc->mbParam.edged_height); -#endif + + if (pEnc->mbParam.global & XVID_GLOBAL_EXTRASTATS) + { image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, + pEnc->mbParam.edged_height); + } image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); @@ -583,10 +571,10 @@ image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); -#ifdef _DEBUG_PSNR - image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, - pEnc->mbParam.edged_height); -#endif + if (pEnc->mbParam.global & XVID_GLOBAL_EXTRASTATS) + { image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, + pEnc->mbParam.edged_height); + } /* Encoder structure */ @@ -604,7 +592,7 @@ static __inline void inc_frame_num(Encoder * pEnc) { - pEnc->current->stamp = pEnc->mbParam.m_stamp; // first frame is zero + pEnc->current->stamp = pEnc->mbParam.m_stamp; /* first frame is zero */ pEnc->mbParam.m_stamp += pEnc->mbParam.fincr; } @@ -630,6 +618,11 @@ return; stop_conv_timer(); + if ((pFrame->general & XVID_CHROMAOPT)) { + image_chroma_optimize(&pEnc->queue[pEnc->queue_tail], + pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); + } + pEnc->queue_size++; pEnc->queue_tail = (pEnc->queue_tail + 1) % pEnc->mbParam.max_bframes; } @@ -641,7 +634,7 @@ pCur->ticks = (int32_t)pCur->stamp % time_base; pCur->seconds = ((int32_t)pCur->stamp / time_base) - ((int32_t)pRef->stamp / time_base) ; - //HEAVY DEBUG OUTPUT remove when timecodes prove to be stable + /* HEAVY DEBUG OUTPUT remove when timecodes prove to be stable */ /* fprintf(stderr,"WriteVop: %d - %d \n", ((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base)); @@ -658,10 +651,10 @@ /* convert pFrame->intra to coding_type */ static int intra2coding_type(int intra) { - if (intra < 0) return -1; - if (intra == 1) return I_VOP; - if (intra == 2) return B_VOP; - + if (intra < 0) return -1; + if (intra == 1) return I_VOP; + if (intra == 2) return B_VOP; + return P_VOP; } @@ -689,11 +682,6 @@ int input_valid = 1; int bframes_count = 0; -#ifdef _DEBUG_PSNR - float psnr; - char temp[128]; -#endif - ENC_CHECK(pEnc); ENC_CHECK(pFrame); ENC_CHECK(pFrame->image); @@ -734,8 +722,17 @@ pFrame->length = BitstreamLength(&bs); pFrame->intra = 0; + emms(); + if (pResult) { + pResult->quant = pEnc->current->quant; + pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8); + pResult->kblks = pEnc->current->sStat.kblks; + pResult->mblks = pEnc->current->sStat.mblks; + pResult->ublks = pEnc->current->sStat.ublks; + } + return XVID_ERR_OK; } @@ -751,6 +748,14 @@ pFrame->length = BitstreamLength(&bs); pFrame->intra = 2; + if (pResult) { + pResult->quant = pEnc->current->quant; + pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8); + pResult->kblks = pEnc->current->sStat.kblks; + pResult->mblks = pEnc->current->sStat.mblks; + pResult->ublks = pEnc->current->sStat.ublks; + } + if (input_valid) queue_image(pEnc, pFrame); @@ -787,6 +792,14 @@ pFrame->length = BitstreamLength(&bs); pFrame->intra = 4; + if (pResult) { + pResult->quant = pEnc->current->quant; + pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8); + pResult->kblks = pEnc->current->sStat.kblks; + pResult->mblks = pEnc->current->sStat.mblks; + pResult->ublks = pEnc->current->sStat.ublks; + } + if (input_valid) queue_image(pEnc, pFrame); @@ -829,7 +842,12 @@ } stop_conv_timer(); - // queue input frame, and dequue next image + if ((pFrame->general & XVID_CHROMAOPT)) { + image_chroma_optimize(&pEnc->current->image, + pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); + } + + /* queue input frame, and dequue next image */ if (pEnc->queue_size > 0) { image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_tail]); @@ -860,12 +878,48 @@ pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); - // BitstreamPutBits(&bs, 0x7f, 8); + /* That disabled line of code was supposed to inform VirtualDub + * that the frame was a dummy delay frame - now disabled (thx god :-) + */ + /* BitstreamPutBits(&bs, 0x7f, 8); */ pFrame->intra = 5; + + if (pResult) { + /* + * We must decide what to put there because i know some apps + * are storing statistics about quantizers and just do + * stats[quant]++ or stats[quant-1]++ + * transcode is one of these app with its 2pass module + */ + + /* + * For now i prefer 31 than 0 that could lead to a segfault + * in transcode + */ + pResult->quant = 31; + + pResult->hlength = 0; + pResult->kblks = 0; + pResult->mblks = 0; + pResult->ublks = 0; + } + + } else { + + if (pResult) { + pResult->quant = pEnc->current->quant; + pResult->hlength = pFrame->length - (pEnc->current->sStat.iTextBits / 8); + pResult->kblks = pEnc->current->sStat.kblks; + pResult->mblks = pEnc->current->sStat.mblks; + pResult->ublks = pEnc->current->sStat.ublks; + } + } pFrame->length = BitstreamLength(&bs); + emms(); + return XVID_ERR_OK; } @@ -873,7 +927,7 @@ emms(); - // only inc frame num, adapt quant, etc. if we havent seen it before + /* only inc frame num, adapt quant, etc. if we havent seen it before */ if (pEnc->bframenum_dx50bvop < 0 ) { mode = intra2coding_type(pFrame->intra); @@ -897,10 +951,10 @@ inc_frame_num(pEnc); -#ifdef _DEBUG_PSNR - image_copy(&pEnc->sOriginal, &pEnc->current->image, - pEnc->mbParam.edged_width, pEnc->mbParam.height); -#endif + if (pFrame->general & XVID_EXTRASTATS) + { image_copy(&pEnc->sOriginal, &pEnc->current->image, + pEnc->mbParam.edged_width, pEnc->mbParam.height); + } emms(); @@ -989,7 +1043,7 @@ image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP"); } - // when we reach an iframe in DX50BVOP mode, encode the last bframe as a pframe + /* when we reach an iframe in DX50BVOP mode, encode the last bframe as a pframe */ if ((pEnc->mbParam.global & XVID_GLOBAL_DX50BVOP) && pEnc->bframenum_tail > 0) { @@ -1002,9 +1056,8 @@ } FrameCodeP(pEnc, &bs, &bits, 1, 0); bframes_count = 0; - pFrame->intra = 0; - + } else { FrameCodeI(pEnc, &bs, &bits); @@ -1026,7 +1079,7 @@ * NB : sequences like "IIBB" decode fine with msfdam but, * go screwy with divx 5.00 */ - } else if (mode == P_VOP || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { + } else if (mode == P_VOP || mode == S_VOP || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { /* * This will be coded as a Predicted Frame */ @@ -1082,7 +1135,7 @@ pEnc->bframenum_tail++; -// bframe report by koepi + /* bframe report by koepi */ pFrame->intra = 2; pFrame->length = 0; @@ -1099,20 +1152,27 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + + if (pFrame->general & XVID_EXTRASTATS) + { pResult->sse_y = + plane_sse( pEnc->sOriginal.y, pEnc->current->image.y, + pEnc->mbParam.edged_width, pEnc->mbParam.width, + pEnc->mbParam.height); + + pResult->sse_u = + plane_sse( pEnc->sOriginal.u, pEnc->current->image.u, + pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2, + pEnc->mbParam.height/2); + + pResult->sse_v = + plane_sse( pEnc->sOriginal.v, pEnc->current->image.v, + pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2, + pEnc->mbParam.height/2); + } } emms(); -#ifdef _DEBUG_PSNR - psnr = - image_psnr(&pEnc->sOriginal, &pEnc->current->image, - pEnc->mbParam.edged_width, pEnc->mbParam.width, - pEnc->mbParam.height); - - printf("PSNR: %f\n", psnr); -// DEBUG(temp); -#endif - if (pFrame->quant == 0) { RateControlUpdate(&pEnc->rate_control, pEnc->current->quant, pFrame->length, pFrame->intra); @@ -1146,10 +1206,8 @@ uint32_t bits; uint16_t write_vol_header = 0; -#ifdef _DEBUG_PSNR float psnr; uint8_t temp[128]; -#endif start_global_timer(); @@ -1180,10 +1238,15 @@ return XVID_ERR_FORMAT; stop_conv_timer(); -#ifdef _DEBUG_PSNR - image_copy(&pEnc->sOriginal, &pEnc->current->image, - pEnc->mbParam.edged_width, pEnc->mbParam.height); -#endif + if ((pFrame->general & XVID_CHROMAOPT)) { + image_chroma_optimize(&pEnc->current->image, + pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); + } + + if (pFrame->general & XVID_EXTRASTATS) + { image_copy(&pEnc->sOriginal, &pEnc->current->image, + pEnc->mbParam.edged_width, pEnc->mbParam.height); + } emms(); @@ -1260,7 +1323,7 @@ } if (pFrame->intra < 0) { - if ((pEnc->iFrameNum == 0) + if ((pEnc->iFrameNum == -1) || ((pEnc->mbParam.iMaxKeyInterval > 0) && (pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval))) { pFrame->intra = FrameCodeI(pEnc, &bs, &bits); @@ -1276,8 +1339,11 @@ } -// BitstreamPutBits(&bs, 0xFFFF, 16); -// BitstreamPutBits(&bs, 0xFFFF, 16); + /* Relic from OpenDivX - now disabled + BitstreamPutBits(&bs, 0xFFFF, 16); + BitstreamPutBits(&bs, 0xFFFF, 16); + */ + BitstreamPadAlways(&bs); pFrame->length = BitstreamLength(&bs); @@ -1295,15 +1361,15 @@ RateControlUpdate(&pEnc->rate_control, pEnc->current->quant, pFrame->length, pFrame->intra); } -#ifdef _DEBUG_PSNR - psnr = - image_psnr(&pEnc->sOriginal, &pEnc->current->image, - pEnc->mbParam.edged_width, pEnc->mbParam.width, - pEnc->mbParam.height); - - snprintf(temp, 127, "PSNR: %f\n", psnr); -// DEBUG(temp); -#endif + if (pFrame->general & XVID_EXTRASTATS) + { + psnr = + image_psnr(&pEnc->sOriginal, &pEnc->current->image, + pEnc->mbParam.edged_width, pEnc->mbParam.width, + pEnc->mbParam.height); + + snprintf(temp, 127, "PSNR: %f\n", psnr); + } pEnc->iFrameNum++; @@ -1428,7 +1494,7 @@ pMB->pmvs[vec].x = pMB->mvs[vec].x - pred.x; pMB->pmvs[vec].y = pMB->mvs[vec].y - pred.y; } - } else // intra / stuffing / not_coded + } else /* intra / stuffing / not_coded */ { for (vec = 0; vec < 4; ++vec) { pMB->mvs[vec].x = pMB->mvs[vec].y = 0; @@ -1625,7 +1691,7 @@ HintedMEGet(pEnc, 1); } - return 1; // intra + return 1; /* intra */ } @@ -1766,6 +1832,14 @@ int32_t iSAD = sad16(pEnc->current->image.y + 16*y*pEnc->mbParam.edged_width + 16*x, pEnc->vGMC.y + 16*y*pEnc->mbParam.edged_width + 16*x, pEnc->mbParam.edged_width, 65536); + + if (pEnc->current->motion_flags & PMV_CHROMA16) { + iSAD += sad8(pEnc->current->image.u + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, + pEnc->vGMC.u + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, pEnc->mbParam.edged_width/2); + + iSAD += sad8(pEnc->current->image.v + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, + pEnc->vGMC.v + 8*y*(pEnc->mbParam.edged_width/2) + 8*x, pEnc->mbParam.edged_width/2); + } if (iSAD <= pMB->sad16) { /* mode decision GMC */ @@ -1955,14 +2029,14 @@ iSearchRange = 1 << (3 + pEnc->mbParam.m_fcode); if ((fSigma > iSearchRange / 3) - && (pEnc->mbParam.m_fcode <= (3 + pEnc->mbParam.m_quarterpel))) // maximum search range 128 + && (pEnc->mbParam.m_fcode <= (3 + pEnc->mbParam.m_quarterpel))) /* maximum search range 128 */ { pEnc->mbParam.m_fcode++; iSearchRange *= 2; } else if ((fSigma < iSearchRange / 6) && (pEnc->fMvPrevSigma >= 0) && (pEnc->fMvPrevSigma < iSearchRange / 6) - && (pEnc->mbParam.m_fcode >= (2 + pEnc->mbParam.m_quarterpel))) // minimum search range 16 + && (pEnc->mbParam.m_fcode >= (2 + pEnc->mbParam.m_quarterpel))) /* minimum search range 16 */ { pEnc->mbParam.m_fcode--; iSearchRange /= 2; @@ -1983,7 +2057,7 @@ set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 0); - // copy reference frame details into the current frame + /* copy reference frame details into the current frame */ pEnc->current->quant = pEnc->reference->quant; pEnc->current->motion_flags = pEnc->reference->motion_flags; pEnc->current->rounding_type = pEnc->reference->rounding_type; @@ -2012,7 +2086,7 @@ *pBits = BitstreamPos(bs) - *pBits; - return 0; // inter + return 0; /* inter */ } @@ -2045,7 +2119,7 @@ frame->quarterpel = pEnc->mbParam.m_quarterpel; - // forward + /* forward */ image_setedges(f_ref, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, pEnc->mbParam.width, pEnc->mbParam.height); @@ -2055,7 +2129,7 @@ pEnc->mbParam.m_quarterpel, 0); stop_inter_timer(); - // backward + /* backward */ image_setedges(b_ref, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, pEnc->mbParam.width, pEnc->mbParam.height); @@ -2068,9 +2142,9 @@ start_timer(); MotionEstimationBVOP(&pEnc->mbParam, frame, - ((int32_t)(pEnc->current->stamp - frame->stamp)), // time_bp - ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)), // time_pp - pEnc->reference->mbs, f_ref, + ((int32_t)(pEnc->current->stamp - frame->stamp)), /* time_bp */ + ((int32_t)(pEnc->current->stamp - pEnc->reference->stamp)), /* time_pp */ + pEnc->reference->mbs, f_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv, pEnc->current, b_ref, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV); @@ -2078,10 +2152,11 @@ stop_motion_timer(); - /*if (test_quant_type(&pEnc->mbParam, pEnc->current)) - { - BitstreamWriteVolHeader(bs, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.quant_type); - } */ + /* + if (test_quant_type(&pEnc->mbParam, pEnc->current)) { + BitstreamWriteVolHeader(bs, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.quant_type); + } + */ frame->coding_type = B_VOP; @@ -2101,9 +2176,9 @@ MACROBLOCK * const mb = &frame->mbs[x + y * pEnc->mbParam.mb_width]; int direction = pEnc->mbParam.global & XVID_ALTERNATESCAN ? 2 : 0; - // decoder ignores mb when refence block is INTER(0,0), CBP=0 + /* decoder ignores mb when refence block is INTER(0,0), CBP=0 */ if (mb->mode == MODE_NOT_CODED) { - //mb->mvs[0].x = mb->mvs[0].y = mb->cbp = 0; + /* mb->mvs[0].x = mb->mvs[0].y = mb->cbp = 0; */ continue; } @@ -2122,7 +2197,7 @@ if ( (mb->mode == MODE_DIRECT) && (mb->cbp == 0) && (mb->pmvs[3].x == 0) && (mb->pmvs[3].y == 0) ) { - mb->mode = MODE_DIRECT_NONE_MV; // skipped + mb->mode = MODE_DIRECT_NONE_MV; /* skipped */ } } @@ -2138,7 +2213,7 @@ emms(); - // TODO: dynamic fcode/bcode ??? + /* TODO: dynamic fcode/bcode ??? */ *pBits = BitstreamPos(bs) - *pBits;