[FFmpeg-cvslog] avcodec/vc1_mc: optimize get_chroma_mv, and add get_luma_mv
zhaoxiu.zeng
git at videolan.org
Sun Mar 8 03:52:18 CET 2015
ffmpeg | branch: master | zhaoxiu.zeng <zhaoxiu.zeng at gmail.com> | Sat Mar 7 23:17:53 2015 +0800| [9d7e42e65cfd8c521b1473b3ce1a11d73b6f56fb] | committer: Michael Niedermayer
avcodec/vc1_mc: optimize get_chroma_mv, and add get_luma_mv
Test results:
before:
fate-suite/vc1/SA10091.vc1: 1062 decicycles in ff_vc1_mc_4mv_chroma's get mv, 4089 runs, 7 skips
fate-suite/vc1/SA10143.vc1: 1112 decicycles in ff_vc1_mc_4mv_luma's get mv, 4096 runs, 0 skips
fate-suite/vc1/SA20021.vc1: 991 decicycles in ff_vc1_mc_4mv_chroma get mv, 8192 runs, 0 skips
after:
fate-suite/vc1/SA10091.vc1: 940 decicycles in ff_vc1_mc_4mv_chroma's get mv, 4096 runs, 0 skips
fate-suite/vc1/SA10143.vc1: 786 decicycles in ff_vc1_mc_4mv_luma's get mv, 4096 runs, 0 skips
fate-suite/vc1/SA20021.vc1: 876 decicycles in ff_vc1_mc_4mv_chroma get mv, 8189 runs, 3 skips
Signed-off-by: Zeng Zhaoxiu <zhaoxiu.zeng at gmail.com>
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=9d7e42e65cfd8c521b1473b3ce1a11d73b6f56fb
---
libavcodec/vc1_mc.c | 179 +++++++++++++++++++++------------------------------
1 file changed, 74 insertions(+), 105 deletions(-)
diff --git a/libavcodec/vc1_mc.c b/libavcodec/vc1_mc.c
index 88473ea..569aad0 100644
--- a/libavcodec/vc1_mc.c
+++ b/libavcodec/vc1_mc.c
@@ -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
* 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) {
- int same_count = 0, opp_count = 0, k;
- int chosen_mv[2][4][2], f;
- int tx, ty;
- for (k = 0; k < 4; k++) {
- 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;
+ int opp_count = get_luma_mv(v, 0,
+ &s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][0],
+ &s->current_picture.motion_val[1][s->block_index[0] + v->blocks_off][1]);
+ int k, f = opp_count > 2;
for (k = 0; k < 4; k++)
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
*/
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;
uint8_t *srcU, *srcV;
int uvmx, uvmy, uvsrc_x, uvsrc_y;
- int k, tx = 0, ty = 0;
- int mvx[4], mvy[4], intra[4], mv_f[4];
- int valid_count;
- int chroma_ref_type = v->cur_field_type;
+ int16_t tx, ty;
+ int chroma_ref_type;
int v_edge_pos = s->v_edge_pos >> v->field_mode;
uint8_t (*lutuv)[256];
int use_ic;
@@ -539,31 +520,19 @@ void ff_vc1_mc_4mv_chroma(VC1Context *v, int dir)
if (s->flags & CODEC_FLAG_GRAY)
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 */
- if (!v->field_mode || (v->field_mode && !v->numref)) {
- valid_count = get_chroma_mv(mvx, mvy, intra, 0, &tx, &ty);
- chroma_ref_type = v->ref_field_type[dir];
+ if (!v->field_mode || !v->numref) {
+ int valid_count = get_chroma_mv(v, dir, &tx, &ty);
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][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
}
+ chroma_ref_type = v->ref_field_type[dir];
} else {
- int dominant = 0;
- if (mv_f[0] + mv_f[1] + mv_f[2] + mv_f[3] > 2)
- dominant = 1;
- valid_count = get_chroma_mv(mvx, mvy, mv_f, dominant, &tx, &ty);
- if (dominant)
- chroma_ref_type = !v->cur_field_type;
+ int opp_count = get_luma_mv(v, dir, &tx, &ty);
+ chroma_ref_type = v->cur_field_type ^ (opp_count > 2);
}
if (v->field_mode && chroma_ref_type == 1 && v->cur_field_type == 1 && !v->s.last_picture.f->data[0])
return;
More information about the ffmpeg-cvslog
mailing list