901 |
|
|
902 |
iFound=0; |
iFound=0; |
903 |
|
|
|
/* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion |
|
|
vector of the median. |
|
|
If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 |
|
|
*/ |
|
|
|
|
|
if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) ) |
|
|
iFound=2; |
|
|
|
|
|
/* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. |
|
|
Otherwise select large Diamond Search. |
|
|
*/ |
|
|
|
|
|
if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) ) |
|
|
iDiamondSize=1; // halfpel! |
|
|
else |
|
|
iDiamondSize=2; // halfpel! |
|
|
|
|
|
if (!(MotionFlags & PMV_HALFPELDIAMOND16) ) |
|
|
iDiamondSize*=2; |
|
|
|
|
904 |
/* Step 4: Calculate SAD around the Median prediction. |
/* Step 4: Calculate SAD around the Median prediction. |
905 |
MinSAD=SAD |
MinSAD=SAD |
906 |
If Motion Vector equal to Previous frame motion vector |
If Motion Vector equal to Previous frame motion vector |
908 |
If SAD<=256 goto Step 10. |
If SAD<=256 goto Step 10. |
909 |
*/ |
*/ |
910 |
|
|
|
|
|
|
// Prepare for main loop |
|
|
|
|
911 |
*currMV=pmv[0]; /* current best := prediction */ |
*currMV=pmv[0]; /* current best := prediction */ |
912 |
if (!(MotionFlags & PMV_HALFPEL16 )) |
if (!(MotionFlags & PMV_HALFPEL16 )) |
913 |
{ /* This should NOT be necessary! */ |
{ /* This should NOT be necessary! */ |
939 |
|
|
940 |
if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) ) |
if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,prevMB->mvs[0])) && ((uint32_t)iMinSAD < prevMB->sad16) ) ) |
941 |
{ |
{ |
942 |
|
if (iMinSAD < 2*iQuant) // high chances for SKIP-mode |
943 |
|
{ |
944 |
|
if (!MVzero(*currMV)) |
945 |
|
{ |
946 |
|
iMinSAD += MV16_00_BIAS; |
947 |
|
CHECK_MV16_ZERO; // (0,0) saves space for letterboxed pictures |
948 |
|
iMinSAD -= MV16_00_BIAS; |
949 |
|
} |
950 |
|
} |
951 |
|
|
952 |
if (MotionFlags & PMV_QUICKSTOP16) |
if (MotionFlags & PMV_QUICKSTOP16) |
953 |
goto PMVfast16_Terminate_without_Refine; |
goto PMVfast16_Terminate_without_Refine; |
955 |
goto PMVfast16_Terminate_with_Refine; |
goto PMVfast16_Terminate_with_Refine; |
956 |
} |
} |
957 |
|
|
958 |
|
|
959 |
|
/* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion |
960 |
|
vector of the median. |
961 |
|
If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 |
962 |
|
*/ |
963 |
|
|
964 |
|
if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[0]) ) ) |
965 |
|
iFound=2; |
966 |
|
|
967 |
|
/* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. |
968 |
|
Otherwise select large Diamond Search. |
969 |
|
*/ |
970 |
|
|
971 |
|
if ( (!MVzero(pmv[0])) || (threshB<1536) || (bPredEq) ) |
972 |
|
iDiamondSize=1; // halfpel! |
973 |
|
else |
974 |
|
iDiamondSize=2; // halfpel! |
975 |
|
|
976 |
|
if (!(MotionFlags & PMV_HALFPELDIAMOND16) ) |
977 |
|
iDiamondSize*=2; |
978 |
|
|
979 |
/* |
/* |
980 |
Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. |
Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. |
981 |
Also calculate (0,0) but do not subtract offset. |
Also calculate (0,0) but do not subtract offset. |
985 |
|
|
986 |
// (0,0) is always possible |
// (0,0) is always possible |
987 |
|
|
988 |
|
if (!MVzero(pmv[0])) |
989 |
CHECK_MV16_ZERO; |
CHECK_MV16_ZERO; |
990 |
|
|
991 |
// previous frame MV is always possible |
// previous frame MV is always possible |
992 |
|
|
993 |
|
if (!MVzero(prevMB->mvs[0])) |
994 |
|
if (!MVequal(prevMB->mvs[0],pmv[0])) |
995 |
CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y); |
CHECK_MV16_CANDIDATE(prevMB->mvs[0].x,prevMB->mvs[0].y); |
996 |
|
|
997 |
// left neighbour, if allowed |
// left neighbour, if allowed |
998 |
if (x != 0) |
|
999 |
|
if (!MVzero(pmv[1])) |
1000 |
|
if (!MVequal(pmv[1],prevMB->mvs[0])) |
1001 |
|
if (!MVequal(pmv[1],pmv[0])) |
1002 |
{ |
{ |
1003 |
if (!(MotionFlags & PMV_HALFPEL16 )) |
if (!(MotionFlags & PMV_HALFPEL16 )) |
1004 |
{ pmv[1].x = EVEN(pmv[1].x); |
{ pmv[1].x = EVEN(pmv[1].x); |
1005 |
pmv[1].y = EVEN(pmv[1].y); |
pmv[1].y = EVEN(pmv[1].y); |
1006 |
} |
} |
1007 |
|
|
1008 |
CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y); |
CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y); |
1009 |
} |
} |
1010 |
|
|
1011 |
// top neighbour, if allowed |
// top neighbour, if allowed |
1012 |
if (y != 0) |
if (!MVzero(pmv[2])) |
1013 |
|
if (!MVequal(pmv[2],prevMB->mvs[0])) |
1014 |
|
if (!MVequal(pmv[2],pmv[0])) |
1015 |
|
if (!MVequal(pmv[2],pmv[1])) |
1016 |
{ |
{ |
1017 |
if (!(MotionFlags & PMV_HALFPEL16 )) |
if (!(MotionFlags & PMV_HALFPEL16 )) |
1018 |
{ pmv[2].x = EVEN(pmv[2].x); |
{ pmv[2].x = EVEN(pmv[2].x); |
1021 |
CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y); |
CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y); |
1022 |
|
|
1023 |
// top right neighbour, if allowed |
// top right neighbour, if allowed |
1024 |
if ((uint32_t)x != (iWcount-1)) |
if (!MVzero(pmv[3])) |
1025 |
|
if (!MVequal(pmv[3],prevMB->mvs[0])) |
1026 |
|
if (!MVequal(pmv[3],pmv[0])) |
1027 |
|
if (!MVequal(pmv[3],pmv[1])) |
1028 |
|
if (!MVequal(pmv[3],pmv[2])) |
1029 |
{ |
{ |
1030 |
if (!(MotionFlags & PMV_HALFPEL16 )) |
if (!(MotionFlags & PMV_HALFPEL16 )) |
1031 |
{ pmv[3].x = EVEN(pmv[3].x); |
{ pmv[3].x = EVEN(pmv[3].x); |
1257 |
int32_t psad[4]; |
int32_t psad[4]; |
1258 |
VECTOR newMV; |
VECTOR newMV; |
1259 |
VECTOR backupMV; |
VECTOR backupMV; |
1260 |
|
VECTOR startMV = { start_x, start_y }; |
1261 |
|
|
1262 |
const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; |
const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; |
1263 |
const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount; |
const MACROBLOCK * const prevMB = prevMBs + (x>>1) + (y>>1) * iWcount; |
1266 |
int32_t iFound,bPredEq; |
int32_t iFound,bPredEq; |
1267 |
int32_t iMinSAD,iSAD; |
int32_t iMinSAD,iSAD; |
1268 |
|
|
1269 |
int32_t iSubBlock = ((y&1)<<1) + (x&1); |
int32_t iSubBlock = (y&1)+(y&1) + (x&1); |
1270 |
|
|
1271 |
/* Get maximum range */ |
/* Get maximum range */ |
1272 |
get_range(&min_dx, &max_dx, &min_dy, &max_dy, |
get_range(&min_dx, &max_dx, &min_dy, &max_dy, |
1299 |
|
|
1300 |
iFound=0; |
iFound=0; |
1301 |
|
|
|
/* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion |
|
|
vector of the median. |
|
|
If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 |
|
|
*/ |
|
|
|
|
|
if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) ) |
|
|
iFound=2; |
|
|
|
|
|
/* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. |
|
|
Otherwise select large Diamond Search. |
|
|
*/ |
|
|
|
|
|
if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) ) |
|
|
iDiamondSize=1; // 1 halfpel! |
|
|
else |
|
|
iDiamondSize=2; // 2 halfpel = 1 full pixel! |
|
|
|
|
|
if (!(MotionFlags & PMV_HALFPELDIAMOND8) ) |
|
|
iDiamondSize*=2; |
|
|
|
|
1302 |
/* Step 4: Calculate SAD around the Median prediction. |
/* Step 4: Calculate SAD around the Median prediction. |
1303 |
MinSAD=SAD |
MinSAD=SAD |
1304 |
If Motion Vector equal to Previous frame motion vector |
If Motion Vector equal to Previous frame motion vector |
1309 |
|
|
1310 |
// Prepare for main loop |
// Prepare for main loop |
1311 |
|
|
1312 |
currMV->x=start_x; /* start with mv16 */ |
*currMV = startMV; |
|
currMV->y=start_y; |
|
1313 |
|
|
1314 |
iMinSAD = sad8( cur, |
iMinSAD = sad8( cur, |
1315 |
get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth), |
get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth), |
1316 |
iEdgedWidth); |
iEdgedWidth); |
1317 |
iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant); |
iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode, iQuant); |
1318 |
|
|
1319 |
if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) ) |
if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,prevMB->mvs[iSubBlock])) |
1320 |
|
&& ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) ) |
1321 |
{ |
{ |
1322 |
if (MotionFlags & PMV_QUICKSTOP16) |
if (MotionFlags & PMV_QUICKSTOP16) |
1323 |
goto PMVfast8_Terminate_without_Refine; |
goto PMVfast8_Terminate_without_Refine; |
1325 |
goto PMVfast8_Terminate_with_Refine; |
goto PMVfast8_Terminate_with_Refine; |
1326 |
} |
} |
1327 |
|
|
1328 |
|
/* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion |
1329 |
|
vector of the median. |
1330 |
|
If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2 |
1331 |
|
*/ |
1332 |
|
|
1333 |
|
if ((bPredEq) && (MVequal(pmv[0],prevMB->mvs[iSubBlock]) ) ) |
1334 |
|
iFound=2; |
1335 |
|
|
1336 |
|
/* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. |
1337 |
|
Otherwise select large Diamond Search. |
1338 |
|
*/ |
1339 |
|
|
1340 |
|
if ( (!MVzero(pmv[0])) || (threshB<1536/4) || (bPredEq) ) |
1341 |
|
iDiamondSize=1; // 1 halfpel! |
1342 |
|
else |
1343 |
|
iDiamondSize=2; // 2 halfpel = 1 full pixel! |
1344 |
|
|
1345 |
|
if (!(MotionFlags & PMV_HALFPELDIAMOND8) ) |
1346 |
|
iDiamondSize*=2; |
1347 |
|
|
1348 |
|
|
1349 |
/* |
/* |
1350 |
Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. |
Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. |
1353 |
If MV is (0,0) subtract offset. |
If MV is (0,0) subtract offset. |
1354 |
*/ |
*/ |
1355 |
|
|
1356 |
// the prediction might be even better than mv16 |
// the median prediction might be even better than mv16 |
1357 |
|
|
1358 |
|
if (!MVequal(pmv[0],startMV)) |
1359 |
CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y); |
CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y); |
1360 |
|
|
1361 |
// (0,0) is always possible |
// (0,0) if needed |
1362 |
|
if (!MVzero(pmv[0])) |
1363 |
|
if (!MVzero(startMV)) |
1364 |
CHECK_MV8_ZERO; |
CHECK_MV8_ZERO; |
1365 |
|
|
1366 |
// previous frame MV is always possible |
// previous frame MV if needed |
1367 |
|
if (!MVzero(prevMB->mvs[iSubBlock])) |
1368 |
|
if (!MVequal(prevMB->mvs[iSubBlock],startMV)) |
1369 |
|
if (!MVequal(prevMB->mvs[iSubBlock],pmv[0])) |
1370 |
CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y); |
CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x,prevMB->mvs[iSubBlock].y); |
1371 |
|
|
1372 |
// left neighbour, if allowed |
if ( (iMinSAD <= threshA) || ( MVequal(*currMV,prevMB->mvs[iSubBlock]) && ((uint32_t)iMinSAD < prevMB->sad8[iSubBlock]) ) ) |
1373 |
if (psad[1] != MV_MAX_ERROR) |
{ |
1374 |
|
if (MotionFlags & PMV_QUICKSTOP16) |
1375 |
|
goto PMVfast8_Terminate_without_Refine; |
1376 |
|
if (MotionFlags & PMV_EARLYSTOP16) |
1377 |
|
goto PMVfast8_Terminate_with_Refine; |
1378 |
|
} |
1379 |
|
|
1380 |
|
|
1381 |
|
// left neighbour, if allowed and needed |
1382 |
|
if (!MVzero(pmv[1])) |
1383 |
|
if (!MVequal(pmv[1],startMV)) |
1384 |
|
if (!MVequal(pmv[1],prevMB->mvs[iSubBlock])) |
1385 |
|
if (!MVequal(pmv[1],pmv[0])) |
1386 |
{ |
{ |
1387 |
if (!(MotionFlags & PMV_HALFPEL8 )) |
if (!(MotionFlags & PMV_HALFPEL8 )) |
1388 |
{ pmv[1].x = EVEN(pmv[1].x); |
{ pmv[1].x = EVEN(pmv[1].x); |
1391 |
CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y); |
CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y); |
1392 |
} |
} |
1393 |
|
|
1394 |
// top neighbour, if allowed |
// top neighbour, if allowed and needed |
1395 |
if (psad[2] != MV_MAX_ERROR) |
if (!MVzero(pmv[2])) |
1396 |
|
if (!MVequal(pmv[2],startMV)) |
1397 |
|
if (!MVequal(pmv[2],prevMB->mvs[iSubBlock])) |
1398 |
|
if (!MVequal(pmv[2],pmv[0])) |
1399 |
|
if (!MVequal(pmv[2],pmv[1])) |
1400 |
{ |
{ |
1401 |
if (!(MotionFlags & PMV_HALFPEL8 )) |
if (!(MotionFlags & PMV_HALFPEL8 )) |
1402 |
{ pmv[2].x = EVEN(pmv[2].x); |
{ pmv[2].x = EVEN(pmv[2].x); |
1404 |
} |
} |
1405 |
CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y); |
CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y); |
1406 |
|
|
1407 |
// top right neighbour, if allowed |
// top right neighbour, if allowed and needed |
1408 |
if (psad[3] != MV_MAX_ERROR) |
if (!MVzero(pmv[3])) |
1409 |
|
if (!MVequal(pmv[3],startMV)) |
1410 |
|
if (!MVequal(pmv[3],prevMB->mvs[iSubBlock])) |
1411 |
|
if (!MVequal(pmv[3],pmv[0])) |
1412 |
|
if (!MVequal(pmv[3],pmv[1])) |
1413 |
|
if (!MVequal(pmv[3],pmv[2])) |
1414 |
{ |
{ |
1415 |
if (!(MotionFlags & PMV_HALFPEL8 )) |
if (!(MotionFlags & PMV_HALFPEL8 )) |
1416 |
{ pmv[3].x = EVEN(pmv[3].x); |
{ pmv[3].x = EVEN(pmv[3].x); |