shithub: libvpx

Download patch

ref: 12345cb3913a2b646c46b532dad3aa6a116a8be4
parent: 30226a658f7e9c36aa8bb259af167b07ab4e2f25
author: Dmitry Kovalev <dkovalev@google.com>
date: Wed Jun 5 16:56:37 EDT 2013

Moving bits from compressed header to uncompressed one.

Bits moved: refresh_frame_flags, active_ref_idx[], ref_frame_sign_bias[],
allow_high_precision_mv, mcomp_filter_type, ref_pred_probs[].

Derf results: +0.040%

Change-Id: I011f43c7eac0371d533b255fd99aee5ed75b85a5

--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -10,17 +10,16 @@
 
 
 #include "./vpx_config.h"
-#include "vp9/common/vp9_blockd.h"
 #include "vpx_mem/vpx_mem.h"
-#include "vp9/common/vp9_onyxc_int.h"
-#include "vp9/common/vp9_findnearmv.h"
+#include "vp9/common/vp9_blockd.h"
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_entropymv.h"
+#include "vp9/common/vp9_findnearmv.h"
+#include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_systemdependent.h"
 
-
-void vp9_update_mode_info_border(VP9_COMMON *cpi, MODE_INFO *mi) {
-  const int stride = cpi->mode_info_stride;
+void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi) {
+  const int stride = cm->mode_info_stride;
   int i;
 
   // Clear down top border row
@@ -27,24 +26,23 @@
   vpx_memset(mi, 0, sizeof(MODE_INFO) * stride);
 
   // Clear left border column
-  for (i = 1; i < cpi->mi_rows + 1; i++)
+  for (i = 1; i < cm->mi_rows + 1; i++)
     vpx_memset(&mi[i * stride], 0, sizeof(MODE_INFO));
 }
 
-void vp9_update_mode_info_in_image(VP9_COMMON *cpi, MODE_INFO *mi) {
+void vp9_update_mode_info_in_image(VP9_COMMON *cm, MODE_INFO *mi) {
   int i, j;
-  MODE_INFO *ptr;
 
   // For each in image mode_info element set the in image flag to 1
-  for (i = 0; i < cpi->mi_rows; i++) {
-    ptr = mi;
-    for (j = 0; j < cpi->mi_cols; j++) {
+  for (i = 0; i < cm->mi_rows; i++) {
+    MODE_INFO *ptr = mi;
+    for (j = 0; j < cm->mi_cols; j++) {
       ptr->mbmi.mb_in_image = 1;
       ptr++;  // Next element in the row
     }
 
     // Step over border element at start of next row
-    mi += cpi->mode_info_stride;
+    mi += cm->mode_info_stride;
   }
 }
 
@@ -69,6 +67,30 @@
   oci->above_seg_context = 0;
 }
 
+static void set_mb_mi(VP9_COMMON *cm, int aligned_width, int aligned_height) {
+  cm->mb_cols = aligned_width >> 4;
+  cm->mb_rows = aligned_height >> 4;
+  cm->MBs = cm->mb_rows * cm->mb_cols;
+
+  cm->mi_cols = aligned_width >> LOG2_MI_SIZE;
+  cm->mi_rows = aligned_height >> LOG2_MI_SIZE;
+  cm->mode_info_stride = cm->mi_cols + 1;
+}
+
+static void setup_mi(VP9_COMMON *cm) {
+  cm->mi = cm->mip + cm->mode_info_stride + 1;
+  cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
+
+  vpx_memset(cm->mip, 0,
+             cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
+
+  vp9_update_mode_info_border(cm, cm->mip);
+  vp9_update_mode_info_in_image(cm, cm->mi);
+
+  vp9_update_mode_info_border(cm, cm->prev_mip);
+  vp9_update_mode_info_in_image(cm, cm->prev_mi);
+}
+
 int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
   int i, mi_cols;
 
@@ -75,17 +97,16 @@
   // Our internal buffers are always multiples of 16
   const int aligned_width = multiple16(width);
   const int aligned_height = multiple16(height);
+  const int ss_x = oci->subsampling_x;
+  const int ss_y = oci->subsampling_y;
 
   vp9_free_frame_buffers(oci);
 
   for (i = 0; i < NUM_YV12_BUFFERS; i++) {
     oci->fb_idx_ref_cnt[i] = 0;
-    if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
-                               oci->subsampling_x, oci->subsampling_y,
-                               VP9BORDERINPIXELS) < 0) {
-      vp9_free_frame_buffers(oci);
-      return 1;
-    }
+    if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height, ss_x, ss_y,
+                               VP9BORDERINPIXELS) < 0)
+      goto fail;
   }
 
   oci->new_fb_idx = NUM_YV12_BUFFERS - 1;
