Merge "Cleaning up vp9_dthread.{c, h}."
diff --git a/build/make/Makefile b/build/make/Makefile
index dd7fb4a..0c5ff64 100644
--- a/build/make/Makefile
+++ b/build/make/Makefile
@@ -147,6 +147,15 @@
 	$(if $(quiet),@echo "    [CXX] $@")
 	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
 
+$(BUILD_PFX)%.cpp.d: %.cpp
+	$(if $(quiet),@echo "    [DEP] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.cpp.o: %.cpp
+	$(if $(quiet),@echo "    [CXX] $@")
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
+
 $(BUILD_PFX)%.asm.d: %.asm
 	$(if $(quiet),@echo "    [DEP] $@")
 	$(qexec)mkdir -p $(dir $@)
@@ -218,7 +227,7 @@
 
 find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
 find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
-obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o
+obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o .cpp=.cpp.o
 objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
 
 install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
diff --git a/configure b/configure
index ff350cc..01c421d 100755
--- a/configure
+++ b/configure
@@ -704,13 +704,11 @@
         enabled postproc || die "postproc_visualizer requires postproc to be enabled"
     fi
 
-    # Enable WebM IO by default.
-    soft_enable webm_io
-
     # Enable unit tests by default if we have a working C++ compiler.
     case "$toolchain" in
         *-vs*)
             soft_enable unit_tests
+            soft_enable webm_io
         ;;
         *-android-*)
             # GTestLog must be modified to use Android logging utilities.
@@ -726,13 +724,21 @@
             check_cxx "$@" <<EOF && soft_enable unit_tests
 int z;
 EOF
+            check_cxx "$@" <<EOF && soft_enable webm_io
+int z;
+EOF
         ;;
         *)
             enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests
 int z;
 EOF
+            check_cxx "$@" <<EOF && soft_enable webm_io
+int z;
+EOF
         ;;
     esac
+    # libwebm needs to be linked with C++ standard library
+    enabled webm_io && LD=${CXX}
 }
 
 
diff --git a/examples.mk b/examples.mk
index fa5d66c..91b9801 100644
--- a/examples.mk
+++ b/examples.mk
@@ -15,6 +15,16 @@
                 third_party/libyuv/source/scale.c  \
                 third_party/libyuv/source/cpu_id.c
 
+LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer.cpp \
+                      third_party/libwebm/mkvmuxerutil.cpp \
+                      third_party/libwebm/mkvwriter.cpp \
+                      third_party/libwebm/mkvmuxer.hpp \
+                      third_party/libwebm/mkvmuxertypes.hpp \
+                      third_party/libwebm/mkvmuxerutil.hpp \
+                      third_party/libwebm/mkvparser.hpp \
+                      third_party/libwebm/mkvwriter.hpp \
+                      third_party/libwebm/webmids.hpp
+
 # List of examples to build. UTILS are tools meant for distribution
 # while EXAMPLES demonstrate specific portions of the API.
 UTILS-$(CONFIG_DECODERS)    += vpxdec.c
@@ -53,10 +63,8 @@
 vpxenc.SRCS                 += vpxstats.c vpxstats.h
 vpxenc.SRCS                 += $(LIBYUV_SRCS)
 ifeq ($(CONFIG_WEBM_IO),yes)
-  vpxenc.SRCS                 += third_party/libmkv/EbmlIDs.h
-  vpxenc.SRCS                 += third_party/libmkv/EbmlWriter.c
-  vpxenc.SRCS                 += third_party/libmkv/EbmlWriter.h
-  vpxenc.SRCS                 += webmenc.c webmenc.h
+  vpxenc.SRCS                 += $(LIBWEBM_MUXER_SRCS)
+  vpxenc.SRCS                 += webmenc.cc webmenc.h
 endif
 vpxenc.GUID                  = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
 vpxenc.DESCRIPTION           = Full featured encoder
diff --git a/examples/vpx_temporal_scalable_patterns.c b/examples/vpx_temporal_scalable_patterns.c
index 5cb4ee9..07dd318 100644
--- a/examples/vpx_temporal_scalable_patterns.c
+++ b/examples/vpx_temporal_scalable_patterns.c
@@ -526,7 +526,7 @@
   // Enable error resilient mode.
   cfg.g_error_resilient = 1;
   cfg.g_lag_in_frames   = 0;
-  cfg.kf_mode = VPX_KF_DISABLED;
+  cfg.kf_mode = VPX_KF_AUTO;
 
   // Disable automatic keyframe placement.
   cfg.kf_min_dist = cfg.kf_max_dist = 3000;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index ef37c0e..32c5997 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -1761,8 +1761,11 @@
 
 }
 
+#ifndef M_LOG2_E
 #define M_LOG2_E 0.693147180559945309417
+#endif
 #define log2f(x) (log (x) / (float) M_LOG2_E)
+
 static void cal_mvsadcosts(int *mvsadcost[2])
 {
     int i = 1;
diff --git a/vp9/common/vp9_mvref_common.c b/vp9/common/vp9_mvref_common.c
index 1aab362..61682c4 100644
--- a/vp9/common/vp9_mvref_common.c
+++ b/vp9/common/vp9_mvref_common.c
@@ -195,7 +195,7 @@
                              int block, int mi_row, int mi_col) {
   const int *ref_sign_bias = cm->ref_frame_sign_bias;
   int i, refmv_count = 0;
-  const MODE_INFO *prev_mi = cm->prev_mi
+  const MODE_INFO *prev_mi = cm->coding_use_prev_mi && cm->prev_mi
         ? cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col]
         : NULL;
   const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index fe9cc9e..77f563f 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -284,15 +284,15 @@
   xd->left_available  = (mi_col > tile->mi_col_start);
 }
 
-static INLINE MODE_INFO *get_prev_mi(VP9_COMMON *cm) {
-  const int use_prev_mi = cm->coding_use_prev_mi &&
-                          cm->width == cm->last_width &&
-                          cm->height == cm->last_height &&
-                          !cm->intra_only &&
-                          cm->last_show_frame;
+static INLINE void set_prev_mi(VP9_COMMON *cm) {
+  const int use_prev_in_find_mv_refs = cm->width == cm->last_width &&
+                                       cm->height == cm->last_height &&
+                                       !cm->intra_only &&
+                                       cm->last_show_frame;
   // Special case: set prev_mi to NULL when the previous mode info
   // context cannot be used.
-  return use_prev_mi ? &cm->prev_mip[cm->mi_stride + 1] : NULL;
+  cm->prev_mi = use_prev_in_find_mv_refs ?
+                  cm->prev_mip + cm->mi_stride + 1 : NULL;
 }
 
 static INLINE int frame_is_intra_only(const VP9_COMMON *const cm) {
diff --git a/vp9/common/x86/vp9_copy_sse2.asm b/vp9/common/x86/vp9_copy_sse2.asm
index dd522c6..b263837 100644
--- a/vp9/common/x86/vp9_copy_sse2.asm
+++ b/vp9/common/x86/vp9_copy_sse2.asm
@@ -133,10 +133,14 @@
   movh                    m3, [srcq+r5q]
   lea                   srcq, [srcq+src_strideq*4]
 %ifidn %1, avg
-  pavgb                   m0, [dstq]
-  pavgb                   m1, [dstq+dst_strideq]
-  pavgb                   m2, [dstq+dst_strideq*2]
-  pavgb                   m3, [dstq+r6q]
+  movh                    m4, [dstq]
+  movh                    m5, [dstq+dst_strideq]
+  movh                    m6, [dstq+dst_strideq*2]
+  movh                    m7, [dstq+r6q]
+  pavgb                   m0, m4
+  pavgb                   m1, m5
+  pavgb                   m2, m6
+  pavgb                   m3, m7
 %endif
   movh  [dstq              ], m0
   movh  [dstq+dst_strideq  ], m1
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 9b63961..022a429 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -1296,7 +1296,11 @@
   }
 
   init_macroblockd(cm, &pbi->mb);
-  cm->prev_mi = get_prev_mi(cm);
+
+  if (cm->coding_use_prev_mi)
+    set_prev_mi(cm);
+  else
+    cm->prev_mi = NULL;
 
   setup_plane_dequants(cm, xd, cm->base_qindex);
   vp9_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 61a5022..34ea88c 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -103,34 +103,31 @@
 };
 
 static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi,
