shithub: libvpx

Download patch

ref: 4ee671a15c9674456cf447168beb0462278ee14b
parent: 8ae091823de3fc90451a6f67731687ca552ce99b
parent: c2876cf0fde6baf9cbdf3c7570adedfd1065f3db
author: Adrian Grange <agrange@google.com>
date: Mon Apr 15 05:46:16 EDT 2013

Merge "Initial addition of multiple ARF frames" into experimental

--- a/configure
+++ b/configure
@@ -253,6 +253,7 @@
     scatterscan
     oneshotq
     sbsegment
+    multiple_arf
 "
 CONFIG_LIST="
     external_build
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -2685,7 +2685,7 @@
     /* Clear the alternate reference update pending flag. */
     cpi->source_alt_ref_pending = 0;
 
-    /* Set the alternate refernce frame active flag */
+    /* Set the alternate reference frame active flag */
     cpi->source_alt_ref_active = 1;
 
 
@@ -3332,7 +3332,7 @@
     else
         cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 0;
 
-    /* Check to see if a key frame is signalled
+    /* Check to see if a key frame is signaled
      * For two pass with auto key frame enabled cm->frame_type may already
      * be set, but not for one pass.
      */
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -18,6 +18,7 @@
 #include "vp9/common/vp9_entropymv.h"
 #include "vp9/common/vp9_entropy.h"
 #include "vp9/common/vp9_entropymode.h"
+
 #if CONFIG_POSTPROC
 #include "vp9/common/vp9_postproc.h"
 #endif
@@ -37,8 +38,13 @@
 
 #define QINDEX_RANGE (MAXQ + 1)
 
+#if CONFIG_MULTIPLE_ARF
+#define NUM_REF_FRAMES 8
+#define NUM_REF_FRAMES_LG2 3
+#else
 #define NUM_REF_FRAMES 3
 #define NUM_REF_FRAMES_LG2 2
+#endif
 
 #define ALLOWED_REFS_PER_FRAME 3
 
@@ -51,6 +57,8 @@
 #define NUM_FRAME_CONTEXTS (1 << NUM_FRAME_CONTEXTS_LG2)
 
 #define COMP_PRED_CONTEXTS   2
+
+#define MAX_LAG_BUFFERS 25
 
 typedef struct frame_contexts {
   vp9_prob bmode_prob[VP9_NKF_BINTRAMODES - 1];
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -249,7 +249,7 @@
   return 0;
 }
 
-/* If any buffer updating is signalled it should be done here. */
+/* If any buffer updating is signaled it should be done here. */
 static void swap_frame_buffers(VP9D_COMP *pbi) {
   int ref_index = 0, mask;
 
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -2617,7 +2617,12 @@
     int refresh_mask;
 
     // Should the GF or ARF be updated using the transmitted frame or buffer
-    if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+#if CONFIG_MULTIPLE_ARF
+    if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
+        !cpi->refresh_alt_ref_frame) {
+#else
+      if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+#endif
       /* Preserve the previously existing golden frame and update the frame in
        * the alt ref slot instead. This is highly specific to the use of
        * alt-ref as a forward reference, and this needs to be generalized as
@@ -2630,10 +2635,21 @@
       refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
                      (cpi->refresh_golden_frame << cpi->alt_fb_idx);
     } else {
+      int arf_idx = cpi->alt_fb_idx;
+#if CONFIG_MULTIPLE_ARF
+      // Determine which ARF buffer to use to encode this ARF frame.
+      if (cpi->multi_arf_enabled) {
+        int sn = cpi->sequence_number;
+        arf_idx = (cpi->frame_coding_order[sn] < 0) ?
+            cpi->arf_buffer_idx[sn + 1] :
+            cpi->arf_buffer_idx[sn];
+      }
+#endif
       refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
                      (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
-                     (cpi->refresh_alt_ref_frame << cpi->alt_fb_idx);
+                     (cpi->refresh_alt_ref_frame << arf_idx);
     }
+
     vp9_write_literal(&header_bc, refresh_mask, NUM_REF_FRAMES);
     vp9_write_literal(&header_bc, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
     vp9_write_literal(&header_bc, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -317,15 +317,20 @@
 }
 
 
-// This function returns the current per frame maximum bitrate target
+// This function returns the current per frame maximum bitrate target.
 static int frame_max_bits(VP9_COMP *cpi) {
-  // Max allocation for a single frame based on the max section guidelines passed in and how many bits are left
+  // Max allocation for a single frame based on the max section guidelines
+  // passed in and how many bits are left.
   int max_bits;
 
-  // For VBR base this on the bits and frames left plus the two_pass_vbrmax_section rate passed in by the user
-  max_bits = (int)(((double)cpi->twopass.bits_left / (cpi->twopass.total_stats->count - (double)cpi->common.current_video_frame)) * ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));
+  // For VBR base this on the bits and frames left plus the
+  // two_pass_vbrmax_section rate passed in by the user.
+  max_bits = (int) (((double) cpi->twopass.bits_left
+      / (cpi->twopass.total_stats->count - (double) cpi->common
+             .current_video_frame))
+                    * ((double) cpi->oxcf.two_pass_vbrmax_section / 100.0));
 
-  // Trap case where we are out of bits
+  // Trap case where we are out of bits.
   if (max_bits < 0)
     max_bits = 0;
 
@@ -746,7 +751,7 @@
     }
 
     // TODO:  handle the case when duration is set to 0, or something less
-    // than the full time between subsequent cpi->source_time_stamp s  .
+    // than the full time between subsequent values of cpi->source_time_stamp.
     fps.duration = (double)(cpi->source->ts_end
                             - cpi->source->ts_start);
 
@@ -873,7 +878,7 @@
 
 // Given a current maxQ value sets a range for future values.
 // PGW TODO..
-// This code removes direct dependency on QIndex to determin the range
+// This code removes direct dependency on QIndex to determine the range
 // (now uses the actual quantizer) but has not been tuned.
 static void adjust_maxq_qrange(VP9_COMP *cpi) {
   int i;
@@ -991,7 +996,7 @@
   }
 
   // Adjust maxq_min_limit and maxq_max_limit limits based on
-  // averaga q observed in clip for non kf/gf/arf frames
+  // average q observed in clip for non kf/gf/arf frames
   // Give average a chance to settle though.
   // PGW TODO.. This code is broken for the extended Q range
   if ((cpi->ni_frames >
@@ -1379,7 +1384,7 @@
                                   &this_frame_mv_in_out, &mv_in_out_accumulator,
                                   &abs_mv_in_out_accumulator, &mv_ratio_accumulator);
 
-    // We want to discount the the flash frame itself and the recovery
+    // We want to discount the flash frame itself and the recovery
     // frame that follows as both will have poor scores.
     flash_detected = detect_flash(cpi, (i + offset)) ||
                      detect_flash(cpi, (i + offset + 1));
@@ -1442,9 +1447,8 @@
   return arf_boost;
 }
 
-static void configure_arnr_filter(VP9_COMP *cpi,
-                                  FIRSTPASS_STATS *this_frame,
-                                  int group_boost) {
+void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
+                           int group_boost) {
   int half_gf_int;
   int frames_after_arf;
   int frames_bwd = cpi->oxcf.arnr_max_frames - 1;
@@ -1458,8 +1462,7 @@
   // Note: this_frame->frame has been updated in the loop
   // so it now points at the ARF frame.
   half_gf_int = cpi->baseline_gf_interval >> 1;
-  frames_after_arf = (int)(cpi->twopass.total_stats->count -
-                           this_frame->frame - 1);
+  frames_after_arf = (int)(cpi->twopass.total_stats->count - this_frame - 1);
 
   switch (cpi->oxcf.arnr_type) {
     case 1: // Backward filter
@@ -1515,7 +1518,144 @@
   }
 }
 
-// Analyse and define a gf/arf group .
+#if CONFIG_MULTIPLE_ARF
+// Work out the frame coding order for a GF or an ARF group.
+// The current implementation codes frames in their natural order for a
+// GF group, and inserts additional ARFs into an ARF group using a
+// binary split approach.
+// NOTE: this function is currently implemented recursively.
+static void schedule_frames(VP9_COMP *cpi, const int start, const int end,
+                            const int arf_idx, const int gf_or_arf_group,
+                            const int level) {
+  int i, abs_end, half_range;
+  int *cfo = cpi->frame_coding_order;
+  int idx = cpi->new_frame_coding_order_period;
+
+  // If (end < 0) an ARF should be coded at position (-end).
+  assert(start >= 0);
+
+  // printf("start:%d end:%d\n", start, end);
+
+  // GF Group: code frames in logical order.
+  if (gf_or_arf_group == 0) {
+    assert(end >= start);
+    for (i = start; i <= end; ++i) {
+      cfo[idx] = i;
+      cpi->arf_buffer_idx[idx] = arf_idx;
+      cpi->arf_weight[idx] = -1;
+      ++idx;
+    }
+    cpi->new_frame_coding_order_period = idx;
+    return;
+  }
+
+  // ARF Group: work out the ARF schedule.
+  // Mark ARF frames as negative.
+  if (end < 0) {
+    // printf("start:%d end:%d\n", -end, -end);
+    // ARF frame is at the end of the range.
+    cfo[idx] = end;
+    // What ARF buffer does this ARF use as predictor.
+    cpi->arf_buffer_idx[idx] = (arf_idx > 2) ? (arf_idx - 1) : 2;
+    cpi->arf_weight[idx] = level;
+    ++idx;
+    abs_end = -end;
+  } else {
+    abs_end = end;
+  }
+
+  half_range = (abs_end - start) >> 1;
+
+  // ARFs may not be adjacent, they must be separated by at least
+  // MIN_GF_INTERVAL non-ARF frames.
+  if ((start + MIN_GF_INTERVAL) >= (abs_end - MIN_GF_INTERVAL)) {
+    // printf("start:%d end:%d\n", start, abs_end);
+    // Update the coding order and active ARF.
+    for (i = start; i <= abs_end; ++i) {
+      cfo[idx] = i;
+      cpi->arf_buffer_idx[idx] = arf_idx;
+      cpi->arf_weight[idx] = -1;
+      ++idx;
+    }
+    cpi->new_frame_coding_order_period = idx;
+  } else {
+    // Place a new ARF at the mid-point of the range.
+    cpi->new_frame_coding_order_period = idx;
+    schedule_frames(cpi, start, -(start + half_range), arf_idx + 1,
+                    gf_or_arf_group, level + 1);
+    schedule_frames(cpi, start + half_range + 1, abs_end, arf_idx,
+                    gf_or_arf_group, level + 1);
+  }
+}
+
+#define FIXED_ARF_GROUP_SIZE 16
+
+void define_fixed_arf_period(VP9_COMP *cpi) {
+  int i;
+  int max_level = INT_MIN;
+
+  assert(cpi->multi_arf_enabled);
+  assert(cpi->oxcf.lag_in_frames >= FIXED_ARF_GROUP_SIZE);
+
+  // Save the weight of the last frame in the sequence before next
+  // sequence pattern overwrites it.
+  cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number];
+  assert(cpi->this_frame_weight >= 0);
+
+  // Initialize frame coding order variables.
+  cpi->new_frame_coding_order_period = 0;
+  cpi->next_frame_in_order = 0;
+  cpi->arf_buffered = 0;
+  vp9_zero(cpi->frame_coding_order);
+  vp9_zero(cpi->arf_buffer_idx);
+  vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight));
+
+  if (cpi->twopass.frames_to_key <= (FIXED_ARF_GROUP_SIZE + 8)) {
+    // Setup a GF group close to the keyframe.
+    cpi->source_alt_ref_pending = FALSE;
+    cpi->baseline_gf_interval = cpi->twopass.frames_to_key;
+    schedule_frames(cpi, 0, (cpi->baseline_gf_interval - 1), 2, 0, 0);
+  } else {
+    // Setup a fixed period ARF group.
+    cpi->source_alt_ref_pending = TRUE;
+    cpi->baseline_gf_interval = FIXED_ARF_GROUP_SIZE;
+    schedule_frames(cpi, 0, -(cpi->baseline_gf_interval - 1), 2, 1, 0);
+  }
+
+  // Replace level indicator of -1 with correct level.
+  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+    if (cpi->arf_weight[i] > max_level) {
+      max_level = cpi->arf_weight[i];
+    }
+  }
+  ++max_level;
+  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+    if (cpi->arf_weight[i] == -1) {
+      cpi->arf_weight[i] = max_level;
+    }
+  }
+  cpi->max_arf_level = max_level;
+#if 0
+  printf("\nSchedule: ");
+  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+    printf("%4d ", cpi->frame_coding_order[i]);
+  }
+  printf("\n");
+  printf("ARFref:   ");
+  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+    printf("%4d ", cpi->arf_buffer_idx[i]);
+  }
+  printf("\n");
+  printf("Weight:   ");
+  for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+    printf("%4d ", cpi->arf_weight[i]);
+  }
+  printf("\n");
+#endif
+}
+#endif
+
+// Analyse and define a gf/arf group.
 static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
   FIRSTPASS_STATS next_frame;
   FIRSTPASS_STATS *start_pos;
@@ -1619,7 +1759,7 @@
       }
 
       // Break clause to detect very still sections after motion
-      // (for example a staic image after a fade or other transition).
+      // (for example a static image after a fade or other transition).
       if (detect_transition_to_still(cpi, i, 5, loop_decay_rate,
                                      last_loop_decay_rate)) {
         allow_alt_ref = FALSE;
@@ -1637,9 +1777,9 @@
       // Break at cpi->max_gf_interval unless almost totally static
       (i >= active_max_gf_interval && (zero_motion_accumulator < 0.995)) ||
       (
-        // Dont break out with a very short interval
+        // Don't break out with a very short interval
         (i > MIN_GF_INTERVAL) &&
-        // Dont break out very close to a key frame
+        // Don't break out very close to a key frame
         ((cpi->twopass.frames_to_key - i) >= MIN_GF_INTERVAL) &&
         ((boost_score > 125.0) || (next_frame.pcnt_inter < 0.75)) &&
         (!flash_detected) &&
@@ -1657,7 +1797,7 @@
     old_boost_score = boost_score;
   }
 
-  // Dont allow a gf too near the next kf
+  // Don't allow a gf too near the next kf
   if ((cpi->twopass.frames_to_key - i) < MIN_GF_INTERVAL) {
     while (i < cpi->twopass.frames_to_key) {
       i++;
@@ -1672,10 +1812,22 @@
     }
   }
 
-  // Set the interval till the next gf or arf.
+  // Set the interval until the next gf or arf.
   cpi->baseline_gf_interval = i;
 
-  // Should we use the alternate refernce frame
+#if CONFIG_MULTIPLE_ARF
+  if (cpi->multi_arf_enabled) {
+    // Initialize frame coding order variables.
+    cpi->new_frame_coding_order_period = 0;
+    cpi->next_frame_in_order = 0;
+    cpi->arf_buffered = 0;
+    vp9_zero(cpi->frame_coding_order);
+    vp9_zero(cpi->arf_buffer_idx);
+    vpx_memset(cpi->arf_weight, -1, sizeof(cpi->arf_weight));
+  }
+#endif
+
+  // Should we use the alternate reference frame
   if (allow_alt_ref &&
       (i < cpi->oxcf.lag_in_frames) &&
       (i >= MIN_GF_INTERVAL) &&
@@ -1686,16 +1838,66 @@
       ((mv_in_out_accumulator / (double)i > -0.2) ||
        (mv_in_out_accumulator > -2.0)) &&
       (boost_score > 100)) {
-    // Alterrnative boost calculation for alt ref
+    // Alternative boost calculation for alt ref
     cpi->gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, &b_boost);
     cpi->source_alt_ref_pending = TRUE;
 
-    configure_arnr_filter(cpi, this_frame, cpi->gfu_boost);
+#if CONFIG_MULTIPLE_ARF
+    // Set the ARF schedule.
+    if (cpi->multi_arf_enabled) {
+      schedule_frames(cpi, 0, -(cpi->baseline_gf_interval - 1), 2, 1, 0);
+    }
+#endif
   } else {
     cpi->gfu_boost = (int)boost_score;
     cpi->source_alt_ref_pending = FALSE;
+#if CONFIG_MULTIPLE_ARF
+    // Set the GF schedule.
+    if (cpi->multi_arf_enabled) {
+      schedule_frames(cpi, 0, cpi->baseline_gf_interval - 1, 2, 0, 0);
+      assert(cpi->new_frame_coding_order_period == cpi->baseline_gf_interval);
+    }
+#endif
   }
 
+#if CONFIG_MULTIPLE_ARF
+  if (cpi->multi_arf_enabled && (cpi->common.frame_type != KEY_FRAME)) {
+    int max_level = INT_MIN;
+    // Replace level indicator of -1 with correct level.
+    for (i = 0; i < cpi->frame_coding_order_period; ++i) {
+      if (cpi->arf_weight[i] > max_level) {
+        max_level = cpi->arf_weight[i];
+      }
+    }
+    ++max_level;
+    for (i = 0; i < cpi->frame_coding_order_period; ++i) {
+      if (cpi->arf_weight[i] == -1) {
+        cpi->arf_weight[i] = max_level;
+      }
+    }
+    cpi->max_arf_level = max_level;
+  }
+#if 0
+  if (cpi->multi_arf_enabled) {
+    printf("\nSchedule: ");
+    for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+      printf("%4d ", cpi->frame_coding_order[i]);
+    }
+    printf("\n");
+    printf("ARFref:   ");
+    for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+      printf("%4d ", cpi->arf_buffer_idx[i]);
+    }
+    printf("\n");
+    printf("Weight:   ");
+    for (i = 0; i < cpi->new_frame_coding_order_period; ++i) {
+      printf("%4d ", cpi->arf_weight[i]);
+    }
+    printf("\n");
+  }
+#endif
+#endif
+
   // Now decide how many bits should be allocated to the GF group as  a
   // proportion of those remaining in the kf group.
   // The final key frame group in the clip is treated as a special case
@@ -1736,10 +1938,13 @@
   cpi->twopass.modified_error_used += gf_group_err;
 
   // Assign  bits to the arf or gf.
-  for (i = 0; i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME); i++) {
+  for (i = 0;
+      i <= (cpi->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME);
+      ++i) {
     int boost;
     int allocation_chunks;
-    int Q = (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
+    int Q =
+        (cpi->oxcf.fixed_q < 0) ? cpi->last_q[INTER_FRAME] : cpi->oxcf.fixed_q;
     int gf_bits;
 
     boost = (cpi->gfu_boost * vp9_gfboost_qadjust(Q)) / 100;
@@ -1758,7 +1963,7 @@
         (cpi->baseline_gf_interval * 100) + (boost - 100);
 
     // Prevent overflow
-    if (boost > 1028) {
+    if (boost > 1028) {  // TODO(agrange) Should this be 1024?
       int divisor = boost >> 10;
       boost /= divisor;
       allocation_chunks /= divisor;
@@ -1807,18 +2012,21 @@
     if (gf_bits < 0)
       gf_bits = 0;
 
-    gf_bits += cpi->min_frame_bandwidth;                     // Add in minimum for a frame
+    // Add in minimum for a frame
+    gf_bits += cpi->min_frame_bandwidth;
 
     if (i == 0) {
       cpi->twopass.gf_bits = gf_bits;
     }
-    if (i == 1 || (!cpi->source_alt_ref_pending && (cpi->common.frame_type != KEY_FRAME))) {
-      cpi->per_frame_bandwidth = gf_bits;                 // Per frame bit target for this frame
+    if (i == 1 || (!cpi->source_alt_ref_pending
+        && (cpi->common.frame_type != KEY_FRAME))) {
+      // Per frame bit target for this frame
+      cpi->per_frame_bandwidth = gf_bits;
     }
   }
 
   {
-    // Adjust KF group bits and error remainin
+    // Adjust KF group bits and error remaining
     cpi->twopass.kf_group_error_left -= (int64_t)gf_group_err;
     cpi->twopass.kf_group_bits -= cpi->twopass.gf_group_bits;
 
@@ -1835,13 +2043,14 @@
     else
       cpi->twopass.gf_group_error_left = (int64_t)gf_group_err;
 
-    cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits - cpi->min_frame_bandwidth;
+    cpi->twopass.gf_group_bits -= cpi->twopass.gf_bits
+        - cpi->min_frame_bandwidth;
 
     if (cpi->twopass.gf_group_bits < 0)
       cpi->twopass.gf_group_bits = 0;
 
     // This condition could fail if there are two kfs very close together
-    // despite (MIN_GF_INTERVAL) and would cause a devide by 0 in the
+    // despite (MIN_GF_INTERVAL) and would cause a divide by 0 in the
     // calculation of cpi->twopass.alt_extra_bits.
     if (cpi->baseline_gf_interval >= 3) {
       int boost = (cpi->source_alt_ref_pending)
@@ -1853,6 +2062,7 @@
         pct_extra = (boost - 100) / 50;
         pct_extra = (pct_extra > 20) ? 20 : pct_extra;
 
+        // TODO(agrange) Remove cpi->twopass.alt_extra_bits.
         cpi->twopass.alt_extra_bits = (int)
           ((cpi->twopass.gf_group_bits * pct_extra) / 100);
         cpi->twopass.gf_group_bits -= cpi->twopass.alt_extra_bits;
@@ -1887,24 +2097,28 @@
 
 // Allocate bits to a normal frame that is neither a gf an arf or a key frame.
 static void assign_std_frame_bits(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
-  int    target_frame_size;                                                             // gf_group_error_left
+  int target_frame_size;
 
   double modified_err;
-  double err_fraction;                                                                 // What portion of the remaining GF group error is used by this frame
+  double err_fraction;
 
-  int max_bits = frame_max_bits(cpi);    // Max for a single frame
+  // Max for a single frame.
+  int max_bits = frame_max_bits(cpi);
 
-  // Calculate modified prediction error used in bit allocation
+  // Calculate modified prediction error used in bit allocation.
   modified_err = calculate_modified_err(cpi, this_frame);
 
   if (cpi->twopass.gf_group_error_left > 0)
-    err_fraction = modified_err / cpi->twopass.gf_group_error_left;                              // What portion of the remaining GF group error is used by this frame
+    // What portion of the remaining GF group error is used by this frame.
+    err_fraction = modified_err / cpi->twopass.gf_group_error_left;
   else
     err_fraction = 0.0;
 
-  target_frame_size = (int)((double)cpi->twopass.gf_group_bits * err_fraction);                    // How many of those bits available for allocation should we give it?
+  // How many of those bits available for allocation should we give it?
+  target_frame_size = (int)((double)cpi->twopass.gf_group_bits * err_fraction);
 
-  // Clip to target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at the top end.
+  // Clip target size to 0 - max_bits (or cpi->twopass.gf_group_bits) at
+  // the top end.
   if (target_frame_size < 0)
     target_frame_size = 0;
   else {
@@ -1915,17 +2129,18 @@
       target_frame_size = (int)cpi->twopass.gf_group_bits;
   }
 
-  // Adjust error remaining
+  // Adjust error and bits remaining.
   cpi->twopass.gf_group_error_left -= (int64_t)modified_err;
-  cpi->twopass.gf_group_bits -= target_frame_size;                                                // Adjust bits remaining
+  cpi->twopass.gf_group_bits -= target_frame_size;
 
   if (cpi->twopass.gf_group_bits < 0)
     cpi->twopass.gf_group_bits = 0;
 
-  target_frame_size += cpi->min_frame_bandwidth;                                          // Add in the minimum number of bits that is set aside for every frame.
+  // Add in the minimum number of bits that is set aside for every frame.
+  target_frame_size += cpi->min_frame_bandwidth;
 
-
-  cpi->per_frame_bandwidth = target_frame_size;                                           // Per frame bit target for this frame
+  // Per frame bit target for this frame.
+  cpi->per_frame_bandwidth = target_frame_size;
 }
 
 // Make a damped adjustment to the active max q.
@@ -2059,8 +2274,17 @@
   if (cpi->frames_till_gf_update_due == 0) {
     // Define next gf group and assign bits to it
     vpx_memcpy(&this_frame_copy, &this_frame, sizeof(this_frame));
-    define_gf_group(cpi, &this_frame_copy);
 
+#if CONFIG_MULTIPLE_ARF
+    if (cpi->multi_arf_enabled) {
+      define_fixed_arf_period(cpi);
+    } else {
+#endif
+      define_gf_group(cpi, &this_frame_copy);
+#if CONFIG_MULTIPLE_ARF
+    }
+#endif
+
     // If we are going to code an altref frame at the end of the group
     // and the current frame is not a key frame....
     // If the previous group used an arf this frame has already benefited
@@ -2101,7 +2325,7 @@
 
   cpi->twopass.frames_to_key--;
 
-  // Update the total stats remaining sturcture
+  // Update the total stats remaining structure
   subtract_stats(cpi->twopass.total_left_stats, &this_frame);
 }
 
@@ -2178,7 +2402,8 @@
         break;
     }
 
-    // If there is tolerable prediction for at least the next 3 frames then break out else discard this pottential key frame and move on
+    // If there is tolerable prediction for at least the next 3 frames then
+    // break out else discard this potential key frame and move on
     if (boost_score > 30.0 && (i > 3))
       is_viable_kf = TRUE;
     else {
@@ -2231,7 +2456,7 @@
   // Take a copy of the initial frame details
   vpx_memcpy(&first_frame, this_frame, sizeof(*this_frame));
 
-  cpi->twopass.kf_group_bits = 0;        // Total bits avaialable to kf group
+  cpi->twopass.kf_group_bits = 0;        // Total bits available to kf group
   cpi->twopass.kf_group_error_left = 0;  // Group modified error score.
 
   kf_mod_err = calculate_modified_err(cpi, this_frame);
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -82,6 +82,10 @@
 
 #endif
 
+// TODO(agrange) Move this function.
+extern void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
+                                  int group_boost);
+
 // #define OUTPUT_YUV_REC
 
 #ifdef OUTPUT_YUV_SRC
@@ -738,7 +742,12 @@
   sf->optimize_coefficients = !cpi->oxcf.lossless;
   sf->first_step = 0;
   sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
+#if CONFIG_MULTIPLE_ARF
+  // Switch segmentation off.
+  sf->static_segmentation = 0;
+#else
   sf->static_segmentation = 1;
+#endif
   sf->splitmode_breakout = 0;
   sf->mb16_breakout = 0;
 
@@ -748,7 +757,12 @@
       break;
 
     case 1:
+#if CONFIG_MULTIPLE_ARF
+      // Switch segmentation off.
+      sf->static_segmentation = 0;
+#else
       sf->static_segmentation = 1;
+#endif
       sf->splitmode_breakout = 1;
       sf->mb16_breakout = 0;
 
@@ -1265,7 +1279,11 @@
   }
 
   // YX Temp
+#if CONFIG_MULTIPLE_ARF
+  vp9_zero(cpi->alt_ref_source);
+#else
   cpi->alt_ref_source = NULL;
+#endif
   cpi->is_src_frame_alt_ref = 0;
 
 #if 0
@@ -1356,9 +1374,9 @@
   cpi->common.current_video_frame   = 0;
   cpi->kf_overspend_bits            = 0;
   cpi->kf_bitrate_adjustment        = 0;
-  cpi->frames_till_gf_update_due      = 0;
+  cpi->frames_till_gf_update_due    = 0;
   cpi->gf_overspend_bits            = 0;
-  cpi->non_gf_bitrate_adjustment     = 0;
+  cpi->non_gf_bitrate_adjustment    = 0;
   cm->prob_last_coded               = 128;
   cm->prob_gf_coded                 = 128;
   cm->prob_intra_coded              = 63;
@@ -1369,7 +1387,7 @@
   for (i = 0; i < TX_SIZE_MAX_SB - 1; i++)
     cm->prob_tx[i]               = 128;
 
-  // Prime the recent reference frame useage counters.
+  // Prime the recent reference frame usage counters.
   // Hereafter they will be maintained as a sort of moving average
   cpi->recent_ref_frame_usage[INTRA_FRAME]  = 1;
   cpi->recent_ref_frame_usage[LAST_FRAME]   = 1;
@@ -1449,6 +1467,19 @@
   cpi->source_alt_ref_active = FALSE;
   cpi->refresh_alt_ref_frame = 0;
 
+#if CONFIG_MULTIPLE_ARF
+  // Turn multiple ARF usage on/off. This is a quick hack for the initial test
+  // version. It should eventually be set via the codec API.
+  cpi->multi_arf_enabled = 1;
+
+  if (cpi->multi_arf_enabled) {
+    cpi->sequence_number = 0;
+    cpi->frame_coding_order_period = 0;
+    vp9_zero(cpi->frame_coding_order);
+    vp9_zero(cpi->arf_buffer_idx);
+  }
+#endif
+
   cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
 #if CONFIG_INTERNAL_STATS
   cpi->b_calculate_ssimg = 0;
@@ -2193,10 +2224,13 @@
   // this frame refreshes means next frames don't unless specified by user
   cpi->common.frames_since_golden = 0;
 
-  // Clear the alternate reference update pending flag.
-  cpi->source_alt_ref_pending = FALSE;
+#if CONFIG_MULTIPLE_ARF
+  if (!cpi->multi_arf_enabled)
+#endif
+    // Clear the alternate reference update pending flag.
+    cpi->source_alt_ref_pending = FALSE;
 
-  // Set the alternate refernce frame active flag
+  // Set the alternate reference frame active flag
   cpi->source_alt_ref_active = TRUE;
 
 
@@ -2223,7 +2257,7 @@
     // }
     // else
     // {
-    //  // Carry a potrtion of count over to begining of next gf sequence
+    //  // Carry a portion of count over to beginning of next gf sequence
     //  cpi->recent_ref_frame_usage[INTRA_FRAME] >>= 5;
     //  cpi->recent_ref_frame_usage[LAST_FRAME] >>= 5;
     //  cpi->recent_ref_frame_usage[GOLDEN_FRAME] >>= 5;
@@ -2362,7 +2396,7 @@
   VP9_COMMON *cm = &cpi->common;
 
   // Is frame recode allowed at all
-  // Yes if either recode mode 1 is selected or mode two is selcted
+  // Yes if either recode mode 1 is selected or mode two is selected
   // and the frame is a key frame. golden frame or alt_ref_frame
   if ((cpi->sf.recode_loop == 1) ||
       ((cpi->sf.recode_loop == 2) &&
@@ -2403,13 +2437,19 @@
                &cm->ref_frame_map[cpi->gld_fb_idx], cm->new_fb_idx);
     ref_cnt_fb(cm->fb_idx_ref_cnt,
                &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
-  } else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+  }
+#if CONFIG_MULTIPLE_ARF
+  else if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
+      !cpi->refresh_alt_ref_frame) {
+#else
+  else if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+#endif
     /* Preserve the previously existing golden frame and update the frame in
      * the alt ref slot instead. This is highly specific to the current use of
      * alt-ref as a forward reference, and this needs to be generalized as
      * other uses are implemented (like RTC/temporal scaling)
      *
-     * The update to the buffer in the alt ref slot was signalled in
+     * The update to the buffer in the alt ref slot was signaled in
      * vp9_pack_bitstream(), now swap the buffer pointers so that it's treated
      * as the golden frame next time.
      */
@@ -2421,10 +2461,16 @@
     tmp = cpi->alt_fb_idx;
     cpi->alt_fb_idx = cpi->gld_fb_idx;
     cpi->gld_fb_idx = tmp;
-  } else { /* For non key/golden frames */
+  }  else { /* For non key/golden frames */
     if (cpi->refresh_alt_ref_frame) {
+      int arf_idx = cpi->alt_fb_idx;
+#if CONFIG_MULTIPLE_ARF
+      if (cpi->multi_arf_enabled) {
+        arf_idx = cpi->arf_buffer_idx[cpi->sequence_number + 1];
+      }
+#endif
       ref_cnt_fb(cm->fb_idx_ref_cnt,
-                 &cm->ref_frame_map[cpi->alt_fb_idx], cm->new_fb_idx);
+                 &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
     }
 
     if (cpi->refresh_golden_frame) {
@@ -2615,7 +2661,8 @@
   // For an alt ref frame in 2 pass we skip the call to the second
   // pass function that sets the target bandwidth so must set it here
   if (cpi->refresh_alt_ref_frame) {
-    cpi->per_frame_bandwidth = cpi->twopass.gf_bits;                           // Per frame bit target for the alt ref frame
+    // Per frame bit target for the alt ref frame
+    cpi->per_frame_bandwidth = cpi->twopass.gf_bits;
     // per second target bitrate
     cpi->target_bandwidth = (int)(cpi->twopass.gf_bits *
                                   cpi->output_frame_rate);
@@ -2637,7 +2684,7 @@
   // Current default encoder behaviour for the altref sign bias
     cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = cpi->source_alt_ref_active;
 
-  // Check to see if a key frame is signalled
+  // Check to see if a key frame is signaled
   // For two pass with auto key frame enabled cm->frame_type may already be set, but not for one pass.
   if ((cm->current_video_frame == 0) ||
       (cm->frame_flags & FRAMEFLAGS_KEY) ||
@@ -2681,7 +2728,7 @@
 
   // Configure use of segmentation for enhanced coding of static regions.
   // Only allowed for now in second pass of two pass (as requires lagged coding)
-  // and if the relevent speed feature flag is set.
+  // and if the relevant speed feature flag is set.
   if ((cpi->pass == 2) && (cpi->sf.static_segmentation)) {
     configure_static_seg_features(cpi);
   }
@@ -2695,6 +2742,9 @@
   q = cpi->active_worst_quality;
 
   if (cm->frame_type == KEY_FRAME) {
+#if CONFIG_MULTIPLE_ARF
+    double current_q;
+#endif
     int high = 2000;
     int low = 400;
 
@@ -2711,7 +2761,7 @@
       cpi->active_best_quality = kf_low_motion_minq[q] + adjustment;
     }
 
-    // Make an adjustment based on the %s static
+    // Make an adjustment based on the % static
     // The main impact of this is at lower Q to prevent overly large key
     // frames unless a lot of the image is static.
     if (cpi->kf_zeromotion_pct < 64)
@@ -2728,9 +2778,14 @@
       delta_qindex = compute_qdelta(cpi, last_boosted_q,
                                     (last_boosted_q * 0.75));
 
-
       cpi->active_best_quality = MAX(qindex + delta_qindex, cpi->best_quality);
     }
+#if CONFIG_MULTIPLE_ARF
+    // Force the KF quantizer to be 30% of the active_worst_quality.
+    current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality);
+    cpi->active_best_quality = cpi->active_worst_quality
+        + compute_qdelta(cpi, current_q, current_q * 0.3);
+#endif
   } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) {
     int high = 2000;
     int low = 400;
@@ -2776,7 +2831,7 @@
     cpi->active_best_quality = inter_minq[q];
 #endif
 
-    // For the constant/constrained quality mode we dont want
+    // For the constant/constrained quality mode we don't want
     // q to fall below the cq level.
     if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
         (cpi->active_best_quality < cpi->cq_target_quality)) {
@@ -2814,12 +2869,34 @@
   vp9_compute_frame_size_bounds(cpi, &frame_under_shoot_limit,
                                 &frame_over_shoot_limit);
 
-  // Limit Q range for the adaptive loop.
-  bottom_index = cpi->active_best_quality;
-  top_index    = cpi->active_worst_quality;
-  q_low  = cpi->active_best_quality;
-  q_high = cpi->active_worst_quality;
+#if CONFIG_MULTIPLE_ARF
+  // Force the quantizer determined by the coding order pattern.
+  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME)) {
+    double new_q;
+    double current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality);
+    int level = cpi->this_frame_weight;
+    assert(level >= 0);
 
