Merge "Cleanup tokenize_b and hoist some invarients out of the loop."
diff --git a/build/make/obj_int_extract.c b/build/make/obj_int_extract.c
index 8c16957..819ce9d 100644
--- a/build/make/obj_int_extract.c
+++ b/build/make/obj_int_extract.c
@@ -666,7 +666,11 @@
     }
     strcpy(sectionlist[i], sectionname);
 
-    if (!strcmp(sectionname, ".rdata")) sectionrawdata_ptr = get_le32(ptr + 20);
+    // check if it's .rdata and is not a COMDAT section.
+    if (!strcmp(sectionname, ".rdata") &&
+        (get_le32(ptr + 36) & 0x1000) == 0) {
+      sectionrawdata_ptr = get_le32(ptr + 20);
+    }
 
     ptr += 40;
   }
diff --git a/examples.mk b/examples.mk
index 8e74055..5f12b6b 100644
--- a/examples.mk
+++ b/examples.mk
@@ -58,6 +58,8 @@
 vp9_spatial_scalable_encoder.SRCS += args.c args.h
 vp9_spatial_scalable_encoder.SRCS += ivfenc.c ivfenc.h
 vp9_spatial_scalable_encoder.SRCS += tools_common.c tools_common.h
+vp9_spatial_scalable_encoder.SRCS += video_common.h
+vp9_spatial_scalable_encoder.SRCS += video_writer.h video_writer.c
 vp9_spatial_scalable_encoder.GUID   = 4A38598D-627D-4505-9C7B-D4020C84100D
 vp9_spatial_scalable_encoder.DESCRIPTION = Spatial Scalable Encoder
 
@@ -73,6 +75,8 @@
 EXAMPLES-$(CONFIG_ENCODERS)         += vpx_temporal_scalable_patterns.c
 vpx_temporal_scalable_patterns.SRCS += ivfenc.c ivfenc.h
 vpx_temporal_scalable_patterns.SRCS += tools_common.c tools_common.h
+vpx_temporal_scalable_patterns.SRCS += video_common.h
+vpx_temporal_scalable_patterns.SRCS += video_writer.h video_writer.c
 vpx_temporal_scalable_patterns.GUID  = B18C08F2-A439-4502-A78E-849BE3D60947
 vpx_temporal_scalable_patterns.DESCRIPTION = Temporal Scalability Encoder
 EXAMPLES-$(CONFIG_VP8_DECODER)     += simple_decoder.c
@@ -105,6 +109,10 @@
 simple_encoder.GUID              = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
 simple_encoder.DESCRIPTION       = Simplified encoder loop
 EXAMPLES-$(CONFIG_VP8_ENCODER)  += twopass_encoder.c
+twopass_encoder.SRCS            += ivfenc.h ivfenc.c
+twopass_encoder.SRCS            += tools_common.h tools_common.c
+twopass_encoder.SRCS            += video_common.h
+twopass_encoder.SRCS            += video_writer.h video_writer.c
 twopass_encoder.GUID             = 73494FA6-4AF9-4763-8FBB-265C92402FD8
 twopass_encoder.DESCRIPTION      = Two-pass encoder loop
 EXAMPLES-$(CONFIG_VP8_ENCODER)  += force_keyframe.c
diff --git a/examples/decode_to_md5.c b/examples/decode_to_md5.c
index 077513c..aabac60 100644
--- a/examples/decode_to_md5.c
+++ b/examples/decode_to_md5.c
@@ -82,9 +82,9 @@
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
   const VpxVideoInfo *info = NULL;
+  const VpxInterface *decoder = NULL;
 
   exec_name = argv[0];
 
@@ -100,13 +100,13 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder");
 
   while (vpx_video_reader_read_frame(reader)) {
diff --git a/examples/decode_with_drops.c b/examples/decode_with_drops.c
index e8fc076..c6f7d43 100644
--- a/examples/decode_with_drops.c
+++ b/examples/decode_with_drops.c
@@ -76,7 +76,7 @@
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
+  const VpxInterface *decoder = NULL;
   VpxVideoReader *reader = NULL;
   const VpxVideoInfo *info = NULL;
   int n = 0;
@@ -104,13 +104,13 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder.");
 
   while (vpx_video_reader_read_frame(reader)) {
diff --git a/examples/postproc.c b/examples/postproc.c
index 7281f1e..2912fe6 100644
--- a/examples/postproc.c
+++ b/examples/postproc.c
@@ -64,8 +64,8 @@
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
   vpx_codec_err_t res;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
   const VpxVideoInfo *info = NULL;
 
   exec_name = argv[0];
@@ -82,17 +82,16 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  res = vpx_codec_dec_init(&codec, iface, NULL, VPX_CODEC_USE_POSTPROC);
-  if (res == VPX_CODEC_INCAPABLE) {
-    printf("NOTICE: Postproc not supported.\n");
-    res = vpx_codec_dec_init(&codec, iface, NULL, 0);
-  }
+  res = vpx_codec_dec_init(&codec, decoder->interface(), NULL,
+                           VPX_CODEC_USE_POSTPROC);
+  if (res == VPX_CODEC_INCAPABLE)
+    die_codec(&codec, "Postproc not supported by this decoder.");
 
   if (res)
     die_codec(&codec, "Failed to initialize decoder.");
diff --git a/examples/simple_decoder.c b/examples/simple_decoder.c
index 4dc9308..b0ca77d 100644
--- a/examples/simple_decoder.c
+++ b/examples/simple_decoder.c
@@ -101,8 +101,8 @@
   int frame_cnt = 0;
   FILE *outfile = NULL;
   vpx_codec_ctx_t codec;
-  vpx_codec_iface_t *iface = NULL;
   VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
   const VpxVideoInfo *info = NULL;
 
   exec_name = argv[0];
@@ -119,13 +119,13 @@
 
   info = vpx_video_reader_get_info(reader);
 
-  iface = get_codec_interface(info->codec_fourcc);
-  if (!iface)
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
     die("Unknown input codec.");
 
-  printf("Using %s\n", vpx_codec_iface_name(iface));
+  printf("Using %s\n", vpx_codec_iface_name(decoder->interface()));
 
-  if (vpx_codec_dec_init(&codec, iface, NULL, 0))
+  if (vpx_codec_dec_init(&codec, decoder->interface(), NULL, 0))
     die_codec(&codec, "Failed to initialize decoder.");
 
   while (vpx_video_reader_read_frame(reader)) {
diff --git a/examples/simple_encoder.c b/examples/simple_encoder.c
index 0ae012c..2e7c7a6 100644
--- a/examples/simple_encoder.c
+++ b/examples/simple_encoder.c
@@ -86,106 +86,97 @@
 #include <string.h>
 
 #define VPX_CODEC_DISABLE_COMPAT 1
-
-#include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
 
 #include "./tools_common.h"
 #include "./video_writer.h"
 
-#define interface (vpx_codec_vp8_cx())
-
 static const char *exec_name;
 
 void usage_exit() {
-  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
   exit(EXIT_FAILURE);
 }
 
-static int read_frame(FILE *f, vpx_image_t *img) {
-  int res = 1;
-  size_t to_read = img->w * img->h * 3 / 2;
-  size_t nbytes = fread(img->planes[0], 1, to_read, f);
-  if (nbytes != to_read) {
-    res = 0;
-    if (nbytes > 0)
-      printf("Warning: Read partial frame. Check your width & height!\n");
-  }
-  return res;
-}
-
-static int is_valid_dimension(int value) {
-  return value >= 16 && (value % 2 == 0);
-}
-
 int main(int argc, char **argv) {
-  FILE *infile;
+  FILE *infile = NULL;
   vpx_codec_ctx_t codec;
   vpx_codec_enc_cfg_t cfg;
   int frame_count = 0;
   vpx_image_t raw;
   vpx_codec_err_t res;
-  VpxVideoInfo info;
-  VpxVideoWriter *writer;
-  const int fps = 30;  // TODO(dkovalev) add command line argument
-  const int bitrate = 100;  // kbit/s TODO(dkovalev) add command line argument
+  VpxVideoInfo info = {0};
+  VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
+  const int fps = 30;        // TODO(dkovalev) add command line argument
+  const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
 
   exec_name = argv[0];
 
-  if (argc != 5)
+  if (argc != 6)
     die("Invalid number of arguments");
 
-  info.codec_fourcc = VP8_FOURCC;
-  info.frame_width = strtol(argv[1], NULL, 0);
-  info.frame_height = strtol(argv[2], NULL, 0);
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+     die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
   info.time_base.numerator = 1;
   info.time_base.denominator = fps;
 
-  if (!is_valid_dimension(info.frame_width) ||
-      !is_valid_dimension(info.frame_height))
-    die("Invalid resolution: %dx%d", info.frame_width, info.frame_height);
+  if (info.frame_width <= 0 ||
+      info.frame_height <= 0 ||
+      (info.frame_width % 2) != 0 ||
+      (info.frame_height % 2) != 0) {
+    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
+  }
 
   if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
-                                             info.frame_height, 1))
-    die("Failed to allocate image");
-
-  printf("Using %s\n", vpx_codec_iface_name(interface));
-
-  res = vpx_codec_enc_config_default(interface, &cfg, 0);
-  if (res) {
-    printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
-    return EXIT_FAILURE;
+                                             info.frame_height, 1)) {
+    die("Failed to allocate image.");
   }
 
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
+
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
   cfg.g_w = info.frame_width;
   cfg.g_h = info.frame_height;
   cfg.g_timebase.num = info.time_base.numerator;
   cfg.g_timebase.den = info.time_base.denominator;
   cfg.rc_target_bitrate = bitrate;
 
-  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
   if (!writer)
-    die("Failed to open %s for writing.", argv[4]);
+    die("Failed to open %s for writing.", outfile_arg);
 
-  // Open input file for this encoding pass
-  if (!(infile = fopen(argv[3], "rb")))
-    die("Failed to open %s for reading.", argv[3]);
+  if (!(infile = fopen(infile_arg, "rb")))
+    die("Failed to open %s for reading.", infile_arg);
 
-  // Initialize codec
-  if (vpx_codec_enc_init(&codec, interface, &cfg, 0))
+  if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
 
-
-  while (read_frame(infile, &raw)) {
+  while (vpx_img_read(&raw, infile)) {
     vpx_codec_iter_t iter = NULL;
     const vpx_codec_cx_pkt_t *pkt = NULL;
+
+    ++frame_count;
+
     res = vpx_codec_encode(&codec, &raw, frame_count, 1, 0,
                            VPX_DL_GOOD_QUALITY);
     if (res != VPX_CODEC_OK)
       die_codec(&codec, "Failed to encode frame");
 
-    ++frame_count;
-
     while ((pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
       if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
         const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
@@ -195,14 +186,14 @@
                                           pkt->data.frame.pts))
           die_codec(&codec, "Failed to write compressed frame.");
         printf(keyframe ? "K" : ".");
+        fflush(stdout);
       }
     }
   }
   printf("\n");
-
   fclose(infile);
-
   printf("Processed %d frames.\n", frame_count);
+
   vpx_img_free(&raw);
   if (vpx_codec_destroy(&codec))
     die_codec(&codec, "Failed to destroy codec.");
diff --git a/examples/twopass_encoder.c b/examples/twopass_encoder.c
index b0f0426..f16db66 100644
--- a/examples/twopass_encoder.c
+++ b/examples/twopass_encoder.c
@@ -50,218 +50,181 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
 #include <string.h>
+
 #define VPX_CODEC_DISABLE_COMPAT 1
 #include "vpx/vpx_encoder.h"
-#include "vpx/vp8cx.h"
-#define interface (vpx_codec_vp8_cx())
-#define fourcc    0x30385056
 
-#define IVF_FILE_HDR_SZ  (32)
-#define IVF_FRAME_HDR_SZ (12)
+#include "./tools_common.h"
+#include "./video_writer.h"
 
-static void mem_put_le16(char *mem, unsigned int val) {
-    mem[0] = val;
-    mem[1] = val>>8;
+static const char *exec_name;
+
+void usage_exit() {
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
+  exit(EXIT_FAILURE);
 }
 
-static void mem_put_le32(char *mem, unsigned int val) {
-    mem[0] = val;
-    mem[1] = val>>8;
-    mem[2] = val>>16;
-    mem[3] = val>>24;
-}
+static void get_frame_stats(vpx_codec_ctx_t *ctx,
+                            const vpx_image_t *img,
+                            vpx_codec_pts_t pts,
+                            uint64_t duration,
+                            vpx_enc_frame_flags_t flags,
+                            uint64_t deadline,
+                            vpx_fixed_buf_t *stats) {
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags,
+                                               deadline);
+  if (res != VPX_CODEC_OK)
+    die_codec(ctx, "Failed to get frame stats.");
 
-static void die(const char *fmt, ...) {
-    va_list ap;
-
-    va_start(ap, fmt);
-    vprintf(fmt, ap);
-    if(fmt[strlen(fmt)-1] != '\n')
-        printf("\n");
-    exit(EXIT_FAILURE);
-}
-
-static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
-    const char *detail = vpx_codec_error_detail(ctx);
-
-    printf("%s: %s\n", s, vpx_codec_error(ctx));
-    if(detail)
-        printf("    %s\n",detail);
-    exit(EXIT_FAILURE);
-}
-
-static int read_frame(FILE *f, vpx_image_t *img) {
-    size_t nbytes, to_read;
-    int    res = 1;
-
-    to_read = img->w*img->h*3/2;
-    nbytes = fread(img->planes[0], 1, to_read, f);
-    if(nbytes != to_read) {
-        res = 0;
-        if(nbytes > 0)
-            printf("Warning: Read partial frame. Check your width & height!\n");
+  while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
+    if (pkt->kind == VPX_CODEC_STATS_PKT) {
+      const uint8_t *const pkt_buf = pkt->data.twopass_stats.buf;
+      const size_t pkt_size = pkt->data.twopass_stats.sz;
+      stats->buf = realloc(stats->buf, stats->sz + pkt_size);
+      memcpy((uint8_t *)stats->buf + stats->sz, pkt_buf, pkt_size);
+      stats->sz += pkt_size;
     }
-    return res;
+  }
 }
 
-static void write_ivf_file_header(FILE *outfile,
-                                  const vpx_codec_enc_cfg_t *cfg,
-                                  int frame_cnt) {
-    char header[32];
+static void encode_frame(vpx_codec_ctx_t *ctx,
+                         const vpx_image_t *img,
+                         vpx_codec_pts_t pts,
+                         uint64_t duration,
+                         vpx_enc_frame_flags_t flags,
+                         uint64_t deadline,
+                         VpxVideoWriter *writer) {
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags,
+                                               deadline);
+  if (res != VPX_CODEC_OK)
+    die_codec(ctx, "Failed to encode frame.");
 
-    if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
-        return;
-    header[0] = 'D';
-    header[1] = 'K';
-    header[2] = 'I';
-    header[3] = 'F';
-    mem_put_le16(header+4,  0);                   /* version */
-    mem_put_le16(header+6,  32);                  /* headersize */
-    mem_put_le32(header+8,  fourcc);              /* headersize */
-    mem_put_le16(header+12, cfg->g_w);            /* width */
-    mem_put_le16(header+14, cfg->g_h);            /* height */
-    mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
-    mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
-    mem_put_le32(header+24, frame_cnt);           /* length */
-    mem_put_le32(header+28, 0);                   /* unused */
+  while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
+    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+      const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
 
-    (void) fwrite(header, 1, 32, outfile);
-}
-
-
-static void write_ivf_frame_header(FILE *outfile,
-                                   const vpx_codec_cx_pkt_t *pkt)
-{
-    char             header[12];
-    vpx_codec_pts_t  pts;
-
-    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
-        return;
-
-    pts = pkt->data.frame.pts;
-    mem_put_le32(header, pkt->data.frame.sz);
-    mem_put_le32(header+4, pts&0xFFFFFFFF);
-    mem_put_le32(header+8, pts >> 32);
-
-    (void) fwrite(header, 1, 12, outfile);
+      if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
+                                                pkt->data.frame.sz,
+                                                pkt->data.frame.pts))
+        die_codec(ctx, "Failed to write compressed frame.");
+      printf(keyframe ? "K" : ".");
+      fflush(stdout);
+    }
+  }
 }
 
 int main(int argc, char **argv) {
-    FILE                *infile, *outfile;
-    vpx_codec_ctx_t      codec;
-    vpx_codec_enc_cfg_t  cfg;
-    int                  frame_cnt = 0;
-    vpx_image_t          raw;
-    vpx_codec_err_t      res;
-    long                 width;
-    long                 height;
-    int                  frame_avail;
-    int                  got_data;
-    int                  flags = 0;
-    int                  pass;
-    vpx_fixed_buf_t      stats = {0};
+  FILE *infile = NULL;
+  VpxVideoWriter *writer = NULL;
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t cfg;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  vpx_fixed_buf_t stats = {0};
+  VpxVideoInfo info = {0};
+  const VpxInterface *encoder = NULL;
+  int pass;
+  const int fps = 30;        // TODO(dkovalev) add command line argument
+  const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
+  exec_name = argv[0];
 
-    /* Open files */
-    if(argc!=5)
-        die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
-    width = strtol(argv[1], NULL, 0);
-    height = strtol(argv[2], NULL, 0);
-    if(width < 16 || width%2 || height <16 || height%2)
-        die("Invalid resolution: %ldx%ld", width, height);
-    if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
-        die("Faile to allocate image", width, height);
-    if(!(outfile = fopen(argv[4], "wb")))
-        die("Failed to open %s for writing", argv[4]);
+  if (argc != 6)
+    die("Invalid number of arguments.");
 
-    printf("Using %s\n",vpx_codec_iface_name(interface));
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+    die("Unsupported codec.");
 
-    /* Populate encoder configuration */
-    res = vpx_codec_enc_config_default(interface, &cfg, 0);
-    if(res) {
-        printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
-        return EXIT_FAILURE;
+  info.codec_fourcc = encoder->fourcc;
+  info.time_base.numerator = 1;
+  info.time_base.denominator = fps;
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
+
+  if (info.frame_width <= 0 ||
+      info.frame_height <= 0 ||
+      (info.frame_width % 2) != 0 ||
+      (info.frame_height % 2) != 0) {
+    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
+  }
+
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
+                                             info.frame_height, 1)) {
+    die("Failed to allocate image", info.frame_width, info.frame_height);
+  }
+
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
+  if (!writer)
+    die("Failed to open %s for writing", outfile_arg);
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
+
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
+  cfg.g_w = info.frame_width;
+  cfg.g_h = info.frame_height;
+  cfg.g_timebase.num = info.time_base.numerator;
+  cfg.g_timebase.den = info.time_base.denominator;
+  cfg.rc_target_bitrate = bitrate;
+
+  for (pass = 0; pass < 2; ++pass) {
+    int frame_count = 0;
+
+    if (pass == 0) {
+      cfg.g_pass = VPX_RC_FIRST_PASS;
+    } else {
+      cfg.g_pass = VPX_RC_LAST_PASS;
+      cfg.rc_twopass_stats_in = stats;
     }
 
-    /* Update the default configuration with our settings */
-    cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
-                            / cfg.g_w / cfg.g_h;
-    cfg.g_w = width;
-    cfg.g_h = height;
+    if (!(infile = fopen(infile_arg, "rb")))
+      die("Failed to open %s for reading", infile_arg);
 
-    write_ivf_file_header(outfile, &cfg, 0);
+    if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
+      die_codec(&codec, "Failed to initialize encoder");
 
-    for(pass=0; pass<2; pass++) {
-        frame_cnt = 0;
+    while (vpx_img_read(&raw, infile)) {
+      ++frame_count;
 
-        if(pass == 0)
-            cfg.g_pass = VPX_RC_FIRST_PASS;
-        else {
-            cfg.g_pass              = VPX_RC_LAST_PASS;
-            cfg.rc_twopass_stats_in = stats;
-        }
-
-        /* Open input file for this encoding pass */
-        if(!(infile = fopen(argv[3], "rb")))
-            die("Failed to open %s for reading", argv[3]);
-
-        /* Initialize codec */
-        if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
-            die_codec(&codec, "Failed to initialize encoder");
-
-        frame_avail = 1;
-        got_data = 0;
-        while(frame_avail || got_data) {
-            vpx_codec_iter_t iter = NULL;
-            const vpx_codec_cx_pkt_t *pkt;
-
-            frame_avail = read_frame(infile, &raw);
-            if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
-                                1, flags, VPX_DL_BEST_QUALITY))
-                die_codec(&codec, "Failed to encode frame");
-            got_data = 0;
-            while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
-                got_data = 1;
-                switch(pkt->kind) {
-                case VPX_CODEC_CX_FRAME_PKT:
-                    write_ivf_frame_header(outfile, pkt);
-                    (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
-                                  outfile);
-                    break;
-                case VPX_CODEC_STATS_PKT:
-                    stats.buf = realloc(stats.buf, stats.sz
-                                        + pkt->data.twopass_stats.sz);
-                    if(!stats.buf)
-                        die("Memory reallocation failed.\n");
-                    memcpy((char*)stats.buf + stats.sz,
-                           pkt->data.twopass_stats.buf,
-                           pkt->data.twopass_stats.sz);
-                    stats.sz +=  pkt->data.twopass_stats.sz;
-                    break;
-                default:
-                    break;
-                }
-                printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
-                       && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
-                fflush(stdout);
-            }
-            frame_cnt++;
-        }
-        printf("\n");
-        fclose(infile);
-        printf("Pass %d complete.\n", pass+1);
-        if(vpx_codec_destroy(&codec))
-            die_codec(&codec, "Failed to destroy codec");
+      if (pass == 0) {
+        get_frame_stats(&codec, &raw, frame_count, 1, 0, VPX_DL_BEST_QUALITY,
+                        &stats);
+      } else {
+        encode_frame(&codec, &raw, frame_count, 1, 0, VPX_DL_BEST_QUALITY,
+                     writer);
+      }
     }
 
-    printf("Processed %d frames.\n",frame_cnt-1);
-    vpx_img_free(&raw);
-    free(stats.buf);
+    if (pass == 0) {
+      get_frame_stats(&codec, NULL, frame_count, 1, 0, VPX_DL_BEST_QUALITY,
+                      &stats);
+    } else {
+      printf("\n");
+    }
 
-    /* Try to rewrite the file header with the actual frame count */
-    if(!fseek(outfile, 0, SEEK_SET))
-        write_ivf_file_header(outfile, &cfg, frame_cnt-1);
-    fclose(outfile);
-    return EXIT_SUCCESS;
+    fclose(infile);
+    printf("Pass %d complete. Processed %d frames.\n", pass + 1, frame_count);
+    if (vpx_codec_destroy(&codec))
+      die_codec(&codec, "Failed to destroy codec.");
+  }
+
+  vpx_img_free(&raw);
+  free(stats.buf);
+
+  vpx_video_writer_close(writer);
+
+  return EXIT_SUCCESS;
 }
diff --git a/examples/vpx_temporal_scalable_patterns.c b/examples/vpx_temporal_scalable_patterns.c
index f91d33c..c40450e 100644
--- a/examples/vpx_temporal_scalable_patterns.c
+++ b/examples/vpx_temporal_scalable_patterns.c
@@ -12,18 +12,17 @@
 //  encoding scheme based on temporal scalability for video applications
 //  that benefit from a scalable bitstream.
 
-#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 #define VPX_CODEC_DISABLE_COMPAT 1
-#include "./ivfenc.h"
-#include "./tools_common.h"
-#include "./vpx_config.h"
 #include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
 
+#include "./tools_common.h"
+#include "./video_writer.h"
+
 static const char *exec_name;
 
 void usage_exit() {
@@ -341,7 +340,7 @@
 }
 
 int main(int argc, char **argv) {
-  FILE *outfile[VPX_TS_MAX_LAYERS];
+  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS];
   vpx_codec_ctx_t codec;
   vpx_codec_enc_cfg_t cfg;
   int frame_cnt = 0;
@@ -361,9 +360,7 @@
   int flag_periodicity = 1;
   int max_intra_size_pct;
   vpx_svc_layer_id_t layer_id = {0, 0};
-  char *codec_type;
-  const vpx_codec_iface_t *(*interface)(void);
-  unsigned int fourcc;
+  const VpxInterface *encoder = NULL;
   struct VpxInputContext input_ctx = {0};
 
   exec_name = argv[0];
@@ -374,23 +371,11 @@
         argv[0]);
   }
 
-  codec_type = argv[3];
-  if (strncmp(codec_type, "vp9", 3) == 0) {
-#if CONFIG_VP9_ENCODER
-    interface = vpx_codec_vp9_cx;
-    fourcc = 0x30395056;
-#else
-    die("Encoder vp9 selected but not configured");
-#endif
-  } else  {
-#if CONFIG_VP8_ENCODER
-    interface = vpx_codec_vp8_cx;
-    fourcc = 0x30385056;
-#else
-    die("Encoder vp8 selected but not configured");
-#endif
-  }
-  printf("Using %s\n", vpx_codec_iface_name(interface()));
+  encoder = get_vpx_encoder_by_name(argv[3]);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
 
   width = strtol(argv[4], NULL, 0);
   height = strtol(argv[5], NULL, 0);
@@ -412,7 +397,7 @@
   }
 
   // Populate encoder configuration.
-  res = vpx_codec_enc_config_default(interface(), &cfg, 0);
+  res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
   if (res) {
     printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
     return EXIT_FAILURE;
@@ -427,7 +412,7 @@
   cfg.g_timebase.den = strtol(argv[7], NULL, 0);
 
   for (i = 9; i < 9 + mode_to_num_layers[layering_mode]; ++i) {
-    cfg.ts_target_bitrate[i-9] = strtol(argv[i], NULL, 0);
+    cfg.ts_target_bitrate[i - 9] = strtol(argv[i], NULL, 0);
   }
 
   // Real time parameters.
@@ -466,22 +451,29 @@
 
   // Open an output file for each stream.
   for (i = 0; i < cfg.ts_number_layers; ++i) {
-    char file_name[512];
+    char file_name[PATH_MAX];
+    VpxVideoInfo info;
+    info.codec_fourcc = encoder->fourcc;
+    info.frame_width = cfg.g_w;
+    info.frame_height = cfg.g_h;
+    info.time_base.numerator = cfg.g_timebase.num;
+    info.time_base.denominator = cfg.g_timebase.den;
+
     snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
-    if (!(outfile[i] = fopen(file_name, "wb")))
+    outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
+    if (!outfile[i])
       die("Failed to open %s for writing", file_name);
-    ivf_write_file_header(outfile[i], &cfg, fourcc, 0);
   }
   // No spatial layers in this encoder.
   cfg.ss_number_layers = 1;
 
   // Initialize codec.
-  if (vpx_codec_enc_init(&codec, interface(), &cfg, 0))
+  if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
     die_codec(&codec, "Failed to initialize encoder");
 
   vpx_codec_control(&codec, VP8E_SET_CPUUSED, -6);
   vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 1);
-  if (strncmp(codec_type, "vp9", 3) == 0) {
+  if (strncmp(encoder->name, "vp9", 3) == 0) {
     vpx_codec_control(&codec, VP8E_SET_CPUUSED, 3);
     vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 0);
     if (vpx_codec_control(&codec, VP9E_SET_SVC, 1)) {
@@ -520,9 +512,8 @@
         case VPX_CODEC_CX_FRAME_PKT:
           for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
               i < cfg.ts_number_layers; ++i) {
-            ivf_write_frame_header(outfile[i], pts, pkt->data.frame.sz);
-            (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
-                          outfile[i]);
+            vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
+                                         pkt->data.frame.sz, pts);
             ++frames_in_layer[i];
           }
           break;
@@ -534,15 +525,13 @@
     pts += frame_duration;
   }
   fclose(input_ctx.file);
-  printf("Processed %d frames: \n", frame_cnt-1);
-  if (vpx_codec_destroy(&codec)) {
+  printf("Processed %d frames: \n", frame_cnt - 1);
+  if (vpx_codec_destroy(&codec))
     die_codec(&codec, "Failed to destroy codec");
-  }
+
   // Try to rewrite the output file headers with the actual frame count.
-  for (i = 0; i < cfg.ts_number_layers; ++i) {
-    if (!fseek(outfile[i], 0, SEEK_SET))
-      ivf_write_file_header(outfile[i], &cfg, fourcc, frame_cnt);
-    fclose(outfile[i]);
-  }
+  for (i = 0; i < cfg.ts_number_layers; ++i)
+    vpx_video_writer_close(outfile[i]);
+
   return EXIT_SUCCESS;
 }
diff --git a/libs.mk b/libs.mk
index cc40451..eac61f2 100644
--- a/libs.mk
+++ b/libs.mk
@@ -57,13 +57,6 @@
 RTCD += $$(BUILD_PFX)$(1).h
 endef
 
-# x86inc.asm is not compatible with pic 32bit builds. Restrict
-# files which use it to 64bit builds or 32bit without pic
-USE_X86INC = no
-ifeq ($(CONFIG_USE_X86INC),yes)
-  USE_X86INC = yes
-endif
-
 CODEC_SRCS-yes += CHANGELOG
 CODEC_SRCS-yes += libs.mk
 
@@ -182,6 +175,7 @@
 CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec
 
 INSTALL-LIBS-yes += include/vpx/vpx_codec.h
+INSTALL-LIBS-yes += include/vpx/vpx_frame_buffer.h
 INSTALL-LIBS-yes += include/vpx/vpx_image.h
 INSTALL-LIBS-yes += include/vpx/vpx_integer.h
 INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h
diff --git a/test/datarate_test.cc b/test/datarate_test.cc
index 4bcb0b2..5b0a548 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -493,7 +493,10 @@
   cfg_.rc_buf_initial_sz = 500;
   cfg_.rc_buf_optimal_sz = 500;
   cfg_.rc_buf_sz = 1000;
-  cfg_.rc_dropframe_thresh = 1;
+  // TODO(marpan): For now keep frame dropper off. Need to investigate an
+  // issue (rate-mismatch) that occcurs at speed 3 and low bitrate (200k) when
+  // frame dropper is on.
+  cfg_.rc_dropframe_thresh = 0;
   cfg_.rc_min_quantizer = 0;
   cfg_.rc_max_quantizer = 63;
   cfg_.rc_end_usage = VPX_CBR;
diff --git a/tools_common.c b/tools_common.c
index 85bedc9..5a1b701 100644
--- a/tools_common.c
+++ b/tools_common.c
@@ -15,6 +15,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+
 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
 #include "vpx/vp8dx.h"
 #endif
@@ -144,19 +148,75 @@
   return shortread;
 }
 
-vpx_codec_iface_t *get_codec_interface(unsigned int fourcc) {
-  switch (fourcc) {
-#if CONFIG_VP8_DECODER
-    case VP8_FOURCC:
-      return vpx_codec_vp8_dx();
+static const VpxInterface vpx_encoders[] = {
+#if CONFIG_VP8_ENCODER
+  {"vp8", VP8_FOURCC, &vpx_codec_vp8_cx},
 #endif
-#if CONFIG_VP9_DECODER
-    case VP9_FOURCC:
-      return vpx_codec_vp9_dx();
+
+#if CONFIG_VP9_ENCODER
+  {"vp9", VP9_FOURCC, &vpx_codec_vp9_cx},
 #endif
-    default:
-      return NULL;
+};
+
+int get_vpx_encoder_count() {
+  return sizeof(vpx_encoders) / sizeof(vpx_encoders[0]);
+}
+
+const VpxInterface *get_vpx_encoder_by_index(int i) {
+  return &vpx_encoders[i];
+}
+
+const VpxInterface *get_vpx_encoder_by_name(const char *name) {
+  int i;
+
+  for (i = 0; i < get_vpx_encoder_count(); ++i) {
+    const VpxInterface *encoder = get_vpx_encoder_by_index(i);
+    if (strcmp(encoder->name, name) == 0)
+      return encoder;
   }
+
+  return NULL;
+}
+
+static const VpxInterface vpx_decoders[] = {
+#if CONFIG_VP8_DECODER
+  {"vp8", VP8_FOURCC, &vpx_codec_vp8_dx},
+#endif
+
+#if CONFIG_VP9_DECODER
+  {"vp9", VP9_FOURCC, &vpx_codec_vp9_dx},
+#endif
+};
+
+int get_vpx_decoder_count() {
+  return sizeof(vpx_decoders) / sizeof(vpx_decoders[0]);
+}
+
+const VpxInterface *get_vpx_decoder_by_index(int i) {
+  return &vpx_decoders[i];
+}
+
+const VpxInterface *get_vpx_decoder_by_name(const char *name) {
+  int i;
+
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+     const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+     if (strcmp(decoder->name, name) == 0)
+       return decoder;
+  }
+
+  return NULL;
+}
+
+const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc) {
+  int i;
+
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+    const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+    if (decoder->fourcc == fourcc)
+      return decoder;
+  }
+
   return NULL;
 }
 
@@ -168,9 +228,31 @@
     const int stride = img->stride[plane];
     const int w = plane ? (img->d_w + 1) >> 1 : img->d_w;
     const int h = plane ? (img->d_h + 1) >> 1 : img->d_h;
+
     for (y = 0; y < h; ++y) {
       fwrite(buf, 1, w, file);
       buf += stride;
     }
   }
 }
+
+int vpx_img_read(vpx_image_t *img, FILE *file) {
+  int plane;
+
+  for (plane = 0; plane < 3; ++plane) {
+    unsigned char *buf = img->planes[plane];
+    const int stride = img->stride[plane];
+    const int w = plane ? (img->d_w + 1) >> 1 : img->d_w;
+    const int h = plane ? (img->d_h + 1) >> 1 : img->d_h;
+    int y;
+
+    for (y = 0; y < h; ++y) {
+      if (fread(buf, 1, w, file) != w)
+        return 0;
+      buf += stride;
+    }
+  }
+
+  return 1;
+}
+
diff --git a/tools_common.h b/tools_common.h
index 967b7a1..da87b6d 100644
--- a/tools_common.h
+++ b/tools_common.h
@@ -123,12 +123,29 @@
 
 int read_yuv_frame(struct VpxInputContext *input_ctx, vpx_image_t *yuv_frame);
 
-vpx_codec_iface_t *get_codec_interface(unsigned int fourcc);
+typedef struct VpxInterface {
+  const char *const name;
+  const uint32_t fourcc;
+  vpx_codec_iface_t *(*const interface)();
+} VpxInterface;
+
+int get_vpx_encoder_count();
+const VpxInterface *get_vpx_encoder_by_index(int i);
+const VpxInterface *get_vpx_encoder_by_name(const char *name);
+
+int get_vpx_decoder_count();
+const VpxInterface *get_vpx_decoder_by_index(int i);
+const VpxInterface *get_vpx_decoder_by_name(const char *name);
+const VpxInterface *get_vpx_decoder_by_fourcc(uint32_t fourcc);
 
 // TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
 // of vpx_image_t support
 void vpx_img_write(const vpx_image_t *img, FILE *file);
 
+// TODO(dkovalev): move this function to vpx_image.{c, h}, so it will be part
+// of vpx_image_t support
+int vpx_img_read(vpx_image_t *img, FILE *file);
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c
index 968c7f3..afcda9f 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -940,9 +940,9 @@
     /* Crude estimate of overhead cost from modes
      * << 9 is the normalization to (bits * 512) used in vp8_bits_per_mb
      */
-    mode_cost =((((av_pct_inter - av_pct_motion) * zz_cost) +
-                (av_pct_motion * motion_cost) +
-                (av_intra * intra_cost)) * cpi->common.MBs) * 512;
+    mode_cost = (int64_t)((((av_pct_inter - av_pct_motion) * zz_cost) +
+                             (av_pct_motion * motion_cost) +
+                             (av_intra * intra_cost)) * cpi->common.MBs) * 512;
 
     return mv_cost + mode_cost;
 }
@@ -2310,7 +2310,7 @@
                 pct_extra = (pct_extra > 20) ? 20 : pct_extra;
 
                 cpi->twopass.alt_extra_bits =
-                    (cpi->twopass.gf_group_bits * pct_extra) / 100;
+                    (int)(cpi->twopass.gf_group_bits * pct_extra) / 100;
                 cpi->twopass.gf_group_bits -= cpi->twopass.alt_extra_bits;
                 cpi->twopass.alt_extra_bits /=
                     ((cpi->baseline_gf_interval-1)>>1);
@@ -2386,7 +2386,7 @@
             target_frame_size = max_bits;
 
         if (target_frame_size > cpi->twopass.gf_group_bits)
-            target_frame_size = cpi->twopass.gf_group_bits;
+            target_frame_size = (int)cpi->twopass.gf_group_bits;
     }
 
     /* Adjust error and bits remaining */
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index e033fbb..6f77199 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -33,9 +33,16 @@
 void vp9_free_frame_buffers(VP9_COMMON *cm) {
   int i;
 
-  for (i = 0; i < FRAME_BUFFERS; i++)
+  for (i = 0; i < FRAME_BUFFERS; i++) {
     vp9_free_frame_buffer(&cm->frame_bufs[i].buf);
 
+    if (cm->frame_bufs[i].ref_count > 0 &&
+        cm->frame_bufs[i].raw_frame_buffer.data != NULL) {
+      cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[i].raw_frame_buffer);
+      cm->frame_bufs[i].ref_count = 0;
+    }
+  }
+
   vp9_free_frame_buffer(&cm->post_proc_buffer);
 
   vpx_free(cm->mip);
@@ -85,7 +92,7 @@
   int mi_size;
 
   if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
-                               VP9_DEC_BORDER_IN_PIXELS) < 0)
+                               VP9_DEC_BORDER_IN_PIXELS, NULL, NULL, NULL) < 0)
     goto fail;
 
   set_mb_mi(cm, aligned_width, aligned_height);
@@ -199,6 +206,7 @@
 
 void vp9_remove_common(VP9_COMMON *cm) {
   vp9_free_frame_buffers(cm);
+  vp9_free_internal_frame_buffers(&cm->int_frame_buffers);
 }
 
 void vp9_initialize_common() {
diff --git a/vp9/common/vp9_blockd.c b/vp9/common/vp9_blockd.c
index 8cc6571..d918bed 100644
--- a/vp9/common/vp9_blockd.c
+++ b/vp9/common/vp9_blockd.c
@@ -98,16 +98,6 @@
     vp9_foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
 }
 
-void vp9_foreach_transformed_block_uv(const MACROBLOCKD* const xd,
-                                      BLOCK_SIZE bsize,
-                                      foreach_transformed_block_visitor visit,
-                                      void *arg) {
-  int plane;
-
-  for (plane = 1; plane < MAX_MB_PLANE; plane++)
-    vp9_foreach_transformed_block_in_plane(xd, bsize, plane, visit, arg);
-}
-
 void vp9_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
                       BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int has_eob,
                       int aoff, int loff) {
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 70b8ffa..c22c621 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -89,7 +89,6 @@
 
 #define INTER_OFFSET(mode) ((mode) - NEARESTMV)
 
-
 /* For keyframes, intra block modes are predicted by the (already decoded)
    modes for the Y blocks to the left and above us; for interframes, there
    is a single probability table. */
@@ -182,7 +181,7 @@
   int subsampling_y;
   struct buf_2d dst;
   struct buf_2d pre[2];
-  int16_t *dequant;
+  const int16_t *dequant;
   ENTROPY_CONTEXT *above_context;
   ENTROPY_CONTEXT *left_context;
 };
@@ -314,11 +313,6 @@
     const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
     foreach_transformed_block_visitor visit, void *arg);
 
-
-void vp9_foreach_transformed_block_uv(
-    const MACROBLOCKD* const xd, BLOCK_SIZE bsize,
-    foreach_transformed_block_visitor visit, void *arg);
-
 static INLINE void txfrm_block_to_raster_xy(BLOCK_SIZE plane_bsize,
                                             TX_SIZE tx_size, int block,
                                             int *x, int *y) {
diff --git a/vp9/common/vp9_convolve.c b/vp9/common/vp9_convolve.c
index 3807ccc..d30e0b4 100644
--- a/vp9/common/vp9_convolve.c
+++ b/vp9/common/vp9_convolve.c
@@ -145,7 +145,7 @@
 }
 
 static int get_filter_offset(const int16_t *f, const InterpKernel *base) {
-  return (const InterpKernel *)(intptr_t)f - base;
+  return (int)((const InterpKernel *)(intptr_t)f - base);
 }
 
 void vp9_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h
index e030d92..d6b380f 100644
--- a/vp9/common/vp9_entropy.h
+++ b/vp9/common/vp9_entropy.h
@@ -119,7 +119,7 @@
 extern DECLARE_ALIGNED(16, const uint8_t, vp9_coefband_trans_8x8plus[1024]);
 extern DECLARE_ALIGNED(16, const uint8_t, vp9_coefband_trans_4x4[16]);
 