-                                              MACROBLOCK *x,
+                                              const struct buf_2d *ref,
                                               BLOCK_SIZE bs) {
-  unsigned int var, sse;
-  var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
-                           VP9_VAR_OFFS, 0, &sse);
+  unsigned int sse;
+  const unsigned int var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
+                                              VP9_VAR_OFFS, 0, &sse);
   return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
 }
 
 static unsigned int get_sby_perpixel_diff_variance(VP9_COMP *cpi,
-                                                   MACROBLOCK *x,
-                                                   int mi_row,
-                                                   int mi_col,
+                                                   const struct buf_2d *ref,
+                                                   int mi_row, int mi_col,
                                                    BLOCK_SIZE bs) {
-  const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
-  int offset = (mi_row * MI_SIZE) * yv12->y_stride + (mi_col * MI_SIZE);
-  unsigned int var, sse;
-  var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf,
-                           x->plane[0].src.stride,
-                           yv12->y_buffer + offset,
-                           yv12->y_stride,
-                           &sse);
+  const YV12_BUFFER_CONFIG *last = get_ref_frame_buffer(cpi, LAST_FRAME);
+  const uint8_t* last_y = &last->y_buffer[mi_row * MI_SIZE * last->y_stride +
+                                              mi_col * MI_SIZE];
+  unsigned int sse;
+  const unsigned int var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride,
+                                              last_y, last->y_stride, &sse);
   return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
 }
 
 static BLOCK_SIZE get_rd_var_based_fixed_partition(VP9_COMP *cpi,
                                                    int mi_row,
                                                    int mi_col) {
-  unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb,
+  unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb.plane[0].src,
                                                     mi_row, mi_col,
                                                     BLOCK_64X64);
   if (var < 8)
