]> granicus.if.org Git - libvpx/commitdiff
Add biasing to ZEROMV for videos with static background
authorYunqing Wang <yunqingwang@google.com>
Tue, 21 Aug 2012 17:52:35 +0000 (10:52 -0700)
committerYunqing Wang <yunqingwang@google.com>
Tue, 21 Aug 2012 21:56:02 +0000 (14:56 -0700)
For videos with big static background(such as video conferencing
clips), the mode decision was biased to ZEROMV in order to
obtain a stable background. The percentage of ZEROMV on last
frame was used to predict if there is static area in current frame,
and checking already-encoded neighboring macroblocks' motion
vectors to make sure the local area has low motion.

Change-Id: I05b3241d3a56a0bda88b6681e5646c1c8baf2e57

vp8/encoder/onyx_if.c
vp8/encoder/onyx_int.h
vp8/encoder/pickinter.c

index dc6080340cf57dece24804ed7308ff8f32bfccbe..c371cdf582eb5f4e49074a150db68471be8f0ac0 100644 (file)
@@ -1104,6 +1104,7 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi)
 
     /* Data used for real time vc mode to see if gf needs refreshing */
     cpi->inter_zz_count = 0;
+    cpi->zeromv_count = 0;
     cpi->gf_bad_count = 0;
     cpi->gf_update_recommended = 0;
 
@@ -4306,6 +4307,7 @@ static void encode_frame_to_data_rate
         MODE_INFO *tmp = cm->mi;
 
         cpi->inter_zz_count = 0;
+        cpi->zeromv_count = 0;
 
         if(cm->frame_type != KEY_FRAME)
         {
@@ -4315,6 +4317,8 @@ static void encode_frame_to_data_rate
                 {
                     if(tmp->mbmi.mode == ZEROMV && tmp->mbmi.ref_frame == LAST_FRAME)
                         cpi->inter_zz_count++;
+                    if(tmp->mbmi.mode == ZEROMV)
+                        cpi->zeromv_count++;
                     tmp++;
                 }
                 tmp++;
@@ -5116,6 +5120,8 @@ int vp8_get_compressed_data(VP8_COMP *cpi, unsigned int *frame_flags, unsigned l
         vpx_usec_timer_start(&ticktimer);
     }
 
+    cpi->lf_zeromv_pct = (cpi->zeromv_count * 100)/cm->MBs;
+
 #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
     {
         int i;
index caccc60ae83965a3e359477643b79d651f8bdee6..3f1fad60be6cde5776f874b62298899253d3c600 100644 (file)
@@ -515,6 +515,9 @@ typedef struct VP8_COMP
      * would be good to update the gf
      */
     int inter_zz_count;
+    /* Count ZEROMV on all reference frames. */
+    int zeromv_count;
+    int lf_zeromv_pct;
     int gf_bad_count;
     int gf_update_recommended;
     int skip_true_count;
index b67f04b8590a8b3ec2535a12546d9dc1104eaa94..3cad8bfd9a277cbc4d26605ddb18252c24a7c44d 100644 (file)
@@ -480,7 +480,8 @@ static void check_for_encode_breakout(unsigned int sse, MACROBLOCK* x)
     }
 }
 
-static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, VP8_COMP *cpi, MACROBLOCK *x)
+static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2,
+                               VP8_COMP *cpi, MACROBLOCK *x, int rd_adj)
 {
     MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
     int_mv mv = x->e_mbd.mode_info_context->mbmi.mv;
@@ -503,10 +504,63 @@ static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, V
 
     this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2);
 
+    /* Adjust rd to bias to ZEROMV */
+    if(this_mode == ZEROMV)
+    {
+        /* Bias to ZEROMV on LAST_FRAME reference when it is available. */
+        if ((cpi->ref_frame_flags & VP8_LAST_FRAME &
+            cpi->common.refresh_last_frame)
+            && x->e_mbd.mode_info_context->mbmi.ref_frame != LAST_FRAME)
+            rd_adj = 100;
+
+        this_rd = this_rd * rd_adj/100;
+    }
+
     check_for_encode_breakout(*sse, x);
     return this_rd;
 }
 
+static void calculate_zeromv_rd_adjustment(VP8_COMP *cpi, MACROBLOCK *x,
+                                    int *rd_adjustment)
+{
+    MODE_INFO *mic = x->e_mbd.mode_info_context;
+    int_mv mv_l, mv_a, mv_al;
+    int local_motion_check = 0;
+
+    if (cpi->lf_zeromv_pct > 40)
+    {
+        /* left mb */
+        mic -= 1;
+        mv_l = mic->mbmi.mv;
+
+        if (mic->mbmi.ref_frame != INTRA_FRAME)
+            if( abs(mv_l.as_mv.row) < 8 && abs(mv_l.as_mv.col) < 8)
+                local_motion_check++;
+
+        /* above-left mb */
+        mic -= x->e_mbd.mode_info_stride;
+        mv_al = mic->mbmi.mv;
+
+        if (mic->mbmi.ref_frame != INTRA_FRAME)
+            if( abs(mv_al.as_mv.row) < 8 && abs(mv_al.as_mv.col) < 8)
+                local_motion_check++;
+
+        /* above mb */
+        mic += 1;
+        mv_a = mic->mbmi.mv;
+
+        if (mic->mbmi.ref_frame != INTRA_FRAME)
+            if( abs(mv_a.as_mv.row) < 8 && abs(mv_a.as_mv.col) < 8)
+                local_motion_check++;
+
+        if (((!x->e_mbd.mb_to_top_edge || !x->e_mbd.mb_to_left_edge)
+            && local_motion_check >0) ||  local_motion_check >2 )
+            *rd_adjustment = 80;
+        else if (local_motion_check > 0)
+            *rd_adjustment = 90;
+    }
+}
+
 void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
                          int recon_uvoffset, int *returnrate,
                          int *returndistortion, int *returnintra, int mb_row,
@@ -525,6 +579,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
     int num00;
     int mdcounts[4];
     int best_rd = INT_MAX;
+    int rd_adjustment = 100;
     int best_intra_rd = INT_MAX;
     int mode_index;
     int rate;
@@ -594,6 +649,11 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
 
     x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
 
+    /* If the frame has big static background and current MB is in low
+     * motion area, its mode decision is biased to ZEROMV mode.
+     */
+    calculate_zeromv_rd_adjustment(cpi, x, &rd_adjustment);
+
     /* if we encode a new mv this is important
      * find the best new motion vector
      */
@@ -981,7 +1041,8 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
             rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
             x->e_mbd.mode_info_context->mbmi.mv.as_int =
                                                     mode_mv[this_mode].as_int;
-            this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
+            this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x,
+                                          rd_adjustment);
 
             break;
         default:
@@ -1119,7 +1180,8 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
             x->e_mbd.mode_info_context->mbmi.mode = ZEROMV;
             x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
             x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
-            this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
+            this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x,
+                                          rd_adjustment);
 
             if (this_rd < best_rd)
             {