-static const uint8_t *get_band_translate(TX_SIZE tx_size) {
+static INLINE const uint8_t *get_band_translate(TX_SIZE tx_size) {
   return tx_size == TX_4X4 ? vp9_coefband_trans_4x4
                            : vp9_coefband_trans_8x8plus;
 }
@@ -146,8 +146,8 @@
 
 void vp9_model_to_full_probs(const vp9_prob *model, vp9_prob *full);
 
-static int get_entropy_context(TX_SIZE tx_size, const ENTROPY_CONTEXT *a,
-                                                const ENTROPY_CONTEXT *l) {
+static INLINE int get_entropy_context(TX_SIZE tx_size, const ENTROPY_CONTEXT *a,
+                                      const ENTROPY_CONTEXT *l) {
   ENTROPY_CONTEXT above_ec = 0, left_ec = 0;
 
   switch (tx_size) {
@@ -174,8 +174,8 @@
   return combine_entropy_contexts(above_ec, left_ec);
 }
 
-static const scan_order *get_scan(const MACROBLOCKD *xd, TX_SIZE tx_size,
-                                  PLANE_TYPE type, int block_idx) {
+static const INLINE scan_order *get_scan(const MACROBLOCKD *xd, TX_SIZE tx_size,
+                                         PLANE_TYPE type, int block_idx) {
   const MODE_INFO *const mi = xd->mi_8x8[0];
   const MB_MODE_INFO *const mbmi = &mi->mbmi;
 
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 6def3c8..25cba7f 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -345,7 +345,7 @@
 static void adapt_probs(const vp9_tree_index *tree,
                         const vp9_prob *pre_probs, const unsigned int *counts,
                         vp9_prob *probs) {
-  tree_merge_probs(tree, pre_probs, counts, COUNT_SAT, MAX_UPDATE_FACTOR,
+  vp9_tree_merge_probs(tree, pre_probs, counts, COUNT_SAT, MAX_UPDATE_FACTOR,
                    probs);
 }
 
diff --git a/vp9/common/vp9_entropymv.c b/vp9/common/vp9_entropymv.c
index 60ae79f..e1f5ef7 100644
--- a/vp9/common/vp9_entropymv.c
+++ b/vp9/common/vp9_entropymv.c
@@ -192,8 +192,8 @@
 
 static void adapt_probs(const vp9_tree_index *tree, const vp9_prob *pre_probs,
                         const unsigned int *counts, vp9_prob *probs) {
-  tree_merge_probs(tree, pre_probs, counts, MV_COUNT_SAT, MV_MAX_UPDATE_FACTOR,
-                   probs);
+  vp9_tree_merge_probs(tree, pre_probs, counts, MV_COUNT_SAT,
+                       MV_MAX_UPDATE_FACTOR, probs);
 }
 
 void vp9_adapt_mv_probs(VP9_COMMON *cm, int allow_hp) {
diff --git a/vp9/common/vp9_frame_buffers.c b/vp9/common/vp9_frame_buffers.c
new file mode 100644
index 0000000..d903ed6
--- /dev/null
+++ b/vp9/common/vp9_frame_buffers.c
@@ -0,0 +1,84 @@
+/*
+ *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+
+#include "vp9/common/vp9_frame_buffers.h"
+#include "vpx_mem/vpx_mem.h"
+
+int vp9_alloc_internal_frame_buffers(InternalFrameBufferList *list) {
+  assert(list != NULL);
+  vp9_free_internal_frame_buffers(list);
+
+  list->num_internal_frame_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  list->int_fb = vpx_calloc(list->num_internal_frame_buffers,
+                            sizeof(*list->int_fb));
+  return (list->int_fb == NULL);
+}
+
+void vp9_free_internal_frame_buffers(InternalFrameBufferList *list) {
+  int i;
+
+  assert(list != NULL);
+
+  for (i = 0; i < list->num_internal_frame_buffers; ++i) {
+    vpx_free(list->int_fb[i].data);
+    list->int_fb[i].data = NULL;
+  }
+  vpx_free(list->int_fb);
+  list->int_fb = NULL;
+}
+
+int vp9_get_frame_buffer(void *cb_priv, size_t min_size,
+                         vpx_codec_frame_buffer_t *fb) {
+  int i;
+  InternalFrameBufferList *const int_fb_list =
+      (InternalFrameBufferList *)cb_priv;
+  if (int_fb_list == NULL || fb == NULL)
+    return -1;
+
+  // Find a free frame buffer.
+  for (i = 0; i < int_fb_list->num_internal_frame_buffers; ++i) {
+    if (!int_fb_list->int_fb[i].in_use)
+      break;
+  }
+
+  if (i == int_fb_list->num_internal_frame_buffers)
+    return -1;
+
+  if (int_fb_list->int_fb[i].size < min_size) {
+    int_fb_list->int_fb[i].data =
+        (uint8_t *)vpx_realloc(int_fb_list->int_fb[i].data, min_size);
+    if (!int_fb_list->int_fb[i].data)
+      return -1;
+
+    int_fb_list->int_fb[i].size = min_size;
+  }
+
+  fb->data = int_fb_list->int_fb[i].data;
+  fb->size = int_fb_list->int_fb[i].size;
+  int_fb_list->int_fb[i].in_use = 1;
+
+  // Set the frame buffer's private data to point at the internal frame buffer.
+  fb->priv = &int_fb_list->int_fb[i];
+  return 0;
+}
+
+int vp9_release_frame_buffer(void *cb_priv, vpx_codec_frame_buffer_t *fb) {
+  InternalFrameBuffer *int_fb;
+  (void)cb_priv;
+  if (fb == NULL)
+    return -1;
+
+  int_fb = (InternalFrameBuffer *)fb->priv;
+  int_fb->in_use = 0;
+  return 0;
+}
diff --git a/vp9/common/vp9_frame_buffers.h b/vp9/common/vp9_frame_buffers.h
new file mode 100644
index 0000000..e2cfe61
--- /dev/null
+++ b/vp9/common/vp9_frame_buffers.h
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VP9_COMMON_VP9_FRAME_BUFFERS_H_
+#define VP9_COMMON_VP9_FRAME_BUFFERS_H_
+
+#include "vpx/vpx_frame_buffer.h"
+#include "vpx/vpx_integer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct InternalFrameBuffer {
+  uint8_t *data;
+  size_t size;
+  int in_use;
+} InternalFrameBuffer;
+
+typedef struct InternalFrameBufferList {
+  int num_internal_frame_buffers;
+  InternalFrameBuffer *int_fb;
+} InternalFrameBufferList;
+
+// Initializes |list|. Returns 0 on success.
+int vp9_alloc_internal_frame_buffers(InternalFrameBufferList *list);
+
+// Free any data allocated to the frame buffers.
+void vp9_free_internal_frame_buffers(InternalFrameBufferList *list);
+
+// Callback used by libvpx to request an external frame buffer. |cb_priv|
+// Callback private data, which points to an InternalFrameBufferList.
+// |min_size| is the minimum size in bytes needed to decode the next frame.
+// |fb| pointer to the frame buffer.
+int vp9_get_frame_buffer(void *cb_priv, size_t min_size,
+                         vpx_codec_frame_buffer_t *fb);
+
+// Callback used by libvpx when there are no references to the frame buffer.
+// |cb_priv| is not used. |fb| pointer to the frame buffer.
+int vp9_release_frame_buffer(void *cb_priv, vpx_codec_frame_buffer_t *fb);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // VP9_COMMON_VP9_FRAME_BUFFERS_H_
diff --git a/vp9/common/vp9_mv.h b/vp9/common/vp9_mv.h
index 98fd1d8..3eb7f9d 100644
--- a/vp9/common/vp9_mv.h
+++ b/vp9/common/vp9_mv.h
@@ -34,8 +34,8 @@
   int32_t col;
 } MV32;
 
-static void clamp_mv(MV *mv, int min_col, int max_col,
-                             int min_row, int max_row) {
+static INLINE void clamp_mv(MV *mv, int min_col, int max_col,
+                            int min_row, int max_row) {
   mv->col = clamp(mv->col, min_col, max_col);
   mv->row = clamp(mv->row, min_row, max_row);
 }
diff --git a/vp9/common/vp9_mvref_common.h b/vp9/common/vp9_mvref_common.h
index 0936abf..f99952f 100644
--- a/vp9/common/vp9_mvref_common.h
+++ b/vp9/common/vp9_mvref_common.h
@@ -48,7 +48,7 @@
                            int_mv *mvlist, int_mv *nearest, int_mv *near);
 
 // TODO(jingning): this mv clamping function should be block size dependent.
-static void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
+static INLINE void clamp_mv2(MV *mv, const MACROBLOCKD *xd) {
   clamp_mv(mv, xd->mb_to_left_edge - LEFT_TOP_MARGIN,
                xd->mb_to_right_edge + RIGHT_BOTTOM_MARGIN,
                xd->mb_to_top_edge - LEFT_TOP_MARGIN,
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index d92a25b..97983c5 100644
--- 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"
+#include "vp9/common/vp9_frame_buffers.h"
 #include "vp9/common/vp9_quant_common.h"
 #include "vp9/common/vp9_tile_common.h"
 
@@ -94,6 +95,7 @@
 
 typedef struct {
   int ref_count;
+  vpx_codec_frame_buffer_t raw_frame_buffer;
   YV12_BUFFER_CONFIG buf;
 } RefCntBuffer;
 
@@ -223,13 +225,21 @@
   int frame_parallel_decoding_mode;
 
   int log2_tile_cols, log2_tile_rows;
+
+  // Private data associated with the frame buffer callbacks.
+  void *cb_priv;
+  vpx_get_frame_buffer_cb_fn_t get_fb_cb;
+  vpx_release_frame_buffer_cb_fn_t release_fb_cb;
+
+  // Handles memory for the codec.
+  InternalFrameBufferList int_frame_buffers;
 } VP9_COMMON;
 
-static YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
+static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
   return &cm->frame_bufs[cm->new_fb_idx].buf;
 }
 
-static int get_free_fb(VP9_COMMON *cm) {
+static INLINE int get_free_fb(VP9_COMMON *cm) {
   int i;
   for (i = 0; i < FRAME_BUFFERS; i++)
     if (cm->frame_bufs[i].ref_count == 0)
@@ -240,7 +250,7 @@
   return i;
 }
 
-static void ref_cnt_fb(RefCntBuffer *bufs, int *idx, int new_idx) {
+static INLINE void ref_cnt_fb(RefCntBuffer *bufs, int *idx, int new_idx) {
   const int ref_index = *idx;
 
   if (ref_index >= 0 && bufs[ref_index].ref_count > 0)
@@ -251,7 +261,7 @@
   bufs[new_idx].ref_count++;
 }
 
-static int mi_cols_aligned_to_sb(int n_mis) {
+static INLINE int mi_cols_aligned_to_sb(int n_mis) {
   return ALIGN_POWER_OF_TWO(n_mis, MI_BLOCK_SIZE_LOG2);
 }
 
@@ -275,10 +285,10 @@
   }
 }
 
-static void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
-                           int mi_row, int bh,
-                           int mi_col, int bw,
-                           int mi_rows, int mi_cols) {
+static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
+                                  int mi_row, int bh,
+                                  int mi_col, int bw,
+                                  int mi_rows, int mi_cols) {
   xd->mb_to_top_edge    = -((mi_row * MI_SIZE) * 8);
   xd->mb_to_bottom_edge = ((mi_rows - bh - mi_row) * MI_SIZE) * 8;
   xd->mb_to_left_edge   = -((mi_col * MI_SIZE) * 8);
diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h
index 0acee32..33ae5a8 100644
--- a/vp9/common/vp9_pred_common.h
+++ b/vp9/common/vp9_pred_common.h
@@ -98,8 +98,8 @@
 
 int vp9_get_tx_size_context(const MACROBLOCKD *xd);
 
-static const vp9_prob *get_tx_probs(TX_SIZE max_tx_size, int ctx,
-                                    const struct tx_probs *tx_probs) {
+static INLINE const vp9_prob *get_tx_probs(TX_SIZE max_tx_size, int ctx,
+                                           const struct tx_probs *tx_probs) {
   switch (max_tx_size) {
     case TX_8X8:
       return tx_probs->p8x8[ctx];
@@ -113,13 +113,14 @@
   }
 }
 
-static const vp9_prob *get_tx_probs2(TX_SIZE max_tx_size, const MACROBLOCKD *xd,
-                                     const struct tx_probs *tx_probs) {
+static INLINE const vp9_prob *get_tx_probs2(TX_SIZE max_tx_size,
+                                            const MACROBLOCKD *xd,
+                                            const struct tx_probs *tx_probs) {
   return get_tx_probs(max_tx_size, vp9_get_tx_size_context(xd), tx_probs);
 }
 
-static unsigned int *get_tx_counts(TX_SIZE max_tx_size, int ctx,
-                                   struct tx_counts *tx_counts) {
+static INLINE unsigned int *get_tx_counts(TX_SIZE max_tx_size, int ctx,
+                                          struct tx_counts *tx_counts) {
   switch (max_tx_size) {
     case TX_8X8:
       return tx_counts->p8x8[ctx];
diff --git a/vp9/common/vp9_prob.c b/vp9/common/vp9_prob.c
index 884884e..f9bc06e 100644
--- a/vp9/common/vp9_prob.c
+++ b/vp9/common/vp9_prob.c
@@ -28,3 +28,34 @@
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
+
+
+static unsigned int tree_merge_probs_impl(unsigned int i,
+                                          const vp9_tree_index *tree,
+                                          const vp9_prob *pre_probs,
+                                          const unsigned int *counts,
+                                          unsigned int count_sat,
+                                          unsigned int max_update,
+                                          vp9_prob *probs) {
+  const int l = tree[i];
+  const unsigned int left_count = (l <= 0)
+                 ? counts[-l]
+                 : tree_merge_probs_impl(l, tree, pre_probs, counts,
+                                         count_sat, max_update, probs);
+  const int r = tree[i + 1];
+  const unsigned int right_count = (r <= 0)
+                 ? counts[-r]
+                 : tree_merge_probs_impl(r, tree, pre_probs, counts,
+                                         count_sat, max_update, probs);
+  const unsigned int ct[2] = { left_count, right_count };
+  probs[i >> 1] = merge_probs(pre_probs[i >> 1], ct,
+                              count_sat, max_update);
+  return left_count + right_count;
+}
+
+void vp9_tree_merge_probs(const vp9_tree_index *tree, const vp9_prob *pre_probs,
+                          const unsigned int *counts, unsigned int count_sat,
+                          unsigned int max_update_factor, vp9_prob *probs) {
+  tree_merge_probs_impl(0, tree, pre_probs, counts, count_sat,
+                        max_update_factor, probs);
+}
diff --git a/vp9/common/vp9_prob.h b/vp9/common/vp9_prob.h
index cc8d8ab..f361480 100644
--- a/vp9/common/vp9_prob.h
+++ b/vp9/common/vp9_prob.h
@@ -79,37 +79,10 @@
   return weighted_prob(pre_prob, prob, factor);
 }
 
-static unsigned int tree_merge_probs_impl(unsigned int i,
-                                          const vp9_tree_index *tree,
-                                          const vp9_prob *pre_probs,
-                                          const unsigned int *counts,
-                                          unsigned int count_sat,
-                                          unsigned int max_update_factor,
-                                          vp9_prob *probs) {
-  const int l = tree[i];
-  const unsigned int left_count = (l <= 0)
-                 ? counts[-l]
-                 : tree_merge_probs_impl(l, tree, pre_probs, counts,
-                                         count_sat, max_update_factor, probs);
-  const int r = tree[i + 1];
-  const unsigned int right_count = (r <= 0)
-                 ? counts[-r]
-                 : tree_merge_probs_impl(r, tree, pre_probs, counts,
-                                         count_sat, max_update_factor, probs);
-  const unsigned int ct[2] = { left_count, right_count };
-  probs[i >> 1] = merge_probs(pre_probs[i >> 1], ct,
-                              count_sat, max_update_factor);
-  return left_count + right_count;
-}
+void vp9_tree_merge_probs(const vp9_tree_index *tree, const vp9_prob *pre_probs,
+                          const unsigned int *counts, unsigned int count_sat,
+                          unsigned int max_update_factor, vp9_prob *probs);
 
-static void tree_merge_probs(const vp9_tree_index *tree,
-                             const vp9_prob *pre_probs,
-                             const unsigned int *counts,
-                             unsigned int count_sat,
-                             unsigned int max_update_factor, vp9_prob *probs) {
-  tree_merge_probs_impl(0, tree, pre_probs, counts,
-                        count_sat, max_update_factor, probs);
-}
 
 DECLARE_ALIGNED(16, extern const uint8_t, vp9_norm[256]);
 
diff --git a/vp9/common/vp9_quant_common.c b/vp9/common/vp9_quant_common.c
index 6dbdb42..9fef8b1 100644
--- a/vp9/common/vp9_quant_common.c
+++ b/vp9/common/vp9_quant_common.c
@@ -130,7 +130,8 @@
 }
 
 
-int vp9_get_qindex(struct segmentation *seg, int segment_id, int base_qindex) {
+int vp9_get_qindex(const struct segmentation *seg, int segment_id,
+                   int base_qindex) {
   if (vp9_segfeature_active(seg, segment_id, SEG_LVL_ALT_Q)) {
     const int data = vp9_get_segdata(seg, segment_id, SEG_LVL_ALT_Q);
     return seg->abs_delta == SEGMENT_ABSDATA ?
diff --git a/vp9/common/vp9_quant_common.h b/vp9/common/vp9_quant_common.h
index af50e23..5811040 100644
--- a/vp9/common/vp9_quant_common.h
+++ b/vp9/common/vp9_quant_common.h
@@ -27,7 +27,8 @@
 int16_t vp9_dc_quant(int qindex, int delta);
 int16_t vp9_ac_quant(int qindex, int delta);
 
-int vp9_get_qindex(struct segmentation *seg, int segment_id, int base_qindex);
+int vp9_get_qindex(const struct segmentation *seg, int segment_id,
+                   int base_qindex);
 
 #ifdef __cplusplus
 }  // extern "C"
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index bf738c2..dccd609 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -39,18 +39,18 @@
                                enum mv_precision precision,
                                int x, int y);
 
-static int scaled_buffer_offset(int x_offset, int y_offset, int stride,
-                                const struct scale_factors *sf) {
+static INLINE int scaled_buffer_offset(int x_offset, int y_offset, int stride,
+                                       const struct scale_factors *sf) {
   const int x = sf ? sf->scale_value_x(x_offset, sf) : x_offset;
   const int y = sf ? sf->scale_value_y(y_offset, sf) : y_offset;
   return y * stride + x;
 }
 
-static void setup_pred_plane(struct buf_2d *dst,
-                             uint8_t *src, int stride,
-                             int mi_row, int mi_col,
-                             const struct scale_factors *scale,
-                             int subsampling_x, int subsampling_y) {
+static INLINE void setup_pred_plane(struct buf_2d *dst,
+                                    uint8_t *src, int stride,
+                                    int mi_row, int mi_col,
+                                    const struct scale_factors *scale,
+                                    int subsampling_x, int subsampling_y) {
   const int x = (MI_SIZE * mi_col) >> subsampling_x;
   const int y = (MI_SIZE * mi_row) >> subsampling_y;
   dst->buf = src + scaled_buffer_offset(x, y, stride, scale);
diff --git a/vp9/common/vp9_scale.h b/vp9/common/vp9_scale.h
index 90b0d0b..a9dda18 100644
--- a/vp9/common/vp9_scale.h
+++ b/vp9/common/vp9_scale.h
@@ -40,12 +40,12 @@
                                        int other_w, int other_h,
                                        int this_w, int this_h);
 
-static int vp9_is_valid_scale(const struct scale_factors *sf) {
+static INLINE int vp9_is_valid_scale(const struct scale_factors *sf) {
   return sf->x_scale_fp != REF_INVALID_SCALE &&
          sf->y_scale_fp != REF_INVALID_SCALE;
 }
 
-static int vp9_is_scaled(const struct scale_factors *sf) {
+static INLINE int vp9_is_scaled(const struct scale_factors *sf) {
   return sf->x_scale_fp != REF_NO_SCALE ||
          sf->y_scale_fp != REF_NO_SCALE;
 }
diff --git a/vp9/common/vp9_systemdependent.h b/vp9/common/vp9_systemdependent.h
index fb8626c..7455abc 100644
--- a/vp9/common/vp9_systemdependent.h
+++ b/vp9/common/vp9_systemdependent.h
@@ -34,7 +34,7 @@
 
 #if defined(_MSC_VER) && _MSC_VER < 1800
 // round is not defined in MSVC before VS2013.
-static int round(double x) {
+static INLINE int round(double x) {
   if (x < 0)
     return (int)ceil(x - 0.5);
   else
diff --git a/vp9/common/x86/vp9_asm_stubs.c b/vp9/common/x86/vp9_asm_stubs.c
index feb0098..60018ea 100644
--- a/vp9/common/x86/vp9_asm_stubs.c
+++ b/vp9/common/x86/vp9_asm_stubs.c
@@ -16,15 +16,15 @@
 
 typedef void filter8_1dfunction (
   const unsigned char *src_ptr,
-  const unsigned int src_pitch,
+  const ptrdiff_t src_pitch,
   unsigned char *output_ptr,
-  unsigned int out_pitch,
+  ptrdiff_t out_pitch,
   unsigned int output_height,
   const short *filter
 );
 
 #define FUN_CONV_1D(name, step_q4, filter, dir, src_start, avg, opt) \
-void vp9_convolve8_##name##_##opt(const uint8_t *src, ptrdiff_t src_stride, \
+  void vp9_convolve8_##name##_##opt(const uint8_t *src, ptrdiff_t src_stride, \
                                    uint8_t *dst, ptrdiff_t dst_stride, \
                                    const int16_t *filter_x, int x_step_q4, \
                                    const int16_t *filter_y, int y_step_q4, \
@@ -32,50 +32,68 @@
   if (step_q4 == 16 && filter[3] != 128) { \
     if (filter[0] || filter[1] || filter[2]) { \
       while (w >= 16) { \
-        vp9_filter_block1d16_##dir##8_##avg##opt(src_start, src_stride, \
-                                                  dst, dst_stride, \
-                                                  h, filter); \
+        vp9_filter_block1d16_##dir##8_##avg##opt(src_start, \
+                                                 src_stride, \
+                                                 dst, \
+                                                 dst_stride, \
+                                                 h, \
+                                                 filter); \
         src += 16; \
         dst += 16; \
         w -= 16; \
       } \
       while (w >= 8) { \
-        vp9_filter_block1d8_##dir##8_##avg##opt(src_start, src_stride, \
-                                                 dst, dst_stride, \
-                                                 h, filter); \
+        vp9_filter_block1d8_##dir##8_##avg##opt(src_start, \
+                                                src_stride, \
+                                                dst, \
+                                                dst_stride, \
+                                                h, \
+                                                filter); \
         src += 8; \
         dst += 8; \
         w -= 8; \
       } \
       while (w >= 4) { \
-        vp9_filter_block1d4_##dir##8_##avg##opt(src_start, src_stride, \
-                                                 dst, dst_stride, \
-                                                 h, filter); \
+        vp9_filter_block1d4_##dir##8_##avg##opt(src_start, \
+                                                src_stride, \
+                                                dst, \
+                                                dst_stride, \
+                                                h, \
+                                                filter); \
         src += 4; \
         dst += 4; \
         w -= 4; \
       } \
     } else { \
       while (w >= 16) { \
-        vp9_filter_block1d16_##dir##2_##avg##opt(src, src_stride, \
-                                                  dst, dst_stride, \
-                                                  h, filter); \
+        vp9_filter_block1d16_##dir##2_##avg##opt(src, \
+                                                 src_stride, \
+                                                 dst, \
+                                                 dst_stride, \
+                                                 h, \
+                                                 filter); \
         src += 16; \
         dst += 16; \
         w -= 16; \
       } \
       while (w >= 8) { \
-        vp9_filter_block1d8_##dir##2_##avg##opt(src, src_stride, \
-                                                 dst, dst_stride, \
-                                                 h, filter); \
+        vp9_filter_block1d8_##dir##2_##avg##opt(src, \
+                                                src_stride, \
+                                                dst, \
+                                                dst_stride, \
+                                                h, \
+                                                filter); \
         src += 8; \
         dst += 8; \
         w -= 8; \
       } \
       while (w >= 4) { \
-        vp9_filter_block1d4_##dir##2_##avg##opt(src, src_stride, \
-                                                 dst, dst_stride, \
-                                                 h, filter); \
+        vp9_filter_block1d4_##dir##2_##avg##opt(src, \
+                                                src_stride, \
+                                                dst, \
+                                                dst_stride, \
+                                                h, \
+                                                filter); \
         src += 4; \
         dst += 4; \
         w -= 4; \
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 93ef750..d37afa5 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -691,9 +691,14 @@
     vp9_update_frame_size(cm);
   }
 
-  vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height,
-                           cm->subsampling_x, cm->subsampling_y,
-                           VP9_DEC_BORDER_IN_PIXELS);
+  if (vp9_realloc_frame_buffer(
+          get_frame_new_buffer(cm), cm->width, cm->height,
+          cm->subsampling_x, cm->subsampling_y, VP9_DEC_BORDER_IN_PIXELS,
+          &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer, cm->get_fb_cb,
+          cm->cb_priv)) {
+    vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+                       "Failed to allocate frame buffer");
+  }
 }
 
 static void setup_frame_size(VP9D_COMP *pbi,
@@ -1114,7 +1119,7 @@
   cm->show_existing_frame = vp9_rb_read_bit(rb);
   if (cm->show_existing_frame) {
     // Show an existing frame directly.
-    int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
+    const int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
     ref_cnt_fb(cm->frame_bufs, &cm->new_fb_idx, frame_to_show);
     pbi->refresh_frame_flags = 0;
     cm->lf.filter_level = 0;
diff --git a/vp9/decoder/vp9_dthread.c b/vp9/decoder/vp9_dthread.c
index 128b9f8..542732a 100644
--- a/vp9/decoder/vp9_dthread.c
+++ b/vp9/decoder/vp9_dthread.c
@@ -220,11 +220,13 @@
 
   CHECK_MEM_ERROR(cm, lf_sync->mutex_,
                   vpx_malloc(sizeof(*lf_sync->mutex_) * rows));
-  CHECK_MEM_ERROR(cm, lf_sync->cond_,
-                  vpx_malloc(sizeof(*lf_sync->cond_) * rows));
-
   for (i = 0; i < rows; ++i) {
     pthread_mutex_init(&lf_sync->mutex_[i], NULL);
+  }
+
+  CHECK_MEM_ERROR(cm, lf_sync->cond_,
+                  vpx_malloc(sizeof(*lf_sync->cond_) * rows));
+  for (i = 0; i < rows; ++i) {
     pthread_cond_init(&lf_sync->cond_[i], NULL);
   }
 #endif  // CONFIG_MULTITHREAD
@@ -242,18 +244,29 @@
   if (lf_sync != NULL) {
     int i;
 
-    for (i = 0; i < rows; ++i) {
-      pthread_mutex_destroy(&lf_sync->mutex_[i]);
-      pthread_cond_destroy(&lf_sync->cond_[i]);
+    if (lf_sync->mutex_ != NULL) {
+      for (i = 0; i < rows; ++i) {
+        pthread_mutex_destroy(&lf_sync->mutex_[i]);
+      }
+      vpx_free(lf_sync->mutex_);
+    }
+    if (lf_sync->cond_ != NULL) {
+      for (i = 0; i < rows; ++i) {
+        pthread_cond_destroy(&lf_sync->cond_[i]);
+      }
+      vpx_free(lf_sync->cond_);
     }
 
-    vpx_free(lf_sync->mutex_);
-    vpx_free(lf_sync->cond_);
     vpx_free(lf_sync->cur_sb_col);
+    // clear the structure as the source of this call may be a resize in which
+    // case this call will be followed by an _alloc() which may fail.
+    vpx_memset(lf_sync, 0, sizeof(*lf_sync));
   }
 #else
   (void)rows;
-  if (lf_sync != NULL)
+  if (lf_sync != NULL) {
     vpx_free(lf_sync->cur_sb_col);
+    vpx_memset(lf_sync, 0, sizeof(*lf_sync));
+  }
 #endif  // CONFIG_MULTITHREAD
 }
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index 803d536..1d3522e 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -290,9 +290,14 @@
   VP9_COMMON *const cm = &pbi->common;
 
   for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
-    if (mask & 1)
+    if (mask & 1) {
+      const int old_idx = cm->ref_frame_map[ref_index];
       ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index],
                  cm->new_fb_idx);
+      if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0)
+        cm->release_fb_cb(cm->cb_priv,
+                          &cm->frame_bufs[old_idx].raw_frame_buffer);
+    }
     ++ref_index;
   }
 
@@ -337,6 +342,10 @@
       cm->frame_refs[0].buf->corrupted = 1;
   }
 
+  // Check if the previous frame was a frame without any references to it.
+  if (cm->new_fb_idx >= 0 && cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
+    cm->release_fb_cb(cm->cb_priv,
+                      &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
   cm->new_fb_idx = get_free_fb(cm);
 
   if (setjmp(cm->error.jmp)) {
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index e895d0a..1b106f4 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -319,7 +319,7 @@
 }
 
 // Macroblock activity masking
-void vp9_activity_masking(VP9_COMP *cpi, MACROBLOCK *x) {
+static void activity_masking(VP9_COMP *cpi, MACROBLOCK *x) {
 #if USE_ACT_INDEX
   x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);
   x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
@@ -613,7 +613,7 @@
     x->encode_breakout = cpi->segment_encode_breakout[mbmi->segment_id];
   } else {
     mbmi->segment_id = 0;
-    x->encode_breakout = cpi->oxcf.encode_breakout;
+    x->encode_breakout = cpi->encode_breakout;
   }
 }
 
@@ -673,7 +673,7 @@
   }
 
   if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
-    vp9_activity_masking(cpi, x);
+    activity_masking(cpi, x);
 
   if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
     vp9_clear_system_state();  // __asm emms;
@@ -713,36 +713,40 @@
 
 static void update_stats(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
-  MACROBLOCK *const x = &cpi->mb;
-  MACROBLOCKD *const xd = &x->e_mbd;
-  MODE_INFO *mi = xd->mi_8x8[0];
-  MB_MODE_INFO *const mbmi = &mi->mbmi;
+  const MACROBLOCK *const x = &cpi->mb;
+  const MACROBLOCKD *const xd = &x->e_mbd;
+  const MODE_INFO *const mi = xd->mi_8x8[0];
+  const MB_MODE_INFO *const mbmi = &mi->mbmi;
 
   if (!frame_is_intra_only(cm)) {
     const int seg_ref_active = vp9_segfeature_active(&cm->seg, mbmi->segment_id,
                                                      SEG_LVL_REF_FRAME);
+    if (!seg_ref_active) {
+      FRAME_COUNTS *const counts = &cm->counts;
+      const int inter_block = is_inter_block(mbmi);
 
-    if (!seg_ref_active)
-      cm->counts.intra_inter[vp9_get_intra_inter_context(xd)]
-                            [is_inter_block(mbmi)]++;
+      counts->intra_inter[vp9_get_intra_inter_context(xd)][inter_block]++;
 
-    // If the segment reference feature is enabled we have only a single
-    // reference frame allowed for the segment so exclude it from
-    // the reference frame counts used to work out probabilities.
-    if (is_inter_block(mbmi) && !seg_ref_active) {
-      if (cm->reference_mode == REFERENCE_MODE_SELECT)
-        cm->counts.comp_inter[vp9_get_reference_mode_context(cm, xd)]
-                             [has_second_ref(mbmi)]++;
+      // If the segment reference feature is enabled we have only a single
+      // reference frame allowed for the segment so exclude it from
+      // the reference frame counts used to work out probabilities.
+      if (inter_block) {
+        const MV_REFERENCE_FRAME ref0 = mbmi->ref_frame[0];
 
-      if (has_second_ref(mbmi)) {
-        cm->counts.comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)]
-                           [mbmi->ref_frame[0] == GOLDEN_FRAME]++;
-      } else {
-        cm->counts.single_ref[vp9_get_pred_context_single_ref_p1(xd)][0]
-                             [mbmi->ref_frame[0] != LAST_FRAME]++;
-        if (mbmi->ref_frame[0] != LAST_FRAME)
-          cm->counts.single_ref[vp9_get_pred_context_single_ref_p2(xd)][1]
-                               [mbmi->ref_frame[0] != GOLDEN_FRAME]++;
+        if (cm->reference_mode == REFERENCE_MODE_SELECT)
+          counts->comp_inter[vp9_get_reference_mode_context(cm, xd)]
+                            [has_second_ref(mbmi)]++;
+
+        if (has_second_ref(mbmi)) {
+          counts->comp_ref[vp9_get_pred_context_comp_ref_p(cm, xd)]
+                          [ref0 == GOLDEN_FRAME]++;
+        } else {
+          counts->single_ref[vp9_get_pred_context_single_ref_p1(xd)][0]
+                            [ref0 != LAST_FRAME]++;
+          if (ref0 != LAST_FRAME)
+            counts->single_ref[vp9_get_pred_context_single_ref_p2(xd)][1]
+                              [ref0 != GOLDEN_FRAME]++;
+        }
       }
     }
   }
@@ -1524,6 +1528,15 @@
   }
 }
 
+// Next square block size less or equal than current block size.
+static const BLOCK_SIZE next_square_size[BLOCK_SIZES] = {
+  BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
+  BLOCK_8X8, BLOCK_8X8, BLOCK_8X8,
+  BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
+  BLOCK_32X32, BLOCK_32X32, BLOCK_32X32,
+  BLOCK_64X64
+};
+
 // Look at neighboring blocks and set a min and max partition size based on
 // what they chose.
 static void rd_auto_partition_range(VP9_COMP *cpi, const TileInfo *const tile,
@@ -1590,36 +1603,28 @@
                                         row8x8_remaining, col8x8_remaining,
                                         &bh, &bw);
   *min_block_size = MIN(*min_block_size, *max_block_size);
+
+  // When use_square_partition_only is true, make sure at least one square
+  // partition is allowed by selecting the next smaller square size as
+  // *min_block_size.
+  if (cpi->sf.use_square_partition_only &&
+      (*max_block_size - *min_block_size) < 2) {
+    *min_block_size = next_square_size[*min_block_size];
+  }
 }
 
 static void compute_fast_motion_search_level(VP9_COMP *cpi, BLOCK_SIZE bsize) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
 
-  // Only use 8x8 result for non HD videos.
-  // int use_8x8 = (MIN(cpi->common.width, cpi->common.height) < 720) ? 1 : 0;
-  int use_8x8 = 1;
-
-  if (cm->frame_type && !cpi->rc.is_src_frame_alt_ref &&
-      ((use_8x8 && bsize == BLOCK_16X16) ||
-      bsize == BLOCK_32X32 || bsize == BLOCK_64X64)) {
-    int ref0 = 0, ref1 = 0, ref2 = 0, ref3 = 0;
-    PICK_MODE_CONTEXT *block_context = NULL;
-
-    if (bsize == BLOCK_16X16) {
-      block_context = x->sb8x8_context[x->sb_index][x->mb_index];
-    } else if (bsize == BLOCK_32X32) {
-      block_context = x->mb_context[x->sb_index];
-    } else if (bsize == BLOCK_64X64) {
-      block_context = x->sb32_context;
-    }
-
-    if (block_context) {
-      ref0 = block_context[0].mic.mbmi.ref_frame[0];
-      ref1 = block_context[1].mic.mbmi.ref_frame[0];
-      ref2 = block_context[2].mic.mbmi.ref_frame[0];
-      ref3 = block_context[3].mic.mbmi.ref_frame[0];
-    }
+  if (cm->frame_type == INTER_FRAME &&
+      !cpi->rc.is_src_frame_alt_ref &&
+      (bsize == BLOCK_16X16 || bsize == BLOCK_32X32 || bsize == BLOCK_64X64)) {
+    const PICK_MODE_CONTEXT *block_context = get_block_context(x, bsize);
+    const int ref0 = block_context[0].mic.mbmi.ref_frame[0];
+    const int ref1 = block_context[1].mic.mbmi.ref_frame[0];
+    const int ref2 = block_context[2].mic.mbmi.ref_frame[0];
+    const int ref3 = block_context[3].mic.mbmi.ref_frame[0];
 
     // Currently, only consider 4 inter reference frames.
     if (ref0 && ref1 && ref2 && ref3) {
@@ -2184,108 +2189,6 @@
     cpi->common.tx_mode = ALLOW_32X32;
 }
 
-static void encode_frame_internal(VP9_COMP *cpi) {
-  int mi_row;
-  MACROBLOCK *const x = &cpi->mb;
-  VP9_COMMON *const cm = &cpi->common;
-  MACROBLOCKD *const xd = &x->e_mbd;
-
-//  fprintf(stderr, "encode_frame_internal frame %d (%d) type %d\n",
-//           cpi->common.current_video_frame, cpi->common.show_frame,
-//           cm->frame_type);
-
-  vp9_zero(cm->counts.switchable_interp);
-  vp9_zero(cpi->tx_stepdown_count);
-
-  xd->mi_8x8 = cm->mi_grid_visible;
-  // required for vp9_frame_init_quantizer
-  xd->mi_8x8[0] = cm->mi;
-
-  xd->last_mi = cm->prev_mi;
-
-  vp9_zero(cm->counts.mv);
-  vp9_zero(cpi->coef_counts);
-  vp9_zero(cm->counts.eob_branch);
-
-  cpi->mb.e_mbd.lossless = cm->base_qindex == 0 && cm->y_dc_delta_q == 0
-      && cm->uv_dc_delta_q == 0 && cm->uv_ac_delta_q == 0;
-  switch_lossless_mode(cpi, cpi->mb.e_mbd.lossless);
-
-  vp9_frame_init_quantizer(cpi);
-
-  vp9_initialize_rd_consts(cpi);
-  vp9_initialize_me_consts(cpi, cm->base_qindex);
-  switch_tx_mode(cpi);
-
-  if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
-    // Initialize encode frame context.
-    init_encode_frame_mb_context(cpi);
-
-    // Build a frame level activity map
-    build_activity_map(cpi);
-  }
-
-  // Re-initialize encode frame context.
-  init_encode_frame_mb_context(cpi);
-
-  vp9_zero(cpi->rd_comp_pred_diff);
-  vp9_zero(cpi->rd_filter_diff);
-  vp9_zero(cpi->rd_tx_select_diff);
-  vp9_zero(cpi->rd_tx_select_threshes);
-
-  set_prev_mi(cm);
-
-  {
-    struct vpx_usec_timer emr_timer;
-    vpx_usec_timer_start(&emr_timer);
-
-    {
-      // Take tiles into account and give start/end MB
-      int tile_col, tile_row;
-      TOKENEXTRA *tp = cpi->tok;
-      const int tile_cols = 1 << cm->log2_tile_cols;
-      const int tile_rows = 1 << cm->log2_tile_rows;
-
-      for (tile_row = 0; tile_row < tile_rows; tile_row++) {
-        for (tile_col = 0; tile_col < tile_cols; tile_col++) {
-          TileInfo tile;
-          TOKENEXTRA *tp_old = tp;
-
-          // For each row of SBs in the frame
-          vp9_tile_init(&tile, cm, tile_row, tile_col);
-          for (mi_row = tile.mi_row_start;
-               mi_row < tile.mi_row_end; mi_row += 8)
-            encode_sb_row(cpi, &tile, mi_row, &tp);
-
-          cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
-          assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
-        }
-      }
-    }
-
-    vpx_usec_timer_mark(&emr_timer);
-    cpi->time_encode_sb_row += vpx_usec_timer_elapsed(&emr_timer);
-  }
-
-  if (cpi->sf.skip_encode_sb) {
-    int j;
-    unsigned int intra_count = 0, inter_count = 0;
-    for (j = 0; j < INTRA_INTER_CONTEXTS; ++j) {
-      intra_count += cm->counts.intra_inter[j][0];
-      inter_count += cm->counts.intra_inter[j][1];
-    }
-    cpi->sf.skip_encode_frame = ((intra_count << 2) < inter_count);
-    cpi->sf.skip_encode_frame &= (cm->frame_type != KEY_FRAME);
-    cpi->sf.skip_encode_frame &= cm->show_frame;
-  } else {
-    cpi->sf.skip_encode_frame = 0;
-  }
-
-#if 0
-  // Keep record of the total distortion this time around for future use
-  cpi->last_frame_distortion = cpi->frame_distortion;
-#endif
-}
 
 static int check_dual_ref_flags(VP9_COMP *cpi) {
   const int ref_flags = cpi->ref_frame_flags;
@@ -2575,28 +2478,18 @@
                      &dummy_rate, &dummy_dist, 1);
   }
 }
+// end RTC play code
 
-
-static void encode_rtc_frame_internal(VP9_COMP *cpi) {
+static void encode_frame_internal(VP9_COMP *cpi) {
   int mi_row;
-  MACROBLOCK * const x = &cpi->mb;
-  VP9_COMMON * const cm = &cpi->common;
-  MACROBLOCKD * const xd = &x->e_mbd;
+  MACROBLOCK *const x = &cpi->mb;
+  VP9_COMMON *const cm = &cpi->common;
+  MACROBLOCKD *const xd = &x->e_mbd;
 
 //  fprintf(stderr, "encode_frame_internal frame %d (%d) type %d\n",
 //           cpi->common.current_video_frame, cpi->common.show_frame,
 //           cm->frame_type);
 
-// debug output
-#if DBG_PRNT_SEGMAP
-  {
-    FILE *statsfile;
-    statsfile = fopen("segmap2.stt", "a");
-    fprintf(statsfile, "\n");
-    fclose(statsfile);
-  }
-#endif
-
   vp9_zero(cm->counts.switchable_interp);
   vp9_zero(cpi->tx_stepdown_count);
 
@@ -2606,7 +2499,7 @@
 
   xd->last_mi = cm->prev_mi;
 
-  vp9_zero(cpi->common.counts.mv);
+  vp9_zero(cm->counts.mv);
   vp9_zero(cpi->coef_counts);
   vp9_zero(cm->counts.eob_branch);
 
@@ -2619,7 +2512,6 @@
   vp9_initialize_rd_consts(cpi);
   vp9_initialize_me_consts(cpi, cm->base_qindex);
   switch_tx_mode(cpi);
-  cpi->sf.always_this_block_size = BLOCK_16X16;
 
   if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
     // Initialize encode frame context.
@@ -2658,9 +2550,12 @@
           // For each row of SBs in the frame
           vp9_tile_init(&tile, cm, tile_row, tile_col);
           for (mi_row = tile.mi_row_start;
-               mi_row < tile.mi_row_end; mi_row += 8)
-            encode_rtc_sb_row(cpi, &tile, mi_row, &tp);
-
+               mi_row < tile.mi_row_end; mi_row += 8) {
+            if (cpi->sf.use_pick_mode)
+              encode_rtc_sb_row(cpi, &tile, mi_row, &tp);
+            else
+              encode_sb_row(cpi, &tile, mi_row, &tp);
+          }
           cpi->tok_count[tile_row][tile_col] = (unsigned int)(tp - tp_old);
           assert(tp - cpi->tok <= get_token_alloc(cm->mb_rows, cm->mb_cols));
         }
@@ -2690,8 +2585,6 @@
   cpi->last_frame_distortion = cpi->frame_distortion;
 #endif
 }
-// end RTC play code
-
 
 void vp9_encode_frame(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
@@ -2716,7 +2609,7 @@
     }
   }
 
-  if (cpi->sf.RD) {
+  if (cpi->sf.frame_parameter_update) {
     int i;
     REFERENCE_MODE reference_mode;
     /*
@@ -2766,10 +2659,7 @@
     select_tx_mode(cpi);
     cm->reference_mode = reference_mode;
 
-    if (cpi->sf.super_fast_rtc)
-      encode_rtc_frame_internal(cpi);
-    else
-      encode_frame_internal(cpi);
+    encode_frame_internal(cpi);
 
     for (i = 0; i < REFERENCE_MODES; ++i) {
       const int diff = (int) (cpi->rd_comp_pred_diff[i] / cm->MBs);
@@ -2849,10 +2739,7 @@
   } else {
     // Force the usage of the BILINEAR interp_filter.
     cm->interp_filter = BILINEAR;
-    if (cpi->sf.super_fast_rtc)
-      encode_rtc_frame_internal(cpi);
-    else
-      encode_frame_internal(cpi);
+    encode_frame_internal(cpi);
   }
 }
 
@@ -2929,7 +2816,7 @@
   const int mi_height = num_8x8_blocks_high_lookup[bsize];
   x->skip_recode = !x->select_txfm_size && mbmi->sb_type >= BLOCK_8X8 &&
                    (cpi->oxcf.aq_mode != COMPLEXITY_AQ) &&
-                   !cpi->sf.super_fast_rtc;
+                   !cpi->sf.use_pick_mode;
   x->skip_optimize = ctx->is_coded;
   ctx->is_coded = 1;
   x->use_lp32x32fdct = cpi->sf.use_lp32x32fdct;
@@ -2960,9 +2847,10 @@
   }
 
   if (!is_inter_block(mbmi)) {
+    int plane;
     mbmi->skip_coeff = 1;
-    vp9_encode_intra_block_y(x, MAX(bsize, BLOCK_8X8));
-    vp9_encode_intra_block_uv(x, MAX(bsize, BLOCK_8X8));
+    for (plane = 0; plane < MAX_MB_PLANE; ++plane)
+      vp9_encode_intra_block_plane(x, MAX(bsize, BLOCK_8X8), plane);
     if (output_enabled)
       sum_intra_stats(&cm->counts, mi);
   } else {
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index c7507c1..ad28f31 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -24,6 +24,17 @@
 #include "vp9/encoder/vp9_rdopt.h"
 #include "vp9/encoder/vp9_tokenize.h"
 
+struct optimize_ctx {
+  ENTROPY_CONTEXT ta[MAX_MB_PLANE][16];
+  ENTROPY_CONTEXT tl[MAX_MB_PLANE][16];
+};
+
+struct encode_b_args {
+  MACROBLOCK *x;
+  struct optimize_ctx *ctx;
+  unsigned char *skip_coeff;
+};
+
 void vp9_subtract_block_c(int rows, int cols,
                           int16_t *diff_ptr, ptrdiff_t diff_stride,
                           const uint8_t *src_ptr, ptrdiff_t src_stride,
@@ -337,11 +348,9 @@
                            pd->above_context, pd->left_context,
                            num_4x4_w, num_4x4_h);
 }
-void vp9_xform_quant(int plane, int block, BLOCK_SIZE plane_bsize,
-                     TX_SIZE tx_size, void *arg) {
-  struct encode_b_args* const args = arg;
-  MACROBLOCK* const x = args->x;
-  MACROBLOCKD* const xd = &x->e_mbd;
+void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
+                     BLOCK_SIZE plane_bsize, TX_SIZE tx_size) {
+  MACROBLOCKD *const xd = &x->e_mbd;
   struct macroblock_plane *const p = &x->plane[plane];
   struct macroblockd_plane *const pd = &xd->plane[plane];
   int16_t *coeff = BLOCK_OFFSET(p->coeff, block);
@@ -420,7 +429,7 @@
   }
 
   if (!x->skip_recode)
-    vp9_xform_quant(plane, block, plane_bsize, tx_size, arg);
+    vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
 
   if (x->optimize && (!x->skip_recode || !x->skip_optimize)) {
     vp9_optimize_b(plane, block, plane_bsize, tx_size, x, ctx);
@@ -468,7 +477,7 @@
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
   dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
 
-  vp9_xform_quant(plane, block, plane_bsize, tx_size, arg);
+  vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
 
   if (p->eobs[block] == 0)
     return;
@@ -508,8 +517,8 @@
   vp9_foreach_transformed_block(xd, bsize, encode_block, &arg);
 }
 
-void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
-                            TX_SIZE tx_size, void *arg) {
+static void encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
+                               TX_SIZE tx_size, void *arg) {
   struct encode_b_args* const args = arg;
   MACROBLOCK *const x = args->x;
   MACROBLOCKD *const xd = &x->e_mbd;
@@ -642,21 +651,20 @@
     *(args->skip_coeff) = 0;
 }
 
-void vp9_encode_intra_block_y(MACROBLOCK *x, BLOCK_SIZE bsize) {
-  MACROBLOCKD* const xd = &x->e_mbd;
-  struct optimize_ctx ctx;
-  MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
-  struct encode_b_args arg = {x, &ctx, &mbmi->skip_coeff};
-
-  vp9_foreach_transformed_block_in_plane(xd, bsize, 0, vp9_encode_block_intra,
-                                     &arg);
+void vp9_encode_block_intra(MACROBLOCK *x, int plane, int block,
+                            BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
+                            unsigned char *skip_coeff) {
+  struct encode_b_args arg = {x, NULL, skip_coeff};
+  encode_block_intra(plane, block, plane_bsize, tx_size, &arg);
 }
-void vp9_encode_intra_block_uv(MACROBLOCK *x, BLOCK_SIZE bsize) {
-  MACROBLOCKD* const xd = &x->e_mbd;
-  struct optimize_ctx ctx;
-  MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
-  struct encode_b_args arg = {x, &ctx, &mbmi->skip_coeff};
-  vp9_foreach_transformed_block_uv(xd, bsize, vp9_encode_block_intra, &arg);
+
+
+void vp9_encode_intra_block_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane) {
+  const MACROBLOCKD *const xd = &x->e_mbd;
+  struct encode_b_args arg = {x, NULL, &xd->mi_8x8[0]->mbmi.skip_coeff};
+
+  vp9_foreach_transformed_block_in_plane(xd, bsize, plane, encode_block_intra,
+                                         &arg);
 }
 
 int vp9_encode_intra(MACROBLOCK *x, int use_16x16_pred) {
@@ -667,6 +675,6 @@
   mbmi->tx_size = use_16x16_pred ? (mbmi->sb_type >= BLOCK_16X16 ? TX_16X16
                                                                  : TX_8X8)
                                    : TX_4X4;
-  vp9_encode_intra_block_y(x, mbmi->sb_type);
+  vp9_encode_intra_block_plane(x, mbmi->sb_type, 0);
   return vp9_get_mb_ss(x->plane[0].src_diff);
 }
diff --git a/vp9/encoder/vp9_encodemb.h b/vp9/encoder/vp9_encodemb.h
index 9f6c9f0..cf7097d 100644
--- a/vp9/encoder/vp9_encodemb.h
+++ b/vp9/encoder/vp9_encodemb.h
@@ -20,32 +20,21 @@
 extern "C" {
 #endif
 
-struct optimize_ctx {
-  ENTROPY_CONTEXT ta[MAX_MB_PLANE][16];
-  ENTROPY_CONTEXT tl[MAX_MB_PLANE][16];
-};
-
-struct encode_b_args {
-  MACROBLOCK *x;
-  struct optimize_ctx *ctx;
-  unsigned char *skip_coeff;
-};
-
 void vp9_encode_sb(MACROBLOCK *x, BLOCK_SIZE bsize);
 void vp9_encode_sby(MACROBLOCK *x, BLOCK_SIZE bsize);
 
-void vp9_xform_quant(int plane, int block, BLOCK_SIZE plane_bsize,
-                     TX_SIZE tx_size, void *arg);
+void vp9_xform_quant(MACROBLOCK *x, int plane, int block,
+                     BLOCK_SIZE plane_bsize, TX_SIZE tx_size);
 
 void vp9_subtract_sby(MACROBLOCK *x, BLOCK_SIZE bsize);
 void vp9_subtract_sbuv(MACROBLOCK *x, BLOCK_SIZE bsize);
 void vp9_subtract_sb(MACROBLOCK *x, BLOCK_SIZE bsize);
 
-void vp9_encode_block_intra(int plane, int block, BLOCK_SIZE plane_bsize,
-                            TX_SIZE tx_size, void *arg);
+void vp9_encode_block_intra(MACROBLOCK *x, int plane, int block,
+                            BLOCK_SIZE plane_bsize, TX_SIZE tx_size,
+                            unsigned char *skip_coeff);
 
-void vp9_encode_intra_block_y(MACROBLOCK *x, BLOCK_SIZE bsize);
-void vp9_encode_intra_block_uv(MACROBLOCK *x, BLOCK_SIZE bsize);
+void vp9_encode_intra_block_plane(MACROBLOCK *x, BLOCK_SIZE bsize, int plane);
 
 int vp9_encode_intra(MACROBLOCK *x, int use_16x16_pred);
 
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 838f74e..3e04c2f 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -902,8 +902,8 @@
   return fclamp(pow(error_term, power_term), 0.05, 5.0);
 }
 
-static int estimate_max_q(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
-                          int section_target_bandwitdh) {
+int vp9_twopass_worst_quality(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
+                              int section_target_bandwitdh) {
   int q;
   const int num_mbs = cpi->common.MBs;
   int target_norm_bits_per_mb;
@@ -2275,15 +2275,14 @@
   vp9_clear_system_state();
 
   if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
-    rc->active_worst_quality = cpi->oxcf.cq_level;
+    twopass->active_worst_quality = cpi->oxcf.cq_level;
   } else if (cm->current_video_frame == 0) {
     // Special case code for first frame.
     const int section_target_bandwidth = (int)(twopass->bits_left /
                                                frames_left);
-    const int tmp_q = estimate_max_q(cpi, &twopass->total_left_stats,
-                                     section_target_bandwidth);
-
-    rc->active_worst_quality = tmp_q;
+    const int tmp_q = vp9_twopass_worst_quality(cpi, &twopass->total_left_stats,
+                                                section_target_bandwidth);
+    twopass->active_worst_quality = tmp_q;
     rc->ni_av_qi = tmp_q;
     rc->avg_q = vp9_convert_qindex_to_q(tmp_q);
 
@@ -2328,11 +2327,11 @@
 
     if (twopass->gf_zeromotion_pct > 995) {
       // As long as max_thresh for encode breakout is small enough, it is ok
-      // to enable it for no-show frame, i.e. set enable_encode_breakout to 2.
+      // to enable it for show frame, i.e. set allow_encode_breakout to 2.
       if (!cm->show_frame)
-        cpi->enable_encode_breakout = 0;
+        cpi->allow_encode_breakout = ENCODE_BREAKOUT_DISABLED;
       else
-        cpi->enable_encode_breakout = 2;
+        cpi->allow_encode_breakout = ENCODE_BREAKOUT_LIMITED;
     }
 
     rc->frames_till_gf_update_due = rc->baseline_gf_interval;
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index 19b5981..83e337b 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -10,20 +10,88 @@
 
 #ifndef VP9_ENCODER_VP9_FIRSTPASS_H_
 #define VP9_ENCODER_VP9_FIRSTPASS_H_
-#include "vp9/encoder/vp9_onyx_int.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-void vp9_init_first_pass(VP9_COMP *cpi);
-void vp9_rc_get_first_pass_params(VP9_COMP *cpi);
-void vp9_first_pass(VP9_COMP *cpi);
-void vp9_end_first_pass(VP9_COMP *cpi);
+typedef struct {
+  double frame;
+  double intra_error;
+  double coded_error;
+  double sr_coded_error;
+  double ssim_weighted_pred_err;
+  double pcnt_inter;
+  double pcnt_motion;
+  double pcnt_second_ref;
+  double pcnt_neutral;
+  double MVr;
+  double mvr_abs;
+  double MVc;
+  double mvc_abs;
+  double MVrv;
+  double MVcv;
+  double mv_in_out_count;
+  double new_mv_count;
+  double duration;
+  double count;
+} FIRSTPASS_STATS;
 
-void vp9_init_second_pass(VP9_COMP *cpi);
-void vp9_rc_get_second_pass_params(VP9_COMP *cpi);
-void vp9_end_second_pass(VP9_COMP *cpi);
+struct twopass_rc {
+  unsigned int section_intra_rating;
+  unsigned int next_iiratio;
+  unsigned int this_iiratio;
+  FIRSTPASS_STATS total_stats;
+  FIRSTPASS_STATS this_frame_stats;
+  FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start;
+  FIRSTPASS_STATS total_left_stats;
+  int first_pass_done;
+  int64_t bits_left;
+  int64_t clip_bits_total;
+  double avg_iiratio;
+  double modified_error_min;
+  double modified_error_max;
+  double modified_error_total;
+  double modified_error_left;
+  double kf_intra_err_min;
+  double gf_intra_err_min;
+  int static_scene_max_gf_interval;
+  int kf_bits;
+  // Remaining error from uncoded frames in a gf group. Two pass use only
+  int64_t gf_group_error_left;
+
+  // Projected total bits available for a key frame group of frames
+  int64_t kf_group_bits;
+
+  // Error score of frames still to be coded in kf group
+  int64_t kf_group_error_left;
+
+  // Projected Bits available for a group of frames including 1 GF or ARF
+  int64_t gf_group_bits;
+  // Bits for the golden frame or ARF - 2 pass only
+  int gf_bits;
+  int alt_extra_bits;
+
+  int sr_update_lag;
+
+  int kf_zeromotion_pct;
+  int gf_zeromotion_pct;
+
+  int active_worst_quality;
+};
+
+struct VP9_COMP;
+
+void vp9_init_first_pass(struct VP9_COMP *cpi);
+void vp9_rc_get_first_pass_params(struct VP9_COMP *cpi);
+void vp9_first_pass(struct VP9_COMP *cpi);
+void vp9_end_first_pass(struct VP9_COMP *cpi);
+
+void vp9_init_second_pass(struct VP9_COMP *cpi);
+void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi);
+void vp9_end_second_pass(struct VP9_COMP *cpi);
+int vp9_twopass_worst_quality(struct VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
+                              int section_target_bandwitdh);
 
 // Post encode update of the rate control parameters for 2-pass
 void vp9_twopass_postencode_update(struct VP9_COMP *cpi,
diff --git a/vp9/encoder/vp9_lookahead.c b/vp9/encoder/vp9_lookahead.c
index e6e59c0..4b642e2 100644
--- a/vp9/encoder/vp9_lookahead.c
+++ b/vp9/encoder/vp9_lookahead.c
@@ -11,9 +11,12 @@
 #include <stdlib.h>
 
 #include "./vpx_config.h"
+
 #include "vp9/common/vp9_common.h"
+
 #include "vp9/encoder/vp9_extend.h"
 #include "vp9/encoder/vp9_lookahead.h"
+#include "vp9/encoder/vp9_onyx_int.h"
 
 struct lookahead_ctx {
   unsigned int max_sz;         /* Absolute size of the queue */
diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c
index 198e11c..b2555e6 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -1338,76 +1338,55 @@
 
 int vp9_full_search_sad_c(const MACROBLOCK *x, MV *ref_mv,
                           int sad_per_bit, int distance,
-                          vp9_variance_fn_ptr_t *fn_ptr, int *mvjcost,
-                          int *mvcost[2],
-                          const MV *center_mv, int n) {
+                          vp9_variance_fn_ptr_t *fn_ptr,
+                          int *mvjcost, int *mvcost[2],
+                          const MV *center_mv, int block) {
+  int r, c;
   const MACROBLOCKD *const xd = &x->e_mbd;
   const uint8_t *const what = x->plane[0].src.buf;
   const int what_stride = x->plane[0].src.stride;
   const uint8_t *const in_what = xd->plane[0].pre[0].buf;
   const int in_what_stride = xd->plane[0].pre[0].stride;
-  MV *best_mv = &xd->mi_8x8[0]->bmi[n].as_mv[0].as_mv;
-  MV this_mv;
-  int bestsad = INT_MAX;
-  int r, c;
-  int thissad;
-  int ref_row = ref_mv->row;
-  int ref_col = ref_mv->col;
-  // Apply further limits to prevent us looking using vectors that stretch
-  // beyond the UMV border
-  const int row_min = MAX(ref_row - distance, x->mv_row_min);
-  const int row_max = MIN(ref_row + distance, x->mv_row_max);
-  const int col_min = MAX(ref_col - distance, x->mv_col_min);
-  const int col_max = MIN(ref_col + distance, x->mv_col_max);
-  const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+  const int row_min = MAX(ref_mv->row - distance, x->mv_row_min);
+  const int row_max = MIN(ref_mv->row + distance, x->mv_row_max);
+  const int col_min = MAX(ref_mv->col - distance, x->mv_col_min);
+  const int col_max = MIN(ref_mv->col + distance, x->mv_col_max);
   const int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
+  const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+  const uint8_t *best_address = &in_what[ref_mv->row * in_what_stride +
+                                         ref_mv->col];
+  int best_sad = fn_ptr->sdf(what, what_stride, best_address, in_what_stride,
+                             0x7fffffff) +
+      mvsad_err_cost(ref_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit);
+  MV *best_mv = &xd->mi_8x8[0]->bmi[block].as_mv[0].as_mv;
+  *best_mv = *ref_mv;
 
-  // Work out the mid point for the search
-  const uint8_t *bestaddress = &in_what[ref_row * in_what_stride + ref_col];
+  for (r = row_min; r < row_max; ++r) {
+    for (c = col_min; c < col_max; ++c) {
+      const MV this_mv = {r, c};
+      const uint8_t *check_here = &in_what[r * in_what_stride + c];
+      const int sad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
+                                  best_sad) +
+          mvsad_err_cost(&this_mv, &fcenter_mv,
+                         mvjsadcost, mvsadcost, sad_per_bit);
 
-  best_mv->row = ref_row;
-  best_mv->col = ref_col;
-
-  // Baseline value at the centre
-  bestsad = fn_ptr->sdf(what, what_stride, bestaddress,
-                        in_what_stride, 0x7fffffff)
-                           + mvsad_err_cost(best_mv, &fcenter_mv,
-                                            mvjsadcost, mvsadcost, sad_per_bit);
-
-  for (r = row_min; r < row_max; r++) {
-    const uint8_t *check_here = &in_what[r * in_what_stride + col_min];
-    this_mv.row = r;
-
-    for (c = col_min; c < col_max; c++) {
-      thissad = fn_ptr->sdf(what, what_stride, check_here, in_what_stride,
-                            bestsad);
-
-      this_mv.col = c;
-      thissad += mvsad_err_cost(&this_mv, &fcenter_mv,
-                                mvjsadcost, mvsadcost, sad_per_bit);
-
-      if (thissad < bestsad) {
-        bestsad = thissad;
-        best_mv->row = r;
-        best_mv->col = c;
-        bestaddress = check_here;
+      if (sad < best_sad) {
+        best_sad = sad;
+        *best_mv = this_mv;
+        best_address = check_here;
       }
-
-      check_here++;
     }
   }
 
-  this_mv.row = best_mv->row * 8;
-  this_mv.col = best_mv->col * 8;
-
-  if (bestsad < INT_MAX)
-    return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride,
-                      (unsigned int *)(&thissad)) +
-                      mv_err_cost(&this_mv, center_mv,
-                                  mvjcost, mvcost, x->errorperbit);
-  else
+  if (best_sad < INT_MAX) {
+    unsigned int unused;
+    const MV mv = {best_mv->row * 8, best_mv->col * 8};
+    return fn_ptr->vf(what, what_stride, best_address, in_what_stride, &unused)
+                + mv_err_cost(&mv, center_mv, mvjcost, mvcost, x->errorperbit);
+  } else {
     return INT_MAX;
+  }
 }
 
 int vp9_full_search_sadx3(const MACROBLOCK *x, MV *ref_mv,
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 917d3a4..9f4d47b 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -744,6 +744,8 @@
   sf->static_segmentation = 0;
   sf->adaptive_rd_thresh = 1;
   sf->recode_loop = ((speed < 1) ? ALLOW_RECODE : ALLOW_RECODE_KFMAXBW);
+  sf->encode_breakout_thresh = 1;
+
   if (speed == 1) {
     sf->use_square_partition_only = !frame_is_intra_only(cm);
     sf->less_rectangular_check = 1;
@@ -765,6 +767,7 @@
     sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+    sf->encode_breakout_thresh = 8;
   }
   if (speed >= 2) {
     sf->use_square_partition_only = !frame_is_intra_only(cm);
@@ -804,6 +807,7 @@
     sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
     sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+    sf->encode_breakout_thresh = 200;
   }
   if (speed >= 3) {
     sf->use_square_partition_only = 1;
@@ -826,11 +830,13 @@
     sf->use_fast_coef_updates = 2;
     sf->adaptive_rd_thresh = 4;
     sf->mode_skip_start = 6;
+    sf->encode_breakout_thresh = 400;
   }
   if (speed >= 4) {
     sf->optimize_coefficients = 0;
     sf->disable_split_mask = DISABLE_ALL_SPLIT;
     sf->use_fast_lpf_pick = 2;
+    sf->encode_breakout_thresh = 700;
   }
   if (speed >= 5) {
     int i;
@@ -842,10 +848,13 @@
       sf->intra_y_mode_mask[i] = INTRA_DC_H_V;
       sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY;
     }
-    sf->RD = 0;
+    sf->frame_parameter_update = 0;
+    sf->encode_breakout_thresh = 1000;
   }
   if (speed >= 6) {
-    sf->super_fast_rtc = 1;
+    sf->always_this_block_size = BLOCK_16X16;
+    sf->use_pick_mode = 1;
+    sf->encode_breakout_thresh = 1000;
   }
 }
 
@@ -863,7 +872,7 @@
     cpi->mode_chosen_counts[i] = 0;
 
   // best quality defaults
-  sf->RD = 1;
+  sf->frame_parameter_update = 1;
   sf->search_method = NSTEP;
   sf->recode_loop = ALLOW_RECODE;
   sf->subpel_search_method = SUBPEL_TREE;
@@ -904,7 +913,8 @@
   sf->use_fast_coef_updates = 0;
   sf->using_small_partition_info = 0;
   sf->mode_skip_start = MAX_MODES;  // Mode index at which mode skip mask set
-  sf->super_fast_rtc = 0;
+  sf->use_pick_mode = 0;
+  sf->encode_breakout_thresh = 0;
 
   switch (cpi->oxcf.mode) {
     case MODE_BESTQUALITY:
@@ -948,6 +958,10 @@
   }
 
   cpi->mb.optimize = cpi->sf.optimize_coefficients == 1 && cpi->pass != 1;
+
+  if (cpi->encode_breakout && cpi->oxcf.mode == MODE_REALTIME &&
+      sf->encode_breakout_thresh > cpi->encode_breakout)
+    cpi->encode_breakout = sf->encode_breakout_thresh;
 }
 
 static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
@@ -963,7 +977,7 @@
   if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
                                cpi->oxcf.width, cpi->oxcf.height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9_ENC_BORDER_IN_PIXELS))
+                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
     vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate altref buffer");
 }
@@ -1031,14 +1045,14 @@
   if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9_ENC_BORDER_IN_PIXELS))
+                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
     vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to reallocate last frame buffer");
 
   if (vp9_realloc_frame_buffer(&cpi->scaled_source,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9_ENC_BORDER_IN_PIXELS))
+                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
     vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to reallocate scaled source buffer");
 
@@ -1154,15 +1168,17 @@
       ++temporal_layer) {
     LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
     RATE_CONTROL *const lrc = &lc->rc;
-    lrc->active_worst_quality = q_trans[oxcf->worst_allowed_q];
     lrc->avg_frame_qindex[INTER_FRAME] = q_trans[oxcf->worst_allowed_q];
     lrc->last_q[INTER_FRAME] = q_trans[oxcf->worst_allowed_q];
-    lrc->ni_av_qi = lrc->active_worst_quality;
+    lrc->ni_av_qi = q_trans[oxcf->worst_allowed_q];
     lrc->total_actual_bits = 0;
     lrc->total_target_vs_actual = 0;
     lrc->ni_tot_qi = 0;
     lrc->tot_q = 0.0;
+    lrc->avg_q = 0.0;
     lrc->ni_frames = 0;
+    lrc->decimation_count = 0;
+    lrc->decimation_factor = 0;
     lrc->rate_correction_factor = 1.0;
     lrc->key_frame_rate_correction_factor = 1.0;
     lc->target_bandwidth = oxcf->ts_target_bitrate[temporal_layer] *
@@ -1199,7 +1215,6 @@
     // Update qp-related quantities.
     lrc->worst_quality = rc->worst_quality;
     lrc->best_quality = rc->best_quality;
-    lrc->active_worst_quality = rc->active_worst_quality;
   }
 }
 