@@ -146,7 +143,7 @@
 static BLOCK_SIZE get_nonrd_var_based_fixed_partition(VP9_COMP *cpi,
                                                       int mi_row,
                                                       int mi_col) {
-  unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb,
+  unsigned int var = get_sby_perpixel_diff_variance(cpi, &cpi->mb.plane[0].src,
                                                     mi_row, mi_col,
                                                     BLOCK_64X64);
   if (var < 4)
@@ -1013,12 +1010,16 @@
   // Set to zero to make sure we do not use the previous encoded frame stats
   mbmi->skip = 0;
 
-  x->source_variance = get_sby_perpixel_variance(cpi, x, bsize);
+  x->source_variance = get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
+
+  // Save rdmult before it might be changed, so it can be restored later.
+  orig_rdmult = x->rdmult;
+  if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
+    activity_masking(cpi, x);
 
   if (aq_mode == VARIANCE_AQ) {
     const int energy = bsize <= BLOCK_16X16 ? x->mb_energy
                                             : vp9_block_energy(cpi, x, bsize);
-
     if (cm->frame_type == KEY_FRAME ||
         cpi->refresh_alt_ref_frame ||
         (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
@@ -1031,14 +1032,6 @@
 
     rdmult_ratio = vp9_vaq_rdmult_ratio(energy);
     vp9_init_plane_quantizers(cpi, x);
-  }
-
-  // Save rdmult before it might be changed, so it can be restored later.
-  orig_rdmult = x->rdmult;
-  if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
-    activity_masking(cpi, x);
-
-  if (aq_mode == VARIANCE_AQ) {
     vp9_clear_system_state();
     x->rdmult = (int)round(x->rdmult * rdmult_ratio);
   } else if (aq_mode == COMPLEXITY_AQ) {
@@ -1070,14 +1063,11 @@
                                     totaldist, bsize, ctx, best_rd);
   }
 
-  if (aq_mode == VARIANCE_AQ) {
-    x->rdmult = orig_rdmult;
-    if (*totalrate != INT_MAX) {
-      vp9_clear_system_state();
-      *totalrate = (int)round(*totalrate * rdmult_ratio);
-    }
-  } else if (aq_mode == COMPLEXITY_AQ || aq_mode == CYCLIC_REFRESH_AQ) {
-    x->rdmult = orig_rdmult;
+  x->rdmult = orig_rdmult;
+
+  if (aq_mode == VARIANCE_AQ && *totalrate != INT_MAX) {
+    vp9_clear_system_state();
+    *totalrate = (int)round(*totalrate * rdmult_ratio);
   }
 }
 
@@ -1483,8 +1473,8 @@
     const int pre_offset = (mi_row * MI_SIZE) * pre_stride +
                            (mi_col * MI_SIZE);
     const uint8_t *pre_src = cpi->Last_Source->y_buffer + pre_offset;
-    const int thr_32x32 = cpi->sf.source_var_thresh;
-    const int thr_64x64 = thr_32x32 << 1;
+    const unsigned int thr_32x32 = cpi->sf.source_var_thresh;
+    const unsigned int thr_64x64 = thr_32x32 << 1;
     int i, j;
     int index;
     diff d32[4];
@@ -2234,7 +2224,7 @@
   if (cpi->sf.disable_split_var_thresh && partition_none_allowed) {
     unsigned int source_variancey;
     vp9_setup_src_planes(x, cpi->Source, mi_row, mi_col);
-    source_variancey = get_sby_perpixel_variance(cpi, x, bsize);
+    source_variancey = get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
     if (source_variancey < cpi->sf.disable_split_var_thresh) {
       do_split = 0;
       if (source_variancey < cpi->sf.disable_split_var_thresh / 2)
@@ -3266,7 +3256,7 @@
   if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
     build_activity_map(cpi);
 
-  cm->prev_mi = get_prev_mi(cm);
+  set_prev_mi(cm);
 
   if (sf->use_nonrd_pick_mode) {
     // Initialize internal buffer pointers for rtc coding, where non-RD
@@ -3284,9 +3274,9 @@
     }
     vp9_zero(x->zcoeff_blk);
 
-    if (cpi->sf.partition_search_type == SOURCE_VAR_BASED_PARTITION &&
+    if (sf->partition_search_type == SOURCE_VAR_BASED_PARTITION &&
         cm->current_video_frame > 0) {
-      int check_freq = cpi->sf.search_type_check_frequency;
+      int check_freq = sf->search_type_check_frequency;
 
       if ((cm->current_video_frame - 1) % check_freq == 0) {
         cpi->use_large_partition_rate = 0;
@@ -3303,7 +3293,7 @@
 
       if ((cm->current_video_frame - 1) % check_freq >= 1) {
         if (cpi->use_large_partition_rate < 15)
-          cpi->sf.partition_search_type = FIXED_PARTITION;
+          sf->partition_search_type = FIXED_PARTITION;
       }
     }
   }
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 5e98e4e..2bea93f 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -105,9 +105,8 @@
   return pt;
 }
 
-static void optimize_b(int plane, int block, BLOCK_SIZE plane_bsize,
-                       TX_SIZE tx_size, MACROBLOCK *mb,
-                       ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l) {
+static int optimize_b(MACROBLOCK *mb, int plane, int block,
+                      BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int ctx) {
   MACROBLOCKD *const xd = &mb->e_mbd;
   struct macroblock_plane *p = &mb->plane[plane];
   struct macroblockd_plane *pd = &xd->plane[plane];
@@ -172,12 +171,10 @@
       if (next < default_eob) {
         band = band_translate[i + 1];
         pt = trellis_get_coeff_context(scan, nb, i, t0, token_cache);
-        rate0 +=
-          mb->token_costs[tx_size][type][ref][band][0][pt]
-                         [tokens[next][0].token];
-        rate1 +=
-          mb->token_costs[tx_size][type][ref][band][0][pt]
-                         [tokens[next][1].token];
+        rate0 += mb->token_costs[tx_size][type][ref][band][0][pt]
+                                [tokens[next][0].token];
+        rate1 += mb->token_costs[tx_size][type][ref][band][0][pt]
+                                [tokens[next][1].token];
       }
       UPDATE_RD_COST();
       /* And pick the best. */
@@ -274,15 +271,14 @@
 
   /* Now pick the best path through the whole trellis. */
   band = band_translate[i + 1];
-  pt = combine_entropy_contexts(*a, *l);
   rate0 = tokens[next][0].rate;
   rate1 = tokens[next][1].rate;
   error0 = tokens[next][0].error;
   error1 = tokens[next][1].error;
   t0 = tokens[next][0].token;
   t1 = tokens[next][1].token;
-  rate0 += mb->token_costs[tx_size][type][ref][band][0][pt][t0];
-  rate1 += mb->token_costs[tx_size][type][ref][band][0][pt][t1];
+  rate0 += mb->token_costs[tx_size][type][ref][band][0][ctx][t0];
+  rate1 += mb->token_costs[tx_size][type][ref][band][0][ctx][t1];
   UPDATE_RD_COST();
   best = rd_cost1 < rd_cost0;
   final_eob = i0 - 1;
@@ -303,7 +299,7 @@
   final_eob++;
 
   mb->plane[plane].eobs[block] = final_eob;
-  *a = *l = (final_eob > 0);
+  return final_eob;
 }
 
 static INLINE void fdct32x32(int rd_transform,
@@ -393,7 +389,8 @@
     vp9_xform_quant(x, plane, block, plane_bsize, tx_size);
 
   if (x->optimize && (!x->skip_recode || !x->skip_optimize)) {
-    optimize_b(plane, block, plane_bsize, tx_size, x, a, l);
+    const int ctx = combine_entropy_contexts(*a, *l);
+    *a = *l = optimize_b(x, plane, block, plane_bsize, tx_size, ctx) > 0;
   } else {
     *a = *l = p->eobs[block] > 0;
   }
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index db32ef8..3324b9c 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -981,8 +981,6 @@
                                    oxcf->target_bandwidth / 10000000.0);
   }
 
-  cpi->output_framerate = oxcf->framerate;
-
   // Calculate a minimum intra value to be used in determining the IIratio
   // scores used in the second pass. We have this minimum to make sure
   // that clips that are static but "low complexity" in the intra domain
diff --git a/vp9/encoder/vp9_mcomp.c b/vp9/encoder/vp9_mcomp.c
index f7a02a4..37201a9 100644
--- a/vp9/encoder/vp9_mcomp.c
+++ b/vp9/encoder/vp9_mcomp.c
@@ -993,20 +993,21 @@
   const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
   const int *mvjsadcost = x->nmvjointsadcost;
   int *mvsadcost[2] = {x->nmvsadcost[0], x->nmvsadcost[1]};
-  const uint8_t *best_address;
+  const uint8_t *best_address, *in_what_ref;
   int best_sad = INT_MAX;
   int best_site = 0;
   int last_site = 0;
   int i, j, step;
 
   clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
-  best_address = get_buf_from_mv(in_what, ref_mv);
+  in_what_ref = get_buf_from_mv(in_what, ref_mv);
+  best_address = in_what_ref;
   *num00 = 0;
   *best_mv = *ref_mv;
 
   // Check the starting position
   best_sad = fn_ptr->sdf(what->buf, what->stride,
-                        in_what->buf, in_what->stride, 0x7fffffff) +
+                         best_address, in_what->stride, 0x7fffffff) +
       mvsad_err_cost(best_mv, &fcenter_mv, mvjsadcost, mvsadcost, sad_per_bit);
 
   i = 1;
@@ -1060,7 +1061,7 @@
         break;
       };
 #endif
-    } else if (best_address == in_what->buf) {
+    } else if (best_address == in_what_ref) {
       (*num00)++;
     }
   }
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 0ac9d5f..871d057 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -633,9 +633,8 @@
   int vbr_max_bits;
 
   oxcf->framerate = framerate < 0.1 ? 30 : framerate;
-  cpi->output_framerate = cpi->oxcf.framerate;
   rc->av_per_frame_bandwidth = (int)(oxcf->target_bandwidth /
-                                     cpi->output_framerate);
+                                   oxcf->framerate);
   rc->min_frame_bandwidth = (int)(rc->av_per_frame_bandwidth *
                                   oxcf->two_pass_vbrmin_section / 100);
 
@@ -906,7 +905,9 @@
   cpi->ext_refresh_frame_context_pending = 0;
 }
 
+#ifndef M_LOG2_E
 #define M_LOG2_E 0.693147180559945309417
+#endif
 #define log2f(x) (log (x) / (float) M_LOG2_E)
 
 static void cal_nmvjointsadcost(int *mvjointsadcost) {
@@ -1386,8 +1387,6 @@
 
   cm->error.setjmp = 0;
 
-  vp9_zero(cpi->common.counts.uv_mode);
-
 #ifdef MODE_TEST_HIT_STATS
   vp9_zero(cpi->mode_test_hits);
 #endif
@@ -2658,6 +2657,7 @@
 
   get_ref_frame_flags(cpi);
 
+  cm->last_frame_type = cm->frame_type;
   vp9_rc_postencode_update(cpi, *size);
 
   if (cm->frame_type == KEY_FRAME) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 18203f9..126711e 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -376,7 +376,6 @@
   int active_arnr_frames;           // <= cpi->oxcf.arnr_max_frames
   int active_arnr_strength;         // <= cpi->oxcf.arnr_max_strength
 
-  double output_framerate;
   int64_t last_time_stamp_seen;
   int64_t last_end_time_stamp_seen;
   int64_t first_time_stamp_ever;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 3420816..00489cd 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -367,8 +367,8 @@
 
   // Calculate required scaling factor based on target frame size and size of
   // frame produced using previous Q.
-    target_bits_per_mb =
-        ((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
+  target_bits_per_mb =
+      ((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
 
   i = active_best_quality;
 
@@ -1065,11 +1065,10 @@
 }
 
 void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
-  VP9_COMMON *const cm = &cpi->common;
+  const VP9_COMMON *const cm = &cpi->common;
   const VP9_CONFIG *const oxcf = &cpi->oxcf;
   RATE_CONTROL *const rc = &cpi->rc;
 
-  cm->last_frame_type = cm->frame_type;
   // Update rate control heuristics
   rc->projected_frame_size = (int)(bytes_used << 3);
 
@@ -1258,17 +1257,25 @@
 
 static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
   const RATE_CONTROL *rc = &cpi->rc;
+  const VP9_CONFIG *oxcf = &cpi->oxcf;
+  const SVC *const svc = &cpi->svc;
   int target;
-
   if (cpi->common.current_video_frame == 0) {
     target = ((cpi->oxcf.starting_buffer_level / 2) > INT_MAX)
       ? INT_MAX : (int)(cpi->oxcf.starting_buffer_level / 2);
   } else {
-    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) {
+    int kf_boost = 32;
+    double framerate = oxcf->framerate;
+    if (svc->number_temporal_layers > 1 &&
+        oxcf->end_usage == USAGE_STREAM_FROM_SERVER) {
+      // Use the layer framerate for temporal layers CBR mode.
+      const LAYER_CONTEXT *lc = &svc->layer_context[svc->temporal_layer_id];
+      framerate = lc->framerate;
+    }
+    kf_boost = MAX(kf_boost, (int)(2 * framerate - 16));
+    if (rc->frames_since_key <  framerate / 2) {
       kf_boost = (int)(kf_boost * rc->frames_since_key /
-                       (cpi->output_framerate / 2));
+                       (framerate / 2));
     }
     target = ((16 + kf_boost) * rc->av_per_frame_bandwidth) >> 4;
   }
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 7693c2b..0b12a4c 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -125,8 +125,7 @@
 
 // Post encode update of the rate control parameters based
 // on bytes used
-void vp9_rc_postencode_update(struct VP9_COMP *cpi,
-                              uint64_t bytes_used);
+void vp9_rc_postencode_update(struct VP9_COMP *cpi, uint64_t bytes_used);
 // Post encode update of the rate control parameters for dropped frames
 void vp9_rc_postencode_update_drop_frame(struct VP9_COMP *cpi);
 
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 1d70c1f..1b4cc51 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -81,7 +81,7 @@
   const scan_order *so;
 };
 
-const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
+static const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
   {NEARESTMV, {LAST_FRAME,   NONE}},
   {NEARESTMV, {ALTREF_FRAME, NONE}},
   {NEARESTMV, {GOLDEN_FRAME, NONE}},
@@ -121,7 +121,7 @@
   {D45_PRED,  {INTRA_FRAME,  NONE}},
 };
 
-const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
+static const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
   {{LAST_FRAME,   NONE}},
   {{GOLDEN_FRAME, NONE}},
   {{ALTREF_FRAME, NONE}},
@@ -134,8 +134,9 @@
 // certain modes are assumed to be based on 8x8 blocks.
 // This table is used to correct for blocks size.
 // The factors here are << 2 (2 = x0.5, 32 = x8 etc).
-static int rd_thresh_block_size_factor[BLOCK_SIZES] =
-  {2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32};
+static const uint8_t rd_thresh_block_size_factor[BLOCK_SIZES] = {
+  2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32
+};
 
 static int raster_block_offset(BLOCK_SIZE plane_bsize,
                                int raster_block, int stride) {
@@ -192,7 +193,7 @@
           }
 }
 