+    // Set quantizer steps at 10% increments.
+    new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
+    q = cpi->active_worst_quality + compute_qdelta(cpi, current_q, new_q);
+
+    bottom_index = q;
+    top_index    = q;
+    q_low  = q;
+    q_high = q;
+
+    printf("frame:%d q:%d\n", cm->current_video_frame, q);
+  } else {
+#endif
+    // Limit Q range for the adaptive loop.
+    bottom_index = cpi->active_best_quality;
+    top_index    = cpi->active_worst_quality;
+    q_low  = cpi->active_best_quality;
+    q_high = cpi->active_worst_quality;
+#if CONFIG_MULTIPLE_ARF
+  }
+#endif
   loop_count = 0;
 
   if (cm->frame_type != KEY_FRAME) {
@@ -2936,8 +3013,8 @@
       if (cm->frame_type == KEY_FRAME) {
         /* Choose which entropy context to use. When using a forward reference
          * frame, it immediately follows the keyframe, and thus benefits from
-         * using the same entropy context established by the keyframe. Otherwise,
-         * use the default context 0.
+         * using the same entropy context established by the keyframe.
+         *  Otherwise, use the default context 0.
          */
         cm->frame_context_idx = cpi->oxcf.play_alternate;
         vp9_setup_key_frame(cpi);
@@ -3191,7 +3268,7 @@
     }
   }
 