@@ -1207,13 +1222,24 @@
 // for the current layer.
 static void update_layer_framerate(VP9_COMP *const cpi) {
   int temporal_layer = cpi->svc.temporal_layer_id;
+  const VP9_CONFIG *const oxcf = &cpi->oxcf;
   LAYER_CONTEXT *const lc = &cpi->svc.layer_context[temporal_layer];
   RATE_CONTROL *const lrc = &lc->rc;
-  lc->framerate = cpi->oxcf.framerate /
-      cpi->oxcf.ts_rate_decimator[temporal_layer];
-  lrc->av_per_frame_bandwidth = (int)(lc->target_bandwidth /
-      lc->framerate);
+  lc->framerate = oxcf->framerate / oxcf->ts_rate_decimator[temporal_layer];
+  lrc->av_per_frame_bandwidth = (int)(lc->target_bandwidth / lc->framerate);
   lrc->max_frame_bandwidth = cpi->rc.max_frame_bandwidth;
+  // Update the average layer frame size (non-cumulative per-frame-bw).
+  if (temporal_layer == 0) {
+    lc->avg_frame_size = lrc->av_per_frame_bandwidth;
+  } else {
+    double prev_layer_framerate = oxcf->framerate /
+        oxcf->ts_rate_decimator[temporal_layer - 1];
+    int prev_layer_target_bandwidth =
+        oxcf->ts_target_bitrate[temporal_layer - 1] * 1000;
+    lc->avg_frame_size =
+        (int)(lc->target_bandwidth - prev_layer_target_bandwidth) /
+        (lc->framerate - prev_layer_framerate);
+  }
 }
 
 // Prior to encoding the frame, set the layer context, for the current layer
@@ -1287,8 +1313,6 @@
   vp9_change_config(ptr, oxcf);
 
   // Initialize active best and worst q and average q values.
-  cpi->rc.active_worst_quality      = cpi->oxcf.worst_allowed_q;
-
   if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
     cpi->rc.avg_frame_qindex[0] = cpi->oxcf.worst_allowed_q;
     cpi->rc.avg_frame_qindex[1] = cpi->oxcf.worst_allowed_q;
@@ -1393,6 +1417,7 @@
     for (i = 0; i < MAX_SEGMENTS; i++)
       cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
   }
+  cpi->encode_breakout = cpi->oxcf.encode_breakout;
 
   // local file playback mode == really big buffer
   if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK) {
@@ -1434,9 +1459,6 @@
   cpi->rc.best_quality = cpi->oxcf.best_allowed_q;
 
   // active values should only be modified if out of new range
-  cpi->rc.active_worst_quality = clamp(cpi->rc.active_worst_quality,
-                                       cpi->rc.best_quality,
-                                       cpi->rc.worst_quality);
 
   cpi->cq_target_quality = cpi->oxcf.cq_level;
 
@@ -1452,7 +1474,7 @@
 
   if (cpi->initial_width) {
     // Increasing the size of the frame beyond the first seen frame, or some
-    // otherwise signalled maximum size, is not supported.
+    // otherwise signaled maximum size, is not supported.
     // TODO(jkoleszar): exit gracefully.
     assert(cm->width <= cpi->initial_width);
     assert(cm->height <= cpi->initial_height);
@@ -1467,14 +1489,13 @@
   cpi->speed = cpi->oxcf.cpu_used;
 
   if (cpi->oxcf.lag_in_frames == 0) {
-    // force to allowlag to 0 if lag_in_frames is 0;
+    // Force allow_lag to 0 if lag_in_frames is 0.
     cpi->oxcf.allow_lag = 0;
   } else if (cpi->oxcf.lag_in_frames > MAX_LAG_BUFFERS) {
-     // Limit on lag buffers as these are not currently dynamically allocated
+     // Limit on lag buffers as these are not currently dynamically allocated.
     cpi->oxcf.lag_in_frames = MAX_LAG_BUFFERS;
   }
 
-  // YX Temp
 #if CONFIG_MULTIPLE_ARF
   vp9_zero(cpi->alt_ref_source);
 #else
@@ -1729,11 +1750,6 @@
                                sizeof(*cpi->mbgraph_stats[i].mb_stats), 1));
   }
 
-#ifdef ENTROPY_STATS
-  if (cpi->pass != 1)
-    init_context_counters();
-#endif
-
   /*Initialize the feed-forward activity masking.*/
   cpi->activity_avg = 90 << 12;
   cpi->key_frame_frequency = cpi->oxcf.key_freq;
@@ -1838,7 +1854,7 @@
 
   cpi->output_pkt_list = oxcf->output_pkt_list;
 
-  cpi->enable_encode_breakout = 1;
+  cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
 
   if (cpi->pass == 1) {
     vp9_init_first_pass(cpi);
@@ -2664,7 +2680,7 @@
       vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
-                               VP9_ENC_BORDER_IN_PIXELS);
+                               VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
       scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf);
       cpi->scaled_ref_idx[ref_frame - 1] = new_fb;
     } else {
@@ -2717,7 +2733,7 @@
   if (cpi->twopass.total_left_stats.coded_error != 0.0)
     fprintf(f, "%10u %10d %10d %10d %10d %10d "
         "%10"PRId64" %10"PRId64" %10d "
-        "%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf %7.2lf"
+        "%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf"
         "%6d %6d %5d %5d %5d "
         "%10"PRId64" %10.3lf"
         "%10lf %8u %10d %10d %10d\n",
@@ -2730,7 +2746,7 @@
         cpi->rc.total_actual_bits, cm->base_qindex,
         vp9_convert_qindex_to_q(cm->base_qindex),
         (double)vp9_dc_quant(cm->base_qindex, 0) / 4.0,
-        vp9_convert_qindex_to_q(cpi->rc.active_worst_quality), cpi->rc.avg_q,
+        cpi->rc.avg_q,
         vp9_convert_qindex_to_q(cpi->rc.ni_av_qi),
         vp9_convert_qindex_to_q(cpi->cq_target_quality),
         cpi->refresh_last_frame, cpi->refresh_golden_frame,
@@ -2767,10 +2783,10 @@
 static void encode_without_recode_loop(VP9_COMP *cpi,
                                        size_t *size,
                                        uint8_t *dest,
-                                       int *q) {
+                                       int q) {
   VP9_COMMON *const cm = &cpi->common;
   vp9_clear_system_state();  // __asm emms;
-  vp9_set_quantizer(cpi, *q);
+  vp9_set_quantizer(cpi, q);
 
   // Set up entropy context depending on frame type. The decoder mandates
   // the use of the default context, index 0, for keyframes and inter
@@ -2804,7 +2820,7 @@
 static void encode_with_recode_loop(VP9_COMP *cpi,
                                     size_t *size,
                                     uint8_t *dest,
-                                    int *q,
+                                    int q,
                                     int bottom_index,
                                     int top_index) {
   VP9_COMMON *const cm = &cpi->common;
@@ -2824,7 +2840,7 @@
   do {
     vp9_clear_system_state();  // __asm emms;
 
-    vp9_set_quantizer(cpi, *q);
+    vp9_set_quantizer(cpi, q);
 
     if (loop_count == 0) {
       // Set up entropy context depending on frame type. The decoder mandates
@@ -2865,7 +2881,7 @@
     if (cpi->sf.recode_loop >= ALLOW_RECODE_KFARFGF) {
       vp9_save_coding_context(cpi);
       cpi->dummy_packing = 1;
-      if (!cpi->sf.super_fast_rtc)
+      if (!cpi->sf.use_pick_mode)
         vp9_pack_bitstream(cpi, dest, size);
 
       cpi->rc.projected_frame_size = (*size) << 3;
@@ -2881,7 +2897,7 @@
       if ((cm->frame_type == KEY_FRAME) &&
            cpi->rc.this_key_frame_forced &&
            (cpi->rc.projected_frame_size < cpi->rc.max_frame_bandwidth)) {
-        int last_q = *q;
+        int last_q = q;
         int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
 
         int high_err_target = cpi->ambient_err;
@@ -2897,32 +2913,32 @@
             (kf_err > low_err_target &&
              cpi->rc.projected_frame_size <= frame_under_shoot_limit)) {
           // Lower q_high
-          q_high = *q > q_low ? *q - 1 : q_low;
+          q_high = q > q_low ? q - 1 : q_low;
 
           // Adjust Q
-          *q = ((*q) * high_err_target) / kf_err;
-          *q = MIN((*q), (q_high + q_low) >> 1);
+          q = (q * high_err_target) / kf_err;
+          q = MIN(q, (q_high + q_low) >> 1);
         } else if (kf_err < low_err_target &&
                    cpi->rc.projected_frame_size >= frame_under_shoot_limit) {
           // The key frame is much better than the previous frame
           // Raise q_low
-          q_low = *q < q_high ? *q + 1 : q_high;
+          q_low = q < q_high ? q + 1 : q_high;
 
           // Adjust Q
-          *q = ((*q) * low_err_target) / kf_err;
-          *q = MIN((*q), (q_high + q_low + 1) >> 1);
+          q = (q * low_err_target) / kf_err;
+          q = MIN(q, (q_high + q_low + 1) >> 1);
         }
 
         // Clamp Q to upper and lower limits:
-        *q = clamp(*q, q_low, q_high);
+        q = clamp(q, q_low, q_high);
 
-        loop = *q != last_q;
+        loop = q != last_q;
       } else if (recode_loop_test(
           cpi, frame_over_shoot_limit, frame_under_shoot_limit,
-          *q, MAX(q_high, top_index), bottom_index)) {
+          q, MAX(q_high, top_index), bottom_index)) {
         // Is the projected frame size out of range and are we allowed
         // to attempt to recode.
-        int last_q = *q;
+        int last_q = q;
         int retries = 0;
 
         // Frame size out of permitted range:
@@ -2935,23 +2951,23 @@
             q_high = cpi->rc.worst_quality;
 
           // Raise Qlow as to at least the current value
-          q_low = *q < q_high ? *q + 1 : q_high;
+          q_low = q < q_high ? q + 1 : q_high;
 
           if (undershoot_seen || loop_count > 1) {
             // Update rate_correction_factor unless
             vp9_rc_update_rate_correction_factors(cpi, 1);
 
-            *q = (q_high + q_low + 1) / 2;
+            q = (q_high + q_low + 1) / 2;
           } else {
             // Update rate_correction_factor unless
             vp9_rc_update_rate_correction_factors(cpi, 0);
 
-            *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+            q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
                                    bottom_index, MAX(q_high, top_index));
 
-            while (*q < q_low && retries < 10) {
+            while (q < q_low && retries < 10) {
               vp9_rc_update_rate_correction_factors(cpi, 0);
-              *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+              q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
                                      bottom_index, MAX(q_high, top_index));
               retries++;
             }
@@ -2960,27 +2976,27 @@
           overshoot_seen = 1;
         } else {
           // Frame is too small
-          q_high = *q > q_low ? *q - 1 : q_low;
+          q_high = q > q_low ? q - 1 : q_low;
 
           if (overshoot_seen || loop_count > 1) {
             vp9_rc_update_rate_correction_factors(cpi, 1);
-            *q = (q_high + q_low) / 2;
+            q = (q_high + q_low) / 2;
           } else {
             vp9_rc_update_rate_correction_factors(cpi, 0);
-            *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+            q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
                                    bottom_index, top_index);
             // Special case reset for qlow for constrained quality.
             // This should only trigger where there is very substantial
             // undershoot on a frame and the auto cq level is above
             // the user passsed in value.
             if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY &&
-                *q < q_low) {
-              q_low = *q;
+                q < q_low) {
+              q_low = q;
             }
 
-            while (*q > q_high && retries < 10) {
+            while (q > q_high && retries < 10) {
               vp9_rc_update_rate_correction_factors(cpi, 0);
-              *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+              q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
                                      bottom_index, top_index);
               retries++;
             }
@@ -2990,9 +3006,9 @@
         }
 
         // Clamp Q to upper and lower limits:
-        *q = clamp(*q, q_low, q_high);
+        q = clamp(q, q_low, q_high);
 
-        loop = *q != last_q;
+        loop = q != last_q;
       } else {
         loop = 0;
       }
@@ -3199,9 +3215,7 @@
 #endif
 
   // Decide q and q bounds.
-  q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
-                                        &bottom_index,
-                                        &top_index);
+  q = vp9_rc_pick_q_and_bounds(cpi, &bottom_index, &top_index);
 
   if (!frame_is_intra_only(cm)) {
     cm->interp_filter = DEFAULT_INTERP_FILTER;
@@ -3210,9 +3224,9 @@
   }
 
   if (cpi->sf.recode_loop == DISALLOW_RECODE) {
-    encode_without_recode_loop(cpi, size, dest, &q);
+    encode_without_recode_loop(cpi, size, dest, q);
   } else {
-    encode_with_recode_loop(cpi, size, dest, &q, bottom_index, top_index);
+    encode_with_recode_loop(cpi, size, dest, q, bottom_index, top_index);
   }
 
   // Special case code to reduce pulsing when key frames are forced at a
@@ -3272,10 +3286,6 @@
     }
   }
 
-#ifdef ENTROPY_STATS
-  vp9_update_mode_context_stats(cpi);
-#endif
-
 #if 0
   output_frame_level_debug_stats(cpi);
 #endif
@@ -3392,7 +3402,7 @@
 
 static void Pass2Encode(VP9_COMP *cpi, size_t *size,
                         uint8_t *dest, unsigned int *frame_flags) {
-  cpi->enable_encode_breakout = 1;
+  cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
 
   vp9_rc_get_second_pass_params(cpi);
   encode_frame_to_data_rate(cpi, size, dest, frame_flags);
@@ -3678,7 +3688,7 @@
   vp9_realloc_frame_buffer(get_frame_new_buffer(cm),
                            cm->width, cm->height,
                            cm->subsampling_x, cm->subsampling_y,
-                           VP9_ENC_BORDER_IN_PIXELS);
+                           VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
 
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
     const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
@@ -3943,11 +3953,11 @@
     cm->width = width;
     if (cm->width * 5 < cpi->initial_width) {
       cm->width = cpi->initial_width / 5 + 1;
-      printf("Warning: Desired width too small, changed to %d \n", cm->width);
+      printf("Warning: Desired width too small, changed to %d\n", cm->width);
     }
     if (cm->width > cpi->initial_width) {
       cm->width = cpi->initial_width;
-      printf("Warning: Desired width too large, changed to %d \n", cm->width);
+      printf("Warning: Desired width too large, changed to %d\n", cm->width);
     }
   }
 
@@ -3955,11 +3965,11 @@
     cm->height = height;
     if (cm->height * 5 < cpi->initial_height) {
       cm->height = cpi->initial_height / 5 + 1;
-      printf("Warning: Desired height too small, changed to %d \n", cm->height);
+      printf("Warning: Desired height too small, changed to %d\n", cm->height);
     }
     if (cm->height > cpi->initial_height) {
       cm->height = cpi->initial_height;
-      printf("Warning: Desired height too large, changed to %d \n", cm->height);
+      printf("Warning: Desired height too large, changed to %d\n", cm->height);
     }
   }
 
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 05b4634..88a0419 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -23,6 +23,7 @@
 #include "vp9/common/vp9_onyxc_int.h"
 
 #include "vp9/encoder/vp9_encodemb.h"
+#include "vp9/encoder/vp9_firstpass.h"
 #include "vp9/encoder/vp9_lookahead.h"
 #include "vp9/encoder/vp9_mbgraph.h"
 #include "vp9/encoder/vp9_mcomp.h"
@@ -44,7 +45,7 @@
 #else
 #define MIN_GF_INTERVAL             4
 #endif
-#define DEFAULT_GF_INTERVAL         11
+#define DEFAULT_GF_INTERVAL         10
 #define DEFAULT_KF_BOOST            2000
 #define DEFAULT_GF_BOOST            2000
 
@@ -79,28 +80,6 @@
   FRAME_CONTEXT fc;
 } CODING_CONTEXT;
 
-typedef struct {
-  double frame;
-  double intra_error;
-  double coded_error;
-  double sr_coded_error;
-  double ssim_weighted_pred_err;
-  double pcnt_inter;
-  double pcnt_motion;
-  double pcnt_second_ref;
-  double pcnt_neutral;
-  double MVr;
-  double mvr_abs;
-  double MVc;
-  double mvc_abs;
-  double MVrv;
-  double MVcv;
-  double mv_in_out_count;
-  double new_mv_count;
-  double duration;
-  double count;
-} FIRSTPASS_STATS;
-
 // This enumerator type needs to be kept aligned with the mode order in
 // const MODE_DEFINITION vp9_mode_order[MAX_MODES] used in the rd code.
 typedef enum {
@@ -229,9 +208,18 @@
   ALLOW_RECODE = 3,
 } RECODE_LOOP_TYPE;
 
+typedef enum {
+  // encode_breakout is disabled.
+  ENCODE_BREAKOUT_DISABLED = 0,
+  // encode_breakout is enabled.
+  ENCODE_BREAKOUT_ENABLED = 1,
+  // encode_breakout is enabled with small max_thresh limit.
+  ENCODE_BREAKOUT_LIMITED = 2
+} ENCODE_BREAKOUT_TYPE;
+
 typedef struct {
-  // This flag refers to whether or not to perform rd optimization.
-  int RD;
+  // Frame level coding parameter update
+  int frame_parameter_update;
 
   // Motion search method (Diamond, NSTEP, Hex, Big Diamond, Square, etc).
   SEARCH_METHODS search_method;
@@ -411,8 +399,12 @@
   // by only looking at counts from 1/2 the bands.
   int use_fast_coef_updates;  // 0: 2-loop, 1: 1-loop, 2: 1-loop reduced
 
-  // This flag control the use of the new super fast rtc mode
-  int super_fast_rtc;
+  // This flag controls the use of non-RD mode decision.
+  int use_pick_mode;
+
+  // This variable sets the encode_breakout threshold. Currently, it is only
+  // enabled in real time mode.
+  int encode_breakout_thresh;
 } SPEED_FEATURES;
 
 typedef struct {
@@ -422,6 +414,7 @@
   int64_t optimal_buffer_level;
   int64_t maximum_buffer_size;
   double framerate;
+  int avg_frame_size;
 } LAYER_CONTEXT;
 
 typedef struct VP9_COMP {
@@ -566,6 +559,13 @@
   unsigned int max_mv_magnitude;
   int mv_step_param;
 
+  // Default value is 1. From first pass stats, encode_breakout may be disabled.
+  ENCODE_BREAKOUT_TYPE allow_encode_breakout;
+
+  // Get threshold from external input. In real time mode, it can be
+  // overwritten according to encoding speed.
+  int encode_breakout;
+
   unsigned char *segmentation_map;
 
   // segment threashold for encode breakout
@@ -587,46 +587,7 @@
   uint64_t time_pick_lpf;
   uint64_t time_encode_sb_row;
 
-  struct twopass_rc {
-    unsigned int section_intra_rating;
-    unsigned int next_iiratio;
-    unsigned int this_iiratio;
-    FIRSTPASS_STATS total_stats;
-    FIRSTPASS_STATS this_frame_stats;
-    FIRSTPASS_STATS *stats_in, *stats_in_end, *stats_in_start;
-    FIRSTPASS_STATS total_left_stats;
-    int first_pass_done;
-    int64_t bits_left;
-    int64_t clip_bits_total;
-    double avg_iiratio;
-    double modified_error_min;
-    double modified_error_max;
-    double modified_error_total;
-    double modified_error_left;
-    double kf_intra_err_min;
-    double gf_intra_err_min;
-    int static_scene_max_gf_interval;
-    int kf_bits;
-    // Remaining error from uncoded frames in a gf group. Two pass use only
-    int64_t gf_group_error_left;
-
-    // Projected total bits available for a key frame group of frames
-    int64_t kf_group_bits;
-
-    // Error score of frames still to be coded in kf group
-    int64_t kf_group_error_left;
-
-    // Projected Bits available for a group of frames including 1 GF or ARF
-    int64_t gf_group_bits;
-    // Bits for the golden frame or ARF - 2 pass only
-    int gf_bits;
-    int alt_extra_bits;
-
-    int sr_update_lag;
-
-    int kf_zeromotion_pct;
-    int gf_zeromotion_pct;
-  } twopass;
+  struct twopass_rc twopass;
 
   YV12_BUFFER_CONFIG alt_ref_buffer;
   YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS];
@@ -695,9 +656,6 @@
     LAYER_CONTEXT layer_context[VPX_TS_MAX_LAYERS];
   } svc;
 
-  int enable_encode_breakout;   // Default value is 1. From first pass stats,
-                                // encode_breakout may be disabled.
-
 #if CONFIG_MULTIPLE_ARF
   // ARF tracking variables.
   int multi_arf_enabled;
@@ -751,8 +709,6 @@
 
 void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size);
 
-void vp9_activity_masking(VP9_COMP *cpi, MACROBLOCK *x);
-
 void vp9_set_speed_features(VP9_COMP *cpi);
 
 int vp9_calc_ss_err(const YV12_BUFFER_CONFIG *source,
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index 1aaa416..3b4a7f6 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -170,6 +170,10 @@
   mbmi->ref_frame[1] = NONE;
   mbmi->tx_size = MIN(max_txsize_lookup[bsize],
                       tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
+  mbmi->interp_filter = cpi->common.interp_filter == SWITCHABLE ?
+                        EIGHTTAP : cpi->common.interp_filter;
+  mbmi->skip_coeff = 0;
+  mbmi->segment_id = 0;
 
   for (ref_frame = LAST_FRAME; ref_frame <= LAST_FRAME ; ++ref_frame) {
     x->pred_mv_sad[ref_frame] = INT_MAX;
@@ -195,7 +199,7 @@
     clamp_mv2(&frame_mv[NEARMV][ref_frame].as_mv, xd);
 
     for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
-      int rate = cost[this_mode - NEARESTMV];
+      int rate = cost[INTER_OFFSET(this_mode)];
       int64_t dist;
 
       if (this_mode == NEWMV) {
@@ -219,15 +223,7 @@
         mbmi->ref_frame[0] = ref_frame;
         mbmi->mv[0].as_int = frame_mv[this_mode][ref_frame].as_int;
         xd->mi_8x8[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
-        mbmi->interp_filter = cpi->common.interp_filter == SWITCHABLE ?
-            EIGHTTAP : cpi->common.interp_filter;
-
-        mbmi->ref_frame[1] = INTRA_FRAME;
-        mbmi->tx_size = max_txsize_lookup[bsize];
         mbmi->uv_mode = this_mode;
-        mbmi->skip_coeff = 0;
-        mbmi->sb_type = bsize;
-        mbmi->segment_id = 0;
       }
     }
   }
diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c
index a2eea1c..862573f 100644
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -79,55 +79,47 @@
                             const int16_t *dequant_ptr,
                             int zbin_oq_value, uint16_t *eob_ptr,
                             const int16_t *scan, const int16_t *iscan) {
-  int i, rc, eob;
-  int zbins[2], nzbins[2];
-  int x, y, z, sz;
+  const int zbins[2] = { ROUND_POWER_OF_TWO(zbin_ptr[0] + zbin_oq_value, 1),
+                         ROUND_POWER_OF_TWO(zbin_ptr[1] + zbin_oq_value, 1) };
+  const int nzbins[2] = {zbins[0] * -1, zbins[1] * -1};
+
   int idx = 0;
   int idx_arr[1024];
+  int i, eob = -1;
 
-  vpx_memset(qcoeff_ptr, 0, n_coeffs*sizeof(int16_t));
-  vpx_memset(dqcoeff_ptr, 0, n_coeffs*sizeof(int16_t));
-
-  eob = -1;
-
-  // Base ZBIN
-  zbins[0] = ROUND_POWER_OF_TWO(zbin_ptr[0] + zbin_oq_value, 1);
-  zbins[1] = ROUND_POWER_OF_TWO(zbin_ptr[1] + zbin_oq_value, 1);
-  nzbins[0] = zbins[0] * -1;
-  nzbins[1] = zbins[1] * -1;
+  vpx_memset(qcoeff_ptr, 0, n_coeffs * sizeof(int16_t));
+  vpx_memset(dqcoeff_ptr, 0, n_coeffs * sizeof(int16_t));
 
   if (!skip_block) {
     // Pre-scan pass
     for (i = 0; i < n_coeffs; i++) {
-      rc = scan[i];
-      z = coeff_ptr[rc];
+      const int rc = scan[i];
+      const int coeff = coeff_ptr[rc];
 
       // If the coefficient is out of the base ZBIN range, keep it for
       // quantization.
-      if (z >= zbins[rc != 0] || z <= nzbins[rc != 0])
+      if (coeff >= zbins[rc != 0] || coeff <= nzbins[rc != 0])
         idx_arr[idx++] = i;
     }
 
     // Quantization pass: only process the coefficients selected in
     // pre-scan pass. Note: idx can be zero.
     for (i = 0; i < idx; i++) {
-      rc = scan[idx_arr[i]];
+      const int rc = scan[idx_arr[i]];
+      const int coeff = coeff_ptr[rc];
+      const int coeff_sign = (coeff >> 31);
+      int tmp;
+      int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
+      abs_coeff += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
+      abs_coeff = clamp(abs_coeff, INT16_MIN, INT16_MAX);
+      tmp = ((((abs_coeff * quant_ptr[rc != 0]) >> 16) + abs_coeff) *
+               quant_shift_ptr[rc != 0]) >> 15;
 
-      z = coeff_ptr[rc];
-      sz = (z >> 31);                               // sign of z
-      x  = (z ^ sz) - sz;                           // x = abs(z)
+      qcoeff_ptr[rc] = (tmp ^ coeff_sign) - coeff_sign;
+      dqcoeff_ptr[rc] = qcoeff_ptr[rc] * dequant_ptr[rc != 0] / 2;
 
-      x += ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
-      x  = clamp(x, INT16_MIN, INT16_MAX);
-      y  = ((((x * quant_ptr[rc != 0]) >> 16) + x) *
-            quant_shift_ptr[rc != 0]) >> 15;      // quantize (x)
-
-      x  = (y ^ sz) - sz;                         // get the sign back
-      qcoeff_ptr[rc]  = x;                        // write to destination
-      dqcoeff_ptr[rc] = x * dequant_ptr[rc != 0] / 2;  // dequantized value
-
-      if (y)
-        eob = idx_arr[i];                         // last nonzero coeffs
+      if (tmp)
+        eob = idx_arr[i];
     }
   }
   *eob_ptr = eob + 1;
@@ -136,8 +128,8 @@
 void vp9_regular_quantize_b_4x4(MACROBLOCK *x, int plane, int block,
                                 const int16_t *scan, const int16_t *iscan) {
   MACROBLOCKD *const xd = &x->e_mbd;
-  struct macroblock_plane* p = &x->plane[plane];
-  struct macroblockd_plane* pd = &xd->plane[plane];
+  struct macroblock_plane *p = &x->plane[plane];
+  struct macroblockd_plane *pd = &xd->plane[plane];
 
   vp9_quantize_b(BLOCK_OFFSET(p->coeff, block),
            16, x->skip_block,
@@ -223,38 +215,30 @@
 }
 
 void vp9_mb_init_quantizer(VP9_COMP *cpi, MACROBLOCK *x) {
-  int i;
-  VP9_COMMON *const cm = &cpi->common;
+  const VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
-  int zbin_extra;
-  int segment_id = xd->mi_8x8[0]->mbmi.segment_id;
-  const int qindex = vp9_get_qindex(&cpi->common.seg, segment_id,
-                                    cpi->common.base_qindex);
-
-  int rdmult = vp9_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
+  const int segment_id = xd->mi_8x8[0]->mbmi.segment_id;
+  const int qindex = vp9_get_qindex(&cm->seg, segment_id, cm->base_qindex);
+  const int rdmult = vp9_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
+  const int zbin = cpi->zbin_mode_boost + x->act_zbin_adj;
+  int i;
 
   // Y
-  zbin_extra = (cpi->common.y_dequant[qindex][1] *
-                 (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
-
   x->plane[0].quant = cpi->y_quant[qindex];
   x->plane[0].quant_shift = cpi->y_quant_shift[qindex];
   x->plane[0].zbin = cpi->y_zbin[qindex];
   x->plane[0].round = cpi->y_round[qindex];
-  x->plane[0].zbin_extra = (int16_t)zbin_extra;
-  x->e_mbd.plane[0].dequant = cpi->common.y_dequant[qindex];
+  x->plane[0].zbin_extra = (int16_t)((cm->y_dequant[qindex][1] * zbin) >> 7);
+  xd->plane[0].dequant = cm->y_dequant[qindex];
 
   // UV
-  zbin_extra = (cpi->common.uv_dequant[qindex][1] *
-                (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
-
   for (i = 1; i < 3; i++) {
     x->plane[i].quant = cpi->uv_quant[qindex];
     x->plane[i].quant_shift = cpi->uv_quant_shift[qindex];
     x->plane[i].zbin = cpi->uv_zbin[qindex];
     x->plane[i].round = cpi->uv_round[qindex];
-    x->plane[i].zbin_extra = (int16_t)zbin_extra;
-    x->e_mbd.plane[i].dequant = cpi->common.uv_dequant[qindex];
+    x->plane[i].zbin_extra = (int16_t)((cm->uv_dequant[qindex][1] * zbin) >> 7);
+    xd->plane[i].dequant = cm->uv_dequant[qindex];
   }
 
 #if CONFIG_ALPHA
@@ -263,18 +247,14 @@
   x->plane[3].zbin = cpi->a_zbin[qindex];
   x->plane[3].round = cpi->a_round[qindex];
   x->plane[3].zbin_extra = (int16_t)zbin_extra;
-  x->e_mbd.plane[3].dequant = cpi->common.a_dequant[qindex];
+  xd->plane[3].dequant = cm->a_dequant[qindex];
 #endif
 
-  x->skip_block = vp9_segfeature_active(&cpi->common.seg, segment_id,
-                                        SEG_LVL_SKIP);
-
-  /* save this macroblock QIndex for vp9_update_zbin_extra() */
+  x->skip_block = vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
   x->q_index = qindex;
 
-  /* R/D setup */
-  cpi->mb.errorperbit = rdmult >> 6;
-  cpi->mb.errorperbit += (cpi->mb.errorperbit == 0);
+  x->errorperbit = rdmult >> 6;
+  x->errorperbit += (x->errorperbit == 0);
 
   vp9_initialize_me_consts(cpi, x->q_index);
 }
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index b258107..9afa064 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -215,7 +215,7 @@
                                    rc->av_per_frame_bandwidth >> 5);
   if (target < min_frame_target)
     target = min_frame_target;
-  if (cpi->refresh_golden_frame && rc->source_alt_ref_active) {
+  if (cpi->refresh_golden_frame && rc->is_src_frame_alt_ref) {
     // If there is an active ARF at this location use the minimum
     // bits on this frame even if it is a constructed arf.
     // The active maximum quantizer insures that an appropriate
@@ -460,14 +460,206 @@
   }
 }
 
-static int rc_pick_q_and_adjust_q_bounds_one_pass(const VP9_COMP *cpi,
-                                                  int *bottom_index,
-                                                  int *top_index) {
+static int calc_active_worst_quality_one_pass_vbr(const VP9_COMP *cpi) {
+  int active_worst_quality;
+  if (cpi->common.frame_type == KEY_FRAME) {
+    if (cpi->common.current_video_frame == 0) {
+      active_worst_quality = cpi->rc.worst_quality;
+    } else {
+      // Choose active worst quality twice as large as the last q.
+      active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 2;
+    }
+  } else if (!cpi->rc.is_src_frame_alt_ref &&
+             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+    if (cpi->common.current_video_frame == 1) {
+      active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 5 / 4;
+    } else {
+      // Choose active worst quality twice as large as the last q.
+      active_worst_quality = cpi->rc.last_q[INTER_FRAME];
+    }
+  } else {
+    if (cpi->common.current_video_frame == 1) {
+      active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 2;
+    } else {
+      // Choose active worst quality twice as large as the last q.
+      active_worst_quality = cpi->rc.last_q[INTER_FRAME] * 2;
+    }
+  }
+  if (active_worst_quality > cpi->rc.worst_quality)
+    active_worst_quality = cpi->rc.worst_quality;
+  return active_worst_quality;
+}
+
+// Adjust active_worst_quality level based on buffer level.
+static int calc_active_worst_quality_one_pass_cbr(const VP9_COMP *cpi) {
+  // Adjust active_worst_quality: If buffer is above the optimal/target level,
+  // bring active_worst_quality down depending on fullness of buffer.
+  // If buffer is below the optimal level, let the active_worst_quality go from
+  // ambient Q (at buffer = optimal level) to worst_quality level
+  // (at buffer = critical level).
+  const VP9_CONFIG *oxcf = &cpi->oxcf;
+  const RATE_CONTROL *rc = &cpi->rc;
+  // int active_worst_quality = rc->active_worst_quality;
+  // Maximum limit for down adjustment, ~20%.
+  // Buffer level below which we push active_worst to worst_quality.
+  int critical_level = oxcf->optimal_buffer_level >> 2;
+  int adjustment = 0;
+  int buff_lvl_step = 0;
+  int active_worst_quality;
+  if (cpi->common.frame_type == KEY_FRAME)
+    return rc->worst_quality;
+  if (cpi->common.current_video_frame > 1)
+    active_worst_quality = MIN(rc->worst_quality,
+                               rc->avg_frame_qindex[INTER_FRAME] * 5 / 4);
+  else
+    active_worst_quality = MIN(rc->worst_quality,
+                               rc->avg_frame_qindex[KEY_FRAME] * 3 / 2);
+  if (rc->buffer_level > oxcf->optimal_buffer_level) {
+    // Adjust down.
+    int max_adjustment_down = active_worst_quality / 3;
+    if (max_adjustment_down) {
+      buff_lvl_step = (int)((oxcf->maximum_buffer_size -
+          oxcf->optimal_buffer_level) / max_adjustment_down);
+      if (buff_lvl_step)
+        adjustment = (int)((rc->buffer_level - oxcf->optimal_buffer_level) /
+                            buff_lvl_step);
+      active_worst_quality -= adjustment;
+    }
+  } else if (rc->buffer_level > critical_level) {
+    // Adjust up from ambient Q.
+    if (critical_level) {
+      buff_lvl_step = (oxcf->optimal_buffer_level - critical_level);
+      if (buff_lvl_step) {
+        adjustment = (rc->worst_quality - rc->avg_frame_qindex[INTER_FRAME]) *
+                         (oxcf->optimal_buffer_level - rc->buffer_level) /
+                             buff_lvl_step;
+      }
+      active_worst_quality = rc->avg_frame_qindex[INTER_FRAME] + adjustment;
+    }
+  } else {
+    // Set to worst_quality if buffer is below critical level.
+    active_worst_quality = rc->worst_quality;
+  }
+  return active_worst_quality;
+}
+
+static int rc_pick_q_and_bounds_one_pass_cbr(const VP9_COMP *cpi,
+                                             int *bottom_index,
+                                             int *top_index) {
+  const VP9_COMMON *const cm = &cpi->common;
+  const RATE_CONTROL *const rc = &cpi->rc;
+  int active_best_quality;
+  int active_worst_quality = calc_active_worst_quality_one_pass_cbr(cpi);
+  int q;
+
+  if (frame_is_intra_only(cm)) {
+    active_best_quality = rc->best_quality;
+    // Handle the special case for key frames forced when we have75 reached
+    // the maximum key frame interval. Here force the Q to a range
+    // based on the ambient Q to reduce the risk of popping.
+    if (rc->this_key_frame_forced) {
+      int qindex = rc->last_boosted_qindex;
+      double last_boosted_q = vp9_convert_qindex_to_q(qindex);
+      int delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
+                                            (last_boosted_q * 0.75));
+      active_best_quality = MAX(qindex + delta_qindex, rc->best_quality);
+    } else if (cm->current_video_frame > 0) {
+      // not first frame of one pass and kf_boost is set
+      double q_adj_factor = 1.0;
+      double q_val;
+
+      active_best_quality = get_active_quality(rc->avg_frame_qindex[KEY_FRAME],
+                                               rc->kf_boost,
+                                               kf_low, kf_high,
+                                               kf_low_motion_minq,
+                                               kf_high_motion_minq);
+
+      // Allow somewhat lower kf minq with small image formats.
+      if ((cm->width * cm->height) <= (352 * 288)) {
+        q_adj_factor -= 0.25;
+      }
+
+      // Convert the adjustment factor to a qindex delta
+      // on active_best_quality.
+      q_val = vp9_convert_qindex_to_q(active_best_quality);
+      active_best_quality += vp9_compute_qdelta(cpi, q_val, q_val *
+                                                   q_adj_factor);
+    }
+  } else if (!rc->is_src_frame_alt_ref &&
+             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+    // Use the lower of active_worst_quality and recent
+    // average Q as basis for GF/ARF best Q limit unless last frame was
+    // a key frame.
+    if (rc->frames_since_key > 1 &&
+        rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
+      q = rc->avg_frame_qindex[INTER_FRAME];
+    } else {
+      q = active_worst_quality;
+    }
+    active_best_quality = get_active_quality(
+        q, rc->gfu_boost, gf_low, gf_high,
+        gf_low_motion_minq, gf_high_motion_minq);
+  } else {
+    // Use the lower of active_worst_quality and recent/average Q.
+    if (cm->current_video_frame > 1) {
+      if (rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
+        active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
+      else
+        active_best_quality = inter_minq[active_worst_quality];
+    } else {
+      if (rc->avg_frame_qindex[KEY_FRAME] < active_worst_quality)
+        active_best_quality = inter_minq[rc->avg_frame_qindex[KEY_FRAME]];
+      else
+        active_best_quality = inter_minq[active_worst_quality];
+    }
+  }
+
+  // Clip the active best and worst quality values to limits
+  active_best_quality = clamp(active_best_quality,
+                              rc->best_quality, rc->worst_quality);
+  active_worst_quality = clamp(active_worst_quality,
+                               active_best_quality, rc->worst_quality);
+
+  *top_index = active_worst_quality;
+  *bottom_index = active_best_quality;
+
+#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
+  // Limit Q range for the adaptive loop.
+  if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
+    if (!(cm->current_video_frame == 0))
+      *top_index = (active_worst_quality + active_best_quality * 3) / 4;
+  }
+#endif
+  // Special case code to try and match quality with forced key frames
+  if (cm->frame_type == KEY_FRAME && rc->this_key_frame_forced) {
+    q = rc->last_boosted_qindex;
+  } else {
+    q = vp9_rc_regulate_q(cpi, rc->this_frame_target,
+                          active_best_quality, active_worst_quality);
+    if (q > *top_index) {
+      // Special case when we are targeting the max allowed rate
+      if (cpi->rc.this_frame_target >= cpi->rc.max_frame_bandwidth)
+        *top_index = q;
+      else
+        q = *top_index;
+    }
+  }
+  assert(*top_index <= rc->worst_quality &&
+         *top_index >= rc->best_quality);
+  assert(*bottom_index <= rc->worst_quality &&
+         *bottom_index >= rc->best_quality);
+  assert(q <= rc->worst_quality && q >= rc->best_quality);
+  return q;
+}
+
+static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
+                                             int *bottom_index,
+                                             int *top_index) {
   const VP9_COMMON *const cm = &cpi->common;
   const RATE_CONTROL *const rc = &cpi->rc;
   const VP9_CONFIG *const oxcf = &cpi->oxcf;
   int active_best_quality;
-  int active_worst_quality = rc->active_worst_quality;
+  int active_worst_quality = calc_active_worst_quality_one_pass_vbr(cpi);
   int q;
 
   if (frame_is_intra_only(cm)) {
@@ -487,8 +679,7 @@
       double q_adj_factor = 1.0;
       double q_val;
 
-      // Baseline value derived from cpi->active_worst_quality and kf boost
-      active_best_quality = get_active_quality(active_worst_quality,
+      active_best_quality = get_active_quality(rc->avg_frame_qindex[KEY_FRAME],
                                                rc->kf_boost,
                                                kf_low, kf_high,
                                                kf_low_motion_minq,
@@ -521,7 +712,7 @@
         rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality) {
       q = rc->avg_frame_qindex[INTER_FRAME];
     } else {
-      q = active_worst_quality;
+      q = rc->avg_frame_qindex[KEY_FRAME];
     }
     // For constrained quality dont allow Q less than the cq level
     if (oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) {
@@ -565,10 +756,10 @@
       active_best_quality = cpi->cq_target_quality;
     } else {
       // Use the lower of active_worst_quality and recent/average Q.
-      if (rc->avg_frame_qindex[INTER_FRAME] < active_worst_quality)
-       active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
+      if (cm->current_video_frame > 1)
+        active_best_quality = inter_minq[rc->avg_frame_qindex[INTER_FRAME]];
       else
-        active_best_quality = inter_minq[active_worst_quality];
+        active_best_quality = inter_minq[rc->avg_frame_qindex[KEY_FRAME]];
       // For the constrained quality mode we don't want
       // q to fall below the cq level.
       if ((oxcf->end_usage == USAGE_CONSTRAINED_QUALITY) &&
@@ -599,7 +790,6 @@
     if (!(cm->current_video_frame == 0))
       *top_index = (active_worst_quality + active_best_quality * 3) / 4;
   } else if (!rc->is_src_frame_alt_ref &&
-             (oxcf->end_usage != USAGE_STREAM_FROM_SERVER) &&
              (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
     *top_index = (active_worst_quality + active_best_quality) / 2;
   }
@@ -645,14 +835,14 @@
   return q;
 }
 
-static int rc_pick_q_and_adjust_q_bounds_two_pass(const VP9_COMP *cpi,
-                                                  int *bottom_index,
-                                                  int *top_index) {
+static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
+                                         int *bottom_index,
+                                         int *top_index) {
   const VP9_COMMON *const cm = &cpi->common;
   const RATE_CONTROL *const rc = &cpi->rc;
   const VP9_CONFIG *const oxcf = &cpi->oxcf;
   int active_best_quality;
-  int active_worst_quality = rc->active_worst_quality;
+  int active_worst_quality = cpi->twopass.active_worst_quality;
   int q;
 
   if (frame_is_intra_only(cm)) {
@@ -836,21 +1026,23 @@
   return q;
 }
 
-int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
-                                      int *bottom_index,
-                                      int *top_index) {
+int vp9_rc_pick_q_and_bounds(const VP9_COMP *cpi,
+                             int *bottom_index,
+                             int *top_index) {
   int q;
-  if (cpi->pass == 0)
-    q = rc_pick_q_and_adjust_q_bounds_one_pass(
-        cpi, bottom_index, top_index);
-  else
-    q = rc_pick_q_and_adjust_q_bounds_two_pass(
-        cpi, bottom_index, top_index);
+  if (cpi->pass == 0) {
+    if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)
+      q = rc_pick_q_and_bounds_one_pass_cbr(cpi, bottom_index, top_index);
+    else
+      q = rc_pick_q_and_bounds_one_pass_vbr(cpi, bottom_index, top_index);
+  } else {
+    q = rc_pick_q_and_bounds_two_pass(cpi, bottom_index, top_index);
+  }
 
   // JBB : This is realtime mode.  In real time mode the first frame
   // should be larger. Q of 0 is disabled because we force tx size to be
   // 16x16...
-  if (cpi->sf.super_fast_rtc) {
+  if (cpi->sf.use_pick_mode) {
     if (cpi->common.current_video_frame == 0)
       q /= 3;
     if (q == 0)
@@ -973,7 +1165,8 @@
     rc->avg_frame_qindex[KEY_FRAME] = ROUND_POWER_OF_TWO(
         3 * rc->avg_frame_qindex[KEY_FRAME] + cm->base_qindex, 2);
   } else if (!rc->is_src_frame_alt_ref &&
-             (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
+      (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) &&
+      !(cpi->use_svc && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)) {
     rc->last_q[2] = cm->base_qindex;
     rc->avg_frame_qindex[2] = ROUND_POWER_OF_TWO(
         3 * rc->avg_frame_qindex[2] + cm->base_qindex, 2);
@@ -1056,7 +1249,7 @@
 #define USE_ALTREF_FOR_ONE_PASS   1
 
 static int calc_pframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
-  static const int af_ratio = 5;
+  static const int af_ratio = 10;
   const RATE_CONTROL *rc = &cpi->rc;
   int target;
 #if USE_ALTREF_FOR_ONE_PASS
@@ -1073,7 +1266,7 @@
 }
 
 static int calc_iframe_target_size_one_pass_vbr(const VP9_COMP *const cpi) {
-  static const int kf_ratio = 12;
+  static const int kf_ratio = 25;
   const RATE_CONTROL *rc = &cpi->rc;
   int target = rc->av_per_frame_bandwidth * kf_ratio;
   return vp9_rc_clamp_iframe_target_size(cpi, target);
@@ -1081,46 +1274,31 @@
 
 void vp9_rc_get_one_pass_vbr_params(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
+  RATE_CONTROL *const rc = &cpi->rc;
   int target;
   if (!cpi->refresh_alt_ref_frame &&
       (cm->current_video_frame == 0 ||
        cm->frame_flags & FRAMEFLAGS_KEY ||
-       cpi->rc.frames_to_key == 0 ||
+       rc->frames_to_key == 0 ||
        (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
     cm->frame_type = KEY_FRAME;
-    cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
-                                    cpi->rc.frames_to_key == 0;
-    cpi->rc.frames_to_key = cpi->key_frame_frequency;
-    cpi->rc.kf_boost = DEFAULT_KF_BOOST;
-    cpi->rc.source_alt_ref_active = 0;
-    if (cm->current_video_frame == 0) {
-      cpi->rc.active_worst_quality = cpi->rc.worst_quality;
-    } else {
-      // Choose active worst quality twice as large as the last q.
-      cpi->rc.active_worst_quality = cpi->rc.last_q[KEY_FRAME] * 2;
-      if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
-        cpi->rc.active_worst_quality = cpi->rc.worst_quality;
-    }
+    rc->this_key_frame_forced = cm->current_video_frame != 0 &&
+                                rc->frames_to_key == 0;
+    rc->frames_to_key = cpi->key_frame_frequency;
+    rc->kf_boost = DEFAULT_KF_BOOST;
+    rc->source_alt_ref_active = 0;
   } else {
     cm->frame_type = INTER_FRAME;
-    if (cm->current_video_frame == 1) {
-      cpi->rc.active_worst_quality = cpi->rc.worst_quality;
-    } else {
-      // Choose active worst quality twice as large as the last q.
-      cpi->rc.active_worst_quality = cpi->rc.last_q[INTER_FRAME] * 2;
-      if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
-        cpi->rc.active_worst_quality = cpi->rc.worst_quality;
-    }
   }
-  if (cpi->rc.frames_till_gf_update_due == 0) {
-    cpi->rc.baseline_gf_interval = DEFAULT_GF_INTERVAL;
-    cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
+  if (rc->frames_till_gf_update_due == 0) {
+    rc->baseline_gf_interval = DEFAULT_GF_INTERVAL;
+    rc->frames_till_gf_update_due = rc->baseline_gf_interval;
     // NOTE: frames_till_gf_update_due must be <= frames_to_key.
-    if (cpi->rc.frames_till_gf_update_due > cpi->rc.frames_to_key)
-      cpi->rc.frames_till_gf_update_due = cpi->rc.frames_to_key;
+    if (rc->frames_till_gf_update_due > rc->frames_to_key)
+      rc->frames_till_gf_update_due = rc->frames_to_key;
     cpi->refresh_golden_frame = 1;
-    cpi->rc.source_alt_ref_pending = USE_ALTREF_FOR_ONE_PASS;
-    cpi->rc.gfu_boost = DEFAULT_GF_BOOST;
+    rc->source_alt_ref_pending = USE_ALTREF_FOR_ONE_PASS;
+    rc->gfu_boost = DEFAULT_GF_BOOST;
   }
   if (cm->frame_type == KEY_FRAME)
     target = calc_iframe_target_size_one_pass_vbr(cpi);
@@ -1129,58 +1307,23 @@
   vp9_rc_set_frame_target(cpi, target);
 }
 
-// Adjust active_worst_quality level based on buffer level.
-static int calc_active_worst_quality_one_pass_cbr(const VP9_COMP *cpi) {
-  // Adjust active_worst_quality: If buffer is above the optimal/target level,
-  // bring active_worst_quality down depending on fullness of buffer.
-  // If buffer is below the optimal level, let the active_worst_quality go from
-  // ambient Q (at buffer = optimal level) to worst_quality level
-  // (at buffer = critical level).
-  const VP9_CONFIG *oxcf = &cpi->oxcf;
-  const RATE_CONTROL *rc = &cpi->rc;
-  int active_worst_quality = rc->active_worst_quality;
-  // Maximum limit for down adjustment, ~20%.
-  int max_adjustment_down = active_worst_quality / 5;
-  // Buffer level below which we push active_worst to worst_quality.
-  int critical_level = oxcf->optimal_buffer_level >> 2;
-  int adjustment = 0;
-  int buff_lvl_step = 0;
-  if (rc->buffer_level > oxcf->optimal_buffer_level) {
-    // Adjust down.
-    if (max_adjustment_down) {
-      buff_lvl_step = (int)((oxcf->maximum_buffer_size -
-          oxcf->optimal_buffer_level) / max_adjustment_down);
-      if (buff_lvl_step)
-        adjustment = (int)((rc->buffer_level - oxcf->optimal_buffer_level) /
-                            buff_lvl_step);
-      active_worst_quality -= adjustment;
-    }
-  } else if (rc->buffer_level > critical_level) {
-    // Adjust up from ambient Q.
-    if (critical_level) {
-      buff_lvl_step = (oxcf->optimal_buffer_level - critical_level);
-      if (buff_lvl_step) {
-        adjustment = (rc->worst_quality - rc->avg_frame_qindex[INTER_FRAME]) *
-                         (oxcf->optimal_buffer_level - rc->buffer_level) /
-                             buff_lvl_step;
-      }
-      active_worst_quality = rc->avg_frame_qindex[INTER_FRAME] + adjustment;
-    }
-  } else {
-    // Set to worst_quality if buffer is below critical level.
-    active_worst_quality = rc->worst_quality;
-  }
-  return active_worst_quality;
-}
-
 static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
   const VP9_CONFIG *oxcf = &cpi->oxcf;
   const RATE_CONTROL *rc = &cpi->rc;
-  int target = rc->av_per_frame_bandwidth;
-  const int min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
-                                   FRAME_OVERHEAD_BITS);
   const int64_t diff = oxcf->optimal_buffer_level - rc->buffer_level;
   const int one_pct_bits = 1 + oxcf->optimal_buffer_level / 100;
+  int min_frame_target = MAX(rc->av_per_frame_bandwidth >> 4,
+                             FRAME_OVERHEAD_BITS);
+  int target = rc->av_per_frame_bandwidth;
+  if (cpi->use_svc && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
+    // Note that for layers, av_per_frame_bandwidth is the cumulative
+    // per-frame-bandwidth. For the target size of this frame, use the
+    // layer average frame size (i.e., non-cumulative per-frame-bw).
+    int current_temporal_layer = cpi->svc.temporal_layer_id;
+    const LAYER_CONTEXT *lc = &cpi->svc.layer_context[current_temporal_layer];
+    target = lc->avg_frame_size;
+    min_frame_target = MAX(lc->avg_frame_size >> 4, FRAME_OVERHEAD_BITS);
+  }
   if (diff > 0) {
     // Lower the target bandwidth for this frame.
     const int pct_low = MIN(diff / one_pct_bits, oxcf->under_shoot_pct);
@@ -1190,26 +1333,23 @@
     const int pct_high = MIN(-diff / one_pct_bits, oxcf->over_shoot_pct);
     target += (target * pct_high) / 200;
   }
-  if (target < min_frame_target)
-    target = min_frame_target;
-  return target;
+  return MAX(min_frame_target, target);
 }
 
 static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
-  int target;
   const RATE_CONTROL *rc = &cpi->rc;
+
   if (cpi->common.current_video_frame == 0) {
-    target = cpi->oxcf.starting_buffer_level / 2;
+    return cpi->oxcf.starting_buffer_level / 2;
   } else {
-    int initial_boost = 32;
+    const int initial_boost = 32;
     int kf_boost = MAX(initial_boost, (int)(2 * cpi->output_framerate - 16));
     if (rc->frames_since_key < cpi->output_framerate / 2) {
       kf_boost = (int)(kf_boost * rc->frames_since_key /
                        (cpi->output_framerate / 2));
     }
-    target = ((16 + kf_boost) * rc->av_per_frame_bandwidth) >> 4;
+    return ((16 + kf_boost) * rc->av_per_frame_bandwidth) >> 4;
   }
-  return target;
 }
 
 void vp9_rc_get_svc_params(VP9_COMP *cpi) {
@@ -1223,14 +1363,11 @@
     cpi->rc.source_alt_ref_active = 0;
     if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
       target = calc_iframe_target_size_one_pass_cbr(cpi);
-      cpi->rc.active_worst_quality = cpi->rc.worst_quality;
     }
   } else {
     cm->frame_type = INTER_FRAME;
     if (cpi->pass == 0 && cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {
       target = calc_pframe_target_size_one_pass_cbr(cpi);
-      cpi->rc.active_worst_quality =
-          calc_active_worst_quality_one_pass_cbr(cpi);
     }
   }
   vp9_rc_set_frame_target(cpi, target);
@@ -1240,27 +1377,25 @@
 
 void vp9_rc_get_one_pass_cbr_params(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
+  RATE_CONTROL *const rc = &cpi->rc;
   int target;
   if ((cm->current_video_frame == 0 ||
       cm->frame_flags & FRAMEFLAGS_KEY ||
-      cpi->rc.frames_to_key == 0 ||
+      rc->frames_to_key == 0 ||
       (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
     cm->frame_type = KEY_FRAME;
-    cpi->rc.this_key_frame_forced = cm->current_video_frame != 0 &&
-                                    cpi->rc.frames_to_key == 0;
-    cpi->rc.frames_to_key = cpi->key_frame_frequency;
-    cpi->rc.kf_boost = DEFAULT_KF_BOOST;
-    cpi->rc.source_alt_ref_active = 0;
+    rc->this_key_frame_forced = cm->current_video_frame != 0 &&
+                                rc->frames_to_key == 0;
+    rc->frames_to_key = cpi->key_frame_frequency;
+    rc->kf_boost = DEFAULT_KF_BOOST;
+    rc->source_alt_ref_active = 0;
     target = calc_iframe_target_size_one_pass_cbr(cpi);
-    cpi->rc.active_worst_quality = cpi->rc.worst_quality;
   } else {
     cm->frame_type = INTER_FRAME;
     target = calc_pframe_target_size_one_pass_cbr(cpi);
-    cpi->rc.active_worst_quality =
-        calc_active_worst_quality_one_pass_cbr(cpi);
   }
   vp9_rc_set_frame_target(cpi, target);
   // Don't use gf_update by default in CBR mode.
-  cpi->rc.frames_till_gf_update_due = INT_MAX;
-  cpi->rc.baseline_gf_interval = INT_MAX;
+  rc->frames_till_gf_update_due = INT_MAX;
+  rc->baseline_gf_interval = INT_MAX;
 }
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 8ff567d..551b6c3 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -73,7 +73,6 @@
   int total_target_vs_actual;        // debug stats
 
   int worst_quality;
-  int active_worst_quality;
   int best_quality;
   // int active_best_quality;
 } RATE_CONTROL;
@@ -141,9 +140,9 @@
                                       int *frame_over_shoot_limit);
 
 // Picks q and q bounds given the target for bits
-int vp9_rc_pick_q_and_adjust_q_bounds(const struct VP9_COMP *cpi,
-                                      int *bottom_index,
-                                      int *top_index);
+int vp9_rc_pick_q_and_bounds(const struct VP9_COMP *cpi,
+                             int *bottom_index,
+                             int *top_index);
 
 // Estimates q to achieve a target bits per frame
 int vp9_rc_regulate_q(const struct VP9_COMP *cpi, int target_bits_per_frame,
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 7b17b85..cae7884 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -285,7 +285,8 @@
   cpi->RDDIV = RDDIV_BITS;  // in bits (to multiply D by 128)
   cpi->RDMULT = vp9_compute_rd_mult(cpi, qindex);
 
-  x->errorperbit = cpi->RDMULT / RD_MULT_EPB_RATIO + (x->errorperbit == 0);
+  x->errorperbit = cpi->RDMULT / RD_MULT_EPB_RATIO;
+  x->errorperbit += (x->errorperbit == 0);
 
   vp9_set_speed_features(cpi);
 
@@ -296,7 +297,7 @@
 
   fill_token_costs(x->token_costs, cm->fc.coef_probs);
 
-  if (!cpi->sf.super_fast_rtc) {
+  if (!cpi->sf.use_pick_mode) {
     for (i = 0; i < PARTITION_CONTEXTS; i++)
       vp9_cost_tokens(x->partition_cost[i], get_partition_probs(cm, i),
                       vp9_partition_tree);
@@ -443,7 +444,7 @@
 
     if (i == 0)
       x->pred_sse[ref] = sse;
-    if (cpi->sf.super_fast_rtc) {
+    if (cpi->sf.use_pick_mode) {
       dist_sum += (int)sse;
     } else {
       int rate;
@@ -643,17 +644,16 @@
   MACROBLOCK *const x = args->x;
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
-  struct encode_b_args encode_args = {x, NULL, &mbmi->skip_coeff};
-
   int64_t rd1, rd2, rd;
 
   if (args->skip)
     return;
 
-  if (!is_inter_block(&xd->mi_8x8[0]->mbmi))
-    vp9_encode_block_intra(plane, block, plane_bsize, tx_size, &encode_args);
+  if (!is_inter_block(mbmi))
+    vp9_encode_block_intra(x, plane, block, plane_bsize, tx_size,
+                           &mbmi->skip_coeff);
   else
-    vp9_xform_quant(plane, block, plane_bsize, tx_size, &encode_args);
+    vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
 
   dist_block(plane, block, tx_size, args);
   rate_block(plane, block, plane_bsize, tx_size, args);
@@ -1645,14 +1645,15 @@
                                     BEST_SEG_INFO *bsi_buf, int filter_idx,
                                     int_mv seg_mvs[4][MAX_REF_FRAMES],
                                     int mi_row, int mi_col) {
-  int i, br = 0, idx, idy;
+  int k, br = 0, idx, idy;
   int64_t bd = 0, block_sse = 0;
   MB_PREDICTION_MODE this_mode;
+  MACROBLOCKD *xd = &x->e_mbd;
   VP9_COMMON *cm = &cpi->common;
-  MODE_INFO *mi = x->e_mbd.mi_8x8[0];
+  MODE_INFO *mi = xd->mi_8x8[0];
   MB_MODE_INFO *const mbmi = &mi->mbmi;
   struct macroblock_plane *const p = &x->plane[0];
-  struct macroblockd_plane *const pd = &x->e_mbd.plane[0];
+  struct macroblockd_plane *const pd = &xd->plane[0];
   const int label_count = 4;
   int64_t this_segment_rd = 0;
   int label_mv_thresh;
@@ -1660,7 +1661,7 @@
   const BLOCK_SIZE bsize = mbmi->sb_type;
   const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
   const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
-  vp9_variance_fn_ptr_t *v_fn_ptr;
+  vp9_variance_fn_ptr_t *v_fn_ptr = &cpi->fn_ptr[bsize];
   ENTROPY_CONTEXT t_above[2], t_left[2];
   BEST_SEG_INFO *bsi = bsi_buf + filter_idx;
   int mode_idx;
@@ -1670,8 +1671,6 @@
   vpx_memcpy(t_above, pd->above_context, sizeof(t_above));
   vpx_memcpy(t_left, pd->left_context, sizeof(t_left));
 
-  v_fn_ptr = &cpi->fn_ptr[bsize];
-
   // 64 makes this threshold really big effectively
   // making it so that we very rarely check mvs on
   // segments.   setting this to 1 would make mv thresh
@@ -1687,20 +1686,17 @@
       int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
       MB_PREDICTION_MODE mode_selected = ZEROMV;
       int64_t best_rd = INT64_MAX;
-      i = idy * 2 + idx;
+      const int i = idy * 2 + idx;
+      int ref;
 
-      frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
-      vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
-                                    i, 0, mi_row, mi_col,
-                                    &frame_mv[NEARESTMV][mbmi->ref_frame[0]],
-                                    &frame_mv[NEARMV][mbmi->ref_frame[0]]);
-      if (has_second_rf) {
-        frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0;
-        vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
-                                      i, 1, mi_row, mi_col,
-                                      &frame_mv[NEARESTMV][mbmi->ref_frame[1]],
-                                      &frame_mv[NEARMV][mbmi->ref_frame[1]]);
+      for (ref = 0; ref < 1 + has_second_rf; ++ref) {
+        const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
+        frame_mv[ZEROMV][frame].as_int = 0;
+        vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, i, ref, mi_row, mi_col,
+                                      &frame_mv[NEARESTMV][frame],
+                                      &frame_mv[NEARMV][frame]);
       }
+
       // search for the best motion vector on this segment
       for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
         const struct buf_2d orig_src = x->plane[0].src;
@@ -2042,8 +2038,8 @@
   bsi->sse = block_sse;
 
   // update the coding decisions
-  for (i = 0; i < 4; ++i)
-    bsi->modes[i] = mi->bmi[i].as_mode;
+  for (k = 0; k < 4; ++k)
+    bsi->modes[k] = mi->bmi[k].as_mode;
 }
 
 static int64_t rd_pick_best_mbsegmentation(VP9_COMP *cpi, MACROBLOCK *x,
@@ -2910,33 +2906,26 @@
   if (cm->interp_filter == SWITCHABLE)
     *rate2 += get_switchable_rate(x);
 
-  if (!is_comp_pred && cpi->enable_encode_breakout) {
+  if (!is_comp_pred) {
     if (cpi->active_map_enabled && x->active_ptr[0] == 0)
       x->skip = 1;
-    else if (x->encode_breakout) {
+    else if (cpi->allow_encode_breakout && x->encode_breakout) {
       const BLOCK_SIZE y_size = get_plane_block_size(bsize, &xd->plane[0]);
       const BLOCK_SIZE uv_size = get_plane_block_size(bsize, &xd->plane[1]);
       unsigned int var, sse;
       // Skipping threshold for ac.
       unsigned int thresh_ac;
-      // The encode_breakout input
-      unsigned int encode_breakout = x->encode_breakout << 4;
-      unsigned int max_thresh = 36000;
-
+      // Set a maximum for threshold to avoid big PSNR loss in low bitrate case.
       // Use extreme low threshold for static frames to limit skipping.
-      if (cpi->enable_encode_breakout == 2)
-        max_thresh = 128;
+      const unsigned int max_thresh = (cpi->allow_encode_breakout ==
+                                      ENCODE_BREAKOUT_LIMITED) ? 128 : 36000;
+      // The encode_breakout input
+      const unsigned int min_thresh = ((x->encode_breakout << 4) > max_thresh) ?
+                                      max_thresh : (x->encode_breakout << 4);
 
       // Calculate threshold according to dequant value.
       thresh_ac = (xd->plane[0].dequant[1] * xd->plane[0].dequant[1]) / 9;
-
-      // Use encode_breakout input if it is bigger than internal threshold.
-      if (thresh_ac < encode_breakout)
-        thresh_ac = encode_breakout;
-
-      // Set a maximum for threshold to avoid big PSNR loss in low bitrate case.
-      if (thresh_ac > max_thresh)
-        thresh_ac = max_thresh;
+      thresh_ac = clamp(thresh_ac, min_thresh, max_thresh);
 
       var = cpi->fn_ptr[y_size].vf(x->plane[0].src.buf, x->plane[0].src.stride,
                                    xd->plane[0].dst.buf,
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index e16467a..ca11dda 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -520,11 +520,16 @@
   cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;
 
   // Adjust the strength based on active max q
-  q = ((int)vp9_convert_qindex_to_q(cpi->rc.active_worst_quality) >> 1);
-  if (q > 8) {
+  if (cpi->common.current_video_frame > 1)
+    q = ((int)vp9_convert_qindex_to_q(
+        cpi->rc.avg_frame_qindex[INTER_FRAME]));
+  else
+    q = ((int)vp9_convert_qindex_to_q(
+        cpi->rc.avg_frame_qindex[KEY_FRAME]));
+  if (q > 16) {
     cpi->active_arnr_strength = cpi->oxcf.arnr_strength;
   } else {
-    cpi->active_arnr_strength = cpi->oxcf.arnr_strength - (8 - q);
+    cpi->active_arnr_strength = cpi->oxcf.arnr_strength - ((16 - q) / 2);
     if (cpi->active_arnr_strength < 0)
       cpi->active_arnr_strength = 0;
   }
diff --git a/vp9/encoder/x86/vp9_quantize_ssse3.asm b/vp9/encoder/x86/vp9_quantize_ssse3.asm
index db30660..48ccef8 100644
--- a/vp9/encoder/x86/vp9_quantize_ssse3.asm
+++ b/vp9/encoder/x86/vp9_quantize_ssse3.asm
@@ -188,7 +188,8 @@
   pmaxsw                          m8, m7
   pshuflw                         m7, m8, 0x1
   pmaxsw                          m8, m7
-  pextrw                        [r2], m8, 0
+  pextrw                          r6, m8, 0
+  mov                             [r2], r6
   RET
 
   ; skip-block, i.e. just write all zeroes
@@ -214,5 +215,5 @@
 %endmacro
 
 INIT_XMM ssse3
-QUANTIZE_FN b, 6
+QUANTIZE_FN b, 7
 QUANTIZE_FN b_32x32, 7
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index f9ba41b..85e83b8 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -23,6 +23,8 @@
 VP9_COMMON_SRCS-yes += common/vp9_entropymv.c
 VP9_COMMON_SRCS-yes += common/vp9_filter.c
 VP9_COMMON_SRCS-yes += common/vp9_filter.h
+VP9_COMMON_SRCS-yes += common/vp9_frame_buffers.c
+VP9_COMMON_SRCS-yes += common/vp9_frame_buffers.h
 VP9_COMMON_SRCS-yes += common/generic/vp9_systemdependent.c
 VP9_COMMON_SRCS-yes += common/vp9_idct.c
 VP9_COMMON_SRCS-yes += common/vp9_alloccommon.h
@@ -82,7 +84,7 @@
 VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_postproc_sse2.asm
 endif
 
-ifeq ($(USE_X86INC),yes)
+ifeq ($(CONFIG_USE_X86INC),yes)
 VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_copy_sse2.asm
 VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_intrapred_sse2.asm
 VP9_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/vp9_intrapred_ssse3.asm
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 85a3b11..f5d5b24 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -222,7 +222,7 @@
     int              n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
     FIRSTPASS_STATS *stats;
 
-    if (!cfg->rc_twopass_stats_in.buf)
+    if (cfg->rc_twopass_stats_in.buf == NULL)
       ERROR("rc_twopass_stats_in.buf not set.");
 
     if (cfg->rc_twopass_stats_in.sz % packet_sz)
@@ -419,7 +419,7 @@
 
   res = validate_config(ctx, cfg, &ctx->vp8_cfg);
 
-  if (!res) {
+  if (res == VPX_CODEC_OK) {
     ctx->cfg = *cfg;
     set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
     vp9_change_config(ctx->cpi, &ctx->oxcf);
@@ -439,8 +439,7 @@
 
 #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
 
-  if (!arg)
-    return VPX_CODEC_INVALID_PARAM;
+  if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
 
   switch (ctrl_id) {
       MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
@@ -482,7 +481,7 @@
 
   res = validate_config(ctx, &ctx->cfg, &xcfg);
 
-  if (!res) {
+  if (res == VPX_CODEC_OK) {
     ctx->vp8_cfg = xcfg;
     set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
     vp9_change_config(ctx->cpi, &ctx->oxcf);
@@ -501,12 +500,10 @@
 
   VP9_PTR optr;
 
-  if (!ctx->priv) {
+  if (ctx->priv == NULL) {
     priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
 
-    if (!priv) {
-      return VPX_CODEC_MEM_ERROR;
-    }
+    if (priv == NULL) return VPX_CODEC_MEM_ERROR;
 
     ctx->priv = &priv->base;
     ctx->priv->sz = sizeof(*ctx->priv);
@@ -543,21 +540,19 @@
 
     priv->cx_data = malloc(priv->cx_data_sz);
 
-    if (!priv->cx_data) {
-      return VPX_CODEC_MEM_ERROR;
-    }
+    if (priv->cx_data == NULL) return VPX_CODEC_MEM_ERROR;
 
     vp9_initialize_enc();
 
     res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
 
-    if (!res) {
+    if (res == VPX_CODEC_OK) {
       set_vp9e_config(&ctx->priv->alg_priv->oxcf,
                       ctx->priv->alg_priv->cfg,
                       ctx->priv->alg_priv->vp8_cfg);
       optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
 
-      if (!optr)
+      if (optr == NULL)
         res = VPX_CODEC_MEM_ERROR;
       else
         ctx->priv->alg_priv->cpi = optr;
@@ -725,7 +720,7 @@
   }
 
   /* Initialize the encoder instance on the first frame. */
-  if (!res && ctx->cpi) {
+  if (res == VPX_CODEC_OK && ctx->cpi != NULL) {
     unsigned int lib_flags;
     YV12_BUFFER_CONFIG sd;
     int64_t dst_time_stamp, dst_end_time_stamp;
@@ -785,8 +780,8 @@
         VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
 
         /* Pack invisible frames with the next visible frame */
-        if (!cpi->common.show_frame) {
-          if (!ctx->pending_cx_data)
+        if (cpi->common.show_frame == 0) {
+          if (ctx->pending_cx_data == 0)
             ctx->pending_cx_data = cx_data;
           ctx->pending_cx_data_sz += size;
           ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
@@ -811,7 +806,7 @@
         if (lib_flags & FRAMEFLAGS_KEY)
           pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
 
-        if (!cpi->common.show_frame) {
+        if (cpi->common.show_frame == 0) {
           pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
 
           // This timestamp should be as close as possible to the
@@ -885,10 +880,9 @@
 static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id,
                                           va_list args) {
-  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+  vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
 
-  if (data) {
-    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+  if (frame != NULL) {
     YV12_BUFFER_CONFIG sd;
 
     image2yuvconfig(&frame->img, &sd);
@@ -903,10 +897,9 @@
 static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
                                            int ctr_id,
                                            va_list args) {
-  vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
+  vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
 
-  if (data) {
-    vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
+  if (frame != NULL) {
     YV12_BUFFER_CONFIG sd;
 
     image2yuvconfig(&frame->img, &sd);
@@ -921,13 +914,13 @@
 static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
                                      int ctr_id,
                                      va_list args) {
-  vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
+  vp9_ref_frame_t *frame = va_arg(args, vp9_ref_frame_t *);
 
-  if (data) {
+  if (frame != NULL) {
     YV12_BUFFER_CONFIG* fb;
 
-    vp9_get_reference_enc(ctx->cpi, data->idx, &fb);
-    yuvconfig2image(&data->img, fb, NULL);
+    vp9_get_reference_enc(ctx->cpi, frame->idx, &fb);
+    yuvconfig2image(&frame->img, fb, NULL);
     return VPX_CODEC_OK;
   } else {
     return VPX_CODEC_INVALID_PARAM;
@@ -938,11 +931,11 @@
                                           int ctr_id,
                                           va_list args) {
 #if CONFIG_VP9_POSTPROC
-  vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
+  vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
   (void)ctr_id;
 
-  if (data) {
-    ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
+  if (config != NULL) {
+    ctx->preview_ppcfg = *config;
     return VPX_CODEC_OK;
   } else {
     return VPX_CODEC_INVALID_PARAM;
@@ -1016,20 +1009,14 @@
 static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
                                           int ctr_id,
                                           va_list args) {
-  vpx_scaling_mode_t *data =  va_arg(args, vpx_scaling_mode_t *);
+  vpx_scaling_mode_t *scalemode =  va_arg(args, vpx_scaling_mode_t *);
 
-  if (data) {
+  if (scalemode != NULL) {
     int res;
-    vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data;
     res = vp9_set_internal_size(ctx->cpi,
-                                (VPX_SCALING)scalemode.h_scaling_mode,
-                                (VPX_SCALING)scalemode.v_scaling_mode);
-
-    if (!res) {
-      return VPX_CODEC_OK;
-    } else {
-      return VPX_CODEC_INVALID_PARAM;
-    }
+                                (VPX_SCALING)scalemode->h_scaling_mode,
+                                (VPX_SCALING)scalemode->v_scaling_mode);
+    return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
   } else {
     return VPX_CODEC_INVALID_PARAM;
   }
@@ -1070,29 +1057,23 @@
 
 static vpx_codec_err_t vp9e_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
                                                int ctr_id, va_list args) {
-  vpx_svc_parameters_t *data = va_arg(args, vpx_svc_parameters_t *);
   VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
-  vpx_svc_parameters_t params;
+  vpx_svc_parameters_t *params = va_arg(args, vpx_svc_parameters_t *);
 
-  if (data == NULL) {
+  if (params == NULL) return VPX_CODEC_INVALID_PARAM;
+
+  cpi->svc.spatial_layer_id = params->spatial_layer;
+  cpi->svc.temporal_layer_id = params->temporal_layer;
+
+  cpi->lst_fb_idx = params->lst_fb_idx;
+  cpi->gld_fb_idx = params->gld_fb_idx;
+  cpi->alt_fb_idx = params->alt_fb_idx;
+
+  if (vp9_set_size_literal(ctx->cpi, params->width, params->height) != 0)
     return VPX_CODEC_INVALID_PARAM;
-  }
 
-  params = *(vpx_svc_parameters_t *)data;
-
-  cpi->svc.spatial_layer_id = params.spatial_layer;
-  cpi->svc.temporal_layer_id = params.temporal_layer;
-
-  cpi->lst_fb_idx = params.lst_fb_idx;
-  cpi->gld_fb_idx = params.gld_fb_idx;
-  cpi->alt_fb_idx = params.alt_fb_idx;
-
-  if (vp9_set_size_literal(ctx->cpi, params.width, params.height) != 0) {
-    return VPX_CODEC_INVALID_PARAM;
-  }
-
-  ctx->cfg.rc_max_quantizer = params.max_quantizer;
-  ctx->cfg.rc_min_quantizer = params.min_quantizer;
+  ctx->cfg.rc_max_quantizer = params->max_quantizer;
+  ctx->cfg.rc_min_quantizer = params->min_quantizer;
 
   set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
   vp9_change_config(ctx->cpi, &ctx->oxcf);
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index 92c6cd2..41750de 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -15,6 +15,7 @@
 #include "vpx/vp8dx.h"
 #include "vpx/internal/vpx_codec_internal.h"
 #include "./vpx_version.h"
+#include "vp9/common/vp9_frame_buffers.h"
 #include "vp9/decoder/vp9_onyxd.h"
 #include "vp9/decoder/vp9_onyxd_int.h"
 #include "vp9/decoder/vp9_read_bit_buffer.h"
@@ -148,7 +149,9 @@
   {
     struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
     const int frame_marker = vp9_rb_read_literal(&rb, 2);
-    const int version = vp9_rb_read_bit(&rb) | (vp9_rb_read_bit(&rb) << 1);
+    const int version = vp9_rb_read_bit(&rb);
+    (void) vp9_rb_read_bit(&rb);  // unused version bit
+
     if (frame_marker != VP9_FRAME_MARKER)
       return VPX_CODEC_UNSUP_BITSTREAM;
 #if CONFIG_NON420
@@ -291,10 +294,25 @@
         ctx->postproc_cfg.noise_level = 0;
       }
 
-      if (!optr)
+      if (!optr) {
         res = VPX_CODEC_ERROR;
-      else
+      } else {
+        VP9D_COMP *const pbi = (VP9D_COMP*)optr;
+        VP9_COMMON *const cm = &pbi->common;
+
+        cm->get_fb_cb = vp9_get_frame_buffer;
+        cm->release_fb_cb = vp9_release_frame_buffer;
+
+        // Set index to not initialized.
+        cm->new_fb_idx = -1;
+
+        if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
+          vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+                             "Failed to initialize internal frame buffers");
+        cm->cb_priv = &cm->int_frame_buffers;
+
         ctx->pbi = optr;
+      }
     }
 
     ctx->decoder_init = 1;
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index 64f9f09..c0d973b 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -89,7 +89,7 @@
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_temporal_filter_apply_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE3) += encoder/x86/vp9_sad_sse3.asm
 
-ifeq ($(USE_X86INC),yes)
+ifeq ($(CONFIG_USE_X86INC),yes)
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_error_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subtract_sse2.asm
diff --git a/vp9_spatial_scalable_encoder.c b/vp9_spatial_scalable_encoder.c
index 50f45c2..bbbe7ed 100644
--- a/vp9_spatial_scalable_encoder.c
+++ b/vp9_spatial_scalable_encoder.c
@@ -18,9 +18,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+
 #include "./args.h"
-#include "./ivfenc.h"
 #include "./tools_common.h"
+#include "./video_writer.h"
+
 #include "vpx/svc_context.h"
 #include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
@@ -183,7 +185,8 @@
 
 int main(int argc, const char **argv) {
   AppInput app_input = {0};
-  FILE *outfile;
+  VpxVideoWriter *writer = NULL;
+  VpxVideoInfo info = {0};
   vpx_codec_ctx_t codec;
   vpx_codec_enc_cfg_t enc_cfg;
   SvcContext svc_ctx;
@@ -206,15 +209,24 @@
   if (!(app_input.input_ctx.file = fopen(app_input.input_ctx.filename, "rb")))
     die("Failed to open %s for reading\n", app_input.input_ctx.filename);
 
-  if (!(outfile = fopen(app_input.output_filename, "wb")))
-    die("Failed to open %s for writing\n", app_input.output_filename);
-
   // Initialize codec
   if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) !=
       VPX_CODEC_OK)
     die("Failed to initialize encoder\n");
 
-  ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, 0);
+  info.codec_fourcc = VP9_FOURCC;
+  info.time_base.numerator = enc_cfg.g_timebase.num;
+  info.time_base.denominator = enc_cfg.g_timebase.den;
+  if (vpx_svc_get_layer_resolution(&svc_ctx, svc_ctx.spatial_layers - 1,
+                                   (unsigned int *)&info.frame_width,
+                                   (unsigned int *)&info.frame_height) !=
+      VPX_CODEC_OK) {
+    die("Failed to get output resolution");
+  }
+  writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF,
+                                 &info);
+  if (!writer)
+    die("Failed to open %s for writing\n", app_input.output_filename);
 
   // skip initial frames
   for (i = 0; i < app_input.frames_to_skip; ++i) {
@@ -232,9 +244,10 @@
       die_codec(&codec, "Failed to encode frame");
     }
     if (vpx_svc_get_frame_size(&svc_ctx) > 0) {
-      ivf_write_frame_header(outfile, pts, vpx_svc_get_frame_size(&svc_ctx));
-      (void)fwrite(vpx_svc_get_buffer(&svc_ctx), 1,
-                   vpx_svc_get_frame_size(&svc_ctx), outfile);
+      vpx_video_writer_write_frame(writer,
+                                   vpx_svc_get_buffer(&svc_ctx),
+                                   vpx_svc_get_frame_size(&svc_ctx),
+                                   pts);
     }
     ++frame_cnt;
     pts += frame_duration;
@@ -245,19 +258,8 @@
   fclose(app_input.input_ctx.file);
   if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
 
-  // rewrite the output file headers with the actual frame count, and
-  // resolution of the highest layer
-  if (!fseek(outfile, 0, SEEK_SET)) {
-    // get resolution of highest layer
-    if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(&svc_ctx,
-                                                     svc_ctx.spatial_layers - 1,
-                                                     &enc_cfg.g_w,
-                                                     &enc_cfg.g_h)) {
-      die("Failed to get output resolution");
-    }
-    ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, frame_cnt);
-  }
-  fclose(outfile);
+  vpx_video_writer_close(writer);
+
   vpx_img_free(&raw);
 
   // display average size, psnr
diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk
index 549c249..111c87e 100644
--- a/vpx/vpx_codec.mk
+++ b/vpx/vpx_codec.mk
@@ -26,6 +26,7 @@
 API_DOC_SRCS-yes += vpx_codec.h
 API_DOC_SRCS-yes += vpx_decoder.h
 API_DOC_SRCS-yes += vpx_encoder.h
+API_DOC_SRCS-yes += vpx_frame_buffer.h
 API_DOC_SRCS-yes += vpx_image.h
 
 API_SRCS-yes                += src/vpx_decoder.c
@@ -37,5 +38,6 @@
 API_SRCS-yes                += src/vpx_image.c
 API_SRCS-yes                += vpx_codec.h
 API_SRCS-yes                += vpx_codec.mk
+API_SRCS-yes                += vpx_frame_buffer.h
 API_SRCS-yes                += vpx_image.h
 API_SRCS-$(BUILD_LIBVPX)    += vpx_integer.h
diff --git a/vpx/vpx_frame_buffer.h b/vpx/vpx_frame_buffer.h
new file mode 100644
index 0000000..b5489b4
--- /dev/null
+++ b/vpx/vpx_frame_buffer.h
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_VPX_FRAME_BUFFER_H_
+#define VPX_VPX_FRAME_BUFFER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "./vpx_integer.h"
+
+/*!\brief The maximum number of work buffers used by libvpx.
+ */
+#define VPX_MAXIMUM_WORK_BUFFERS 1
+
+/*!\brief The maximum number of reference buffers that a VP9 encoder may use.
+ */
+#define VP9_MAXIMUM_REF_BUFFERS 8
+
+/*!\brief External frame buffer
+ *
+ * This structure holds allocated frame buffers used by the decoder.
+ */
+typedef struct vpx_codec_frame_buffer {
+  uint8_t *data;  /**< Pointer to the data buffer */
+  size_t size;  /**< Size of data in bytes */
+  void *priv;  /**< Frame's private data */
+} vpx_codec_frame_buffer_t;
+
+/*!\brief get frame buffer callback prototype
+ *
+ * This callback is invoked by the decoder to retrieve data for the frame
+ * buffer in order for the decode call to complete. The callback must
+ * allocate at least min_size in bytes and assign it to fb->data. Then the
+ * callback must set fb->size to the allocated size. The application does not
+ * need to align the allocated data. The callback is triggered when the
+ * decoder needs a frame buffer to decode a compressed image into. This
+ * function may be called more than once for every call to vpx_codec_decode.
+ * The application may set fb->priv to some data which will be passed
+ * back in the ximage and the release function call. On success the callback
+ * must return 0. Any failure the callback must return a value less than 0.
+ *
+ * \param[in] priv         Callback's private data
+ * \param[in] new_size     Size in bytes needed by the buffer
+ * \param[in,out] fb       Pointer to vpx_codec_frame_buffer_t
+ */
+typedef int (*vpx_get_frame_buffer_cb_fn_t)(
+    void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb);
+
+/*!\brief release frame buffer callback prototype
+ *
+ * This callback is invoked by the decoder when the frame buffer is not
+ * referenced by any other buffers. On success the callback must return 0.
+ * Any failure the callback must return a value less than 0.
+ *
+ * \param[in] priv         Callback's private data
+ * \param[in] fb           Pointer to vpx_codec_frame_buffer_t
+ */
+typedef int (*vpx_release_frame_buffer_cb_fn_t)(
+    void *priv, vpx_codec_frame_buffer_t *fb);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // VPX_VPX_FRAME_BUFFER_H_
diff --git a/vpx/vpx_integer.h b/vpx/vpx_integer.h
index dfa361b..258618b 100644
--- a/vpx/vpx_integer.h
+++ b/vpx/vpx_integer.h
@@ -48,7 +48,7 @@
 #endif
 
 /* VS2010 defines stdint.h, but not inttypes.h */
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && _MSC_VER < 1800
 #define PRId64 "I64d"
 #else
 #include <inttypes.h>
diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c
index 693125a..ab0a30a 100644
--- a/vpx_scale/generic/yv12config.c
+++ b/vpx_scale/generic/yv12config.c
@@ -8,6 +8,8 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <assert.h>
+
 #include "./vpx_config.h"
 #include "vpx_scale/yv12config.h"
 #include "vpx_mem/vpx_mem.h"
@@ -19,10 +21,17 @@
 /****************************************************************************
  *
  ****************************************************************************/
+#define yv12_align_addr(addr, align) \
+    (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
+
 int
 vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
   if (ybf) {
-    vpx_free(ybf->buffer_alloc);
+    // If libvpx is using frame buffer callbacks then buffer_alloc_sz must
+    // not be set.
+    if (ybf->buffer_alloc_sz > 0) {
+      vpx_free(ybf->buffer_alloc);
+    }
 
     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
@@ -108,7 +117,9 @@
 
 int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
   if (ybf) {
-    vpx_free(ybf->buffer_alloc);
+    if (ybf->buffer_alloc_sz > 0) {
+      vpx_free(ybf->buffer_alloc);
+    }
 
     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
@@ -123,7 +134,10 @@
 
 int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
                              int width, int height,
-                             int ss_x, int ss_y, int border) {
+                             int ss_x, int ss_y, int border,
+                             vpx_codec_frame_buffer_t *fb,
+                             vpx_get_frame_buffer_cb_fn_t cb,
+                             void *cb_priv) {
   if (ybf) {
     const int aligned_width = (width + 7) & ~7;
     const int aligned_height = (height + 7) & ~7;
@@ -148,7 +162,26 @@
 #else
     const int frame_size = yplane_size + 2 * uvplane_size;
 #endif
-    if (frame_size > ybf->buffer_alloc_sz) {
+    if (cb != NULL) {
+      const int align_addr_extra_size = 31;
+      const size_t external_frame_size = frame_size + align_addr_extra_size;
+
+      assert(fb != NULL);
+
+      // Allocation to hold larger frame, or first allocation.
+      if (cb(cb_priv, external_frame_size, fb) < 0)
+        return -1;
+
+      if (fb->data == NULL || fb->size < external_frame_size)
+        return -1;
+
+      // This memset is needed for fixing valgrind error from C loop filter
+      // due to access uninitialized memory in frame border. It could be
+      // removed if border is totally removed.
+      vpx_memset(fb->data, 0, fb->size);
+
+      ybf->buffer_alloc = yv12_align_addr(fb->data, 32);
+    } else if (frame_size > ybf->buffer_alloc_sz) {
       // Allocation to hold larger frame, or first allocation.
       if (ybf->buffer_alloc)
         vpx_free(ybf->buffer_alloc);
@@ -159,14 +192,11 @@
       ybf->buffer_alloc_sz = frame_size;
 
       // This memset is needed for fixing valgrind error from C loop filter
-      // due to access uninitialized memory in frame boarder. It could be
+      // due to access uninitialized memory in frame border. It could be
       // removed if border is totally removed.
       vpx_memset(ybf->buffer_alloc, 0, ybf->buffer_alloc_sz);
     }
 
-    if (ybf->buffer_alloc_sz < frame_size)
-      return -1;
-
     /* Only support allocating buffers that have a border that's a multiple
      * of 32. The border restriction is required to get 16-byte alignment of
      * the start of the chroma rows without introducing an arbitrary gap
@@ -214,7 +244,8 @@
                            int ss_x, int ss_y, int border) {
   if (ybf) {
     vp9_free_frame_buffer(ybf);
-    return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border);
+    return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border,
+                                    NULL, NULL, NULL);
   }
   return -2;
 }
diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h
index 8f39eb7..525f3a0 100644
--- a/vpx_scale/yv12config.h
+++ b/vpx_scale/yv12config.h
@@ -15,6 +15,7 @@
 extern "C" {
 #endif
 
+#include "vpx/vpx_frame_buffer.h"
 #include "vpx/vpx_integer.h"
 
 #define VP8BORDERINPIXELS           32
@@ -65,9 +66,19 @@
   int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
                              int width, int height, int ss_x, int ss_y,
                              int border);
+
+  // Updates the yv12 buffer config with the frame buffer. If cb is not
+  // NULL, then libvpx is using the frame buffer callbacks to handle memory.
+  // If cb is not NULL, libvpx will call cb with minimum size in bytes needed
+  // to decode the current frame. If cb is NULL, libvpx will allocate memory
+  // internally to decode the current frame. Returns 0 on success. Returns < 0
+  // on failure.
   int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
                                int width, int height, int ss_x, int ss_y,
-                               int border);
+                               int border,
+                               vpx_codec_frame_buffer_t *fb,
+                               vpx_get_frame_buffer_cb_fn_t cb,
+                               void *cb_priv);
   int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf);
 
 #ifdef __cplusplus
diff --git a/vpxdec.c b/vpxdec.c
index 98d1550..7f85fc9 100644
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -37,19 +37,6 @@
 
 static const char *exec_name;
 
-static const struct {
-  char const *name;
-  vpx_codec_iface_t *(*iface)(void);
-  uint32_t fourcc;
-} ifaces[] = {
-#if CONFIG_VP8_DECODER
-  {"vp8",  vpx_codec_vp8_dx,   VP8_FOURCC},
-#endif
-#if CONFIG_VP9_DECODER
-  {"vp9",  vpx_codec_vp9_dx,   VP9_FOURCC},
-#endif
-};
-
 struct VpxDecInputContext {
   struct VpxInputContext *vpx_input_ctx;
   struct WebmInputContext *webm_ctx;
@@ -170,10 +157,11 @@
          );
   fprintf(stderr, "\nIncluded decoders:\n\n");
 
-  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
+  for (i = 0; i < get_vpx_decoder_count(); ++i) {
+    const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
     fprintf(stderr, "    %-6s - %s\n",
-            ifaces[i].name,
-            vpx_codec_iface_name(ifaces[i].iface()));
+            decoder->name, vpx_codec_iface_name(decoder->interface()));
+  }
 
   exit(EXIT_FAILURE);
 }
@@ -300,11 +288,12 @@
     int i;
 
     if (mem_get_le32(buf) < 256 * 1024 * 1024) {
-      for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) {
-        if (!vpx_codec_peek_stream_info(ifaces[i].iface(),
+      for (i = 0; i < get_vpx_decoder_count(); ++i) {
+        const VpxInterface *const decoder = get_vpx_decoder_by_index(i);
+        if (!vpx_codec_peek_stream_info(decoder->interface(),
                                         buf + 4, 32 - 4, &si)) {
           is_raw = 1;
-          input->fourcc = ifaces[i].fourcc;
+          input->fourcc = decoder->fourcc;
           input->width = si.w;
           input->height = si.h;
           input->framerate.numerator = 30;
@@ -441,7 +430,6 @@
 int main_loop(int argc, const char **argv_) {
   vpx_codec_ctx_t       decoder;
   char                  *fn = NULL;
-  int                    i;
   uint8_t               *buf = NULL;
   size_t                 bytes_in_buffer = 0, buffer_size = 0;
   FILE                  *infile;
@@ -450,7 +438,8 @@
   int                    stop_after = 0, postproc = 0, summary = 0, quiet = 1;
   int                    arg_skip = 0;
   int                    ec_enabled = 0;
-  vpx_codec_iface_t       *iface = NULL;
+  const VpxInterface *interface = NULL;
+  const VpxInterface *fourcc_interface = NULL;
   unsigned long          dx_time = 0;
   struct arg               arg;
   char                   **argv, **argi, **argj;
@@ -493,17 +482,9 @@
     arg.argv_step = 1;
 
     if (arg_match(&arg, &codecarg, argi)) {
-      int j, k = -1;
-
-      for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
-        if (!strcmp(ifaces[j].name, arg.val))
-          k = j;
-
-      if (k >= 0)
-        iface = ifaces[k].iface();
-      else
-        die("Error: Unrecognized argument (%s) to --codec\n",
-            arg.val);
+      interface = get_vpx_decoder_by_name(arg.val);
+      if (!interface)
+        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
     } else if (arg_match(&arg, &looparg, argi)) {
       // no-op
     } else if (arg_match(&arg, &outputfile, argi))
@@ -660,24 +641,20 @@
     }
   }
 
-  /* Try to determine the codec from the fourcc. */
-  for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
-    if (vpx_input_ctx.fourcc == ifaces[i].fourcc) {
-      vpx_codec_iface_t *vpx_iface = ifaces[i].iface();
+  fourcc_interface = get_vpx_decoder_by_fourcc(vpx_input_ctx.fourcc);
+  if (interface && fourcc_interface && interface != fourcc_interface)
+    warn("Header indicates codec: %s\n", fourcc_interface->name);
+  else
+    interface = fourcc_interface;
 
-      if (iface && iface != vpx_iface)
-        warn("Header indicates codec: %s\n", ifaces[i].name);
-      else
-        iface = vpx_iface;
-
-      break;
-    }
+  if (!interface)
+    interface = get_vpx_decoder_by_index(0);
 
   dec_flags = (postproc ? VPX_CODEC_USE_POSTPROC : 0) |
               (ec_enabled ? VPX_CODEC_USE_ERROR_CONCEALMENT : 0);
-  if (vpx_codec_dec_init(&decoder, iface ? iface :  ifaces[0].iface(), &cfg,
-                         dec_flags)) {
-    fprintf(stderr, "Failed to initialize decoder: %s\n", vpx_codec_error(&decoder));
+  if (vpx_codec_dec_init(&decoder, interface->interface(), &cfg, dec_flags)) {
+    fprintf(stderr, "Failed to initialize decoder: %s\n",
+            vpx_codec_error(&decoder));
     return EXIT_FAILURE;
   }
 
diff --git a/vpxenc.c b/vpxenc.c
index cf3831c..73b3144 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -27,6 +27,7 @@
 #include "third_party/libyuv/include/libyuv/scale.h"
 #include "./args.h"
 #include "./ivfenc.h"
+#include "./tools_common.h"
 
 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
 #include "vpx/vp8cx.h"
@@ -35,7 +36,7 @@
 #include "vpx/vp8dx.h"
 #endif
 
-#include "./tools_common.h"
+#include "vpx/vpx_integer.h"
 #include "vpx_ports/mem_ops.h"
 #include "vpx_ports/vpx_timer.h"
 #include "./rate_hist.h"
@@ -60,24 +61,6 @@
 
 static const char *exec_name;
 
-static const struct codec_item {
-  char const              *name;
-  vpx_codec_iface_t *(*iface)(void);
-  vpx_codec_iface_t *(*dx_iface)(void);
-  unsigned int             fourcc;
-} codecs[] = {
-#if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
-  {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC},
-#elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER
-  {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC},
-#endif
-#if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
-  {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC},
-#elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
-  {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC},
-#endif
-};
-
 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
                                    const char *s, va_list ap) {
   if (ctx->err) {
@@ -461,14 +444,13 @@
   fprintf(stderr, "\nStream timebase (--timebase):\n"
           "  The desired precision of timestamps in the output, expressed\n"
           "  in fractional seconds. Default is 1/1000.\n");
-  fprintf(stderr, "\n"
-          "Included encoders:\n"
-          "\n");
+  fprintf(stderr, "\nIncluded encoders:\n\n");
 
-  for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
+  for (i = 0; i < get_vpx_encoder_count(); ++i) {
+    const VpxInterface *const encoder = get_vpx_encoder_by_index(i);
     fprintf(stderr, "    %-6s - %s\n",
-            codecs[i].name,
-            vpx_codec_iface_name(codecs[i].iface()));
+            encoder->name, vpx_codec_iface_name(encoder->interface()));
+  }
 
   exit(EXIT_FAILURE);
 }
@@ -665,7 +647,7 @@
 
   /* Initialize default parameters */
   memset(global, 0, sizeof(*global));
-  global->codec = codecs;
+  global->codec = get_vpx_encoder_by_index(0);
   global->passes = 0;
   global->use_i420 = 1;
   /* Assign default deadline to good quality */
@@ -675,18 +657,9 @@
     arg.argv_step = 1;
 
     if (arg_match(&arg, &codecarg, argi)) {
-      int j, k = -1;
-
-      for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++)
-        if (!strcmp(codecs[j].name, arg.val))
-          k = j;
-
-      if (k >= 0)
-        global->codec = codecs + k;
-      else
-        die("Error: Unrecognized argument (%s) to --codec\n",
-            arg.val);
-
+      global->codec = get_vpx_encoder_by_name(arg.val);
+      if (!global->codec)
+        die("Error: Unrecognized argument (%s) to --codec\n", arg.val);
     } else if (arg_match(&arg, &passes, argi)) {
       global->passes = arg_parse_uint(&arg);
 
@@ -749,7 +722,7 @@
 #if CONFIG_VP9_ENCODER
     // Make default VP9 passes = 2 until there is a better quality 1-pass
     // encoder
-    global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1);
+    global->passes = strcmp(global->codec->name, "vp9") == 0 ? 2 : 1;
 #else
     global->passes = 1;
 #endif
@@ -829,7 +802,7 @@
     vpx_codec_err_t  res;
 
     /* Populate encoder configuration */
-    res = vpx_codec_enc_config_default(global->codec->iface(),
+    res = vpx_codec_enc_config_default(global->codec->interface(),
                                        &stream->config.cfg,
                                        global->usage);
     if (res)
@@ -873,15 +846,15 @@
   struct stream_config    *config = &stream->config;
   int                      eos_mark_found = 0;
 
-  /* Handle codec specific options */
+  // Handle codec specific options
   if (0) {
 #if CONFIG_VP8_ENCODER
-  } else if (global->codec->iface == vpx_codec_vp8_cx) {
+  } else if (strcmp(global->codec->name, "vp8") == 0) {
     ctrl_args = vp8_args;
     ctrl_args_map = vp8_arg_ctrl_map;
 #endif
 #if CONFIG_VP9_ENCODER
-  } else if (global->codec->iface == vpx_codec_vp9_cx) {
+  } else if (strcmp(global->codec->name, "vp9") == 0) {
     ctrl_args = vp9_args;
     ctrl_args_map = vp9_arg_ctrl_map;
 #endif
@@ -1089,7 +1062,7 @@
 
   if (stream->index == 0) {
     fprintf(stderr, "Codec: %s\n",
-            vpx_codec_iface_name(global->codec->iface()));
+            vpx_codec_iface_name(global->codec->interface()));
     fprintf(stderr, "Source file: %s Format: %s\n", input->filename,
             input->use_i420 ? "I420" : "YV12");
   }
@@ -1213,7 +1186,7 @@
   flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
 
   /* Construct Encoder Context */
-  vpx_codec_enc_init(&stream->encoder, global->codec->iface(),
+  vpx_codec_enc_init(&stream->encoder, global->codec->interface(),
                      &stream->config.cfg, flags);
   ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
 
@@ -1233,7 +1206,8 @@
 
 #if CONFIG_DECODERS
   if (global->test_decode != TEST_DECODE_OFF) {
-    vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0);
+    const VpxInterface *decoder = get_vpx_decoder_by_name(global->codec->name);
+    vpx_codec_dec_init(&stream->decoder, decoder->interface(), NULL, 0);
   }
 #endif
 }
@@ -1352,7 +1326,7 @@
 #if CONFIG_DECODERS
         if (global->test_decode != TEST_DECODE_OFF && !stream->mismatch_seen) {
           vpx_codec_decode(&stream->decoder, pkt->data.frame.buf,
-                           pkt->data.frame.sz, NULL, 0);
+                           (unsigned int)pkt->data.frame.sz, NULL, 0);
           if (stream->decoder.err) {
             warn_or_exit_on_error(&stream->decoder,
                                   global->test_decode == TEST_DECODE_FATAL,
@@ -1419,14 +1393,14 @@
 
 static void test_decode(struct stream_state  *stream,
                         enum TestDecodeFatality fatal,
-                        const struct codec_item *codec) {
+                        const VpxInterface *codec) {
   vpx_image_t enc_img, dec_img;
 
   if (stream->mismatch_seen)
     return;
 
   /* Get the internal reference frame */
-  if (codec->fourcc == VP8_FOURCC) {
+  if (strcmp(codec->name, "vp8") == 0) {
     struct vpx_ref_frame ref_enc, ref_dec;
     int width, height;
 
@@ -1475,7 +1449,9 @@
 
 
 static void print_time(const char *label, int64_t etl) {
-  int hours, mins, secs;
+  int64_t hours;
+  int64_t mins;
+  int64_t secs;
 
   if (etl >= 0) {
     hours = etl / 3600;
@@ -1484,7 +1460,7 @@
     etl -= mins * 60;
     secs = etl;
 
-    fprintf(stderr, "[%3s %2d:%02d:%02d] ",
+    fprintf(stderr, "[%3s %2"PRId64":%02"PRId64": % 02"PRId64"] ",
             label, hours, mins, secs);
   } else {
     fprintf(stderr, "[%3s  unknown] ", label);
@@ -1688,7 +1664,7 @@
           int64_t rate;
 
           if (global.limit) {
-            int frame_in_lagged = (seen_frames - lagged_count) * 1000;
+            off_t frame_in_lagged = (seen_frames - lagged_count) * 1000;
 
             rate = cx_time ? frame_in_lagged * (int64_t)1000000 / cx_time : 0;
             remaining = 1000 * (global.limit - global.skip_frames
diff --git a/vpxenc.h b/vpxenc.h
index 5103ee6..1e6acaa 100644
--- a/vpxenc.h
+++ b/vpxenc.h
@@ -22,9 +22,11 @@
   TEST_DECODE_WARN,
 };
 
+struct VpxInterface;
+
 /* Configuration elements common to all streams. */
 struct VpxEncoderConfig {
-  const struct codec_item *codec;
+  const struct VpxInterface *codec;
   int passes;
   int pass;
   int usage;
diff --git a/warnings.c b/warnings.c
index 6defde9..7ac678a 100644
--- a/warnings.c
+++ b/warnings.c
@@ -54,11 +54,10 @@
 }
 
 static void free_warning_list(struct WarningList *warning_list) {
-  struct WarningListNode *node = warning_list->warning_node;
   while (warning_list->warning_node != NULL) {
-    node = warning_list->warning_node->next_warning;
-    free(warning_list->warning_node);
-    warning_list->warning_node = node;
+    struct WarningListNode *const node = warning_list->warning_node;
+    warning_list->warning_node = node->next_warning;
+    free(node);
   }
 }