-static const int rd_iifactor[32] = {
+static const uint8_t rd_iifactor[32] = {
   4, 4, 3, 2, 1, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0,
@@ -2267,7 +2268,7 @@
                          int_mv *ref_mv,
                          int_mv *second_ref_mv,
                          int64_t comp_pred_diff[REFERENCE_MODES],
-                         int64_t tx_size_diff[TX_MODES],
+                         const int64_t tx_size_diff[TX_MODES],
                          int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS]) {
   MACROBLOCKD *const xd = &x->e_mbd;
 
@@ -3145,7 +3146,7 @@
   int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
   int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
   MB_MODE_INFO best_mbmode = { 0 };
-  int mode_index, best_mode_index = 0;
+  int mode_index, best_mode_index = -1;
   unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
   vp9_prob comp_mode_p;
   int64_t best_intra_rd = INT64_MAX;
@@ -3302,7 +3303,7 @@
 
     // Look at the reference frame of the best mode so far and set the
     // skip mask to look at a subset of the remaining modes.
-    if (mode_index == mode_skip_start && best_rd < INT64_MAX) {
+    if (mode_index == mode_skip_start && best_mode_index >= 0) {
       switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
         case INTRA_FRAME:
           break;
@@ -3339,6 +3340,7 @@
     comp_pred = second_ref_frame > INTRA_FRAME;
     if (comp_pred) {
       if ((mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) &&
+          best_mode_index >=0 &&
           vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
         continue;
       if ((mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH) &&
@@ -3366,7 +3368,8 @@
         // one of the neighboring directional modes
         if ((mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
             (this_mode >= D45_PRED && this_mode <= TM_PRED)) {
-          if (vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
+          if (best_mode_index >= 0 &&
+              vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
             continue;
         }
         if (mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
@@ -3654,7 +3657,7 @@
       break;
   }
 
-  if (best_rd >= best_rd_so_far)
+  if (best_mode_index < 0 || best_rd >= best_rd_so_far)
     return INT64_MAX;
 
   // If we used an estimate for the uv intra rd in the loop above...
@@ -3768,8 +3771,7 @@
                                     VP9_ALT_FLAG };
   int64_t best_rd = best_rd_so_far;
   int64_t best_yrd = best_rd_so_far;  // FIXME(rbultje) more precise
-  int64_t best_tx_rd[TX_MODES];
-  int64_t best_tx_diff[TX_MODES];
+  static const int64_t best_tx_diff[TX_MODES] = { 0 };
   int64_t best_pred_diff[REFERENCE_MODES];
   int64_t best_pred_rd[REFERENCE_MODES];
   int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
@@ -3781,10 +3783,10 @@
   int64_t best_inter_rd = INT64_MAX;
   MV_REFERENCE_FRAME best_inter_ref_frame = LAST_FRAME;
   INTERP_FILTER tmp_best_filter = SWITCHABLE;
-  int rate_uv_intra[TX_SIZES], rate_uv_tokenonly[TX_SIZES];
-  int64_t dist_uv[TX_SIZES];
-  int skip_uv[TX_SIZES];
-  MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 };
+  int rate_uv_intra, rate_uv_tokenonly;
+  int64_t dist_uv;
+  int skip_uv;
+  MB_PREDICTION_MODE mode_uv = DC_PRED;
   int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
   int_mv seg_mvs[4][MAX_REF_FRAMES];
   b_mode_info best_bmodes[4];
@@ -3806,12 +3808,9 @@
 
   for (i = 0; i < REFERENCE_MODES; ++i)
     best_pred_rd[i] = INT64_MAX;
-  for (i = 0; i < TX_MODES; i++)
-    best_tx_rd[i] = INT64_MAX;
   for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; i++)
     best_filter_rd[i] = INT64_MAX;
-  for (i = 0; i < TX_SIZES; i++)
-    rate_uv_intra[i] = INT_MAX;
+  rate_uv_intra = INT_MAX;
 
   *returnrate = INT_MAX;
 
@@ -3845,7 +3844,6 @@
     int rate2 = 0, rate_y = 0, rate_uv = 0;
     int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
     int skippable = 0;
-    int64_t tx_cache[TX_MODES];
     int i;
     int this_skip2 = 0;
     int64_t total_sse = INT_MAX;
@@ -3968,9 +3966,6 @@
         xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
     }
 
-    for (i = 0; i < TX_MODES; ++i)
-      tx_cache[i] = INT64_MAX;
-
 #ifdef MODE_TEST_HIT_STATS
     // TEST/DEBUG CODE
     // Keep a rcord of the number of test hits at each size
@@ -3986,21 +3981,18 @@
       rate2 += intra_cost_penalty;
       distortion2 += distortion_y;
 
-      if (rate_uv_intra[TX_4X4] == INT_MAX) {
+      if (rate_uv_intra == INT_MAX) {
         choose_intra_uv_mode(cpi, ctx, bsize, TX_4X4,
-                             &rate_uv_intra[TX_4X4],
-                             &rate_uv_tokenonly[TX_4X4],
-                             &dist_uv[TX_4X4], &skip_uv[TX_4X4],
-                             &mode_uv[TX_4X4]);
+                             &rate_uv_intra,
+                             &rate_uv_tokenonly,
+                             &dist_uv, &skip_uv,
+                             &mode_uv);
       }
-      rate2 += rate_uv_intra[TX_4X4];
-      rate_uv = rate_uv_tokenonly[TX_4X4];
-      distortion2 += dist_uv[TX_4X4];
-      distortion_uv = dist_uv[TX_4X4];
-      mbmi->uv_mode = mode_uv[TX_4X4];
-      tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
-      for (i = 0; i < TX_MODES; ++i)
-        tx_cache[i] = tx_cache[ONLY_4X4];
+      rate2 += rate_uv_intra;
+      rate_uv = rate_uv_tokenonly;
+      distortion2 += dist_uv;
+      distortion_uv = dist_uv;
+      mbmi->uv_mode = mode_uv;
     } else {
       int rate;
       int64_t distortion;
@@ -4163,10 +4155,6 @@
         distortion2 += distortion_uv;
         skippable = skippable && uv_skippable;
         total_sse += uv_sse;
-
-        tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
-        for (i = 0; i < TX_MODES; ++i)
-          tx_cache[i] = tx_cache[ONLY_4X4];
       }
     }
 
@@ -4324,23 +4312,6 @@
       }
     }
 
-    /* keep record of best txfm size */
-    tx_cache[ALLOW_8X8] = tx_cache[ONLY_4X4];
-    tx_cache[ALLOW_16X16] = tx_cache[ALLOW_8X8];
-    tx_cache[ALLOW_32X32] = tx_cache[ALLOW_16X16];
-    if (!mode_excluded && this_rd != INT64_MAX) {
-      for (i = 0; i < TX_MODES && tx_cache[i] < INT64_MAX; i++) {
-        int64_t adj_rd = INT64_MAX;
-        if (ref_frame > INTRA_FRAME)
-          adj_rd = this_rd + tx_cache[i] - tx_cache[cm->tx_mode];
-        else
-          adj_rd = this_rd;
-
-        if (adj_rd < best_tx_rd[i])
-          best_tx_rd[i] = adj_rd;
-      }
-    }
-
     if (early_term)
       break;
 
@@ -4355,14 +4326,12 @@
   if (cpi->sf.use_uv_intra_rd_estimate) {
     // Do Intra UV best rd mode selection if best mode choice above was intra.
     if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
-      TX_SIZE uv_tx_size;
       *mbmi = best_mbmode;
-      uv_tx_size = get_uv_tx_size(mbmi);
-      rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra[uv_tx_size],
-                              &rate_uv_tokenonly[uv_tx_size],
-                              &dist_uv[uv_tx_size],
-                              &skip_uv[uv_tx_size],
-                              BLOCK_8X8, uv_tx_size);
+      rd_pick_intra_sbuv_mode(cpi, x, ctx, &rate_uv_intra,
+                              &rate_uv_tokenonly,
+                              &dist_uv,
+                              &skip_uv,
+                              BLOCK_8X8, TX_4X4);
     }
   }
 
@@ -4424,15 +4393,8 @@
     }
     if (cm->interp_filter == SWITCHABLE)
       assert(best_filter_diff[SWITCHABLE_FILTERS] == 0);
-    for (i = 0; i < TX_MODES; i++) {
-      if (best_tx_rd[i] == INT64_MAX)
-        best_tx_diff[i] = 0;
-      else
-        best_tx_diff[i] = best_rd - best_tx_rd[i];
-    }
   } else {
     vp9_zero(best_filter_diff);
-    vp9_zero(best_tx_diff);
   }
 
   set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index d6b6174..adad800 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -269,9 +269,6 @@
     sf->partition_search_type = SOURCE_VAR_BASED_PARTITION;
     sf->search_type_check_frequency = 50;
     sf->source_var_thresh = 360;
-
-    sf->use_nonrd_pick_mode = 1;
-    sf->search_method = FAST_DIAMOND;
   }
 
   if (speed >= 7) {
diff --git a/vp9/encoder/vp9_speed_features.h b/vp9/encoder/vp9_speed_features.h
index 72f548a..5542297 100644
--- a/vp9/encoder/vp9_speed_features.h
+++ b/vp9/encoder/vp9_speed_features.h
@@ -344,7 +344,7 @@
   int search_type_check_frequency;
 
   // The threshold used in SOURCE_VAR_BASED_PARTITION search type.
-  int source_var_thresh;
+  unsigned int source_var_thresh;
 } SPEED_FEATURES;
 
 struct VP9_COMP;
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index c2b6263..9b3fc6e 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -178,7 +178,6 @@
   cpi->oxcf.starting_buffer_level = lc->starting_buffer_level;
   cpi->oxcf.optimal_buffer_level = lc->optimal_buffer_level;
   cpi->oxcf.maximum_buffer_size = lc->maximum_buffer_size;
