shithub: libvpx

Download patch

ref: f0459549a60b1df09220f2abf6afefabb81b40a3
parent: 5d0b5a17d9a73b3f4588ae95fbd4b18e7af79f35
author: Paul Wilkins <paulwilkins@google.com>
date: Tue Jan 31 07:45:30 EST 2012

Reference frame prediction:

Extended prediction and coding of reference frame where
a subset of options are flagged as available at the segment level.

Updated copyright notices.

Switch to SAD in mbgraph code as SATD problematic for the
foreground and background separation as it can ignore large DC shifts.

Change-Id: I661dbbb2f94f3ec0f96bb928c1655e5e415a7de1

--- a/vp8/common/pred_common.c
+++ b/vp8/common/pred_common.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
@@ -157,6 +157,7 @@
 
     unsigned char left_pred;
     unsigned char above_pred;
+    unsigned char frame_allowed[MAX_REF_FRAMES];
 
     MV_REFERENCE_FRAME left;
     MV_REFERENCE_FRAME above;
@@ -163,6 +164,12 @@
     MV_REFERENCE_FRAME above_left;
     MV_REFERENCE_FRAME pred_ref = LAST_FRAME;
 
+    int segment_id = xd->mode_info_context->mbmi.segment_id;
+    int seg_ref_active;
+
+    // Is segment coding ennabled
+    seg_ref_active = segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME );
+
     // Reference frame used by neighbours
     left = (m - 1)->mbmi.ref_frame;
     above = (m - cm->mode_info_stride)->mbmi.ref_frame;
@@ -173,6 +180,32 @@
     left_pred = (m - 1)->mbmi.ref_predicted;
     above_pred = (m - cm->mode_info_stride)->mbmi.ref_predicted;
 
+    // Special case treatment if segment coding is enabled.
+    // Dont allow prediction of a reference frame that the segment
+    // does not allow
+    if ( seg_ref_active )
+    {
+        frame_allowed[INTRA_FRAME] =
+            check_segref( xd, segment_id, INTRA_FRAME );
+        frame_allowed[LAST_FRAME] =
+            check_segref( xd, segment_id, LAST_FRAME );
+        frame_allowed[GOLDEN_FRAME] =
+            check_segref( xd, segment_id, GOLDEN_FRAME );
+        frame_allowed[ALTREF_FRAME] =
+            check_segref( xd, segment_id, ALTREF_FRAME );
+    }
+    else
+    {
+        frame_allowed[INTRA_FRAME] = 1;
+        frame_allowed[LAST_FRAME] = 1;
+        frame_allowed[GOLDEN_FRAME] = 1;
+        frame_allowed[ALTREF_FRAME] = 1;
+    }
+
+    // Dont predict if not allowed
+    left_pred = left_pred * frame_allowed[left];
+    above_pred = above_pred * frame_allowed[above];
+
     // Boost prediction scores of above / left if they are predicted and match
     // the above left.
     if ( left_pred )
@@ -181,7 +214,7 @@
         above_pred += (above == above_left);
 
     // Only consider "in image" mbs as giving valid prediction.
-    if ( (left == above) &&
+    if ( (left == above) && frame_allowed[left] &&
          ((m - 1)->mbmi.mb_in_image ||
           (m - cm->mode_info_stride)->mbmi.mb_in_image) )
     {
@@ -195,18 +228,45 @@
     {
         pred_ref = above;
     }
-    else
+    // If we reach this clause left_pred and above_pred must be the same
+    else if ( left_pred > 0 )
     {
         // Choose from above or left.
         // For now this is based on a fixed preference order.
         // Last,Altref,Golden
-        if ( (left == LAST_FRAME) || (above == LAST_FRAME) )
+        if ( frame_allowed[LAST_FRAME] &&
+             ((left == LAST_FRAME) || (above == LAST_FRAME)) )
+        {
             pred_ref = LAST_FRAME;
-        else if ( (left == ALTREF_FRAME) || (above == ALTREF_FRAME) )
+        }
+        else if ( frame_allowed[ALTREF_FRAME] &&
+                  ((left == ALTREF_FRAME) || (above == ALTREF_FRAME)) )
+        {
             pred_ref = ALTREF_FRAME;
-        else if ( (left == GOLDEN_FRAME) || (above == GOLDEN_FRAME) )
+        }
+        else if ( frame_allowed[GOLDEN_FRAME] &&
+                  ((left == GOLDEN_FRAME) || (above == GOLDEN_FRAME)) )
+        {
             pred_ref = GOLDEN_FRAME;
+        }
+        else
+        {
+            pred_ref = INTRA_FRAME;
+        }
     }
+    // No prediction case.. choose in fixed order from allowed options
+    // TBD could order based onf frequency.
+    else
+    {
+        if ( frame_allowed[LAST_FRAME] )
+            pred_ref = LAST_FRAME;
+        else if ( frame_allowed[ALTREF_FRAME] )
+            pred_ref = ALTREF_FRAME;
+        else if ( frame_allowed[GOLDEN_FRAME] )
+            pred_ref = GOLDEN_FRAME;
+        else
+            pred_ref = INTRA_FRAME;
+    }
 
     return pred_ref;
 }
@@ -246,6 +306,10 @@
 
 }
 
+// Computes a set of modified conditional probabilities for the reference frame
+// Values willbe set to 0 for reference frame options that are not possible
+// because wither they were predicted and prediction has failed or because
+// they are not allowed for a given segment.
 void compute_mod_refprobs( VP8_COMMON *const cm )
 {
     int norm_cnt[MAX_REF_FRAMES];
@@ -255,6 +319,7 @@
     int gfarf_count;
     int gf_count;
     int arf_count;
+    int i;
 
     intra_count = cm->prob_intra_coded;
     inter_count = (255 - intra_count);
@@ -292,6 +357,5 @@
     norm_cnt[3] = 0;
     calc_ref_probs( norm_cnt, cm->mod_refprobs[ALTREF_FRAME] );
     cm->mod_refprobs[ALTREF_FRAME][2] = 0;  // This branch implicit
-
 }
 #endif
--- a/vp8/common/pred_common.h
+++ b/vp8/common/pred_common.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
--- a/vp8/common/seg_common.h
+++ b/vp8/common/seg_common.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -236,6 +236,7 @@
 {
     MV_REFERENCE_FRAME ref_frame;
     int seg_ref_active;
+    int seg_ref_count = 0;
 
 //#if CONFIG_SEGFEATURES
     VP8_COMMON *const cm = & pbi->common;
@@ -245,8 +246,25 @@
                                         segment_id,
                                         SEG_LVL_REF_FRAME );
 
-    // Segment reference frame features not available
+
+#if CONFIG_COMPRED
+
+    // If segment coding enabled does the segment allow for more than one
+    // possible reference frame
+    if ( seg_ref_active )
+    {
+        seg_ref_count = check_segref( xd, segment_id, INTRA_FRAME ) +
+                        check_segref( xd, segment_id, LAST_FRAME ) +
+                        check_segref( xd, segment_id, GOLDEN_FRAME ) +
+                        check_segref( xd, segment_id, ALTREF_FRAME );
+    }
+
+    // Segment reference frame features not available or allows for
+    // multiple reference frame options
+    if ( !seg_ref_active || (seg_ref_count > 1) )
+#else
     if ( !seg_ref_active )
