summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Koleszar <jkoleszar@google.com>2012-05-23 13:47:48 -0700
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>2012-05-23 13:47:48 -0700
commita419f0f232be2ada510304f96eb3270b31669e25 (patch)
tree5cff4d125ddaa3a7d6a4aaa8768c5a0945ca5a68
parentad479a9b3d510617f1400d2b168bd1594d422d67 (diff)
parentb9180fc0499a7c1480a47e17328e7a35bb788086 (diff)
downloadlibvpx-a419f0f232be2ada510304f96eb3270b31669e25.tar
libvpx-a419f0f232be2ada510304f96eb3270b31669e25.tar.gz
libvpx-a419f0f232be2ada510304f96eb3270b31669e25.tar.bz2
libvpx-a419f0f232be2ada510304f96eb3270b31669e25.zip
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
-rw-r--r--build/make/Makefile7
-rwxr-xr-xbuild/make/configure.sh45
-rwxr-xr-xconfigure10
-rw-r--r--libs.mk32
-rw-r--r--test/boolcoder_test.cc (renamed from vp8/encoder/boolcoder_test.cc)6
-rw-r--r--test/encode_test_driver.cc137
-rw-r--r--test/encode_test_driver.h178
-rwxr-xr-xtest/idctllm_test.cc (renamed from vp8/common/idctllm_test.h)18
-rw-r--r--test/keyframe_test.cc103
-rw-r--r--test/test.mk8
-rw-r--r--[-rwxr-xr-x]test/test_libvpx.cc (renamed from vp8/common/x86/idctllm_mmx_test.cc)21
-rw-r--r--test/video_source.h109
-rwxr-xr-xvp8/common/idctllm_test.cc31
-rw-r--r--vp8/vp8_common.mk2
-rw-r--r--vp8/vp8cx.mk2
15 files changed, 629 insertions, 80 deletions
diff --git a/build/make/Makefile b/build/make/Makefile
index b6cf3208a..26ca0be70 100644
--- a/build/make/Makefile
+++ b/build/make/Makefile
@@ -66,6 +66,7 @@ endif
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)%.c.o: %.c
$(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 @@ define linkerxx_template
$(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
diff --git a/build/make/configure.sh b/build/make/configure.sh
index 068ccdc2a..f8d69aed1 100755
--- a/build/make/configure.sh
+++ b/build/make/configure.sh
@@ -166,6 +166,17 @@ is_in(){
add_cflags() {
CFLAGS="${CFLAGS} $@"
+ CXXFLAGS="${CXXFLAGS} $@"
+}
+
+
+add_cflags_only() {
+ CFLAGS="${CFLAGS} $@"
+}
+
+
+add_cxxflags_only() {
+ CXXFLAGS="${CXXFLAGS} $@"
}
@@ -277,6 +288,13 @@ check_cc() {
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 @@ int x;
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 @@ true
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 @@ TOOLCHAIN=${toolchain}
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 @@ STRIP=${STRIP}
NM=${NM}
CFLAGS = ${CFLAGS}
+CXXFLAGS = ${CXXFLAGS}
ARFLAGS = -rus\$(if \$(quiet),c,v)
LDFLAGS = ${LDFLAGS}
ASFLAGS = ${ASFLAGS}
@@ -538,6 +577,7 @@ post_process_cmdline() {
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 @@ process_common_toolchain() {
-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 @@ process_common_toolchain() {
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 @@ process_common_toolchain() {
;;
solaris*)
CC=${CC:-${CROSS}gcc}
+ CXX=${CXX:-${CROSS}g++}
LD=${LD:-${CROSS}gcc}
CROSS=${CROSS:-g}
;;
diff --git a/configure b/configure
index 2b1328dbd..eed6f970b 100755
--- a/configure
+++ b/configure
@@ -586,6 +586,16 @@ process_toolchain() {
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
}
diff --git a/libs.mk b/libs.mk
index f241d07ac..516e6d834 100644
--- a/libs.mk
+++ b/libs.mk
@@ -329,7 +329,6 @@ CLEAN-OBJS += $(BUILD_PFX)vpx_version.h
#
# 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 @@ CODEC_DOC_SRCS += vpx/vpx_codec.h \
##
## 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 @@ else
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 @@ libs.doxy: $(CODEC_DOC_SRCS)
@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
diff --git a/vp8/encoder/boolcoder_test.cc b/test/boolcoder_test.cc
index 9d9462690..00c2b7593 100644
--- a/vp8/encoder/boolcoder_test.cc
+++ b/test/boolcoder_test.cc
@@ -121,9 +121,3 @@ TEST(VP8, TestBitIO)
}
}
}
-
-int main(int argc, char **argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc
new file mode 100644
index 000000000..0a188facf
--- /dev/null
+++ b/test/encode_test_driver.cc
@@ -0,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
diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h
new file mode 100644
index 000000000..43faaaed7
--- /dev/null
+++ b/test/encode_test_driver.h
@@ -0,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_
diff --git a/vp8/common/idctllm_test.h b/test/idctllm_test.cc
index a6a694b18..dd42e2299 100755
--- a/vp8/common/idctllm_test.h
+++ b/test/idctllm_test.cc
@@ -9,10 +9,15 @@
*/
- #include "third_party/googletest/src/include/gtest/gtest.h"
+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);
+ int pred_stride, unsigned char *dst_ptr,
+ int dst_stride);
namespace {
class IDCTTest : public ::testing::TestWithParam<idct_fn_t>
{
@@ -110,4 +115,11 @@ TEST_P(IDCTTest, TestWithData)
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
}
diff --git a/test/keyframe_test.cc b/test/keyframe_test.cc
new file mode 100644
index 000000000..db18e5dab
--- /dev/null
+++ b/test/keyframe_test.cc
@@ -0,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
diff --git a/test/test.mk b/test/test.mk
new file mode 100644
index 000000000..d04ad170f
--- /dev/null
+++ b/test/test.mk
@@ -0,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
diff --git a/vp8/common/x86/idctllm_mmx_test.cc b/test/test_libvpx.cc
index 8c115335e..48bfc6c76 100755..100644
--- a/vp8/common/x86/idctllm_mmx_test.cc
+++ b/test/test_libvpx.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ * 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
@@ -7,24 +7,7 @@
* 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
-
+#include "third_party/googletest/src/include/gtest/gtest.h"
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/test/video_source.h b/test/video_source.h
new file mode 100644
index 000000000..86c6caa83
--- /dev/null
+++ b/test/video_source.h
@@ -0,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_
diff --git a/vp8/common/idctllm_test.cc b/vp8/common/idctllm_test.cc
deleted file mode 100755
index 0f6ebe7fe..000000000
--- a/vp8/common/idctllm_test.cc
+++ /dev/null
@@ -1,31 +0,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();
-}
diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk
index 3a7b146fc..1fbe5d43b 100644
--- a/vp8/vp8_common.mk
+++ b/vp8/vp8_common.mk
@@ -30,7 +30,6 @@ VP8_COMMON_SRCS-yes += common/findnearmv.c
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-$(CONFIG_POSTPROC) += common/postproc.c
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
diff --git a/vp8/vp8cx.mk b/vp8/vp8cx.mk
index 28deaf276..5976297bc 100644
--- a/vp8/vp8cx.mk
+++ b/vp8/vp8cx.mk
@@ -88,8 +88,6 @@ VP8_CX_SRCS-yes += encoder/temporal_filter.c
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