@@ -99,48 +120,29 @@
     oci->fb_idx_ref_cnt[i] = 1;
   }
 
-  if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
-                             oci->subsampling_x, oci->subsampling_y,
-                             VP9BORDERINPIXELS) < 0) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16, ss_x, ss_y,
+                             VP9BORDERINPIXELS) < 0)
+    goto fail;
 
-  if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
-                             oci->subsampling_x, oci->subsampling_y,
-                             VP9BORDERINPIXELS) < 0) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height, ss_x, ss_y,
+                             VP9BORDERINPIXELS) < 0)
+    goto fail;
 
-  oci->mb_rows = aligned_height >> 4;
-  oci->mi_rows = aligned_height >> LOG2_MI_SIZE;
-  oci->mb_cols = aligned_width >> 4;
-  oci->mi_cols = aligned_width >> LOG2_MI_SIZE;
-  oci->MBs = oci->mb_rows * oci->mb_cols;
-  oci->mode_info_stride = oci->mi_cols + 1;
+  set_mb_mi(oci, aligned_width, aligned_height);
+
+  // Allocation
   oci->mip = vpx_calloc(oci->mode_info_stride * (oci->mi_rows + 1),
                         sizeof(MODE_INFO));
+  if (!oci->mip)
+    goto fail;
 
-  if (!oci->mip) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
-
-  oci->mi = oci->mip + oci->mode_info_stride + 1;
-
-  /* allocate memory for last frame MODE_INFO array */
-
   oci->prev_mip = vpx_calloc(oci->mode_info_stride * (oci->mi_rows + 1),
                              sizeof(MODE_INFO));
+  if (!oci->prev_mip)
+    goto fail;
 
-  if (!oci->prev_mip) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  setup_mi(oci);
 
-  oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
-
   // FIXME(jkoleszar): allocate subsampled arrays for U/V once subsampling
   // information is exposed at this level
   mi_cols = mi_cols_aligned_to_sb(oci);
@@ -150,26 +152,22 @@
 #else
   oci->above_context[0] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * 6 * mi_cols, 1);
 #endif
-  if (!oci->above_context[0]) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  if (!oci->above_context[0])
+    goto fail;
+
   for (i = 1; i < MAX_MB_PLANE; i++)
     oci->above_context[i] =
         oci->above_context[0] + i * sizeof(ENTROPY_CONTEXT) * 2 * mi_cols;
 
-  oci->above_seg_context =
-    vpx_calloc(sizeof(PARTITION_CONTEXT) * mi_cols, 1);
+  oci->above_seg_context = vpx_calloc(sizeof(PARTITION_CONTEXT) * mi_cols, 1);
+  if (!oci->above_seg_context)
+    goto fail;
 
-  if (!oci->above_seg_context) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
-
-  vp9_update_mode_info_border(oci, oci->mip);
-  vp9_update_mode_info_in_image(oci, oci->mi);
-
   return 0;
+
+ fail:
+  vp9_free_frame_buffers(oci);
+  return 1;
 }
 
 void vp9_setup_version(VP9_COMMON *cm) {
@@ -222,27 +220,10 @@
   vp9_entropy_mv_init();
 }
 