-  // Update the GF useage maps.
+  // Update the GF usage maps.
   // This is done after completing the compression of a frame when all modes
   // etc. are finalized but before loop filter
   vp9_update_gf_useage_maps(cpi, cm, &cpi->mb);
@@ -3366,7 +3443,7 @@
   // in this frame.
   update_base_skip_probs(cpi);
 
-#if 0  // 1 && CONFIG_INTERNAL_STATS
+#if 0 && CONFIG_INTERNAL_STATS
   {
     FILE *f = fopen("tmp.stt", "a");
     int recon_err;
@@ -3513,10 +3590,33 @@
     // Tell the caller that the frame was coded as a key frame
     *frame_flags = cm->frame_flags | FRAMEFLAGS_KEY;
 
-    // As this frame is a key frame  the next defaults to an inter frame.
+#if CONFIG_MULTIPLE_ARF
+    // Reset the sequence number.
+    if (cpi->multi_arf_enabled) {
+      cpi->sequence_number = 0;
+      cpi->frame_coding_order_period = cpi->new_frame_coding_order_period;
+      cpi->new_frame_coding_order_period = -1;
+    }
+#endif
+
+    // As this frame is a key frame the next defaults to an inter frame.
     cm->frame_type = INTER_FRAME;
   } else {
     *frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY;
+
+#if CONFIG_MULTIPLE_ARF
+    /* Increment position in the coded frame sequence. */
+    if (cpi->multi_arf_enabled) {
+      ++cpi->sequence_number;
+      if (cpi->sequence_number >= cpi->frame_coding_order_period) {
+        cpi->sequence_number = 0;
+        cpi->frame_coding_order_period = cpi->new_frame_coding_order_period;
+        cpi->new_frame_coding_order_period = -1;
+      }
+      cpi->this_frame_weight = cpi->arf_weight[cpi->sequence_number];
+      assert(cpi->this_frame_weight >= 0);
+    }
+#endif
   }
 
   // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas.