+#endif
     {
 #if CONFIG_COMPRED
         // Values used in prediction model coding
@@ -274,8 +292,24 @@
         // else decode the explicitly coded value
         else
         {
-            vp8_prob * mod_refprobs = cm->mod_refprobs[pred_ref];
+            //vp8_prob * mod_refprobs = cm->mod_refprobs[pred_ref];
+            vp8_prob mod_refprobs[PREDICTION_PROBS];
+            vpx_memcpy( mod_refprobs,
+                        cm->mod_refprobs[pred_ref], sizeof(mod_refprobs) );
 
+            // If segment coding enabled blank out options that cant occur by
+            // setting the branch probability to 0.
+            if ( seg_ref_active )
+            {
+                mod_refprobs[INTRA_FRAME] *=
+                    check_segref( xd, segment_id, INTRA_FRAME );
+                mod_refprobs[LAST_FRAME] *=
+                    check_segref( xd, segment_id, LAST_FRAME );
+                mod_refprobs[GOLDEN_FRAME] *=
+                    ( check_segref( xd, segment_id, GOLDEN_FRAME ) *
+                      check_segref( xd, segment_id, ALTREF_FRAME ) );
+            }
+
             // Default to INTRA_FRAME (value 0)
             ref_frame = INTRA_FRAME;
 
@@ -300,8 +334,19 @@
                         ref_frame += vp8_read(bc, mod_refprobs[2]);
                     else
                     {
-                        ref_frame = (pred_ref == GOLDEN_FRAME)
-                                    ? ALTREF_FRAME : GOLDEN_FRAME;
+                        if ( seg_ref_active )
+                        {
+                            if ( (pred_ref == GOLDEN_FRAME) ||
+                                 !check_segref( xd, segment_id, GOLDEN_FRAME) )
+                            {
+                                ref_frame = ALTREF_FRAME;
+                            }
+                            else
+                                ref_frame = GOLDEN_FRAME;
+                        }
+                        else
+                            ref_frame = (pred_ref == GOLDEN_FRAME)
+                                        ? ALTREF_FRAME : GOLDEN_FRAME;
                     }
                 }
             }
@@ -330,8 +375,8 @@
         // if it is signaled at the segment level for the purposes of the
         // common prediction model
         set_pred_flag( xd, PRED_REF, 1 );
-#endif
-
+        ref_frame = get_pred_ref( cm, xd );
+#else
         // If there are no inter reference frames enabled we can set INTRA
         if ( !check_segref_inter(xd, segment_id) )
         {
@@ -401,6 +446,7 @@
                 }
             }
         }
+#endif
     }
 
     return (MV_REFERENCE_FRAME)ref_frame;
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -843,13 +843,27 @@
                               MV_REFERENCE_FRAME rf )
 {
     int seg_ref_active;
+    int seg_ref_count = 0;
 //#if CONFIG_SEGFEATURES
     seg_ref_active = segfeature_active( xd,
                                         segment_id,
                                         SEG_LVL_REF_FRAME );
 
+#if CONFIG_COMPRED
+    if ( seg_ref_active )
+    {
+        seg_ref_count = check_segref( xd, segment_id, INTRA_FRAME ) +
+                        check_segref( xd, segment_id, LAST_FRAME ) +
+                        check_segref( xd, segment_id, GOLDEN_FRAME ) +
+                        check_segref( xd, segment_id, ALTREF_FRAME );
+    }
+
     // If segment level coding of this signal is disabled...
-    if ( !seg_ref_active )
+    // or the segment allows multiple reference frame options
+    if ( !seg_ref_active || (seg_ref_count > 1) )
+#else
+    if ( !seg_ref_active  )
+#endif
     {
 #if CONFIG_COMPRED
         // Values used in prediction model coding
@@ -869,8 +883,25 @@
             // Get the predicted value so that it can be excluded.
             MV_REFERENCE_FRAME pred_rf = get_pred_ref( cm, xd );
 
-            vp8_prob * mod_refprobs = cm->mod_refprobs[pred_rf];
+            //vp8_prob * mod_refprobs = cm->mod_refprobs[pred_rf];
+            vp8_prob mod_refprobs[PREDICTION_PROBS];
 
+            vpx_memcpy( mod_refprobs,
+                        cm->mod_refprobs[pred_rf], sizeof(mod_refprobs) );
+
+            // If segment coding enabled blank out options that cant occur by
+            // setting the branch probability to 0.
+            if ( seg_ref_active )
+            {
+                mod_refprobs[INTRA_FRAME] *=
+                    check_segref( xd, segment_id, INTRA_FRAME );
+                mod_refprobs[LAST_FRAME] *=
+                    check_segref( xd, segment_id, LAST_FRAME );
+                mod_refprobs[GOLDEN_FRAME] *=
+                    ( check_segref( xd, segment_id, GOLDEN_FRAME ) *
+                      check_segref( xd, segment_id, ALTREF_FRAME ) );
+            }
+
             if ( mod_refprobs[0] )
             {
                 vp8_write(w, (rf != INTRA_FRAME), mod_refprobs[0] );
@@ -915,7 +946,12 @@
         }
 #endif
     }
+
+    // if using the prediction mdoel we have nothing further to do because
+    // the reference frame is fully coded by the segment
+
 //#if CONFIG_SEGFEATURES
+#if !CONFIG_COMPRED
     // Else use the segment
     else
     {
@@ -958,6 +994,7 @@
             }
         }
     }