-  cpi->output_framerate = lc->framerate;
   // Reset the frames_since_key and frames_to_key counters to their values
   // before the layer restore. Keep these defined for the stream (not layer).
   if (cpi->svc.number_temporal_layers > 1) {
@@ -197,7 +196,6 @@
   lc->starting_buffer_level = oxcf->starting_buffer_level;
   lc->optimal_buffer_level = oxcf->optimal_buffer_level;
   lc->maximum_buffer_size = oxcf->maximum_buffer_size;
-  lc->framerate = cpi->output_framerate;
 }
 
 void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
diff --git a/vpxenc.c b/vpxenc.c
index 00d3e3e..cb91d94 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -123,55 +123,6 @@
   return 0;
 }
 
-#if CONFIG_WEBM_IO
-/* Murmur hash derived from public domain reference implementation at
- *   http:// sites.google.com/site/murmurhash/
- */
-static unsigned int murmur(const void *key, int len, unsigned int seed) {
-  const unsigned int m = 0x5bd1e995;
-  const int r = 24;
-
-  unsigned int h = seed ^ len;
-
-  const unsigned char *data = (const unsigned char *)key;
-
-  while (len >= 4) {
-    unsigned int k;
-
-    k  = (unsigned int)data[0];
-    k |= (unsigned int)data[1] << 8;
-    k |= (unsigned int)data[2] << 16;
-    k |= (unsigned int)data[3] << 24;
-
-    k *= m;
-    k ^= k >> r;
-    k *= m;
-
-    h *= m;
-    h ^= k;
-
-    data += 4;
-    len -= 4;
-  }
-
-  switch (len) {
-    case 3:
-      h ^= data[2] << 16;
-    case 2:
-      h ^= data[1] << 8;
-    case 1:
-      h ^= data[0];
-      h *= m;
-  };
-
-  h ^= h >> 13;
-  h *= m;
-  h ^= h >> 15;
-
-  return h;
-}
-#endif  // CONFIG_WEBM_IO
-
 static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
                                            "Debug mode (makes output deterministic)");
 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
@@ -619,7 +570,6 @@
   FILE                     *file;
   struct rate_hist         *rate_hist;
   struct EbmlGlobal         ebml;
-  uint32_t                  hash;
   uint64_t                  psnr_sse_total;
   uint64_t                  psnr_samples_total;
   double                    psnr_totals[4];
@@ -841,7 +791,9 @@
     stream->config.stereo_fmt = STEREO_FORMAT_MONO;
     stream->config.write_webm = 1;
 #if CONFIG_WEBM_IO
-    stream->ebml.last_pts_ms = -1;
+    stream->ebml.last_pts_ns = -1;
+    stream->ebml.writer = NULL;
+    stream->ebml.segment = NULL;
 #endif
 
     /* Allows removal of the application version from the EBML tags */
@@ -1176,9 +1128,7 @@
 
 #if CONFIG_WEBM_IO
   if (stream->config.write_webm) {
-    write_webm_file_footer(&stream->ebml, stream->hash);
-    free(stream->ebml.cue_list);
-    stream->ebml.cue_list = NULL;
+    write_webm_file_footer(&stream->ebml);
   }
 #endif
 
@@ -1334,12 +1284,6 @@
         update_rate_histogram(stream->rate_hist, cfg, pkt);
 #if CONFIG_WEBM_IO
         if (stream->config.write_webm) {
-          /* Update the hash */
-          if (!stream->ebml.debug)
-            stream->hash = murmur(pkt->data.frame.buf,
-                                  (int)pkt->data.frame.sz,
-                                  stream->hash);
-
           write_webm_block(&stream->ebml, cfg, pkt);
         }
 #endif