@@ -3528,16 +3628,15 @@
   cm->last_width = cm->width;
   cm->last_height = cm->height;
 
-  // Dont increment frame counters if this was an altref buffer update not a real frame
+  // Don't increment frame counters if this was an altref buffer
+  // update not a real frame
   if (cm->show_frame) {
-    cm->current_video_frame++;
-    cpi->frames_since_key++;
+    ++cm->current_video_frame;
+    ++cpi->frames_since_key;
   }
 
   // reset to normal state now that we are done.
 
-
-
 #if 0
   {
     char filename[512];
@@ -3624,6 +3723,12 @@
          mb->update_mb_segmentation_data;
 }
 
+#if CONFIG_MULTIPLE_ARF
+int is_next_frame_arf(VP9_COMP *cpi) {
+  // Negative entry in frame_coding_order indicates an ARF at this position.
+  return cpi->frame_coding_order[cpi->sequence_number + 1] < 0 ? 1 : 0;
+}
+#endif
 
 int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
                             unsigned long *size, unsigned char *dest,
@@ -3633,6 +3738,7 @@
   struct vpx_usec_timer  cmptimer;
   YV12_BUFFER_CONFIG    *force_src_buffer = NULL;
   int i;
+  // FILE *fp_out = fopen("enc_frame_type.txt", "a");
 
   if (!cpi)
     return -1;
