]> granicus.if.org Git - libvpx/commitdiff
Reference frame prediction:
authorPaul Wilkins <paulwilkins@google.com>
Tue, 31 Jan 2012 12:45:30 +0000 (12:45 +0000)
committerPaul Wilkins <paulwilkins@google.com>
Fri, 3 Feb 2012 12:44:45 +0000 (12:44 +0000)
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

vp8/common/pred_common.c
vp8/common/pred_common.h
vp8/common/seg_common.h
vp8/decoder/decodemv.c
vp8/encoder/bitstream.c
vp8/encoder/encodeframe.c
vp8/encoder/mbgraph.c
vp8/encoder/onyx_if.c
vp8/encoder/segmentation.c

index 1d1d107ea457f7d80afa540db6bd934764e2b8ae..e4cd037e860f735c901ced106386e92d0c3de5e1 100644 (file)
@@ -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,12 +157,19 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
 
     unsigned char left_pred;
     unsigned char above_pred;
+    unsigned char frame_allowed[MAX_REF_FRAMES];
 
     MV_REFERENCE_FRAME left;
     MV_REFERENCE_FRAME above;
     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 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
     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 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
         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,17 +228,44 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
     {
         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 ( frame_allowed[ALTREF_FRAME] &&
+                  ((left == ALTREF_FRAME) || (above == ALTREF_FRAME)) )
+        {
+            pred_ref = ALTREF_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 ( (left == ALTREF_FRAME) || (above == ALTREF_FRAME) )
+        else if ( frame_allowed[ALTREF_FRAME] )
             pred_ref = ALTREF_FRAME;
-        else if ( (left == GOLDEN_FRAME) || (above == GOLDEN_FRAME) )
+        else if ( frame_allowed[GOLDEN_FRAME] )
             pred_ref = GOLDEN_FRAME;
+        else
+            pred_ref = INTRA_FRAME;
     }
 
     return pred_ref;
@@ -246,6 +306,10 @@ void calc_ref_probs( int * count, vp8_prob * probs )
 
 }
 
+// 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 @@ void compute_mod_refprobs( VP8_COMMON *const cm )
     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 @@ void compute_mod_refprobs( VP8_COMMON *const cm )
     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
index 60476f9c5d4d43c125e6766104a18e4d9c25bb23..9463937dbe95df4b30f0b140fe75a6b689cc8770 100644 (file)
@@ -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
index 1f4e38dadeee39e6e2929070fc399e5d7454d49d..f3f2d9f1983ed4b74f7ad2ffc1b40c28fe23d97d 100644 (file)
@@ -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
index 1dee3beea1326549c5be74c49be792cdf3979b9f..432b339b18e54f2f952480062cc68dbc8f3ed502 100644 (file)
@@ -236,6 +236,7 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
 {
     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 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
                                         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,7 +292,23 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
         // 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 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
                         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 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
         // 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 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
                 }
             }
         }
+#endif
     }
 
     return (MV_REFERENCE_FRAME)ref_frame;
index 2aee8249d51558f8d577b2e293933ae43ea816a7..26f1cb4877a34f5762f66069f9c87f8ecb0b3909 100644 (file)
@@ -843,13 +843,27 @@ static void encode_ref_frame( vp8_writer *const w,
                               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,7 +883,24 @@ static void encode_ref_frame( vp8_writer *const w,
             // 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] )
             {
@@ -915,7 +946,12 @@ static void encode_ref_frame( vp8_writer *const w,
         }
 #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 @@ static void encode_ref_frame( vp8_writer *const w,
             }
         }
     }
+#endif
 }
 
 #if CONFIG_SUPERBLOCKS
index a0a0245925b3ed57b717aecaa9175610e812ba9b..30352d7190452b257d9177a078d515a18bc588f5 100644 (file)
@@ -1979,11 +1979,8 @@ int vp8cx_encode_inter_macroblock
     // 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
 
index 18c30a4177b13d54c50251f38f9997d0e9b1c7d1..e0fed4a4741ff52f65d270c36839ae358d860bcc 100644 (file)
@@ -91,7 +91,8 @@ static unsigned int do_16x16_motion_iteration
 
     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 @@ static int do_16x16_motion_search
     // 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 @@ static int do_16x16_zerozero_search
     // 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 @@ static int find_best_16x16_intra
 
         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);
index b3b0790ff1d94ef9b7dbaea524622eba7b941092..2ea41ab355d022f7f1bd85f90ec098acfc968d75 100644 (file)
@@ -474,7 +474,7 @@ static void init_seg_features(VP8_COMP *cpi)
     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 @@ static void init_seg_features(VP8_COMP *cpi)
                 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 @@ static void init_seg_features(VP8_COMP *cpi)
 
         // 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);
index 91dffe166c32dbf864769f1aa699fa7afb857034..4a1ce649c78463f325da0ffd09e8ce3dc4e2d55e 100644 (file)
@@ -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