-
 void vp9_update_frame_size(VP9_COMMON *cm) {
   const int aligned_width = multiple16(cm->width);
   const int aligned_height = multiple16(cm->height);
 
-  cm->mb_rows = aligned_height >> 4;
-  cm->mb_cols = aligned_width >> 4;
-
-  cm->mi_rows = aligned_height >> LOG2_MI_SIZE;
-  cm->mi_cols = aligned_width >> LOG2_MI_SIZE;
-
-  cm->MBs = cm->mb_rows * cm->mb_cols;
-  cm->mode_info_stride = cm->mi_cols + 1;
-  cm->mi = cm->mip + cm->mode_info_stride + 1;
-  cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
-
-  memset(cm->mip, 0,
-         cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
-  vp9_update_mode_info_border(cm, cm->mip);
-  vp9_update_mode_info_in_image(cm, cm->mi);
-
-  vp9_update_mode_info_border(cm, cm->prev_mip);
-  vp9_update_mode_info_in_image(cm, cm->prev_mi);
+  set_mb_mi(cm, aligned_width, aligned_height);
+  setup_mi(cm);
 }
--- a/vp9/common/vp9_alloccommon.h
+++ b/vp9/common/vp9_alloccommon.h
@@ -14,6 +14,8 @@
 
 #include "vp9/common/vp9_onyxc_int.h"
 
+void vp9_initialize_common();
+
 void vp9_update_mode_info_border(VP9_COMMON *cpi, MODE_INFO *mi);
 void vp9_update_mode_info_in_image(VP9_COMMON *cpi, MODE_INFO *mi);
 
--- a/vp9/common/vp9_enums.h
+++ b/vp9/common/vp9_enums.h
@@ -16,8 +16,6 @@
 #define LOG2_MI_SIZE 3
 
 #define MI_SIZE (1 << LOG2_MI_SIZE)
-#define MI_UV_SIZE (1 << (LOG2_MI_SIZE - 1))
-
 #define MI_MASK ((64 >> LOG2_MI_SIZE) - 1)
 
 typedef enum BLOCK_SIZE_TYPE {
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -26,8 +26,6 @@
 
 /* Create/destroy static data structures. */
 
-void vp9_initialize_common(void);
-
 // Define the number of candidate reference buffers.
 #define NUM_REF_FRAMES 8
 #define NUM_REF_FRAMES_LG2 3
@@ -248,9 +246,6 @@
   int near_boffset[3];
   int version;
 
-#ifdef PACKET_TESTING
-  VP9_HEADER oh;
-#endif
   double bitrate;
   double framerate;
 
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -530,25 +530,6 @@
                        "Failed to allocate bool decoder %d", 1);
 }
 
-static void init_frame(VP9D_COMP *pbi) {
-  VP9_COMMON *const pc = &pbi->common;
-  MACROBLOCKD *const xd = &pbi->mb;
-
-  if (pc->frame_type == KEY_FRAME) {
-    vp9_setup_past_independence(pc, xd);
-    // All buffers are implicitly updated on key frames.
-    pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
-  } else if (pc->error_resilient_mode) {
-    vp9_setup_past_independence(pc, xd);
-  }
-
-  xd->mode_info_context = pc->mi;
-  xd->prev_mode_info_context = pc->prev_mi;
-  xd->frame_type = pc->frame_type;
-  xd->mode_info_context->mbmi.mode = DC_PRED;
-  xd->mode_info_stride = pc->mode_info_stride;
-}
-
 static void read_coef_probs_common(FRAME_CONTEXT *fc, TX_SIZE tx_size,
                                    vp9_reader *r) {
   const int entropy_nodes_update = UNCONSTRAINED_NODES;
@@ -646,22 +627,6 @@
   }
 }
 
-static void setup_pred_probs(VP9_COMMON *pc, vp9_reader *r) {
-  // Read common prediction model status flag probability updates for the
-  // reference frame
-  if (pc->frame_type == KEY_FRAME) {
-    // Set the prediction probabilities to defaults
-    pc->ref_pred_probs[0] = DEFAULT_PRED_PROB_0;
-    pc->ref_pred_probs[1] = DEFAULT_PRED_PROB_1;
-    pc->ref_pred_probs[2] = DEFAULT_PRED_PROB_2;
-  } else {
-    int i;
-    for (i = 0; i < PREDICTION_PROBS; ++i)
-      if (vp9_read_bit(r))
-        pc->ref_pred_probs[i] = vp9_read_prob(r);
-  }
-}
-
 static void setup_loopfilter(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
@@ -716,9 +681,10 @@
     vp9_init_dequantizer(cm);
 }
 
