summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/avcodec.h7
-rw-r--r--libavcodec/motion_est.c66
-rw-r--r--libavcodec/utils.c1
3 files changed, 71 insertions, 3 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index fd66eb3735..e09351f94b 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1862,6 +1862,13 @@ typedef struct AVCodecContext {
* - decoding: set by user.
*/
enum AVDiscard skip_frame;
+
+ /**
+ *
+ * - encoding: set by user.
+ * - decoding: unused
+ */
+ int bidir_refine;
} AVCodecContext;
/**
diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c
index b01c386c99..b645ffef03 100644
--- a/libavcodec/motion_est.c
+++ b/libavcodec/motion_est.c
@@ -1617,6 +1617,7 @@ static inline int check_bidir_mv(MpegEncContext * s,
/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
{
+ MotionEstContext * const c= &s->me;
const int mot_stride = s->mb_stride;
const int xy = mb_y *mot_stride + mb_x;
int fbmin;
@@ -1628,8 +1629,13 @@ static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
-
- //FIXME do refinement and add flag
+ const int flags= c->sub_flags;
+ const int qpel= flags&FLAG_QPEL;
+ const int shift= 1+qpel;
+ const int xmin= c->xmin<<shift;
+ const int ymin= c->ymin<<shift;
+ const int xmax= c->xmax<<shift;
+ const int ymax= c->ymax<<shift;
fbmin= check_bidir_mv(s, motion_fx, motion_fy,
motion_bx, motion_by,
@@ -1637,7 +1643,61 @@ static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
pred_bx, pred_by,
0, 16);
- return fbmin;
+ if(s->avctx->bidir_refine){
+ int score, end;
+#define CHECK_BIDIR(fx,fy,bx,by)\
+ score= check_bidir_mv(s, motion_fx+fx, motion_fy+fy, motion_bx+bx, motion_by+by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);\
+ if(score < fbmin){\
+ fbmin= score;\
+ motion_fx+=fx;\
+ motion_fy+=fy;\
+ motion_bx+=bx;\
+ motion_by+=by;\
+ end=0;\
+ }
+#define CHECK_BIDIR2(a,b,c,d)\
+CHECK_BIDIR(a,b,c,d)\
+CHECK_BIDIR(-a,-b,-c,-d)
+
+#define CHECK_BIDIRR(a,b,c,d)\
+CHECK_BIDIR2(a,b,c,d)\
+CHECK_BIDIR2(b,c,d,a)\
+CHECK_BIDIR2(c,d,a,b)\
+CHECK_BIDIR2(d,a,b,c)
+
+ do{
+ end=1;
+
+ if( motion_fx >= xmax || motion_bx >= xmax || motion_fx <= xmin || motion_bx <= xmin
+ || motion_fy >= ymax || motion_by >= ymax || motion_fy <= ymin || motion_by <= ymin)
+ break;
+
+ CHECK_BIDIRR( 0, 0, 0, 1)
+ if(s->avctx->bidir_refine > 1){
+ CHECK_BIDIRR( 0, 0, 1, 1)
+ CHECK_BIDIR2( 0, 1, 0, 1)
+ CHECK_BIDIR2( 1, 0, 1, 0)
+ CHECK_BIDIRR( 0, 0,-1, 1)
+ CHECK_BIDIR2( 0,-1, 0, 1)
+ CHECK_BIDIR2(-1, 0, 1, 0)
+ if(s->avctx->bidir_refine > 2){
+ CHECK_BIDIRR( 0, 1, 1, 1)
+ CHECK_BIDIRR( 0,-1, 1, 1)
+ CHECK_BIDIRR( 0, 1,-1, 1)
+ CHECK_BIDIRR( 0, 1, 1,-1)
+ if(s->avctx->bidir_refine > 3){
+ CHECK_BIDIR2( 1, 1, 1, 1)
+ CHECK_BIDIRR( 1, 1, 1,-1)
+ CHECK_BIDIR2( 1, 1,-1,-1)
+ CHECK_BIDIR2( 1,-1,-1, 1)
+ CHECK_BIDIR2( 1,-1, 1,-1)
+ }
+ }
+ }
+ }while(!end);
+ }
+
+ return fbmin;
}
static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y)
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index fa4ed68399..0c51d961d0 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -707,6 +707,7 @@ static AVOption options[]={
{"mb_lmin", NULL, OFFSET(mb_lmin), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
{"mb_lmax", NULL, OFFSET(mb_lmax), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
{"me_penalty_compensation", NULL, OFFSET(me_penalty_compensation), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E},
+{"bidir_refine", NULL, OFFSET(bidir_refine), FF_OPT_TYPE_INT, DEFAULT, 0, 4, V|E},
{NULL},
};