--- motion_est.c 2002/11/07 10:28:15 1.44.2.15 +++ motion_est.c 2002/11/12 14:46:03 1.44.2.18 @@ -845,11 +845,11 @@ /* finally, intra decision */ InterBias = MV16_INTER_BIAS; - if (pMB->quant > 8) InterBias += 80 * (pMB->quant - 8); // to make high quants work + if (pMB->quant > 8) InterBias += 100 * (pMB->quant - 8); // to make high quants work if (y != 0) - if ((pMB - pParam->mb_width)->mode == MODE_INTER ) InterBias -= 80; + if ((pMB - pParam->mb_width)->mode == MODE_INTRA ) InterBias -= 80; if (x != 0) - if ((pMB - 1)->mode == MODE_INTER ) InterBias -= 80; + if ((pMB - 1)->mode == MODE_INTRA ) InterBias -= 80; if (Data.chroma) InterBias += 50; // to compensate bigger SAD @@ -1615,7 +1615,7 @@ const IMAGE * const f_refV, const IMAGE * const f_refHV, // backward (future) reference - const MACROBLOCK * const b_mbs, + const FRAMEINFO * const b_reference, const IMAGE * const b_ref, const IMAGE * const b_refH, const IMAGE * const b_refV, @@ -1625,6 +1625,7 @@ int32_t best_sad, skip_sad; int f_count = 0, b_count = 0, i_count = 0, d_count = 0, n_count = 0; static const VECTOR zeroMV={0,0}; + const MACROBLOCK * const b_mbs = b_reference->mbs; VECTOR f_predMV, b_predMV; /* there is no prediction for direct mode*/ @@ -1652,10 +1653,11 @@ const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width; /* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */ - if (b_mb->mode == MODE_NOT_CODED) { - pMB->mode = MODE_NOT_CODED; - continue; - } + if (b_reference->coding_type != S_VOP) + if (b_mb->mode == MODE_NOT_CODED) { + pMB->mode = MODE_NOT_CODED; + continue; + } Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16; pMB->quant = frame->quant; @@ -1960,49 +1962,68 @@ int i = 255, mask; VECTOR pmv[3]; - *(Data->iMinSAD) = MV_MAX_ERROR; - Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); + + //median is only used as prediction. it doesn't have to be real + if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0; + else + if (x == 1) //left macroblock does not have any vector now + Data->predMV = (pMB - pParam->mb_width)->mvs[0]; // top instead of median + else if (y == 1) // top macroblock don't have it's vector + Data->predMV = (pMB - 1)->mvs[0]; // left instead of median + else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); //else median + get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 16, pParam->width, pParam->height, Data->iFcode, pParam->m_quarterpel); Data->Cur = pCur + (x + y * pParam->edged_width) * 16; Data->Ref = pRef + (x + y * pParam->edged_width) * 16; - CheckCandidate = CheckCandidate16no4vI; - pmv[1].x = EVEN(pMB->mvs[0].x); pmv[1].y = EVEN(pMB->mvs[0].y); - pmv[0].x = EVEN(Data->predMV.x); - pmv[0].y = EVEN(Data->predMV.y); - pmv[2].x = pmv[2].y = 0; + pmv[2].x = EVEN(Data->predMV.x); + pmv[2].y = EVEN(Data->predMV.y); + pmv[0].x = pmv[0].y = 0; + + (*CheckCandidate)(0, 0, 255, &i, Data); + +//early skip for 0,0 + if (*Data->iMinSAD < MAX_SAD00_FOR_SKIP * 4) { + pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0]; + pMB->mode = MODE_NOT_CODED; + return 0; + } - CheckCandidate16no4vI(pmv[0].x, pmv[0].y, 255, &i, Data); if (!(mask = make_mask(pmv, 1))) - CheckCandidate16no4vI(pmv[1].x, pmv[1].y, mask, &i, Data); + (*CheckCandidate)(pmv[1].x, pmv[1].y, mask, &i, Data); if (!(mask = make_mask(pmv, 2))) - CheckCandidate16no4vI(0, 0, mask, &i, Data); + (*CheckCandidate)(pmv[2].x, pmv[2].y, mask, &i, Data); - DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i); + if (*Data->iMinSAD > MAX_SAD00_FOR_SKIP * 4) // diamond only if needed + DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, i); - pMB->mvs[0] = *Data->currentMV; + pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = Data->currentMV[0]; pMB->mode = MODE_INTER; - return *(Data->iMinSAD); } #define INTRA_THRESH 1350 #define INTER_THRESH 900 + int MEanalysis( const IMAGE * const pRef, - const IMAGE * const pCurrent, + FRAMEINFO * const Current, MBParam * const pParam, - MACROBLOCK * const pMBs, - const uint32_t iFcode) + int maxIntra, //maximum number if non-I frames + int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame + int bCount) // number if B frames in a row { uint32_t x, y, intra = 0; int sSAD = 0; + MACROBLOCK * const pMBs = Current->mbs; + const IMAGE * const pCurrent = &Current->image; + int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH; VECTOR currentMV; int32_t iMinSAD; @@ -2010,7 +2031,18 @@ Data.iEdgedWidth = pParam->edged_width; Data.currentMV = ¤tMV; Data.iMinSAD = &iMinSAD; - Data.iFcode = iFcode; + Data.iFcode = Current->fcode; + CheckCandidate = CheckCandidate16no4vI; + + if (intraCount < 12) // we're right after an I frame + IntraThresh += 4 * (intraCount - 12) * (intraCount - 12); + else + if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec + IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra; + + + InterThresh += 300 * (1 - bCount); + if (InterThresh < 200) InterThresh = 200; if (sadInit) (*sadInit) (); @@ -2022,17 +2054,19 @@ sad = MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, pMB, &Data); - if (sad > INTRA_THRESH) { + if (sad > IntraThresh) { dev = dev16(pCurrent->y + (x + y * pParam->edged_width) * 16, pParam->edged_width); - if (dev + INTRA_THRESH < sad) { intra++; pMB->mode = MODE_INTRA; } - if (intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2; // I frame + if (dev + IntraThresh < sad) { + pMB->mode = MODE_INTRA; + if (++intra > (pParam->mb_height-2)*(pParam->mb_width-2)/2) return 2; // I frame } + } sSAD += sad; } } sSAD /= (pParam->mb_height-2)*(pParam->mb_width-2); - if (sSAD > INTER_THRESH ) return 1; //P frame + if (sSAD > InterThresh ) return 1; //P frame emms(); return 0; // B frame