21 |
* along with this program ; if not, write to the Free Software |
* along with this program ; if not, write to the Free Software |
22 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 |
* |
* |
24 |
* $Id: estimation_bvop.c,v 1.27 2010-12-18 16:02:00 Isibaar Exp $ |
* $Id$ |
25 |
* |
* |
26 |
****************************************************************************/ |
****************************************************************************/ |
27 |
|
|
396 |
const uint32_t iWcount, |
const uint32_t iWcount, |
397 |
const MACROBLOCK * const pMB, |
const MACROBLOCK * const pMB, |
398 |
const uint32_t mode_curr, |
const uint32_t mode_curr, |
399 |
const VECTOR hint) |
const VECTOR hint, const int bound) |
400 |
{ |
{ |
401 |
|
int lx, ly; /* left */ |
402 |
|
int tx, ty; /* top */ |
403 |
|
int rtx, rty; /* top-right */ |
404 |
|
int ltx, lty; /* top-left */ |
405 |
|
int lpos, tpos, rtpos, ltpos; |
406 |
|
|
407 |
|
lx = x - 1; ly = y; |
408 |
|
tx = x; ty = y - 1; |
409 |
|
rtx = x + 1; rty = y - 1; |
410 |
|
ltx = x - 1; lty = y - 1; |
411 |
|
|
412 |
|
lpos = lx + ly * iWcount; |
413 |
|
rtpos = rtx + rty * iWcount; |
414 |
|
tpos = tx + ty * iWcount; |
415 |
|
ltpos = ltx + lty * iWcount; |
416 |
|
|
417 |
|
|
418 |
/* [0] is prediction */ |
/* [0] is prediction */ |
419 |
/* [1] is zero */ |
/* [1] is zero */ |
420 |
pmv[1].x = pmv[1].y = 0; |
pmv[1].x = pmv[1].y = 0; |
421 |
|
|
422 |
pmv[2].x = hint.x; pmv[2].y = hint.y; |
pmv[2].x = hint.x; pmv[2].y = hint.y; |
423 |
|
|
424 |
if ((y != 0)&&(x != (int)(iWcount+1))) { /* [3] top-right neighbour */ |
if (rtpos >= bound && rtx < (int)iWcount) { /* [3] top-right neighbour */ |
425 |
pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr); |
pmv[3] = ChoosePred(pMB+1-iWcount, mode_curr); |
426 |
} else pmv[3].x = pmv[3].y = 0; |
} else pmv[3].x = pmv[3].y = 0; |
427 |
|
|
428 |
if (y != 0) { |
if (tpos >= bound) { |
429 |
pmv[4] = ChoosePred(pMB-iWcount, mode_curr); |
pmv[4] = ChoosePred(pMB-iWcount, mode_curr); /* [4] top */ |
430 |
} else pmv[4].x = pmv[4].y = 0; |
} else pmv[4].x = pmv[4].y = 0; |
431 |
|
|
432 |
if (x != 0) { |
if (lpos >= bound && lx >= 0) { |
433 |
pmv[5] = ChoosePred(pMB-1, mode_curr); |
pmv[5] = ChoosePred(pMB-1, mode_curr); /* [5] left */ |
434 |
} else pmv[5].x = pmv[5].y = 0; |
} else pmv[5].x = pmv[5].y = 0; |
435 |
|
|
436 |
if (x != 0 && y != 0) { |
if (ltpos >= bound && ltx >= 0) { |
437 |
pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr); |
pmv[6] = ChoosePred(pMB-1-iWcount, mode_curr); /* [6] top-left */ |
438 |
} else pmv[6].x = pmv[6].y = 0; |
} else pmv[6].x = pmv[6].y = 0; |
439 |
} |
} |
440 |
|
|
449 |
int32_t * const best_sad, |
int32_t * const best_sad, |
450 |
const int32_t mode_current, |
const int32_t mode_current, |
451 |
SearchData * const Data, |
SearchData * const Data, |
452 |
VECTOR hint) |
VECTOR hint, const int bound) |
453 |
{ |
{ |
454 |
|
|
455 |
int i; |
int i; |
468 |
hint.x /= 2; hint.y /= 2; |
hint.x /= 2; hint.y /= 2; |
469 |
} |
} |
470 |
|
|
471 |
PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current, hint); |
PreparePredictionsBF(pmv, x, y, pParam->mb_width, pMB, mode_current, hint, bound); |
472 |
|
|
473 |
Data->currentMV->x = Data->currentMV->y = 0; |
Data->currentMV->x = Data->currentMV->y = 0; |
474 |
|
|
810 |
} |
} |
811 |
|
|
812 |
static void |
static void |
813 |
|
SearchInterpolate_final_fast(const int x, const int y, |
814 |
|
const uint32_t MotionFlags, |
815 |
|
const MBParam * const pParam, |
816 |
|
int32_t * const best_sad, |
817 |
|
SearchData * const Data) |
818 |
|
{ |
819 |
|
/* qpel refinement */ |
820 |
|
if (Data->qpel) { |
821 |
|
Data->qpel_precision = 1; |
822 |
|
get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, |
823 |
|
x, y, 4, pParam->width, pParam->height, Data->iFcode, 2); |
824 |
|
|
825 |
|
Data->currentQMV[0].x = 2 * Data->currentMV[0].x; |
826 |
|
Data->currentQMV[0].y = 2 * Data->currentMV[0].y; |
827 |
|
Data->currentQMV[1].x = 2 * Data->currentMV[1].x; |
828 |
|
Data->currentQMV[1].y = 2 * Data->currentMV[1].y; |
829 |
|
} |
830 |
|
} |
831 |
|
|
832 |
|
static void |
833 |
ModeDecision_BVOP_SAD(const SearchData * const Data_d, |
ModeDecision_BVOP_SAD(const SearchData * const Data_d, |
834 |
const SearchData * const Data_b, |
const SearchData * const Data_b, |
835 |
const SearchData * const Data_f, |
const SearchData * const Data_f, |
837 |
MACROBLOCK * const pMB, |
MACROBLOCK * const pMB, |
838 |
const MACROBLOCK * const b_mb, |
const MACROBLOCK * const b_mb, |
839 |
VECTOR * f_predMV, |
VECTOR * f_predMV, |
840 |
VECTOR * b_predMV) |
VECTOR * b_predMV, |
841 |
|
int force_direct) |
842 |
{ |
{ |
843 |
int mode = MODE_DIRECT, k; |
int mode = MODE_DIRECT, k; |
844 |
int best_sad, f_sad, b_sad, i_sad; |
int best_sad, f_sad, b_sad, i_sad; |
850 |
f_sad = Data_f->iMinSAD[0] + 4*Data_d->lambda16; |
f_sad = Data_f->iMinSAD[0] + 4*Data_d->lambda16; |
851 |
i_sad = Data_i->iMinSAD[0] + 2*Data_d->lambda16; |
i_sad = Data_i->iMinSAD[0] + 2*Data_d->lambda16; |
852 |
|
|
853 |
|
if (force_direct) |
854 |
|
goto set_mode; /* bypass checks for non-direct modes */ |
855 |
|
|
856 |
if (b_sad < best_sad) { |
if (b_sad < best_sad) { |
857 |
mode = MODE_BACKWARD; |
mode = MODE_BACKWARD; |
858 |
best_sad = b_sad; |
best_sad = b_sad; |
868 |
best_sad = i_sad; |
best_sad = i_sad; |
869 |
} |
} |
870 |
|
|
871 |
|
set_mode: |
872 |
pMB->sad16 = best_sad; |
pMB->sad16 = best_sad; |
873 |
pMB->mode = mode; |
pMB->mode = mode; |
874 |
pMB->cbp = 63; |
pMB->cbp = 63; |
1003 |
const IMAGE * const b_ref, |
const IMAGE * const b_ref, |
1004 |
const IMAGE * const b_refH, |
const IMAGE * const b_refH, |
1005 |
const IMAGE * const b_refV, |
const IMAGE * const b_refV, |
1006 |
const IMAGE * const b_refHV) |
const IMAGE * const b_refHV, |
1007 |
|
const int num_slices) |
1008 |
{ |
{ |
1009 |
uint32_t i, j; |
uint32_t i, j; |
1010 |
int32_t best_sad = 256*4096; |
int32_t best_sad = 256*4096; |
1014 |
|
|
1015 |
VECTOR f_predMV, b_predMV; |
VECTOR f_predMV, b_predMV; |
1016 |
|
|
1017 |
|
int mb_width = pParam->mb_width; |
1018 |
|
int mb_height = pParam->mb_height; |
1019 |
int MVmaxF = 0, MVmaxB = 0; |
int MVmaxF = 0, MVmaxB = 0; |
1020 |
const int32_t TRB = time_pp - time_bp; |
const int32_t TRB = time_pp - time_bp; |
1021 |
const int32_t TRD = time_pp; |
const int32_t TRD = time_pp; |
1045 |
Data_b.iFcode = Data_i.bFcode = frame->bcode = b_reference->fcode; |
Data_b.iFcode = Data_i.bFcode = frame->bcode = b_reference->fcode; |
1046 |
|
|
1047 |
for (j = 0; j < pParam->mb_height; j++) { |
for (j = 0; j < pParam->mb_height; j++) { |
1048 |
|
int new_bound = mb_width * ((((j*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices); |
1049 |
|
|
1050 |
f_predMV = b_predMV = zeroMV; /* prediction is reset at left boundary */ |
f_predMV = b_predMV = zeroMV; /* prediction is reset at left boundary */ |
1051 |
|
|
1052 |
for (i = 0; i < pParam->mb_width; i++) { |
for (i = 0; i < pParam->mb_width; i++) { |
1053 |
MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width; |
MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width; |
1054 |
const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width; |
const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width; |
1055 |
|
int force_direct = (((j*mb_width+i)==new_bound) && (j > 0)) ? 1 : 0; /* MTK decoder chipsets do NOT reset predMVs upon resync marker in BVOPs. We workaround this problem |
1056 |
|
by placing the slice border on second MB in a row and then force the first MB to be direct mode */ |
1057 |
|
|
1058 |
pMB->mode = -1; |
pMB->mode = -1; |
1059 |
|
|
1060 |
initialize_searchData(&Data_d, &Data_f, &Data_b, &Data_i, |
initialize_searchData(&Data_d, &Data_f, &Data_b, &Data_i, |
1083 |
} |
} |
1084 |
|
|
1085 |
SearchBF_initial(i, j, frame->motion_flags, frame->fcode, pParam, pMB, |
SearchBF_initial(i, j, frame->motion_flags, frame->fcode, pParam, pMB, |
1086 |
&f_predMV, &best_sad, MODE_FORWARD, &Data_f, Data_d.currentMV[1]); |
&f_predMV, &best_sad, MODE_FORWARD, &Data_f, Data_d.currentMV[1], new_bound); |
1087 |
|
|
1088 |
SearchBF_initial(i, j, frame->motion_flags, frame->bcode, pParam, pMB, |
SearchBF_initial(i, j, frame->motion_flags, frame->bcode, pParam, pMB, |
1089 |
&b_predMV, &best_sad, MODE_BACKWARD, &Data_b, Data_d.currentMV[2]); |
&b_predMV, &best_sad, MODE_BACKWARD, &Data_b, Data_d.currentMV[2], new_bound); |
1090 |
|
|
1091 |
if (frame->motion_flags&XVID_ME_BFRAME_EARLYSTOP) |
if (frame->motion_flags&XVID_ME_BFRAME_EARLYSTOP) |
1092 |
fb_thresh = best_sad; |
fb_thresh = best_sad; |
1103 |
&Data_i, Data_f.currentMV[0], Data_b.currentMV[0]); |
&Data_i, Data_f.currentMV[0], Data_b.currentMV[0]); |
1104 |
|
|
1105 |
if (((Data_i.iMinSAD[0] < best_sad +(best_sad>>3)) && !(frame->motion_flags&XVID_ME_FAST_MODEINTERPOLATE)) |
if (((Data_i.iMinSAD[0] < best_sad +(best_sad>>3)) && !(frame->motion_flags&XVID_ME_FAST_MODEINTERPOLATE)) |
1106 |
|| Data_i.iMinSAD[0] <= best_sad) |
|| Data_i.iMinSAD[0] <= best_sad) { |
1107 |
|
|
1108 |
SearchInterpolate_final(i, j, frame->motion_flags, pParam, &best_sad, &Data_i); |
SearchInterpolate_final(i, j, frame->motion_flags, pParam, &best_sad, &Data_i); |
1109 |
|
} |
1110 |
|
else { |
1111 |
|
SearchInterpolate_final_fast(i, j, frame->motion_flags, pParam, &best_sad, &Data_i); |
1112 |
|
} |
1113 |
|
|
1114 |
if (Data_d.iMinSAD[0] <= 2*best_sad) |
if (Data_d.iMinSAD[0] <= 2*best_sad) |
1115 |
if ((!(frame->motion_flags&XVID_ME_SKIP_DELTASEARCH) && (best_sad > 750)) |
if ((!(frame->motion_flags&XVID_ME_SKIP_DELTASEARCH) && (best_sad > 750)) |
1134 |
|
|
1135 |
if (frame->vop_flags & XVID_VOP_RD_BVOP) |
if (frame->vop_flags & XVID_VOP_RD_BVOP) |
1136 |
ModeDecision_BVOP_RD(&Data_d, &Data_b, &Data_f, &Data_i, |
ModeDecision_BVOP_RD(&Data_d, &Data_b, &Data_f, &Data_i, |
1137 |
pMB, b_mb, &f_predMV, &b_predMV, frame->motion_flags, frame->vop_flags, pParam, i, j, best_sad); |
pMB, b_mb, &f_predMV, &b_predMV, frame->motion_flags, frame->vop_flags, pParam, i, j, best_sad, force_direct); |
1138 |
else |
else |
1139 |
ModeDecision_BVOP_SAD(&Data_d, &Data_b, &Data_f, &Data_i, pMB, b_mb, &f_predMV, &b_predMV); |
ModeDecision_BVOP_SAD(&Data_d, &Data_b, &Data_f, &Data_i, pMB, b_mb, &f_predMV, &b_predMV, force_direct); |
1140 |
|
|
1141 |
maxMotionBVOP(&MVmaxF, &MVmaxB, pMB, Data_d.qpel); |
maxMotionBVOP(&MVmaxF, &MVmaxB, pMB, Data_d.qpel); |
1142 |
|
|
1170 |
const IMAGE * const b_refV = &pEnc->vInterV; |
const IMAGE * const b_refV = &pEnc->vInterV; |
1171 |
const IMAGE * const b_refHV = &pEnc->vInterHV; |
const IMAGE * const b_refHV = &pEnc->vInterHV; |
1172 |
|
|
1173 |
|
int mb_width = pParam->mb_width; |
1174 |
|
int mb_height = pParam->mb_height; |
1175 |
|
int num_slices = pEnc->num_slices; |
1176 |
int y_row = h->y_row; |
int y_row = h->y_row; |
1177 |
int y_step = h->y_step; |
int y_step = h->y_step; |
1178 |
int start_y = h->start_y; |
int start_y = h->start_y; |
1221 |
max_mbs = 0; |
max_mbs = 0; |
1222 |
|
|
1223 |
for (j = (start_y+y_row); j < stop_y; j += y_step) { |
for (j = (start_y+y_row); j < stop_y; j += y_step) { |
1224 |
|
int new_bound = mb_width * ((((j*num_slices) / mb_height) * mb_height + (num_slices-1)) / num_slices); |
1225 |
|
|
1226 |
if (j == start_y) max_mbs = pParam->mb_width; /* we can process all blocks of the first row */ |
if (j == start_y) max_mbs = pParam->mb_width; /* we can process all blocks of the first row */ |
1227 |
|
|
1228 |
f_predMV = b_predMV = zeroMV; /* prediction is reset at left boundary */ |
f_predMV = b_predMV = zeroMV; /* prediction is reset at left boundary */ |
1230 |
for (i = 0; i < (int) pParam->mb_width; i++) { |
for (i = 0; i < (int) pParam->mb_width; i++) { |
1231 |
MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width; |
MACROBLOCK * const pMB = frame->mbs + i + j * pParam->mb_width; |
1232 |
const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width; |
const MACROBLOCK * const b_mb = b_mbs + i + j * pParam->mb_width; |
1233 |
|
int force_direct = (((j*mb_width+i)==new_bound) && (j > 0)) ? 1 : 0; /* MTK decoder chipsets do NOT reset predMVs upon resync marker in BVOPs. We workaround this problem |
1234 |
|
by placing the slice border on second MB in a row and then force the first MB to be direct mode */ |
1235 |
pMB->mode = -1; |
pMB->mode = -1; |
1236 |
|
|
1237 |
initialize_searchData(&Data_d, &Data_f, &Data_b, &Data_i, |
initialize_searchData(&Data_d, &Data_f, &Data_b, &Data_i, |
1286 |
} |
} |
1287 |
|
|
1288 |
SearchBF_initial(i, j, frame->motion_flags, frame->fcode, pParam, pMB, |
SearchBF_initial(i, j, frame->motion_flags, frame->fcode, pParam, pMB, |
1289 |
&f_predMV, &best_sad, MODE_FORWARD, &Data_f, Data_d.currentMV[1]); |
&f_predMV, &best_sad, MODE_FORWARD, &Data_f, Data_d.currentMV[1], new_bound); |
1290 |
|
|
1291 |
SearchBF_initial(i, j, frame->motion_flags, frame->bcode, pParam, pMB, |
SearchBF_initial(i, j, frame->motion_flags, frame->bcode, pParam, pMB, |
1292 |
&b_predMV, &best_sad, MODE_BACKWARD, &Data_b, Data_d.currentMV[2]); |
&b_predMV, &best_sad, MODE_BACKWARD, &Data_b, Data_d.currentMV[2], new_bound); |
1293 |
|
|
1294 |
if (frame->motion_flags&XVID_ME_BFRAME_EARLYSTOP) |
if (frame->motion_flags&XVID_ME_BFRAME_EARLYSTOP) |
1295 |
fb_thresh = best_sad; |
fb_thresh = best_sad; |
1335 |
|
|
1336 |
if (frame->vop_flags & XVID_VOP_RD_BVOP) |
if (frame->vop_flags & XVID_VOP_RD_BVOP) |
1337 |
ModeDecision_BVOP_RD(&Data_d, &Data_b, &Data_f, &Data_i, |
ModeDecision_BVOP_RD(&Data_d, &Data_b, &Data_f, &Data_i, |
1338 |
pMB, b_mb, &f_predMV, &b_predMV, frame->motion_flags, frame->vop_flags, pParam, i, j, best_sad); |
pMB, b_mb, &f_predMV, &b_predMV, frame->motion_flags, frame->vop_flags, pParam, i, j, best_sad, force_direct); |
1339 |
else |
else |
1340 |
ModeDecision_BVOP_SAD(&Data_d, &Data_b, &Data_f, &Data_i, pMB, b_mb, &f_predMV, &b_predMV); |
ModeDecision_BVOP_SAD(&Data_d, &Data_b, &Data_f, &Data_i, pMB, b_mb, &f_predMV, &b_predMV, force_direct); |
1341 |
|
|
1342 |
*complete_count_self = i+1; |
*complete_count_self = i+1; |
1343 |
current_mb++; |
current_mb++; |