--- encoder.c 2003/01/11 14:59:23 1.76.2.35 +++ encoder.c 2003/01/25 22:44:50 1.76.2.41 @@ -39,7 +39,7 @@ * MinChen * 14.04.2002 added FrameCodeB() * - * $Id: encoder.c,v 1.76.2.35 2003/01/11 14:59:23 chl Exp $ + * $Id: encoder.c,v 1.76.2.41 2003/01/25 22:44:50 chl Exp $ * ****************************************************************************/ @@ -229,7 +229,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 +254,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 +269,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 +325,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 +464,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 +584,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 */ @@ -658,10 +659,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,10 +690,8 @@ int input_valid = 1; int bframes_count = 0; -#ifdef _DEBUG_PSNR float psnr; char temp[128]; -#endif ENC_CHECK(pEnc); ENC_CHECK(pFrame); @@ -730,12 +729,21 @@ FrameCodeP(pEnc, &bs, &bits, 1, 0); bframes_count = 0; - BitstreamPad(&bs); + BitstreamPadAlways(&bs); 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; } @@ -747,10 +755,18 @@ FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs, &bits); pEnc->bframenum_head++; - BitstreamPad(&bs); + BitstreamPadAlways(&bs); 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); @@ -776,16 +792,25 @@ pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); - BitstreamPad(&bs); tmp = pEnc->current->seconds; pEnc->current->seconds = 0; /* force time_base = 0 */ + BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0); pEnc->current->seconds = tmp; + BitstreamPadAlways(&bs); 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); @@ -859,12 +884,45 @@ pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); - BitstreamPutBits(&bs, 0x7f, 8); + // 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; } @@ -896,10 +954,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(); @@ -1001,9 +1059,8 @@ } FrameCodeP(pEnc, &bs, &bits, 1, 0); bframes_count = 0; - pFrame->intra = 0; - + } else { FrameCodeI(pEnc, &bs, &bits); @@ -1025,7 +1082,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 */ @@ -1089,7 +1146,7 @@ goto bvop_loop; } - BitstreamPad(&bs); + BitstreamPadAlways(&bs); pFrame->length = BitstreamLength(&bs); if (pResult) { @@ -1098,20 +1155,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); @@ -1145,10 +1209,8 @@ uint32_t bits; uint16_t write_vol_header = 0; -#ifdef _DEBUG_PSNR float psnr; uint8_t temp[128]; -#endif start_global_timer(); @@ -1179,10 +1241,10 @@ 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_EXTRASTATS) + { image_copy(&pEnc->sOriginal, &pEnc->current->image, + pEnc->mbParam.edged_width, pEnc->mbParam.height); + } emms(); @@ -1275,9 +1337,9 @@ } - BitstreamPutBits(&bs, 0xFFFF, 16); - BitstreamPutBits(&bs, 0xFFFF, 16); - BitstreamPad(&bs); +// BitstreamPutBits(&bs, 0xFFFF, 16); +// BitstreamPutBits(&bs, 0xFFFF, 16); + BitstreamPadAlways(&bs); pFrame->length = BitstreamLength(&bs); if (pResult) { @@ -1294,15 +1356,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++; @@ -1468,7 +1530,7 @@ if (intra) { if (!hint->rawhints) { - BitstreamPad(&bs); + BitstreamPadAlways(&bs); hint->hintlength = BitstreamLength(&bs); } return; @@ -1574,6 +1636,8 @@ BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); + + BitstreamPadAlways(bs); BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1); *pBits = BitstreamPos(bs); @@ -1713,15 +1777,17 @@ generate_GMCimage(&pEnc->current->gmc_data, &pEnc->reference->image, pEnc->mbParam.mb_width, pEnc->mbParam.mb_height, pEnc->mbParam.edged_width, pEnc->mbParam.edged_width/2, - pEnc->mbParam.m_fcode, 0, 0, + pEnc->mbParam.m_fcode, pEnc->mbParam.m_quarterpel, 0, pEnc->current->rounding_type, pEnc->current->mbs, &pEnc->vGMC); } + set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); if (vol_header) - BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); + { BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); + BitstreamPadAlways(bs); + } - set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1); *pBits = BitstreamPos(bs); @@ -1738,7 +1804,6 @@ /* Mode decision: Check, if the block should be INTRA / INTER or GMC-coded */ /* For a start, leave INTRA decision as is, only choose only between INTER/GMC - gruel, 9.1.2002 */ - bIntra = (pMB->mode == MODE_INTRA) || (pMB->mode == MODE_INTRA_Q); if (bIntra) { @@ -1753,6 +1818,7 @@ pEnc->current->sStat.kblks++; MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); + stop_coding_timer(); continue; } @@ -1760,13 +1826,22 @@ 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); + 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 */ + if (pEnc->mbParam.m_quarterpel) - pMB->qmvs[0] = pMB->qmvs[1] =pMB->qmvs[2] =pMB->qmvs[3] = pMB->amv; + pMB->qmvs[0] = pMB->qmvs[1] = pMB->qmvs[2] = pMB->qmvs[3] = pMB->amv; else - pMB->mvs[0] = pMB->mvs[1] =pMB->mvs[2] =pMB->mvs[3] = pMB->amv; + pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv; pMB->mode = MODE_INTER; pMB->mcsel = 1; @@ -1774,8 +1849,7 @@ } else { pMB->mcsel = 0; } - } else - { + } else { pMB->mcsel = 0; /* just a precaution */ } @@ -1813,7 +1887,6 @@ dct_codes, qcoeff); } - if (pMB->cbp || pMB->mvs[0].x || pMB->mvs[0].y || pMB->mvs[1].x || pMB->mvs[1].y || pMB->mvs[2].x || pMB->mvs[2].y || pMB->mvs[3].x || pMB->mvs[3].y) { @@ -1826,16 +1899,16 @@ /* Finished processing the MB, now check if to CODE or SKIP */ - skip_possible = (pMB->cbp == 0) & (pMB->mode == MODE_INTER) & + skip_possible = (pMB->cbp == 0) && (pMB->mode == MODE_INTER) && (pMB->dquant == NO_CHANGE); if (pEnc->current->coding_type == S_VOP) skip_possible &= (pMB->mcsel == 1); else if (pEnc->current->coding_type == P_VOP) { if (pEnc->mbParam.m_quarterpel) - skip_possible &= (pMB->qmvs[0].x == 0) & (pMB->qmvs[0].y == 0); + skip_possible &= ( (pMB->qmvs[0].x == 0) && (pMB->qmvs[0].y == 0) ); else - skip_possible &= (pMB->mvs[0].x == 0) & (pMB->mvs[0].y == 0); + skip_possible &= ( (pMB->mvs[0].x == 0) && (pMB->mvs[0].y == 0) ); } if ( (pMB->mode == MODE_NOT_CODED) || (skip_possible)) { @@ -1873,6 +1946,7 @@ pMB->cbp = 0; MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); stop_coding_timer(); + continue; /* next MB */ } } @@ -1922,8 +1996,10 @@ } } + MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); stop_coding_timer(); + } }