]> granicus.if.org Git - libvpx/commitdiff
Modified prediction behavior for reference frame.
authorPaul Wilkins <paulwilkins@google.com>
Fri, 3 Feb 2012 13:46:18 +0000 (13:46 +0000)
committerPaul Wilkins <paulwilkins@google.com>
Mon, 6 Feb 2012 16:34:41 +0000 (16:34 +0000)
Trial of a modified prediction function that ranks each possible
reference frame based on a combination of local usage and
frame level probability. The code is a bit cleaner and simpler.

In direct comparison with old unpredicted method with segment level
coding turned off for mode,ref & EOB the prediction gives a gain on derf
of around 0.4%. There is some further gain from bug fixes over earlier code.

With segment coding on the prediction method is slightly -ve on some very
easy clips (at low rates) due to slightly higher overheads, but better on harder
clips. Overall neutral on derf in direct comparison on latest code base, but
compared to earlier code without bug fixes about +0.7% overall psnr
+0.3% SSIM.

Change-Id: I5b8474658b208134d352d24f6517f25795490789

vp8/common/onyxc_int.h
vp8/common/pred_common.c
vp8/decoder/decodemv.c
vp8/encoder/bitstream.c
vp8/encoder/encodeframe.c
vp8/encoder/onyx_if.c
vp8/encoder/onyx_int.h

index fd6a5580150d2d8ee1f048c0eb92dbf2d84f4862..a86635a7c67e3a878e1fe8a1dcd51f079f0b6397 100644 (file)
@@ -236,6 +236,7 @@ typedef struct VP8Common
 
 #if CONFIG_COMPRED
     // Context probabilities for reference frame prediction
+    unsigned char ref_scores[MAX_REF_FRAMES];
     vp8_prob ref_pred_probs[PREDICTION_PROBS];
     vp8_prob mod_refprobs[MAX_REF_FRAMES][PREDICTION_PROBS];
 #endif
index e4cd037e860f735c901ced106386e92d0c3de5e1..bda140058485790325fcd9a7e29db00d67bc44e2 100644 (file)
@@ -155,10 +155,6 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
 {
     MODE_INFO *m = xd->mode_info_context;
 
-    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;
@@ -166,107 +162,68 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm,
 
     int segment_id = xd->mode_info_context->mbmi.segment_id;
     int seg_ref_active;
+    int i;
+
+    unsigned char frame_allowed[MAX_REF_FRAMES] = {1,1,1,1};
+    unsigned char ref_score[MAX_REF_FRAMES];
+    unsigned char best_score = 0;
+    unsigned char left_in_image;
+    unsigned char above_in_image;
+    unsigned char above_left_in_image;
 
     // 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;
-    above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame;
-
-    // Reference frame prediction status of immediate neigbours.
-    // This can only be set if the mb is "in image"
-    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 );
+        for ( i = 0; i < MAX_REF_FRAMES; i++ )
+        {
+            frame_allowed[i] =
+                check_segref( xd, segment_id, i );
+
+            // Score set to 0 if ref frame not allowed
+            ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
+        }
     }
     else
-    {
-        frame_allowed[INTRA_FRAME] = 1;
-        frame_allowed[LAST_FRAME] = 1;
-        frame_allowed[GOLDEN_FRAME] = 1;
-        frame_allowed[ALTREF_FRAME] = 1;
-    }
+        vpx_memcpy( ref_score, cm->ref_scores, sizeof(ref_score) );
 
-    // 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 )
-        left_pred += (left == above_left);
-    if ( above_pred )
-        above_pred += (above == above_left);
-
-    // Only consider "in image" mbs as giving valid prediction.
-    if ( (left == above) && frame_allowed[left] &&
-         ((m - 1)->mbmi.mb_in_image ||
-          (m - cm->mode_info_stride)->mbmi.mb_in_image) )
-    {
-        pred_ref = left;
-    }
-    else if ( left_pred > above_pred )
+    // Reference frames used by neighbours
+    left = (m - 1)->mbmi.ref_frame;
+    above = (m - cm->mode_info_stride)->mbmi.ref_frame;
+    above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame;
+
+    // Are neighbours in image
+    left_in_image = (m - 1)->mbmi.mb_in_image;
+    above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
+    above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image;
+
+    // Adjust scores for candidate reference frames based on neigbours
+    if  ( frame_allowed[left] && left_in_image )
     {
-        pred_ref = left;
+        ref_score[left] += 16;
+        if ( above_left_in_image && (left == above_left) )
+            ref_score[left] += 4;
     }
-    else if ( above_pred > left_pred )
+    if  ( frame_allowed[above] && above_in_image )
     {
-        pred_ref = above;
+        ref_score[above] += 16;
+        if ( above_left_in_image && (above == above_left) )
+            ref_score[above] += 4;
     }
