📄 estimation_bvop.c
字号:
static voidSearchInterpolate_final(const int x, const int y, const uint32_t MotionFlags, const MBParam * const pParam, int32_t * const best_sad, SearchData * const Data){ int i, j; int b_range[4], f_range[4]; get_range(f_range, f_range+1, f_range+2, f_range+3, x, y, 4, pParam->width, pParam->height, Data->iFcode - Data->qpel, 1); get_range(b_range, b_range+1, b_range+2, b_range+3, x, y, 4, pParam->width, pParam->height, Data->bFcode - Data->qpel, 1); /* diamond */ do { Data->dir = 0; /* forward MV moves */ i = Data->currentMV[0].x; j = Data->currentMV[0].y; CheckCandidateInt(i + 1, j, Data, 1); CheckCandidateInt(i, j + 1, Data, 1); CheckCandidateInt(i - 1, j, Data, 1); CheckCandidateInt(i, j - 1, Data, 1); /* backward MV moves */ set_range(b_range, Data); i = Data->currentMV[1].x; j = Data->currentMV[1].y; CheckCandidateInt(i + 1, j, Data, 2); CheckCandidateInt(i, j + 1, Data, 2); CheckCandidateInt(i - 1, j, Data, 2); CheckCandidateInt(i, j - 1, Data, 2); set_range(f_range, Data); } while (Data->dir != 0); /* qpel refinement */ if (Data->qpel) { Data->qpel_precision = 1; get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4, pParam->width, pParam->height, Data->iFcode, 2); Data->currentQMV[0].x = 2 * Data->currentMV[0].x; Data->currentQMV[0].y = 2 * Data->currentMV[0].y; Data->currentQMV[1].x = 2 * Data->currentMV[1].x; Data->currentQMV[1].y = 2 * Data->currentMV[1].y; if (MotionFlags & XVID_ME_QUARTERPELREFINE16) { xvid_me_SubpelRefine(Data->currentQMV[0], Data, CheckCandidateInt, 1); get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4, pParam->width, pParam->height, Data->bFcode, 2); xvid_me_SubpelRefine(Data->currentQMV[1], Data, CheckCandidateInt, 2); } } if (Data->iMinSAD[0] < *best_sad) *best_sad = Data->iMinSAD[0];}static void ModeDecision_BVOP_SAD(const SearchData * const Data_d, const SearchData * const Data_b, const SearchData * const Data_f, const SearchData * const Data_i, MACROBLOCK * const pMB, const MACROBLOCK * const b_mb, VECTOR * f_predMV, VECTOR * b_predMV){ int mode = MODE_DIRECT, k; int best_sad, f_sad, b_sad, i_sad; const int qpel = Data_d->qpel; /* evaluate cost of all modes - quite simple in SAD */ best_sad = Data_d->iMinSAD[0] + 1*Data_d->lambda16; b_sad = Data_b->iMinSAD[0] + 3*Data_d->lambda16; f_sad = Data_f->iMinSAD[0] + 4*Data_d->lambda16; i_sad = Data_i->iMinSAD[0] + 2*Data_d->lambda16; if (b_sad < best_sad) { mode = MODE_BACKWARD; best_sad = b_sad; } if (f_sad < best_sad) { mode = MODE_FORWARD; best_sad = f_sad; } if (i_sad < best_sad) { mode = MODE_INTERPOLATE; best_sad = i_sad; } pMB->sad16 = best_sad; pMB->mode = mode; pMB->cbp = 63; switch (mode) { case MODE_DIRECT: if (!qpel && b_mb->mode != MODE_INTER4V) pMB->mode = MODE_DIRECT_NO4V; /* for faster compensation */ pMB->pmvs[3] = Data_d->currentMV[0]; for (k = 0; k < 4; k++) { pMB->mvs[k].x = Data_d->directmvF[k].x + Data_d->currentMV->x; pMB->b_mvs[k].x = ( (Data_d->currentMV->x == 0) ? Data_d->directmvB[k].x :pMB->mvs[k].x - Data_d->referencemv[k].x); pMB->mvs[k].y = (Data_d->directmvF[k].y + Data_d->currentMV->y); pMB->b_mvs[k].y = ((Data_d->currentMV->y == 0) ? Data_d->directmvB[k].y : pMB->mvs[k].y - Data_d->referencemv[k].y); if (qpel) { pMB->qmvs[k].x = pMB->mvs[k].x; pMB->mvs[k].x /= 2; pMB->b_qmvs[k].x = pMB->b_mvs[k].x; pMB->b_mvs[k].x /= 2; pMB->qmvs[k].y = pMB->mvs[k].y; pMB->mvs[k].y /= 2; pMB->b_qmvs[k].y = pMB->b_mvs[k].y; pMB->b_mvs[k].y /= 2; } if (b_mb->mode != MODE_INTER4V) { pMB->mvs[3] = pMB->mvs[2] = pMB->mvs[1] = pMB->mvs[0]; pMB->b_mvs[3] = pMB->b_mvs[2] = pMB->b_mvs[1] = pMB->b_mvs[0]; pMB->qmvs[3] = pMB->qmvs[2] = pMB->qmvs[1] = pMB->qmvs[0]; pMB->b_qmvs[3] = pMB->b_qmvs[2] = pMB->b_qmvs[1] = pMB->b_qmvs[0]; break; } } break; case MODE_FORWARD: if (qpel) { pMB->pmvs[0].x = Data_f->currentQMV->x - f_predMV->x; pMB->pmvs[0].y = Data_f->currentQMV->y - f_predMV->y; pMB->qmvs[0] = *Data_f->currentQMV; *f_predMV = Data_f->currentQMV[0]; } else { pMB->pmvs[0].x = Data_f->currentMV->x - f_predMV->x; pMB->pmvs[0].y = Data_f->currentMV->y - f_predMV->y; *f_predMV = Data_f->currentMV[0]; } pMB->mvs[0] = *Data_f->currentMV; pMB->b_mvs[0] = *Data_b->currentMV; /* hint for future searches */ break; case MODE_BACKWARD: if (qpel) { pMB->pmvs[0].x = Data_b->currentQMV->x - b_predMV->x; pMB->pmvs[0].y = Data_b->currentQMV->y - b_predMV->y; pMB->b_qmvs[0] = *Data_b->currentQMV; *b_predMV = Data_b->currentQMV[0]; } else { pMB->pmvs[0].x = Data_b->currentMV->x - b_predMV->x; pMB->pmvs[0].y = Data_b->currentMV->y - b_predMV->y; *b_predMV = Data_b->currentMV[0]; } pMB->b_mvs[0] = *Data_b->currentMV; pMB->mvs[0] = *Data_f->currentMV; /* hint for future searches */ break; case MODE_INTERPOLATE: pMB->mvs[0] = Data_i->currentMV[0]; pMB->b_mvs[0] = Data_i->currentMV[1]; if (qpel) { pMB->qmvs[0] = Data_i->currentQMV[0]; pMB->b_qmvs[0] = Data_i->currentQMV[1]; pMB->pmvs[1].x = pMB->qmvs[0].x - f_predMV->x; pMB->pmvs[1].y = pMB->qmvs[0].y - f_predMV->y; pMB->pmvs[0].x = pMB->b_qmvs[0].x - b_predMV->x; pMB->pmvs[0].y = pMB->b_qmvs[0].y - b_predMV->y; *f_predMV = Data_i->currentQMV[0]; *b_predMV = Data_i->currentQMV[1]; } else { pMB->pmvs[1].x = pMB->mvs[0].x - f_predMV->x; pMB->pmvs[1].y = pMB->mvs[0].y - f_predMV->y; pMB->pmvs[0].x = pMB->b_mvs[0].x - b_predMV->x; pMB->pmvs[0].y = pMB->b_mvs[0].y - b_predMV->y; *f_predMV = Data_i->currentMV[0]; *b_predMV = Data_i->currentMV[1]; } break; }}static __inline voidmaxMotionBVOP(int * const MVmaxF, int * const MVmaxB, const MACROBLOCK * const pMB, const int qpel){ if (pMB->mode == MODE_FORWARD || pMB->mode == MODE_INTERPOLATE) { const VECTOR * const mv = qpel ? pMB->qmvs : pMB->mvs; int max = *MVmaxF; if (mv[0].x > max) max = mv[0].x; else if (-mv[0].x - 1 > max) max = -mv[0].x - 1; if (mv[0].y > max) max = mv[0].y; else if (-mv[0].y - 1 > max) max = -mv[0].y - 1; *MVmaxF = max; } if (pMB->mode == MODE_BACKWARD || pMB->mode == MODE_INTERPOLATE) { const VECTOR * const mv = qpel ? pMB->b_qmvs : pMB->b_mvs; int max = *MVmaxB; if (mv[0].x > max) max = mv[0].x; else if (-mv[0].x - 1 > max) max = -mv[0].x - 1; if (mv[0].y > max) max = mv[0].y; else if (-mv[0].y - 1 > max) max = -mv[0].y - 1; *MVmaxB = max; }}voidMotionEstimationBVOP(MBParam * const pParam, FRAMEINFO * const frame, const int32_t time_bp, const int32_t time_pp, /* forward (past) reference */ const MACROBLOCK * const f_mbs, const IMAGE * const f_ref, const IMAGE * const f_refH, const IMAGE * const f_refV, const IMAGE * const f_refHV, /* backward (future) reference */ const FRAMEINFO * const b_reference, const IMAGE * const b_ref, const IMAGE * const b_refH, const IMAGE * const b_refV, const IMAGE * const b_refHV){ uint32_t i, j; int32_t best_sad = 256*4096; uint32_t skip_sad; int fb_thresh; const MACROBLOCK * const b_mbs = b_reference->mbs; VECTOR f_predMV, b_predMV; int MVmaxF = 0, MVmaxB = 0; const int32_t TRB = time_pp - time_bp; const int32_t TRD = time_pp; DECLARE_ALIGNED_MATRIX(dct_space, 3, 64, int16_t, CACHE_LINE); /* some pre-inintialized data for the rest of the search */ SearchData Data_d, Data_f, Data_b, Data_i; memset(&Data_d, 0, sizeof(SearchData)); Data_d.iEdgedWidth = pParam->edged_width; Data_d.qpel = pParam->vol_flags & XVID_VOL_QUARTERPEL ? 1 : 0; Data_d.rounding = 0; Data_d.chroma = frame->motion_flags & XVID_ME_CHROMA_BVOP; Data_d.iQuant = frame->quant; Data_d.quant_sq = frame->quant*frame->quant; Data_d.dctSpace = dct_space; Data_d.quant_type = !(pParam->vol_flags & XVID_VOL_MPEGQUANT); Data_d.mpeg_quant_matrices = pParam->mpeg_quant_matrices; Data_d.RefQ = f_refV->u; /* a good place, also used in MC (for similar purpose) */ memcpy(&Data_f, &Data_d, sizeof(SearchData)); memcpy(&Data_b, &Data_d, sizeof(SearchData)); memcpy(&Data_i, &Data_d, sizeof(SearchData)); Data_f.iFcode = Data_i.iFcode = frame->fcode = b_reference->fcode; Data_b.iFcode = Data_i.bFcode = frame->bcode = b_reference->fcode; for (j = 0; j < pParam->mb_height; j++) { f_predMV = b_predMV = zeroMV; /* prediction is reset at left boundary */ for (i = 0; i < pParam->mb_width; i++) { MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width; const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width; pMB->mode = -1; initialize_searchData(&Data_d, &Data_f, &Data_b, &Data_i, i, j, f_ref, f_refH->y, f_refV->y, f_refHV->y, b_ref, b_refH->y, b_refV->y, b_refHV->y, &frame->image, b_mb);/* special case, if collocated block is SKIPed in P-VOP: encoding is forward (0,0), cpb=0 without further ado */ if (b_reference->coding_type != S_VOP) if (b_mb->mode == MODE_NOT_CODED) { pMB->mode = MODE_NOT_CODED; pMB->mvs[0] = pMB->b_mvs[0] = zeroMV; pMB->sad16 = 0; continue; }/* direct search comes first, because it (1) checks for SKIP-mode and (2) sets very good predictions for forward and backward search */ skip_sad = SearchDirect_initial(i, j, frame->motion_flags, TRB, TRD, pParam, pMB, b_mb, &best_sad, &Data_d); if (pMB->mode == MODE_DIRECT_NONE_MV) { pMB->sad16 = best_sad; pMB->cbp = 0; continue; } SearchBF_initial(i, j, frame->motion_flags, frame->fcode, pParam, pMB, &f_predMV, &best_sad, MODE_FORWARD, &Data_f, Data_d.currentMV[1]); SearchBF_initial(i, j, frame->motion_flags, frame->bcode, pParam, pMB, &b_predMV, &best_sad, MODE_BACKWARD, &Data_b, Data_d.currentMV[2]); if (frame->motion_flags&XVID_ME_BFRAME_EARLYSTOP) fb_thresh = best_sad; else fb_thresh = best_sad + (best_sad>>1); if (Data_f.iMinSAD[0] <= fb_thresh) SearchBF_final(i, j, frame->motion_flags, pParam, &best_sad, &Data_f); if (Data_b.iMinSAD[0] <= fb_thresh) SearchBF_final(i, j, frame->motion_flags, pParam, &best_sad, &Data_b); SearchInterpolate_initial(i, j, frame->motion_flags, pParam, &f_predMV, &b_predMV, &best_sad, &Data_i, Data_f.currentMV[0], Data_b.currentMV[0]); if (((Data_i.iMinSAD[0] < best_sad +(best_sad>>3)) && !(frame->motion_flags&XVID_ME_FAST_MODEINTERPOLATE)) || Data_i.iMinSAD[0] <= best_sad) SearchInterpolate_final(i, j, frame->motion_flags, pParam, &best_sad, &Data_i); if (Data_d.iMinSAD[0] <= 2*best_sad) if ((!(frame->motion_flags&XVID_ME_SKIP_DELTASEARCH) && (best_sad > 750)) || (best_sad > 1000)) SearchDirect_final(frame->motion_flags, b_mb, &best_sad, &Data_d); /* final skip decision */ if ( (skip_sad < 2 * Data_d.iQuant * MAX_SAD00_FOR_SKIP ) && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) ) { Data_d.chromaSAD = 0; /* green light for chroma check */ SkipDecisionB(pMB, &Data_d); if (pMB->mode == MODE_DIRECT_NONE_MV) { /* skipped? */ pMB->sad16 = skip_sad; pMB->cbp = 0; continue; } } if (frame->vop_flags & XVID_VOP_RD_BVOP) ModeDecision_BVOP_RD(&Data_d, &Data_b, &Data_f, &Data_i, pMB, b_mb, &f_predMV, &b_predMV, frame->motion_flags, pParam, i, j, best_sad); else ModeDecision_BVOP_SAD(&Data_d, &Data_b, &Data_f, &Data_i, pMB, b_mb, &f_predMV, &b_predMV); maxMotionBVOP(&MVmaxF, &MVmaxB, pMB, Data_d.qpel); } } frame->fcode = getMinFcode(MVmaxF); frame->bcode = getMinFcode(MVmaxB);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -