📄 estimation_bvop.c
字号:
CHECK_CANDIDATE(centerMV.x - size, centerMV.y, dir); CHECK_CANDIDATE(centerMV.x - size, centerMV.y - size, dir); second_best = data->currentQMV[dir-1]; /* after second_best has been found, go back to the vector we began with */ data->currentQMV[dir-1] = centerMV; *data->iMinSAD = best_sad; xo = centerMV.x; yo = centerMV.y; xo2 = second_best.x; yo2 = second_best.y; data->iMinSAD2 = 256 * 4096; if (yo == yo2) { CHECK_CANDIDATE((xo+xo2)>>1, yo, dir); CHECK_CANDIDATE(xo, yo-1, dir); CHECK_CANDIDATE(xo, yo+1, dir); if(best_sad <= data->iMinSAD2) return; if(data->currentQMV[dir-1].x == data->currentQMV2.x) { CHECK_CANDIDATE((xo+xo2)>>1, yo-1, dir); CHECK_CANDIDATE((xo+xo2)>>1, yo+1, dir); } else { CHECK_CANDIDATE((xo+xo2)>>1, (data->currentQMV[dir-1].x == xo) ? data->currentQMV[dir-1].y : data->currentQMV2.y, dir); } return; } if (xo == xo2) { CHECK_CANDIDATE(xo, (yo+yo2)>>1, dir); CHECK_CANDIDATE(xo-1, yo, dir); CHECK_CANDIDATE(xo+1, yo, dir); if(best_sad < data->iMinSAD2) return; if(data->currentQMV[dir-1].y == data->currentQMV2.y) { CHECK_CANDIDATE(xo-1, (yo+yo2)>>1, dir); CHECK_CANDIDATE(xo+1, (yo+yo2)>>1, dir); } else { CHECK_CANDIDATE((data->currentQMV[dir-1].y == yo) ? data->currentQMV[dir-1].x : data->currentQMV2.x, (yo+yo2)>>1, dir); } return; } CHECK_CANDIDATE(xo, (yo+yo2)>>1, dir); CHECK_CANDIDATE((xo+xo2)>>1, yo, dir); if(best_sad <= data->iMinSAD2) return; CHECK_CANDIDATE((xo+xo2)>>1, (yo+yo2)>>1, dir);}static voidSearchInterpolate(const IMAGE * const f_Ref, const uint8_t * const f_RefH, const uint8_t * const f_RefV, const uint8_t * const f_RefHV, const IMAGE * const b_Ref, const uint8_t * const b_RefH, const uint8_t * const b_RefV, const uint8_t * const b_RefHV, const int x, const int y, const uint32_t fcode, const uint32_t bcode, const uint32_t MotionFlags, const MBParam * const pParam, const VECTOR * const f_predMV, const VECTOR * const b_predMV, MACROBLOCK * const pMB, int32_t * const best_sad, SearchData * const Data){ int i, j; int b_range[4], f_range[4]; int threshA = (MotionFlags & XVID_ME_FAST_MODEINTERPOLATE) ? 250 : 500; int threshB = (MotionFlags & XVID_ME_FAST_MODEINTERPOLATE) ? 150 : 300; Data->qpel_precision = 0; *Data->iMinSAD = 4096*256; Data->iFcode = fcode; Data->bFcode = bcode; i = (x + y * Data->iEdgedWidth) * 16; Data->RefP[0] = f_Ref->y + i; Data->RefP[2] = f_RefH + i; Data->RefP[1] = f_RefV + i; Data->RefP[3] = f_RefHV + i; Data->b_RefP[0] = b_Ref->y + i; Data->b_RefP[2] = b_RefH + i; Data->b_RefP[1] = b_RefV + i; Data->b_RefP[3] = b_RefHV + i; Data->RefP[4] = f_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8; Data->RefP[5] = f_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8; Data->b_RefP[4] = b_Ref->u + (x + (Data->iEdgedWidth/2) * y) * 8; Data->b_RefP[5] = b_Ref->v + (x + (Data->iEdgedWidth/2) * y) * 8; Data->predMV = *f_predMV; Data->bpredMV = *b_predMV; Data->currentMV[0] = Data->currentMV[2]; /* forward search left its vector here */ get_range(f_range, f_range+1, f_range+2, f_range+3, x, y, 4, pParam->width, pParam->height, fcode - Data->qpel, 1, 0); get_range(b_range, b_range+1, b_range+2, b_range+3, x, y, 4, pParam->width, pParam->height, bcode - Data->qpel, 1, 0); if (Data->currentMV[0].x > f_range[1]) Data->currentMV[0].x = f_range[1]; if (Data->currentMV[0].x < f_range[0]) Data->currentMV[0].x = f_range[0]; if (Data->currentMV[0].y > f_range[3]) Data->currentMV[0].y = f_range[3]; if (Data->currentMV[0].y < f_range[2]) Data->currentMV[0].y = f_range[2]; if (Data->currentMV[1].x > b_range[1]) Data->currentMV[1].x = b_range[1]; if (Data->currentMV[1].x < b_range[0]) Data->currentMV[1].x = b_range[0]; if (Data->currentMV[1].y > b_range[3]) Data->currentMV[1].y = b_range[3]; if (Data->currentMV[1].y < b_range[2]) Data->currentMV[1].y = b_range[2]; set_range(f_range, Data); CheckCandidateInt(Data->currentMV[0].x, Data->currentMV[0].y, Data, 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) { if (*Data->iMinSAD > *best_sad + threshA) return; 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, fcode, 2, 0); 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) { if (MotionFlags & XVID_ME_FASTREFINE16) SubpelRefine_Fast_dir(Data, CheckCandidateInt_qpel, 1); else SubpelRefine_dir(Data, CheckCandidateInt, 1); } if (*Data->iMinSAD > *best_sad + threshB) return; get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4, pParam->width, pParam->height, bcode, 2, 0); if (MotionFlags & XVID_ME_QUARTERPELREFINE16) { if (MotionFlags & XVID_ME_FASTREFINE16) SubpelRefine_Fast_dir(Data, CheckCandidateInt_qpel, 2); else SubpelRefine_dir(Data, CheckCandidateInt, 2); } } *Data->iMinSAD += 2 * Data->lambda16; /* two bits are needed to code interpolate mode. */ if (*Data->iMinSAD < *best_sad) { *best_sad = *Data->iMinSAD; pMB->mvs[0] = Data->currentMV[0]; pMB->b_mvs[0] = Data->currentMV[1]; pMB->mode = MODE_INTERPOLATE; if (Data->qpel) { pMB->qmvs[0] = Data->currentQMV[0]; pMB->b_qmvs[0] = Data->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; } 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; } }}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; uint32_t skip_sad; const MACROBLOCK * const b_mbs = b_reference->mbs; MACROBLOCK *const pMBs = frame->mbs; VECTOR f_predMV, b_predMV; const int32_t TRB = time_pp - time_bp; const int32_t TRD = time_pp; /* some pre-inintialized data for the rest of the search */ SearchData Data; memset(&Data, 0, sizeof(SearchData)); Data.iEdgedWidth = pParam->edged_width; Data.qpel = pParam->vol_flags & XVID_VOL_QUARTERPEL ? 1 : 0; Data.rounding = 0; Data.chroma = frame->motion_flags & XVID_ME_CHROMA_BVOP; Data.iQuant = frame->quant; Data.RefQ = f_refV->u; /* a good place, also used in MC (for similar purpose) */ /* note: i==horizontal, j==vertical */ 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; int interpol_search = 0; int bf_search = 0; int bf_thresh = 0;/* 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; } Data.lambda16 = xvid_me_lambda_vec16[b_mb->quant]; Data.Cur = frame->image.y + (j * Data.iEdgedWidth + i) * 16; Data.CurU = frame->image.u + (j * Data.iEdgedWidth/2 + i) * 8; Data.CurV = frame->image.v + (j * Data.iEdgedWidth/2 + i) * 8;/* 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(f_ref, f_refH->y, f_refV->y, f_refHV->y, b_ref, b_refH->y, b_refV->y, b_refHV->y, &frame->image, i, j, frame->motion_flags, TRB, TRD, pParam, pMB, b_mb, &best_sad, &Data); if (pMB->mode == MODE_DIRECT_NONE_MV) { pMB->sad16 = best_sad; continue; } if (frame->motion_flags & XVID_ME_BFRAME_EARLYSTOP) { if(i > 0 && j > 0 && i < pParam->mb_width) { bf_thresh = MIN((&pMBs[(i-1) + j * pParam->mb_width])->sad16, MIN((&pMBs[i + (j-1) * pParam->mb_width])->sad16, (&pMBs[(i+1) + (j-1) * pParam->mb_width])->sad16)); if (((&pMBs[(i-1) + j * pParam->mb_width])->mode != MODE_FORWARD) && ((&pMBs[(i-1) + j * pParam->mb_width])->mode != MODE_BACKWARD) && ((&pMBs[(i-1) + j * pParam->mb_width])->mode != MODE_INTERPOLATE)) bf_search++; if (((&pMBs[i + (j - 1) * pParam->mb_width])->mode != MODE_FORWARD) && ((&pMBs[i + (j - 1) * pParam->mb_width])->mode != MODE_BACKWARD) && ((&pMBs[i + (j - 1) * pParam->mb_width])->mode != MODE_INTERPOLATE)) bf_search++; if (((&pMBs[(i + 1) + (j - 1) * pParam->mb_width])->mode != MODE_FORWARD) && ((&pMBs[(i + 1) + (j - 1) * pParam->mb_width])->mode != MODE_BACKWARD) && ((&pMBs[(i + 1) + (j - 1) * pParam->mb_width])->mode != MODE_INTERPOLATE)) bf_search++; } if ((best_sad < bf_thresh) && (bf_search == 3)) continue; } /* forward search */ SearchBF(f_ref, f_refH->y, f_refV->y, f_refHV->y, i, j, frame->motion_flags, frame->fcode, pParam, pMB, &f_predMV, &best_sad, MODE_FORWARD, &Data); /* backward search */ SearchBF(b_ref, b_refH->y, b_refV->y, b_refHV->y, i, j, frame->motion_flags, frame->bcode, pParam, pMB, &b_predMV, &best_sad, MODE_BACKWARD, &Data); /* interpolate search comes last, because it uses data from forward and backward as prediction */ if (frame->motion_flags & XVID_ME_FAST_MODEINTERPOLATE) { if(i > 0 && j > 0 && i < pParam->mb_width) { if ((&pMBs[(i-1) + j * pParam->mb_width])->mode == MODE_INTERPOLATE) interpol_search++; if ((&pMBs[i + (j - 1) * pParam->mb_width])->mode == MODE_INTERPOLATE) interpol_search++; if ((&pMBs[(i + 1) + (j - 1) * pParam->mb_width])->mode == MODE_INTERPOLATE) interpol_search++; } else interpol_search = 1; interpol_search |= !(best_sad < 3 * Data.iQuant * MAX_SAD00_FOR_SKIP * (Data.chroma ? 3:2)); } else interpol_search = 1; if (interpol_search) { SearchInterpolate(f_ref, f_refH->y, f_refV->y, f_refHV->y, b_ref, b_refH->y, b_refV->y, b_refHV->y, i, j, frame->fcode, frame->bcode, frame->motion_flags, pParam, &f_predMV, &b_predMV, pMB, &best_sad, &Data); } /* final skip decision */ if ( (skip_sad < Data.iQuant * MAX_SAD00_FOR_SKIP * (Data.chroma ? 3:2) ) && ((100*best_sad)/(skip_sad+1) > FINAL_SKIP_THRESH) ) SkipDecisionB(&frame->image, f_ref, b_ref, pMB, i, j, &Data); switch (pMB->mode) { case MODE_FORWARD: f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0]; pMB->sad16 = best_sad; break; case MODE_BACKWARD: b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0]; pMB->sad16 = best_sad; break; case MODE_INTERPOLATE: f_predMV = Data.qpel ? pMB->qmvs[0] : pMB->mvs[0]; b_predMV = Data.qpel ? pMB->b_qmvs[0] : pMB->b_mvs[0]; pMB->sad16 = best_sad; break; default: pMB->sad16 = best_sad; break; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -