--- encoder.c 2002/10/17 19:10:57 1.76.2.13 +++ encoder.c 2002/12/12 12:42:31 1.76.2.29 @@ -39,7 +39,7 @@ * MinChen * 14.04.2002 added FrameCodeB() * - * $Id: encoder.c,v 1.76.2.13 2002/10/17 19:10:57 Isibaar Exp $ + * $Id: encoder.c,v 1.76.2.29 2002/12/12 12:42:31 suxen_drol Exp $ * ****************************************************************************/ @@ -54,10 +54,8 @@ #include "global.h" #include "utils/timer.h" #include "image/image.h" -#ifdef BFRAMES #include "image/font.h" #include "motion/sad.h" -#endif #include "motion/motion.h" #include "bitstream/cbp.h" #include "utils/mbfunctions.h" @@ -109,13 +107,6 @@ }; -static void __inline -image_null(IMAGE * image) -{ - image->y = image->u = image->v = NULL; -} - - /***************************************************************************** * Encoder creation * @@ -233,14 +224,14 @@ pEnc->mbParam.m_quant_type = H263_QUANT; - pEnc->sStat.fMvPrevSigma = -1; + pEnc->fMvPrevSigma = -1; /* Fill rate control parameters */ pEnc->bitrate = pParam->rc_bitrate; pEnc->iFrameNum = 0; - pEnc->iMaxKeyInterval = pParam->max_key_interval; + pEnc->mbParam.iMaxKeyInterval = pParam->max_key_interval; /* try to allocate frame memory */ @@ -333,10 +324,11 @@ /* B Frames specific init */ - pEnc->global = pParam->global; + pEnc->mbParam.global = pParam->global; pEnc->mbParam.max_bframes = pParam->max_bframes; - pEnc->bquant_ratio = pParam->bquant_ratio; - pEnc->frame_drop_ratio = pParam->frame_drop_ratio; + pEnc->mbParam.bquant_ratio = pParam->bquant_ratio; + pEnc->mbParam.bquant_offset = pParam->bquant_offset; + pEnc->mbParam.frame_drop_ratio = pParam->frame_drop_ratio; pEnc->bframes = NULL; if (pEnc->mbParam.max_bframes > 0) { @@ -625,7 +617,7 @@ start_timer(); if (image_input (&pEnc->queue[pEnc->queue_tail], pEnc->mbParam.width, pEnc->mbParam.height, - pEnc->mbParam.edged_width, pFrame->image, pFrame->colorspace)) + pEnc->mbParam.edged_width, pFrame->image, pFrame->stride, pFrame->colorspace, pFrame->general & XVID_INTERLACING)) return; stop_conv_timer(); @@ -654,6 +646,16 @@ +/* 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; + + return P_VOP; +} + /***************************************************************************** @@ -675,6 +677,7 @@ uint32_t bits, mode; int input_valid = 1; + int bframes_count = 0; #ifdef _DEBUG_PSNR float psnr; @@ -715,11 +718,14 @@ SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); FrameCodeP(pEnc, &bs, &bits, 1, 0); + bframes_count = 0; BitstreamPad(&bs); pFrame->length = BitstreamLength(&bs); pFrame->intra = 0; + emms(); + return XVID_ERR_OK; } @@ -733,11 +739,13 @@ BitstreamPad(&bs); pFrame->length = BitstreamLength(&bs); - pFrame->intra = 0; + pFrame->intra = 2; if (input_valid) queue_image(pEnc, pFrame); + emms(); + return XVID_ERR_OK; } @@ -751,7 +759,7 @@ indentical to the future-referece frame. */ - if ((pEnc->global & XVID_GLOBAL_PACKED)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED)) { int tmp; DPRINTF(DPRINTF_DEBUG,"*** EMPTY bf: head=%i tail=%i queue: head=%i tail=%i size=%i", @@ -766,11 +774,13 @@ pEnc->current->seconds = tmp; pFrame->length = BitstreamLength(&bs); - pFrame->intra = 0; + pFrame->intra = 4; if (input_valid) queue_image(pEnc, pFrame); + emms(); + return XVID_ERR_OK; } } @@ -784,7 +794,7 @@ SWAP(pEnc->current, pEnc->reference); SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); - if ((pEnc->global & XVID_GLOBAL_DEBUG)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 IVOP"); } @@ -801,8 +811,11 @@ start_timer(); if (image_input (&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height, - pEnc->mbParam.edged_width, pFrame->image, pFrame->colorspace)) + pEnc->mbParam.edged_width, pFrame->image, pFrame->stride, pFrame->colorspace, pFrame->general & XVID_INTERLACING)) + { + emms(); return XVID_ERR_FORMAT; + } stop_conv_timer(); // queue input frame, and dequue next image @@ -837,10 +850,11 @@ pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); BitstreamPutBits(&bs, 0x7f, 8); - pFrame->intra = 0; + pFrame->intra = 5; } pFrame->length = BitstreamLength(&bs); + emms(); return XVID_ERR_OK; } @@ -851,6 +865,7 @@ // only inc frame num, adapt quant, etc. if we havent seen it before if (pEnc->bframenum_dx50bvop < 0 ) { + mode = intra2coding_type(pFrame->intra); if (pFrame->quant == 0) pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0); else @@ -878,7 +893,7 @@ emms(); - if ((pEnc->global & XVID_GLOBAL_DEBUG)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5, "%i if:%i st:%i", pEnc->m_framenum++, pEnc->iFrameNum, pEnc->current->stamp); } @@ -922,47 +937,67 @@ /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * ivop/pvop/bvop selection * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ + pEnc->iFrameNum++; + if (pEnc->iFrameNum == 0 || pEnc->bframenum_dx50bvop >= 0 || + (mode < 0 && pEnc->mbParam.iMaxKeyInterval > 0 && + pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)) + { + mode = I_VOP; + }else{ + mode = MEanalysis(&pEnc->reference->image, pEnc->current, + &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval, + (mode < 0) ? pEnc->iFrameNum : 0, + bframes_count++); + } - if (pEnc->iFrameNum == 0 || pFrame->intra == 1 || pEnc->bframenum_dx50bvop >= 0 || - (pFrame->intra < 0 && pEnc->iMaxKeyInterval > 0 && - pEnc->iFrameNum >= pEnc->iMaxKeyInterval) - || /*image_mad(&pEnc->reference->image, &pEnc->current->image, - pEnc->mbParam.edged_width, pEnc->mbParam.width, - pEnc->mbParam.height) > 30) {*/ - 2 == (mode = MEanalysis(&pEnc->reference->image, &pEnc->current->image, - &pEnc->mbParam, pEnc->current->mbs, pEnc->current->fcode))) { - + if (mode == I_VOP) { /* * This will be coded as an Intra Frame */ + if ((pEnc->current->global_flags & XVID_QUARTERPEL)) + pEnc->mbParam.m_quarterpel = 1; + else + pEnc->mbParam.m_quarterpel = 0; + + if (pEnc->current->global_flags & XVID_MPEGQUANT) pEnc->mbParam.m_quant_type = MPEG4_QUANT; + + if ((pEnc->current->global_flags & XVID_CUSTOM_QMATRIX) > 0) { + if (pFrame->quant_intra_matrix != NULL) + set_intra_matrix(pFrame->quant_intra_matrix); + if (pFrame->quant_inter_matrix != NULL) + set_inter_matrix(pFrame->quant_inter_matrix); + } + DPRINTF(DPRINTF_DEBUG,"*** IFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); - if ((pEnc->global & XVID_GLOBAL_DEBUG)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { 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 - if ((pEnc->global & XVID_GLOBAL_DX50BVOP) && pEnc->bframenum_tail > 0) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DX50BVOP) && pEnc->bframenum_tail > 0) { pEnc->bframenum_tail--; pEnc->bframenum_dx50bvop = pEnc->bframenum_tail; SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); - if ((pEnc->global & XVID_GLOBAL_DEBUG)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 BVOP->PVOP"); } FrameCodeP(pEnc, &bs, &bits, 1, 0); + bframes_count = 0; pFrame->intra = 0; } else { FrameCodeI(pEnc, &bs, &bits); + bframes_count = 0; pFrame->intra = 1; pEnc->bframenum_dx50bvop = -1; @@ -970,7 +1005,7 @@ pEnc->flush_bframes = 1; - if ((pEnc->global & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) { + if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) { BitstreamPadAlways(&bs); input_valid = 0; goto ipvop_loop; @@ -980,7 +1015,7 @@ * NB : sequences like "IIBB" decode fine with msfdam but, * go screwy with divx 5.00 */ - } else if (pEnc->bframenum_tail >= pEnc->mbParam.max_bframes || mode != 0) { + } else if (mode == P_VOP || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { /* * This will be coded as a Predicted Frame */ @@ -989,48 +1024,46 @@ pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); - if ((pEnc->global & XVID_GLOBAL_DEBUG)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP"); } FrameCodeP(pEnc, &bs, &bits, 1, 0); + bframes_count = 0; pFrame->intra = 0; pEnc->flush_bframes = 1; - if ((pEnc->global & XVID_GLOBAL_PACKED)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED) && (pEnc->bframenum_tail > 0)) { BitstreamPadAlways(&bs); input_valid = 0; goto ipvop_loop; } - } else { + } else { /* mode == B_VOP */ /* * This will be coded as a Bidirectional Frame */ - if ((pEnc->global & XVID_GLOBAL_DEBUG)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP"); } if (pFrame->bquant < 1) { - pEnc->current->quant = - ((pEnc->reference->quant + - pEnc->current->quant) * pEnc->bquant_ratio) / 200; + pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) * + pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100; + } else { pEnc->current->quant = pFrame->bquant; } - if (pEnc->current->quant < 1) - pEnc->current->quant = 1; - if (pEnc->current->quant > 31) - pEnc->current->quant = 31; + if (pEnc->current->quant < 1) + pEnc->current->quant = 1; + else if (pEnc->current->quant > 31) + pEnc->current->quant = 31; - - DPRINTF(DPRINTF_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i queue: head=%i tail=%i size=%i quant=%i\n", - pEnc->bframenum_head, pEnc->bframenum_tail, - pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant); - - + DPRINTF(DPRINTF_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i queue: head=%i tail=%i size=%i quant=%i\n", + pEnc->bframenum_head, pEnc->bframenum_tail, + pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant); /* store frame into bframe buffer & swap ref back to current */ SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); @@ -1038,24 +1071,23 @@ pEnc->bframenum_tail++; - pFrame->intra = 0; +// bframe report by koepi + pFrame->intra = 2; pFrame->length = 0; input_valid = 0; goto bvop_loop; } - pEnc->iFrameNum++; - BitstreamPad(&bs); pFrame->length = BitstreamLength(&bs); if (pResult) { pResult->quant = pEnc->current->quant; - pResult->hlength = pFrame->length - (pEnc->sStat.iTextBits / 8); - pResult->kblks = pEnc->sStat.kblks; - pResult->mblks = pEnc->sStat.mblks; - pResult->ublks = pEnc->sStat.ublks; + 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; } emms(); @@ -1078,6 +1110,7 @@ stop_global_timer(); write_timer(); + emms(); return XVID_ERR_OK; } @@ -1132,7 +1165,7 @@ start_timer(); if (image_input (&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height, - pEnc->mbParam.edged_width, pFrame->image, pFrame->colorspace) < 0) + pEnc->mbParam.edged_width, pFrame->image, pFrame->stride, pFrame->colorspace, pFrame->general & XVID_INTERLACING) < 0) return XVID_ERR_FORMAT; stop_conv_timer(); @@ -1217,8 +1250,8 @@ if (pFrame->intra < 0) { if ((pEnc->iFrameNum == 0) - || ((pEnc->iMaxKeyInterval > 0) - && (pEnc->iFrameNum >= pEnc->iMaxKeyInterval))) { + || ((pEnc->mbParam.iMaxKeyInterval > 0) + && (pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval))) { pFrame->intra = FrameCodeI(pEnc, &bs, &bits); } else { pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 0, write_vol_header); @@ -1239,10 +1272,10 @@ if (pResult) { pResult->quant = pEnc->current->quant; - pResult->hlength = pFrame->length - (pEnc->sStat.iTextBits / 8); - pResult->kblks = pEnc->sStat.kblks; - pResult->mblks = pEnc->sStat.mblks; - pResult->ublks = pEnc->sStat.ublks; + 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; } emms(); @@ -1500,21 +1533,39 @@ Bitstream * bs, uint32_t * pBits) { + int mb_width = pEnc->mbParam.mb_width; + int mb_height = pEnc->mbParam.mb_height; DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); uint16_t x, y; + if ((pEnc->current->global_flags & XVID_REDUCED)) + { + mb_width = (pEnc->mbParam.width + 31) / 32; + mb_height = (pEnc->mbParam.height + 31) / 32; + + /* 16x16->8x8 downsample requires 1 additional edge pixel*/ + /* XXX: setedges is overkill */ + start_timer(); + image_setedges(&pEnc->current->image, + pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, + pEnc->mbParam.width, pEnc->mbParam.height); + stop_edges_timer(); + } + pEnc->iFrameNum = 0; pEnc->mbParam.m_rounding_type = 1; pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type; + pEnc->current->quarterpel = pEnc->mbParam.m_quarterpel; pEnc->current->coding_type = I_VOP; BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); + /* XXX: move this stuff to BitstreamWriteVolHeader */ #define DIVX501B481P "DivX501b481p" - if ((pEnc->global & XVID_GLOBAL_PACKED)) { + if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED)) { BitstreamWriteUserData(bs, DIVX501B481P, strlen(DIVX501B481P)); } @@ -1526,12 +1577,12 @@ *pBits = BitstreamPos(bs); - pEnc->sStat.iTextBits = 0; - pEnc->sStat.kblks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height; - pEnc->sStat.mblks = pEnc->sStat.ublks = 0; + pEnc->current->sStat.iTextBits = 0; + pEnc->current->sStat.kblks = mb_width * mb_height; + pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0; - for (y = 0; y < pEnc->mbParam.mb_height; y++) - for (x = 0; x < pEnc->mbParam.mb_width; x++) { + for (y = 0; y < mb_height; y++) + for (x = 0; x < mb_width; x++) { MACROBLOCK *pMB = &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width]; @@ -1550,16 +1601,19 @@ qcoeff[4*64+0]=0; /* zero, because for INTRA MBs DC value is saved */ qcoeff[5*64+0]=0; } - MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->sStat); + MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); stop_coding_timer(); } + if ((pEnc->current->global_flags & XVID_REDUCED)) + { + image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, + pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width); + } emms(); *pBits = BitstreamPos(bs) - *pBits; - pEnc->sStat.fMvPrevSigma = -1; - pEnc->sStat.iMvSum = 0; - pEnc->sStat.iMvCount = 0; + pEnc->fMvPrevSigma = -1; pEnc->mbParam.m_fcode = 2; if (pEnc->current->global_flags & XVID_HINTEDME_GET) { @@ -1585,6 +1639,9 @@ DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); + int mb_width = pEnc->mbParam.mb_width; + int mb_height = pEnc->mbParam.mb_height; + int iLimit; int x, y, k; int iSearchRange; @@ -1593,6 +1650,13 @@ /* IMAGE *pCurrent = &pEnc->current->image; */ IMAGE *pRef = &pEnc->reference->image; + if ((pEnc->current->global_flags & XVID_REDUCED)) + { + mb_width = (pEnc->mbParam.width + 31) / 32; + mb_height = (pEnc->mbParam.height + 31) / 32; + } + + start_timer(); image_setedges(pRef, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, pEnc->mbParam.width, pEnc->mbParam.height); @@ -1600,14 +1664,13 @@ pEnc->mbParam.m_rounding_type = 1 - pEnc->mbParam.m_rounding_type; pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type; + pEnc->current->quarterpel = pEnc->mbParam.m_quarterpel; pEnc->current->fcode = pEnc->mbParam.m_fcode; if (!force_inter) - iLimit = - (int) (pEnc->mbParam.mb_width * pEnc->mbParam.mb_height * - INTRA_THRESHOLD); + iLimit = (int)(mb_width * mb_height * INTRA_THRESHOLD); else - iLimit = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height + 1; + iLimit = mb_width * mb_height + 1; if ((pEnc->current->global_flags & XVID_HALFPEL)) { start_timer(); @@ -1619,28 +1682,35 @@ stop_inter_timer(); } + if (pEnc->current->global_flags & XVID_GMC) { +// printf("Global Motion = %d %d quarterpel=%d\n", pEnc->current->GMC_MV.x, pEnc->current->GMC_MV.y,pEnc->current->quarterpel); + DPRINTF(DPRINTF_HEADER, "Global Motion = %d %d quarterpel=%d\n", pEnc->current->GMC_MV.x, pEnc->current->GMC_MV.y,pEnc->current->quarterpel); + pEnc->current->coding_type = S_VOP; + } else + pEnc->current->coding_type = P_VOP; + start_timer(); if (pEnc->current->global_flags & XVID_HINTEDME_SET) { HintedMESet(pEnc, &bIntra); if (bIntra == 0) { - pEnc->current->fcode = FindFcode(&pEnc->mbParam, pEnc->current); MotionEstimationHinted(&pEnc->mbParam, pEnc->current, pEnc->reference, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV); } } else { - bIntra = - MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference, + bIntra = + MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, iLimit); - } stop_motion_timer(); if (bIntra == 1) return FrameCodeI(pEnc, bs, pBits); - pEnc->current->coding_type = P_VOP; + if ( (pEnc->current->GMC_MV.x == 0) && (pEnc->current->GMC_MV.y == 0) ) + pEnc->current->coding_type = P_VOP; /* no global motion -> no GMC */ + if (vol_header) BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); @@ -1651,11 +1721,11 @@ *pBits = BitstreamPos(bs); - pEnc->sStat.iTextBits = pEnc->sStat.iMvSum = pEnc->sStat.iMvCount = - pEnc->sStat.kblks = pEnc->sStat.mblks = pEnc->sStat.ublks = 0; + pEnc->current->sStat.iTextBits = pEnc->current->sStat.iMvSum = pEnc->current->sStat.iMvCount = + pEnc->current->sStat.kblks = pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0; - for (y = 0; y < pEnc->mbParam.mb_height; y++) { - for (x = 0; x < pEnc->mbParam.mb_width; x++) { + for (y = 0; y < mb_height; y++) { + for (x = 0; x < mb_width; x++) { MACROBLOCK *pMB = &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width]; @@ -1670,6 +1740,7 @@ pEnc->mbParam.height, pEnc->mbParam.edged_width, pEnc->mbParam.m_quarterpel, + (pEnc->current->global_flags & XVID_REDUCED), pEnc->current->rounding_type); stop_comp_timer(); @@ -1702,13 +1773,13 @@ stop_prediction_timer(); if (pMB->mode == MODE_INTRA || pMB->mode == MODE_INTRA_Q) { - pEnc->sStat.kblks++; + pEnc->current->sStat.kblks++; } else 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) { - pEnc->sStat.mblks++; + pEnc->current->sStat.mblks++; } else { - pEnc->sStat.ublks++; + pEnc->current->sStat.ublks++; } start_timer(); @@ -1719,40 +1790,52 @@ (pMB->dquant == NO_CHANGE); if(pEnc->mbParam.m_quarterpel) - skip_possible &= (pMB->qmvs[0].x == 0) & (pMB->qmvs[0].y == 0); + { skip_possible &= (pMB->qmvs[0].x == pEnc->current->GMC_MV.x) & (pMB->qmvs[0].y == pEnc->current->GMC_MV.y); + } else - skip_possible &= (pMB->mvs[0].x == 0) & (pMB->mvs[0].y == 0); + { skip_possible &= (pMB->mvs[0].x == pEnc->current->GMC_MV.x) & (pMB->mvs[0].y == pEnc->current->GMC_MV.y); + } + + if ( (pMB->mode == MODE_NOT_CODED) || (skip_possible)) { - if ((pMB->mode == MODE_NOT_CODED) || (skip_possible)) { -/* This is a candidate for SKIPping, but check intermediate B-frames first */ +/* This is a candidate for SKIPping, but for P-VOPs check intermediate B-frames first */ + int bSkip = 1; - int bSkip = 1; - pMB->mode = MODE_NOT_CODED; - - for (k=pEnc->bframenum_head; k< pEnc->bframenum_tail; k++) - { - int iSAD; - iSAD = sad16(pEnc->reference->image.y + 16*y*pEnc->mbParam.edged_width + 16*x, - pEnc->bframes[k]->image.y + 16*y*pEnc->mbParam.edged_width + 16*x, + if (pEnc->current->coding_type == P_VOP) /* special rule for P-VOP's SKIP */ + for (k=pEnc->bframenum_head; k< pEnc->bframenum_tail; k++) + { + int iSAD; + iSAD = sad16(pEnc->reference->image.y + 16*y*pEnc->mbParam.edged_width + 16*x, + pEnc->bframes[k]->image.y + 16*y*pEnc->mbParam.edged_width + 16*x, pEnc->mbParam.edged_width,BFRAME_SKIP_THRESHHOLD); - if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant) - { bSkip = 0; - break; + if (iSAD >= BFRAME_SKIP_THRESHHOLD * pMB->quant) + { bSkip = 0; + break; + } } - } - if (!bSkip) - { + + if (!bSkip) + { VECTOR predMV; - if(pEnc->mbParam.m_quarterpel) + if(pEnc->mbParam.m_quarterpel) { predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0); - else + pMB->pmvs[0].x = pMB->qmvs[0].x - predMV.x; /* with GMC, qmvs doesn't have to be (0,0)! */ + pMB->pmvs[0].y = pMB->qmvs[0].y - predMV.y; + } + else { predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0); - pMB->pmvs[0].x = -predMV.x; pMB->pmvs[0].y = -predMV.y; + pMB->pmvs[0].x = pMB->mvs[0].x - predMV.x; /* with GMC, mvs doesn't have to be (0,0)! */ + pMB->pmvs[0].y = pMB->mvs[0].y - predMV.y; + } pMB->mode = MODE_INTER; pMB->cbp = 0; - MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->sStat); + MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); + } + else + { + pMB->mode = MODE_NOT_CODED; + MBSkip(bs); } - else MBSkip(bs); } else { if (pEnc->current->global_flags & XVID_GREYSCALE) @@ -1760,23 +1843,29 @@ qcoeff[4*64+0]=0; /* zero, because DC for INTRA MBs DC value is saved */ qcoeff[5*64+0]=0; } - MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->sStat); + MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); } stop_coding_timer(); } } + if ((pEnc->current->global_flags & XVID_REDUCED)) + { + image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, + pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width); + } + emms(); if (pEnc->current->global_flags & XVID_HINTEDME_GET) { HintedMEGet(pEnc, 0); } - if (pEnc->sStat.iMvCount == 0) - pEnc->sStat.iMvCount = 1; + if (pEnc->current->sStat.iMvCount == 0) + pEnc->current->sStat.iMvCount = 1; - fSigma = (float) sqrt((float) pEnc->sStat.iMvSum / pEnc->sStat.iMvCount); + fSigma = (float) sqrt((float) pEnc->current->sStat.iMvSum / pEnc->current->sStat.iMvCount); iSearchRange = 1 << (3 + pEnc->mbParam.m_fcode); @@ -1786,24 +1875,23 @@ pEnc->mbParam.m_fcode++; iSearchRange *= 2; } else if ((fSigma < iSearchRange / 6) - && (pEnc->sStat.fMvPrevSigma >= 0) - && (pEnc->sStat.fMvPrevSigma < 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--; iSearchRange /= 2; } - pEnc->sStat.fMvPrevSigma = fSigma; + pEnc->fMvPrevSigma = fSigma; -#ifdef FRAMEDROP /* frame drop code */ - // DPRINTF(DPRINTF_DEBUG, "kmu %i %i %i", pEnc->sStat.kblks, pEnc->sStat.mblks, pEnc->sStat.ublks); - if (pEnc->sStat.kblks + pEnc->sStat.mblks < - (pEnc->frame_drop_ratio * pEnc->mbParam.mb_width * pEnc->mbParam.mb_height) / 100) + // DPRINTF(DPRINTF_DEBUG, "kmu %i %i %i", pEnc->current->sStat.kblks, pEnc->current->sStat.mblks, pEnc->current->sStat.ublks); + if (pEnc->current->sStat.kblks + pEnc->current->sStat.mblks < + (pEnc->mbParam.frame_drop_ratio * mb_width * mb_height) / 100) { - pEnc->sStat.kblks = pEnc->sStat.mblks = 0; - pEnc->sStat.ublks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height; + pEnc->current->sStat.kblks = pEnc->current->sStat.mblks = 0; + pEnc->current->sStat.ublks = mb_width * mb_height; BitstreamReset(bs); @@ -1814,13 +1902,28 @@ pEnc->current->quant = pEnc->reference->quant; pEnc->current->motion_flags = pEnc->reference->motion_flags; pEnc->current->rounding_type = pEnc->reference->rounding_type; + pEnc->current->quarterpel = pEnc->reference->quarterpel; pEnc->current->fcode = pEnc->reference->fcode; pEnc->current->bcode = pEnc->reference->bcode; image_copy(&pEnc->current->image, &pEnc->reference->image, pEnc->mbParam.edged_width, pEnc->mbParam.height); - memcpy(pEnc->current->mbs, pEnc->reference->mbs, sizeof(MACROBLOCK) * pEnc->mbParam.mb_width * pEnc->mbParam.mb_height); - + memcpy(pEnc->current->mbs, pEnc->reference->mbs, sizeof(MACROBLOCK) * mb_width * mb_height); } -#endif + + /* XXX: debug + { + char s[100]; + sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum); + image_dump_yuvpgm(&pEnc->current->image, + pEnc->mbParam.edged_width, + pEnc->mbParam.width, pEnc->mbParam.height, s); + + sprintf(s, "\\%05i_ref.pgm", pEnc->m_framenum); + image_dump_yuvpgm(&pEnc->reference->image, + pEnc->mbParam.edged_width, + pEnc->mbParam.width, pEnc->mbParam.height, s); + } + */ + *pBits = BitstreamPos(bs) - *pBits; @@ -1828,7 +1931,7 @@ } -static __inline void +static void FrameCodeB(Encoder * pEnc, FRAMEINFO * frame, Bitstream * bs, @@ -1848,11 +1951,15 @@ fprintf(fp,"Y=%3d X=%3d MB=%2d CBP=%02X\n",y,x,mb->mode,mb->cbp); \ } + pEnc->current->global_flags &= ~XVID_REDUCED; /* reduced resoltion not yet supported */ + if (!first){ fp=fopen("C:\\XVIDDBGE.TXT","w"); } #endif + frame->quarterpel = pEnc->mbParam.m_quarterpel; + // forward image_setedges(f_ref, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, pEnc->mbParam.width, @@ -1880,7 +1987,7 @@ ((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->mbs, b_ref, &pEnc->vInterH, + pEnc->current, b_ref, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV); @@ -1898,16 +2005,16 @@ *pBits = BitstreamPos(bs); - pEnc->sStat.iTextBits = 0; - pEnc->sStat.iMvSum = 0; - pEnc->sStat.iMvCount = 0; - pEnc->sStat.kblks = pEnc->sStat.mblks = pEnc->sStat.ublks = 0; + frame->sStat.iTextBits = 0; + frame->sStat.iMvSum = 0; + frame->sStat.iMvCount = 0; + frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0; for (y = 0; y < pEnc->mbParam.mb_height; y++) { for (x = 0; x < pEnc->mbParam.mb_width; x++) { MACROBLOCK * const mb = &frame->mbs[x + y * pEnc->mbParam.mb_width]; - int direction = pEnc->global & XVID_ALTERNATESCAN ? 2 : 0; + int direction = pEnc->mbParam.global & XVID_ALTERNATESCAN ? 2 : 0; // decoder ignores mb when refence block is INTER(0,0), CBP=0 if (mb->mode == MODE_NOT_CODED) { @@ -1939,7 +2046,7 @@ #endif start_timer(); MBCodingBVOP(mb, qcoeff, frame->fcode, frame->bcode, bs, - &pEnc->sStat, direction); + &frame->sStat, direction); stop_coding_timer(); } }