@@ -3644,37 +3750,90 @@
   cpi->mb.e_mbd.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV;
   set_mvcost(&cpi->mb);
 
-  // Should we code an alternate reference frame
-  if (cpi->oxcf.play_alternate &&
-      cpi->source_alt_ref_pending) {
-    if ((cpi->source = vp9_lookahead_peek(cpi->lookahead,
-                                          cpi->frames_till_gf_update_due))) {
+  // Should we code an alternate reference frame.
+  if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) {
+    int frames_to_arf;
+
+#if CONFIG_MULTIPLE_ARF
+    assert(!cpi->multi_arf_enabled ||
+           cpi->frame_coding_order[cpi->sequence_number] < 0);
+
+    if (cpi->multi_arf_enabled && (cpi->pass == 2))
+      frames_to_arf = (-cpi->frame_coding_order[cpi->sequence_number])
+        - cpi->next_frame_in_order;
+    else
+#endif
+      frames_to_arf = cpi->frames_till_gf_update_due;
+
+    assert(frames_to_arf < cpi->twopass.frames_to_key);
+
+    if ((cpi->source = vp9_lookahead_peek(cpi->lookahead, frames_to_arf))) {
+#if CONFIG_MULTIPLE_ARF
+      cpi->alt_ref_source[cpi->arf_buffered] = cpi->source;
+#else
       cpi->alt_ref_source = cpi->source;
+#endif
+
       if (cpi->oxcf.arnr_max_frames > 0) {
-        vp9_temporal_filter_prepare(cpi, cpi->frames_till_gf_update_due);
+        // Produce the filtered ARF frame.
+        // TODO(agrange) merge these two functions.
+        configure_arnr_filter(cpi, cm->current_video_frame + frames_to_arf,
+                              cpi->gfu_boost);
+        vp9_temporal_filter_prepare(cpi, frames_to_arf);
         force_src_buffer = &cpi->alt_ref_buffer;
       }
-      cm->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due;
+
+      cm->show_frame = 0;
       cpi->refresh_alt_ref_frame = 1;
       cpi->refresh_golden_frame = 0;
       cpi->refresh_last_frame = 0;
-      cm->show_frame = 0;
-      cpi->source_alt_ref_pending = FALSE;   // Clear Pending altf Ref flag.
       cpi->is_src_frame_alt_ref = 0;
+
+      // TODO(agrange) This needs to vary depending on where the next ARF is.
+      cm->frames_till_alt_ref_frame = frames_to_arf;
+
+#if CONFIG_MULTIPLE_ARF
+      if (!cpi->multi_arf_enabled)
+#endif
+        cpi->source_alt_ref_pending = FALSE;   // Clear Pending altf Ref flag.
     }
   }
 
   if (!cpi->source) {
+#if CONFIG_MULTIPLE_ARF
+    int i;
+#endif
     if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) {
       cm->show_frame = 1;
 
+#if CONFIG_MULTIPLE_ARF
+      // Is this frame the ARF overlay.
+      cpi->is_src_frame_alt_ref = FALSE;
+      for (i = 0; i < cpi->arf_buffered; ++i) {
+        if (cpi->source == cpi->alt_ref_source[i]) {
+          cpi->is_src_frame_alt_ref = TRUE;
+          cpi->refresh_golden_frame = TRUE;
+          break;
+        }
+      }
+#else
       cpi->is_src_frame_alt_ref = cpi->alt_ref_source
                                   && (cpi->source == cpi->alt_ref_source);
-
+#endif
       if (cpi->is_src_frame_alt_ref) {
-        cpi->refresh_last_frame = 0;
+        // Current frame is an ARF overlay frame.
+#if CONFIG_MULTIPLE_ARF
+        cpi->alt_ref_source[i] = NULL;
+#else
         cpi->alt_ref_source = NULL;
+#endif
+        // Don't refresh the last buffer for an ARF overlay frame. It will
+        // become the GF so preserve last as an alternative prediction option.
+        cpi->refresh_last_frame = 0;
       }
+#if CONFIG_MULTIPLE_ARF
+      ++cpi->next_frame_in_order;
+#endif
     }
   }
 
