--- trunk/xvidcore/src/encoder.c 2002/07/19 14:56:00 317 +++ trunk/xvidcore/src/encoder.c 2002/07/29 19:21:23 349 @@ -39,10 +39,11 @@ * MinChen * 14.04.2002 added FrameCodeB() * - * $Id: encoder.c,v 1.57 2002-07-19 14:56:00 chl Exp $ + * $Id: encoder.c,v 1.66 2002-07-29 19:21:23 chl Exp $ * ****************************************************************************/ + #include #include #include @@ -55,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" @@ -209,7 +211,7 @@ /* 1 keyframe each 10 seconds */ - if (pParam->max_key_interval == 0) + if (pParam->max_key_interval <= 0) pParam->max_key_interval = 10 * pParam->fincr / pParam->fbase; pEnc = (Encoder *) xvid_malloc(sizeof(Encoder), CACHE_LINE); @@ -344,6 +346,7 @@ pEnc->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->bframes = NULL; if (pEnc->mbParam.max_bframes > 0) { @@ -421,7 +424,7 @@ pEnc->mbParam.m_seconds = 0; pEnc->mbParam.m_ticks = 0; pEnc->m_framenum = 0; - pEnc->last_pframe = 1; + pEnc->last_pframe = 0; #endif pParam->handle = (void *) pEnc; @@ -852,12 +855,12 @@ else pEnc->current->quant = pFrame->quant; - if (pEnc->current->quant < 1) +/* if (pEnc->current->quant < 1) pEnc->current->quant = 1; if (pEnc->current->quant > 31) pEnc->current->quant = 31; - +*/ pEnc->current->global_flags = pFrame->general; pEnc->current->motion_flags = pFrame->motion; @@ -1004,10 +1007,6 @@ * This will be coded as a Bidirectional Frame */ - DPRINTF(DPRINTF_DEBUG,"*** BFRAME (store) 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)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP"); } @@ -1019,6 +1018,18 @@ } else { pEnc->current->quant = pFrame->bquant; } + if (pEnc->current->quant < 1) + pEnc->current->quant = 1; + + 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); + + /* store frame into bframe buffer & swap ref back to current */ SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); @@ -1546,6 +1557,7 @@ #define INTRA_THRESHOLD 0.5 +#define BFRAME_SKIP_THRESHHOLD 16 static int FrameCodeP(Encoder * pEnc, @@ -1560,7 +1572,8 @@ DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); int iLimit; - uint32_t x, y; + int k; + int x, y; int iSearchRange; int bIntra; @@ -1683,12 +1696,51 @@ 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++; - } else { + } else { pEnc->sStat.ublks++; - } + } 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) + { + 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 { + MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->sStat); + } + stop_coding_timer(); } } @@ -1722,12 +1774,38 @@ pEnc->sStat.fMvPrevSigma = fSigma; +#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 <= + (pEnc->frame_drop_ratio * pEnc->mbParam.mb_width * pEnc->mbParam.mb_height) / 100) + { + pEnc->sStat.kblks = pEnc->sStat.mblks = 0; + pEnc->sStat.ublks = pEnc->mbParam.mb_width * pEnc->mbParam.mb_height; + + BitstreamReset(bs); + BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 0); + + // 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; + 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); + + } +#endif + *pBits = BitstreamPos(bs) - *pBits; - pEnc->time_pp = ((int32_t)pEnc->mbParam.fbase - (int32_t)pEnc->last_pframe + (int32_t)pEnc->mbParam.m_ticks) % (int32_t)pEnc->mbParam.fbase; - fprintf(stderr,"fbase=%d last_p=%d ticks=%d time_pp = %d\n",pEnc->mbParam.fbase,pEnc->last_pframe,pEnc->mbParam.m_ticks,pEnc->time_pp); +#ifdef BFRAMES + 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 - pEnc->last_pframe = pEnc->mbParam.m_ticks; return 0; // inter } @@ -1783,9 +1861,8 @@ stop_inter_timer(); start_timer(); - fprintf(stderr,"m_ticks =%d\n",(int32_t)pEnc->mbParam.m_ticks+1); 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, @@ -1850,12 +1927,12 @@ qcoeff); //mb->cbp = MBTransQuantBVOP(&pEnc->mbParam, x, y, dct_codes, qcoeff, &frame->image, frame->quant); - - if ((mb->mode == MODE_INTERPOLATE || mb->mode == MODE_DIRECT) - && mb->cbp == 0 && mb->mvs[0].x == 0 && mb->mvs[0].y == 0) { + if ( (mb->mode == MODE_DIRECT) && (mb->cbp == 0) + && (mb->deltamv.x == 0) && (mb->deltamv.y == 0) ) { mb->mode = MODE_DIRECT_NONE_MV; // skipped } +/* update predictors for forward and backward vectors */ if (mb->mode == MODE_INTERPOLATE || mb->mode == MODE_FORWARD) { mb->pmvs[0].x = mb->mvs[0].x - forward.x; mb->pmvs[0].y = mb->mvs[0].y - forward.y; @@ -1869,6 +1946,7 @@ backward.x = mb->b_mvs[0].x; backward.y = mb->b_mvs[0].y; } + // DPRINTF("%05i : [%i %i] M=%i CBP=%i MVS=%i,%i forward=%i,%i", pEnc->m_framenum, x, y, mb->mode, mb->cbp, mb->mvs[0].x, mb->mvs[0].y, forward.x, forward.y); #ifdef BFRAMES_DEC_DEBUG @@ -1896,3 +1974,18 @@ #endif } #endif + + +/* in case internal output is needed somewhere... */ +/* { + FILE *filehandle; + filehandle=fopen("last-b.pgm","wb"); + if (filehandle) + { + fprintf(filehandle,"P5\n\n"); // + fprintf(filehandle,"%d %d 255\n",pEnc->mbParam.edged_width,pEnc->mbParam.edged_height); + fwrite(frame->image.y,pEnc->mbParam.edged_width,pEnc->mbParam.edged_height,filehandle); + fclose(filehandle); + } + } +*/