-    // If we reach this clause left_pred and above_pred must be the same
-    else if ( left_pred > 0 )
+
+    // Now choose the candidate with the highest score
+    for ( i = 0; i < MAX_REF_FRAMES; i++ )
     {
-        // Choose from above or left.
-        // For now this is based on a fixed preference order.
-        // Last,Altref,Golden
-        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)) )
+        if ( ref_score[i] > best_score  )
         {
-            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;
+            pred_ref = i;
+            best_score = ref_score[i];
         }
     }
-    // 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;
 }
@@ -357,5 +314,13 @@ 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
+
+    // Score the reference frames based on overal frequency.
+    // These scores contribute to the prediction choices.
+    // Max score 17 min 1
+    cm->ref_scores[INTRA_FRAME] = 1 + (intra_count * 16 / 255);
+    cm->ref_scores[LAST_FRAME] = 1 + (last_count * 16 / 255);
+    cm->ref_scores[GOLDEN_FRAME] = 1 + (gf_count * 16 / 255);
+    cm->ref_scores[ALTREF_FRAME] = 1 + (arf_count * 16 / 255);
 }
 #endif
index 432b339b18e54f2f952480062cc68dbc8f3ed502..4238e4d18ef9187036fb6d2dc9bf67d8ea983749 100644 (file)
@@ -292,7 +292,6 @@ 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[PREDICTION_PROBS];
             vpx_memcpy( mod_refprobs,
                         cm->mod_refprobs[pred_ref], sizeof(mod_refprobs) );