@@ -3684,6 +3843,23 @@
     *time_stamp = cpi->source->ts_start;
     *time_end = cpi->source->ts_end;
     *frame_flags = cpi->source->flags;
+
+    // fprintf(fp_out, "   Frame:%d", cm->current_video_frame);
+#if CONFIG_MULTIPLE_ARF
+    if (cpi->multi_arf_enabled) {
+      // fprintf(fp_out, "   seq_no:%d  this_frame_weight:%d",
+      //         cpi->sequence_number, cpi->this_frame_weight);
+    } else {
+      // fprintf(fp_out, "\n");
+    }
+#else
+    // fprintf(fp_out, "\n");
+#endif
+
+#if CONFIG_MULTIPLE_ARF
+    if ((cm->frame_type != KEY_FRAME) && (cpi->pass == 2))
+      cpi->source_alt_ref_pending = is_next_frame_arf(cpi);
+#endif
   } else {
     *size = 0;
     if (flush && cpi->pass == 1 && !cpi->twopass.first_pass_done) {
@@ -3691,6 +3867,7 @@
       cpi->twopass.first_pass_done = 1;
     }
 
+    // fclose(fp_out);
     return -1;
   }
 
@@ -3745,22 +3922,6 @@
   // Clear down mmx registers
   vp9_clear_system_state();  // __asm emms;
 
-  cm->frame_type = INTER_FRAME;
-  cm->frame_flags = *frame_flags;
-
-#if 0
-
-  if (cpi->refresh_alt_ref_frame) {
-    // cpi->refresh_golden_frame = 1;
-    cpi->refresh_golden_frame = 0;
-    cpi->refresh_last_frame = 0;
-  } else {
-    cpi->refresh_golden_frame = 0;
-    cpi->refresh_last_frame = 1;
-  }
-
-#endif
-
   /* find a free buffer for the new frame, releasing the reference previously
    * held.
    */
@@ -3767,11 +3928,38 @@
   cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
   cm->new_fb_idx = get_free_fb(cm);
 
+#if CONFIG_MULTIPLE_ARF
+  /* Set up the correct ARF frame. */
+  if (cpi->refresh_alt_ref_frame) {
+    ++cpi->arf_buffered;
+  }
+  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
+      (cpi->pass == 2)) {
+    cpi->alt_fb_idx = cpi->arf_buffer_idx[cpi->sequence_number];
+  }
+#endif
+
   /* Get the mapping of L/G/A to the reference buffer pool */
   cm->active_ref_idx[0] = cm->ref_frame_map[cpi->lst_fb_idx];
   cm->active_ref_idx[1] = cm->ref_frame_map[cpi->gld_fb_idx];
   cm->active_ref_idx[2] = cm->ref_frame_map[cpi->alt_fb_idx];
 