-static INTERPOLATIONFILTERTYPE read_mcomp_filter_type(vp9_reader *r) {
-  return vp9_read_bit(r) ? SWITCHABLE
-                         : vp9_read_literal(r, 2);
+static INTERPOLATIONFILTERTYPE read_interp_filter_type(
+    struct vp9_read_bit_buffer *rb) {
+  return vp9_rb_read_bit(rb) ? SWITCHABLE
+                             : vp9_rb_read_literal(rb, 2);
 }
 
 static void read_frame_size(VP9_COMMON *cm,
@@ -757,8 +723,8 @@
       if (vp9_alloc_frame_buffers(pc, width, height))
         vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                            "Failed to allocate frame buffers");
-        pbi->initial_width = width;
-        pbi->initial_height = height;
+      pbi->initial_width = width;
+      pbi->initial_height = height;
     } else {
       if (width > pbi->initial_width)
         vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
@@ -776,6 +742,10 @@
 
     vp9_update_frame_size(pc);
   }
+
+  vp9_realloc_frame_buffer(&pc->yv12_fb[pc->new_fb_idx], pc->width, pc->height,
+                           pc->subsampling_x, pc->subsampling_y,
+                           VP9BORDERINPIXELS);
 }
 
 static void update_frame_context(FRAME_CONTEXT *fc) {
@@ -784,10 +754,8 @@
   vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob);
   vp9_copy(fc->pre_partition_prob, fc->partition_prob);
   fc->pre_nmvc = fc->nmvc;
-  vp9_copy(fc->pre_switchable_interp_prob,
-           fc->switchable_interp_prob);
-  vp9_copy(fc->pre_inter_mode_probs,
-           fc->inter_mode_probs);
+  vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob);
+  vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs);
 
   vp9_zero(fc->coef_counts);
   vp9_zero(fc->eob_branch_counts);
@@ -909,8 +877,9 @@
 size_t read_uncompressed_header(VP9D_COMP *pbi,
                                 struct vp9_read_bit_buffer *rb) {
   VP9_COMMON *const cm = &pbi->common;
+  MACROBLOCKD *const xd = &pbi->mb;
 
-  int scaling_active;
+  int scaling_active, i;
   cm->last_frame_type = cm->frame_type;
   cm->frame_type = (FRAME_TYPE) vp9_rb_read_bit(rb);
   cm->version = vp9_rb_read_literal(rb, 3);
@@ -923,22 +892,13 @@
     if (vp9_rb_read_literal(rb, 8) != SYNC_CODE_0 ||
         vp9_rb_read_literal(rb, 8) != SYNC_CODE_1 ||
         vp9_rb_read_literal(rb, 8) != SYNC_CODE_2) {
-        vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
-                           "Invalid frame sync code");
+      vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
+                         "Invalid frame sync code");
     }
   }
 
   setup_frame_size(pbi, scaling_active, rb);
 
-  if (!cm->show_frame) {
-    cm->intra_only = vp9_rb_read_bit(rb);
-  } else {
-    cm->intra_only = 0;
-  }
-
-  cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
-  cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
-
   cm->error_resilient_mode = vp9_rb_read_bit(rb);
   if (!cm->error_resilient_mode) {
     cm->reset_frame_context = vp9_rb_read_bit(rb);
@@ -950,6 +910,44 @@
     cm->frame_parallel_decoding_mode = 1;
   }
 
