shithub: libvpx

Download patch

ref: a419f0f232be2ada510304f96eb3270b31669e25
parent: ad479a9b3d510617f1400d2b168bd1594d422d67
parent: b9180fc0499a7c1480a47e17328e7a35bb788086
author: John Koleszar <jkoleszar@google.com>
date: Wed May 23 09:47:48 EDT 2012

Merge changes I38e93fe2,I6d6a0fb6,I51155833,If4c3e5d4,Ia2f40ef2

* changes:
  Add initial keyframe tests
  Move all tests to test/ directory
  Enable unit tests by default
  Build unit tests monolithically
  configure: initial support for CXX, CXXFLAGS variables

diff: cannot open b/test//null: file does not exist: 'b/test//null'
--- a/build/make/Makefile
+++ b/build/make/Makefile
@@ -66,6 +66,7 @@
 BUILD_ROOT?=.
 VPATH=$(SRC_PATH_BARE)
 CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
+CXXFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
 ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT)/ -I$(SRC_PATH)/
 DIST_DIR?=dist
 HOSTCC?=gcc
@@ -111,11 +112,11 @@
 $(BUILD_PFX)%.cc.d: %.cc
 	$(if $(quiet),@echo "    [DEP] $@")
 	$(qexec)mkdir -p $(dir $@)
-	$(qexec)g++ $(INTERNAL_CFLAGS) $(CFLAGS) -M $< | $(fmt_deps) > $@
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
 
 $(BUILD_PFX)%.cc.o: %.cc
 	$(if $(quiet),@echo "    [CXX] $@")
-	$(qexec)g++ $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
 
 $(BUILD_PFX)%.asm.d: %.asm
 	$(if $(quiet),@echo "    [DEP] $@")
@@ -213,7 +214,7 @@
 $(1): $(filter-out -%,$(2))
 $(1):
 	$(if $(quiet),@echo    "    [LD] $$@")
-	$(qexec)g++ $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
+	$(qexec)$$(CXX) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
 endef
 # make-3.80 has a bug with expanding large input strings to the eval function,
 # which was triggered in some cases by the following component of
--- a/build/make/configure.sh
+++ b/build/make/configure.sh
@@ -166,9 +166,20 @@
 
 add_cflags() {
     CFLAGS="${CFLAGS} $@"
+    CXXFLAGS="${CXXFLAGS} $@"
 }
 
 
+add_cflags_only() {
+    CFLAGS="${CFLAGS} $@"
+}
+
+
+add_cxxflags_only() {
+    CXXFLAGS="${CXXFLAGS} $@"
+}
+
+
 add_ldflags() {
     LDFLAGS="${LDFLAGS} $@"
 }
@@ -277,6 +288,13 @@
     check_cmd ${CC} ${CFLAGS} "$@" -c -o ${TMP_O} ${TMP_C}
 }
 
+check_cxx() {
+    log check_cxx "$@"
+    cat >${TMP_C}
+    log_file ${TMP_C}
+    check_cmd ${CXX} ${CXXFLAGS} "$@" -c -o ${TMP_O} ${TMP_C}
+}
+
 check_cpp() {
     log check_cpp "$@"
     cat > ${TMP_C}
@@ -310,8 +328,25 @@
 EOF
 }
 
