--- trunk/xvidcore/src/encoder.c 2002/07/24 23:17:19 340 +++ branches/dev-api-3/xvidcore/src/encoder.c 2002/09/04 18:44:41 392 @@ -39,7 +39,7 @@ * MinChen * 14.04.2002 added FrameCodeB() * - * $Id: encoder.c,v 1.64 2002-07-24 23:17:19 chl Exp $ + * $Id: encoder.c,v 1.76 2002-09-03 17:25:18 chl Exp $ * ****************************************************************************/ @@ -56,6 +56,7 @@ #include "image/image.h" #ifdef BFRAMES #include "image/font.h" +#include "motion/sad.h" #endif #include "motion/motion.h" #include "bitstream/cbp.h" @@ -423,7 +424,8 @@ pEnc->mbParam.m_seconds = 0; pEnc->mbParam.m_ticks = 0; pEnc->m_framenum = 0; - pEnc->last_pframe = 1; + pEnc->last_pframe = 0; + pEnc->last_sync = 0; #endif pParam->handle = (void *) pEnc; @@ -619,17 +621,28 @@ } -#ifdef BFRAMES void inc_frame_num(Encoder * pEnc) { - pEnc->iFrameNum++; pEnc->mbParam.m_ticks += pEnc->mbParam.fincr; +#ifdef BFRAMES + pEnc->mbParam.m_ticks = pEnc->mbParam.m_ticks % pEnc->mbParam.fbase; + if (pEnc->mbParam.m_ticks < pEnc->last_sync) + pEnc->mbParam.m_seconds = 1; // more than 1 second since last I or P is not supported. + else + pEnc->mbParam.m_seconds = 0; + + if (pEnc->current->coding_type != B_VOP) + pEnc->last_sync = pEnc->mbParam.m_ticks; +#else + pEnc->mbParam.m_seconds = pEnc->mbParam.m_ticks / pEnc->mbParam.fbase; pEnc->mbParam.m_ticks = pEnc->mbParam.m_ticks % pEnc->mbParam.fbase; -} + #endif +} + #ifdef BFRAMES void queue_image(Encoder * pEnc, XVID_ENC_FRAME * pFrame) @@ -825,7 +838,7 @@ pFrame->intra = 0; - BitstreamPutBits(&bs, 0x7f, 8); + BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0); // write N_VOP BitstreamPad(&bs); pFrame->length = BitstreamLength(&bs); @@ -1043,6 +1056,8 @@ goto bvop_loop; } + pEnc->iFrameNum++; + BitstreamPad(&bs); pFrame->length = BitstreamLength(&bs); @@ -1117,10 +1132,8 @@ pEnc->current->global_flags = pFrame->general; pEnc->current->motion_flags = pFrame->motion; -#ifdef BFRAMES pEnc->current->seconds = pEnc->mbParam.m_seconds; pEnc->current->ticks = pEnc->mbParam.m_ticks; -#endif pEnc->mbParam.hint = &pFrame->hint; start_timer(); @@ -1250,12 +1263,8 @@ DEBUG(temp); #endif -#ifdef BFRAMES inc_frame_num(pEnc); -#else pEnc->iFrameNum++; -#endif - stop_global_timer(); write_timer(); @@ -1535,6 +1544,11 @@ stop_prediction_timer(); start_timer(); + if (pEnc->current->global_flags & XVID_GREYSCALE) + { pMB->cbp &= 0x3C; /* keep only bits 5-2 */ + 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); stop_coding_timer(); } @@ -1556,6 +1570,7 @@ #define INTRA_THRESHOLD 0.5 +#define BFRAME_SKIP_THRESHHOLD 16 static int FrameCodeP(Encoder * pEnc, @@ -1570,7 +1585,7 @@ DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); int iLimit; - uint32_t x, y; + int x, y, k; int iSearchRange; int bIntra; @@ -1698,7 +1713,55 @@ } start_timer(); - MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->sStat); + + /* Finished processing the MB, now check if to CODE or SKIP */ + + if (pMB->cbp == 0 && pMB->mode == MODE_INTER && pMB->mvs[0].x == 0 && + pMB->mvs[0].y == 0) { + +/* This is a candidate for SKIPping, but check intermediate B-frames first */ + +#ifdef BFRAMES + int iSAD=BFRAME_SKIP_THRESHHOLD; + int bSkip=1; + + for (k=pEnc->bframenum_head; k< pEnc->bframenum_tail; k++) + { + 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) + { bSkip = 0; + break; + } + } + if (!bSkip) + { + if (pEnc->current->global_flags & XVID_GREYSCALE) + { pMB->cbp &= 0x3C; /* keep only bits 5-2 */ + 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); + pMB->cbp = 0x80; /* trick! so cbp!=0, but still nothing is written to bs */ + } + else + MBSkip(bs); + +#else + MBSkip(bs); /* without B-frames, no precautions are needed */ + +#endif + + } else { + if (pEnc->current->global_flags & XVID_GREYSCALE) + { pMB->cbp &= 0x3C; /* keep only bits 5-2 */ + 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); + } + stop_coding_timer(); } } @@ -1735,7 +1798,7 @@ #ifdef BFRAMES /* 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 <= + if (pEnc->sStat.kblks + pEnc->sStat.mblks < (pEnc->frame_drop_ratio * pEnc->mbParam.mb_width * pEnc->mbParam.mb_height) / 100) { pEnc->sStat.kblks = pEnc->sStat.mblks = 0; @@ -1759,8 +1822,9 @@ *pBits = BitstreamPos(bs) - *pBits; #ifdef BFRAMES - pEnc->time_pp = ((int32_t)pEnc->mbParam.fbase - (int32_t)pEnc->last_pframe + (int32_t)pEnc->mbParam.m_ticks) % (int32_t)pEnc->mbParam.fbase; - pEnc->last_pframe = pEnc->mbParam.m_ticks; + pEnc->time_pp = ((int32_t)pEnc->mbParam.fbase - (int32_t)pEnc->last_pframe + (int32_t)pEnc->current->ticks) % + (int32_t)pEnc->mbParam.fbase; + pEnc->last_pframe = pEnc->current->ticks; #endif return 0; // inter @@ -1819,7 +1883,7 @@ start_timer(); MotionEstimationBVOP(&pEnc->mbParam, frame, - ((int32_t)pEnc->mbParam.fbase + (int32_t)pEnc->mbParam.m_ticks + 1 - (int32_t)pEnc->last_pframe) % pEnc->mbParam.fbase, + ((int32_t)pEnc->mbParam.fbase + pEnc->last_pframe - frame->ticks) % pEnc->mbParam.fbase, pEnc->time_pp, pEnc->reference->mbs, f_ref, &pEnc->f_refh, &pEnc->f_refv, &pEnc->f_refhv, @@ -1880,8 +1944,7 @@ mb->quant = frame->quant; mb->cbp = - MBTransQuantInter(&pEnc->mbParam, frame, mb, x, y, dct_codes, - qcoeff); + MBTransQuantInterBVOP(&pEnc->mbParam, frame, mb, dct_codes, qcoeff); //mb->cbp = MBTransQuantBVOP(&pEnc->mbParam, x, y, dct_codes, qcoeff, &frame->image, frame->quant); if ( (mb->mode == MODE_DIRECT) && (mb->cbp == 0)