+  if (cm->frame_type == KEY_FRAME) {
+    vp9_setup_past_independence(cm, xd);
+
+    pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
+
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
+      cm->active_ref_idx[i] = cm->new_fb_idx;
+
+    cm->ref_pred_probs[0] = DEFAULT_PRED_PROB_0;
+    cm->ref_pred_probs[1] = DEFAULT_PRED_PROB_1;
+    cm->ref_pred_probs[2] = DEFAULT_PRED_PROB_2;
+  } else {
+    if (cm->error_resilient_mode)
+      vp9_setup_past_independence(cm, xd);
+
+    pbi->refresh_frame_flags = vp9_rb_read_literal(rb, NUM_REF_FRAMES);
+
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
+      const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LG2);
+      cm->active_ref_idx[i] = cm->ref_frame_map[ref];
+      vp9_setup_scale_factors(cm, i);
+    }
+
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
+      cm->ref_frame_sign_bias[i + 1] = vp9_rb_read_bit(rb);
+
+    for (i = 0; i < PREDICTION_PROBS; ++i)
+      if (vp9_rb_read_bit(rb))
+        cm->ref_pred_probs[i] = vp9_rb_read_literal(rb, 8);
+
+    xd->allow_high_precision_mv = vp9_rb_read_bit(rb);
+    cm->mcomp_filter_type = read_interp_filter_type(rb);
+  }
+
+  cm->intra_only = cm->show_frame ? 0 : vp9_rb_read_bit(rb);
+  cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
+  cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
+
   setup_loopfilter(pbi, rb);
   setup_quantization(pbi, rb);
 
@@ -961,7 +959,7 @@
   vp9_reader header_bc, residual_bc;
   VP9_COMMON *const pc = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
-  YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
+
   const uint8_t *data = pbi->source;
   const uint8_t *data_end = pbi->source + pbi->source_sz;
 
@@ -969,6 +967,7 @@
                                     pc, error_handler };
   const size_t first_partition_size = read_uncompressed_header(pbi, &rb);
   const int keyframe = pc->frame_type == KEY_FRAME;
+  YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
 
   data += vp9_rb_bytes_read(&rb);
   xd->corrupted = 0;
@@ -981,16 +980,14 @@
 
   vp9_setup_version(pc);
   if (!read_is_valid(data, first_partition_size, data_end))
-      vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                         "Truncated packet or corrupt partition 0 length");
+    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                       "Truncated packet or corrupt partition 0 length");
 
-  init_frame(pbi);
+  xd->mode_info_context = pc->mi;
+  xd->prev_mode_info_context = pc->prev_mi;
+  xd->frame_type = pc->frame_type;
+  xd->mode_info_stride = pc->mode_info_stride;
 
-  // Reset the frame pointers to the current frame size
-  vp9_realloc_frame_buffer(new_fb, pc->width, pc->height,
-                           pc->subsampling_x, pc->subsampling_y,
-                           VP9BORDERINPIXELS);
-
   if (vp9_reader_init(&header_bc, data, first_partition_size))
     vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate bool decoder 0");
@@ -1011,43 +1008,14 @@
     xd->itxm_add_uv_block = vp9_idct_add_uv_block;
   }
 
-  // Determine if the golden frame or ARF buffer should be updated and how.
-  // For all non key frames the GF and ARF refresh flags and sign bias
-  // flags must be set explicitly.
-  if (keyframe) {
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
-      pc->active_ref_idx[i] = pc->new_fb_idx;
-  } else {
-    // Should the GF or ARF be updated from the current frame
-    pbi->refresh_frame_flags = vp9_read_literal(&header_bc, NUM_REF_FRAMES);
-
-    // Select active reference frames and calculate scaling factors
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
-      const int ref = vp9_read_literal(&header_bc, NUM_REF_FRAMES_LG2);
-      pc->active_ref_idx[i] = pc->ref_frame_map[ref];
-      vp9_setup_scale_factors(pc, i);
-    }
-
-    // Read the sign bias for each reference frame buffer.
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
-      pc->ref_frame_sign_bias[i + 1] = vp9_read_bit(&header_bc);
-
-    xd->allow_high_precision_mv = vp9_read_bit(&header_bc);
-    pc->mcomp_filter_type = read_mcomp_filter_type(&header_bc);
-
-    // To enable choice of different interpolation filters
+  if (!keyframe)
     vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
-  }
 
   pc->fc = pc->frame_contexts[pc->frame_context_idx];
 
   setup_segmentation(pc, xd, &header_bc);
 