+check_cxxflags() {
+    log check_cxxflags "$@"
+
+    # Catch CFLAGS that trigger CXX warnings
+    case "$CXX" in
+      *g++*) check_cxx -Werror "$@" <<EOF
+int x;
+EOF
+      ;;
+      *) check_cxx "$@" <<EOF
+int x;
+EOF
+      ;;
+    esac
+}
+
 check_add_cflags() {
-    check_cflags "$@" && add_cflags "$@"
+    check_cxxflags "$@" && add_cxxflags_only "$@"
+    check_cflags "$@" && add_cflags_only "$@"
 }
 
 check_add_asflags() {
@@ -367,7 +402,9 @@
 
 write_common_target_config_mk() {
     local CC=${CC}
+    local CXX=${CXX}
     enabled ccache && CC="ccache ${CC}"
+    enabled ccache && CXX="ccache ${CXX}"
     print_webm_license $1 "##" ""
 
     cat >> $1 << EOF
@@ -379,6 +416,7 @@
 ASM_CONVERSION=${asm_conversion_cmd:-${source_path}/build/make/ads2gas.pl}
 
 CC=${CC}
+CXX=${CXX}
 AR=${AR}
 LD=${LD}
 AS=${AS}
@@ -386,6 +424,7 @@
 NM=${NM}
 
 CFLAGS  = ${CFLAGS}
+CXXFLAGS  = ${CXXFLAGS}
 ARFLAGS = -rus\$(if \$(quiet),c,v)
 LDFLAGS = ${LDFLAGS}
 ASFLAGS = ${ASFLAGS}
@@ -538,6 +577,7 @@
 
 setup_gnu_toolchain() {
         CC=${CC:-${CROSS}gcc}
+        CXX=${CXX:-${CROSS}g++}
         AR=${AR:-${CROSS}ar}
         LD=${LD:-${CROSS}${link_with_cc:-ld}}
         AS=${AS:-${CROSS}as}
@@ -792,6 +832,7 @@
                                -name "arm-linux-androideabi-gcc*" -print -quit`
             TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/arm-linux-androideabi-
             CC=${TOOLCHAIN_PATH}gcc
+            CXX=${TOOLCHAIN_PATH}g++
             AR=${TOOLCHAIN_PATH}ar
             LD=${TOOLCHAIN_PATH}gcc
             AS=${TOOLCHAIN_PATH}as
@@ -827,6 +868,7 @@
                 SDK_PATH=${sdk_path}
             fi
             TOOLCHAIN_PATH=${SDK_PATH}/usr/bin
+            CXX=${TOOLCHAIN_PATH}/g++
             CC=${TOOLCHAIN_PATH}/gcc
             AR=${TOOLCHAIN_PATH}/ar
             LD=${TOOLCHAIN_PATH}/arm-apple-darwin10-llvm-gcc-4.2
@@ -938,6 +980,7 @@
                 ;;
             solaris*)
                 CC=${CC:-${CROSS}gcc}
+                CXX=${CXX:-${CROSS}g++}
                 LD=${LD:-${CROSS}gcc}
                 CROSS=${CROSS:-g}
                 ;;
--- a/configure
+++ b/configure
@@ -586,6 +586,16 @@
     if enabled postproc_visualizer; then
         enabled postproc || die "postproc_visualizer requires postproc to be enabled"
     fi
+
+    # Enable unit tests if we have a working C++ compiler
+    case "$tgt_cc" in
+        vs*)
+            soft_enable unit_tests;;
+        *)
+            check_cxx "$@" <<EOF && soft_enable unit_tests
+int z;
+EOF
+    esac
 }
 
 
--- a/libs.mk
+++ b/libs.mk
@@ -329,7 +329,6 @@
 #
 # Rule to generate runtime cpu detection files
 #
-$(OBJS-yes:.o=.d): $(BUILD_PFX)vpx_rtcd.h
 $(BUILD_PFX)vpx_rtcd.h: $(SRC_PATH_BARE)/$(sort $(filter %rtcd_defs.sh,$(CODEC_SRCS)))
 	@echo "    [CREATE] $@"
 	$(qexec)$(SRC_PATH_BARE)/build/make/rtcd.sh --arch=$(TGT_ISA) \
@@ -346,14 +345,15 @@
 ##
 ## libvpx test directives
 ##
-
 ifeq ($(CONFIG_UNIT_TESTS),yes)
+
+include $(SRC_PATH_BARE)/test/test.mk
+LIBVPX_TEST_SRCS=$(addprefix test/,$(call enabled,LIBVPX_TEST_SRCS))
+LIBVPX_TEST_BINS=./test_libvpx
+
 ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
 ifeq ($(CONFIG_MSVS),yes)
 
-LIBVPX_TEST_SRCS=$(filter %_test.cc,$(call enabled,CODEC_SRCS))
-LIBVPX_TEST_BINS=$(sort $(LIBVPX_TEST_SRCS:.cc.o=))
-
 gtest.vcproj: $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc
 	@echo "    [CREATE] $@"
 	$(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh \
@@ -397,23 +397,26 @@
 include $(SRC_PATH_BARE)/third_party/googletest/gtest.mk
 GTEST_SRCS := $(addprefix third_party/googletest/src/,$(call enabled,GTEST_SRCS))
 GTEST_OBJS=$(call objs,$(GTEST_SRCS))
-$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
-$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
+$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
+$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
 OBJS-$(BUILD_LIBVPX) += $(GTEST_OBJS)
 LIBS-$(BUILD_LIBVPX) += $(BUILD_PFX)libgtest.a $(BUILD_PFX)libgtest_g.a
 $(BUILD_PFX)libgtest_g.a: $(GTEST_OBJS)
 
-LIBVPX_TEST_SRCS=$(filter %_test.cc,$(call enabled,CODEC_SRCS))
-LIBVPX_TEST_OBJS=$(call objs,$(LIBVPX_TEST_SRCS))
-$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
-$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
-LIBVPX_TEST_BINS=$(sort $(LIBVPX_TEST_OBJS:.cc.o=))
+LIBVPX_TEST_OBJS=$(sort $(call objs,$(LIBVPX_TEST_SRCS)))
+$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src
+$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
 OBJS-$(BUILD_LIBVPX) += $(LIBVPX_TEST_OBJS)
 
+# Install test sources only if codec source is included
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(patsubst $(SRC_PATH_BARE)/%,%,\
+    $(shell find $(SRC_PATH_BARE)/third_party/googletest -type f))
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(LIBVPX_TEST_SRCS)
+
 $(foreach bin,$(LIBVPX_TEST_BINS),\
     $(if $(BUILD_LIBVPX),$(eval $(bin): libvpx.a libgtest.a ))\
     $(if $(BUILD_LIBVPX),$(eval $(call linkerxx_template,$(bin),\
-        $(bin).cc.o \
+        $(LIBVPX_TEST_OBJS) \
         -L. -lvpx -lgtest -lpthread -lm)\
         )))\
     $(if $(LIPO_LIBS),$(eval $(call lipo_bin_template,$(bin))))\
@@ -436,3 +439,6 @@
 	@echo "PREDEFINED = VPX_CODEC_DISABLE_COMPAT" >> $@
 	@echo "INCLUDE_PATH += ." >> $@;
 	@echo "ENABLED_SECTIONS += $(sort $(CODEC_DOC_SECTIONS))" >> $@
+
+## Generate vpx_rtcd.h for all objects
+$(OBJS-yes:.o=.d): $(BUILD_PFX)vpx_rtcd.h
--- /dev/null
+++ b/test/boolcoder_test.cc
@@ -1,0 +1,123 @@
+/*
+ *  Copyright (c) 2012 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.
+ */
+
+extern "C"
+{
+#include "vp8/encoder/boolhuff.h"
+#include "vp8/decoder/dboolhuff.h"
+}
+
+#include <math.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+typedef unsigned char uint8_t;
+
+namespace
+{
+const int num_tests = 10;
+
+class ACMRandom
+{
+public:
+    ACMRandom(int seed) { Reset(seed);}
+
+    void Reset(int seed) { srand(seed); }
+
+    uint8_t Rand8(void) { return (rand() >> 8) & 0xff; }
+
+    int PseudoUniform(int range) { return (rand() >> 8) % range; }
+
+    int operator()(int n) { return PseudoUniform(n); }
+
+    static int DeterministicSeed(void) { return 0xbaba; }
+};
+}
+
+TEST(VP8, TestBitIO)
+{
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    for (int n = 0; n < num_tests; ++n)
+    {
+        for (int method = 0; method <= 7; ++method)
+        {   // we generate various proba
+            const int bits_to_test = 1000;
+
+            uint8_t probas[bits_to_test];
+
+            for (int i = 0; i < bits_to_test; ++i)
+            {
+                const int parity = i & 1;
+                probas[i] =
+                        (method == 0) ? 0 :
+                        (method == 1) ? 255 :
+                        (method == 2) ? 128 :
+                        (method == 3) ? rnd.Rand8() :
+                        (method == 4) ? (parity ? 0 : 255) :
+                        // alternate between low and high proba:
+                        (method == 5) ? (parity ? rnd(128) : 255 - rnd(128)) :
+                        (method == 6) ?
+                                (parity ? rnd(64) : 255 - rnd(64)) :
+                                (parity ? rnd(32) : 255 - rnd(32));
+            }
+            for (int bit_method = 0; bit_method <= 3; ++bit_method)
+            {
+                const int random_seed = 6432;
+                const int buffer_size = 10000;
+                ACMRandom bit_rnd(random_seed);
+                BOOL_CODER bw;
+                uint8_t bw_buffer[buffer_size];
+                vp8_start_encode(&bw, bw_buffer, bw_buffer + buffer_size);
+
+                int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
+                for (int i = 0; i < bits_to_test; ++i)
+                {
+                    if (bit_method == 2)
+                    {
+                        bit = (i & 1);
+                    }
+                    else if (bit_method == 3)
+                    {
+                        bit = bit_rnd(2);
+                    }
+                    vp8_encode_bool(&bw, bit, (int) probas[i]);
+                }
+
+                vp8_stop_encode(&bw);
+
+                BOOL_DECODER br;
+                vp8dx_start_decode(&br, bw_buffer, buffer_size);
+                bit_rnd.Reset(random_seed);
+                for (int i = 0; i < bits_to_test; ++i)
+                {
+                    if (bit_method == 2)
+                    {
+                        bit = (i & 1);
+                    }
+                    else if (bit_method == 3)
+                    {
+                        bit = bit_rnd(2);
+                    }
+                    GTEST_ASSERT_EQ(vp8dx_decode_bool(&br, probas[i]), bit)
+                      << "pos: "
+                      << i << " / " << bits_to_test << " bit_method: "
+                      << bit_method << " method: " << method;
+                }
+
+            }
+        }
+    }
+}
--- /dev/null
+++ b/test/encode_test_driver.cc
@@ -1,0 +1,137 @@
+/*
+ *  Copyright (c) 2012 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 "test/encode_test_driver.h"
+#include "test/video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace libvpx_test {
+
+void Encoder::EncodeFrame(VideoSource *video, unsigned long flags) {
+  if (video->img())
+    EncodeFrameInternal(*video, flags);
+  else
+    Flush();
+
+  // Handle twopass stats
+  CxDataIterator iter = GetCxData();
+
+  while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+    if (pkt->kind != VPX_CODEC_STATS_PKT)
+      continue;
+
+    stats_->Append(*pkt);
+  }
+}
+
+void Encoder::EncodeFrameInternal(const VideoSource &video,
+                                  unsigned long flags) {
+  vpx_codec_err_t res;
+  const vpx_image_t *img = video.img();
+
+  // Handle first frame initialization
+  if (!encoder_.priv) {
+    cfg_.g_w = img->d_w;
+    cfg_.g_h = img->d_h;
+    cfg_.g_timebase = video.timebase();
+    cfg_.rc_twopass_stats_in = stats_->buf();
+    res = vpx_codec_enc_init(&encoder_, &vpx_codec_vp8_cx_algo, &cfg_, 0);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  // Handle frame resizing
+  if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) {
+    cfg_.g_w = img->d_w;
+    cfg_.g_h = img->d_h;
+    res = vpx_codec_enc_config_set(&encoder_, &cfg_);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  // Encode the frame
+  res = vpx_codec_encode(&encoder_,
+                         video.img(), video.pts(), video.duration(),
+                         flags, deadline_);
+  ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+}
+
+void Encoder::Flush() {
+  const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0,
+                                               deadline_);
+  ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+}
+
+void EncoderTest::SetMode(TestMode mode) {
+  switch (mode) {
+    case kRealTime:
+      deadline_ = VPX_DL_REALTIME;
+      break;
+
+    case kOnePassGood:
+    case kTwoPassGood:
+      deadline_ = VPX_DL_GOOD_QUALITY;
+      break;
+
+    case kOnePassBest:
+    case kTwoPassBest:
+      deadline_ = VPX_DL_BEST_QUALITY;
+      break;
+
+    default:
+      ASSERT_TRUE(false) << "Unexpected mode " << mode;
+  }
+
+  if (mode == kTwoPassGood || mode == kTwoPassBest)
+    passes_ = 2;
+  else
+    passes_ = 1;
+}
+
+void EncoderTest::RunLoop(VideoSource *video) {
+  for (unsigned int pass = 0; pass < passes_; pass++) {
+    if (passes_ == 1)
+      cfg_.g_pass = VPX_RC_ONE_PASS;
+    else if (pass == 0)
+      cfg_.g_pass = VPX_RC_FIRST_PASS;
+    else
+      cfg_.g_pass = VPX_RC_LAST_PASS;
+
+    BeginPassHook(pass);
+    Encoder encoder(cfg_, deadline_, &stats_);
+
+    bool again;
+
+    for (video->Begin(), again = true; again; video->Next()) {
+      again = video->img() != NULL;
+
+      PreEncodeFrameHook(video);
+      encoder.EncodeFrame(video, flags_);
+
+      CxDataIterator iter = encoder.GetCxData();
+
+      while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+        again = true;
+
+        if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+          continue;
+
+        FramePktHook(pkt);
+      }
+
+      if (!Continue())
+        break;
+    }
+
+    EndPassHook();
+
+    if (!Continue())
+      break;
+  }
+}
+
+}  // namespace libvpx_test
--- /dev/null
+++ b/test/encode_test_driver.h
@@ -1,0 +1,178 @@
+/*
+ *  Copyright (c) 2012 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 TEST_ENCODE_TEST_DRIVER_H_
+#define TEST_ENCODE_TEST_DRIVER_H_
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+
+namespace libvpx_test {
+
+class VideoSource;
+
+enum TestMode {
+  kRealTime,
+  kOnePassGood,
+  kOnePassBest,
+  kTwoPassGood,
+  kTwoPassBest
+};
+#define ALL_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
+                                         ::libvpx_test::kOnePassGood, \
+                                         ::libvpx_test::kOnePassBest, \
+                                         ::libvpx_test::kTwoPassGood, \
+                                         ::libvpx_test::kTwoPassBest)
+
+
+// Provides an object to handle the libvpx get_cx_data() iteration pattern
+class CxDataIterator {
+ public:
+  explicit CxDataIterator(vpx_codec_ctx_t *encoder)
+    : encoder_(encoder), iter_(NULL) {}
+
+  const vpx_codec_cx_pkt_t *Next() {
+    return vpx_codec_get_cx_data(encoder_, &iter_);
+  }
+
+ private:
+  vpx_codec_ctx_t  *encoder_;
+  vpx_codec_iter_t  iter_;
+};
+
+
+// Implements an in-memory store for libvpx twopass statistics
+class TwopassStatsStore {
+ public:
+  void Append(const vpx_codec_cx_pkt_t &pkt) {
+    buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
+                   pkt.data.twopass_stats.sz);
+  }
+
+  vpx_fixed_buf_t buf() {
+    const vpx_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
+    return buf;
+  }
+
+ protected:
+  std::string  buffer_;
+};
+
+
+// Provides a simplified interface to manage one video encoding pass, given
+// a configuration and video source.
+//
+// TODO(jkoleszar): The exact services it provides and the appropriate
+// level of abstraction will be fleshed out as more tests are written.
+class Encoder {
+ public:
+  Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+          TwopassStatsStore *stats)
+    : cfg_(cfg), deadline_(deadline), stats_(stats) {
+    memset(&encoder_, 0, sizeof(encoder_));
+  }
+
+  ~Encoder() {
+    vpx_codec_destroy(&encoder_);
+  }
+
+  CxDataIterator GetCxData() {
+    return CxDataIterator(&encoder_);
+  }
+
+  // This is a thin wrapper around vpx_codec_encode(), so refer to
+  // vpx_encoder.h for its semantics.
+  void EncodeFrame(VideoSource *video, unsigned long flags);
+
+  // Convenience wrapper for EncodeFrame()
+  void EncodeFrame(VideoSource *video) {
+    EncodeFrame(video, 0);
+  }
+
+  void set_deadline(unsigned long deadline) {
+    deadline_ = deadline;
+  }
+
+ protected:
+  const char *EncoderError() {
+    const char *detail = vpx_codec_error_detail(&encoder_);
+    return detail ? detail : vpx_codec_error(&encoder_);
+  }
+
+  // Encode an image
+  void EncodeFrameInternal(const VideoSource &video, unsigned long flags);
+
+  // Flush the encoder on EOS
+  void Flush();
+
+  vpx_codec_ctx_t      encoder_;
+  vpx_codec_enc_cfg_t  cfg_;
+  unsigned long        deadline_;
+  TwopassStatsStore   *stats_;
+};
+
+
+// Common test functionality for all Encoder tests.
+//
+// This class is a mixin which provides the main loop common to all
+// encoder tests. It provides hooks which can be overridden by subclasses
+// to implement each test's specific behavior, while centralizing the bulk
+// of the boilerplate. Note that it doesn't inherit the gtest testing
+// classes directly, so that tests can be parameterized differently.
+class EncoderTest {
+ protected:
+  EncoderTest() : abort_(false), flags_(0) {}
+
+  virtual ~EncoderTest() {}
+
+  // Initialize the cfg_ member with the default configuration.
+  void InitializeConfig() {
+    const vpx_codec_err_t res = vpx_codec_enc_config_default(
+                                    &vpx_codec_vp8_cx_algo, &cfg_, 0);
+    ASSERT_EQ(VPX_CODEC_OK, res);
+  }
+
+  // Map the TestMode enum to the deadline_ and passes_ variables.
+  void SetMode(TestMode mode);
+
+  // Main loop.
+  virtual void RunLoop(VideoSource *video);
+
+  // Hook to be called at the beginning of a pass.
+  virtual void BeginPassHook(unsigned int pass) {}
+
+  // Hook to be called at the end of a pass.
+  virtual void EndPassHook() {}
+
+  // Hook to be called before encoding a frame.
+  virtual void PreEncodeFrameHook(VideoSource *video) {}
+
+  // Hook to be called on every compressed data packet.
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {}
+
+  // Hook to determine whether the encode loop should continue.
+  virtual bool Continue() const { return !abort_; }
+
+  bool                 abort_;
+  vpx_codec_enc_cfg_t  cfg_;
+  unsigned int         passes_;
+  unsigned long        deadline_;
+  TwopassStatsStore    stats_;
+  unsigned long        flags_;
+};
+
+}  // namespace libvpx_test
+
+// Macros to be used with ::testing::Combine
+#define PARAMS(...) ::testing::TestWithParam< std::tr1::tuple< __VA_ARGS__ > >
+#define GET_PARAM(k) std::tr1::get< k >(GetParam())
+
+#endif  // TEST_ENCODE_TEST_DRIVER_H_
--- /dev/null
+++ b/test/idctllm_test.cc
@@ -1,0 +1,125 @@
+/*
+ *  Copyright (c) 2010 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.
+ */
+
+
+extern "C" {
+#include "vpx_config.h"
+#include "vpx_rtcd.h"
+}
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+typedef void (*idct_fn_t)(short *input, unsigned char *pred_ptr,
+                          int pred_stride, unsigned char *dst_ptr,
+                          int dst_stride);
+namespace {
+class IDCTTest : public ::testing::TestWithParam<idct_fn_t>
+{
+  protected:
+    virtual void SetUp()
+    {
+        int i;
+
+        UUT = GetParam();
+        memset(input, 0, sizeof(input));
+        /* Set up guard blocks */
+        for(i=0; i<256; i++)
+            output[i] = ((i&0xF)<4&&(i<64))?0:-1;
+    }
+
+    idct_fn_t UUT;
+    short input[16];
+    unsigned char output[256];
+    unsigned char predict[256];
+};
+
+TEST_P(IDCTTest, TestGuardBlocks)
+{
+    int i;
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(0, output[i]) << i;
+        else
+            EXPECT_EQ(255, output[i]);
+}
+
+TEST_P(IDCTTest, TestAllZeros)
+{
+    int i;
+
+    UUT(input, output, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(0, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestAllOnes)
+{
+    int i;
+
+    input[0] = 4;
+    UUT(input, output, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(1, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestAddOne)
+{
+    int i;
+
+    for(i=0; i<256; i++)
+        predict[i] = i;
+
+    input[0] = 4;
+    UUT(input, predict, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) < 4 && i<64)
+            EXPECT_EQ(i+1, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestWithData)
+{
+    int i;
+
+    for(i=0; i<16; i++)
+        input[i] = i;
+
+    UUT(input, output, 16, output, 16);
+
+    for(i=0; i<256; i++)
+        if((i&0xF) > 3 || i>63)
+            EXPECT_EQ(255, output[i]) << "i==" << i;
+        else if(i == 0)
+            EXPECT_EQ(11, output[i]) << "i==" << i;
+        else if(i == 34)
+            EXPECT_EQ(1, output[i]) << "i==" << i;
+        else if(i == 2 || i == 17 || i == 32)
+            EXPECT_EQ(3, output[i]) << "i==" << i;
+        else
+            EXPECT_EQ(0, output[i]) << "i==" << i;
+}
+
+INSTANTIATE_TEST_CASE_P(C, IDCTTest,
+                        ::testing::Values(vp8_short_idct4x4llm_c));
+#if HAVE_MMX
+INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
+                        ::testing::Values(vp8_short_idct4x4llm_mmx));
+#endif
+}
--- /dev/null
+++ b/test/keyframe_test.cc
@@ -1,0 +1,103 @@
+/*
+ *  Copyright (c) 2012 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 <climits>
+#include <vector>
+#include "test/encode_test_driver.h"
+#include "test/video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace {
+
+class KeyframeTest : public ::libvpx_test::EncoderTest,
+  public ::testing::TestWithParam<enum libvpx_test::TestMode> {
+ protected:
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GetParam());
+    kf_count_ = 0;
+    kf_count_max_ = INT_MAX;
+    kf_do_force_kf_ = false;
+  }
+
+  virtual bool Continue() {
+    return !HasFatalFailure() && !abort_;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video) {
+    if (kf_do_force_kf_)
+      flags_ = (video->frame() % 3) ? 0 : VPX_EFLAG_FORCE_KF;
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+      kf_pts_list_.push_back(pkt->data.frame.pts);
+      kf_count_++;
+      abort_ |= kf_count_ > kf_count_max_;
+    }
+  }
+
+  bool kf_do_force_kf_;
+  int kf_count_;
+  int kf_count_max_;
+  std::vector< vpx_codec_pts_t > kf_pts_list_;
+};
+
+TEST_P(KeyframeTest, TestRandomVideoSource) {
+  // Validate that encoding the RandomVideoSource produces multiple keyframes.
+  // This validates the results of the TestDisableKeyframes test.
+  kf_count_max_ = 2;  // early exit successful tests.
+
+  ::libvpx_test::RandomVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  EXPECT_GT(kf_count_, 1);
+}
+
+TEST_P(KeyframeTest, TestDisableKeyframes) {
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  kf_count_max_ = 1;  // early exit failed tests.
+
+  ::libvpx_test::RandomVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  EXPECT_EQ(1, kf_count_);
+}
+
+TEST_P(KeyframeTest, TestForceKeyframe) {
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  kf_do_force_kf_ = true;
+
+  ::libvpx_test::DummyVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // verify that every third frame is a keyframe.
+  for (std::vector<vpx_codec_pts_t>::iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end();
+       ++iter) {
+    ASSERT_EQ(0, *iter % 3) << "Unexpected keyframe at frame " << *iter;
+  }
+}
+
+TEST_P(KeyframeTest, TestKeyframeMaxDistance) {
+  cfg_.kf_max_dist = 25;
+
+  ::libvpx_test::DummyVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // verify that keyframe interval matches kf_max_dist
+  for (std::vector<vpx_codec_pts_t>::iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end();
+       iter++) {
+    ASSERT_EQ(0, *iter % 25) << "Unexpected keyframe at frame " << *iter;
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(AllModes, KeyframeTest, ALL_TEST_MODES);
+}  // namespace
--- /dev/null
+++ b/test/test.mk
@@ -1,0 +1,8 @@
+LIBVPX_TEST_SRCS-yes += test.mk
+LIBVPX_TEST_SRCS-yes += boolcoder_test.cc
+LIBVPX_TEST_SRCS-yes += encode_test_driver.cc
+LIBVPX_TEST_SRCS-yes += encode_test_driver.h
+LIBVPX_TEST_SRCS-yes += idctllm_test.cc
+LIBVPX_TEST_SRCS-yes += keyframe_test.cc
+LIBVPX_TEST_SRCS-yes += test_libvpx.cc
+LIBVPX_TEST_SRCS-yes += video_source.h
--- /dev/null
+++ b/test/test_libvpx.cc
@@ -1,0 +1,14 @@
+/*
+ *  Copyright (c) 2012 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 "third_party/googletest/src/include/gtest/gtest.h"
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
--- /dev/null
+++ b/test/video_source.h
@@ -1,0 +1,109 @@
+/*
+ *  Copyright (c) 2012 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 TEST_VIDEO_SOURCE_H_
+#define TEST_VIDEO_SOURCE_H_
+#include "vpx/vpx_encoder.h"
+
+namespace libvpx_test {
+
+// Abstract base class for test video sources, which provide a stream of
+// vpx_image_t images with associated timestamps and duration.
+class VideoSource {
+ public:
+  virtual ~VideoSource() {}
+
+  // Prepare the stream for reading, rewind/open as necessary.
+  virtual void Begin() = 0;
+
+  // Advance the cursor to the next frame
+  virtual void Next() = 0;
+
+  // Get the current video frame, or NULL on End-Of-Stream.
+  virtual vpx_image_t *img() const = 0;
+
+  // Get the presentation timestamp of the current frame.
+  virtual vpx_codec_pts_t pts() const = 0;
+
+  // Get the current frame's duration
+  virtual unsigned long duration() const = 0;
+
+  // Get the timebase for the stream
+  virtual vpx_rational_t timebase() const = 0;
+
+  // Get the current frame counter, starting at 0.
+  virtual unsigned int frame() const = 0;
+};
+
+
+class DummyVideoSource : public VideoSource {
+ public:
+  DummyVideoSource()
+    : img_(NULL), limit_(100) { SetSize(80, 64); }
+
+  virtual ~DummyVideoSource() { vpx_img_free(img_); }
+
+  virtual void Begin() {
+    frame_ = 0;
+    FillFrame();
+  }
+
+  virtual void Next() {
+    ++frame_;
+    FillFrame();
+  }
+
+  virtual vpx_image_t *img() const {
+    return (frame_ < limit_) ? img_ : NULL;
+  }
+
+  // Models a stream where Timebase = 1/FPS, so pts == frame.
+  virtual vpx_codec_pts_t pts() const { return frame_; }
+
+  virtual unsigned long duration() const { return 1; }
+
+  virtual vpx_rational_t timebase() const {
+    const vpx_rational_t t = {1, 30};
+    return t;
+  }
+
+  virtual unsigned int frame() const { return frame_; }
+
+  void SetSize(unsigned int width, unsigned int height) {
+    vpx_img_free(img_);
+    raw_sz_ = ((width + 31)&~31) * height * 3 / 2;
+    img_ = vpx_img_alloc(NULL, VPX_IMG_FMT_VPXI420, width, height, 32);
+  }
+
+ protected:
+  virtual void FillFrame() { memset(img_->img_data, 0, raw_sz_); }
+
+  vpx_image_t *img_;
+  size_t       raw_sz_;
+  unsigned int limit_;
+  unsigned int frame_;
+};
+
+
+class RandomVideoSource : public DummyVideoSource {
+ protected:
+  // 15 frames of noise, followed by 15 static frames. Reset to 0 rather
+  // than holding previous frames to encourage keyframes to be thrown.
+  virtual void FillFrame() {
+    if (frame_ % 30 < 15)
+      for (size_t i = 0; i < raw_sz_; ++i)
+        img_->img_data[i] = rand();
+    else
+      memset(img_->img_data, 0, raw_sz_);
+  }
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_VIDEO_SOURCE_H_
--- a/vp8/common/idctllm_test.cc
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- *  Copyright (c) 2010 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.
- */
-
-
- extern "C" {
-    void vp8_short_idct4x4llm_c(short *input, unsigned char *pred_ptr,
-                            int pred_stride, unsigned char *dst_ptr,
-                            int dst_stride);
-}
-
-#include "vpx_config.h"
-#include "idctllm_test.h"
-namespace
-{
-
-INSTANTIATE_TEST_CASE_P(C, IDCTTest,
-                        ::testing::Values(vp8_short_idct4x4llm_c));
-
-} // namespace
-
-int main(int argc, char **argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
--- a/vp8/common/idctllm_test.h
+++ /dev/null
@@ -1,113 +1,0 @@
-/*
- *  Copyright (c) 2010 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 "third_party/googletest/src/include/gtest/gtest.h"
-typedef void (*idct_fn_t)(short *input, unsigned char *pred_ptr,
-                            int pred_stride, unsigned char *dst_ptr,
-                            int dst_stride);
-namespace {
-class IDCTTest : public ::testing::TestWithParam<idct_fn_t>
-{
-  protected:
-    virtual void SetUp()
-    {
-        int i;
-
-        UUT = GetParam();
-        memset(input, 0, sizeof(input));
-        /* Set up guard blocks */
-        for(i=0; i<256; i++)
-            output[i] = ((i&0xF)<4&&(i<64))?0:-1;
-    }
-
-    idct_fn_t UUT;
-    short input[16];
-    unsigned char output[256];
-    unsigned char predict[256];
-};
-
-TEST_P(IDCTTest, TestGuardBlocks)
-{
-    int i;
-
-    for(i=0; i<256; i++)
-        if((i&0xF) < 4 && i<64)
-            EXPECT_EQ(0, output[i]) << i;
-        else
-            EXPECT_EQ(255, output[i]);
-}
-
-TEST_P(IDCTTest, TestAllZeros)
-{
-    int i;
-
-    UUT(input, output, 16, output, 16);
-
-    for(i=0; i<256; i++)
-        if((i&0xF) < 4 && i<64)
-            EXPECT_EQ(0, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(255, output[i]) << "i==" << i;
-}
-
-TEST_P(IDCTTest, TestAllOnes)
-{
-    int i;
-
-    input[0] = 4;
-    UUT(input, output, 16, output, 16);
-
-    for(i=0; i<256; i++)
-        if((i&0xF) < 4 && i<64)
-            EXPECT_EQ(1, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(255, output[i]) << "i==" << i;
-}
-
-TEST_P(IDCTTest, TestAddOne)
-{
-    int i;
-
-    for(i=0; i<256; i++)
-        predict[i] = i;
-
-    input[0] = 4;
-    UUT(input, predict, 16, output, 16);
-
-    for(i=0; i<256; i++)
-        if((i&0xF) < 4 && i<64)
-            EXPECT_EQ(i+1, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(255, output[i]) << "i==" << i;
-}
-
-TEST_P(IDCTTest, TestWithData)
-{
-    int i;
-
-    for(i=0; i<16; i++)
-        input[i] = i;
-
-    UUT(input, output, 16, output, 16);
-
-    for(i=0; i<256; i++)
-        if((i&0xF) > 3 || i>63)
-            EXPECT_EQ(255, output[i]) << "i==" << i;
-        else if(i == 0)
-            EXPECT_EQ(11, output[i]) << "i==" << i;
-        else if(i == 34)
-            EXPECT_EQ(1, output[i]) << "i==" << i;
-        else if(i == 2 || i == 17 || i == 32)
-            EXPECT_EQ(3, output[i]) << "i==" << i;
-        else
-            EXPECT_EQ(0, output[i]) << "i==" << i;
-}
-}
--- a/vp8/common/x86/idctllm_mmx_test.cc
+++ /dev/null
@@ -1,31 +1,0 @@
-/*
- *  Copyright (c) 2010 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.
- */
-
-
- extern "C" {
-    void vp8_short_idct4x4llm_mmx(short *input, unsigned char *pred_ptr,
-                            int pred_stride, unsigned char *dst_ptr,
-                            int dst_stride);
-}
-
-#include "vp8/common/idctllm_test.h"
-
-namespace
-{
-
-INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
-                        ::testing::Values(vp8_short_idct4x4llm_mmx));
-
-} // namespace
-
-int main(int argc, char **argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
--- a/vp8/encoder/boolcoder_test.cc
+++ /dev/null
@@ -1,129 +1,0 @@
-/*
- *  Copyright (c) 2012 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.
- */
-
-extern "C"
-{
-#include "vp8/encoder/boolhuff.h"
-#include "vp8/decoder/dboolhuff.h"
-}
-
-#include <math.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "third_party/googletest/src/include/gtest/gtest.h"
-
-typedef unsigned char uint8_t;
-
-namespace
-{
-const int num_tests = 10;
-
-class ACMRandom
-{
-public:
-    ACMRandom(int seed) { Reset(seed);}
-
-    void Reset(int seed) { srand(seed); }
-
-    uint8_t Rand8(void) { return (rand() >> 8) & 0xff; }
-
-    int PseudoUniform(int range) { return (rand() >> 8) % range; }
-
-    int operator()(int n) { return PseudoUniform(n); }
-
-    static int DeterministicSeed(void) { return 0xbaba; }
-};
-}
-
-TEST(VP8, TestBitIO)
-{
-    ACMRandom rnd(ACMRandom::DeterministicSeed());
-    for (int n = 0; n < num_tests; ++n)
-    {
-        for (int method = 0; method <= 7; ++method)
-        {   // we generate various proba
-            const int bits_to_test = 1000;
-
-            uint8_t probas[bits_to_test];
-
-            for (int i = 0; i < bits_to_test; ++i)
-            {
-                const int parity = i & 1;
-                probas[i] =
-                        (method == 0) ? 0 :
-                        (method == 1) ? 255 :
-                        (method == 2) ? 128 :
-                        (method == 3) ? rnd.Rand8() :
-                        (method == 4) ? (parity ? 0 : 255) :
-                        // alternate between low and high proba:
-                        (method == 5) ? (parity ? rnd(128) : 255 - rnd(128)) :
-                        (method == 6) ?
-                                (parity ? rnd(64) : 255 - rnd(64)) :
-                                (parity ? rnd(32) : 255 - rnd(32));
-            }
-            for (int bit_method = 0; bit_method <= 3; ++bit_method)
-            {
-                const int random_seed = 6432;
-                const int buffer_size = 10000;
-                ACMRandom bit_rnd(random_seed);
-                BOOL_CODER bw;
-                uint8_t bw_buffer[buffer_size];
-                vp8_start_encode(&bw, bw_buffer, bw_buffer + buffer_size);
-
-                int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
-                for (int i = 0; i < bits_to_test; ++i)
-                {
-                    if (bit_method == 2)
-                    {
-                        bit = (i & 1);
-                    }
-                    else if (bit_method == 3)
-                    {
-                        bit = bit_rnd(2);
-                    }
-                    vp8_encode_bool(&bw, bit, (int) probas[i]);
-                }
-
-                vp8_stop_encode(&bw);
-
-                BOOL_DECODER br;
-                vp8dx_start_decode(&br, bw_buffer, buffer_size);
-                bit_rnd.Reset(random_seed);
-                for (int i = 0; i < bits_to_test; ++i)
-                {
-                    if (bit_method == 2)
-                    {
-                        bit = (i & 1);
-                    }
-                    else if (bit_method == 3)
-                    {
-                        bit = bit_rnd(2);
-                    }
-                    GTEST_ASSERT_EQ(vp8dx_decode_bool(&br, probas[i]), bit)
-                      << "pos: "
-                      << i << " / " << bits_to_test << " bit_method: "
-                      << bit_method << " method: " << method;
-                }
-
-            }
-        }
-    }
-}
-
-int main(int argc, char **argv)
-{
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
--- a/vp8/vp8_common.mk
+++ b/vp8/vp8_common.mk
@@ -30,7 +30,6 @@
 VP8_COMMON_SRCS-yes += common/generic/systemdependent.c
 VP8_COMMON_SRCS-yes += common/idct_blk.c
 VP8_COMMON_SRCS-yes += common/idctllm.c
-VP8_COMMON_SRCS-yes += common/idctllm_test.cc
 VP8_COMMON_SRCS-yes += common/alloccommon.h
 VP8_COMMON_SRCS-yes += common/blockd.h
 VP8_COMMON_SRCS-yes += common/common.h
@@ -85,7 +84,6 @@
 VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/dequantize_mmx.asm
 VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idct_blk_mmx.c
 VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idctllm_mmx.asm
-VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/idctllm_mmx_test.cc
 VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/iwalsh_mmx.asm
 VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/loopfilter_mmx.asm
 VP8_COMMON_SRCS-$(HAVE_MMX) += common/x86/recon_mmx.asm
--- a/vp8/vp8cx.mk
+++ b/vp8/vp8cx.mk
@@ -88,8 +88,6 @@
 VP8_CX_SRCS-$(CONFIG_MULTI_RES_ENCODING) += encoder/mr_dissim.c
 VP8_CX_SRCS-$(CONFIG_MULTI_RES_ENCODING) += encoder/mr_dissim.h
 
-VP8_CX_SRCS-$(CONFIG_UNIT_TESTS) += encoder/boolcoder_test.cc
-
 ifeq ($(CONFIG_REALTIME_ONLY),yes)
 VP8_CX_SRCS_REMOVE-yes += encoder/firstpass.c
 VP8_CX_SRCS_REMOVE-yes += encoder/temporal_filter.c