index 26f1cb4877a34f5762f66069f9c87f8ecb0b3909..3c0ea4c2baeadb7b69fa908f76a25e797696fd5e 100644 (file)
@@ -869,21 +869,24 @@ static void encode_ref_frame( vp8_writer *const w,
         // Values used in prediction model coding
         unsigned char prediction_flag;
         vp8_prob pred_prob;
+        MV_REFERENCE_FRAME pred_rf;
 
         // Get the context probability the prediction flag
         pred_prob = get_pred_prob( cm, xd, PRED_REF );
 
-        // Code the prediction flag
-        prediction_flag = get_pred_flag( xd, PRED_REF );
+        // Get the predicted value.
+        pred_rf = get_pred_ref( cm, xd );
+
+        // Did the chosen reference frame match its predicted value.
+        prediction_flag =
+            ( xd->mode_info_context->mbmi.ref_frame == pred_rf );
+
+        set_pred_flag( xd, PRED_REF, prediction_flag );
         vp8_write( w, prediction_flag, pred_prob );
 
         // If not predicted correctly then code value explicitly
         if ( !prediction_flag )
         {
-            // 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[PREDICTION_PROBS];
 
             vpx_memcpy( mod_refprobs,
@@ -997,6 +1000,42 @@ static void encode_ref_frame( vp8_writer *const w,
 #endif
 }
 
+// Update the probabilities used to encode reference frame data
+static void update_ref_probs( VP8_COMP *const cpi )
+{
+    VP8_COMMON *const cm = & cpi->common;
+
+    const int *const rfct = cpi->count_mb_ref_frame_usage;
+    const int rf_intra = rfct[INTRA_FRAME];
+    const int rf_inter = rfct[LAST_FRAME] +
+                         rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
+
+//#if CONFIG_SEGFEATURES
+    cm->prob_intra_coded = (rf_intra + rf_inter)
+                            ? rf_intra * 255 / (rf_intra + rf_inter) : 1;
+
+    if (!cm->prob_intra_coded)
+        cm->prob_intra_coded = 1;
+
+    cm->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
+
+    if (!cm->prob_last_coded)
+        cm->prob_last_coded = 1;
+
+    cm->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
+                        ? (rfct[GOLDEN_FRAME] * 255) /
+                          (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
+
+    if (!cm->prob_gf_coded)
+       cm->prob_gf_coded = 1;
+
+#if CONFIG_COMPRED
+    // Compute a modified set of probabilities to use when prediction of the
+    // reference frame fails
+    compute_mod_refprobs( cm );
+#endif
+}
+
 #if CONFIG_SUPERBLOCKS
 static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 {
@@ -1010,9 +1049,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 #endif
     int pred_context;
 
-    const int *const rfct = cpi->count_mb_ref_frame_usage;
-    const int rf_intra = rfct[INTRA_FRAME];
-    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
     MODE_INFO *m = pc->mi;
 #if CONFIG_NEWNEAR
     MODE_INFO *prev_m = pc->prev_mi;
@@ -1036,31 +1072,8 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 
     cpi->mb.partition_info = cpi->mb.pi;
 
-    // Calculate the probabilities to be used to code the reference frame
-    // based on actual useage this frame
-//#if CONFIG_SEGFEATURES
-    pc->prob_intra_coded = (rf_intra + rf_inter)
-                            ? rf_intra * 255 / (rf_intra + rf_inter) : 1;
-
-    if (!pc->prob_intra_coded)
-        pc->prob_intra_coded = 1;
-
-    pc->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
-
-    if (!pc->prob_last_coded)
-        pc->prob_last_coded = 1;
-
-    pc->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
-                    ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
-
-    if (!pc->prob_gf_coded)
-        pc->prob_gf_coded = 1;
-
-#if CONFIG_COMPRED
-    // Compute a modified set of probabilities to use when prediction of the
-    // reference frame fails
-    compute_mod_refprobs( pc );
-#endif
+    // Update the probabilities used to encode reference frame data
+    update_ref_probs( cpi );
 
 #ifdef ENTROPY_STATS
     active_section = 1;
@@ -1425,9 +1438,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 #endif
     int pred_context;
 
-    const int *const rfct = cpi->count_mb_ref_frame_usage;
-    const int rf_intra = rfct[INTRA_FRAME];
-    const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
 
     MODE_INFO *m = pc->mi;
 #if CONFIG_NEWNEAR
@@ -1448,31 +1458,8 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
 
     cpi->mb.partition_info = cpi->mb.pi;
 
-    // Calculate the probabilities to be used to code the reference frame
-    // based on actual useage this frame
-//#if CONFIG_SEGFEATURES
-    pc->prob_intra_coded = (rf_intra + rf_inter)
-                            ? rf_intra * 255 / (rf_intra + rf_inter) : 1;
-
-    if (!pc->prob_intra_coded)
-        pc->prob_intra_coded = 1;
-
-    pc->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
-
-    if (!pc->prob_last_coded)
-        pc->prob_last_coded = 1;
-
-   pc->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
-                    ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
-
-    if (!pc->prob_gf_coded)
-       pc->prob_gf_coded = 1;
-
-#if CONFIG_COMPRED
-    // Compute a modified set of probabilities to use when prediction of the
-    // reference frame fails
-    compute_mod_refprobs( pc );
-#endif
+    // Update the probabilities used to encode reference frame data
+    update_ref_probs( cpi );
 
 #ifdef ENTROPY_STATS
     active_section = 1;
@@ -2825,7 +2812,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
     {
         for (i = 0; i < PREDICTION_PROBS; i++)
         {
-            if ( cpi->ref_probs_update[i] )
+            if ( cpi->ref_pred_probs_update[i] )
             {
                 vp8_write_bit(bc, 1);
                 vp8_write_literal(bc, pc->ref_pred_probs[i], 8);
index 30352d7190452b257d9177a078d515a18bc588f5..2e5bd20c8fdc6ed69ed455bf070cfecad82f91f1 100644 (file)
@@ -1982,6 +1982,7 @@ int vp8cx_encode_inter_macroblock
     ref_pred_flag = ( (xd->mode_info_context->mbmi.ref_frame ==
                            get_pred_ref( cm, xd )) );
     set_pred_flag( xd, PRED_REF, ref_pred_flag );
+
 #endif
 
     // If we have just a single reference frame coded for a segment then
index 2ea41ab355d022f7f1bd85f90ec098acfc968d75..e3656e2d8021947cc32bacfa25cfde23ff98d85a 100644 (file)
@@ -3418,6 +3418,7 @@ static void update_golden_frame_stats(VP8_COMP *cpi)
 }
 
 #if !CONFIG_COMPRED
+//#if 1
 // This function updates the reference frame probability estimates that
 // will be used during mode selection
 static void update_rd_ref_frame_probs(VP8_COMP *cpi)
@@ -3899,7 +3900,9 @@ static void update_refpred_stats( VP8_COMP *cpi )
         cm->ref_pred_probs[0] = 120;
         cm->ref_pred_probs[1] = 80;
         cm->ref_pred_probs[2] = 40;
-        vpx_memset(cpi->ref_probs_update, 0, sizeof(cpi->ref_probs_update) );
+
+        vpx_memset(cpi->ref_pred_probs_update, 0,
+                   sizeof(cpi->ref_pred_probs_update) );
     }
     else
     {
@@ -3988,11 +3991,11 @@ static void update_refpred_stats( VP8_COMP *cpi )
             // Cost saving must be >= 8 bits (2048 in these units)
             if ( (old_cost - new_cost) >= 2048 )
             {
-                cpi->ref_probs_update[i] = 1;
+                cpi->ref_pred_probs_update[i] = 1;
                 cm->ref_pred_probs[i] = new_pred_probs[i];
             }
             else
-                cpi->ref_probs_update[i] = 0;
+                cpi->ref_pred_probs_update[i] = 0;
 
         }
     }
@@ -4156,6 +4159,7 @@ static void encode_frame_to_data_rate
 #endif
 
 #if !CONFIG_COMPRED
+//#if 1
     update_rd_ref_frame_probs(cpi);
 #endif
 
index 214006cfd6a74d52a53557995ec6e4e0a1797917..cd2f25eaa77979f7fb1aef9a8b2a8c2c817c7c2e 100644 (file)
@@ -519,7 +519,7 @@ typedef struct VP8_COMP
     int last_frame_percent_intra;
     int ref_frame_flags;
 
-    unsigned char ref_probs_update[PREDICTION_PROBS];
+    unsigned char ref_pred_probs_update[PREDICTION_PROBS];
 
     SPEED_FEATURES sf;
     int error_bins[1024];