Implement twopass support for the xiphrc system

This commit implements support for twopass encoding using the xiphrc
experimental rate control system. Most of the code and logic comes
from the theora project encoder.

Currently support is limited to the bitrate targeting mode of the
rate control system and while it does visibly improve quality and does
bring rate closer to the target than the one pass mode there's still
tuning and bug fixing to be done.

Change-Id: Iae0d65bbce5ddfbb95b436e2238a43d6100a23b3
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index a627800..d1cb67f 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -293,13 +293,16 @@
     ERROR("Option --tune=ssim is not currently supported in AV1.");
 
   if (cfg->g_pass == AOM_RC_LAST_PASS) {
+#if !CONFIG_XIPHRC
     const size_t packet_sz = sizeof(FIRSTPASS_STATS);
     const int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
     const FIRSTPASS_STATS *stats;
+#endif
 
     if (cfg->rc_twopass_stats_in.buf == NULL)
       ERROR("rc_twopass_stats_in.buf not set.");
 
+#if !CONFIG_XIPHRC
     if (cfg->rc_twopass_stats_in.sz % packet_sz)
       ERROR("rc_twopass_stats_in.sz indicates truncated packet.");
 
@@ -311,6 +314,7 @@
 
     if ((int)(stats->count + 0.5) != n_packets - 1)
       ERROR("rc_twopass_stats_in missing EOS stats packet");
+#endif
   }
 
 #if !CONFIG_AOM_HIGHBITDEPTH
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index bfd0090..aca6e0b 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -2187,6 +2187,7 @@
   cpi->od_rc.keyframe_rate = oxcf->key_freq;
   cpi->od_rc.goldenframe_rate = FIXED_GF_INTERVAL;
   cpi->od_rc.altref_rate = 25;
+  cpi->od_rc.firstpass_quant = 1;
   cpi->od_rc.bit_depth = cm->bit_depth;
   cpi->od_rc.minq = oxcf->best_allowed_q;
   cpi->od_rc.maxq = oxcf->worst_allowed_q;
@@ -2314,6 +2315,12 @@
   kf_list = fopen("kf_list.stt", "w");
 #endif
 
+#if CONFIG_XIPHRC
+  if (oxcf->pass == 2) {
+    cpi->od_rc.twopass_allframes_buf = oxcf->two_pass_stats_in.buf;
+    cpi->od_rc.twopass_allframes_buf_size = oxcf->two_pass_stats_in.sz;
+  }
+#else
   if (oxcf->pass == 1) {
     av1_init_first_pass(cpi);
   } else if (oxcf->pass == 2) {
@@ -2339,6 +2346,7 @@
 
     av1_init_second_pass(cpi);
   }
+#endif
 
   init_upsampled_ref_frame_bufs(cpi);
 
@@ -3972,9 +3980,11 @@
     }
   }
 
+#if !CONFIG_XIPHRC
   if (oxcf->pass == 2) {
     av1_set_target_rate(cpi);
   }
+#endif
 
   alloc_frame_mvs(cm, cm->new_fb_idx);
 
@@ -4705,7 +4715,7 @@
 
 #endif
 static void encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size,
-                                      uint8_t *dest,
+                                      uint8_t *dest, int skip_adapt,
                                       unsigned int *frame_flags) {
   AV1_COMMON *const cm = &cpi->common;
   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
@@ -4951,6 +4961,8 @@
   // Build the bitstream
   av1_pack_bitstream(cpi, dest, size);
 
+  if (skip_adapt) return;
+
 #if CONFIG_REFERENCE_BUFFER
   {
     int i;
@@ -5099,7 +5111,7 @@
 }
 
 static void Pass0Encode(AV1_COMP *cpi, size_t *size, uint8_t *dest,
-                        unsigned int *frame_flags) {
+                        int skip_adapt, unsigned int *frame_flags) {
 #if CONFIG_XIPHRC
   int64_t ip_count;
   int frame_type, is_golden, is_altref;
@@ -5132,12 +5144,13 @@
     av1_rc_get_one_pass_vbr_params(cpi);
   }
 #endif
-  encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+  encode_frame_to_data_rate(cpi, size, dest, skip_adapt, frame_flags);
 }
 
+#if !CONFIG_XIPHRC
 static void Pass2Encode(AV1_COMP *cpi, size_t *size, uint8_t *dest,
                         unsigned int *frame_flags) {
-  encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+  encode_frame_to_data_rate(cpi, size, dest, 0, frame_flags);
 
 #if CONFIG_EXT_REFS
   // Do not do post-encoding update for those frames that do not have a spot in
@@ -5151,6 +5164,7 @@
   av1_twopass_postencode_update(cpi);
 #endif  // CONFIG_EXT_REFS
 }
