--- encoder.c 2003/02/15 18:48:15 1.92 +++ encoder.c 2003/05/03 23:24:30 1.99.2.1 @@ -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.92 2003/02/15 18:48:15 edgomez Exp $ + * $Id: encoder.c,v 1.99.2.1 2003/05/03 23:24:30 Isibaar Exp $ * ****************************************************************************/ @@ -72,7 +59,7 @@ ****************************************************************************/ #define ENC_CHECK(X) if(!(X)) return XVID_ERR_FORMAT -#define SWAP(_T_,A,B) { _T_ tmp = A; A = B; B = tmp; } +#define SWAP(_T_,A,B) { _T_ tmp = A; A = B; B = tmp; } /***************************************************************************** * Local function prototypes @@ -86,12 +73,15 @@ Bitstream * bs, uint32_t * pBits, bool force_inter, - bool vol_header); + bool vol_header, + int interpolate); static void FrameCodeB(Encoder * pEnc, FRAMEINFO * frame, Bitstream * bs, - uint32_t * pBits); + uint32_t * pBits, + int interpolate_forward, + int interpolate_backward); /***************************************************************************** * Local data @@ -117,10 +107,10 @@ * and cleaning code. * * Returned values : - * - XVID_ERR_OK - no errors - * - XVID_ERR_MEMORY - the libc could not allocate memory, the function - * cleans the structure before exiting. - * pParam->handle is also set to NULL. + * - XVID_ERR_OK - no errors + * - XVID_ERR_MEMORY - the libc could not allocate memory, the function + * cleans the structure before exiting. + * pParam->handle is also set to NULL. * ****************************************************************************/ @@ -129,7 +119,6 @@ { Encoder *pEnc; int i; - pParam->handle = NULL; ENC_CHECK(pParam); @@ -379,7 +368,6 @@ pEnc->queue = NULL; - if (pEnc->mbParam.max_bframes > 0) { int n; @@ -432,7 +420,6 @@ xvid_err_memory5: - if (pEnc->mbParam.max_bframes > 0) { for (i = 0; i < pEnc->mbParam.max_bframes; i++) { @@ -453,12 +440,12 @@ image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); - + xvid_free(pEnc->bframes[i]->mbs); - + xvid_free(pEnc->bframes[i]); - } + } xvid_free(pEnc->bframes); } @@ -518,7 +505,7 @@ * successful encoder_create call. * * Returned values (for now only one returned value) : - * - XVID_ERR_OK - no errors + * - XVID_ERR_OK - no errors * ****************************************************************************/ @@ -526,21 +513,20 @@ encoder_destroy(Encoder * pEnc) { int i; - + ENC_CHECK(pEnc); /* B Frames specific */ if (pEnc->mbParam.max_bframes > 0) { for (i = 0; i < pEnc->mbParam.max_bframes; i++) { - + image_destroy(&pEnc->queue[i], pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); } xvid_free(pEnc->queue); } - if (pEnc->mbParam.max_bframes > 0) { for (i = 0; i < pEnc->mbParam.max_bframes; i++) { @@ -557,7 +543,7 @@ } xvid_free(pEnc->bframes); - + } /* All images, reference, current etc ... */ @@ -605,7 +591,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; } @@ -632,7 +618,7 @@ stop_conv_timer(); if ((pFrame->general & XVID_CHROMAOPT)) { - image_chroma_optimize(&pEnc->queue[pEnc->queue_tail], + image_chroma_optimize(&pEnc->queue[pEnc->queue_tail], pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); } @@ -640,14 +626,14 @@ pEnc->queue_tail = (pEnc->queue_tail + 1) % pEnc->mbParam.max_bframes; } -static __inline void +static __inline void set_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base) { 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)); @@ -677,23 +663,25 @@ * IPB frame encoder entry point * * Returned values : - * - XVID_ERR_OK - no errors - * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong - * format + * - XVID_ERR_OK - no errors + * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong + * format ****************************************************************************/ int encoder_encode_bframes(Encoder * pEnc, - XVID_ENC_FRAME * pFrame, - XVID_ENC_STATS * pResult) + XVID_ENC_FRAME * pFrame, + XVID_ENC_STATS * pResult) { uint16_t x, y; Bitstream bs; uint32_t bits; - int mode; + int mode = -1; /* Just to shut up compiler warning */ int input_valid = 1; int bframes_count = 0; + int interpolate_forward = 1; + int interpolate_backward = 1; ENC_CHECK(pEnc); ENC_CHECK(pFrame); @@ -728,8 +716,15 @@ SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); - FrameCodeP(pEnc, &bs, &bits, 1, 0); + if (pEnc->mbParam.m_quarterpel) + pEnc->current->global_flags |= XVID_QUARTERPEL; + else + pEnc->current->global_flags &= ~XVID_QUARTERPEL; + + FrameCodeP(pEnc, &bs, &bits, 1, 0, interpolate_backward); bframes_count = 0; + interpolate_forward = 0; + interpolate_backward = 1; BitstreamPadAlways(&bs); pFrame->length = BitstreamLength(&bs); @@ -744,19 +739,30 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + pResult->iblks = pEnc->current->sStat.iblks; + pResult->qblks = pEnc->current->sStat.qblks; } return XVID_ERR_OK; } - + DPRINTF(DPRINTF_DEBUG,"*** BFRAME (flush) 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); - FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs, &bits); + if (pEnc->mbParam.m_quarterpel) + pEnc->current->global_flags |= XVID_QUARTERPEL; + else + pEnc->current->global_flags &= ~XVID_QUARTERPEL; + + FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs, + &bits, interpolate_forward, interpolate_backward); pEnc->bframenum_head++; + interpolate_forward = 0; + interpolate_backward = 0; + BitstreamPadAlways(&bs); pFrame->length = BitstreamLength(&bs); pFrame->intra = 2; @@ -767,6 +773,15 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + pResult->iblks = pEnc->current->sStat.iblks; + pResult->qblks = pEnc->current->sStat.qblks; + } + + emms(); + + if (pFrame->quant == 0) { + RateControlUpdate(&pEnc->rate_control, pEnc->current->quant, + pFrame->length, pFrame->intra); } if (input_valid) @@ -781,20 +796,18 @@ pEnc->bframenum_head = pEnc->bframenum_tail = 0; /* write an empty marker to the bitstream. - for divx5 decoder compatibility, this marker must consist - of a not-coded p-vop, with a time_base of zero, and time_increment + of a not-coded p-vop, with a time_base of zero, and time_increment indentical to the future-referece frame. */ 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", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); - tmp = pEnc->current->seconds; pEnc->current->seconds = 0; /* force time_base = 0 */ @@ -811,6 +824,15 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + pResult->iblks = pEnc->current->sStat.iblks; + pResult->qblks = pEnc->current->sStat.qblks; + } + + emms(); + + if (pFrame->quant == 0) { + RateControlUpdate(&pEnc->rate_control, pEnc->current->quant, + pFrame->length, pFrame->intra); } if (input_valid) @@ -829,7 +851,7 @@ { SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); - SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); + SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 IVOP"); @@ -856,11 +878,11 @@ stop_conv_timer(); if ((pFrame->general & XVID_CHROMAOPT)) { - image_chroma_optimize(&pEnc->current->image, + image_chroma_optimize(&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); } - // queue input frame, and dequue next image + /* queue input frame, and dequue next image */ if (pEnc->queue_size > 0) { image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_tail]); @@ -873,7 +895,7 @@ } } else if (pEnc->queue_size > 0) { - + SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head]); @@ -891,7 +913,10 @@ 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) { @@ -912,8 +937,9 @@ pResult->kblks = 0; pResult->mblks = 0; pResult->ublks = 0; + pResult->iblks = 0; + pResult->qblks = 0; } - } else { if (pResult) { @@ -922,6 +948,8 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + pResult->iblks = pEnc->current->sStat.iblks; + pResult->qblks = pEnc->current->sStat.qblks; } } @@ -937,7 +965,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); @@ -969,7 +997,7 @@ emms(); if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { - image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5, + 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); } @@ -1000,13 +1028,10 @@ pMB->dquant = iDQtab[temp_dquants[OFFSET(x, y)] + 2]; } - #undef OFFSET } - xvid_free(temp_dquants); } - } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1015,15 +1040,14 @@ pEnc->iFrameNum++; if (pEnc->iFrameNum == 0 || pEnc->bframenum_dx50bvop >= 0 || - (mode < 0 && pEnc->mbParam.iMaxKeyInterval > 0 && - pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)) - { + (mode < 0 && pEnc->mbParam.iMaxKeyInterval > 0 && + pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)) { mode = I_VOP; - }else{ + } else { mode = MEanalysis(&pEnc->reference->image, pEnc->current, &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval, - (mode < 0) ? pEnc->iFrameNum : 0, - bframes_count++); + (/*mode < 0*/1/*hack*/) ? pEnc->iFrameNum : 0, + bframes_count++, pFrame->bframe_threshold); } if (mode == I_VOP) { @@ -1048,12 +1072,12 @@ 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->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 + /* 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) { @@ -1064,14 +1088,29 @@ 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); + + if (pEnc->mbParam.m_quarterpel) + pEnc->current->global_flags |= XVID_QUARTERPEL; + else + pEnc->current->global_flags &= ~XVID_QUARTERPEL; + + FrameCodeP(pEnc, &bs, &bits, 1, 0, interpolate_backward); bframes_count = 0; pFrame->intra = 0; + interpolate_forward = 0; + interpolate_backward = 1; } else { + if (pEnc->mbParam.m_quarterpel) + pEnc->current->global_flags |= XVID_QUARTERPEL; + else + pEnc->current->global_flags &= ~XVID_QUARTERPEL; + FrameCodeI(pEnc, &bs, &bits); bframes_count = 0; + interpolate_forward = 1; + interpolate_backward = 1; pFrame->intra = 1; pEnc->bframenum_dx50bvop = -1; @@ -1087,7 +1126,7 @@ /* * NB : sequences like "IIBB" decode fine with msfdam but, - * go screwy with divx 5.00 + * go screwy with divx 5.00 */ } else if (mode == P_VOP || mode == S_VOP || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { /* @@ -1097,14 +1136,21 @@ DPRINTF(DPRINTF_DEBUG,"*** PFRAME 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->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); + if (pEnc->mbParam.m_quarterpel) + pEnc->current->global_flags |= XVID_QUARTERPEL; + else + pEnc->current->global_flags &= ~XVID_QUARTERPEL; + + FrameCodeP(pEnc, &bs, &bits, 1, 0, interpolate_backward); bframes_count = 0; pFrame->intra = 0; + interpolate_forward = 0; + interpolate_backward = 1; pEnc->flush_bframes = 1; if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED) && (pEnc->bframenum_tail > 0)) { @@ -1123,7 +1169,7 @@ } if (pFrame->bquant < 1) { - pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) * + pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) * pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100; } else { @@ -1133,8 +1179,8 @@ if (pEnc->current->quant < 1) pEnc->current->quant = 1; else if (pEnc->current->quant > 31) - 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); @@ -1145,7 +1191,7 @@ pEnc->bframenum_tail++; -// bframe report by koepi + /* bframe report by koepi */ pFrame->intra = 2; pFrame->length = 0; @@ -1162,6 +1208,8 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + pResult->iblks = pEnc->current->sStat.iblks; + pResult->qblks = pEnc->current->sStat.qblks; if (pFrame->general & XVID_EXTRASTATS) { pResult->sse_y = @@ -1177,7 +1225,7 @@ 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); + pEnc->mbParam.height/2); } } @@ -1201,9 +1249,9 @@ * "original" IP frame encoder entry point * * Returned values : - * - XVID_ERR_OK - no errors - * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong - * format + * - XVID_ERR_OK - no errors + * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong + * format ****************************************************************************/ int @@ -1215,9 +1263,10 @@ Bitstream bs; uint32_t bits; uint16_t write_vol_header = 0; + unsigned int old_qpel; float psnr; - uint8_t temp[128]; + char temp[128]; start_global_timer(); @@ -1249,7 +1298,7 @@ stop_conv_timer(); if ((pFrame->general & XVID_CHROMAOPT)) { - image_chroma_optimize(&pEnc->current->image, + image_chroma_optimize(&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); } @@ -1268,6 +1317,8 @@ pEnc->current->quant = pFrame->quant; } + old_qpel = pEnc->mbParam.m_quarterpel; + if ((pEnc->current->global_flags & XVID_QUARTERPEL)) pEnc->mbParam.m_quarterpel = 1; else @@ -1338,19 +1389,26 @@ && (pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval))) { pFrame->intra = FrameCodeI(pEnc, &bs, &bits); } else { - pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 0, write_vol_header); + if (old_qpel != pEnc->mbParam.m_quarterpel) + pEnc->mbParam.m_quarterpel = old_qpel; + pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 0, write_vol_header, 1); } } else { if (pFrame->intra == 1) { pFrame->intra = FrameCodeI(pEnc, &bs, &bits); } else { - pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 1, write_vol_header); + if (old_qpel != pEnc->mbParam.m_quarterpel) + pEnc->mbParam.m_quarterpel = old_qpel; + pFrame->intra = FrameCodeP(pEnc, &bs, &bits, 1, write_vol_header, 1); } } -// 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); @@ -1360,6 +1418,8 @@ pResult->kblks = pEnc->current->sStat.kblks; pResult->mblks = pEnc->current->sStat.mblks; pResult->ublks = pEnc->current->sStat.ublks; + pResult->iblks = pEnc->current->sStat.iblks; + pResult->qblks = pEnc->current->sStat.qblks; } emms(); @@ -1374,7 +1434,7 @@ image_psnr(&pEnc->sOriginal, &pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.width, pEnc->mbParam.height); - + snprintf(temp, 127, "PSNR: %f\n", psnr); } @@ -1441,9 +1501,8 @@ return; } - pEnc->current->fcode = - (hint->rawhints) ? hint->mvhint.fcode : BitstreamGetBits(&bs, - FCODEBITS); + pEnc->current->fcode = (hint->rawhints) ? + (uint32_t)hint->mvhint.fcode : BitstreamGetBits(&bs, FCODEBITS); length = pEnc->current->fcode + 5; high = 1 << (length - 1); @@ -1458,20 +1517,17 @@ VECTOR tmp; int vec; - pMB->mode = - (hint->rawhints) ? bhint->mode : BitstreamGetBits(&bs, - MODEBITS); + pMB->mode = (hint->rawhints) ? + (uint32_t)bhint->mode : BitstreamGetBits(&bs, MODEBITS); pMB->mode = (pMB->mode == MODE_INTER_Q) ? MODE_INTER : pMB->mode; pMB->mode = (pMB->mode == MODE_INTRA_Q) ? MODE_INTRA : pMB->mode; if (pMB->mode == MODE_INTER) { - tmp.x = - (hint->rawhints) ? bhint->mvs[0].x : BitstreamGetBits(&bs, - length); - tmp.y = - (hint->rawhints) ? bhint->mvs[0].y : BitstreamGetBits(&bs, - length); + tmp.x = (hint->rawhints) ? + bhint->mvs[0].x : (int)BitstreamGetBits(&bs, length); + tmp.y = (hint->rawhints) ? + bhint->mvs[0].y : (int)BitstreamGetBits(&bs, length); tmp.x -= (tmp.x >= high) ? high * 2 : 0; tmp.y -= (tmp.y >= high) ? high * 2 : 0; @@ -1485,12 +1541,10 @@ } } else if (pMB->mode == MODE_INTER4V) { for (vec = 0; vec < 4; ++vec) { - tmp.x = - (hint->rawhints) ? bhint->mvs[vec]. - x : BitstreamGetBits(&bs, length); - tmp.y = - (hint->rawhints) ? bhint->mvs[vec]. - y : BitstreamGetBits(&bs, length); + tmp.x = (hint->rawhints) ? + bhint->mvs[vec].x : (int)BitstreamGetBits(&bs, length); + tmp.y = (hint->rawhints) ? + bhint->mvs[vec].y : (int)BitstreamGetBits(&bs, length); tmp.x -= (tmp.x >= high) ? high * 2 : 0; tmp.y -= (tmp.y >= high) ? high * 2 : 0; @@ -1501,7 +1555,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; @@ -1633,12 +1687,11 @@ /* 16x16->8x8 downsample requires 1 additional edge pixel*/ /* XXX: setedges is overkill */ start_timer(); - image_setedges(&pEnc->current->image, + 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; @@ -1657,6 +1710,7 @@ pEnc->current->sStat.iTextBits = 0; pEnc->current->sStat.kblks = mb_width * mb_height; pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0; + pEnc->current->sStat.iblks = pEnc->current->sStat.qblks = 0; for (y = 0; y < mb_height; y++) for (x = 0; x < mb_width; x++) { @@ -1684,7 +1738,7 @@ if ((pEnc->current->global_flags & XVID_REDUCED)) { - image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, + image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width, 16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV); } @@ -1698,7 +1752,7 @@ HintedMEGet(pEnc, 1); } - return 1; // intra + return 1; /* intra */ } @@ -1712,7 +1766,8 @@ Bitstream * bs, uint32_t * pBits, bool force_inter, - bool vol_header) + bool vol_header, + int interpolate) { float fSigma; @@ -1726,7 +1781,8 @@ int x, y, k; int iSearchRange; int bIntra, skip_possible; - + IMAGE *refh, *refv, *refhv; + /* IMAGE *pCurrent = &pEnc->current->image; */ IMAGE *pRef = &pEnc->reference->image; @@ -1736,12 +1792,6 @@ 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); - stop_edges_timer(); - 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; @@ -1752,51 +1802,67 @@ else iLimit = mb_width * mb_height + 1; - if ((pEnc->current->global_flags & XVID_HALFPEL)) { + if((interpolate) || (pEnc->current->rounding_type != 0)) { start_timer(); - image_interpolate(pRef, &pEnc->vInterH, &pEnc->vInterV, - &pEnc->vInterHV, pEnc->mbParam.edged_width, - pEnc->mbParam.edged_height, - pEnc->mbParam.m_quarterpel, - pEnc->current->rounding_type); - stop_inter_timer(); + image_setedges(pRef, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, + pEnc->mbParam.width, pEnc->mbParam.height); + stop_edges_timer(); + + if ((pEnc->current->global_flags & XVID_HALFPEL)) { + start_timer(); + image_interpolate(pRef, &pEnc->vInterH, &pEnc->vInterV, + &pEnc->vInterHV, pEnc->mbParam.edged_width, + pEnc->mbParam.edged_height, + pEnc->mbParam.m_quarterpel, + pEnc->current->rounding_type); + stop_inter_timer(); + } + + refh = &pEnc->vInterH; + refv = &pEnc->vInterV; + refhv = &pEnc->vInterHV; + } + else { + refh = &pEnc->f_refh; + refv = &pEnc->f_refv; + refhv = &pEnc->f_refhv; } pEnc->current->coding_type = P_VOP; - + start_timer(); if (pEnc->current->global_flags & XVID_HINTEDME_SET) HintedMESet(pEnc, &bIntra); else bIntra = MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference, - &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, - iLimit); + refh, refv, refhv, + iLimit); stop_motion_timer(); if (bIntra == 1) return FrameCodeI(pEnc, bs, pBits); - if ( ( pEnc->current->global_flags & XVID_GMC ) + if ( ( pEnc->current->global_flags & XVID_GMC ) && ( (pEnc->current->warp.duv[1].x != 0) || (pEnc->current->warp.duv[1].y != 0) ) ) { pEnc->current->coding_type = S_VOP; - generate_GMCparameters( 2, 16, &pEnc->current->warp, - pEnc->mbParam.width, pEnc->mbParam.height, + generate_GMCparameters( 2, 16, &pEnc->current->warp, + pEnc->mbParam.width, pEnc->mbParam.height, &pEnc->current->gmc_data); - generate_GMCimage(&pEnc->current->gmc_data, &pEnc->reference->image, + 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, pEnc->mbParam.m_quarterpel, 0, + pEnc->mbParam.edged_width, pEnc->mbParam.edged_width/2, + 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); } @@ -1804,8 +1870,9 @@ *pBits = BitstreamPos(bs); - 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; + 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; + pEnc->current->sStat.iblks = pEnc->current->sStat.qblks = 0; for (y = 0; y < mb_height; y++) { @@ -1833,13 +1900,13 @@ stop_coding_timer(); continue; } - + if (pEnc->current->coding_type == S_VOP) { 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->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); @@ -1867,8 +1934,8 @@ start_timer(); MBMotionCompensation(pMB, x, y, &pEnc->reference->image, - &pEnc->vInterH, &pEnc->vInterV, - &pEnc->vInterHV, &pEnc->vGMC, + refh, refv, + refhv, &pEnc->vGMC, &pEnc->current->image, dct_codes, pEnc->mbParam.width, pEnc->mbParam.height, @@ -1906,20 +1973,30 @@ } else { pEnc->current->sStat.ublks++; } - + + if(pEnc->mbParam.m_quarterpel) { + for (k = 0; k < ((pMB->mode == MODE_INTER4V) ? 4 : 1); k++) { + if (((pMB->qmvs[k].x % 4) != 0) || ((pMB->qmvs[k].y % 4) != 0)) + pEnc->current->sStat.iblks++; + + if (((pMB->qmvs[k].x % 4) & 1) || ((pMB->qmvs[k].y % 4) & 1)) + pEnc->current->sStat.qblks++; + } + } + start_timer(); /* Finished processing the MB, now check if to CODE or SKIP */ 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) ); - else + else skip_possible &= ( (pMB->mvs[0].x == 0) && (pMB->mvs[0].y == 0) ); } @@ -1929,8 +2006,8 @@ if (pEnc->current->coding_type == P_VOP) /* special rule for P-VOP's SKIP */ { - int bSkip = 1; - + int bSkip = 1; + for (k=pEnc->bframenum_head; k< pEnc->bframenum_tail; k++) { int iSAD; @@ -1938,21 +2015,21 @@ 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; + { bSkip = 0; break; } } - + if (!bSkip) { /* no SKIP, but trivial block */ if(pEnc->mbParam.m_quarterpel) { VECTOR predMV = get_qpmv2(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 = - predMV.x; + pMB->pmvs[0].y = - predMV.y; } else { VECTOR 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 = - predMV.x; + pMB->pmvs[0].y = - predMV.y; } pMB->mode = MODE_INTER; pMB->cbp = 0; @@ -1979,13 +2056,13 @@ if(pEnc->mbParam.m_quarterpel) { VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0); - pMB->pmvs[0].x = pMB->qmvs[0].x - predMV.x; - pMB->pmvs[0].y = pMB->qmvs[0].y - predMV.y; + pMB->pmvs[0].x = pMB->qmvs[0].x - predMV.x; + pMB->pmvs[0].y = pMB->qmvs[0].y - predMV.y; DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[0].x, pMB->pmvs[0].y, predMV.x, predMV.y, pMB->mvs[0].x, pMB->mvs[0].y); } else { VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, 0); - pMB->pmvs[0].x = pMB->mvs[0].x - predMV.x; - pMB->pmvs[0].y = pMB->mvs[0].y - predMV.y; + pMB->pmvs[0].x = pMB->mvs[0].x - predMV.x; + pMB->pmvs[0].y = pMB->mvs[0].y - predMV.y; DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[0].x, pMB->pmvs[0].y, predMV.x, predMV.y, pMB->mvs[0].x, pMB->mvs[0].y); } @@ -1996,19 +2073,19 @@ { if(pEnc->mbParam.m_quarterpel) { VECTOR predMV = get_qpmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, k); - pMB->pmvs[k].x = pMB->qmvs[k].x - predMV.x; - pMB->pmvs[k].y = pMB->qmvs[k].y - predMV.y; + pMB->pmvs[k].x = pMB->qmvs[k].x - predMV.x; + pMB->pmvs[k].y = pMB->qmvs[k].y - predMV.y; DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[k].x, pMB->pmvs[k].y, predMV.x, predMV.y, pMB->mvs[k].x, pMB->mvs[k].y); } else { VECTOR predMV = get_pmv2(pEnc->current->mbs, pEnc->mbParam.mb_width, 0, x, y, k); - pMB->pmvs[k].x = pMB->mvs[k].x - predMV.x; - pMB->pmvs[k].y = pMB->mvs[k].y - predMV.y; + pMB->pmvs[k].x = pMB->mvs[k].x - predMV.x; + pMB->pmvs[k].y = pMB->mvs[k].y - predMV.y; DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)", pMB->pmvs[k].x, pMB->pmvs[k].y, predMV.x, predMV.y, pMB->mvs[k].x, pMB->mvs[k].y); } } } - + MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat); stop_coding_timer(); @@ -2017,7 +2094,7 @@ if ((pEnc->current->global_flags & XVID_REDUCED)) { - image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, + image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width, 16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV); } @@ -2036,14 +2113,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; @@ -2064,7 +2141,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; @@ -2079,21 +2156,21 @@ { char s[100]; sprintf(s, "\\%05i_cur.pgm", pEnc->m_framenum); - image_dump_yuvpgm(&pEnc->current->image, + 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, + image_dump_yuvpgm(&pEnc->reference->image, pEnc->mbParam.edged_width, pEnc->mbParam.width, pEnc->mbParam.height, s); - } + } */ *pBits = BitstreamPos(bs) - *pBits; - return 0; // inter + return 0; /* inter */ } @@ -2101,7 +2178,9 @@ FrameCodeB(Encoder * pEnc, FRAMEINFO * frame, Bitstream * bs, - uint32_t * pBits) + uint32_t * pBits, + int interpolate_forward, + int interpolate_backward) { DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); @@ -2125,44 +2204,48 @@ #endif frame->quarterpel = pEnc->mbParam.m_quarterpel; + + if ((interpolate_forward) || ((pEnc->mbParam.m_rounding_type != 1) && interpolate_backward)) { - // forward - image_setedges(f_ref, pEnc->mbParam.edged_width, - pEnc->mbParam.edged_height, pEnc->mbParam.width, - pEnc->mbParam.height); - start_timer(); - image_interpolate(f_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv, - pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, - pEnc->mbParam.m_quarterpel, 0); - stop_inter_timer(); - - // backward - image_setedges(b_ref, pEnc->mbParam.edged_width, - pEnc->mbParam.edged_height, pEnc->mbParam.width, - pEnc->mbParam.height); - start_timer(); - image_interpolate(b_ref, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, - pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, - pEnc->mbParam.m_quarterpel, 0); - stop_inter_timer(); + /* forward */ + image_setedges(f_ref, pEnc->mbParam.edged_width, + pEnc->mbParam.edged_height, pEnc->mbParam.width, + pEnc->mbParam.height); + start_timer(); + image_interpolate(f_ref, &pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, + pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, + pEnc->mbParam.m_quarterpel, 0); + stop_inter_timer(); + } - start_timer(); + if (interpolate_backward) { - 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, - &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv, - pEnc->current, b_ref, &pEnc->vInterH, - &pEnc->vInterV, &pEnc->vInterHV); + /* backward */ + image_setedges(b_ref, pEnc->mbParam.edged_width, + pEnc->mbParam.edged_height, pEnc->mbParam.width, + pEnc->mbParam.height); + start_timer(); + image_interpolate(b_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv, + pEnc->mbParam.edged_width, pEnc->mbParam.edged_height, + pEnc->mbParam.m_quarterpel, 0); + stop_inter_timer(); + } + start_timer(); - stop_motion_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, &pEnc->vInterH, + &pEnc->vInterV, &pEnc->vInterHV, + pEnc->current, b_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv); - /*if (test_quant_type(&pEnc->mbParam, pEnc->current)) - { - BitstreamWriteVolHeader(bs, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.quant_type); - } */ + stop_motion_timer(); + /* + 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; @@ -2175,6 +2258,7 @@ frame->sStat.iMvSum = 0; frame->sStat.iMvCount = 0; frame->sStat.kblks = frame->sStat.mblks = frame->sStat.ublks = 0; + frame->sStat.iblks = frame->sStat.qblks = 0; for (y = 0; y < pEnc->mbParam.mb_height; y++) { @@ -2182,28 +2266,28 @@ 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; } if (mb->mode != MODE_DIRECT_NONE_MV) { MBMotionCompensationBVOP(&pEnc->mbParam, mb, x, y, &frame->image, - f_ref, &pEnc->f_refh, &pEnc->f_refv, - &pEnc->f_refhv, b_ref, &pEnc->vInterH, - &pEnc->vInterV, &pEnc->vInterHV, + f_ref, &pEnc->vInterH, &pEnc->vInterV, + &pEnc->vInterHV, b_ref, &pEnc->f_refh, + &pEnc->f_refv, &pEnc->f_refhv, dct_codes); if (mb->mode == MODE_DIRECT_NO4V) mb->mode = MODE_DIRECT; mb->quant = frame->quant; - + mb->cbp = MBTransQuantInterBVOP(&pEnc->mbParam, frame, mb, dct_codes, qcoeff); 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 */ } } @@ -2219,7 +2303,7 @@ emms(); - // TODO: dynamic fcode/bcode ??? + /* TODO: dynamic fcode/bcode ??? */ *pBits = BitstreamPos(bs) - *pBits;