diff --git a/webmenc.c b/webmenc.c
deleted file mode 100644
index 17bbeec..0000000
--- a/webmenc.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- *  Copyright (c) 2013 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 "webmenc.h"
-
-#include <limits.h>
-#include <string.h>
-
-#include "third_party/libmkv/EbmlWriter.h"
-#include "third_party/libmkv/EbmlIDs.h"
-
-void Ebml_Write(struct EbmlGlobal *glob,
-                const void *buffer_in,
-                unsigned long len) {
-  (void) fwrite(buffer_in, 1, len, glob->stream);
-}
-
-#define WRITE_BUFFER(s) \
-for (i = len - 1; i >= 0; i--) { \
-  x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
-  Ebml_Write(glob, &x, 1); \
-}
-
-void Ebml_Serialize(struct EbmlGlobal *glob,
-                    const void *buffer_in,
-                    int buffer_size,
-                    unsigned long len) {
-  char x;
-  int i;
-
-  /* buffer_size:
-   * 1 - int8_t;
-   * 2 - int16_t;
-   * 3 - int32_t;
-   * 4 - int64_t;
-   */
-  switch (buffer_size) {
-    case 1:
-      WRITE_BUFFER(int8_t)
-      break;
-    case 2:
-      WRITE_BUFFER(int16_t)
-      break;
-    case 4:
-      WRITE_BUFFER(int32_t)
-      break;
-    case 8:
-      WRITE_BUFFER(int64_t)
-      break;
-    default:
-      break;
-  }
-}
-#undef WRITE_BUFFER
-
-/* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
- * one, but not a 32 bit one.
- */
-static void Ebml_SerializeUnsigned32(struct EbmlGlobal *glob,
-                                     unsigned int class_id,
-                                     uint64_t ui) {
-  const unsigned char sizeSerialized = 4 | 0x80;
-  Ebml_WriteID(glob, class_id);
-  Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
-  Ebml_Serialize(glob, &ui, sizeof(ui), 4);
-}
-
-static void Ebml_StartSubElement(struct EbmlGlobal *glob,
-                                 EbmlLoc *ebmlLoc,
-                                 unsigned int class_id) {
-  const uint64_t kEbmlUnknownLength = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
-  Ebml_WriteID(glob, class_id);
-  *ebmlLoc = ftello(glob->stream);
-  Ebml_Serialize(glob, &kEbmlUnknownLength, sizeof(kEbmlUnknownLength), 8);
-}
-
-static void Ebml_EndSubElement(struct EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
-  off_t pos;
-  uint64_t size;
-
-  /* Save the current stream pointer. */
-  pos = ftello(glob->stream);
-
-  /* Calculate the size of this element. */
-  size = pos - *ebmlLoc - 8;
-  size |= LITERALU64(0x01000000, 0x00000000);
-
-  /* Seek back to the beginning of the element and write the new size. */
-  fseeko(glob->stream, *ebmlLoc, SEEK_SET);
-  Ebml_Serialize(glob, &size, sizeof(size), 8);
-
-  /* Reset the stream pointer. */
-  fseeko(glob->stream, pos, SEEK_SET);
-}
-
-void write_webm_seek_element(struct EbmlGlobal *ebml,
-                             unsigned int id,
-                             off_t pos) {
-  uint64_t offset = pos - ebml->position_reference;
-  EbmlLoc start;
-  Ebml_StartSubElement(ebml, &start, Seek);
-  Ebml_SerializeBinary(ebml, SeekID, id);
-  Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
-  Ebml_EndSubElement(ebml, &start);
-}
-
-void write_webm_seek_info(struct EbmlGlobal *ebml) {
-  off_t pos;
-  EbmlLoc start;
-  EbmlLoc startInfo;
-  uint64_t frame_time;
-  char version_string[64];
-
-  /* Save the current stream pointer. */
-  pos = ftello(ebml->stream);
-
-  if (ebml->seek_info_pos)
-    fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
-  else
-    ebml->seek_info_pos = pos;
-
-  Ebml_StartSubElement(ebml, &start, SeekHead);
-  write_webm_seek_element(ebml, Tracks, ebml->track_pos);
-  write_webm_seek_element(ebml, Cues, ebml->cue_pos);
-  write_webm_seek_element(ebml, Info, ebml->segment_info_pos);
-  Ebml_EndSubElement(ebml, &start);
-
-  /* Create and write the Segment Info. */
-  if (ebml->debug) {
-    strcpy(version_string, "vpxenc");
-  } else {
-    strcpy(version_string, "vpxenc ");
-    strncat(version_string,
-            vpx_codec_version_str(),
-            sizeof(version_string) - 1 - strlen(version_string));
-  }
-
-  frame_time = (uint64_t)1000 * ebml->framerate.den
-               / ebml->framerate.num;
-  ebml->segment_info_pos = ftello(ebml->stream);
-  Ebml_StartSubElement(ebml, &startInfo, Info);
-  Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
-  Ebml_SerializeFloat(ebml, Segment_Duration,
-                      (double)(ebml->last_pts_ms + frame_time));
-  Ebml_SerializeString(ebml, 0x4D80, version_string);
-  Ebml_SerializeString(ebml, 0x5741, version_string);
-  Ebml_EndSubElement(ebml, &startInfo);
-}
-
-void write_webm_file_header(struct EbmlGlobal *glob,
-                            const vpx_codec_enc_cfg_t *cfg,
-                            const struct vpx_rational *fps,
-                            stereo_format_t stereo_fmt,
-                            unsigned int fourcc) {
-  EbmlLoc start;
-  EbmlLoc trackStart;
-  EbmlLoc videoStart;
-  unsigned int trackNumber = 1;
-  uint64_t trackID = 0;
-  unsigned int pixelWidth = cfg->g_w;
-  unsigned int pixelHeight = cfg->g_h;
-
-  /* Write the EBML header. */
-  Ebml_StartSubElement(glob, &start, EBML);
-  Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
-  Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
-  Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
-  Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
-  Ebml_SerializeString(glob, DocType, "webm");
-  Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
-  Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
-  Ebml_EndSubElement(glob, &start);
-
-  /* Open and begin writing the segment element. */
-  Ebml_StartSubElement(glob, &glob->startSegment, Segment);
-  glob->position_reference = ftello(glob->stream);
-  glob->framerate = *fps;
-  write_webm_seek_info(glob);
-
-  /* Open and write the Tracks element. */
-  glob->track_pos = ftello(glob->stream);
-  Ebml_StartSubElement(glob, &trackStart, Tracks);
-
-  /* Open and write the Track entry. */
-  Ebml_StartSubElement(glob, &start, TrackEntry);
-  Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
-  glob->track_id_pos = ftello(glob->stream);
-  Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
-  Ebml_SerializeUnsigned(glob, TrackType, 1);
-  Ebml_SerializeString(glob, CodecID,
-                       fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
-  Ebml_StartSubElement(glob, &videoStart, Video);
-  Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
-  Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
-  Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
-  Ebml_EndSubElement(glob, &videoStart);
-
-  /* Close Track entry. */
-  Ebml_EndSubElement(glob, &start);
-
-  /* Close Tracks element. */
-  Ebml_EndSubElement(glob, &trackStart);
-
-  /* Segment element remains open. */
-}
-
-void write_webm_block(struct EbmlGlobal *glob,
-                      const vpx_codec_enc_cfg_t *cfg,
-                      const vpx_codec_cx_pkt_t *pkt) {
-  unsigned int block_length;
-  unsigned char track_number;
-  uint16_t block_timecode = 0;
-  unsigned char flags;
-  int64_t pts_ms;
-  int start_cluster = 0, is_keyframe;
-
-  /* Calculate the PTS of this frame in milliseconds. */
-  pts_ms = pkt->data.frame.pts * 1000
-           * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
-
-  if (pts_ms <= glob->last_pts_ms)
-    pts_ms = glob->last_pts_ms + 1;
-
-  glob->last_pts_ms = pts_ms;
-
-  /* Calculate the relative time of this block. */
-  if (pts_ms - glob->cluster_timecode > SHRT_MAX)
-    start_cluster = 1;
-  else
-    block_timecode = (uint16_t)pts_ms - glob->cluster_timecode;
-
-  is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
-  if (start_cluster || is_keyframe) {
-    if (glob->cluster_open)
-      Ebml_EndSubElement(glob, &glob->startCluster);
-
-    /* Open the new cluster. */
-    block_timecode = 0;
-    glob->cluster_open = 1;
-    glob->cluster_timecode = (uint32_t)pts_ms;
-    glob->cluster_pos = ftello(glob->stream);
-    Ebml_StartSubElement(glob, &glob->startCluster, Cluster);
-    Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
-
-    /* Save a cue point if this is a keyframe. */
-    if (is_keyframe) {
-      struct cue_entry *cue, *new_cue_list;
-
-      new_cue_list = realloc(glob->cue_list,
-                             (glob->cues + 1) * sizeof(struct cue_entry));
-      if (new_cue_list)
-        glob->cue_list = new_cue_list;
-      else
-        fatal("Failed to realloc cue list.");
-
-      cue = &glob->cue_list[glob->cues];
-      cue->time = glob->cluster_timecode;
-      cue->loc = glob->cluster_pos;
-      glob->cues++;
-    }
-  }
-
-  /* Write the Simple Block. */
-  Ebml_WriteID(glob, SimpleBlock);
-
-  block_length = (unsigned int)pkt->data.frame.sz + 4;
-  block_length |= 0x10000000;
-  Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
-
-  track_number = 1;
-  track_number |= 0x80;
-  Ebml_Write(glob, &track_number, 1);
-
-  Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
-
-  flags = 0;
-  if (is_keyframe)
-    flags |= 0x80;
-  if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
-    flags |= 0x08;
-  Ebml_Write(glob, &flags, 1);
-
-  Ebml_Write(glob, pkt->data.frame.buf, (unsigned int)pkt->data.frame.sz);
-}
-
-void write_webm_file_footer(struct EbmlGlobal *glob, int hash) {
-  EbmlLoc start_cues;
-  EbmlLoc start_cue_point;
-  EbmlLoc start_cue_tracks;
-  unsigned int i;
-
-  if (glob->cluster_open)
-    Ebml_EndSubElement(glob, &glob->startCluster);
-
-  glob->cue_pos = ftello(glob->stream);
-  Ebml_StartSubElement(glob, &start_cues, Cues);
-
-  for (i = 0; i < glob->cues; i++) {
-    struct cue_entry *cue = &glob->cue_list[i];
-    Ebml_StartSubElement(glob, &start_cue_point, CuePoint);
-    Ebml_SerializeUnsigned(glob, CueTime, cue->time);
-
-    Ebml_StartSubElement(glob, &start_cue_tracks, CueTrackPositions);
-    Ebml_SerializeUnsigned(glob, CueTrack, 1);
-    Ebml_SerializeUnsigned64(glob, CueClusterPosition,
-                             cue->loc - glob->position_reference);
-    Ebml_EndSubElement(glob, &start_cue_tracks);
-
-    Ebml_EndSubElement(glob, &start_cue_point);
-  }
-
-  Ebml_EndSubElement(glob, &start_cues);
-
-  /* Close the Segment. */
-  Ebml_EndSubElement(glob, &glob->startSegment);
-
-  /* Patch up the seek info block. */
-  write_webm_seek_info(glob);
-
-  /* Patch up the track id. */
-  fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
-  Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
-
-  fseeko(glob->stream, 0, SEEK_END);
-}
diff --git a/webmenc.cc b/webmenc.cc
new file mode 100644
index 0000000..a0e542b
--- /dev/null
+++ b/webmenc.cc
@@ -0,0 +1,87 @@
+/*
+ *  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 "./webmenc.h"
+
+#include <string>
+
+#include "third_party/libwebm/mkvmuxer.hpp"
+#include "third_party/libwebm/mkvmuxerutil.hpp"
+#include "third_party/libwebm/mkvwriter.hpp"
+
+namespace {
+const uint64_t kDebugTrackUid = 0xDEADBEEF;
+const int kVideoTrackNumber = 1;
+}  // namespace
+
+void write_webm_file_header(struct EbmlGlobal *glob,
+                            const vpx_codec_enc_cfg_t *cfg,
+                            const struct vpx_rational *fps,
+                            stereo_format_t stereo_fmt,
+                            unsigned int fourcc) {
+  mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(glob->stream);
+  mkvmuxer::Segment *const segment = new mkvmuxer::Segment();
+  segment->Init(writer);
+  segment->set_mode(mkvmuxer::Segment::kFile);
+  segment->OutputCues(true);
+
+  mkvmuxer::SegmentInfo *const info = segment->GetSegmentInfo();
+  const uint64_t kTimecodeScale = 1000000;
+  info->set_timecode_scale(kTimecodeScale);
+  std::string version = "vpxenc";
+  if (!glob->debug) {
+    version.append(std::string(" ") + vpx_codec_version_str());
+  }
+  info->set_writing_app(version.c_str());
+
+  const uint64_t video_track_id =
+      segment->AddVideoTrack(static_cast<int>(cfg->g_w),
+                             static_cast<int>(cfg->g_h),
+                             kVideoTrackNumber);
+  mkvmuxer::VideoTrack* const video_track =
+      static_cast<mkvmuxer::VideoTrack*>(
+          segment->GetTrackByNumber(video_track_id));
+  video_track->SetStereoMode(stereo_fmt);
+  video_track->set_codec_id(fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
+  if (glob->debug) {
+    video_track->set_uid(kDebugTrackUid);
+  }
+  glob->writer = writer;
+  glob->segment = segment;
+}
+
+void write_webm_block(struct EbmlGlobal *glob,
+                      const vpx_codec_enc_cfg_t *cfg,
+                      const vpx_codec_cx_pkt_t *pkt) {
+  mkvmuxer::Segment *const segment =
+      reinterpret_cast<mkvmuxer::Segment*>(glob->segment);
+  int64_t pts_ns = pkt->data.frame.pts * 1000000000ll *
+                   cfg->g_timebase.num / cfg->g_timebase.den;
+  if (pts_ns <= glob->last_pts_ns)
+    pts_ns = glob->last_pts_ns + 1000000;
+  glob->last_pts_ns = pts_ns;
+
+  segment->AddFrame(static_cast<uint8_t*>(pkt->data.frame.buf),
+                    pkt->data.frame.sz,
+                    kVideoTrackNumber,
+                    pts_ns,
+                    pkt->data.frame.flags & VPX_FRAME_IS_KEY);
+}
+
+void write_webm_file_footer(struct EbmlGlobal *glob) {
+  mkvmuxer::MkvWriter *const writer =
+      reinterpret_cast<mkvmuxer::MkvWriter*>(glob->writer);
+  mkvmuxer::Segment *const segment =
+      reinterpret_cast<mkvmuxer::Segment*>(glob->segment);
+  segment->Finalize();
+  delete segment;
+  delete writer;
+  glob->writer = NULL;
+  glob->segment = NULL;
+}
diff --git a/webmenc.h b/webmenc.h
index 362aa89..0ac606b 100644
--- a/webmenc.h
+++ b/webmenc.h
@@ -13,13 +13,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#if defined(_MSC_VER)
-/* MSVS doesn't define off_t */
-typedef __int64 off_t;
-#else
-#include <stdint.h>
-#endif
-
 #include "tools_common.h"
 #include "vpx/vpx_encoder.h"
 
@@ -27,40 +20,13 @@
 extern "C" {
 #endif
 
-typedef off_t EbmlLoc;
-
-struct cue_entry {
-  unsigned int time;
-  uint64_t loc;
-};
-
+/* TODO(vigneshv): Rename this struct */
 struct EbmlGlobal {
   int debug;
-
   FILE *stream;
-  int64_t last_pts_ms;
-  vpx_rational_t framerate;
-
-  /* These pointers are to the start of an element */
-  off_t position_reference;
-  off_t seek_info_pos;
-  off_t segment_info_pos;
-  off_t track_pos;
-  off_t cue_pos;
-  off_t cluster_pos;
-
-  /* This pointer is to a specific element to be serialized */
-  off_t track_id_pos;
-
-  /* These pointers are to the size field of the element */
-  EbmlLoc startSegment;
-  EbmlLoc startCluster;
-
-  uint32_t cluster_timecode;
-  int cluster_open;
-
-  struct cue_entry *cue_list;
-  unsigned int cues;
+  int64_t last_pts_ns;
+  void *writer;
+  void *segment;
 };
 
 /* Stereo 3D packed frame format */
@@ -72,10 +38,6 @@
   STEREO_FORMAT_RIGHT_LEFT = 11
 } stereo_format_t;
 
-void write_webm_seek_element(struct EbmlGlobal *ebml,
-                             unsigned int id,
-                             off_t pos);
-
 void write_webm_file_header(struct EbmlGlobal *glob,
                             const vpx_codec_enc_cfg_t *cfg,
                             const struct vpx_rational *fps,
@@ -86,7 +48,7 @@
                       const vpx_codec_enc_cfg_t *cfg,
                       const vpx_codec_cx_pkt_t *pkt);
 
-void write_webm_file_footer(struct EbmlGlobal *glob, int hash);
+void write_webm_file_footer(struct EbmlGlobal *glob);
 
 #ifdef __cplusplus
 }  // extern "C"