54 |
|
|
55 |
#define iDiamondSize 2 |
#define iDiamondSize 2 |
56 |
|
|
57 |
|
static VECTOR |
58 |
|
GlobalMotionEst(const MACROBLOCK * const pMBs, |
59 |
|
const MBParam * const pParam, const uint32_t iFcode); |
60 |
|
|
61 |
|
|
62 |
static __inline int |
static __inline int |
63 |
d_mv_bits(int x, int y, const uint32_t iFcode) |
d_mv_bits(int x, int y, const uint32_t iFcode) |
64 |
{ |
{ |
142 |
Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data) |
Interpolate8x8qpel(const int x, const int y, const int block, const int dir, const SearchData * const data) |
143 |
{ |
{ |
144 |
// create or find a qpel-precision reference picture; return pointer to it |
// create or find a qpel-precision reference picture; return pointer to it |
145 |
uint8_t * Reference = (uint8_t *)data->RefQ; |
uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir; |
146 |
const int32_t iEdgedWidth = data->iEdgedWidth; |
const int32_t iEdgedWidth = data->iEdgedWidth; |
147 |
const uint32_t rounding = data->rounding; |
const uint32_t rounding = data->rounding; |
148 |
const int halfpel_x = x/2; |
const int halfpel_x = x/2; |
160 |
case 1: // x halfpel, y qpel - top or bottom during qpel refinement |
case 1: // x halfpel, y qpel - top or bottom during qpel refinement |
161 |
ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data); |
ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data); |
162 |
ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth; |
ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth; |
163 |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8); |
164 |
break; |
break; |
165 |
|
|
166 |
case 2: // x qpel, y halfpel - left or right during qpel refinement |
case 2: // x qpel, y halfpel - left or right during qpel refinement |
167 |
ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data); |
ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data); |
168 |
ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth; |
ref2 += 8 * (block&1) + 8 * (block>>1) * iEdgedWidth; |
169 |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8); |
170 |
break; |
break; |
171 |
|
|
172 |
default: // x and y in qpel resolution - the "corners" (top left/right and |
default: // x and y in qpel resolution - the "corners" (top left/right and |
187 |
Interpolate16x16qpel(const int x, const int y, const int dir, const SearchData * const data) |
Interpolate16x16qpel(const int x, const int y, const int dir, const SearchData * const data) |
188 |
{ |
{ |
189 |
// create or find a qpel-precision reference picture; return pointer to it |
// create or find a qpel-precision reference picture; return pointer to it |
190 |
uint8_t * Reference = (uint8_t *)data->RefQ; |
uint8_t * Reference = (uint8_t *)data->RefQ + 16*dir; |
191 |
const int32_t iEdgedWidth = data->iEdgedWidth; |
const int32_t iEdgedWidth = data->iEdgedWidth; |
192 |
const uint32_t rounding = data->rounding; |
const uint32_t rounding = data->rounding; |
193 |
const int halfpel_x = x/2; |
const int halfpel_x = x/2; |
200 |
return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data); |
return (uint8_t *) GetReference(halfpel_x, halfpel_y, dir, data); |
201 |
case 1: // x halfpel, y qpel - top or bottom during qpel refinement |
case 1: // x halfpel, y qpel - top or bottom during qpel refinement |
202 |
ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data); |
ref2 = GetReference(halfpel_x, y - halfpel_y, dir, data); |
203 |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8); |
204 |
interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8); |
205 |
interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8); |
206 |
interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8); |
207 |
break; |
break; |
208 |
|
|
209 |
case 2: // x qpel, y halfpel - left or right during qpel refinement |
case 2: // x qpel, y halfpel - left or right during qpel refinement |
210 |
ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data); |
ref2 = GetReference(x - halfpel_x, halfpel_y, dir, data); |
211 |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference, ref1, ref2, iEdgedWidth, rounding, 8); |
212 |
interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference+8, ref1+8, ref2+8, iEdgedWidth, rounding, 8); |
213 |
interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference+8*iEdgedWidth, ref1+8*iEdgedWidth, ref2+8*iEdgedWidth, iEdgedWidth, rounding, 8); |
214 |
interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding); |
interpolate8x8_avg2(Reference+8*iEdgedWidth+8, ref1+8*iEdgedWidth+8, ref2+8*iEdgedWidth+8, iEdgedWidth, rounding, 8); |
215 |
break; |
break; |
216 |
|
|
217 |
default: // x and y in qpel resolution - the "corners" (top left/right and |
default: // x and y in qpel resolution - the "corners" (top left/right and |
1373 |
Data->min_dy *= 2; |
Data->min_dy *= 2; |
1374 |
Data->referencemv = b_mb->qmvs; |
Data->referencemv = b_mb->qmvs; |
1375 |
} else Data->referencemv = b_mb->mvs; |
} else Data->referencemv = b_mb->mvs; |
1376 |
Data->qpel_precision = 0; // it'm a trick. it's 1 not 0, but we need 0 here |
Data->qpel_precision = 0; // it's a trick. it's 1 not 0, but we need 0 here |
1377 |
|
|
1378 |
for (k = 0; k < 4; k++) { |
for (k = 0; k < 4; k++) { |
1379 |
pMB->mvs[k].x = Data->directmvF[k].x = ((TRB * Data->referencemv[k].x) / TRD); |
pMB->mvs[k].x = Data->directmvF[k].x = ((TRB * Data->referencemv[k].x) / TRD); |
1460 |
|
|
1461 |
SubpelRefine(Data); |
SubpelRefine(Data); |
1462 |
|
|
1463 |
*Data->iMinSAD += 1 * Data->lambda16; // one bit is needed to code direct mode |
// *Data->iMinSAD += 1 * Data->lambda16; // one bit is needed to code direct mode |
1464 |
*best_sad = *Data->iMinSAD; |
*best_sad = *Data->iMinSAD; |
1465 |
|
|
1466 |
// if (b_mb->mode == MODE_INTER4V) |
if (b_mb->mode == MODE_INTER4V) |
1467 |
pMB->mode = MODE_DIRECT; |
pMB->mode = MODE_DIRECT; |
1468 |
// else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation |
else pMB->mode = MODE_DIRECT_NO4V; //for faster compensation |
1469 |
|
|
1470 |
pMB->pmvs[3] = *Data->currentMV; |
pMB->pmvs[3] = *Data->currentMV; |
1471 |
|
|
1540 |
bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16; |
bData.RefV = fData->bRefV = b_RefV + (x + y * iEdgedWidth) * 16; |
1541 |
bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16; |
bData.RefHV = fData->bRefHV = b_RefHV + (x + y * iEdgedWidth) * 16; |
1542 |
bData.RefQ = fData->RefQ; |
bData.RefQ = fData->RefQ; |
1543 |
fData->qpel_precision = bData.qpel_precision = 0; |
fData->qpel_precision = bData.qpel_precision = 0; bData.qpel = fData->qpel; |
1544 |
bData.rounding = 0; |
bData.rounding = 0; |
1545 |
|
|
1546 |
bData.bpredMV = fData->predMV = *f_predMV; |
bData.bpredMV = fData->predMV = *f_predMV; |
1551 |
get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, pParam->m_quarterpel); |
get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, pParam->m_quarterpel); |
1552 |
|
|
1553 |
if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx; |
if (fData->currentMV[0].x > fData->max_dx) fData->currentMV[0].x = fData->max_dx; |
1554 |
if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dy; |
if (fData->currentMV[0].x < fData->min_dx) fData->currentMV[0].x = fData->min_dx; |
1555 |
if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dx; |
if (fData->currentMV[0].y > fData->max_dy) fData->currentMV[0].y = fData->max_dy; |
1556 |
if (fData->currentMV[0].y > fData->min_dy) fData->currentMV[0].y = fData->min_dy; |
if (fData->currentMV[0].y < fData->min_dy) fData->currentMV[0].y = fData->min_dy; |
1557 |
|
|
1558 |
if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx; |
if (fData->currentMV[1].x > bData.max_dx) fData->currentMV[1].x = bData.max_dx; |
1559 |
if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dy; |
if (fData->currentMV[1].x < bData.min_dx) fData->currentMV[1].x = bData.min_dx; |
1560 |
if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dx; |
if (fData->currentMV[1].y > bData.max_dy) fData->currentMV[1].y = bData.max_dy; |
1561 |
if (fData->currentMV[1].y > bData.min_dy) fData->currentMV[1].y = bData.min_dy; |
if (fData->currentMV[1].y < bData.min_dy) fData->currentMV[1].y = bData.min_dy; |
1562 |
|
|
1563 |
CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData); |
CheckCandidateInt(fData->currentMV[0].x, fData->currentMV[0].y, 255, &iDirection, fData); |
1564 |
|
|
1584 |
|
|
1585 |
} while (!(iDirection)); |
} while (!(iDirection)); |
1586 |
|
|
|
*fData->iMinSAD += 2 * fData->lambda16; // two bits are needed to code interpolate mode. |
|
|
|
|
1587 |
if (fData->qpel) { |
if (fData->qpel) { |
1588 |
|
CheckCandidate = CheckCandidateInt; |
1589 |
fData->qpel_precision = bData.qpel_precision = 1; |
fData->qpel_precision = bData.qpel_precision = 1; |
1590 |
get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0); |
get_range(&fData->min_dx, &fData->max_dx, &fData->min_dy, &fData->max_dy, x, y, 16, pParam->width, pParam->height, fcode, 0); |
1591 |
get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0); |
get_range(&bData.min_dx, &bData.max_dx, &bData.min_dy, &bData.max_dy, x, y, 16, pParam->width, pParam->height, bcode, 0); |
1598 |
SubpelRefine(&bData); |
SubpelRefine(&bData); |
1599 |
} |
} |
1600 |
|
|
1601 |
|
*fData->iMinSAD += 2 * fData->lambda16; // two bits are needed to code interpolate mode. |
1602 |
|
|
1603 |
if (*fData->iMinSAD < *best_sad) { |
if (*fData->iMinSAD < *best_sad) { |
1604 |
*best_sad = *fData->iMinSAD; |
*best_sad = *fData->iMinSAD; |
1605 |
pMB->mvs[0] = fData->currentMV[0]; |
pMB->mvs[0] = fData->currentMV[0]; |
1660 |
Data.iEdgedWidth = pParam->edged_width; |
Data.iEdgedWidth = pParam->edged_width; |
1661 |
Data.currentMV = currentMV; Data.currentQMV = currentQMV; |
Data.currentMV = currentMV; Data.currentQMV = currentQMV; |
1662 |
Data.iMinSAD = &iMinSAD; |
Data.iMinSAD = &iMinSAD; |
1663 |
Data.lambda16 = lambda_vec16[frame->quant]; |
Data.lambda16 = lambda_vec16[frame->quant] + 2; |
1664 |
Data.qpel = pParam->m_quarterpel; |
Data.qpel = pParam->m_quarterpel; |
1665 |
Data.rounding = 0; |
Data.rounding = 0; |
1666 |
|
|
1757 |
case MODE_DIRECT: |
case MODE_DIRECT: |
1758 |
case MODE_DIRECT_NO4V: |
case MODE_DIRECT_NO4V: |
1759 |
d_count++; |
d_count++; |
|
break; |
|
1760 |
default: |
default: |
1761 |
break; |
break; |
1762 |
} |
} |
2042 |
} |
} |
2043 |
|
|
2044 |
#define INTRA_THRESH 1350 |
#define INTRA_THRESH 1350 |
2045 |
#define INTER_THRESH 900 |
#define INTER_THRESH 1200 |
2046 |
|
|
2047 |
|
|
2048 |
int |
int |
2075 |
IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra; |
IntraThresh -= (IntraThresh * (maxIntra - 5*(maxIntra - intraCount)))/maxIntra; |
2076 |
|
|
2077 |
|
|
2078 |
InterThresh += 300 * (1 - bCount); |
InterThresh += 400 * (1 - bCount); |
2079 |
if (InterThresh < 200) InterThresh = 200; |
if (InterThresh < 200) InterThresh = 200; |
2080 |
|
|
2081 |
if (sadInit) (*sadInit) (); |
if (sadInit) (*sadInit) (); |