-  setup_pred_probs(pc, &header_bc);
-
   setup_txfm_mode(pc, xd->lossless, &header_bc);
-
-  // Read inter mode probability context updates
 
   update_frame_context(&pc->fc);
 
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -53,11 +53,6 @@
 
 static int update_bits[255];
 
-static INLINE void write_le16(uint8_t *p, int value) {
-  p[0] = value;
-  p[1] = value >> 8;
-}
-
 static INLINE void write_le32(uint8_t *p, int value) {
   p[0] = value;
   p[1] = value >> 8;
@@ -1169,6 +1164,8 @@
 }
 
 static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) {
+  const TXFM_MODE txfm_mode = cpi->common.txfm_mode;
+
   vp9_clear_system_state();
 
   // Build the cofficient contexts based on counts collected in encode loop
@@ -1176,18 +1173,15 @@
 
   update_coef_probs_common(bc, cpi, TX_4X4);
 
-  /* do not do this if not even allowed */
-  if (cpi->common.txfm_mode != ONLY_4X4) {
+  // do not do this if not even allowed
+  if (txfm_mode > ONLY_4X4)
     update_coef_probs_common(bc, cpi, TX_8X8);
-  }
 
-  if (cpi->common.txfm_mode > ALLOW_8X8) {
+  if (txfm_mode > ALLOW_8X8)
     update_coef_probs_common(bc, cpi, TX_16X16);
-  }
 
-  if (cpi->common.txfm_mode > ALLOW_16X16) {
+  if (txfm_mode > ALLOW_16X16)
     update_coef_probs_common(bc, cpi, TX_32X32);
-  }
 }
 
 static void segment_reference_frames(VP9_COMP *cpi) {
@@ -1395,6 +1389,38 @@
   }
 }
 
+static void write_interp_filter_type(INTERPOLATIONFILTERTYPE type,
+                                     struct vp9_write_bit_buffer *wb) {
+  vp9_wb_write_bit(wb, type == SWITCHABLE);
+  if (type != SWITCHABLE)
+    vp9_wb_write_literal(wb, type, 2);
+}
+
+static void fix_mcomp_filter_type(VP9_COMP *cpi) {
+  VP9_COMMON *const cm = &cpi->common;
+
+  if (cm->mcomp_filter_type == SWITCHABLE) {
+    // Check to see if only one of the filters is actually used
+    int count[VP9_SWITCHABLE_FILTERS];
+    int i, j, c = 0;
+    for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
+      count[i] = 0;
+      for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j)
+        count[i] += cm->fc.switchable_interp_count[j][i];
+      c += (count[i] > 0);
+    }
+    if (c == 1) {
+      // Only one filter is used. So set the filter at frame level
+      for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
+        if (count[i]) {
+          cm->mcomp_filter_type = vp9_switchable_interp[i];
+          break;
+        }
+      }
+    }
+  }
+}
+
 void write_uncompressed_header(VP9_COMP *cpi,
                                struct vp9_write_bit_buffer *wb) {
   VP9_COMMON *const cm = &cpi->common;
@@ -1424,13 +1450,6 @@
   vp9_wb_write_literal(wb, cm->width, 16);
   vp9_wb_write_literal(wb, cm->height, 16);
 
-  if (!cm->show_frame) {
-      vp9_wb_write_bit(wb, cm->intra_only);
-  }
-
-  vp9_wb_write_literal(wb, cm->frame_context_idx, NUM_FRAME_CONTEXTS_LG2);
-  vp9_wb_write_bit(wb, cm->clr_type);
-
   vp9_wb_write_bit(wb, cm->error_resilient_mode);
   if (!cm->error_resilient_mode) {
     vp9_wb_write_bit(wb, cm->reset_frame_context);
@@ -1438,34 +1457,9 @@
     vp9_wb_write_bit(wb, cm->frame_parallel_decoding_mode);
   }
 
-  encode_loopfilter(cm, xd, wb);
-  encode_quantization(cm, wb);
-}
-
-void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
-  int i, bytes_packed;
-  VP9_COMMON *const pc = &cpi->common;
-  vp9_writer header_bc, residual_bc;
-  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
-
-  uint8_t *cx_data = dest;
-  struct vp9_write_bit_buffer wb = {dest, 0};
-  struct vp9_write_bit_buffer first_partition_size_wb;
-
-  write_uncompressed_header(cpi, &wb);
-  first_partition_size_wb = wb;
-  vp9_wb_write_literal(&wb, 0, 16);  // don't know in advance first part. size
-
-  bytes_packed = vp9_rb_bytes_written(&wb);
-  cx_data += bytes_packed;
-
-  compute_update_table();
-
-  vp9_start_encode(&header_bc, cx_data);
-
   // When there is a key frame all reference buffers are updated using the new key frame