+#endif
 
 static void init_ref_frame_bufs(AV1_COMMON *cm) {
   int i;
@@ -5673,7 +5687,9 @@
   } else {
     *size = 0;
     if (flush && oxcf->pass == 1 && !cpi->twopass.first_pass_done) {
-#if !CONFIG_XIPHRC
+#if CONFIG_XIPHRC
+      od_enc_rc_2pass_out(&cpi->od_rc, cpi->output_pkt_list, 1);
+#else
       av1_end_first_pass(cpi); /* get last stats packet */
 #endif
       cpi->twopass.first_pass_done = 1;
@@ -5725,12 +5741,15 @@
   cpi->frame_flags = *frame_flags;
 
   if (oxcf->pass == 2) {
-#if !CONFIG_XIPHRC
+#if CONFIG_XIPHRC
+    if (od_enc_rc_2pass_in(&cpi->od_rc) < 0) return -1;
+  }
+#else
     av1_rc_get_second_pass_params(cpi);
-#endif
   } else if (oxcf->pass == 1) {
     set_frame_size(cpi);
   }
+#endif
 
   if (cpi->oxcf.pass != 0 || frame_is_intra_only(cm) == 1) {
     for (i = 0; i < TOTAL_REFS_PER_FRAME; ++i)
@@ -5749,6 +5768,23 @@
   }
 #endif
 
+#if CONFIG_XIPHRC
+  if (oxcf->pass == 1) {
+    size_t tmp;
+    if (cpi->od_rc.cur_frame == 0) Pass0Encode(cpi, &tmp, dest, 1, frame_flags);
+    cpi->od_rc.firstpass_quant = cpi->od_rc.target_quantizer;
+    Pass0Encode(cpi, &tmp, dest, 0, frame_flags);
+    od_enc_rc_2pass_out(&cpi->od_rc, cpi->output_pkt_list, 0);
+  } else if (oxcf->pass == 2) {
+    Pass0Encode(cpi, size, dest, 0, frame_flags);
+  } else {
+    if (cpi->od_rc.cur_frame == 0) {
+      size_t tmp;
+      Pass0Encode(cpi, &tmp, dest, 1, frame_flags);
+    }
+    Pass0Encode(cpi, size, dest, 0, frame_flags);
+  }
+#else
   if (oxcf->pass == 1) {
     cpi->td.mb.e_mbd.lossless[0] = is_lossless_requested(oxcf);
     av1_first_pass(cpi, source);
@@ -5756,8 +5792,9 @@
     Pass2Encode(cpi, size, dest, frame_flags);
   } else {
     // One pass encode
-    Pass0Encode(cpi, size, dest, frame_flags);
+    Pass0Encode(cpi, size, dest, 0, frame_flags);
   }
+#endif
 
   if (!cm->error_resilient_mode)
     cm->frame_contexts[cm->frame_context_idx] = *cm->fc;
diff --git a/av1/encoder/ratectrl_xiph.c b/av1/encoder/ratectrl_xiph.c
index 57361fe..9514a61 100644
--- a/av1/encoder/ratectrl_xiph.c
+++ b/av1/encoder/ratectrl_xiph.c
@@ -648,12 +648,15 @@
                                             int is_altref_frame, int frame_type,
                                             int *bottom_idx, int *top_idx) {
   int frame_subtype;
+  int64_t log_cur_scale;
   int lossy_quantizer_min;
   int lossy_quantizer_max;
   double mqp_i = OD_MQP_I;
   double mqp_p = OD_MQP_P;
   double mqp_gp = OD_MQP_GP;
   double mqp_ap = OD_MQP_AP;
+  int reservoir_frames;
+  int nframes[OD_FRAME_NSUBTYPES];
   int32_t mqp_Q12[OD_FRAME_NSUBTYPES];
   int64_t dqp_Q45[OD_FRAME_NSUBTYPES];
   /*Verify the closed-form frame type determination code matches what the
@@ -677,6 +680,75 @@
     OD_ASSERT(closed_form_altref == is_altref_frame);
     OD_ASSERT(closed_form_golden == is_golden_frame);
   }
+
+  log_cur_scale = (int64_t)rc->scalefilter[frame_type].y[0] << 33;
+
+  /*Count the various types and classes of frames.*/
+  reservoir_frames = frame_type_count(rc, nframes);
+  nframes[OD_I_FRAME] = od_rc_scale_drop(rc, OD_I_FRAME, nframes[OD_I_FRAME]);
+  nframes[OD_P_FRAME] = od_rc_scale_drop(rc, OD_P_FRAME, nframes[OD_P_FRAME]);
+  nframes[OD_GOLDEN_P_FRAME] =
+      od_rc_scale_drop(rc, OD_GOLDEN_P_FRAME, nframes[OD_GOLDEN_P_FRAME]);
+  nframes[OD_ALTREF_P_FRAME] =
+      od_rc_scale_drop(rc, OD_ALTREF_P_FRAME, nframes[OD_ALTREF_P_FRAME]);
+
+  switch (rc->twopass_state) {
+    default: break;
+    case 1: {
+      /*Pass 1 mode: use a fixed qi value.*/
+      return rc->firstpass_quant;
+    } break;
+    case 2: {
+      int i;
+      int64_t scale_sum[OD_FRAME_NSUBTYPES];
+      int qti;
+      /*Pass 2 mode: we know exactly how much of each frame type there is in
+         the current buffer window, and have estimates for the scales.*/
+      for (i = 0; i < OD_FRAME_NSUBTYPES; i++) {
+        nframes[i] = rc->nframes[i];
+        nframes[i] = rc->nframes[i];
+        scale_sum[i] = rc->scale_sum[i];
+      }
+      /*If we're not using the same frame type as in pass 1 (because someone
+         changed the keyframe interval), remove that scale estimate.
+        We'll add in a replacement for the correct frame type below.*/
+      qti = rc->cur_metrics.frame_type;
+      if (qti != frame_type) {
+        nframes[qti]--;
+        scale_sum[qti] -= od_bexp64_q24(rc->cur_metrics.log_scale);
+      }
+      /*Compute log_scale estimates for each frame type from the pass-1 scales
+         we measured in the current window.*/
+      for (qti = 0; qti < OD_FRAME_NSUBTYPES; qti++) {
+        rc->log_scale[qti] = nframes[qti] > 0
+                                 ? od_blog64(scale_sum[qti]) -
+                                       od_blog64(nframes[qti]) - OD_Q57(24)
+                                 : -rc->log_npixels;
+      }
+      /*If we're not using the same frame type as in pass 1, add a scale
+         estimate for the corresponding frame using the current low-pass
+         filter value.
+        This is mostly to ensure we have a valid estimate even when pass 1 had
+         no frames of this type in the buffer window.
+        TODO: We could also plan ahead and figure out how many keyframes we'll
+         be forced to add in the current buffer window.*/
+      qti = rc->cur_metrics.frame_type;
+      if (qti != frame_type) {
+        int64_t scale;
+        scale = rc->log_scale[frame_type] < OD_Q57(23)
+                    ? od_bexp64(rc->log_scale[frame_type] + OD_Q57(24))
+                    : 0x7FFFFFFFFFFFLL;
+        scale *= nframes[frame_type];
+        nframes[frame_type]++;
+        scale += od_bexp64_q24(log_cur_scale >> 33);
+        rc->log_scale[frame_type] =
+            od_blog64(scale) - od_blog64(nframes[qti]) - OD_Q57(24);
+      } else {
+        log_cur_scale = (int64_t)rc->cur_metrics.log_scale << 33;
+      }
+    } break;
+  }
+
   /*Quantizer selection sticks to the codable, lossy portion of the quantizer
     range.*/
   lossy_quantizer_min = convert_to_ac_quant(rc->minq, rc->bit_depth);
@@ -762,8 +834,6 @@
     }
   } else {
     int clamp;
-    int reservoir_frames;
-    int nframes[OD_FRAME_NSUBTYPES];
     int64_t rate_bias;
     int64_t rate_total;
     int base_quantizer;
@@ -777,20 +847,6 @@
        before the last keyframe in our current buffer window (after the current
        frame), or the end of the buffer window, whichever comes first.*/
     /*Single pass only right now.*/
-    /*Count the various types and classes of frames.*/
-    reservoir_frames = frame_type_count(rc, nframes);
-    /*Downgrade the delta frame rate to correspond to the recent drop count
-       history.
-      At the moment, drop frames can only be one frame type at a time:
-       B-frames only if B-frames are in use, otherwise P-frames only.
-      In the event this is extended later, the drop tracking watches all
-       frame types.*/
-    nframes[OD_I_FRAME] = od_rc_scale_drop(rc, OD_I_FRAME, nframes[OD_I_FRAME]);
-    nframes[OD_P_FRAME] = od_rc_scale_drop(rc, OD_P_FRAME, nframes[OD_P_FRAME]);
-    nframes[OD_GOLDEN_P_FRAME] =
-        od_rc_scale_drop(rc, OD_GOLDEN_P_FRAME, nframes[OD_GOLDEN_P_FRAME]);
-    nframes[OD_ALTREF_P_FRAME] =
-        od_rc_scale_drop(rc, OD_ALTREF_P_FRAME, nframes[OD_ALTREF_P_FRAME]);
     /*If we've been missing our target, add a penalty term.*/
     rate_bias = (rc->rate_bias / (rc->cur_frame + 1000)) * reservoir_frames;
     /*rate_total is the total bits available over the next
@@ -971,9 +1027,10 @@
   }
   *bottom_idx = lossy_quantizer_min;
   *top_idx = lossy_quantizer_max;
-  return av1_qindex_from_ac(
+  rc->target_quantizer = av1_qindex_from_ac(
       OD_CLAMPI(lossy_quantizer_min, rc->target_quantizer, lossy_quantizer_max),
       rc->bit_depth);
+  return rc->target_quantizer;
 }
 
 int od_enc_rc_update_state(od_rc_state *rc, int64_t bits, int is_golden_frame,
@@ -996,7 +1053,6 @@
       bits = 0;
       ++rc->prev_drop_count[frame_subtype];
     } else {
-      od_iir_bessel2 *f;
       int64_t log_bits;
       int64_t log_qexp;
       /*Compute the estimated scale factor for this frame type.*/
@@ -1004,6 +1060,27 @@
       log_qexp = od_blog64(rc->target_quantizer);
       log_qexp = (log_qexp >> 6) * (rc->exp[frame_type]);
       log_scale = OD_MINI(log_bits - rc->log_npixels + log_qexp, OD_Q57(16));
+    }
+
+    switch (rc->twopass_state) {
+      case 1: {
+        int golden, altref;
+        int64_t ipc;
+        rc->cur_metrics.frame_type =
+            od_frame_type(rc, rc->cur_frame, &golden, &altref, &ipc);
+        /*Pass 1 mode: save the metrics for this frame.*/
+        rc->cur_metrics.log_scale = od_q57_to_q24(log_scale);
+      } break;
+      case 2: {
+        /*Pass 2 mode:*/
+        int m_frame_type = rc->cur_metrics.frame_type;
+        rc->nframes[m_frame_type]--;
+        rc->scale_sum[m_frame_type] -= od_bexp64_q24(rc->cur_metrics.log_scale);
+      } break;
+    }
+
+    if (bits > 0) {
+      od_iir_bessel2 *f;
       /*If this is the first example of the given frame type we've
          seen, we immediately replace the default scale factor guess
          with the estimate we just computed using the first frame.*/
@@ -1011,17 +1088,13 @@
         f = rc->scalefilter + frame_type;
         f->y[1] = f->y[0] = f->x[1] = f->x[0] = od_q57_to_q24(log_scale);
         rc->log_scale[frame_type] = log_scale;
-        /*P frame stats are duplicated into a OD_GOLDEN_P_FRAME slot
-           for convenience in rate estimation code.*/
-        if (frame_type == OD_P_FRAME)
-          rc->log_scale[OD_GOLDEN_P_FRAME] = log_scale;
       } else {
         /*Lengthen the time constant for the inter filters as we collect more
            frame statistics, until we reach our target.*/
-        if (frame_type == OD_P_FRAME &&
+        if (frame_type != OD_I_FRAME &&
             rc->inter_p_delay < rc->inter_delay_target &&
-            rc->frame_count[OD_P_FRAME] >= rc->inter_p_delay) {
-          od_iir_bessel2_reinit(&rc->scalefilter[OD_P_FRAME],
+            rc->frame_count[frame_type] >= rc->inter_p_delay) {
+          od_iir_bessel2_reinit(&rc->scalefilter[frame_type],
                                 ++rc->inter_p_delay);
         }
         /*Update the low-pass scale filter for this frame type
@@ -1057,7 +1130,7 @@
         rc->prev_drop_count[frame_subtype] = 0;
       }
       /*Increment the frame count for filter adaptation purposes.*/
-      if (rc->frame_count[frame_type] < INT_MAX) ++rc->frame_count[frame_type];
+      if (!rc->twopass_state) rc->frame_count[frame_type]++;
     }
     rc->reservoir_fullness += rc->bits_per_frame - bits;
     /*If we're too quick filling the buffer and overflow is capped,
@@ -1075,3 +1148,101 @@
   }
   return dropped;
 }
+
+static inline void od_rc_buffer_val(od_rc_state *rc, int64_t val, int bytes) {
+  while (bytes-- > 0) {
+    rc->twopass_buffer[rc->twopass_buffer_bytes++] = (uint8_t)(val & 0xFF);
+    val >>= 8;
+  }
+}
+
+static inline int64_t od_rc_unbuffer_val(od_rc_state *rc, int bytes) {
+  int64_t ret = 0;
+  int shift = 0;
+  while (bytes-- > 0) {
+    ret |= ((int64_t)rc->twopass_buffer[rc->twopass_buffer_bytes++]) << shift;
+    shift += 8;
+  }
+  return ret;
+}
+
+int od_enc_rc_2pass_out(od_rc_state *rc, struct aom_codec_pkt_list *pkt_list,
+                        int summary) {
+  int i;
+  struct aom_codec_cx_pkt pkt;
+  rc->twopass_buffer = rc->firstpass_buffer;
+  rc->twopass_buffer_bytes = 0;
+  if (!rc->twopass_state) {
+    rc->twopass_state = 1;
+    for (i = 0; i < OD_FRAME_NSUBTYPES; i++) {
+      rc->frame_count[i] = 0;
+      rc->exp[i] = 0;
+      rc->scale_sum[i] = 0;
+    }
+  }
+  if (summary) {
+    od_rc_buffer_val(rc, OD_RC_2PASS_MAGIC, 4);
+    od_rc_buffer_val(rc, OD_RC_2PASS_VERSION, 1);
+    for (i = 0; i < OD_FRAME_NSUBTYPES; i++) {
+      od_rc_buffer_val(rc, rc->frame_count[i], 4);
+      od_rc_buffer_val(rc, rc->exp[i], 4);
+      od_rc_buffer_val(rc, rc->scale_sum[i], 8);
+    }
+  } else {
+    int frame_type = rc->cur_metrics.frame_type;
+    rc->scale_sum[frame_type] += od_bexp64_q24(rc->cur_metrics.log_scale);
+    rc->frame_count[frame_type]++;
+    od_rc_buffer_val(rc, rc->cur_metrics.frame_type, 1);
+    od_rc_buffer_val(rc, rc->cur_metrics.log_scale, 4);
+  }
+  pkt.data.twopass_stats.buf = rc->firstpass_buffer;
+  pkt.data.twopass_stats.sz = rc->twopass_buffer_bytes;
+  pkt.kind = AOM_CODEC_STATS_PKT;
+  aom_codec_pkt_list_add(pkt_list, &pkt);
+  return 0;
+}
+
+int od_enc_rc_2pass_in(od_rc_state *rc) {
+  /* Enable pass 2 mode if this is the first call. */
+  if (rc->twopass_state == 0) {
+    uint32_t i, total_frames = 0;
+
+    if (!rc->twopass_allframes_buf ||
+        rc->twopass_allframes_buf_size < OD_RC_2PASS_MIN)
+      return -1;
+
+    /* Find summary packet at the end */
+    rc->twopass_buffer = rc->twopass_allframes_buf;
+    rc->twopass_buffer +=
+        rc->twopass_allframes_buf_size - OD_RC_2PASS_SUMMARY_SZ;
+    rc->twopass_buffer_bytes = 0;
+
+    if (od_rc_unbuffer_val(rc, 4) != OD_RC_2PASS_MAGIC) return -1;
+    if (od_rc_unbuffer_val(rc, 1) != OD_RC_2PASS_VERSION) return -1;
+
+    for (i = 0; i < OD_FRAME_NSUBTYPES; i++) {
+      rc->frame_count[i] = od_rc_unbuffer_val(rc, 4);
+      rc->exp[i] = od_rc_unbuffer_val(rc, 4);
+      rc->scale_sum[i] = od_rc_unbuffer_val(rc, 8);
+      rc->nframes[i] = rc->frame_count[i];
+      total_frames += rc->frame_count[i];
+    }
+
+    if (total_frames < 1) return -1;
+
+    if (total_frames * OD_RC_2PASS_PACKET_SZ > rc->twopass_allframes_buf_size)
+      return -1;
+
+    od_enc_rc_reset(rc);
+
+    /* Everything looks ok */
+    rc->twopass_buffer = rc->twopass_allframes_buf;
+    rc->twopass_state = 2;
+    rc->twopass_buffer_bytes = 0;
+  }
+
+  rc->cur_metrics.frame_type = od_rc_unbuffer_val(rc, 1);
+  rc->cur_metrics.log_scale = od_rc_unbuffer_val(rc, 4);
+
+  return 0;
+}
diff --git a/av1/encoder/ratectrl_xiph.h b/av1/encoder/ratectrl_xiph.h
index d5df984..a4a9052 100644
--- a/av1/encoder/ratectrl_xiph.h
+++ b/av1/encoder/ratectrl_xiph.h
@@ -13,6 +13,7 @@
 #define _ratectrl_xiph_H (1)
 
 #include "av1/encoder/ratectrl.h"
+#include "aom/internal/aom_codec_internal.h"
 
 /*Frame types.*/
 #define OD_I_FRAME (0)
@@ -48,6 +49,12 @@
    conversion (6.235 * 2^45) */
 #define OD_LOG_QUANTIZER_OFFSET_Q45 (0x0000C7851EB851ECLL)
 
+#define OD_RC_2PASS_MAGIC (0x53015641) /* [A, V, 1, S] in little endian */
+#define OD_RC_2PASS_SUMMARY_SZ (4 + 1 + (4 + 4 + 8) * OD_FRAME_NSUBTYPES)
+#define OD_RC_2PASS_PACKET_SZ (1 + 4)
+#define OD_RC_2PASS_MIN (OD_RC_2PASS_PACKET_SZ + OD_RC_2PASS_SUMMARY_SZ)
+#define OD_RC_2PASS_VERSION (1)
+
 /*A 2nd order low-pass Bessel follower.
   We use this for rate control because it has fast reaction time, but is
    critically damped.*/
@@ -58,6 +65,14 @@
   int32_t y[2];
 } od_iir_bessel2;
 