+#if 0  // CONFIG_MULTIPLE_ARF
+  if (cpi->multi_arf_enabled) {
+    fprintf(fp_out, "      idx(%d, %d, %d, %d) active(%d, %d, %d)",
+        cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx, cm->new_fb_idx,
+        cm->active_ref_idx[0], cm->active_ref_idx[1], cm->active_ref_idx[2]);
+    if (cpi->refresh_alt_ref_frame)
+      fprintf(fp_out, "  type:ARF");
+    if (cpi->is_src_frame_alt_ref)
+      fprintf(fp_out, "  type:OVERLAY[%d]", cpi->alt_fb_idx);
+    fprintf(fp_out, "\n");
+  }
+#endif
+
+  cm->frame_type = INTER_FRAME;
+  cm->frame_flags = *frame_flags;
+
   /* Reset the frame pointers to the current frame size */
   vp8_yv12_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx],
                                 cm->width, cm->height,
@@ -3814,7 +4002,6 @@
     cpi->refresh_golden_frame = 0;
     cpi->refresh_last_frame = 1;
     cm->frame_type = INTER_FRAME;
-
   }
 
   vpx_usec_timer_mark(&cmptimer);
@@ -3927,12 +4114,11 @@
         cpi->total_ssimg_v += v;
         cpi->total_ssimg_all += frame_all;
       }
-
     }
   }
 
 #endif
-
+  // fclose(fp_out);
   return 0;
 }
 
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -31,18 +31,22 @@
 
 // Experimental rate control switches
 #if CONFIG_ONESHOTQ
-#define ONE_SHOT_Q_ESTIMATE 1
-#define STRICT_ONE_SHOT_Q 1
-#define DISABLE_RC_LONG_TERM_MEM 1
+#define ONE_SHOT_Q_ESTIMATE 0
+#define STRICT_ONE_SHOT_Q 0
+#define DISABLE_RC_LONG_TERM_MEM 0
 #endif
+
 // #define SPEEDSTATS 1
+#if CONFIG_MULTIPLE_ARF
+// Set MIN_GF_INTERVAL to 1 for the full decomposition.
+#define MIN_GF_INTERVAL             2
+#else
 #define MIN_GF_INTERVAL             4
+#endif
 #define DEFAULT_GF_INTERVAL         7
 
 #define KEY_FRAME_CONTEXT 5
 
-#define MAX_LAG_BUFFERS 25
-
 #if CONFIG_COMP_INTERINTRA_PRED
 #define MAX_MODES 54
 #else
@@ -326,7 +330,11 @@
 
   struct lookahead_ctx    *lookahead;
   struct lookahead_entry  *source;
+#if CONFIG_MULTIPLE_ARF
+  struct lookahead_entry  *alt_ref_source[NUM_REF_FRAMES];
+#else
   struct lookahead_entry  *alt_ref_source;
+#endif
 
   YV12_BUFFER_CONFIG *Source;
   YV12_BUFFER_CONFIG *un_scaled_source;
@@ -345,6 +353,9 @@
   int lst_fb_idx;
   int gld_fb_idx;
   int alt_fb_idx;
+#if CONFIG_MULTIPLE_ARF
+  int alt_ref_fb_idx[NUM_REF_FRAMES - 3];
+#endif
   int refresh_last_frame;
   int refresh_golden_frame;
   int refresh_alt_ref_frame;
@@ -358,6 +369,12 @@
   unsigned int key_frame_frequency;
   unsigned int this_key_frame_forced;
   unsigned int next_key_frame_forced;
+#if CONFIG_MULTIPLE_ARF
+  // Position within a frame coding order (including any additional ARF frames).
+  unsigned int sequence_number;
+  // Next frame in naturally occurring order that has not yet been coded.
+  int next_frame_in_order;
+#endif
 
   // Ambient reconstruction err target for force key frames
   int ambient_err;
@@ -396,7 +413,6 @@
   double gf_rate_correction_factor;
 
   int frames_till_gf_update_due;      // Count down till next GF
-  int current_gf_interval;          // GF interval chosen when we coded the last GF
 
   int gf_overspend_bits;            // Total bits overspent becasue of GF boost (cumulative)
 
@@ -686,6 +702,19 @@
 
   int initial_width;
   int initial_height;
+
+#if CONFIG_MULTIPLE_ARF
+  // ARF tracking variables.
+  int multi_arf_enabled;
+  unsigned int frame_coding_order_period;
+  unsigned int new_frame_coding_order_period;
+  int frame_coding_order[MAX_LAG_BUFFERS * 2];
+  int arf_buffer_idx[MAX_LAG_BUFFERS * 3 / 2];
+  int arf_weight[MAX_LAG_BUFFERS];
+  int arf_buffered;
+  int this_frame_weight;
+  int max_arf_level;
+#endif
 } VP9_COMP;
 
 void vp9_encode_frame(VP9_COMP *cpi);
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -112,7 +112,7 @@
   const double q = vp9_convert_qindex_to_q(qindex);
   int enumerator = frame_type == KEY_FRAME ? 4000000 : 2500000;
 
-  // q based adjustment to baseline enumberator
+  // q based adjustment to baseline enumerator
   enumerator += (int)(enumerator * q) >> 12;
   return (int)(0.5 + (enumerator * correction_factor / q));
 }
@@ -300,7 +300,7 @@
 }
 
 
-//  Do the best we can to define the parameteres for the next GF based
+//  Do the best we can to define the parameters for the next GF based
 //  on what information we have available.
 //
 //  In this experimental code only two pass is supported
@@ -358,16 +358,13 @@
           (estimate_bits_at_q(1, q, cpi->common.MBs, 1.0)
            * cpi->last_boost) / 100;
       }
-
     } else {
       // If there is an active ARF at this location use the minimum
-      // bits on this frame even if it is a contructed arf.
+      // bits on this frame even if it is a constructed arf.
       // The active maximum quantizer insures that an appropriate
-      // number of bits will be spent if needed for contstructed ARFs.
+      // number of bits will be spent if needed for constructed ARFs.
       cpi->this_frame_target = 0;
     }
-
-    cpi->current_gf_interval = cpi->frames_till_gf_update_due;
   }
 }
 
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -486,7 +486,10 @@
     priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
     priv->vp8_cfg.experimental = experimental;
 
-    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
+    // TODO(agrange) Check the limits set on this buffer, or the check that is
+    // applied in vp8e_encode.
+    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
+//    priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
 
     if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
 
@@ -754,7 +757,7 @@
         vpx_codec_cx_pkt_t pkt;
         VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
 
-        /* Pack invisible frames with the next visisble frame */
+        /* Pack invisible frames with the next visible frame */
         if (!cpi->common.show_frame) {
           if (!ctx->pending_cx_data)
             ctx->pending_cx_data = cx_data;
--