-  if (pc->frame_type != KEY_FRAME) {
-    int refresh_mask;
+  if (cm->frame_type != KEY_FRAME) {
+    int refresh_mask, i;
 
     // Should the GF or ARF be updated using the transmitted frame or buffer
 #if CONFIG_MULTIPLE_ARF
@@ -1472,17 +1466,16 @@
     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) {
+    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
-       * other uses are implemented (like RTC/temporal scaling)
-       *
-       * gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
-       * that happens in vp9_onyx_if.c:update_reference_frames() so that it can
-       * be done outside of the recode loop.
-       */
+      // 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
+      // other uses are implemented (like RTC/temporal scaling)
+      //
+      // gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
+      // that happens in vp9_onyx_if.c:update_reference_frames() so that it can
+      // be done outside of the recode loop.
       refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
                      (cpi->refresh_golden_frame << cpi->alt_fb_idx);
     } else {
@@ -1501,44 +1494,64 @@
                      (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);
-    vp9_write_literal(&header_bc, cpi->alt_fb_idx, NUM_REF_FRAMES_LG2);
+    vp9_wb_write_literal(wb, refresh_mask, NUM_REF_FRAMES);
+    vp9_wb_write_literal(wb, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
+    vp9_wb_write_literal(wb, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
+    vp9_wb_write_literal(wb, cpi->alt_fb_idx, NUM_REF_FRAMES_LG2);
 
     // Indicate the sign bias for each reference frame buffer.
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
-      vp9_write_bit(&header_bc, pc->ref_frame_sign_bias[LAST_FRAME + i]);
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
+      vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[LAST_FRAME + i]);
+
+    // Encode the common prediction model status flag probability updates for
+    // the reference frame
+    update_refpred_stats(cpi);
+    for (i = 0; i < PREDICTION_PROBS; i++) {
+      const int update = cpi->ref_pred_probs_update[i];
+      vp9_wb_write_bit(wb, update);
+      if (update)
+        vp9_wb_write_literal(wb, cm->ref_pred_probs[i], 8);
     }
 
     // Signal whether to allow high MV precision
-    vp9_write_bit(&header_bc, (xd->allow_high_precision_mv) ? 1 : 0);
-    if (pc->mcomp_filter_type == SWITCHABLE) {
-      /* Check to see if only one of the filters is actually used */
-      int count[VP9_SWITCHABLE_FILTERS];
-      int i, j, c = 0;
-      for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-        count[i] = 0;
-        for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j)
-          count[i] += cpi->common.fc.switchable_interp_count[j][i];
-        c += (count[i] > 0);
-      }
-      if (c == 1) {
-        /* Only one filter is used. So set the filter at frame level */
-        for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-          if (count[i]) {
-            pc->mcomp_filter_type = vp9_switchable_interp[i];
-            break;
-          }
-        }
-      }
-    }
+    vp9_wb_write_bit(wb, xd->allow_high_precision_mv);
+
     // Signal the type of subpel filter to use
-    vp9_write_bit(&header_bc, (pc->mcomp_filter_type == SWITCHABLE));
-    if (pc->mcomp_filter_type != SWITCHABLE)
-      vp9_write_literal(&header_bc, (pc->mcomp_filter_type), 2);
+    fix_mcomp_filter_type(cpi);
+    write_interp_filter_type(cm->mcomp_filter_type, wb);
   }
 