+/* The 2-pass metrics associated with a single frame. */
+typedef struct od_frame_metrics {
+  /*The log base 2 of the scale factor for this frame in Q24 format.*/
+  int64_t log_scale;
+  /*The frame type from pass 1.*/
+  unsigned frame_type : 1;
+} od_frame_metrics;
+
 /*Rate control setup and working state information.*/
 typedef struct od_rc_state {
   /* Image format */
@@ -83,6 +98,26 @@
   int maxq;
   /* Min Q */
   int minq;
+  /* Quantizer to use for the first pass */
+  int firstpass_quant;
+
+  /* 2-pass metrics */
+  od_frame_metrics cur_metrics;
+
+  /* 2-pass state */
+  int64_t scale_sum[OD_FRAME_NSUBTYPES];
+  int nframes[OD_FRAME_NSUBTYPES];
+
+  /* 2-pass bytestream reader/writer context */
+  uint8_t *twopass_buffer;
+  int twopass_buffer_bytes;
+
+  /* Pass 1 stats packet storage */
+  uint8_t firstpass_buffer[OD_RC_2PASS_SUMMARY_SZ];
+
+  /* Every state packet from the first pass in a single buffer */
+  uint8_t *twopass_allframes_buf;
+  size_t twopass_allframes_buf_size;
 
   /* Actual returned quantizer */
   int target_quantizer;
@@ -157,4 +192,9 @@
 
 int od_enc_rc_resize(od_rc_state *rc);
 
+int od_enc_rc_2pass_out(od_rc_state *rc, struct aom_codec_pkt_list *pkt_list,
+                        int summary);
+
+int od_enc_rc_2pass_in(od_rc_state *rc);
+
 #endif
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 81ef54f..69076a8 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -567,7 +567,11 @@
 
   if (oxcf->mode == REALTIME)
     set_rt_speed_feature(cpi, sf, oxcf->speed, oxcf->content);
-  else if (oxcf->mode == GOOD)
+  else if (oxcf->mode == GOOD
+#if CONFIG_XIPHRC
+           || oxcf->pass == 1
+#endif
+           )
     set_good_speed_feature(cpi, cm, sf, oxcf->speed);
 
   // sf->partition_search_breakout_dist_thr is set assuming max 64x64
@@ -607,9 +611,11 @@
     }
   }
 
+#if !CONFIG_XIPHRC
   // Slow quant, dct and trellis not worthwhile for first pass
   // so make sure they are always turned off.
   if (oxcf->pass == 1) sf->optimize_coefficients = 0;
+#endif
 
   // No recode for 1 pass.
   if (oxcf->pass == 0) {