|
|
@ -103,6 +103,69 @@ static av_always_inline void vc1_lut_scale_chroma(uint8_t *srcU, uint8_t *srcV, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const uint8_t popcount4[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static av_always_inline int get_luma_mv(VC1Context *v, int dir, int16_t *tx, int16_t *ty) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MpegEncContext *s = &v->s; |
|
|
|
|
|
|
|
int idx = v->mv_f[dir][s->block_index[0] + v->blocks_off] | |
|
|
|
|
|
|
|
(v->mv_f[dir][s->block_index[1] + v->blocks_off] << 1) | |
|
|
|
|
|
|
|
(v->mv_f[dir][s->block_index[2] + v->blocks_off] << 2) | |
|
|
|
|
|
|
|
(v->mv_f[dir][s->block_index[3] + v->blocks_off] << 3); |
|
|
|
|
|
|
|
static const uint8_t index2[16] = { 0, 0, 0, 0x23, 0, 0x13, 0x03, 0, 0, 0x12, 0x02, 0, 0x01, 0, 0, 0 }; |
|
|
|
|
|
|
|
int opp_count = popcount4[idx]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (opp_count) { |
|
|
|
|
|
|
|
case 0: |
|
|
|
|
|
|
|
case 4: |
|
|
|
|
|
|
|
*tx = median4(s->mv[dir][0][0], s->mv[dir][1][0], s->mv[dir][2][0], s->mv[dir][3][0]); |
|
|
|
|
|
|
|
*ty = median4(s->mv[dir][0][1], s->mv[dir][1][1], s->mv[dir][2][1], s->mv[dir][3][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 1: |
|
|
|
|
|
|
|
*tx = mid_pred(s->mv[dir][idx < 2][0], s->mv[dir][1 + (idx < 4)][0], s->mv[dir][2 + (idx < 8)][0]); |
|
|
|
|
|
|
|
*ty = mid_pred(s->mv[dir][idx < 2][1], s->mv[dir][1 + (idx < 4)][1], s->mv[dir][2 + (idx < 8)][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 3: |
|
|
|
|
|
|
|
*tx = mid_pred(s->mv[dir][idx > 0xd][0], s->mv[dir][1 + (idx > 0xb)][0], s->mv[dir][2 + (idx > 0x7)][0]); |
|
|
|
|
|
|
|
*ty = mid_pred(s->mv[dir][idx > 0xd][1], s->mv[dir][1 + (idx > 0xb)][1], s->mv[dir][2 + (idx > 0x7)][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 2: |
|
|
|
|
|
|
|
*tx = (s->mv[dir][index2[idx] >> 4][0] + s->mv[dir][index2[idx] & 0xf][0]) / 2; |
|
|
|
|
|
|
|
*ty = (s->mv[dir][index2[idx] >> 4][1] + s->mv[dir][index2[idx] & 0xf][1]) / 2; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return opp_count; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static av_always_inline int get_chroma_mv(VC1Context *v, int dir, int16_t *tx, int16_t *ty) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
MpegEncContext *s = &v->s; |
|
|
|
|
|
|
|
int idx = !v->mb_type[0][s->block_index[0]] | |
|
|
|
|
|
|
|
(!v->mb_type[0][s->block_index[1]] << 1) | |
|
|
|
|
|
|
|
(!v->mb_type[0][s->block_index[2]] << 2) | |
|
|
|
|
|
|
|
(!v->mb_type[0][s->block_index[3]] << 3); |
|
|
|
|
|
|
|
static const uint8_t index2[16] = { 0, 0, 0, 0x01, 0, 0x02, 0x12, 0, 0, 0x03, 0x13, 0, 0x23, 0, 0, 0 }; |
|
|
|
|
|
|
|
int valid_count = popcount4[idx]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (valid_count) { |
|
|
|
|
|
|
|
case 4: |
|
|
|
|
|
|
|
*tx = median4(s->mv[dir][0][0], s->mv[dir][1][0], s->mv[dir][2][0], s->mv[dir][3][0]); |
|
|
|
|
|
|
|
*ty = median4(s->mv[dir][0][1], s->mv[dir][1][1], s->mv[dir][2][1], s->mv[dir][3][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 3: |
|
|
|
|
|
|
|
*tx = mid_pred(s->mv[dir][idx > 0xd][0], s->mv[dir][1 + (idx > 0xb)][0], s->mv[dir][2 + (idx > 0x7)][0]); |
|
|
|
|
|
|
|
*ty = mid_pred(s->mv[dir][idx > 0xd][1], s->mv[dir][1 + (idx > 0xb)][1], s->mv[dir][2 + (idx > 0x7)][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 2: |
|
|
|
|
|
|
|
*tx = (s->mv[dir][index2[idx] >> 4][0] + s->mv[dir][index2[idx] & 0xf][0]) / 2; |
|
|
|
|
|
|
|
*ty = (s->mv[dir][index2[idx] >> 4][1] + s->mv[dir][index2[idx] & 0xf][1]) / 2; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return valid_count; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Do motion compensation over 1 macroblock
|
|
|
|
/** Do motion compensation over 1 macroblock
|
|
|
|
* Mostly adapted hpel_motion and qpel_motion from mpegvideo.c |
|
|
|
* Mostly adapted hpel_motion and qpel_motion from mpegvideo.c |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -330,37 +393,10 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_P && n == 3 && v->field_mode) { |
|
|
|
if (s->pict_type == AV_PICTURE_TYPE_P && n == 3 && v->field_mode) { |
|
|
|
int same_count = 0, opp_count = 0, k; |
|
|
|
int opp_count = get_luma_mv(v, 0, |
|
|
|
int chosen_mv[2][4][2], f; |
|
|
|
&s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0], |
|
|
|
int tx, ty; |
|
|
|
&s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1]); |
|
|
|
for (k = 0; k < 4; k++) { |
|
|
|
int k, f = opp_count > 2; |
|
|
|
f = v->mv_f[0][s->block_index[k] + v->blocks_off]; |
|
|
|
|
|
|
|
chosen_mv[f][f ? opp_count : same_count][0] = s->mv[0][k][0]; |
|
|
|
|
|
|
|
chosen_mv[f][f ? opp_count : same_count][1] = s->mv[0][k][1]; |
|
|
|
|
|
|
|
opp_count += f; |
|
|
|
|
|
|
|
same_count += 1 - f; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
f = opp_count > same_count; |
|
|
|
|
|
|
|
switch (f ? opp_count : same_count) { |
|
|
|
|
|
|
|
case 4: |
|
|
|
|
|
|
|
tx = median4(chosen_mv[f][0][0], chosen_mv[f][1][0], |
|
|
|
|
|
|
|
chosen_mv[f][2][0], chosen_mv[f][3][0]); |
|
|
|
|
|
|
|
ty = median4(chosen_mv[f][0][1], chosen_mv[f][1][1], |
|
|
|
|
|
|
|
chosen_mv[f][2][1], chosen_mv[f][3][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 3: |
|
|
|
|
|
|
|
tx = mid_pred(chosen_mv[f][0][0], chosen_mv[f][1][0], chosen_mv[f][2][0]); |
|
|
|
|
|
|
|
ty = mid_pred(chosen_mv[f][0][1], chosen_mv[f][1][1], chosen_mv[f][2][1]); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 2: |
|
|
|
|
|
|
|
tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2; |
|
|
|
|
|
|
|
ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
av_assert0(0); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; |
|
|
|
|
|
|
|
s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; |
|
|
|
|
|
|
|
for (k = 0; k < 4; k++) |
|
|
|
for (k = 0; k < 4; k++) |
|
|
|
v->mv_f[1][s->block_index[k] + v->blocks_off] = f; |
|
|
|
v->mv_f[1][s->block_index[k] + v->blocks_off] = f; |
|
|
|
} |
|
|
|
} |
|
|
@ -465,59 +501,6 @@ void ff_vc1_mc_4mv_luma(VC1Context *v, int n, int dir, int avg) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static av_always_inline int get_chroma_mv(int *mvx, int *mvy, int *a, int flag, int *tx, int *ty) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int idx, i; |
|
|
|
|
|
|
|
static const int count[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
idx = ((a[3] != flag) << 3) |
|
|
|
|
|
|
|
| ((a[2] != flag) << 2) |
|
|
|
|
|
|
|
| ((a[1] != flag) << 1) |
|
|
|
|
|
|
|
| (a[0] != flag); |
|
|
|
|
|
|
|
if (!idx) { |
|
|
|
|
|
|
|
*tx = median4(mvx[0], mvx[1], mvx[2], mvx[3]); |
|
|
|
|
|
|
|
*ty = median4(mvy[0], mvy[1], mvy[2], mvy[3]); |
|
|
|
|
|
|
|
return 4; |
|
|
|
|
|
|
|
} else if (count[idx] == 1) { |
|
|
|
|
|
|
|
switch (idx) { |
|
|
|
|
|
|
|
case 0x1: |
|
|
|
|
|
|
|
*tx = mid_pred(mvx[1], mvx[2], mvx[3]); |
|
|
|
|
|
|
|
*ty = mid_pred(mvy[1], mvy[2], mvy[3]); |
|
|
|
|
|
|
|
return 3; |
|
|
|
|
|
|
|
case 0x2: |
|
|
|
|
|
|
|
*tx = mid_pred(mvx[0], mvx[2], mvx[3]); |
|
|
|
|
|
|
|
*ty = mid_pred(mvy[0], mvy[2], mvy[3]); |
|
|
|
|
|
|
|
return 3; |
|
|
|
|
|
|
|
case 0x4: |
|
|
|
|
|
|
|
*tx = mid_pred(mvx[0], mvx[1], mvx[3]); |
|
|
|
|
|
|
|
*ty = mid_pred(mvy[0], mvy[1], mvy[3]); |
|
|
|
|
|
|
|
return 3; |
|
|
|
|
|
|
|
case 0x8: |
|
|
|
|
|
|
|
*tx = mid_pred(mvx[0], mvx[1], mvx[2]); |
|
|
|
|
|
|
|
*ty = mid_pred(mvy[0], mvy[1], mvy[2]); |
|
|
|
|
|
|
|
return 3; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (count[idx] == 2) { |
|
|
|
|
|
|
|
int t1 = 0, t2 = 0; |
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) |
|
|
|
|
|
|
|
if (!a[i]) { |
|
|
|
|
|
|
|
t1 = i; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
for (i = t1 + 1; i < 4; i++) |
|
|
|
|
|
|
|
if (!a[i]) { |
|
|
|
|
|
|
|
t2 = i; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
*tx = (mvx[t1] + mvx[t2]) / 2; |
|
|
|
|
|
|
|
*ty = (mvy[t1] + mvy[t2]) / 2; |
|
|
|
|
|
|
|
return 2; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Do motion compensation for 4-MV macroblock - both chroma blocks
|
|
|
|
/** Do motion compensation for 4-MV macroblock - both chroma blocks
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir) |
|
|
|
void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir) |
|
|
@ -526,10 +509,8 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir) |
|
|
|
H264ChromaContext *h264chroma = &v->h264chroma; |
|
|
|
H264ChromaContext *h264chroma = &v->h264chroma; |
|
|
|
uint8_t *srcU, *srcV; |
|
|
|
uint8_t *srcU, *srcV; |
|
|
|
int uvmx, uvmy, uvsrc_x, uvsrc_y; |
|
|
|
int uvmx, uvmy, uvsrc_x, uvsrc_y; |
|
|
|
int k, tx = 0, ty = 0; |
|
|
|
int16_t tx, ty; |
|
|
|
int mvx[4], mvy[4], intra[4], mv_f[4]; |
|
|
|
int chroma_ref_type; |
|
|
|
int valid_count; |
|
|
|
|
|
|
|
int chroma_ref_type = v->cur_field_type; |
|
|
|
|
|
|
|
int v_edge_pos = s->v_edge_pos >> v->field_mode; |
|
|
|
int v_edge_pos = s->v_edge_pos >> v->field_mode; |
|
|
|
uint8_t (*lutuv)[256]; |
|
|
|
uint8_t (*lutuv)[256]; |
|
|
|
int use_ic; |
|
|
|
int use_ic; |
|
|
@ -539,31 +520,19 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir) |
|
|
|
if (s->flags & CODEC_FLAG_GRAY) |
|
|
|
if (s->flags & CODEC_FLAG_GRAY) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
for (k = 0; k < 4; k++) { |
|
|
|
|
|
|
|
mvx[k] = s->mv[dir][k][0]; |
|
|
|
|
|
|
|
mvy[k] = s->mv[dir][k][1]; |
|
|
|
|
|
|
|
intra[k] = v->mb_type[0][s->block_index[k]]; |
|
|
|
|
|
|
|
if (v->field_mode) |
|
|
|
|
|
|
|
mv_f[k] = v->mv_f[dir][s->block_index[k] + v->blocks_off]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* calculate chroma MV vector from four luma MVs */ |
|
|
|
/* calculate chroma MV vector from four luma MVs */ |
|
|
|
if (!v->field_mode || (v->field_mode && !v->numref)) { |
|
|
|
if (!v->field_mode || !v->numref) { |
|
|
|
valid_count = get_chroma_mv(mvx, mvy, intra, 0, &tx, &ty); |
|
|
|
int valid_count = get_chroma_mv(v, dir, &tx, &ty); |
|
|
|
chroma_ref_type = v->ref_field_type[dir]; |
|
|
|
|
|
|
|
if (!valid_count) { |
|
|
|
if (!valid_count) { |
|
|
|
s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; |
|
|
|
s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; |
|
|
|
s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; |
|
|
|
s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; |
|
|
|
v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; |
|
|
|
v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; |
|
|
|
return; //no need to do MC for intra blocks
|
|
|
|
return; //no need to do MC for intra blocks
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
chroma_ref_type = v->ref_field_type[dir]; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
int dominant = 0; |
|
|
|
int opp_count = get_luma_mv(v, dir, &tx, &ty); |
|
|
|
if (mv_f[0] + mv_f[1] + mv_f[2] + mv_f[3] > 2) |
|
|
|
chroma_ref_type = v->cur_field_type ^ (opp_count > 2); |
|
|
|
dominant = 1; |
|
|
|
|
|
|
|
valid_count = get_chroma_mv(mvx, mvy, mv_f, dominant, &tx, &ty); |
|
|
|
|
|
|
|
if (dominant) |
|
|
|
|
|
|
|
chroma_ref_type = !v->cur_field_type; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f->data[0]) |
|
|
|
if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f->data[0]) |
|
|
|
return; |
|
|
|
return; |
|
|
|