+  if (!cm->show_frame)
+    vp9_wb_write_bit(wb, cm->intra_only);
+
+  vp9_wb_write_literal(wb, cm->frame_context_idx, NUM_FRAME_CONTEXTS_LG2);
+  vp9_wb_write_bit(wb, cm->clr_type);
+
+  encode_loopfilter(cm, xd, wb);
+  encode_quantization(cm, wb);
+}
+
+void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
+  int i, bytes_packed;
+  VP9_COMMON *const pc = &cpi->common;
+  vp9_writer header_bc, residual_bc;
+  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
+
+  uint8_t *cx_data = dest;
+  struct vp9_write_bit_buffer wb = {dest, 0};
+  struct vp9_write_bit_buffer first_partition_size_wb;
+
+  write_uncompressed_header(cpi, &wb);
+  first_partition_size_wb = wb;
+  vp9_wb_write_literal(&wb, 0, 16);  // don't know in advance first part. size
+
+  bytes_packed = vp9_rb_bytes_written(&wb);
+  cx_data += bytes_packed;
+
+  compute_update_table();
+
+  vp9_start_encode(&header_bc, cx_data);
+
 #ifdef ENTROPY_STATS
   if (pc->frame_type == INTER_FRAME)
     active_section = 0;
@@ -1548,20 +1561,6 @@
 
   encode_segmentation(cpi, &header_bc);
 
-  // Encode the common prediction model status flag probability updates for
-  // the reference frame
-  update_refpred_stats(cpi);
-  if (pc->frame_type != KEY_FRAME) {
-    for (i = 0; i < PREDICTION_PROBS; i++) {
-      if (cpi->ref_pred_probs_update[i]) {
-        vp9_write_bit(&header_bc, 1);
-        vp9_write_prob(&header_bc, pc->ref_pred_probs[i]);
-      } else {
-        vp9_write_bit(&header_bc, 0);
-      }
-    }
-  }
-
   if (xd->lossless)
     pc->txfm_mode = ONLY_4X4;
   else
@@ -1569,15 +1568,13 @@
 
   vp9_clear_system_state();  // __asm emms;
 
-  vp9_copy(cpi->common.fc.pre_coef_probs, cpi->common.fc.coef_probs);
-  vp9_copy(cpi->common.fc.pre_y_mode_prob, cpi->common.fc.y_mode_prob);
-  vp9_copy(cpi->common.fc.pre_uv_mode_prob, cpi->common.fc.uv_mode_prob);
-  vp9_copy(cpi->common.fc.pre_partition_prob, cpi->common.fc.partition_prob);
-  cpi->common.fc.pre_nmvc = cpi->common.fc.nmvc;
-  vp9_copy(cpi->common.fc.pre_switchable_interp_prob,
-           cpi->common.fc.switchable_interp_prob);
-  vp9_copy(cpi->common.fc.pre_inter_mode_probs,
-           cpi->common.fc.inter_mode_probs);
+  vp9_copy(pc->fc.pre_coef_probs, pc->fc.coef_probs);
+  vp9_copy(pc->fc.pre_y_mode_prob, pc->fc.y_mode_prob);
+  vp9_copy(pc->fc.pre_uv_mode_prob, pc->fc.uv_mode_prob);
+  vp9_copy(pc->fc.pre_partition_prob, pc->fc.partition_prob);
+  pc->fc.pre_nmvc = pc->fc.nmvc;
+  vp9_copy(pc->fc.pre_switchable_interp_prob, pc->fc.switchable_interp_prob);
+  vp9_copy(pc->fc.pre_inter_mode_probs, pc->fc.inter_mode_probs);
 
   update_coef_probs(cpi, &header_bc);
 
@@ -1586,9 +1583,8 @@
 #endif
 
   vp9_update_skip_probs(cpi);
-  for (i = 0; i < MBSKIP_CONTEXTS; ++i) {
+  for (i = 0; i < MBSKIP_CONTEXTS; ++i)
     vp9_write_prob(&header_bc, pc->mbskip_pred_probs[i]);
-  }
 
   if (pc->frame_type != KEY_FRAME) {