+#endif
 }
 
 #if CONFIG_SUPERBLOCKS
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -1979,11 +1979,8 @@
     // SET VARIOUS PREDICTION FLAGS
 
     // Did the chosen reference frame match its predicted value.
-    // If the reference frame is predicted at the segment level we
-    // mark it as correctly predicted
     ref_pred_flag = ( (xd->mode_info_context->mbmi.ref_frame ==
-                          get_pred_ref( cm, xd )) ||
-                       seg_ref_active );
+                           get_pred_ref( cm, xd )) );
     set_pred_flag( xd, PRED_REF, ref_pred_flag );
 #endif
 
--- a/vp8/encoder/mbgraph.c
+++ b/vp8/encoder/mbgraph.c
@@ -91,7 +91,8 @@
 
     vp8_set_mbmode_and_mvs(x, NEWMV, dst_mv);
     vp8_build_inter16x16_predictors_mby(xd);
-    VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+    //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+    best_err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
                     (xd->dst.y_buffer, xd->dst.y_stride,
                      xd->predictor, 16, &best_err);
 
@@ -138,7 +139,8 @@
     // FIXME should really use something like near/nearest MV and/or MV prediction
     xd->pre.y_buffer = ref->y_buffer + mb_y_offset;
     xd->pre.y_stride = ref->y_stride;
-    VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+    //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+    err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
                     (ref->y_buffer + mb_y_offset,
                      ref->y_stride, xd->dst.y_buffer,
                      xd->dst.y_stride, &err);
@@ -203,10 +205,12 @@
     // FIXME should really use something like near/nearest MV and/or MV prediction
     xd->pre.y_buffer = ref->y_buffer + mb_y_offset;
     xd->pre.y_stride = ref->y_stride;
-    VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+    //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+    err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
                     (ref->y_buffer + mb_y_offset,
                      ref->y_stride, xd->dst.y_buffer,
                      xd->dst.y_stride, &err);
+
     dst_mv->as_int = 0;
 
     return err;
@@ -232,7 +236,8 @@
 
         xd->mode_info_context->mbmi.mode = mode;
         RECON_INVOKE(&cpi->rtcd.common->recon, build_intra_predictors_mby)(xd);
-        VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+        //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16)
+        err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16)
                         (xd->predictor, 16,
                          buf->y_buffer + mb_y_offset,
                          buf->y_stride, &err);
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -474,7 +474,7 @@
     VP8_COMMON *cm = &cpi->common;
     MACROBLOCKD *xd = &cpi->mb.e_mbd;
 
-    int high_q = (int)(cpi->avg_q > 32.0);
+    int high_q = (int)(cpi->avg_q > 48.0);
     int qi_delta;
 
     // For now at least dont enable seg features alongside cyclic refresh.
@@ -575,15 +575,10 @@
                 set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
                 enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
 
-#if CONFIG_COMPRED
                 // Segment coding disabled for compred testing
                 if ( high_q || (cpi->static_mb_pct == 100) )
-                //if ( 0 )
-#else
-                if ( high_q || (cpi->static_mb_pct == 100) )
-                //if ( 0 )
-#endif
                 {
+                    //set_segref(xd, 1, LAST_FRAME);
                     set_segref(xd, 1, ALTREF_FRAME);
                     enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
 
@@ -618,14 +613,8 @@
 
         // Special case where we are coding over the top of a previous
         // alt ref frame
-#if CONFIG_COMPRED
         // Segment coding disabled for compred testing
         else if ( cpi->is_src_frame_alt_ref )
-        //else if ( 0 )
-#else
-        else if ( cpi->is_src_frame_alt_ref )
-        //else if ( 0 )
-#endif
         {
             // Enable mode and ref frame features for segment 0 as well
             enable_segfeature(xd, 0, SEG_LVL_REF_FRAME);
--- a/vp8/encoder/segmentation.c
+++ b/vp8/encoder/segmentation.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
  *
  *  Use of this source code is governed by a BSD-style license
  *  that can be found in the LICENSE file in the root of the source