summaryrefslogtreecommitdiffstats
path: root/media/libvpx/libvpx/test
diff options
context:
space:
mode:
Diffstat (limited to 'media/libvpx/libvpx/test')
-rw-r--r--media/libvpx/libvpx/test/acm_random.h93
-rw-r--r--media/libvpx/libvpx/test/active_map_refresh_test.cc128
-rw-r--r--media/libvpx/libvpx/test/active_map_test.cc93
-rw-r--r--media/libvpx/libvpx/test/add_noise_test.cc149
-rw-r--r--media/libvpx/libvpx/test/alt_ref_aq_segment_test.cc157
-rw-r--r--media/libvpx/libvpx/test/altref_test.cc152
-rw-r--r--media/libvpx/libvpx/test/android/Android.mk67
-rw-r--r--media/libvpx/libvpx/test/android/README33
-rw-r--r--media/libvpx/libvpx/test/android/get_files.py118
-rw-r--r--media/libvpx/libvpx/test/android/scrape_gtest_log.py57
-rw-r--r--media/libvpx/libvpx/test/aq_segment_test.cc109
-rw-r--r--media/libvpx/libvpx/test/avg_test.cc756
-rw-r--r--media/libvpx/libvpx/test/bench.cc38
-rw-r--r--media/libvpx/libvpx/test/bench.h30
-rw-r--r--media/libvpx/libvpx/test/blockiness_test.cc222
-rw-r--r--media/libvpx/libvpx/test/borders_test.cc84
-rw-r--r--media/libvpx/libvpx/test/buffer.h382
-rw-r--r--media/libvpx/libvpx/test/byte_alignment_test.cc185
-rw-r--r--media/libvpx/libvpx/test/clear_system_state.h23
-rw-r--r--media/libvpx/libvpx/test/codec_factory.h268
-rw-r--r--media/libvpx/libvpx/test/comp_avg_pred_test.cc270
-rw-r--r--media/libvpx/libvpx/test/config_test.cc62
-rw-r--r--media/libvpx/libvpx/test/consistency_test.cc215
-rw-r--r--media/libvpx/libvpx/test/convolve_test.cc1488
-rw-r--r--media/libvpx/libvpx/test/cpu_speed_test.cc156
-rw-r--r--media/libvpx/libvpx/test/cq_test.cc131
-rwxr-xr-xmedia/libvpx/libvpx/test/cx_set_ref.sh60
-rw-r--r--media/libvpx/libvpx/test/dct16x16_test.cc1028
-rw-r--r--media/libvpx/libvpx/test/dct32x32_test.cc605
-rw-r--r--media/libvpx/libvpx/test/dct_partial_test.cc183
-rw-r--r--media/libvpx/libvpx/test/dct_test.cc790
-rw-r--r--media/libvpx/libvpx/test/decode_api_test.cc215
-rw-r--r--media/libvpx/libvpx/test/decode_corrupted.cc103
-rw-r--r--media/libvpx/libvpx/test/decode_perf_test.cc263
-rw-r--r--media/libvpx/libvpx/test/decode_svc_test.cc125
-rw-r--r--media/libvpx/libvpx/test/decode_test_driver.cc119
-rw-r--r--media/libvpx/libvpx/test/decode_test_driver.h162
-rwxr-xr-xmedia/libvpx/libvpx/test/decode_to_md5.sh73
-rwxr-xr-xmedia/libvpx/libvpx/test/decode_with_drops.sh79
-rw-r--r--media/libvpx/libvpx/test/encode_api_test.cc491
-rw-r--r--media/libvpx/libvpx/test/encode_perf_test.cc188
-rw-r--r--media/libvpx/libvpx/test/encode_test_driver.cc269
-rw-r--r--media/libvpx/libvpx/test/encode_test_driver.h302
-rw-r--r--media/libvpx/libvpx/test/error_resilience_test.cc582
-rwxr-xr-xmedia/libvpx/libvpx/test/examples.sh29
-rw-r--r--media/libvpx/libvpx/test/external_frame_buffer_test.cc519
-rw-r--r--media/libvpx/libvpx/test/fdct8x8_test.cc778
-rw-r--r--media/libvpx/libvpx/test/frame_size_tests.cc216
-rw-r--r--media/libvpx/libvpx/test/hadamard_test.cc337
-rw-r--r--media/libvpx/libvpx/test/i420_video_source.h33
-rw-r--r--media/libvpx/libvpx/test/idct8x8_test.cc87
-rw-r--r--media/libvpx/libvpx/test/idct_test.cc180
-rw-r--r--media/libvpx/libvpx/test/invalid_file_test.cc221
-rw-r--r--media/libvpx/libvpx/test/ivf_video_source.h106
-rw-r--r--media/libvpx/libvpx/test/keyframe_test.cc149
-rw-r--r--media/libvpx/libvpx/test/level_test.cc147
-rw-r--r--media/libvpx/libvpx/test/lpf_test.cc721
-rw-r--r--media/libvpx/libvpx/test/md5_helper.h75
-rw-r--r--media/libvpx/libvpx/test/minmax_test.cc248
-rw-r--r--media/libvpx/libvpx/test/non_greedy_mv_test.cc200
-rw-r--r--media/libvpx/libvpx/test/partial_idct_test.cc973
-rwxr-xr-xmedia/libvpx/libvpx/test/postproc.sh63
-rw-r--r--media/libvpx/libvpx/test/pp_filter_test.cc575
-rw-r--r--media/libvpx/libvpx/test/predict_test.cc406
-rw-r--r--media/libvpx/libvpx/test/quantize_test.cc234
-rw-r--r--media/libvpx/libvpx/test/realtime_test.cc117
-rw-r--r--media/libvpx/libvpx/test/register_state_check.h205
-rw-r--r--media/libvpx/libvpx/test/resize_test.cc788
-rwxr-xr-xmedia/libvpx/libvpx/test/resize_util.sh69
-rw-r--r--media/libvpx/libvpx/test/sad_test.cc2004
-rwxr-xr-xmedia/libvpx/libvpx/test/set_maps.sh59
-rw-r--r--media/libvpx/libvpx/test/set_roi.cc166
-rwxr-xr-xmedia/libvpx/libvpx/test/simple_decoder.sh61
-rw-r--r--media/libvpx/libvpx/test/simple_encode_test.cc574
-rwxr-xr-xmedia/libvpx/libvpx/test/simple_encoder.sh59
-rwxr-xr-xmedia/libvpx/libvpx/test/stress.sh183
-rw-r--r--media/libvpx/libvpx/test/sum_squares_test.cc129
-rw-r--r--media/libvpx/libvpx/test/superframe_test.cc102
-rw-r--r--media/libvpx/libvpx/test/svc_datarate_test.cc1796
-rw-r--r--media/libvpx/libvpx/test/svc_end_to_end_test.cc825
-rw-r--r--media/libvpx/libvpx/test/svc_test.cc135
-rw-r--r--media/libvpx/libvpx/test/svc_test.h67
-rw-r--r--media/libvpx/libvpx/test/test-data.mk898
-rw-r--r--media/libvpx/libvpx/test/test-data.sha1872
-rw-r--r--media/libvpx/libvpx/test/test.mk229
-rw-r--r--media/libvpx/libvpx/test/test_intra_pred_speed.cc601
-rw-r--r--media/libvpx/libvpx/test/test_libvpx.cc75
-rw-r--r--media/libvpx/libvpx/test/test_rc_interface.cc6
-rw-r--r--media/libvpx/libvpx/test/test_vector_test.cc205
-rw-r--r--media/libvpx/libvpx/test/test_vectors.cc385
-rw-r--r--media/libvpx/libvpx/test/test_vectors.h34
-rw-r--r--media/libvpx/libvpx/test/tile_independence_test.cc104
-rw-r--r--media/libvpx/libvpx/test/timestamp_test.cc101
-rwxr-xr-xmedia/libvpx/libvpx/test/tools_common.sh442
-rwxr-xr-xmedia/libvpx/libvpx/test/twopass_encoder.sh63
-rw-r--r--media/libvpx/libvpx/test/user_priv_test.cc100
-rw-r--r--media/libvpx/libvpx/test/util.h48
-rw-r--r--media/libvpx/libvpx/test/variance_test.cc1950
-rw-r--r--media/libvpx/libvpx/test/video_source.h283
-rw-r--r--media/libvpx/libvpx/test/vp8_boolcoder_test.cc118
-rw-r--r--media/libvpx/libvpx/test/vp8_datarate_test.cc438
-rw-r--r--media/libvpx/libvpx/test/vp8_decrypt_test.cc69
-rw-r--r--media/libvpx/libvpx/test/vp8_denoiser_sse2_test.cc119
-rw-r--r--media/libvpx/libvpx/test/vp8_fdct4x4_test.cc211
-rw-r--r--media/libvpx/libvpx/test/vp8_fragments_test.cc36
-rwxr-xr-xmedia/libvpx/libvpx/test/vp8_multi_resolution_encoder.sh87
-rw-r--r--media/libvpx/libvpx/test/vp8_ratectrl_rtc_test.cc343
-rw-r--r--media/libvpx/libvpx/test/vp9_arf_freq_test.cc219
-rw-r--r--media/libvpx/libvpx/test/vp9_block_error_test.cc218
-rw-r--r--media/libvpx/libvpx/test/vp9_boolcoder_test.cc92
-rw-r--r--media/libvpx/libvpx/test/vp9_datarate_test.cc1096
-rw-r--r--media/libvpx/libvpx/test/vp9_decrypt_test.cc69
-rw-r--r--media/libvpx/libvpx/test/vp9_denoiser_test.cc136
-rw-r--r--media/libvpx/libvpx/test/vp9_encoder_parms_get_to_decoder.cc153
-rw-r--r--media/libvpx/libvpx/test/vp9_end_to_end_test.cc354
-rw-r--r--media/libvpx/libvpx/test/vp9_ethread_test.cc429
-rw-r--r--media/libvpx/libvpx/test/vp9_ext_ratectrl_test.cc964
-rw-r--r--media/libvpx/libvpx/test/vp9_intrapred_test.cc1198
-rw-r--r--media/libvpx/libvpx/test/vp9_lossless_test.cc125
-rw-r--r--media/libvpx/libvpx/test/vp9_motion_vector_test.cc99
-rw-r--r--media/libvpx/libvpx/test/vp9_quantize_test.cc758
-rw-r--r--media/libvpx/libvpx/test/vp9_ratectrl_rtc_test.cc571
-rw-r--r--media/libvpx/libvpx/test/vp9_roi_test.cc148
-rw-r--r--media/libvpx/libvpx/test/vp9_scale_test.cc215
-rw-r--r--media/libvpx/libvpx/test/vp9_skip_loopfilter_test.cc183
-rw-r--r--media/libvpx/libvpx/test/vp9_subtract_test.cc321
-rw-r--r--media/libvpx/libvpx/test/vp9_thread_test.cc295
-rw-r--r--media/libvpx/libvpx/test/vpx_scale_test.cc101
-rw-r--r--media/libvpx/libvpx/test/vpx_scale_test.h201
-rwxr-xr-xmedia/libvpx/libvpx/test/vpx_temporal_svc_encoder.sh334
-rwxr-xr-xmedia/libvpx/libvpx/test/vpxdec.sh135
-rwxr-xr-xmedia/libvpx/libvpx/test/vpxenc.sh489
-rw-r--r--media/libvpx/libvpx/test/webm_video_source.h95
-rw-r--r--media/libvpx/libvpx/test/y4m_test.cc244
-rw-r--r--media/libvpx/libvpx/test/y4m_video_source.h123
-rw-r--r--media/libvpx/libvpx/test/yuv_temporal_filter_test.cc726
-rw-r--r--media/libvpx/libvpx/test/yuv_video_source.h128
137 files changed, 42775 insertions, 0 deletions
diff --git a/media/libvpx/libvpx/test/acm_random.h b/media/libvpx/libvpx/test/acm_random.h
new file mode 100644
index 0000000000..c7122b9338
--- /dev/null
+++ b/media/libvpx/libvpx/test/acm_random.h
@@ -0,0 +1,93 @@
+/*
+ * 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 VPX_TEST_ACM_RANDOM_H_
+#define VPX_TEST_ACM_RANDOM_H_
+
+#include <assert.h>
+
+#include <limits>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "vpx/vpx_integer.h"
+
+namespace libvpx_test {
+
+class ACMRandom {
+ public:
+ ACMRandom() : random_(DeterministicSeed()) {}
+
+ explicit ACMRandom(int seed) : random_(seed) {}
+
+ void Reset(int seed) { random_.Reseed(seed); }
+ uint16_t Rand16() {
+ const uint32_t value =
+ random_.Generate(testing::internal::Random::kMaxRange);
+ return (value >> 15) & 0xffff;
+ }
+
+ int32_t Rand20Signed() {
+ // Use 20 bits: values between 524287 and -524288.
+ const uint32_t value = random_.Generate(1048576);
+ return static_cast<int32_t>(value) - 524288;
+ }
+
+ int16_t Rand16Signed() {
+ // Use 16 bits: values between 32767 and -32768.
+ return static_cast<int16_t>(random_.Generate(65536));
+ }
+
+ int16_t Rand13Signed() {
+ // Use 13 bits: values between 4095 and -4096.
+ const uint32_t value = random_.Generate(8192);
+ return static_cast<int16_t>(value) - 4096;
+ }
+
+ int16_t Rand9Signed() {
+ // Use 9 bits: values between 255 (0x0FF) and -256 (0x100).
+ const uint32_t value = random_.Generate(512);
+ return static_cast<int16_t>(value) - 256;
+ }
+
+ uint8_t Rand8() {
+ const uint32_t value =
+ random_.Generate(testing::internal::Random::kMaxRange);
+ // There's a bit more entropy in the upper bits of this implementation.
+ return (value >> 23) & 0xff;
+ }
+
+ uint8_t Rand8Extremes() {
+ // Returns a random value near 0 or near 255, to better exercise
+ // saturation behavior.
+ const uint8_t r = Rand8();
+ return static_cast<uint8_t>((r < 128) ? r << 4 : r >> 4);
+ }
+
+ uint32_t RandRange(const uint32_t range) {
+ // testing::internal::Random::Generate provides values in the range
+ // testing::internal::Random::kMaxRange.
+ assert(range <= testing::internal::Random::kMaxRange);
+ return random_.Generate(range);
+ }
+
+ int PseudoUniform(int range) { return random_.Generate(range); }
+
+ int operator()(int n) { return PseudoUniform(n); }
+
+ static int DeterministicSeed() { return 0xbaba; }
+
+ private:
+ testing::internal::Random random_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_ACM_RANDOM_H_
diff --git a/media/libvpx/libvpx/test/active_map_refresh_test.cc b/media/libvpx/libvpx/test/active_map_refresh_test.cc
new file mode 100644
index 0000000000..68d8856eaa
--- /dev/null
+++ b/media/libvpx/libvpx/test/active_map_refresh_test.cc
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 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 <algorithm>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+
+namespace {
+
+// Check if any pixel in a 16x16 macroblock varies between frames.
+int CheckMb(const vpx_image_t &current, const vpx_image_t &previous, int mb_r,
+ int mb_c) {
+ for (int plane = 0; plane < 3; plane++) {
+ int r = 16 * mb_r;
+ int c0 = 16 * mb_c;
+ int r_top = std::min(r + 16, static_cast<int>(current.d_h));
+ int c_top = std::min(c0 + 16, static_cast<int>(current.d_w));
+ r = std::max(r, 0);
+ c0 = std::max(c0, 0);
+ if (plane > 0 && current.x_chroma_shift) {
+ c_top = (c_top + 1) >> 1;
+ c0 >>= 1;
+ }
+ if (plane > 0 && current.y_chroma_shift) {
+ r_top = (r_top + 1) >> 1;
+ r >>= 1;
+ }
+ for (; r < r_top; ++r) {
+ for (int c = c0; c < c_top; ++c) {
+ if (current.planes[plane][current.stride[plane] * r + c] !=
+ previous.planes[plane][previous.stride[plane] * r + c]) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void GenerateMap(int mb_rows, int mb_cols, const vpx_image_t &current,
+ const vpx_image_t &previous, uint8_t *map) {
+ for (int mb_r = 0; mb_r < mb_rows; ++mb_r) {
+ for (int mb_c = 0; mb_c < mb_cols; ++mb_c) {
+ map[mb_r * mb_cols + mb_c] = CheckMb(current, previous, mb_r, mb_c);
+ }
+ }
+}
+
+const int kAqModeCyclicRefresh = 3;
+
+class ActiveMapRefreshTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~ActiveMapRefreshTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ cpu_used_ = GET_PARAM(2);
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ ::libvpx_test::Y4mVideoSource *y4m_video =
+ static_cast<libvpx_test::Y4mVideoSource *>(video);
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ encoder->Control(VP9E_SET_AQ_MODE, kAqModeCyclicRefresh);
+ } else if (video->frame() >= 2 && video->img()) {
+ vpx_image_t *current = video->img();
+ vpx_image_t *previous = y4m_holder_->img();
+ ASSERT_NE(previous, nullptr);
+ vpx_active_map_t map = vpx_active_map_t();
+ const int width = static_cast<int>(current->d_w);
+ const int height = static_cast<int>(current->d_h);
+ const int mb_width = (width + 15) / 16;
+ const int mb_height = (height + 15) / 16;
+ uint8_t *active_map = new uint8_t[mb_width * mb_height];
+ GenerateMap(mb_height, mb_width, *current, *previous, active_map);
+ map.cols = mb_width;
+ map.rows = mb_height;
+ map.active_map = active_map;
+ encoder->Control(VP8E_SET_ACTIVEMAP, &map);
+ delete[] active_map;
+ }
+ if (video->img()) {
+ y4m_video->SwapBuffers(y4m_holder_);
+ }
+ }
+
+ int cpu_used_;
+ ::libvpx_test::Y4mVideoSource *y4m_holder_;
+};
+
+TEST_P(ActiveMapRefreshTest, Test) {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_profile = 1;
+ cfg_.rc_target_bitrate = 600;
+ cfg_.rc_resize_allowed = 0;
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 30;
+ cfg_.g_pass = VPX_RC_ONE_PASS;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.kf_max_dist = 90000;
+
+ ::libvpx_test::Y4mVideoSource video("desktop_credits.y4m", 0, 30);
+ ::libvpx_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 30);
+ video_holder.Begin();
+ y4m_holder_ = &video_holder;
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(ActiveMapRefreshTest,
+ ::testing::Values(::libvpx_test::kRealTime),
+ ::testing::Range(5, 6));
+} // namespace
diff --git a/media/libvpx/libvpx/test/active_map_test.cc b/media/libvpx/libvpx/test/active_map_test.cc
new file mode 100644
index 0000000000..543ec0d358
--- /dev/null
+++ b/media/libvpx/libvpx/test/active_map_test.cc
@@ -0,0 +1,93 @@
+/*
+ * 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 <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class ActiveMapTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode, int,
+ int> {
+ protected:
+ static const int kWidth = 208;
+ static const int kHeight = 144;
+
+ ActiveMapTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~ActiveMapTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ cpu_used_ = GET_PARAM(2);
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ encoder->Control(VP9E_SET_AQ_MODE, GET_PARAM(3));
+ } else if (video->frame() == 3) {
+ vpx_active_map_t map = vpx_active_map_t();
+ /* clang-format off */
+ uint8_t active_map[9 * 13] = {
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,
+ 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1,
+ 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0,
+ };
+ /* clang-format on */
+ map.cols = (kWidth + 15) / 16;
+ map.rows = (kHeight + 15) / 16;
+ ASSERT_EQ(map.cols, 13u);
+ ASSERT_EQ(map.rows, 9u);
+ map.active_map = active_map;
+ encoder->Control(VP8E_SET_ACTIVEMAP, &map);
+ } else if (video->frame() == 15) {
+ vpx_active_map_t map = vpx_active_map_t();
+ map.cols = (kWidth + 15) / 16;
+ map.rows = (kHeight + 15) / 16;
+ map.active_map = nullptr;
+ encoder->Control(VP8E_SET_ACTIVEMAP, &map);
+ }
+ }
+
+ int cpu_used_;
+};
+
+TEST_P(ActiveMapTest, Test) {
+ // Validate that this non multiple of 64 wide clip encodes
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_target_bitrate = 400;
+ cfg_.rc_resize_allowed = 0;
+ cfg_.g_pass = VPX_RC_ONE_PASS;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.kf_max_dist = 90000;
+
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", kWidth, kHeight, 30, 1,
+ 0, 20);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(ActiveMapTest,
+ ::testing::Values(::libvpx_test::kRealTime),
+ ::testing::Range(5, 10), ::testing::Values(0, 3));
+} // namespace
diff --git a/media/libvpx/libvpx/test/add_noise_test.cc b/media/libvpx/libvpx/test/add_noise_test.cc
new file mode 100644
index 0000000000..7dc86e3eb6
--- /dev/null
+++ b/media/libvpx/libvpx/test/add_noise_test.cc
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2016 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 <math.h>
+#include <tuple>
+
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_dsp_rtcd.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_dsp/postproc.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+static const int kNoiseSize = 3072;
+
+typedef void (*AddNoiseFunc)(uint8_t *start, const int8_t *noise,
+ int blackclamp, int whiteclamp, int width,
+ int height, int pitch);
+
+typedef std::tuple<double, AddNoiseFunc> AddNoiseTestFPParam;
+
+class AddNoiseTest : public ::testing::Test,
+ public ::testing::WithParamInterface<AddNoiseTestFPParam> {
+ public:
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+ virtual ~AddNoiseTest() {}
+};
+
+double stddev6(char a, char b, char c, char d, char e, char f) {
+ const double n = (a + b + c + d + e + f) / 6.0;
+ const double v = ((a - n) * (a - n) + (b - n) * (b - n) + (c - n) * (c - n) +
+ (d - n) * (d - n) + (e - n) * (e - n) + (f - n) * (f - n)) /
+ 6.0;
+ return sqrt(v);
+}
+
+TEST_P(AddNoiseTest, CheckNoiseAdded) {
+ const int width = 64;
+ const int height = 64;
+ const int image_size = width * height;
+ int8_t noise[kNoiseSize];
+ const int clamp = vpx_setup_noise(GET_PARAM(0), noise, kNoiseSize);
+ uint8_t *const s =
+ reinterpret_cast<uint8_t *>(vpx_calloc(image_size, sizeof(*s)));
+ ASSERT_NE(s, nullptr);
+ memset(s, 99, image_size * sizeof(*s));
+
+ ASM_REGISTER_STATE_CHECK(
+ GET_PARAM(1)(s, noise, clamp, clamp, width, height, width));
+
+ // Check to make sure we don't end up having either the same or no added
+ // noise either vertically or horizontally.
+ for (int i = 0; i < image_size - 6 * width - 6; ++i) {
+ const double hd = stddev6(s[i] - 99, s[i + 1] - 99, s[i + 2] - 99,
+ s[i + 3] - 99, s[i + 4] - 99, s[i + 5] - 99);
+ const double vd = stddev6(s[i] - 99, s[i + width] - 99,
+ s[i + 2 * width] - 99, s[i + 3 * width] - 99,
+ s[i + 4 * width] - 99, s[i + 5 * width] - 99);
+
+ EXPECT_NE(hd, 0);
+ EXPECT_NE(vd, 0);
+ }
+
+ // Initialize pixels in the image to 255 and check for roll over.
+ memset(s, 255, image_size);
+
+ ASM_REGISTER_STATE_CHECK(
+ GET_PARAM(1)(s, noise, clamp, clamp, width, height, width));
+
+ // Check to make sure don't roll over.
+ for (int i = 0; i < image_size; ++i) {
+ EXPECT_GT(static_cast<int>(s[i]), clamp) << "i = " << i;
+ }
+
+ // Initialize pixels in the image to 0 and check for roll under.
+ memset(s, 0, image_size);
+
+ ASM_REGISTER_STATE_CHECK(
+ GET_PARAM(1)(s, noise, clamp, clamp, width, height, width));
+
+ // Check to make sure don't roll under.
+ for (int i = 0; i < image_size; ++i) {
+ EXPECT_LT(static_cast<int>(s[i]), 255 - clamp) << "i = " << i;
+ }
+
+ vpx_free(s);
+}
+
+TEST_P(AddNoiseTest, CheckCvsAssembly) {
+ const int width = 64;
+ const int height = 64;
+ const int image_size = width * height;
+ int8_t noise[kNoiseSize];
+ const int clamp = vpx_setup_noise(4.4, noise, kNoiseSize);
+
+ uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
+ uint8_t *const d = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
+ ASSERT_NE(s, nullptr);
+ ASSERT_NE(d, nullptr);
+
+ memset(s, 99, image_size);
+ memset(d, 99, image_size);
+
+ srand(0);
+ ASM_REGISTER_STATE_CHECK(
+ GET_PARAM(1)(s, noise, clamp, clamp, width, height, width));
+ srand(0);
+ ASM_REGISTER_STATE_CHECK(
+ vpx_plane_add_noise_c(d, noise, clamp, clamp, width, height, width));
+
+ for (int i = 0; i < image_size; ++i) {
+ EXPECT_EQ(static_cast<int>(s[i]), static_cast<int>(d[i])) << "i = " << i;
+ }
+
+ vpx_free(d);
+ vpx_free(s);
+}
+
+using std::make_tuple;
+
+INSTANTIATE_TEST_SUITE_P(
+ C, AddNoiseTest,
+ ::testing::Values(make_tuple(3.25, vpx_plane_add_noise_c),
+ make_tuple(4.4, vpx_plane_add_noise_c)));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, AddNoiseTest,
+ ::testing::Values(make_tuple(3.25, vpx_plane_add_noise_sse2),
+ make_tuple(4.4, vpx_plane_add_noise_sse2)));
+#endif
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, AddNoiseTest,
+ ::testing::Values(make_tuple(3.25, vpx_plane_add_noise_msa),
+ make_tuple(4.4, vpx_plane_add_noise_msa)));
+#endif
+} // namespace
diff --git a/media/libvpx/libvpx/test/alt_ref_aq_segment_test.cc b/media/libvpx/libvpx/test/alt_ref_aq_segment_test.cc
new file mode 100644
index 0000000000..00a00e27c5
--- /dev/null
+++ b/media/libvpx/libvpx/test/alt_ref_aq_segment_test.cc
@@ -0,0 +1,157 @@
+/*
+ * 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"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class AltRefAqSegmentTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ AltRefAqSegmentTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~AltRefAqSegmentTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ set_cpu_used_ = GET_PARAM(2);
+ aq_mode_ = 0;
+ alt_ref_aq_mode_ = 0;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ encoder->Control(VP9E_SET_ALT_REF_AQ, alt_ref_aq_mode_);
+ encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
+ encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100);
+ }
+ }
+
+ int set_cpu_used_;
+ int aq_mode_;
+ int alt_ref_aq_mode_;
+};
+
+// Validate that this ALT_REF_AQ/AQ segmentation mode
+// (ALT_REF_AQ=0, AQ=0/no_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ0) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 0;
+ alt_ref_aq_mode_ = 1;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this ALT_REF_AQ/AQ segmentation mode
+// (ALT_REF_AQ=0, AQ=1/variance_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ1) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 1;
+ alt_ref_aq_mode_ = 1;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this ALT_REF_AQ/AQ segmentation mode
+// (ALT_REF_AQ=0, AQ=2/complexity_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ2) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 2;
+ alt_ref_aq_mode_ = 1;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this ALT_REF_AQ/AQ segmentation mode
+// (ALT_REF_AQ=0, AQ=3/cyclicrefresh_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ3) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 3;
+ alt_ref_aq_mode_ = 1;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this ALT_REF_AQ/AQ segmentation mode
+// (ALT_REF_AQ=0, AQ=4/equator360_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AltRefAqSegmentTest, TestNoMisMatchAltRefAQ4) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 4;
+ alt_ref_aq_mode_ = 1;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(AltRefAqSegmentTest,
+ ::testing::Values(::libvpx_test::kOnePassGood,
+ ::libvpx_test::kTwoPassGood),
+ ::testing::Range(2, 5));
+} // namespace
diff --git a/media/libvpx/libvpx/test/altref_test.cc b/media/libvpx/libvpx/test/altref_test.cc
new file mode 100644
index 0000000000..69bcef774e
--- /dev/null
+++ b/media/libvpx/libvpx/test/altref_test.cc
@@ -0,0 +1,152 @@
+/*
+ * 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"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+namespace {
+
+#if CONFIG_VP8_ENCODER
+
+// lookahead range: [kLookAheadMin, kLookAheadMax).
+const int kLookAheadMin = 5;
+const int kLookAheadMax = 26;
+
+class AltRefTest : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+ AltRefTest() : EncoderTest(GET_PARAM(0)), altref_count_(0) {}
+ virtual ~AltRefTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(libvpx_test::kTwoPassGood);
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) { altref_count_ = 0; }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_CPUUSED, 3);
+ }
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) ++altref_count_;
+ }
+
+ int altref_count() const { return altref_count_; }
+
+ private:
+ int altref_count_;
+};
+
+TEST_P(AltRefTest, MonotonicTimestamps) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 1000;
+ cfg_.g_lag_in_frames = GET_PARAM(1);
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 30);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ EXPECT_GE(altref_count(), 1);
+}
+
+VP8_INSTANTIATE_TEST_SUITE(AltRefTest,
+ ::testing::Range(kLookAheadMin, kLookAheadMax));
+
+#endif // CONFIG_VP8_ENCODER
+
+class AltRefForcedKeyTestLarge
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ AltRefForcedKeyTestLarge()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
+ cpu_used_(GET_PARAM(2)), forced_kf_frame_num_(1), frame_num_(0) {}
+ virtual ~AltRefForcedKeyTestLarge() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.g_threads = 0;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+#if CONFIG_VP9_ENCODER
+ // override test default for tile columns if necessary.
+ if (GET_PARAM(0) == &libvpx_test::kVP9) {
+ encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
+ }
+#endif
+ }
+ frame_flags_ =
+ (video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (frame_num_ == forced_kf_frame_num_) {
+ ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY))
+ << "Frame #" << frame_num_ << " isn't a keyframe!";
+ }
+ ++frame_num_;
+ }
+
+ ::libvpx_test::TestMode encoding_mode_;
+ int cpu_used_;
+ unsigned int forced_kf_frame_num_;
+ unsigned int frame_num_;
+};
+
+TEST_P(AltRefForcedKeyTestLarge, Frame1IsKey) {
+ const vpx_rational timebase = { 1, 30 };
+ const int lag_values[] = { 3, 15, 25, -1 };
+
+ forced_kf_frame_num_ = 1;
+ for (int i = 0; lag_values[i] != -1; ++i) {
+ frame_num_ = 0;
+ cfg_.g_lag_in_frames = lag_values[i];
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 30);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+}
+
+TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) {
+ const vpx_rational timebase = { 1, 30 };
+ const int lag_values[] = { 3, 15, 25, -1 };
+
+ for (int i = 0; lag_values[i] != -1; ++i) {
+ frame_num_ = 0;
+ forced_kf_frame_num_ = lag_values[i] - 1;
+ cfg_.g_lag_in_frames = lag_values[i];
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 30);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+}
+
+VP8_INSTANTIATE_TEST_SUITE(AltRefForcedKeyTestLarge,
+ ::testing::Values(::libvpx_test::kOnePassGood),
+ ::testing::Range(0, 9));
+
+VP9_INSTANTIATE_TEST_SUITE(AltRefForcedKeyTestLarge,
+ ::testing::Values(::libvpx_test::kOnePassGood),
+ ::testing::Range(0, 9));
+} // namespace
diff --git a/media/libvpx/libvpx/test/android/Android.mk b/media/libvpx/libvpx/test/android/Android.mk
new file mode 100644
index 0000000000..9a7533ebba
--- /dev/null
+++ b/media/libvpx/libvpx/test/android/Android.mk
@@ -0,0 +1,67 @@
+# 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.
+#
+# This make file builds vpx_test app for android.
+# The test app itself runs on the command line through adb shell
+# The paths are really messed up as the libvpx make file
+# expects to be made from a parent directory.
+
+# Ignore this file during non-NDK builds.
+ifdef NDK_ROOT
+CUR_WD := $(call my-dir)
+BINDINGS_DIR := $(CUR_WD)/../../..
+LOCAL_PATH := $(CUR_WD)/../../..
+
+#libwebm
+include $(CLEAR_VARS)
+include $(BINDINGS_DIR)/libvpx/third_party/libwebm/Android.mk
+LOCAL_PATH := $(CUR_WD)/../../..
+
+#libvpx
+include $(CLEAR_VARS)
+LOCAL_STATIC_LIBRARIES := libwebm
+include $(BINDINGS_DIR)/libvpx/build/make/Android.mk
+LOCAL_PATH := $(CUR_WD)/../..
+
+#libgtest
+include $(CLEAR_VARS)
+LOCAL_ARM_MODE := arm
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_MODULE := gtest
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/third_party/googletest/src/
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/third_party/googletest/src/include/
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/third_party/googletest/src/include/
+LOCAL_SRC_FILES := ./third_party/googletest/src/src/gtest-all.cc
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../LICENSE $(LOCAL_PATH)/../../PATENTS
+include $(BUILD_STATIC_LIBRARY)
+
+#libvpx_test
+include $(CLEAR_VARS)
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE := libvpx_test
+LOCAL_STATIC_LIBRARIES := gtest libwebm
+
+ifeq ($(ENABLE_SHARED),1)
+ LOCAL_SHARED_LIBRARIES := vpx
+else
+ LOCAL_STATIC_LIBRARIES += vpx
+endif
+
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../LICENSE $(LOCAL_PATH)/../../PATENTS
+include $(LOCAL_PATH)/test/test.mk
+LOCAL_C_INCLUDES := $(BINDINGS_DIR)
+FILTERED_SRC := $(sort $(filter %.cc %.c, $(LIBVPX_TEST_SRCS-yes)))
+LOCAL_SRC_FILES := $(addprefix ./test/, $(FILTERED_SRC))
+# some test files depend on *_rtcd.h, ensure they're generated first.
+$(eval $(call rtcd_dep_template))
+include $(BUILD_EXECUTABLE)
+endif # NDK_ROOT
diff --git a/media/libvpx/libvpx/test/android/README b/media/libvpx/libvpx/test/android/README
new file mode 100644
index 0000000000..0cd30779d4
--- /dev/null
+++ b/media/libvpx/libvpx/test/android/README
@@ -0,0 +1,33 @@
+Android.mk will build vpx unittests on android.
+1) Configure libvpx from the parent directory:
+./libvpx/configure --target=armv7-android-gcc --enable-external-build \
+ --enable-postproc --disable-install-srcs --enable-multi-res-encoding \
+ --enable-temporal-denoising --disable-unit-tests --disable-install-docs \
+ --disable-examples --disable-runtime-cpu-detect
+
+2) From the parent directory, invoke ndk-build:
+NDK_PROJECT_PATH=. ndk-build APP_BUILD_SCRIPT=./libvpx/test/android/Android.mk \
+ APP_ABI=armeabi-v7a APP_PLATFORM=android-18 APP_OPTIM=release \
+ APP_STL=c++_static
+
+Note: Both adb and ndk-build are available at:
+ https://developer.android.com/studio#downloads
+ https://developer.android.com/ndk/downloads
+
+3) Run get_files.py to download the test files:
+python get_files.py -i /path/to/test-data.sha1 -o /path/to/put/files \
+ -u https://storage.googleapis.com/downloads.webmproject.org/test_data/libvpx
+
+4) Transfer files to device using adb. Ensure you have proper permissions for
+the target
+
+adb push /path/to/test_files /data/local/tmp
+adb push /path/to/built_libs /data/local/tmp
+
+NOTE: Built_libs defaults to parent_dir/libs/armeabi-v7a
+
+5) Run tests:
+adb shell
+(on device)
+cd /data/local/tmp
+LD_LIBRARY_PATH=. ./vpx_test
diff --git a/media/libvpx/libvpx/test/android/get_files.py b/media/libvpx/libvpx/test/android/get_files.py
new file mode 100644
index 0000000000..1c69740d2b
--- /dev/null
+++ b/media/libvpx/libvpx/test/android/get_files.py
@@ -0,0 +1,118 @@
+# 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.
+#
+# This simple script pulls test files from the webm homepage
+# It is intelligent enough to only pull files if
+# 1) File / test_data folder does not exist
+# 2) SHA mismatch
+
+import pycurl
+import csv
+import hashlib
+import re
+import os.path
+import time
+import itertools
+import sys
+import getopt
+
+#globals
+url = ''
+file_list_path = ''
+local_resource_path = ''
+
+# Helper functions:
+# A simple function which returns the sha hash of a file in hex
+def get_file_sha(filename):
+ try:
+ sha_hash = hashlib.sha1()
+ with open(filename, 'rb') as file:
+ buf = file.read(HASH_CHUNK)
+ while len(buf) > 0:
+ sha_hash.update(buf)
+ buf = file.read(HASH_CHUNK)
+ return sha_hash.hexdigest()
+ except IOError:
+ print "Error reading " + filename
+
+# Downloads a file from a url, and then checks the sha against the passed
+# in sha
+def download_and_check_sha(url, filename, sha):
+ path = os.path.join(local_resource_path, filename)
+ fp = open(path, "wb")
+ curl = pycurl.Curl()
+ curl.setopt(pycurl.URL, url + "/" + filename)
+ curl.setopt(pycurl.WRITEDATA, fp)
+ curl.perform()
+ curl.close()
+ fp.close()
+ return get_file_sha(path) == sha
+
+#constants
+ftp_retries = 3
+
+SHA_COL = 0
+NAME_COL = 1
+EXPECTED_COL = 2
+HASH_CHUNK = 65536
+
+# Main script
+try:
+ opts, args = \
+ getopt.getopt(sys.argv[1:], \
+ "u:i:o:", ["url=", "input_csv=", "output_dir="])
+except:
+ print 'get_files.py -u <url> -i <input_csv> -o <output_dir>'
+ sys.exit(2)
+
+for opt, arg in opts:
+ if opt == '-u':
+ url = arg
+ elif opt in ("-i", "--input_csv"):
+ file_list_path = os.path.join(arg)
+ elif opt in ("-o", "--output_dir"):
+ local_resource_path = os.path.join(arg)
+
+if len(sys.argv) != 7:
+ print "Expects two paths and a url!"
+ exit(1)
+
+if not os.path.isdir(local_resource_path):
+ os.makedirs(local_resource_path)
+
+file_list_csv = open(file_list_path, "rb")
+
+# Our 'csv' file uses multiple spaces as a delimiter, python's
+# csv class only uses single character delimiters, so we convert them below
+file_list_reader = csv.reader((re.sub(' +', ' ', line) \
+ for line in file_list_csv), delimiter = ' ')
+
+file_shas = []
+file_names = []
+
+for row in file_list_reader:
+ if len(row) != EXPECTED_COL:
+ continue
+ file_shas.append(row[SHA_COL])
+ file_names.append(row[NAME_COL])
+
+file_list_csv.close()
+
+# Download files, only if they don't already exist and have correct shas
+for filename, sha in itertools.izip(file_names, file_shas):
+ path = os.path.join(local_resource_path, filename)
+ if os.path.isfile(path) \
+ and get_file_sha(path) == sha:
+ print path + ' exists, skipping'
+ continue
+ for retry in range(0, ftp_retries):
+ print "Downloading " + path
+ if not download_and_check_sha(url, filename, sha):
+ print "Sha does not match, retrying..."
+ else:
+ break
diff --git a/media/libvpx/libvpx/test/android/scrape_gtest_log.py b/media/libvpx/libvpx/test/android/scrape_gtest_log.py
new file mode 100644
index 0000000000..487845c270
--- /dev/null
+++ b/media/libvpx/libvpx/test/android/scrape_gtest_log.py
@@ -0,0 +1,57 @@
+# 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.
+
+"""Standalone script which parses a gtest log for json.
+
+Json is returned returns as an array. This script is used by the libvpx
+waterfall to gather json results mixed in with gtest logs. This is
+dubious software engineering.
+"""
+
+import getopt
+import json
+import os
+import re
+import sys
+
+
+def main():
+ if len(sys.argv) != 3:
+ print "Expects a file to write json to!"
+ exit(1)
+
+ try:
+ opts, _ = \
+ getopt.getopt(sys.argv[1:], \
+ 'o:', ['output-json='])
+ except getopt.GetOptError:
+ print 'scrape_gtest_log.py -o <output_json>'
+ sys.exit(2)
+
+ output_json = ''
+ for opt, arg in opts:
+ if opt in ('-o', '--output-json'):
+ output_json = os.path.join(arg)
+
+ blob = sys.stdin.read()
+ json_string = '[' + ','.join('{' + x + '}' for x in
+ re.findall(r'{([^}]*.?)}', blob)) + ']'
+ print blob
+
+ output = json.dumps(json.loads(json_string), indent=4, sort_keys=True)
+ print output
+
+ path = os.path.dirname(output_json)
+ if path and not os.path.exists(path):
+ os.makedirs(path)
+
+ outfile = open(output_json, 'w')
+ outfile.write(output)
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/media/libvpx/libvpx/test/aq_segment_test.cc b/media/libvpx/libvpx/test/aq_segment_test.cc
new file mode 100644
index 0000000000..2cbc991d0c
--- /dev/null
+++ b/media/libvpx/libvpx/test/aq_segment_test.cc
@@ -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.
+ */
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class AqSegmentTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ AqSegmentTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~AqSegmentTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ set_cpu_used_ = GET_PARAM(2);
+ aq_mode_ = 0;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
+ encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100);
+ }
+ }
+
+ int set_cpu_used_;
+ int aq_mode_;
+};
+
+// Validate that this AQ segmentation mode (AQ=1, variance_ap)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ1) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 1;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this AQ segmentation mode (AQ=2, complexity_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ2) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 2;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this AQ segmentation mode (AQ=3, cyclic_refresh_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ3) {
+ cfg_.rc_min_quantizer = 8;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_target_bitrate = 300;
+
+ aq_mode_ = 3;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 100);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(AqSegmentTest,
+ ::testing::Values(::libvpx_test::kRealTime,
+ ::libvpx_test::kOnePassGood),
+ ::testing::Range(3, 9));
+} // namespace
diff --git a/media/libvpx/libvpx/test/avg_test.cc b/media/libvpx/libvpx/test/avg_test.cc
new file mode 100644
index 0000000000..a0428304a2
--- /dev/null
+++ b/media/libvpx/libvpx/test/avg_test.cc
@@ -0,0 +1,756 @@
+/*
+ * 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 <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/vpx_timer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+template <typename Pixel>
+class AverageTestBase : public ::testing::Test {
+ public:
+ AverageTestBase(int width, int height)
+ : width_(width), height_(height), source_data_(nullptr),
+ source_stride_(0), bit_depth_(8) {}
+
+ virtual void TearDown() {
+ vpx_free(source_data_);
+ source_data_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ // Handle blocks up to 4 blocks 64x64 with stride up to 128
+ static const int kDataAlignment = 16;
+ static const int kDataBlockSize = 64 * 128;
+
+ virtual void SetUp() {
+ source_data_ = reinterpret_cast<Pixel *>(
+ vpx_memalign(kDataAlignment, kDataBlockSize * sizeof(source_data_[0])));
+ ASSERT_NE(source_data_, nullptr);
+ source_stride_ = (width_ + 31) & ~31;
+ bit_depth_ = 8;
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ // Sum Pixels
+ static unsigned int ReferenceAverage8x8(const Pixel *source, int pitch) {
+ unsigned int average = 0;
+ for (int h = 0; h < 8; ++h) {
+ for (int w = 0; w < 8; ++w) average += source[h * pitch + w];
+ }
+ return ((average + 32) >> 6);
+ }
+
+ static unsigned int ReferenceAverage4x4(const Pixel *source, int pitch) {
+ unsigned int average = 0;
+ for (int h = 0; h < 4; ++h) {
+ for (int w = 0; w < 4; ++w) average += source[h * pitch + w];
+ }
+ return ((average + 8) >> 4);
+ }
+
+ void FillConstant(Pixel fill_constant) {
+ for (int i = 0; i < width_ * height_; ++i) {
+ source_data_[i] = fill_constant;
+ }
+ }
+
+ void FillRandom() {
+ for (int i = 0; i < width_ * height_; ++i) {
+ source_data_[i] = rnd_.Rand16() & ((1 << bit_depth_) - 1);
+ }
+ }
+
+ int width_, height_;
+ Pixel *source_data_;
+ int source_stride_;
+ int bit_depth_;
+
+ ACMRandom rnd_;
+};
+typedef unsigned int (*AverageFunction)(const uint8_t *s, int pitch);
+
+typedef std::tuple<int, int, int, int, AverageFunction> AvgFunc;
+
+class AverageTest : public AverageTestBase<uint8_t>,
+ public ::testing::WithParamInterface<AvgFunc> {
+ public:
+ AverageTest() : AverageTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+ void CheckAverages() {
+ const int block_size = GET_PARAM(3);
+ unsigned int expected = 0;
+ if (block_size == 8) {
+ expected =
+ ReferenceAverage8x8(source_data_ + GET_PARAM(2), source_stride_);
+ } else if (block_size == 4) {
+ expected =
+ ReferenceAverage4x4(source_data_ + GET_PARAM(2), source_stride_);
+ }
+
+ ASM_REGISTER_STATE_CHECK(
+ GET_PARAM(4)(source_data_ + GET_PARAM(2), source_stride_));
+ unsigned int actual =
+ GET_PARAM(4)(source_data_ + GET_PARAM(2), source_stride_);
+
+ EXPECT_EQ(expected, actual);
+ }
+};
+
+#if CONFIG_VP9_HIGHBITDEPTH
+class AverageTestHBD : public AverageTestBase<uint16_t>,
+ public ::testing::WithParamInterface<AvgFunc> {
+ public:
+ AverageTestHBD() : AverageTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+ void CheckAverages() {
+ const int block_size = GET_PARAM(3);
+ unsigned int expected = 0;
+ if (block_size == 8) {
+ expected =
+ ReferenceAverage8x8(source_data_ + GET_PARAM(2), source_stride_);
+ } else if (block_size == 4) {
+ expected =
+ ReferenceAverage4x4(source_data_ + GET_PARAM(2), source_stride_);
+ }
+
+ ASM_REGISTER_STATE_CHECK(GET_PARAM(4)(
+ CONVERT_TO_BYTEPTR(source_data_ + GET_PARAM(2)), source_stride_));
+ unsigned int actual = GET_PARAM(4)(
+ CONVERT_TO_BYTEPTR(source_data_ + GET_PARAM(2)), source_stride_);
+
+ EXPECT_EQ(expected, actual);
+ }
+};
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON || HAVE_SSE2 || HAVE_MSA
+typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref,
+ const int ref_stride, const int height);
+
+typedef std::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam;
+
+class IntProRowTest : public AverageTestBase<uint8_t>,
+ public ::testing::WithParamInterface<IntProRowParam> {
+ public:
+ IntProRowTest()
+ : AverageTestBase(16, GET_PARAM(0)), hbuf_asm_(nullptr),
+ hbuf_c_(nullptr) {
+ asm_func_ = GET_PARAM(1);
+ c_func_ = GET_PARAM(2);
+ }
+
+ protected:
+ virtual void SetUp() {
+ source_data_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBlockSize * sizeof(source_data_[0])));
+ ASSERT_NE(source_data_, nullptr);
+
+ hbuf_asm_ = reinterpret_cast<int16_t *>(
+ vpx_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16));
+ hbuf_c_ = reinterpret_cast<int16_t *>(
+ vpx_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16));
+ }
+
+ virtual void TearDown() {
+ vpx_free(source_data_);
+ source_data_ = nullptr;
+ vpx_free(hbuf_c_);
+ hbuf_c_ = nullptr;
+ vpx_free(hbuf_asm_);
+ hbuf_asm_ = nullptr;
+ }
+
+ void RunComparison() {
+ ASM_REGISTER_STATE_CHECK(c_func_(hbuf_c_, source_data_, 0, height_));
+ ASM_REGISTER_STATE_CHECK(asm_func_(hbuf_asm_, source_data_, 0, height_));
+ EXPECT_EQ(0, memcmp(hbuf_c_, hbuf_asm_, sizeof(*hbuf_c_) * 16))
+ << "Output mismatch";
+ }
+
+ private:
+ IntProRowFunc asm_func_;
+ IntProRowFunc c_func_;
+ int16_t *hbuf_asm_;
+ int16_t *hbuf_c_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IntProRowTest);
+
+typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width);
+
+typedef std::tuple<int, IntProColFunc, IntProColFunc> IntProColParam;
+
+class IntProColTest : public AverageTestBase<uint8_t>,
+ public ::testing::WithParamInterface<IntProColParam> {
+ public:
+ IntProColTest() : AverageTestBase(GET_PARAM(0), 1), sum_asm_(0), sum_c_(0) {
+ asm_func_ = GET_PARAM(1);
+ c_func_ = GET_PARAM(2);
+ }
+
+ protected:
+ void RunComparison() {
+ ASM_REGISTER_STATE_CHECK(sum_c_ = c_func_(source_data_, width_));
+ ASM_REGISTER_STATE_CHECK(sum_asm_ = asm_func_(source_data_, width_));
+ EXPECT_EQ(sum_c_, sum_asm_) << "Output mismatch";
+ }
+
+ private:
+ IntProColFunc asm_func_;
+ IntProColFunc c_func_;
+ int16_t sum_asm_;
+ int16_t sum_c_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IntProColTest);
+#endif // HAVE_NEON || HAVE_SSE2 || HAVE_MSA
+
+typedef int (*SatdFunc)(const tran_low_t *coeffs, int length);
+typedef std::tuple<int, SatdFunc> SatdTestParam;
+
+class SatdTest : public ::testing::Test,
+ public ::testing::WithParamInterface<SatdTestParam> {
+ protected:
+ virtual void SetUp() {
+ satd_size_ = GET_PARAM(0);
+ satd_func_ = GET_PARAM(1);
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ src_ = reinterpret_cast<tran_low_t *>(
+ vpx_memalign(16, sizeof(*src_) * satd_size_));
+ ASSERT_NE(src_, nullptr);
+ }
+
+ virtual void TearDown() {
+ libvpx_test::ClearSystemState();
+ vpx_free(src_);
+ }
+
+ void FillConstant(const tran_low_t val) {
+ for (int i = 0; i < satd_size_; ++i) src_[i] = val;
+ }
+
+ virtual void FillRandom() = 0;
+
+ void Check(const int expected) {
+ int total;
+ ASM_REGISTER_STATE_CHECK(total = satd_func_(src_, satd_size_));
+ EXPECT_EQ(expected, total);
+ }
+
+ tran_low_t *GetCoeff() const { return src_; }
+
+ int satd_size_;
+ ACMRandom rnd_;
+ tran_low_t *src_;
+
+ private:
+ SatdFunc satd_func_;
+};
+
+class SatdLowbdTest : public SatdTest {
+ protected:
+ virtual void FillRandom() {
+ for (int i = 0; i < satd_size_; ++i) {
+ const int16_t tmp = rnd_.Rand16Signed();
+ src_[i] = (tran_low_t)tmp;
+ }
+ }
+};
+
+typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff,
+ const tran_low_t *dqcoeff, int block_size);
+typedef std::tuple<int, BlockErrorFunc> BlockErrorTestFPParam;
+
+class BlockErrorTestFP
+ : public ::testing::Test,
+ public ::testing::WithParamInterface<BlockErrorTestFPParam> {
+ protected:
+ virtual void SetUp() {
+ txfm_size_ = GET_PARAM(0);
+ block_error_func_ = GET_PARAM(1);
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ coeff_ = reinterpret_cast<tran_low_t *>(
+ vpx_memalign(16, sizeof(*coeff_) * txfm_size_));
+ dqcoeff_ = reinterpret_cast<tran_low_t *>(
+ vpx_memalign(16, sizeof(*dqcoeff_) * txfm_size_));
+ ASSERT_NE(coeff_, nullptr);
+ ASSERT_NE(dqcoeff_, nullptr);
+ }
+
+ virtual void TearDown() {
+ libvpx_test::ClearSystemState();
+ vpx_free(coeff_);
+ vpx_free(dqcoeff_);
+ }
+
+ void FillConstant(const tran_low_t coeff_val, const tran_low_t dqcoeff_val) {
+ for (int i = 0; i < txfm_size_; ++i) coeff_[i] = coeff_val;
+ for (int i = 0; i < txfm_size_; ++i) dqcoeff_[i] = dqcoeff_val;
+ }
+
+ void FillRandom() {
+ // Just two fixed seeds
+ rnd_.Reset(0xb0b9);
+ for (int i = 0; i < txfm_size_; ++i) coeff_[i] = rnd_.Rand16() >> 1;
+ rnd_.Reset(0xb0c8);
+ for (int i = 0; i < txfm_size_; ++i) dqcoeff_[i] = rnd_.Rand16() >> 1;
+ }
+
+ void Check(const int64_t expected) {
+ int64_t total;
+ ASM_REGISTER_STATE_CHECK(
+ total = block_error_func_(coeff_, dqcoeff_, txfm_size_));
+ EXPECT_EQ(expected, total);
+ }
+
+ tran_low_t *GetCoeff() const { return coeff_; }
+
+ tran_low_t *GetDQCoeff() const { return dqcoeff_; }
+
+ int txfm_size_;
+
+ private:
+ tran_low_t *coeff_;
+ tran_low_t *dqcoeff_;
+ BlockErrorFunc block_error_func_;
+ ACMRandom rnd_;
+};
+
+TEST_P(AverageTest, MinValue) {
+ FillConstant(0);
+ CheckAverages();
+}
+
+TEST_P(AverageTest, MaxValue) {
+ FillConstant(255);
+ CheckAverages();
+}
+
+TEST_P(AverageTest, Random) {
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ for (int i = 0; i < 1000; i++) {
+ FillRandom();
+ CheckAverages();
+ }
+}
+#if CONFIG_VP9_HIGHBITDEPTH
+TEST_P(AverageTestHBD, MinValue) {
+ FillConstant(0);
+ CheckAverages();
+}
+
+TEST_P(AverageTestHBD, MaxValue) {
+ FillConstant((1 << VPX_BITS_12) - 1);
+ CheckAverages();
+}
+
+TEST_P(AverageTestHBD, Random) {
+ bit_depth_ = VPX_BITS_12;
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ for (int i = 0; i < 1000; i++) {
+ FillRandom();
+ CheckAverages();
+ }
+}
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON || HAVE_SSE2 || HAVE_MSA
+TEST_P(IntProRowTest, MinValue) {
+ FillConstant(0);
+ RunComparison();
+}
+
+TEST_P(IntProRowTest, MaxValue) {
+ FillConstant(255);
+ RunComparison();
+}
+
+TEST_P(IntProRowTest, Random) {
+ FillRandom();
+ RunComparison();
+}
+
+TEST_P(IntProColTest, MinValue) {
+ FillConstant(0);
+ RunComparison();
+}
+
+TEST_P(IntProColTest, MaxValue) {
+ FillConstant(255);
+ RunComparison();
+}
+
+TEST_P(IntProColTest, Random) {
+ FillRandom();
+ RunComparison();
+}
+#endif
+
+TEST_P(SatdLowbdTest, MinValue) {
+ const int kMin = -32640;
+ const int expected = -kMin * satd_size_;
+ FillConstant(kMin);
+ Check(expected);
+}
+
+TEST_P(SatdLowbdTest, MaxValue) {
+ const int kMax = 32640;
+ const int expected = kMax * satd_size_;
+ FillConstant(kMax);
+ Check(expected);
+}
+
+TEST_P(SatdLowbdTest, Random) {
+ int expected;
+ switch (satd_size_) {
+ case 16: expected = 261036; break;
+ case 64: expected = 991732; break;
+ case 256: expected = 4136358; break;
+ case 1024: expected = 16677592; break;
+ default:
+ FAIL() << "Invalid satd size (" << satd_size_
+ << ") valid: 16/64/256/1024";
+ }
+ FillRandom();
+ Check(expected);
+}
+
+TEST_P(SatdLowbdTest, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 20000;
+ vpx_usec_timer timer;
+ const int blocksize = GET_PARAM(0);
+ FillRandom();
+ tran_low_t *coeff = GetCoeff();
+
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ GET_PARAM(1)(coeff, blocksize);
+ }
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+class SatdHighbdTest : public SatdTest {
+ protected:
+ virtual void FillRandom() {
+ for (int i = 0; i < satd_size_; ++i) {
+ src_[i] = rnd_.Rand20Signed();
+ }
+ }
+};
+
+TEST_P(SatdHighbdTest, MinValue) {
+ const int kMin = -524280;
+ const int expected = -kMin * satd_size_;
+ FillConstant(kMin);
+ Check(expected);
+}
+
+TEST_P(SatdHighbdTest, MaxValue) {
+ const int kMax = 524280;
+ const int expected = kMax * satd_size_;
+ FillConstant(kMax);
+ Check(expected);
+}
+
+TEST_P(SatdHighbdTest, Random) {
+ int expected;
+ switch (satd_size_) {
+ case 16: expected = 5249712; break;
+ case 64: expected = 18362120; break;
+ case 256: expected = 66100520; break;
+ case 1024: expected = 266094734; break;
+ default:
+ FAIL() << "Invalid satd size (" << satd_size_
+ << ") valid: 16/64/256/1024";
+ }
+ FillRandom();
+ Check(expected);
+}
+
+TEST_P(SatdHighbdTest, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 20000;
+ vpx_usec_timer timer;
+ const int blocksize = GET_PARAM(0);
+ FillRandom();
+ tran_low_t *coeff = GetCoeff();
+
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ GET_PARAM(1)(coeff, blocksize);
+ }
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time);
+}
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+TEST_P(BlockErrorTestFP, MinValue) {
+ const int64_t kMin = -32640;
+ const int64_t expected = kMin * kMin * txfm_size_;
+ FillConstant(kMin, 0);
+ Check(expected);
+}
+
+TEST_P(BlockErrorTestFP, MaxValue) {
+ const int64_t kMax = 32640;
+ const int64_t expected = kMax * kMax * txfm_size_;
+ FillConstant(kMax, 0);
+ Check(expected);
+}
+
+TEST_P(BlockErrorTestFP, Random) {
+ int64_t expected;
+ switch (txfm_size_) {
+ case 16: expected = 2051681432; break;
+ case 64: expected = 11075114379; break;
+ case 256: expected = 44386271116; break;
+ case 1024: expected = 184774996089; break;
+ default:
+ FAIL() << "Invalid satd size (" << txfm_size_
+ << ") valid: 16/64/256/1024";
+ }
+ FillRandom();
+ Check(expected);
+}
+
+TEST_P(BlockErrorTestFP, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 20000;
+ vpx_usec_timer timer;
+ const int blocksize = GET_PARAM(0);
+ FillRandom();
+ tran_low_t *coeff = GetCoeff();
+ tran_low_t *dqcoeff = GetDQCoeff();
+
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ GET_PARAM(1)(coeff, dqcoeff, blocksize);
+ }
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("blocksize: %4d time: %4d us\n", blocksize, elapsed_time);
+}
+
+using std::make_tuple;
+
+INSTANTIATE_TEST_SUITE_P(
+ C, AverageTest,
+ ::testing::Values(make_tuple(16, 16, 1, 8, &vpx_avg_8x8_c),
+ make_tuple(16, 16, 1, 4, &vpx_avg_4x4_c)));
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, AverageTestHBD,
+ ::testing::Values(make_tuple(16, 16, 1, 8, &vpx_highbd_avg_8x8_c),
+ make_tuple(16, 16, 1, 4, &vpx_highbd_avg_4x4_c)));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, AverageTestHBD,
+ ::testing::Values(make_tuple(16, 16, 1, 8, &vpx_highbd_avg_8x8_sse2),
+ make_tuple(16, 16, 1, 4, &vpx_highbd_avg_4x4_sse2)));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, AverageTestHBD,
+ ::testing::Values(make_tuple(16, 16, 1, 8, &vpx_highbd_avg_8x8_neon),
+ make_tuple(16, 16, 1, 4, &vpx_highbd_avg_4x4_neon)));
+#endif // HAVE_NEON
+
+INSTANTIATE_TEST_SUITE_P(C, SatdHighbdTest,
+ ::testing::Values(make_tuple(16, &vpx_satd_c),
+ make_tuple(64, &vpx_satd_c),
+ make_tuple(256, &vpx_satd_c),
+ make_tuple(1024, &vpx_satd_c)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+INSTANTIATE_TEST_SUITE_P(C, SatdLowbdTest,
+ ::testing::Values(make_tuple(16, &vpx_satd_c),
+ make_tuple(64, &vpx_satd_c),
+ make_tuple(256, &vpx_satd_c),
+ make_tuple(1024, &vpx_satd_c)));
+
+INSTANTIATE_TEST_SUITE_P(
+ C, BlockErrorTestFP,
+ ::testing::Values(make_tuple(16, &vp9_block_error_fp_c),
+ make_tuple(64, &vp9_block_error_fp_c),
+ make_tuple(256, &vp9_block_error_fp_c),
+ make_tuple(1024, &vp9_block_error_fp_c)));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, AverageTest,
+ ::testing::Values(make_tuple(16, 16, 0, 8, &vpx_avg_8x8_sse2),
+ make_tuple(16, 16, 5, 8, &vpx_avg_8x8_sse2),
+ make_tuple(32, 32, 15, 8, &vpx_avg_8x8_sse2),
+ make_tuple(16, 16, 0, 4, &vpx_avg_4x4_sse2),
+ make_tuple(16, 16, 5, 4, &vpx_avg_4x4_sse2),
+ make_tuple(32, 32, 15, 4, &vpx_avg_4x4_sse2)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, IntProRowTest,
+ ::testing::Values(make_tuple(16, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
+ make_tuple(32, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
+ make_tuple(64, &vpx_int_pro_row_sse2,
+ &vpx_int_pro_row_c)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, IntProColTest,
+ ::testing::Values(make_tuple(16, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
+ make_tuple(32, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
+ make_tuple(64, &vpx_int_pro_col_sse2,
+ &vpx_int_pro_col_c)));
+
+INSTANTIATE_TEST_SUITE_P(SSE2, SatdLowbdTest,
+ ::testing::Values(make_tuple(16, &vpx_satd_sse2),
+ make_tuple(64, &vpx_satd_sse2),
+ make_tuple(256, &vpx_satd_sse2),
+ make_tuple(1024, &vpx_satd_sse2)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, BlockErrorTestFP,
+ ::testing::Values(make_tuple(16, &vp9_block_error_fp_sse2),
+ make_tuple(64, &vp9_block_error_fp_sse2),
+ make_tuple(256, &vp9_block_error_fp_sse2),
+ make_tuple(1024, &vp9_block_error_fp_sse2)));
+#endif // HAVE_SSE2
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(AVX2, SatdLowbdTest,
+ ::testing::Values(make_tuple(16, &vpx_satd_avx2),
+ make_tuple(64, &vpx_satd_avx2),
+ make_tuple(256, &vpx_satd_avx2),
+ make_tuple(1024, &vpx_satd_avx2)));
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, SatdHighbdTest,
+ ::testing::Values(make_tuple(16, &vpx_highbd_satd_avx2),
+ make_tuple(64, &vpx_highbd_satd_avx2),
+ make_tuple(256, &vpx_highbd_satd_avx2),
+ make_tuple(1024, &vpx_highbd_satd_avx2)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, BlockErrorTestFP,
+ ::testing::Values(make_tuple(16, &vp9_block_error_fp_avx2),
+ make_tuple(64, &vp9_block_error_fp_avx2),
+ make_tuple(256, &vp9_block_error_fp_avx2),
+ make_tuple(1024, &vp9_block_error_fp_avx2)));
+#endif
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, AverageTest,
+ ::testing::Values(make_tuple(16, 16, 0, 8, &vpx_avg_8x8_neon),
+ make_tuple(16, 16, 5, 8, &vpx_avg_8x8_neon),
+ make_tuple(32, 32, 15, 8, &vpx_avg_8x8_neon),
+ make_tuple(16, 16, 0, 4, &vpx_avg_4x4_neon),
+ make_tuple(16, 16, 5, 4, &vpx_avg_4x4_neon),
+ make_tuple(32, 32, 15, 4, &vpx_avg_4x4_neon)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, IntProRowTest,
+ ::testing::Values(make_tuple(16, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
+ make_tuple(32, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
+ make_tuple(64, &vpx_int_pro_row_neon,
+ &vpx_int_pro_row_c)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, IntProColTest,
+ ::testing::Values(make_tuple(16, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
+ make_tuple(32, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
+ make_tuple(64, &vpx_int_pro_col_neon,
+ &vpx_int_pro_col_c)));
+
+INSTANTIATE_TEST_SUITE_P(NEON, SatdLowbdTest,
+ ::testing::Values(make_tuple(16, &vpx_satd_neon),
+ make_tuple(64, &vpx_satd_neon),
+ make_tuple(256, &vpx_satd_neon),
+ make_tuple(1024, &vpx_satd_neon)));
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ NEON, SatdHighbdTest,
+ ::testing::Values(make_tuple(16, &vpx_highbd_satd_neon),
+ make_tuple(64, &vpx_highbd_satd_neon),
+ make_tuple(256, &vpx_highbd_satd_neon),
+ make_tuple(1024, &vpx_highbd_satd_neon)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, BlockErrorTestFP,
+ ::testing::Values(make_tuple(16, &vp9_block_error_fp_neon),
+ make_tuple(64, &vp9_block_error_fp_neon),
+ make_tuple(256, &vp9_block_error_fp_neon),
+ make_tuple(1024, &vp9_block_error_fp_neon)));
+#endif // HAVE_NEON
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, AverageTest,
+ ::testing::Values(make_tuple(16, 16, 0, 8, &vpx_avg_8x8_msa),
+ make_tuple(16, 16, 5, 8, &vpx_avg_8x8_msa),
+ make_tuple(32, 32, 15, 8, &vpx_avg_8x8_msa),
+ make_tuple(16, 16, 0, 4, &vpx_avg_4x4_msa),
+ make_tuple(16, 16, 5, 4, &vpx_avg_4x4_msa),
+ make_tuple(32, 32, 15, 4, &vpx_avg_4x4_msa)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, IntProRowTest,
+ ::testing::Values(make_tuple(16, &vpx_int_pro_row_msa, &vpx_int_pro_row_c),
+ make_tuple(32, &vpx_int_pro_row_msa, &vpx_int_pro_row_c),
+ make_tuple(64, &vpx_int_pro_row_msa,
+ &vpx_int_pro_row_c)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, IntProColTest,
+ ::testing::Values(make_tuple(16, &vpx_int_pro_col_msa, &vpx_int_pro_col_c),
+ make_tuple(32, &vpx_int_pro_col_msa, &vpx_int_pro_col_c),
+ make_tuple(64, &vpx_int_pro_col_msa,
+ &vpx_int_pro_col_c)));
+
+// TODO(jingning): Remove the highbitdepth flag once the SIMD functions are
+// in place.
+#if !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(MSA, SatdLowbdTest,
+ ::testing::Values(make_tuple(16, &vpx_satd_msa),
+ make_tuple(64, &vpx_satd_msa),
+ make_tuple(256, &vpx_satd_msa),
+ make_tuple(1024, &vpx_satd_msa)));
+#endif // !CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_MSA
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/bench.cc b/media/libvpx/libvpx/test/bench.cc
new file mode 100644
index 0000000000..4b883d8250
--- /dev/null
+++ b/media/libvpx/libvpx/test/bench.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 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 <stdio.h>
+#include <algorithm>
+
+#include "test/bench.h"
+#include "vpx_ports/vpx_timer.h"
+
+void AbstractBench::RunNTimes(int n) {
+ for (int r = 0; r < VPX_BENCH_ROBUST_ITER; r++) {
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int j = 0; j < n; ++j) {
+ Run();
+ }
+ vpx_usec_timer_mark(&timer);
+ times_[r] = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ }
+}
+
+void AbstractBench::PrintMedian(const char *title) {
+ std::sort(times_, times_ + VPX_BENCH_ROBUST_ITER);
+ const int med = times_[VPX_BENCH_ROBUST_ITER >> 1];
+ int sad = 0;
+ for (int t = 0; t < VPX_BENCH_ROBUST_ITER; t++) {
+ sad += abs(times_[t] - med);
+ }
+ printf("[%10s] %s %.1f ms ( ±%.1f ms )\n", "BENCH ", title, med / 1000.0,
+ sad / (VPX_BENCH_ROBUST_ITER * 1000.0));
+}
diff --git a/media/libvpx/libvpx/test/bench.h b/media/libvpx/libvpx/test/bench.h
new file mode 100644
index 0000000000..57ca9118ba
--- /dev/null
+++ b/media/libvpx/libvpx/test/bench.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_TEST_BENCH_H_
+#define VPX_TEST_BENCH_H_
+
+// Number of iterations used to compute median run time.
+#define VPX_BENCH_ROBUST_ITER 15
+
+class AbstractBench {
+ public:
+ void RunNTimes(int n);
+ void PrintMedian(const char *title);
+
+ protected:
+ // Implement this method and put the code to benchmark in it.
+ virtual void Run() = 0;
+
+ private:
+ int times_[VPX_BENCH_ROBUST_ITER];
+};
+
+#endif // VPX_TEST_BENCH_H_
diff --git a/media/libvpx/libvpx/test/blockiness_test.cc b/media/libvpx/libvpx/test/blockiness_test.cc
new file mode 100644
index 0000000000..11b2a3f61f
--- /dev/null
+++ b/media/libvpx/libvpx/test/blockiness_test.cc
@@ -0,0 +1,222 @@
+/*
+ * 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 <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if CONFIG_VP9_ENCODER
+#include "./vp9_rtcd.h"
+#endif
+
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+
+#include "vpx_mem/vpx_mem.h"
+#include "vp9/encoder/vp9_blockiness.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+class BlockinessTestBase : public ::testing::Test {
+ public:
+ BlockinessTestBase(int width, int height) : width_(width), height_(height) {}
+
+ static void SetUpTestSuite() {
+ source_data_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ reference_data_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ }
+
+ static void TearDownTestSuite() {
+ vpx_free(source_data_);
+ source_data_ = nullptr;
+ vpx_free(reference_data_);
+ reference_data_ = nullptr;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ // Handle frames up to 640x480
+ static const int kDataAlignment = 16;
+ static const int kDataBufferSize = 640 * 480;
+
+ virtual void SetUp() {
+ source_stride_ = (width_ + 31) & ~31;
+ reference_stride_ = width_ * 2;
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ void FillConstant(uint8_t *data, int stride, uint8_t fill_constant, int width,
+ int height) {
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ data[h * stride + w] = fill_constant;
+ }
+ }
+ }
+
+ void FillConstant(uint8_t *data, int stride, uint8_t fill_constant) {
+ FillConstant(data, stride, fill_constant, width_, height_);
+ }
+
+ void FillRandom(uint8_t *data, int stride, int width, int height) {
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ data[h * stride + w] = rnd_.Rand8();
+ }
+ }
+ }
+
+ void FillRandom(uint8_t *data, int stride) {
+ FillRandom(data, stride, width_, height_);
+ }
+
+ void FillRandomBlocky(uint8_t *data, int stride) {
+ for (int h = 0; h < height_; h += 4) {
+ for (int w = 0; w < width_; w += 4) {
+ FillRandom(data + h * stride + w, stride, 4, 4);
+ }
+ }
+ }
+
+ void FillCheckerboard(uint8_t *data, int stride) {
+ for (int h = 0; h < height_; h += 4) {
+ for (int w = 0; w < width_; w += 4) {
+ if (((h / 4) ^ (w / 4)) & 1) {
+ FillConstant(data + h * stride + w, stride, 255, 4, 4);
+ } else {
+ FillConstant(data + h * stride + w, stride, 0, 4, 4);
+ }
+ }
+ }
+ }
+
+ void Blur(uint8_t *data, int stride, int taps) {
+ int sum = 0;
+ int half_taps = taps / 2;
+ for (int h = 0; h < height_; ++h) {
+ for (int w = 0; w < taps; ++w) {
+ sum += data[w + h * stride];
+ }
+ for (int w = taps; w < width_; ++w) {
+ sum += data[w + h * stride] - data[w - taps + h * stride];
+ data[w - half_taps + h * stride] = (sum + half_taps) / taps;
+ }
+ }
+ for (int w = 0; w < width_; ++w) {
+ for (int h = 0; h < taps; ++h) {
+ sum += data[h + w * stride];
+ }
+ for (int h = taps; h < height_; ++h) {
+ sum += data[w + h * stride] - data[(h - taps) * stride + w];
+ data[(h - half_taps) * stride + w] = (sum + half_taps) / taps;
+ }
+ }
+ }
+ int width_, height_;
+ static uint8_t *source_data_;
+ int source_stride_;
+ static uint8_t *reference_data_;
+ int reference_stride_;
+
+ ACMRandom rnd_;
+};
+
+#if CONFIG_VP9_ENCODER
+typedef std::tuple<int, int> BlockinessParam;
+class BlockinessVP9Test
+ : public BlockinessTestBase,
+ public ::testing::WithParamInterface<BlockinessParam> {
+ public:
+ BlockinessVP9Test() : BlockinessTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+ double GetBlockiness() const {
+ return vp9_get_blockiness(source_data_, source_stride_, reference_data_,
+ reference_stride_, width_, height_);
+ }
+};
+#endif // CONFIG_VP9_ENCODER
+
+uint8_t *BlockinessTestBase::source_data_ = nullptr;
+uint8_t *BlockinessTestBase::reference_data_ = nullptr;
+
+#if CONFIG_VP9_ENCODER
+TEST_P(BlockinessVP9Test, SourceBlockierThanReference) {
+ // Source is blockier than reference.
+ FillRandomBlocky(source_data_, source_stride_);
+ FillConstant(reference_data_, reference_stride_, 128);
+ const double super_blocky = GetBlockiness();
+
+ EXPECT_DOUBLE_EQ(0.0, super_blocky)
+ << "Blocky source should produce 0 blockiness.";
+}
+
+TEST_P(BlockinessVP9Test, ReferenceBlockierThanSource) {
+ // Source is blockier than reference.
+ FillConstant(source_data_, source_stride_, 128);
+ FillRandomBlocky(reference_data_, reference_stride_);
+ const double super_blocky = GetBlockiness();
+
+ EXPECT_GT(super_blocky, 0.0)
+ << "Blocky reference should score high for blockiness.";
+}
+
+TEST_P(BlockinessVP9Test, BlurringDecreasesBlockiness) {
+ // Source is blockier than reference.
+ FillConstant(source_data_, source_stride_, 128);
+ FillRandomBlocky(reference_data_, reference_stride_);
+ const double super_blocky = GetBlockiness();
+
+ Blur(reference_data_, reference_stride_, 4);
+ const double less_blocky = GetBlockiness();
+
+ EXPECT_GT(super_blocky, less_blocky)
+ << "A straight blur should decrease blockiness.";
+}
+
+TEST_P(BlockinessVP9Test, WorstCaseBlockiness) {
+ // Source is blockier than reference.
+ FillConstant(source_data_, source_stride_, 128);
+ FillCheckerboard(reference_data_, reference_stride_);
+
+ const double super_blocky = GetBlockiness();
+
+ Blur(reference_data_, reference_stride_, 4);
+ const double less_blocky = GetBlockiness();
+
+ EXPECT_GT(super_blocky, less_blocky)
+ << "A straight blur should decrease blockiness.";
+}
+#endif // CONFIG_VP9_ENCODER
+
+using std::make_tuple;
+
+//------------------------------------------------------------------------------
+// C functions
+
+#if CONFIG_VP9_ENCODER
+const BlockinessParam c_vp9_tests[] = { make_tuple(320, 240),
+ make_tuple(318, 242),
+ make_tuple(318, 238) };
+INSTANTIATE_TEST_SUITE_P(C, BlockinessVP9Test,
+ ::testing::ValuesIn(c_vp9_tests));
+#endif
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/borders_test.cc b/media/libvpx/libvpx/test/borders_test.cc
new file mode 100644
index 0000000000..3c1f69a923
--- /dev/null
+++ b/media/libvpx/libvpx/test/borders_test.cc
@@ -0,0 +1,84 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class BordersTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ BordersTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~BordersTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, 1);
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+ }
+ }
+};
+
+TEST_P(BordersTest, TestEncodeHighBitrate) {
+ // Validate that this non multiple of 64 wide clip encodes and decodes
+ // without a mismatch when passing in a very low max q. This pushes
+ // the encoder to producing lots of big partitions which will likely
+ // extend into the border and test the border condition.
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 2000;
+ cfg_.rc_max_quantizer = 10;
+
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 40);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+TEST_P(BordersTest, TestLowBitrate) {
+ // Validate that this clip encodes and decodes without a mismatch
+ // when passing in a very high min q. This pushes the encoder to producing
+ // lots of small partitions which might will test the other condition.
+
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 200;
+ cfg_.rc_min_quantizer = 40;
+
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 40);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(BordersTest,
+ ::testing::Values(::libvpx_test::kTwoPassGood));
+} // namespace
diff --git a/media/libvpx/libvpx/test/buffer.h b/media/libvpx/libvpx/test/buffer.h
new file mode 100644
index 0000000000..023939cedf
--- /dev/null
+++ b/media/libvpx/libvpx/test/buffer.h
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2016 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_TEST_BUFFER_H_
+#define VPX_TEST_BUFFER_H_
+
+#include <stdio.h>
+
+#include <limits>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/acm_random.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace libvpx_test {
+
+template <typename T>
+class Buffer {
+ public:
+ Buffer(int width, int height, int top_padding, int left_padding,
+ int right_padding, int bottom_padding)
+ : width_(width), height_(height), top_padding_(top_padding),
+ left_padding_(left_padding), right_padding_(right_padding),
+ bottom_padding_(bottom_padding), alignment_(0), padding_value_(0),
+ stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(nullptr) {}
+
+ Buffer(int width, int height, int top_padding, int left_padding,
+ int right_padding, int bottom_padding, unsigned int alignment)
+ : width_(width), height_(height), top_padding_(top_padding),
+ left_padding_(left_padding), right_padding_(right_padding),
+ bottom_padding_(bottom_padding), alignment_(alignment),
+ padding_value_(0), stride_(0), raw_size_(0), num_elements_(0),
+ raw_buffer_(nullptr) {}
+
+ Buffer(int width, int height, int padding)
+ : width_(width), height_(height), top_padding_(padding),
+ left_padding_(padding), right_padding_(padding),
+ bottom_padding_(padding), alignment_(0), padding_value_(0), stride_(0),
+ raw_size_(0), num_elements_(0), raw_buffer_(nullptr) {}
+
+ Buffer(int width, int height, int padding, unsigned int alignment)
+ : width_(width), height_(height), top_padding_(padding),
+ left_padding_(padding), right_padding_(padding),
+ bottom_padding_(padding), alignment_(alignment), padding_value_(0),
+ stride_(0), raw_size_(0), num_elements_(0), raw_buffer_(nullptr) {}
+
+ ~Buffer() {
+ if (alignment_) {
+ vpx_free(raw_buffer_);
+ } else {
+ delete[] raw_buffer_;
+ }
+ }
+
+ T *TopLeftPixel() const;
+
+ int stride() const { return stride_; }
+
+ // Set the buffer (excluding padding) to 'value'.
+ void Set(const T value);
+
+ // Set the buffer (excluding padding) to the output of ACMRandom function
+ // 'rand_func'.
+ void Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)());
+
+ // Set the buffer (excluding padding) to the output of ACMRandom function
+ // 'RandRange' with range 'low' to 'high' which typically must be within
+ // testing::internal::Random::kMaxRange (1u << 31). However, because we want
+ // to allow negative low (and high) values, it is restricted to INT32_MAX
+ // here.
+ void Set(ACMRandom *rand_class, const T low, const T high);
+
+ // Copy the contents of Buffer 'a' (excluding padding).
+ void CopyFrom(const Buffer<T> &a);
+
+ void DumpBuffer() const;
+
+ // Highlight the differences between two buffers if they are the same size.
+ void PrintDifference(const Buffer<T> &a) const;
+
+ bool HasPadding() const;
+
+ // Sets all the values in the buffer to 'padding_value'.
+ void SetPadding(const T padding_value);
+
+ // Checks if all the values (excluding padding) are equal to 'value' if the
+ // Buffers are the same size.
+ bool CheckValues(const T value) const;
+
+ // Check that padding matches the expected value or there is no padding.
+ bool CheckPadding() const;
+
+ // Compare the non-padding portion of two buffers if they are the same size.
+ bool CheckValues(const Buffer<T> &a) const;
+
+ bool Init() {
+ if (raw_buffer_ != nullptr) return false;
+ EXPECT_GT(width_, 0);
+ EXPECT_GT(height_, 0);
+ EXPECT_GE(top_padding_, 0);
+ EXPECT_GE(left_padding_, 0);
+ EXPECT_GE(right_padding_, 0);
+ EXPECT_GE(bottom_padding_, 0);
+ stride_ = left_padding_ + width_ + right_padding_;
+ num_elements_ = stride_ * (top_padding_ + height_ + bottom_padding_);
+ raw_size_ = num_elements_ * sizeof(T);
+ if (alignment_) {
+ EXPECT_GE(alignment_, sizeof(T));
+ // Ensure alignment of the first value will be preserved.
+ EXPECT_EQ((left_padding_ * sizeof(T)) % alignment_, 0u);
+ // Ensure alignment of the subsequent rows will be preserved when there is
+ // a stride.
+ if (stride_ != width_) {
+ EXPECT_EQ((stride_ * sizeof(T)) % alignment_, 0u);
+ }
+ raw_buffer_ = reinterpret_cast<T *>(vpx_memalign(alignment_, raw_size_));
+ } else {
+ raw_buffer_ = new (std::nothrow) T[num_elements_];
+ }
+ EXPECT_NE(raw_buffer_, nullptr);
+ SetPadding(std::numeric_limits<T>::max());
+ return !::testing::Test::HasFailure();
+ }
+
+ private:
+ bool BufferSizesMatch(const Buffer<T> &a) const;
+
+ const int width_;
+ const int height_;
+ const int top_padding_;
+ const int left_padding_;
+ const int right_padding_;
+ const int bottom_padding_;
+ const unsigned int alignment_;
+ T padding_value_;
+ int stride_;
+ int raw_size_;
+ int num_elements_;
+ T *raw_buffer_;
+};
+
+template <typename T>
+T *Buffer<T>::TopLeftPixel() const {
+ if (!raw_buffer_) return nullptr;
+ return raw_buffer_ + (top_padding_ * stride_) + left_padding_;
+}
+
+template <typename T>
+void Buffer<T>::Set(const T value) {
+ if (!raw_buffer_) return;
+ T *src = TopLeftPixel();
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ src[width] = value;
+ }
+ src += stride_;
+ }
+}
+
+template <typename T>
+void Buffer<T>::Set(ACMRandom *rand_class, T (ACMRandom::*rand_func)()) {
+ if (!raw_buffer_) return;
+ T *src = TopLeftPixel();
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ src[width] = (*rand_class.*rand_func)();
+ }
+ src += stride_;
+ }
+}
+
+template <typename T>
+void Buffer<T>::Set(ACMRandom *rand_class, const T low, const T high) {
+ if (!raw_buffer_) return;
+
+ EXPECT_LE(low, high);
+ EXPECT_LE(static_cast<int64_t>(high) - low,
+ std::numeric_limits<int32_t>::max());
+
+ T *src = TopLeftPixel();
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ // 'low' will be promoted to unsigned given the return type of RandRange.
+ // Store the value as an int to avoid unsigned overflow warnings when
+ // 'low' is negative.
+ const int32_t value =
+ static_cast<int32_t>((*rand_class).RandRange(high - low));
+ src[width] = static_cast<T>(value + low);
+ }
+ src += stride_;
+ }
+}
+
+template <typename T>
+void Buffer<T>::CopyFrom(const Buffer<T> &a) {
+ if (!raw_buffer_) return;
+ if (!BufferSizesMatch(a)) return;
+
+ T *a_src = a.TopLeftPixel();
+ T *b_src = this->TopLeftPixel();
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ b_src[width] = a_src[width];
+ }
+ a_src += a.stride();
+ b_src += this->stride();
+ }
+}
+
+template <typename T>
+void Buffer<T>::DumpBuffer() const {
+ if (!raw_buffer_) return;
+ for (int height = 0; height < height_ + top_padding_ + bottom_padding_;
+ ++height) {
+ for (int width = 0; width < stride_; ++width) {
+ printf("%4d", raw_buffer_[height + width * stride_]);
+ }
+ printf("\n");
+ }
+}
+
+template <typename T>
+bool Buffer<T>::HasPadding() const {
+ if (!raw_buffer_) return false;
+ return top_padding_ || left_padding_ || right_padding_ || bottom_padding_;
+}
+
+template <typename T>
+void Buffer<T>::PrintDifference(const Buffer<T> &a) const {
+ if (!raw_buffer_) return;
+ if (!BufferSizesMatch(a)) return;
+
+ T *a_src = a.TopLeftPixel();
+ T *b_src = TopLeftPixel();
+
+ printf("This buffer:\n");
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ if (a_src[width] != b_src[width]) {
+ printf("*%3d", b_src[width]);
+ } else {
+ printf("%4d", b_src[width]);
+ }
+ }
+ printf("\n");
+ a_src += a.stride();
+ b_src += this->stride();
+ }
+
+ a_src = a.TopLeftPixel();
+ b_src = TopLeftPixel();
+
+ printf("Reference buffer:\n");
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ if (a_src[width] != b_src[width]) {
+ printf("*%3d", a_src[width]);
+ } else {
+ printf("%4d", a_src[width]);
+ }
+ }
+ printf("\n");
+ a_src += a.stride();
+ b_src += this->stride();
+ }
+}
+
+template <typename T>
+void Buffer<T>::SetPadding(const T padding_value) {
+ if (!raw_buffer_) return;
+ padding_value_ = padding_value;
+
+ T *src = raw_buffer_;
+ for (int i = 0; i < num_elements_; ++i) {
+ src[i] = padding_value;
+ }
+}
+
+template <typename T>
+bool Buffer<T>::CheckValues(const T value) const {
+ if (!raw_buffer_) return false;
+ T *src = TopLeftPixel();
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ if (value != src[width]) {
+ return false;
+ }
+ }
+ src += stride_;
+ }
+ return true;
+}
+
+template <typename T>
+bool Buffer<T>::CheckPadding() const {
+ if (!raw_buffer_) return false;
+ if (!HasPadding()) return true;
+
+ // Top padding.
+ T const *top = raw_buffer_;
+ for (int i = 0; i < stride_ * top_padding_; ++i) {
+ if (padding_value_ != top[i]) {
+ return false;
+ }
+ }
+
+ // Left padding.
+ T const *left = TopLeftPixel() - left_padding_;
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < left_padding_; ++width) {
+ if (padding_value_ != left[width]) {
+ return false;
+ }
+ }
+ left += stride_;
+ }
+
+ // Right padding.
+ T const *right = TopLeftPixel() + width_;
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < right_padding_; ++width) {
+ if (padding_value_ != right[width]) {
+ return false;
+ }
+ }
+ right += stride_;
+ }
+
+ // Bottom padding
+ T const *bottom = raw_buffer_ + (top_padding_ + height_) * stride_;
+ for (int i = 0; i < stride_ * bottom_padding_; ++i) {
+ if (padding_value_ != bottom[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <typename T>
+bool Buffer<T>::CheckValues(const Buffer<T> &a) const {
+ if (!raw_buffer_) return false;
+ if (!BufferSizesMatch(a)) return false;
+
+ T *a_src = a.TopLeftPixel();
+ T *b_src = this->TopLeftPixel();
+ for (int height = 0; height < height_; ++height) {
+ for (int width = 0; width < width_; ++width) {
+ if (a_src[width] != b_src[width]) {
+ return false;
+ }
+ }
+ a_src += a.stride();
+ b_src += this->stride();
+ }
+ return true;
+}
+
+template <typename T>
+bool Buffer<T>::BufferSizesMatch(const Buffer<T> &a) const {
+ if (!raw_buffer_) return false;
+ if (a.width_ != this->width_ || a.height_ != this->height_) {
+ printf(
+ "Reference buffer of size %dx%d does not match this buffer which is "
+ "size %dx%d\n",
+ a.width_, a.height_, this->width_, this->height_);
+ return false;
+ }
+
+ return true;
+}
+} // namespace libvpx_test
+#endif // VPX_TEST_BUFFER_H_
diff --git a/media/libvpx/libvpx/test/byte_alignment_test.cc b/media/libvpx/libvpx/test/byte_alignment_test.cc
new file mode 100644
index 0000000000..1e0ffceb8d
--- /dev/null
+++ b/media/libvpx/libvpx/test/byte_alignment_test.cc
@@ -0,0 +1,185 @@
+/*
+ * 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 <string>
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+
+namespace {
+
+#if CONFIG_WEBM_IO
+
+const int kLegacyByteAlignment = 0;
+const int kLegacyYPlaneByteAlignment = 32;
+const int kNumPlanesToCheck = 3;
+const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
+const char kVP9Md5File[] = "vp90-2-02-size-lf-1920x1080.webm.md5";
+
+struct ByteAlignmentTestParam {
+ int byte_alignment;
+ vpx_codec_err_t expected_value;
+ bool decode_remaining;
+};
+
+const ByteAlignmentTestParam kBaTestParams[] = {
+ { kLegacyByteAlignment, VPX_CODEC_OK, true },
+ { 32, VPX_CODEC_OK, true },
+ { 64, VPX_CODEC_OK, true },
+ { 128, VPX_CODEC_OK, true },
+ { 256, VPX_CODEC_OK, true },
+ { 512, VPX_CODEC_OK, true },
+ { 1024, VPX_CODEC_OK, true },
+ { 1, VPX_CODEC_INVALID_PARAM, false },
+ { -2, VPX_CODEC_INVALID_PARAM, false },
+ { 4, VPX_CODEC_INVALID_PARAM, false },
+ { 16, VPX_CODEC_INVALID_PARAM, false },
+ { 255, VPX_CODEC_INVALID_PARAM, false },
+ { 2048, VPX_CODEC_INVALID_PARAM, false },
+};
+
+// Class for testing byte alignment of reference buffers.
+class ByteAlignmentTest
+ : public ::testing::TestWithParam<ByteAlignmentTestParam> {
+ protected:
+ ByteAlignmentTest()
+ : video_(nullptr), decoder_(nullptr), md5_file_(nullptr) {}
+
+ virtual void SetUp() {
+ video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
+ ASSERT_NE(video_, nullptr);
+ video_->Init();
+ video_->Begin();
+
+ const vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+ ASSERT_NE(decoder_, nullptr);
+
+ OpenMd5File(kVP9Md5File);
+ }
+
+ virtual void TearDown() {
+ if (md5_file_ != nullptr) fclose(md5_file_);
+
+ delete decoder_;
+ delete video_;
+ }
+
+ void SetByteAlignment(int byte_alignment, vpx_codec_err_t expected_value) {
+ decoder_->Control(VP9_SET_BYTE_ALIGNMENT, byte_alignment, expected_value);
+ }
+
+ vpx_codec_err_t DecodeOneFrame(int byte_alignment_to_check) {
+ const vpx_codec_err_t res =
+ decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+ CheckDecodedFrames(byte_alignment_to_check);
+ if (res == VPX_CODEC_OK) video_->Next();
+ return res;
+ }
+
+ vpx_codec_err_t DecodeRemainingFrames(int byte_alignment_to_check) {
+ for (; video_->cxdata() != nullptr; video_->Next()) {
+ const vpx_codec_err_t res =
+ decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+ if (res != VPX_CODEC_OK) return res;
+ CheckDecodedFrames(byte_alignment_to_check);
+ }
+ return VPX_CODEC_OK;
+ }
+
+ private:
+ // Check if |data| is aligned to |byte_alignment_to_check|.
+ // |byte_alignment_to_check| must be a power of 2.
+ void CheckByteAlignment(const uint8_t *data, int byte_alignment_to_check) {
+ ASSERT_EQ(0u, reinterpret_cast<size_t>(data) % byte_alignment_to_check);
+ }
+
+ // Iterate through the planes of the decoded frames and check for
+ // alignment based off |byte_alignment_to_check|.
+ void CheckDecodedFrames(int byte_alignment_to_check) {
+ libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
+ const vpx_image_t *img;
+
+ // Get decompressed data
+ while ((img = dec_iter.Next()) != nullptr) {
+ if (byte_alignment_to_check == kLegacyByteAlignment) {
+ CheckByteAlignment(img->planes[0], kLegacyYPlaneByteAlignment);
+ } else {
+ for (int i = 0; i < kNumPlanesToCheck; ++i) {
+ CheckByteAlignment(img->planes[i], byte_alignment_to_check);
+ }
+ }
+ CheckMd5(*img);
+ }
+ }
+
+ // TODO(fgalligan): Move the MD5 testing code into another class.
+ void OpenMd5File(const std::string &md5_file_name_) {
+ md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+ ASSERT_NE(md5_file_, nullptr)
+ << "MD5 file open failed. Filename: " << md5_file_name_;
+ }
+
+ void CheckMd5(const vpx_image_t &img) {
+ ASSERT_NE(md5_file_, nullptr);
+ char expected_md5[33];
+ char junk[128];
+
+ // Read correct md5 checksums.
+ const int res = fscanf(md5_file_, "%s %s", expected_md5, junk);
+ ASSERT_NE(EOF, res) << "Read md5 data failed";
+ expected_md5[32] = '\0';
+
+ ::libvpx_test::MD5 md5_res;
+ md5_res.Add(&img);
+ const char *const actual_md5 = md5_res.Get();
+
+ // Check md5 match.
+ ASSERT_STREQ(expected_md5, actual_md5) << "MD5 checksums don't match";
+ }
+
+ libvpx_test::WebMVideoSource *video_;
+ libvpx_test::VP9Decoder *decoder_;
+ FILE *md5_file_;
+};
+
+TEST_F(ByteAlignmentTest, SwitchByteAlignment) {
+ const int num_elements = 14;
+ const int byte_alignments[] = { 0, 32, 64, 128, 256, 512, 1024,
+ 0, 1024, 32, 512, 64, 256, 128 };
+
+ for (int i = 0; i < num_elements; ++i) {
+ SetByteAlignment(byte_alignments[i], VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame(byte_alignments[i]));
+ }
+ SetByteAlignment(byte_alignments[0], VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(byte_alignments[0]));
+}
+
+TEST_P(ByteAlignmentTest, TestAlignment) {
+ const ByteAlignmentTestParam t = GetParam();
+ SetByteAlignment(t.byte_alignment, t.expected_value);
+ if (t.decode_remaining) {
+ ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(t.byte_alignment));
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(Alignments, ByteAlignmentTest,
+ ::testing::ValuesIn(kBaTestParams));
+
+#endif // CONFIG_WEBM_IO
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/clear_system_state.h b/media/libvpx/libvpx/test/clear_system_state.h
new file mode 100644
index 0000000000..ba3c0b386a
--- /dev/null
+++ b/media/libvpx/libvpx/test/clear_system_state.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+#ifndef VPX_TEST_CLEAR_SYSTEM_STATE_H_
+#define VPX_TEST_CLEAR_SYSTEM_STATE_H_
+
+#include "./vpx_config.h"
+#include "vpx_ports/system_state.h"
+
+namespace libvpx_test {
+
+// Reset system to a known state. This function should be used for all non-API
+// test cases.
+inline void ClearSystemState() { vpx_clear_system_state(); }
+
+} // namespace libvpx_test
+#endif // VPX_TEST_CLEAR_SYSTEM_STATE_H_
diff --git a/media/libvpx/libvpx/test/codec_factory.h b/media/libvpx/libvpx/test/codec_factory.h
new file mode 100644
index 0000000000..96092610c6
--- /dev/null
+++ b/media/libvpx/libvpx/test/codec_factory.h
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ */
+#ifndef VPX_TEST_CODEC_FACTORY_H_
+#define VPX_TEST_CODEC_FACTORY_H_
+
+#include <tuple>
+
+#include "./vpx_config.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx/vpx_encoder.h"
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
+#include "vpx/vp8dx.h"
+#endif
+
+#include "test/decode_test_driver.h"
+#include "test/encode_test_driver.h"
+namespace libvpx_test {
+
+const int kCodecFactoryParam = 0;
+
+class CodecFactory {
+ public:
+ CodecFactory() {}
+
+ virtual ~CodecFactory() {}
+
+ virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg) const = 0;
+
+ virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg,
+ const vpx_codec_flags_t flags) const = 0;
+
+ virtual Encoder *CreateEncoder(vpx_codec_enc_cfg_t cfg,
+ unsigned long deadline,
+ const unsigned long init_flags,
+ TwopassStatsStore *stats) const = 0;
+
+ virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+ int usage) const = 0;
+};
+
+/* Provide CodecTestWith<n>Params classes for a variable number of parameters
+ * to avoid having to include a pointer to the CodecFactory in every test
+ * definition.
+ */
+template <class T1>
+class CodecTestWithParam
+ : public ::testing::TestWithParam<
+ std::tuple<const libvpx_test::CodecFactory *, T1> > {};
+
+template <class T1, class T2>
+class CodecTestWith2Params
+ : public ::testing::TestWithParam<
+ std::tuple<const libvpx_test::CodecFactory *, T1, T2> > {};
+
+template <class T1, class T2, class T3>
+class CodecTestWith3Params
+ : public ::testing::TestWithParam<
+ std::tuple<const libvpx_test::CodecFactory *, T1, T2, T3> > {};
+
+template <class T1, class T2, class T3, class T4>
+class CodecTestWith4Params
+ : public ::testing::TestWithParam<
+ std::tuple<const libvpx_test::CodecFactory *, T1, T2, T3, T4> > {};
+
+/*
+ * VP8 Codec Definitions
+ */
+#if CONFIG_VP8
+class VP8Decoder : public Decoder {
+ public:
+ explicit VP8Decoder(vpx_codec_dec_cfg_t cfg) : Decoder(cfg) {}
+
+ VP8Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag)
+ : Decoder(cfg, flag) {}
+
+ protected:
+ virtual vpx_codec_iface_t *CodecInterface() const {
+#if CONFIG_VP8_DECODER
+ return &vpx_codec_vp8_dx_algo;
+#else
+ return nullptr;
+#endif
+ }
+};
+
+class VP8Encoder : public Encoder {
+ public:
+ VP8Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+ const unsigned long init_flags, TwopassStatsStore *stats)
+ : Encoder(cfg, deadline, init_flags, stats) {}
+
+ protected:
+ virtual vpx_codec_iface_t *CodecInterface() const {
+#if CONFIG_VP8_ENCODER
+ return &vpx_codec_vp8_cx_algo;
+#else
+ return nullptr;
+#endif
+ }
+};
+
+class VP8CodecFactory : public CodecFactory {
+ public:
+ VP8CodecFactory() : CodecFactory() {}
+
+ virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg) const {
+ return CreateDecoder(cfg, 0);
+ }
+
+ virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg,
+ const vpx_codec_flags_t flags) const {
+#if CONFIG_VP8_DECODER
+ return new VP8Decoder(cfg, flags);
+#else
+ (void)cfg;
+ (void)flags;
+ return nullptr;
+#endif
+ }
+
+ virtual Encoder *CreateEncoder(vpx_codec_enc_cfg_t cfg,
+ unsigned long deadline,
+ const unsigned long init_flags,
+ TwopassStatsStore *stats) const {
+#if CONFIG_VP8_ENCODER
+ return new VP8Encoder(cfg, deadline, init_flags, stats);
+#else
+ (void)cfg;
+ (void)deadline;
+ (void)init_flags;
+ (void)stats;
+ return nullptr;
+#endif
+ }
+
+ virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+ int usage) const {
+#if CONFIG_VP8_ENCODER
+ return vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, cfg, usage);
+#else
+ (void)cfg;
+ (void)usage;
+ return VPX_CODEC_INCAPABLE;
+#endif
+ }
+};
+
+const libvpx_test::VP8CodecFactory kVP8;
+
+#define VP8_INSTANTIATE_TEST_SUITE(test, ...) \
+ INSTANTIATE_TEST_SUITE_P( \
+ VP8, test, \
+ ::testing::Combine( \
+ ::testing::Values(static_cast<const libvpx_test::CodecFactory *>( \
+ &libvpx_test::kVP8)), \
+ __VA_ARGS__))
+#else
+#define VP8_INSTANTIATE_TEST_SUITE(test, ...)
+#endif // CONFIG_VP8
+
+/*
+ * VP9 Codec Definitions
+ */
+#if CONFIG_VP9
+class VP9Decoder : public Decoder {
+ public:
+ explicit VP9Decoder(vpx_codec_dec_cfg_t cfg) : Decoder(cfg) {}
+
+ VP9Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag)
+ : Decoder(cfg, flag) {}
+
+ protected:
+ virtual vpx_codec_iface_t *CodecInterface() const {
+#if CONFIG_VP9_DECODER
+ return &vpx_codec_vp9_dx_algo;
+#else
+ return nullptr;
+#endif
+ }
+};
+
+class VP9Encoder : public Encoder {
+ public:
+ VP9Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+ const unsigned long init_flags, TwopassStatsStore *stats)
+ : Encoder(cfg, deadline, init_flags, stats) {}
+
+ protected:
+ virtual vpx_codec_iface_t *CodecInterface() const {
+#if CONFIG_VP9_ENCODER
+ return &vpx_codec_vp9_cx_algo;
+#else
+ return nullptr;
+#endif
+ }
+};
+
+class VP9CodecFactory : public CodecFactory {
+ public:
+ VP9CodecFactory() : CodecFactory() {}
+
+ virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg) const {
+ return CreateDecoder(cfg, 0);
+ }
+
+ virtual Decoder *CreateDecoder(vpx_codec_dec_cfg_t cfg,
+ const vpx_codec_flags_t flags) const {
+#if CONFIG_VP9_DECODER
+ return new VP9Decoder(cfg, flags);
+#else
+ (void)cfg;
+ (void)flags;
+ return nullptr;
+#endif
+ }
+
+ virtual Encoder *CreateEncoder(vpx_codec_enc_cfg_t cfg,
+ unsigned long deadline,
+ const unsigned long init_flags,
+ TwopassStatsStore *stats) const {
+#if CONFIG_VP9_ENCODER
+ return new VP9Encoder(cfg, deadline, init_flags, stats);
+#else
+ (void)cfg;
+ (void)deadline;
+ (void)init_flags;
+ (void)stats;
+ return nullptr;
+#endif
+ }
+
+ virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+ int usage) const {
+#if CONFIG_VP9_ENCODER
+ return vpx_codec_enc_config_default(&vpx_codec_vp9_cx_algo, cfg, usage);
+#else
+ (void)cfg;
+ (void)usage;
+ return VPX_CODEC_INCAPABLE;
+#endif
+ }
+};
+
+const libvpx_test::VP9CodecFactory kVP9;
+
+#define VP9_INSTANTIATE_TEST_SUITE(test, ...) \
+ INSTANTIATE_TEST_SUITE_P( \
+ VP9, test, \
+ ::testing::Combine( \
+ ::testing::Values(static_cast<const libvpx_test::CodecFactory *>( \
+ &libvpx_test::kVP9)), \
+ __VA_ARGS__))
+#else
+#define VP9_INSTANTIATE_TEST_SUITE(test, ...)
+#endif // CONFIG_VP9
+
+} // namespace libvpx_test
+#endif // VPX_TEST_CODEC_FACTORY_H_
diff --git a/media/libvpx/libvpx/test/comp_avg_pred_test.cc b/media/libvpx/libvpx/test/comp_avg_pred_test.cc
new file mode 100644
index 0000000000..f747c3524e
--- /dev/null
+++ b/media/libvpx/libvpx/test/comp_avg_pred_test.cc
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2017 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"
+
+#include "./vpx_dsp_rtcd.h"
+
+#include "test/acm_random.h"
+#include "test/buffer.h"
+#include "test/register_state_check.h"
+#include "vpx_ports/vpx_timer.h"
+
+namespace {
+
+using ::libvpx_test::ACMRandom;
+using ::libvpx_test::Buffer;
+
+template <typename Pixel>
+Pixel avg_with_rounding(Pixel a, Pixel b) {
+ return (a + b + 1) >> 1;
+}
+
+template <typename Pixel>
+void reference_pred(const Buffer<Pixel> &pred, const Buffer<Pixel> &ref,
+ int width, int height, Buffer<Pixel> *avg) {
+ ASSERT_NE(avg->TopLeftPixel(), nullptr);
+ ASSERT_NE(pred.TopLeftPixel(), nullptr);
+ ASSERT_NE(ref.TopLeftPixel(), nullptr);
+
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ avg->TopLeftPixel()[y * avg->stride() + x] =
+ avg_with_rounding<Pixel>(pred.TopLeftPixel()[y * pred.stride() + x],
+ ref.TopLeftPixel()[y * ref.stride() + x]);
+ }
+ }
+}
+
+using AvgPredFunc = void (*)(uint8_t *a, const uint8_t *b, int w, int h,
+ const uint8_t *c, int c_stride);
+
+template <int bitdepth, typename Pixel>
+class AvgPredTest : public ::testing::TestWithParam<AvgPredFunc> {
+ public:
+ virtual void SetUp() {
+ avg_pred_func_ = GetParam();
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ void TestSizeCombinations();
+ void TestCompareReferenceRandom();
+ void TestSpeed();
+
+ protected:
+ AvgPredFunc avg_pred_func_;
+ ACMRandom rnd_;
+};
+
+template <int bitdepth, typename Pixel>
+void AvgPredTest<bitdepth, Pixel>::TestSizeCombinations() {
+ // This is called as part of the sub pixel variance. As such it must be one of
+ // the variance block sizes.
+ for (int width_pow = 2; width_pow <= 6; ++width_pow) {
+ for (int height_pow = width_pow - 1; height_pow <= width_pow + 1;
+ ++height_pow) {
+ // Don't test 4x2 or 64x128
+ if (height_pow == 1 || height_pow == 7) continue;
+
+ // The sse2 special-cases when ref width == stride, so make sure to test
+ // it.
+ for (int ref_padding = 0; ref_padding < 2; ref_padding++) {
+ const int width = 1 << width_pow;
+ const int height = 1 << height_pow;
+ // Only the reference buffer may have a stride not equal to width.
+ Buffer<Pixel> ref = Buffer<Pixel>(width, height, ref_padding ? 8 : 0);
+ ASSERT_TRUE(ref.Init());
+ Buffer<Pixel> pred = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(pred.Init());
+ Buffer<Pixel> avg_ref = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(avg_ref.Init());
+ Buffer<Pixel> avg_chk = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(avg_chk.Init());
+ const int bitdepth_mask = (1 << bitdepth) - 1;
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ ref.TopLeftPixel()[w + h * width] = rnd_.Rand16() & bitdepth_mask;
+ }
+ }
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ pred.TopLeftPixel()[w + h * width] = rnd_.Rand16() & bitdepth_mask;
+ }
+ }
+
+ reference_pred<Pixel>(pred, ref, width, height, &avg_ref);
+ ASM_REGISTER_STATE_CHECK(avg_pred_func_(
+ (uint8_t *)avg_chk.TopLeftPixel(), (uint8_t *)pred.TopLeftPixel(),
+ width, height, (uint8_t *)ref.TopLeftPixel(), ref.stride()));
+
+ EXPECT_TRUE(avg_chk.CheckValues(avg_ref));
+ if (HasFailure()) {
+ printf("Width: %d Height: %d\n", width, height);
+ avg_chk.PrintDifference(avg_ref);
+ return;
+ }
+ }
+ }
+ }
+}
+
+template <int bitdepth, typename Pixel>
+void AvgPredTest<bitdepth, Pixel>::TestCompareReferenceRandom() {
+ const int width = 64;
+ const int height = 32;
+ Buffer<Pixel> ref = Buffer<Pixel>(width, height, 8);
+ ASSERT_TRUE(ref.Init());
+ Buffer<Pixel> pred = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(pred.Init());
+ Buffer<Pixel> avg_ref = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(avg_ref.Init());
+ Buffer<Pixel> avg_chk = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(avg_chk.Init());
+
+ for (int i = 0; i < 500; ++i) {
+ const int bitdepth_mask = (1 << bitdepth) - 1;
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ ref.TopLeftPixel()[w + h * width] = rnd_.Rand16() & bitdepth_mask;
+ }
+ }
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ pred.TopLeftPixel()[w + h * width] = rnd_.Rand16() & bitdepth_mask;
+ }
+ }
+
+ reference_pred<Pixel>(pred, ref, width, height, &avg_ref);
+ ASM_REGISTER_STATE_CHECK(avg_pred_func_(
+ (uint8_t *)avg_chk.TopLeftPixel(), (uint8_t *)pred.TopLeftPixel(),
+ width, height, (uint8_t *)ref.TopLeftPixel(), ref.stride()));
+ EXPECT_TRUE(avg_chk.CheckValues(avg_ref));
+ if (HasFailure()) {
+ printf("Width: %d Height: %d\n", width, height);
+ avg_chk.PrintDifference(avg_ref);
+ return;
+ }
+ }
+}
+
+template <int bitdepth, typename Pixel>
+void AvgPredTest<bitdepth, Pixel>::TestSpeed() {
+ for (int width_pow = 2; width_pow <= 6; ++width_pow) {
+ for (int height_pow = width_pow - 1; height_pow <= width_pow + 1;
+ ++height_pow) {
+ // Don't test 4x2 or 64x128
+ if (height_pow == 1 || height_pow == 7) continue;
+
+ for (int ref_padding = 0; ref_padding < 2; ref_padding++) {
+ const int width = 1 << width_pow;
+ const int height = 1 << height_pow;
+ Buffer<Pixel> ref = Buffer<Pixel>(width, height, ref_padding ? 8 : 0);
+ ASSERT_TRUE(ref.Init());
+ Buffer<Pixel> pred = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(pred.Init());
+ Buffer<Pixel> avg = Buffer<Pixel>(width, height, 0, 16);
+ ASSERT_TRUE(avg.Init());
+ const int bitdepth_mask = (1 << bitdepth) - 1;
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ ref.TopLeftPixel()[w + h * width] = rnd_.Rand16() & bitdepth_mask;
+ }
+ }
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ pred.TopLeftPixel()[w + h * width] = rnd_.Rand16() & bitdepth_mask;
+ }
+ }
+
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < 100000000 / (width * height); ++i) {
+ avg_pred_func_((uint8_t *)avg.TopLeftPixel(),
+ (uint8_t *)pred.TopLeftPixel(), width, height,
+ (uint8_t *)ref.TopLeftPixel(), ref.stride());
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("Average Test (ref_padding: %d) %dx%d time: %5d us\n",
+ ref_padding, width, height, elapsed_time);
+ }
+ }
+ }
+}
+
+using AvgPredTestLBD = AvgPredTest<8, uint8_t>;
+
+TEST_P(AvgPredTestLBD, SizeCombinations) { TestSizeCombinations(); }
+
+TEST_P(AvgPredTestLBD, CompareReferenceRandom) { TestCompareReferenceRandom(); }
+
+TEST_P(AvgPredTestLBD, DISABLED_Speed) { TestSpeed(); }
+
+INSTANTIATE_TEST_SUITE_P(C, AvgPredTestLBD,
+ ::testing::Values(&vpx_comp_avg_pred_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(SSE2, AvgPredTestLBD,
+ ::testing::Values(&vpx_comp_avg_pred_sse2));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, AvgPredTestLBD,
+ ::testing::Values(&vpx_comp_avg_pred_neon));
+#endif // HAVE_NEON
+
+#if HAVE_VSX
+INSTANTIATE_TEST_SUITE_P(VSX, AvgPredTestLBD,
+ ::testing::Values(&vpx_comp_avg_pred_vsx));
+#endif // HAVE_VSX
+
+#if HAVE_LSX
+INSTANTIATE_TEST_SUITE_P(LSX, AvgPredTestLBD,
+ ::testing::Values(&vpx_comp_avg_pred_lsx));
+#endif // HAVE_LSX
+
+#if CONFIG_VP9_HIGHBITDEPTH
+using HighbdAvgPredFunc = void (*)(uint16_t *a, const uint16_t *b, int w, int h,
+ const uint16_t *c, int c_stride);
+
+template <HighbdAvgPredFunc fn>
+void highbd_wrapper(uint8_t *a, const uint8_t *b, int w, int h,
+ const uint8_t *c, int c_stride) {
+ fn((uint16_t *)a, (const uint16_t *)b, w, h, (const uint16_t *)c, c_stride);
+}
+
+using AvgPredTestHBD = AvgPredTest<12, uint16_t>;
+
+TEST_P(AvgPredTestHBD, SizeCombinations) { TestSizeCombinations(); }
+
+TEST_P(AvgPredTestHBD, CompareReferenceRandom) { TestCompareReferenceRandom(); }
+
+TEST_P(AvgPredTestHBD, DISABLED_Speed) { TestSpeed(); }
+
+INSTANTIATE_TEST_SUITE_P(
+ C, AvgPredTestHBD,
+ ::testing::Values(&highbd_wrapper<vpx_highbd_comp_avg_pred_c>));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, AvgPredTestHBD,
+ ::testing::Values(&highbd_wrapper<vpx_highbd_comp_avg_pred_sse2>));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, AvgPredTestHBD,
+ ::testing::Values(&highbd_wrapper<vpx_highbd_comp_avg_pred_neon>));
+#endif // HAVE_NEON
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+} // namespace
diff --git a/media/libvpx/libvpx/test/config_test.cc b/media/libvpx/libvpx/test/config_test.cc
new file mode 100644
index 0000000000..8f4c60e113
--- /dev/null
+++ b/media/libvpx/libvpx/test/config_test.cc
@@ -0,0 +1,62 @@
+/*
+ * 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"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/video_source.h"
+
+namespace {
+
+class ConfigTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ ConfigTest()
+ : EncoderTest(GET_PARAM(0)), frame_count_in_(0), frame_count_out_(0),
+ frame_count_max_(0) {}
+ virtual ~ConfigTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ frame_count_in_ = 0;
+ frame_count_out_ = 0;
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource * /*video*/) {
+ ++frame_count_in_;
+ abort_ |= (frame_count_in_ >= frame_count_max_);
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {
+ ++frame_count_out_;
+ }
+
+ unsigned int frame_count_in_;
+ unsigned int frame_count_out_;
+ unsigned int frame_count_max_;
+};
+
+TEST_P(ConfigTest, LagIsDisabled) {
+ frame_count_max_ = 2;
+ cfg_.g_lag_in_frames = 15;
+
+ libvpx_test::DummyVideoSource video;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ EXPECT_EQ(frame_count_in_, frame_count_out_);
+}
+
+VP8_INSTANTIATE_TEST_SUITE(ConfigTest, ONE_PASS_TEST_MODES);
+} // namespace
diff --git a/media/libvpx/libvpx/test/consistency_test.cc b/media/libvpx/libvpx/test/consistency_test.cc
new file mode 100644
index 0000000000..f0e2cb297e
--- /dev/null
+++ b/media/libvpx/libvpx/test/consistency_test.cc
@@ -0,0 +1,215 @@
+/*
+ * 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 <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if CONFIG_VP9_ENCODER
+#include "./vp9_rtcd.h"
+#endif
+
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx_dsp/ssim.h"
+#include "vpx_mem/vpx_mem.h"
+
+extern "C" double vpx_get_ssim_metrics(uint8_t *img1, int img1_pitch,
+ uint8_t *img2, int img2_pitch, int width,
+ int height, Ssimv *sv2, Metrics *m,
+ int do_inconsistency);
+
+using libvpx_test::ACMRandom;
+
+namespace {
+class ConsistencyTestBase : public ::testing::Test {
+ public:
+ ConsistencyTestBase(int width, int height) : width_(width), height_(height) {}
+
+ static void SetUpTestSuite() {
+ source_data_[0] = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ reference_data_[0] = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ source_data_[1] = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ reference_data_[1] = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ ssim_array_ = new Ssimv[kDataBufferSize / 16];
+ }
+
+ static void ClearSsim() { memset(ssim_array_, 0, kDataBufferSize / 16); }
+ static void TearDownTestSuite() {
+ vpx_free(source_data_[0]);
+ source_data_[0] = nullptr;
+ vpx_free(reference_data_[0]);
+ reference_data_[0] = nullptr;
+ vpx_free(source_data_[1]);
+ source_data_[1] = nullptr;
+ vpx_free(reference_data_[1]);
+ reference_data_[1] = nullptr;
+
+ delete[] ssim_array_;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ // Handle frames up to 640x480
+ static const int kDataAlignment = 16;
+ static const int kDataBufferSize = 640 * 480;
+
+ virtual void SetUp() {
+ source_stride_ = (width_ + 31) & ~31;
+ reference_stride_ = width_ * 2;
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ void FillRandom(uint8_t *data, int stride, int width, int height) {
+ for (int h = 0; h < height; ++h) {
+ for (int w = 0; w < width; ++w) {
+ data[h * stride + w] = rnd_.Rand8();
+ }
+ }
+ }
+
+ void FillRandom(uint8_t *data, int stride) {
+ FillRandom(data, stride, width_, height_);
+ }
+
+ void Copy(uint8_t *reference, uint8_t *source) {
+ memcpy(reference, source, kDataBufferSize);
+ }
+
+ void Blur(uint8_t *data, int stride, int taps) {
+ int sum = 0;
+ int half_taps = taps / 2;
+ for (int h = 0; h < height_; ++h) {
+ for (int w = 0; w < taps; ++w) {
+ sum += data[w + h * stride];
+ }
+ for (int w = taps; w < width_; ++w) {
+ sum += data[w + h * stride] - data[w - taps + h * stride];
+ data[w - half_taps + h * stride] = (sum + half_taps) / taps;
+ }
+ }
+ for (int w = 0; w < width_; ++w) {
+ for (int h = 0; h < taps; ++h) {
+ sum += data[h + w * stride];
+ }
+ for (int h = taps; h < height_; ++h) {
+ sum += data[w + h * stride] - data[(h - taps) * stride + w];
+ data[(h - half_taps) * stride + w] = (sum + half_taps) / taps;
+ }
+ }
+ }
+ int width_, height_;
+ static uint8_t *source_data_[2];
+ int source_stride_;
+ static uint8_t *reference_data_[2];
+ int reference_stride_;
+ static Ssimv *ssim_array_;
+ Metrics metrics_;
+
+ ACMRandom rnd_;
+};
+
+#if CONFIG_VP9_ENCODER
+typedef std::tuple<int, int> ConsistencyParam;
+class ConsistencyVP9Test
+ : public ConsistencyTestBase,
+ public ::testing::WithParamInterface<ConsistencyParam> {
+ public:
+ ConsistencyVP9Test() : ConsistencyTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+ double CheckConsistency(int frame) {
+ EXPECT_LT(frame, 2) << "Frame to check has to be less than 2.";
+ return vpx_get_ssim_metrics(source_data_[frame], source_stride_,
+ reference_data_[frame], reference_stride_,
+ width_, height_, ssim_array_, &metrics_, 1);
+ }
+};
+#endif // CONFIG_VP9_ENCODER
+
+uint8_t *ConsistencyTestBase::source_data_[2] = { nullptr, nullptr };
+uint8_t *ConsistencyTestBase::reference_data_[2] = { nullptr, nullptr };
+Ssimv *ConsistencyTestBase::ssim_array_ = nullptr;
+
+#if CONFIG_VP9_ENCODER
+TEST_P(ConsistencyVP9Test, ConsistencyIsZero) {
+ FillRandom(source_data_[0], source_stride_);
+ Copy(source_data_[1], source_data_[0]);
+ Copy(reference_data_[0], source_data_[0]);
+ Blur(reference_data_[0], reference_stride_, 3);
+ Copy(reference_data_[1], source_data_[0]);
+ Blur(reference_data_[1], reference_stride_, 3);
+
+ double inconsistency = CheckConsistency(1);
+ inconsistency = CheckConsistency(0);
+ EXPECT_EQ(inconsistency, 0.0)
+ << "Should have 0 inconsistency if they are exactly the same.";
+
+ // If sources are not consistent reference frames inconsistency should
+ // be less than if the source is consistent.
+ FillRandom(source_data_[0], source_stride_);
+ FillRandom(source_data_[1], source_stride_);
+ FillRandom(reference_data_[0], reference_stride_);
+ FillRandom(reference_data_[1], reference_stride_);
+ CheckConsistency(0);
+ inconsistency = CheckConsistency(1);
+
+ Copy(source_data_[1], source_data_[0]);
+ CheckConsistency(0);
+ double inconsistency2 = CheckConsistency(1);
+ EXPECT_LT(inconsistency, inconsistency2)
+ << "Should have less inconsistency if source itself is inconsistent.";
+
+ // Less of a blur should be less inconsistent than more blur coming off a
+ // a frame with no blur.
+ ClearSsim();
+ FillRandom(source_data_[0], source_stride_);
+ Copy(source_data_[1], source_data_[0]);
+ Copy(reference_data_[0], source_data_[0]);
+ Copy(reference_data_[1], source_data_[0]);
+ Blur(reference_data_[1], reference_stride_, 4);
+ CheckConsistency(0);
+ inconsistency = CheckConsistency(1);
+ ClearSsim();
+ Copy(reference_data_[1], source_data_[0]);
+ Blur(reference_data_[1], reference_stride_, 8);
+ CheckConsistency(0);
+ inconsistency2 = CheckConsistency(1);
+
+ EXPECT_LT(inconsistency, inconsistency2)
+ << "Stronger Blur should produce more inconsistency.";
+}
+#endif // CONFIG_VP9_ENCODER
+
+using std::make_tuple;
+
+//------------------------------------------------------------------------------
+// C functions
+
+#if CONFIG_VP9_ENCODER
+const ConsistencyParam c_vp9_tests[] = { make_tuple(320, 240),
+ make_tuple(318, 242),
+ make_tuple(318, 238) };
+INSTANTIATE_TEST_SUITE_P(C, ConsistencyVP9Test,
+ ::testing::ValuesIn(c_vp9_tests));
+#endif
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/convolve_test.cc b/media/libvpx/libvpx/test/convolve_test.cc
new file mode 100644
index 0000000000..5a17d80894
--- /dev/null
+++ b/media/libvpx/libvpx/test/convolve_test.cc
@@ -0,0 +1,1488 @@
+/*
+ * 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 <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_common.h"
+#include "vp9/common/vp9_filter.h"
+#include "vpx_dsp/vpx_dsp_common.h"
+#include "vpx_dsp/vpx_filter.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/vpx_timer.h"
+
+namespace {
+
+static const unsigned int kMaxDimension = 64;
+
+typedef void (*ConvolveFunc)(const uint8_t *src, ptrdiff_t src_stride,
+ uint8_t *dst, ptrdiff_t dst_stride,
+ const InterpKernel *filter, int x0_q4,
+ int x_step_q4, int y0_q4, int y_step_q4, int w,
+ int h);
+
+typedef void (*WrapperFilterBlock2d8Func)(
+ const uint8_t *src_ptr, const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter, uint8_t *dst_ptr,
+ unsigned int dst_stride, unsigned int output_width,
+ unsigned int output_height, int use_highbd);
+
+struct ConvolveFunctions {
+ ConvolveFunctions(ConvolveFunc copy, ConvolveFunc avg, ConvolveFunc h8,
+ ConvolveFunc h8_avg, ConvolveFunc v8, ConvolveFunc v8_avg,
+ ConvolveFunc hv8, ConvolveFunc hv8_avg, ConvolveFunc sh8,
+ ConvolveFunc sh8_avg, ConvolveFunc sv8,
+ ConvolveFunc sv8_avg, ConvolveFunc shv8,
+ ConvolveFunc shv8_avg, int bd)
+ : use_highbd_(bd) {
+ copy_[0] = copy;
+ copy_[1] = avg;
+ h8_[0] = h8;
+ h8_[1] = h8_avg;
+ v8_[0] = v8;
+ v8_[1] = v8_avg;
+ hv8_[0] = hv8;
+ hv8_[1] = hv8_avg;
+ sh8_[0] = sh8;
+ sh8_[1] = sh8_avg;
+ sv8_[0] = sv8;
+ sv8_[1] = sv8_avg;
+ shv8_[0] = shv8;
+ shv8_[1] = shv8_avg;
+ }
+
+ ConvolveFunc copy_[2];
+ ConvolveFunc h8_[2];
+ ConvolveFunc v8_[2];
+ ConvolveFunc hv8_[2];
+ ConvolveFunc sh8_[2]; // scaled horiz
+ ConvolveFunc sv8_[2]; // scaled vert
+ ConvolveFunc shv8_[2]; // scaled horiz/vert
+ int use_highbd_; // 0 if high bitdepth not used, else the actual bit depth.
+};
+
+typedef std::tuple<int, int, const ConvolveFunctions *> ConvolveParam;
+
+#define ALL_SIZES(convolve_fn) \
+ make_tuple(4, 4, &convolve_fn), make_tuple(8, 4, &convolve_fn), \
+ make_tuple(4, 8, &convolve_fn), make_tuple(8, 8, &convolve_fn), \
+ make_tuple(16, 8, &convolve_fn), make_tuple(8, 16, &convolve_fn), \
+ make_tuple(16, 16, &convolve_fn), make_tuple(32, 16, &convolve_fn), \
+ make_tuple(16, 32, &convolve_fn), make_tuple(32, 32, &convolve_fn), \
+ make_tuple(64, 32, &convolve_fn), make_tuple(32, 64, &convolve_fn), \
+ make_tuple(64, 64, &convolve_fn)
+
+// Reference 8-tap subpixel filter, slightly modified to fit into this test.
+#define VP9_FILTER_WEIGHT 128
+#define VP9_FILTER_SHIFT 7
+uint8_t clip_pixel(int x) { return x < 0 ? 0 : x > 255 ? 255 : x; }
+
+void filter_block2d_8_c(const uint8_t *src_ptr, const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter,
+ uint8_t *dst_ptr, unsigned int dst_stride,
+ unsigned int output_width, unsigned int output_height) {
+ // Between passes, we use an intermediate buffer whose height is extended to
+ // have enough horizontally filtered values as input for the vertical pass.
+ // This buffer is allocated to be big enough for the largest block type we
+ // support.
+ const int kInterp_Extend = 4;
+ const unsigned int intermediate_height =
+ (kInterp_Extend - 1) + output_height + kInterp_Extend;
+ unsigned int i, j;
+
+ // Size of intermediate_buffer is max_intermediate_height * filter_max_width,
+ // where max_intermediate_height = (kInterp_Extend - 1) + filter_max_height
+ // + kInterp_Extend
+ // = 3 + 16 + 4
+ // = 23
+ // and filter_max_width = 16
+ //
+ uint8_t intermediate_buffer[71 * kMaxDimension];
+ vp9_zero(intermediate_buffer);
+ const int intermediate_next_stride =
+ 1 - static_cast<int>(intermediate_height * output_width);
+
+ // Horizontal pass (src -> transposed intermediate).
+ uint8_t *output_ptr = intermediate_buffer;
+ const int src_next_row_stride = src_stride - output_width;
+ src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1);
+ for (i = 0; i < intermediate_height; ++i) {
+ for (j = 0; j < output_width; ++j) {
+ // Apply filter...
+ const int temp = (src_ptr[0] * hfilter[0]) + (src_ptr[1] * hfilter[1]) +
+ (src_ptr[2] * hfilter[2]) + (src_ptr[3] * hfilter[3]) +
+ (src_ptr[4] * hfilter[4]) + (src_ptr[5] * hfilter[5]) +
+ (src_ptr[6] * hfilter[6]) + (src_ptr[7] * hfilter[7]) +
+ (VP9_FILTER_WEIGHT >> 1); // Rounding
+
+ // Normalize back to 0-255...
+ *output_ptr = clip_pixel(temp >> VP9_FILTER_SHIFT);
+ ++src_ptr;
+ output_ptr += intermediate_height;
+ }
+ src_ptr += src_next_row_stride;
+ output_ptr += intermediate_next_stride;
+ }
+
+ // Vertical pass (transposed intermediate -> dst).
+ src_ptr = intermediate_buffer;
+ const int dst_next_row_stride = dst_stride - output_width;
+ for (i = 0; i < output_height; ++i) {
+ for (j = 0; j < output_width; ++j) {
+ // Apply filter...
+ const int temp = (src_ptr[0] * vfilter[0]) + (src_ptr[1] * vfilter[1]) +
+ (src_ptr[2] * vfilter[2]) + (src_ptr[3] * vfilter[3]) +
+ (src_ptr[4] * vfilter[4]) + (src_ptr[5] * vfilter[5]) +
+ (src_ptr[6] * vfilter[6]) + (src_ptr[7] * vfilter[7]) +
+ (VP9_FILTER_WEIGHT >> 1); // Rounding
+
+ // Normalize back to 0-255...
+ *dst_ptr++ = clip_pixel(temp >> VP9_FILTER_SHIFT);
+ src_ptr += intermediate_height;
+ }
+ src_ptr += intermediate_next_stride;
+ dst_ptr += dst_next_row_stride;
+ }
+}
+
+void block2d_average_c(uint8_t *src, unsigned int src_stride,
+ uint8_t *output_ptr, unsigned int output_stride,
+ unsigned int output_width, unsigned int output_height) {
+ unsigned int i, j;
+ for (i = 0; i < output_height; ++i) {
+ for (j = 0; j < output_width; ++j) {
+ output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1;
+ }
+ output_ptr += output_stride;
+ }
+}
+
+void filter_average_block2d_8_c(const uint8_t *src_ptr,
+ const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter,
+ uint8_t *dst_ptr, unsigned int dst_stride,
+ unsigned int output_width,
+ unsigned int output_height) {
+ uint8_t tmp[kMaxDimension * kMaxDimension];
+
+ assert(output_width <= kMaxDimension);
+ assert(output_height <= kMaxDimension);
+ filter_block2d_8_c(src_ptr, src_stride, hfilter, vfilter, tmp, 64,
+ output_width, output_height);
+ block2d_average_c(tmp, 64, dst_ptr, dst_stride, output_width, output_height);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void highbd_filter_block2d_8_c(const uint16_t *src_ptr,
+ const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter,
+ uint16_t *dst_ptr, unsigned int dst_stride,
+ unsigned int output_width,
+ unsigned int output_height, int bd) {
+ // Between passes, we use an intermediate buffer whose height is extended to
+ // have enough horizontally filtered values as input for the vertical pass.
+ // This buffer is allocated to be big enough for the largest block type we
+ // support.
+ const int kInterp_Extend = 4;
+ const unsigned int intermediate_height =
+ (kInterp_Extend - 1) + output_height + kInterp_Extend;
+
+ /* Size of intermediate_buffer is max_intermediate_height * filter_max_width,
+ * where max_intermediate_height = (kInterp_Extend - 1) + filter_max_height
+ * + kInterp_Extend
+ * = 3 + 16 + 4
+ * = 23
+ * and filter_max_width = 16
+ */
+ uint16_t intermediate_buffer[71 * kMaxDimension];
+ const int intermediate_next_stride =
+ 1 - static_cast<int>(intermediate_height * output_width);
+
+ vp9_zero(intermediate_buffer);
+
+ // Horizontal pass (src -> transposed intermediate).
+ {
+ uint16_t *output_ptr = intermediate_buffer;
+ const int src_next_row_stride = src_stride - output_width;
+ unsigned int i, j;
+ src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1);
+ for (i = 0; i < intermediate_height; ++i) {
+ for (j = 0; j < output_width; ++j) {
+ // Apply filter...
+ const int temp = (src_ptr[0] * hfilter[0]) + (src_ptr[1] * hfilter[1]) +
+ (src_ptr[2] * hfilter[2]) + (src_ptr[3] * hfilter[3]) +
+ (src_ptr[4] * hfilter[4]) + (src_ptr[5] * hfilter[5]) +
+ (src_ptr[6] * hfilter[6]) + (src_ptr[7] * hfilter[7]) +
+ (VP9_FILTER_WEIGHT >> 1); // Rounding
+
+ // Normalize back to 0-255...
+ *output_ptr = clip_pixel_highbd(temp >> VP9_FILTER_SHIFT, bd);
+ ++src_ptr;
+ output_ptr += intermediate_height;
+ }
+ src_ptr += src_next_row_stride;
+ output_ptr += intermediate_next_stride;
+ }
+ }
+
+ // Vertical pass (transposed intermediate -> dst).
+ {
+ src_ptr = intermediate_buffer;
+ const int dst_next_row_stride = dst_stride - output_width;
+ unsigned int i, j;
+ for (i = 0; i < output_height; ++i) {
+ for (j = 0; j < output_width; ++j) {
+ // Apply filter...
+ const int temp = (src_ptr[0] * vfilter[0]) + (src_ptr[1] * vfilter[1]) +
+ (src_ptr[2] * vfilter[2]) + (src_ptr[3] * vfilter[3]) +
+ (src_ptr[4] * vfilter[4]) + (src_ptr[5] * vfilter[5]) +
+ (src_ptr[6] * vfilter[6]) + (src_ptr[7] * vfilter[7]) +
+ (VP9_FILTER_WEIGHT >> 1); // Rounding
+
+ // Normalize back to 0-255...
+ *dst_ptr++ = clip_pixel_highbd(temp >> VP9_FILTER_SHIFT, bd);
+ src_ptr += intermediate_height;
+ }
+ src_ptr += intermediate_next_stride;
+ dst_ptr += dst_next_row_stride;
+ }
+ }
+}
+
+void highbd_block2d_average_c(uint16_t *src, unsigned int src_stride,
+ uint16_t *output_ptr, unsigned int output_stride,
+ unsigned int output_width,
+ unsigned int output_height) {
+ unsigned int i, j;
+ for (i = 0; i < output_height; ++i) {
+ for (j = 0; j < output_width; ++j) {
+ output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1;
+ }
+ output_ptr += output_stride;
+ }
+}
+
+void highbd_filter_average_block2d_8_c(
+ const uint16_t *src_ptr, const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter, uint16_t *dst_ptr,
+ unsigned int dst_stride, unsigned int output_width,
+ unsigned int output_height, int bd) {
+ uint16_t tmp[kMaxDimension * kMaxDimension];
+
+ assert(output_width <= kMaxDimension);
+ assert(output_height <= kMaxDimension);
+ highbd_filter_block2d_8_c(src_ptr, src_stride, hfilter, vfilter, tmp, 64,
+ output_width, output_height, bd);
+ highbd_block2d_average_c(tmp, 64, dst_ptr, dst_stride, output_width,
+ output_height);
+}
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+void wrapper_filter_average_block2d_8_c(
+ const uint8_t *src_ptr, const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter, uint8_t *dst_ptr,
+ unsigned int dst_stride, unsigned int output_width,
+ unsigned int output_height, int use_highbd) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (use_highbd == 0) {
+ filter_average_block2d_8_c(src_ptr, src_stride, hfilter, vfilter, dst_ptr,
+ dst_stride, output_width, output_height);
+ } else {
+ highbd_filter_average_block2d_8_c(CAST_TO_SHORTPTR(src_ptr), src_stride,
+ hfilter, vfilter,
+ CAST_TO_SHORTPTR(dst_ptr), dst_stride,
+ output_width, output_height, use_highbd);
+ }
+#else
+ ASSERT_EQ(0, use_highbd);
+ filter_average_block2d_8_c(src_ptr, src_stride, hfilter, vfilter, dst_ptr,
+ dst_stride, output_width, output_height);
+#endif
+}
+
+void wrapper_filter_block2d_8_c(const uint8_t *src_ptr,
+ const unsigned int src_stride,
+ const int16_t *hfilter, const int16_t *vfilter,
+ uint8_t *dst_ptr, unsigned int dst_stride,
+ unsigned int output_width,
+ unsigned int output_height, int use_highbd) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (use_highbd == 0) {
+ filter_block2d_8_c(src_ptr, src_stride, hfilter, vfilter, dst_ptr,
+ dst_stride, output_width, output_height);
+ } else {
+ highbd_filter_block2d_8_c(CAST_TO_SHORTPTR(src_ptr), src_stride, hfilter,
+ vfilter, CAST_TO_SHORTPTR(dst_ptr), dst_stride,
+ output_width, output_height, use_highbd);
+ }
+#else
+ ASSERT_EQ(0, use_highbd);
+ filter_block2d_8_c(src_ptr, src_stride, hfilter, vfilter, dst_ptr, dst_stride,
+ output_width, output_height);
+#endif
+}
+
+class ConvolveTest : public ::testing::TestWithParam<ConvolveParam> {
+ public:
+ static void SetUpTestSuite() {
+ // Force input_ to be unaligned, output to be 16 byte aligned.
+ input_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kInputBufferSize + 1)) +
+ 1;
+ output_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kOutputBufferSize));
+ output_ref_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kOutputBufferSize));
+#if CONFIG_VP9_HIGHBITDEPTH
+ input16_ = reinterpret_cast<uint16_t *>(vpx_memalign(
+ kDataAlignment, (kInputBufferSize + 1) * sizeof(uint16_t))) +
+ 1;
+ output16_ = reinterpret_cast<uint16_t *>(
+ vpx_memalign(kDataAlignment, (kOutputBufferSize) * sizeof(uint16_t)));
+ output16_ref_ = reinterpret_cast<uint16_t *>(
+ vpx_memalign(kDataAlignment, (kOutputBufferSize) * sizeof(uint16_t)));
+#endif
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ static void TearDownTestSuite() {
+ vpx_free(input_ - 1);
+ input_ = nullptr;
+ vpx_free(output_);
+ output_ = nullptr;
+ vpx_free(output_ref_);
+ output_ref_ = nullptr;
+#if CONFIG_VP9_HIGHBITDEPTH
+ vpx_free(input16_ - 1);
+ input16_ = nullptr;
+ vpx_free(output16_);
+ output16_ = nullptr;
+ vpx_free(output16_ref_);
+ output16_ref_ = nullptr;
+#endif
+ }
+
+ protected:
+ static const int kDataAlignment = 16;
+ static const int kOuterBlockSize = 256;
+ static const int kInputStride = kOuterBlockSize;
+ static const int kOutputStride = kOuterBlockSize;
+ static const int kInputBufferSize = kOuterBlockSize * kOuterBlockSize;
+ static const int kOutputBufferSize = kOuterBlockSize * kOuterBlockSize;
+
+ int Width() const { return GET_PARAM(0); }
+ int Height() const { return GET_PARAM(1); }
+ int BorderLeft() const {
+ const int center = (kOuterBlockSize - Width()) / 2;
+ return (center + (kDataAlignment - 1)) & ~(kDataAlignment - 1);
+ }
+ int BorderTop() const { return (kOuterBlockSize - Height()) / 2; }
+
+ bool IsIndexInBorder(int i) {
+ return (i < BorderTop() * kOuterBlockSize ||
+ i >= (BorderTop() + Height()) * kOuterBlockSize ||
+ i % kOuterBlockSize < BorderLeft() ||
+ i % kOuterBlockSize >= (BorderLeft() + Width()));
+ }
+
+ virtual void SetUp() {
+ UUT_ = GET_PARAM(2);
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ != 0) {
+ mask_ = (1 << UUT_->use_highbd_) - 1;
+ } else {
+ mask_ = 255;
+ }
+#endif
+ /* Set up guard blocks for an inner block centered in the outer block */
+ for (int i = 0; i < kOutputBufferSize; ++i) {
+ if (IsIndexInBorder(i)) {
+ output_[i] = 255;
+#if CONFIG_VP9_HIGHBITDEPTH
+ output16_[i] = mask_;
+#endif
+ } else {
+ output_[i] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+ output16_[i] = 0;
+#endif
+ }
+ }
+
+ ::libvpx_test::ACMRandom prng;
+ for (int i = 0; i < kInputBufferSize; ++i) {
+ if (i & 1) {
+ input_[i] = 255;
+#if CONFIG_VP9_HIGHBITDEPTH
+ input16_[i] = mask_;
+#endif
+ } else {
+ input_[i] = prng.Rand8Extremes();
+#if CONFIG_VP9_HIGHBITDEPTH
+ input16_[i] = prng.Rand16() & mask_;
+#endif
+ }
+ }
+ }
+
+ void SetConstantInput(int value) {
+ memset(input_, value, kInputBufferSize);
+#if CONFIG_VP9_HIGHBITDEPTH
+ vpx_memset16(input16_, value, kInputBufferSize);
+#endif
+ }
+
+ void CopyOutputToRef() {
+ memcpy(output_ref_, output_, kOutputBufferSize);
+#if CONFIG_VP9_HIGHBITDEPTH
+ memcpy(output16_ref_, output16_,
+ kOutputBufferSize * sizeof(output16_ref_[0]));
+#endif
+ }
+
+ void CheckGuardBlocks() {
+ for (int i = 0; i < kOutputBufferSize; ++i) {
+ if (IsIndexInBorder(i)) {
+ EXPECT_EQ(255, output_[i]);
+ }
+ }
+ }
+
+ uint8_t *input() const {
+ const int offset = BorderTop() * kOuterBlockSize + BorderLeft();
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0) {
+ return input_ + offset;
+ } else {
+ return CAST_TO_BYTEPTR(input16_ + offset);
+ }
+#else
+ return input_ + offset;
+#endif
+ }
+
+ uint8_t *output() const {
+ const int offset = BorderTop() * kOuterBlockSize + BorderLeft();
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0) {
+ return output_ + offset;
+ } else {
+ return CAST_TO_BYTEPTR(output16_ + offset);
+ }
+#else
+ return output_ + offset;
+#endif
+ }
+
+ uint8_t *output_ref() const {
+ const int offset = BorderTop() * kOuterBlockSize + BorderLeft();
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0) {
+ return output_ref_ + offset;
+ } else {
+ return CAST_TO_BYTEPTR(output16_ref_ + offset);
+ }
+#else
+ return output_ref_ + offset;
+#endif
+ }
+
+ uint16_t lookup(uint8_t *list, int index) const {
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0) {
+ return list[index];
+ } else {
+ return CAST_TO_SHORTPTR(list)[index];
+ }
+#else
+ return list[index];
+#endif
+ }
+
+ void assign_val(uint8_t *list, int index, uint16_t val) const {
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0) {
+ list[index] = (uint8_t)val;
+ } else {
+ CAST_TO_SHORTPTR(list)[index] = val;
+ }
+#else
+ list[index] = (uint8_t)val;
+#endif
+ }
+
+ const ConvolveFunctions *UUT_;
+ static uint8_t *input_;
+ static uint8_t *output_;
+ static uint8_t *output_ref_;
+#if CONFIG_VP9_HIGHBITDEPTH
+ static uint16_t *input16_;
+ static uint16_t *output16_;
+ static uint16_t *output16_ref_;
+ int mask_;
+#endif
+};
+
+uint8_t *ConvolveTest::input_ = nullptr;
+uint8_t *ConvolveTest::output_ = nullptr;
+uint8_t *ConvolveTest::output_ref_ = nullptr;
+#if CONFIG_VP9_HIGHBITDEPTH
+uint16_t *ConvolveTest::input16_ = nullptr;
+uint16_t *ConvolveTest::output16_ = nullptr;
+uint16_t *ConvolveTest::output16_ref_ = nullptr;
+#endif
+
+TEST_P(ConvolveTest, GuardBlocks) { CheckGuardBlocks(); }
+
+TEST_P(ConvolveTest, DISABLED_Copy_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->copy_[0](in, kInputStride, out, kOutputStride, nullptr, 0, 0, 0, 0,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve_copy_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_Avg_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->copy_[1](in, kInputStride, out, kOutputStride, nullptr, 0, 0, 0, 0,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve_avg_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_Scale_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->shv8_[0](in, kInputStride, out, kOutputStride, eighttap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve_scale_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_8Tap_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP_SHARP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->hv8_[0](in, kInputStride, out, kOutputStride, eighttap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve8_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_8Tap_Horiz_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP_SHARP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->h8_[0](in, kInputStride, out, kOutputStride, eighttap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve8_horiz_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_8Tap_Vert_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP_SHARP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->v8_[0](in, kInputStride, out, kOutputStride, eighttap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve8_vert_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_4Tap_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const fourtap = vp9_filter_kernels[FOURTAP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->hv8_[0](in, kInputStride, out, kOutputStride, fourtap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve4_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_4Tap_Horiz_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const fourtap = vp9_filter_kernels[FOURTAP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->h8_[0](in, kInputStride, out, kOutputStride, fourtap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve4_horiz_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, DISABLED_4Tap_Vert_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const fourtap = vp9_filter_kernels[FOURTAP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->v8_[0](in, kInputStride, out, kOutputStride, fourtap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve4_vert_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+TEST_P(ConvolveTest, DISABLED_8Tap_Avg_Speed) {
+ const uint8_t *const in = input();
+ uint8_t *const out = output();
+ const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP_SHARP];
+ const int kNumTests = 5000000;
+ const int width = Width();
+ const int height = Height();
+ vpx_usec_timer timer;
+
+ SetConstantInput(127);
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ UUT_->hv8_[1](in, kInputStride, out, kOutputStride, eighttap, 8, 16, 8, 16,
+ width, height);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("convolve8_avg_%dx%d_%d: %d us\n", width, height,
+ UUT_->use_highbd_ ? UUT_->use_highbd_ : 8, elapsed_time);
+}
+
+TEST_P(ConvolveTest, Copy) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+
+ ASM_REGISTER_STATE_CHECK(UUT_->copy_[0](in, kInputStride, out, kOutputStride,
+ nullptr, 0, 0, 0, 0, Width(),
+ Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(out, y * kOutputStride + x),
+ lookup(in, y * kInputStride + x))
+ << "(" << x << "," << y << ")";
+ }
+}
+
+TEST_P(ConvolveTest, Avg) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+ uint8_t *const out_ref = output_ref();
+ CopyOutputToRef();
+
+ ASM_REGISTER_STATE_CHECK(UUT_->copy_[1](in, kInputStride, out, kOutputStride,
+ nullptr, 0, 0, 0, 0, Width(),
+ Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(out, y * kOutputStride + x),
+ ROUND_POWER_OF_TWO(lookup(in, y * kInputStride + x) +
+ lookup(out_ref, y * kOutputStride + x),
+ 1))
+ << "(" << x << "," << y << ")";
+ }
+}
+
+TEST_P(ConvolveTest, CopyHoriz) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+
+ ASM_REGISTER_STATE_CHECK(UUT_->sh8_[0](in, kInputStride, out, kOutputStride,
+ vp9_filter_kernels[0], 0, 16, 0, 16,
+ Width(), Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(out, y * kOutputStride + x),
+ lookup(in, y * kInputStride + x))
+ << "(" << x << "," << y << ")";
+ }
+}
+
+TEST_P(ConvolveTest, CopyVert) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+
+ ASM_REGISTER_STATE_CHECK(UUT_->sv8_[0](in, kInputStride, out, kOutputStride,
+ vp9_filter_kernels[0], 0, 16, 0, 16,
+ Width(), Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(out, y * kOutputStride + x),
+ lookup(in, y * kInputStride + x))
+ << "(" << x << "," << y << ")";
+ }
+}
+
+TEST_P(ConvolveTest, Copy2D) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+
+ ASM_REGISTER_STATE_CHECK(UUT_->shv8_[0](in, kInputStride, out, kOutputStride,
+ vp9_filter_kernels[0], 0, 16, 0, 16,
+ Width(), Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(out, y * kOutputStride + x),
+ lookup(in, y * kInputStride + x))
+ << "(" << x << "," << y << ")";
+ }
+}
+
+const int kNumFilterBanks = 5;
+const int kNumFilters = 16;
+
+TEST(ConvolveTest, FiltersWontSaturateWhenAddedPairwise) {
+ for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+ const InterpKernel *filters =
+ vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+ for (int i = 0; i < kNumFilters; i++) {
+ const int p0 = filters[i][0] + filters[i][1];
+ const int p1 = filters[i][2] + filters[i][3];
+ const int p2 = filters[i][4] + filters[i][5];
+ const int p3 = filters[i][6] + filters[i][7];
+ EXPECT_LE(p0, 128);
+ EXPECT_LE(p1, 128);
+ EXPECT_LE(p2, 128);
+ EXPECT_LE(p3, 128);
+ EXPECT_LE(p0 + p3, 128);
+ EXPECT_LE(p0 + p3 + p1, 128);
+ EXPECT_LE(p0 + p3 + p1 + p2, 128);
+ EXPECT_EQ(p0 + p1 + p2 + p3, 128);
+ }
+ }
+}
+
+const WrapperFilterBlock2d8Func wrapper_filter_block2d_8[2] = {
+ wrapper_filter_block2d_8_c, wrapper_filter_average_block2d_8_c
+};
+
+TEST_P(ConvolveTest, MatchesReferenceSubpixelFilter) {
+ for (int i = 0; i < 2; ++i) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+#if CONFIG_VP9_HIGHBITDEPTH
+ uint8_t ref8[kOutputStride * kMaxDimension];
+ uint16_t ref16[kOutputStride * kMaxDimension];
+ uint8_t *ref;
+ if (UUT_->use_highbd_ == 0) {
+ ref = ref8;
+ } else {
+ ref = CAST_TO_BYTEPTR(ref16);
+ }
+#else
+ uint8_t ref[kOutputStride * kMaxDimension];
+#endif
+
+ // Populate ref and out with some random data
+ ::libvpx_test::ACMRandom prng;
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x) {
+ uint16_t r;
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0 || UUT_->use_highbd_ == 8) {
+ r = prng.Rand8Extremes();
+ } else {
+ r = prng.Rand16() & mask_;
+ }
+#else
+ r = prng.Rand8Extremes();
+#endif
+
+ assign_val(out, y * kOutputStride + x, r);
+ assign_val(ref, y * kOutputStride + x, r);
+ }
+ }
+
+ for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+ const InterpKernel *filters =
+ vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+
+ for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) {
+ for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) {
+ wrapper_filter_block2d_8[i](in, kInputStride, filters[filter_x],
+ filters[filter_y], ref, kOutputStride,
+ Width(), Height(), UUT_->use_highbd_);
+
+ if (filter_x && filter_y)
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->hv8_[i](in, kInputStride, out, kOutputStride, filters,
+ filter_x, 16, filter_y, 16, Width(), Height()));
+ else if (filter_y)
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->v8_[i](in, kInputStride, out, kOutputStride, filters, 0,
+ 16, filter_y, 16, Width(), Height()));
+ else if (filter_x)
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->h8_[i](in, kInputStride, out, kOutputStride, filters,
+ filter_x, 16, 0, 16, Width(), Height()));
+ else
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->copy_[i](in, kInputStride, out, kOutputStride, nullptr, 0,
+ 0, 0, 0, Width(), Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(ref, y * kOutputStride + x),
+ lookup(out, y * kOutputStride + x))
+ << "mismatch at (" << x << "," << y << "), "
+ << "filters (" << filter_bank << "," << filter_x << ","
+ << filter_y << ")";
+ }
+ }
+ }
+ }
+ }
+}
+
+TEST_P(ConvolveTest, FilterExtremes) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+#if CONFIG_VP9_HIGHBITDEPTH
+ uint8_t ref8[kOutputStride * kMaxDimension];
+ uint16_t ref16[kOutputStride * kMaxDimension];
+ uint8_t *ref;
+ if (UUT_->use_highbd_ == 0) {
+ ref = ref8;
+ } else {
+ ref = CAST_TO_BYTEPTR(ref16);
+ }
+#else
+ uint8_t ref[kOutputStride * kMaxDimension];
+#endif
+
+ // Populate ref and out with some random data
+ ::libvpx_test::ACMRandom prng;
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x) {
+ uint16_t r;
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (UUT_->use_highbd_ == 0 || UUT_->use_highbd_ == 8) {
+ r = prng.Rand8Extremes();
+ } else {
+ r = prng.Rand16() & mask_;
+ }
+#else
+ r = prng.Rand8Extremes();
+#endif
+ assign_val(out, y * kOutputStride + x, r);
+ assign_val(ref, y * kOutputStride + x, r);
+ }
+ }
+
+ for (int axis = 0; axis < 2; axis++) {
+ int seed_val = 0;
+ while (seed_val < 256) {
+ for (int y = 0; y < 8; ++y) {
+ for (int x = 0; x < 8; ++x) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ assign_val(in, y * kOutputStride + x - SUBPEL_TAPS / 2 + 1,
+ ((seed_val >> (axis ? y : x)) & 1) * mask_);
+#else
+ assign_val(in, y * kOutputStride + x - SUBPEL_TAPS / 2 + 1,
+ ((seed_val >> (axis ? y : x)) & 1) * 255);
+#endif
+ if (axis) seed_val++;
+ }
+ if (axis) {
+ seed_val -= 8;
+ } else {
+ seed_val++;
+ }
+ }
+ if (axis) seed_val += 8;
+
+ for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+ const InterpKernel *filters =
+ vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+ for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) {
+ for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) {
+ wrapper_filter_block2d_8_c(in, kInputStride, filters[filter_x],
+ filters[filter_y], ref, kOutputStride,
+ Width(), Height(), UUT_->use_highbd_);
+ if (filter_x && filter_y)
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->hv8_[0](in, kInputStride, out, kOutputStride, filters,
+ filter_x, 16, filter_y, 16, Width(), Height()));
+ else if (filter_y)
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->v8_[0](in, kInputStride, out, kOutputStride, filters, 0,
+ 16, filter_y, 16, Width(), Height()));
+ else if (filter_x)
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->h8_[0](in, kInputStride, out, kOutputStride, filters,
+ filter_x, 16, 0, 16, Width(), Height()));
+ else
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->copy_[0](in, kInputStride, out, kOutputStride, nullptr,
+ 0, 0, 0, 0, Width(), Height()));
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x)
+ ASSERT_EQ(lookup(ref, y * kOutputStride + x),
+ lookup(out, y * kOutputStride + x))
+ << "mismatch at (" << x << "," << y << "), "
+ << "filters (" << filter_bank << "," << filter_x << ","
+ << filter_y << ")";
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* This test exercises that enough rows and columns are filtered with every
+ possible initial fractional positions and scaling steps. */
+#if !CONFIG_VP9_HIGHBITDEPTH
+static const ConvolveFunc scaled_2d_c_funcs[2] = { vpx_scaled_2d_c,
+ vpx_scaled_avg_2d_c };
+
+TEST_P(ConvolveTest, CheckScalingFiltering) {
+ uint8_t *const in = input();
+ uint8_t *const out = output();
+ uint8_t ref[kOutputStride * kMaxDimension];
+
+ ::libvpx_test::ACMRandom prng;
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x) {
+ const uint16_t r = prng.Rand8Extremes();
+ assign_val(in, y * kInputStride + x, r);
+ }
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ for (INTERP_FILTER filter_type = 0; filter_type < 4; ++filter_type) {
+ const InterpKernel *const eighttap = vp9_filter_kernels[filter_type];
+ for (int frac = 0; frac < 16; ++frac) {
+ for (int step = 1; step <= 32; ++step) {
+ /* Test the horizontal and vertical filters in combination. */
+ scaled_2d_c_funcs[i](in, kInputStride, ref, kOutputStride, eighttap,
+ frac, step, frac, step, Width(), Height());
+ ASM_REGISTER_STATE_CHECK(
+ UUT_->shv8_[i](in, kInputStride, out, kOutputStride, eighttap,
+ frac, step, frac, step, Width(), Height()));
+
+ CheckGuardBlocks();
+
+ for (int y = 0; y < Height(); ++y) {
+ for (int x = 0; x < Width(); ++x) {
+ ASSERT_EQ(lookup(ref, y * kOutputStride + x),
+ lookup(out, y * kOutputStride + x))
+ << "x == " << x << ", y == " << y << ", frac == " << frac
+ << ", step == " << step;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
+using std::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+#define WRAP(func, bd) \
+ void wrap_##func##_##bd( \
+ const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, \
+ ptrdiff_t dst_stride, const InterpKernel *filter, int x0_q4, \
+ int x_step_q4, int y0_q4, int y_step_q4, int w, int h) { \
+ vpx_highbd_##func(reinterpret_cast<const uint16_t *>(src), src_stride, \
+ reinterpret_cast<uint16_t *>(dst), dst_stride, filter, \
+ x0_q4, x_step_q4, y0_q4, y_step_q4, w, h, bd); \
+ }
+
+#if HAVE_SSE2 && VPX_ARCH_X86_64
+WRAP(convolve_copy_sse2, 8)
+WRAP(convolve_avg_sse2, 8)
+WRAP(convolve_copy_sse2, 10)
+WRAP(convolve_avg_sse2, 10)
+WRAP(convolve_copy_sse2, 12)
+WRAP(convolve_avg_sse2, 12)
+WRAP(convolve8_horiz_sse2, 8)
+WRAP(convolve8_avg_horiz_sse2, 8)
+WRAP(convolve8_vert_sse2, 8)
+WRAP(convolve8_avg_vert_sse2, 8)
+WRAP(convolve8_sse2, 8)
+WRAP(convolve8_avg_sse2, 8)
+WRAP(convolve8_horiz_sse2, 10)
+WRAP(convolve8_avg_horiz_sse2, 10)
+WRAP(convolve8_vert_sse2, 10)
+WRAP(convolve8_avg_vert_sse2, 10)
+WRAP(convolve8_sse2, 10)
+WRAP(convolve8_avg_sse2, 10)
+WRAP(convolve8_horiz_sse2, 12)
+WRAP(convolve8_avg_horiz_sse2, 12)
+WRAP(convolve8_vert_sse2, 12)
+WRAP(convolve8_avg_vert_sse2, 12)
+WRAP(convolve8_sse2, 12)
+WRAP(convolve8_avg_sse2, 12)
+#endif // HAVE_SSE2 && VPX_ARCH_X86_64
+
+#if HAVE_AVX2
+WRAP(convolve_copy_avx2, 8)
+WRAP(convolve_avg_avx2, 8)
+WRAP(convolve8_horiz_avx2, 8)
+WRAP(convolve8_avg_horiz_avx2, 8)
+WRAP(convolve8_vert_avx2, 8)
+WRAP(convolve8_avg_vert_avx2, 8)
+WRAP(convolve8_avx2, 8)
+WRAP(convolve8_avg_avx2, 8)
+
+WRAP(convolve_copy_avx2, 10)
+WRAP(convolve_avg_avx2, 10)
+WRAP(convolve8_avx2, 10)
+WRAP(convolve8_horiz_avx2, 10)
+WRAP(convolve8_vert_avx2, 10)
+WRAP(convolve8_avg_avx2, 10)
+WRAP(convolve8_avg_horiz_avx2, 10)
+WRAP(convolve8_avg_vert_avx2, 10)
+
+WRAP(convolve_copy_avx2, 12)
+WRAP(convolve_avg_avx2, 12)
+WRAP(convolve8_avx2, 12)
+WRAP(convolve8_horiz_avx2, 12)
+WRAP(convolve8_vert_avx2, 12)
+WRAP(convolve8_avg_avx2, 12)
+WRAP(convolve8_avg_horiz_avx2, 12)
+WRAP(convolve8_avg_vert_avx2, 12)
+#endif // HAVE_AVX2
+
+#if HAVE_NEON
+WRAP(convolve_copy_neon, 8)
+WRAP(convolve_avg_neon, 8)
+WRAP(convolve_copy_neon, 10)
+WRAP(convolve_avg_neon, 10)
+WRAP(convolve_copy_neon, 12)
+WRAP(convolve_avg_neon, 12)
+WRAP(convolve8_horiz_neon, 8)
+WRAP(convolve8_avg_horiz_neon, 8)
+WRAP(convolve8_vert_neon, 8)
+WRAP(convolve8_avg_vert_neon, 8)
+WRAP(convolve8_neon, 8)
+WRAP(convolve8_avg_neon, 8)
+WRAP(convolve8_horiz_neon, 10)
+WRAP(convolve8_avg_horiz_neon, 10)
+WRAP(convolve8_vert_neon, 10)
+WRAP(convolve8_avg_vert_neon, 10)
+WRAP(convolve8_neon, 10)
+WRAP(convolve8_avg_neon, 10)
+WRAP(convolve8_horiz_neon, 12)
+WRAP(convolve8_avg_horiz_neon, 12)
+WRAP(convolve8_vert_neon, 12)
+WRAP(convolve8_avg_vert_neon, 12)
+WRAP(convolve8_neon, 12)
+WRAP(convolve8_avg_neon, 12)
+#endif // HAVE_NEON
+
+WRAP(convolve_copy_c, 8)
+WRAP(convolve_avg_c, 8)
+WRAP(convolve8_horiz_c, 8)
+WRAP(convolve8_avg_horiz_c, 8)
+WRAP(convolve8_vert_c, 8)
+WRAP(convolve8_avg_vert_c, 8)
+WRAP(convolve8_c, 8)
+WRAP(convolve8_avg_c, 8)
+WRAP(convolve_copy_c, 10)
+WRAP(convolve_avg_c, 10)
+WRAP(convolve8_horiz_c, 10)
+WRAP(convolve8_avg_horiz_c, 10)
+WRAP(convolve8_vert_c, 10)
+WRAP(convolve8_avg_vert_c, 10)
+WRAP(convolve8_c, 10)
+WRAP(convolve8_avg_c, 10)
+WRAP(convolve_copy_c, 12)
+WRAP(convolve_avg_c, 12)
+WRAP(convolve8_horiz_c, 12)
+WRAP(convolve8_avg_horiz_c, 12)
+WRAP(convolve8_vert_c, 12)
+WRAP(convolve8_avg_vert_c, 12)
+WRAP(convolve8_c, 12)
+WRAP(convolve8_avg_c, 12)
+#undef WRAP
+
+const ConvolveFunctions convolve8_c(
+ wrap_convolve_copy_c_8, wrap_convolve_avg_c_8, wrap_convolve8_horiz_c_8,
+ wrap_convolve8_avg_horiz_c_8, wrap_convolve8_vert_c_8,
+ wrap_convolve8_avg_vert_c_8, wrap_convolve8_c_8, wrap_convolve8_avg_c_8,
+ wrap_convolve8_horiz_c_8, wrap_convolve8_avg_horiz_c_8,
+ wrap_convolve8_vert_c_8, wrap_convolve8_avg_vert_c_8, wrap_convolve8_c_8,
+ wrap_convolve8_avg_c_8, 8);
+const ConvolveFunctions convolve10_c(
+ wrap_convolve_copy_c_10, wrap_convolve_avg_c_10, wrap_convolve8_horiz_c_10,
+ wrap_convolve8_avg_horiz_c_10, wrap_convolve8_vert_c_10,
+ wrap_convolve8_avg_vert_c_10, wrap_convolve8_c_10, wrap_convolve8_avg_c_10,
+ wrap_convolve8_horiz_c_10, wrap_convolve8_avg_horiz_c_10,
+ wrap_convolve8_vert_c_10, wrap_convolve8_avg_vert_c_10, wrap_convolve8_c_10,
+ wrap_convolve8_avg_c_10, 10);
+const ConvolveFunctions convolve12_c(
+ wrap_convolve_copy_c_12, wrap_convolve_avg_c_12, wrap_convolve8_horiz_c_12,
+ wrap_convolve8_avg_horiz_c_12, wrap_convolve8_vert_c_12,
+ wrap_convolve8_avg_vert_c_12, wrap_convolve8_c_12, wrap_convolve8_avg_c_12,
+ wrap_convolve8_horiz_c_12, wrap_convolve8_avg_horiz_c_12,
+ wrap_convolve8_vert_c_12, wrap_convolve8_avg_vert_c_12, wrap_convolve8_c_12,
+ wrap_convolve8_avg_c_12, 12);
+const ConvolveParam kArrayConvolve_c[] = { ALL_SIZES(convolve8_c),
+ ALL_SIZES(convolve10_c),
+ ALL_SIZES(convolve12_c) };
+
+#else
+const ConvolveFunctions convolve8_c(
+ vpx_convolve_copy_c, vpx_convolve_avg_c, vpx_convolve8_horiz_c,
+ vpx_convolve8_avg_horiz_c, vpx_convolve8_vert_c, vpx_convolve8_avg_vert_c,
+ vpx_convolve8_c, vpx_convolve8_avg_c, vpx_scaled_horiz_c,
+ vpx_scaled_avg_horiz_c, vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+ vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+const ConvolveParam kArrayConvolve_c[] = { ALL_SIZES(convolve8_c) };
+#endif
+INSTANTIATE_TEST_SUITE_P(C, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve_c));
+
+#if HAVE_SSE2 && VPX_ARCH_X86_64
+#if CONFIG_VP9_HIGHBITDEPTH
+const ConvolveFunctions convolve8_sse2(
+ wrap_convolve_copy_sse2_8, wrap_convolve_avg_sse2_8,
+ wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8,
+ wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8,
+ wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8,
+ wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8,
+ wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8,
+ wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8, 8);
+const ConvolveFunctions convolve10_sse2(
+ wrap_convolve_copy_sse2_10, wrap_convolve_avg_sse2_10,
+ wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10,
+ wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10,
+ wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10,
+ wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10,
+ wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10,
+ wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10, 10);
+const ConvolveFunctions convolve12_sse2(
+ wrap_convolve_copy_sse2_12, wrap_convolve_avg_sse2_12,
+ wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12,
+ wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12,
+ wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12,
+ wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12,
+ wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12,
+ wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12, 12);
+const ConvolveParam kArrayConvolve_sse2[] = { ALL_SIZES(convolve8_sse2),
+ ALL_SIZES(convolve10_sse2),
+ ALL_SIZES(convolve12_sse2) };
+#else
+const ConvolveFunctions convolve8_sse2(
+ vpx_convolve_copy_sse2, vpx_convolve_avg_sse2, vpx_convolve8_horiz_sse2,
+ vpx_convolve8_avg_horiz_sse2, vpx_convolve8_vert_sse2,
+ vpx_convolve8_avg_vert_sse2, vpx_convolve8_sse2, vpx_convolve8_avg_sse2,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve_sse2[] = { ALL_SIZES(convolve8_sse2) };
+#endif // CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(SSE2, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve_sse2));
+#endif
+
+#if HAVE_SSSE3
+const ConvolveFunctions convolve8_ssse3(
+ vpx_convolve_copy_c, vpx_convolve_avg_c, vpx_convolve8_horiz_ssse3,
+ vpx_convolve8_avg_horiz_ssse3, vpx_convolve8_vert_ssse3,
+ vpx_convolve8_avg_vert_ssse3, vpx_convolve8_ssse3, vpx_convolve8_avg_ssse3,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_ssse3, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_ssse3[] = { ALL_SIZES(convolve8_ssse3) };
+INSTANTIATE_TEST_SUITE_P(SSSE3, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve8_ssse3));
+#endif
+
+#if HAVE_AVX2
+#if CONFIG_VP9_HIGHBITDEPTH
+const ConvolveFunctions convolve8_avx2(
+ wrap_convolve_copy_avx2_8, wrap_convolve_avg_avx2_8,
+ wrap_convolve8_horiz_avx2_8, wrap_convolve8_avg_horiz_avx2_8,
+ wrap_convolve8_vert_avx2_8, wrap_convolve8_avg_vert_avx2_8,
+ wrap_convolve8_avx2_8, wrap_convolve8_avg_avx2_8, wrap_convolve8_horiz_c_8,
+ wrap_convolve8_avg_horiz_c_8, wrap_convolve8_vert_c_8,
+ wrap_convolve8_avg_vert_c_8, wrap_convolve8_c_8, wrap_convolve8_avg_c_8, 8);
+const ConvolveFunctions convolve10_avx2(
+ wrap_convolve_copy_avx2_10, wrap_convolve_avg_avx2_10,
+ wrap_convolve8_horiz_avx2_10, wrap_convolve8_avg_horiz_avx2_10,
+ wrap_convolve8_vert_avx2_10, wrap_convolve8_avg_vert_avx2_10,
+ wrap_convolve8_avx2_10, wrap_convolve8_avg_avx2_10,
+ wrap_convolve8_horiz_c_10, wrap_convolve8_avg_horiz_c_10,
+ wrap_convolve8_vert_c_10, wrap_convolve8_avg_vert_c_10, wrap_convolve8_c_10,
+ wrap_convolve8_avg_c_10, 10);
+const ConvolveFunctions convolve12_avx2(
+ wrap_convolve_copy_avx2_12, wrap_convolve_avg_avx2_12,
+ wrap_convolve8_horiz_avx2_12, wrap_convolve8_avg_horiz_avx2_12,
+ wrap_convolve8_vert_avx2_12, wrap_convolve8_avg_vert_avx2_12,
+ wrap_convolve8_avx2_12, wrap_convolve8_avg_avx2_12,
+ wrap_convolve8_horiz_c_12, wrap_convolve8_avg_horiz_c_12,
+ wrap_convolve8_vert_c_12, wrap_convolve8_avg_vert_c_12, wrap_convolve8_c_12,
+ wrap_convolve8_avg_c_12, 12);
+const ConvolveParam kArrayConvolve8_avx2[] = { ALL_SIZES(convolve8_avx2),
+ ALL_SIZES(convolve10_avx2),
+ ALL_SIZES(convolve12_avx2) };
+INSTANTIATE_TEST_SUITE_P(AVX2, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve8_avx2));
+#else // !CONFIG_VP9_HIGHBITDEPTH
+const ConvolveFunctions convolve8_avx2(
+ vpx_convolve_copy_c, vpx_convolve_avg_c, vpx_convolve8_horiz_avx2,
+ vpx_convolve8_avg_horiz_avx2, vpx_convolve8_vert_avx2,
+ vpx_convolve8_avg_vert_avx2, vpx_convolve8_avx2, vpx_convolve8_avg_avx2,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+const ConvolveParam kArrayConvolve8_avx2[] = { ALL_SIZES(convolve8_avx2) };
+INSTANTIATE_TEST_SUITE_P(AVX2, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve8_avx2));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_AVX2
+
+#if HAVE_NEON
+#if CONFIG_VP9_HIGHBITDEPTH
+const ConvolveFunctions convolve8_neon(
+ wrap_convolve_copy_neon_8, wrap_convolve_avg_neon_8,
+ wrap_convolve8_horiz_neon_8, wrap_convolve8_avg_horiz_neon_8,
+ wrap_convolve8_vert_neon_8, wrap_convolve8_avg_vert_neon_8,
+ wrap_convolve8_neon_8, wrap_convolve8_avg_neon_8,
+ wrap_convolve8_horiz_neon_8, wrap_convolve8_avg_horiz_neon_8,
+ wrap_convolve8_vert_neon_8, wrap_convolve8_avg_vert_neon_8,
+ wrap_convolve8_neon_8, wrap_convolve8_avg_neon_8, 8);
+const ConvolveFunctions convolve10_neon(
+ wrap_convolve_copy_neon_10, wrap_convolve_avg_neon_10,
+ wrap_convolve8_horiz_neon_10, wrap_convolve8_avg_horiz_neon_10,
+ wrap_convolve8_vert_neon_10, wrap_convolve8_avg_vert_neon_10,
+ wrap_convolve8_neon_10, wrap_convolve8_avg_neon_10,
+ wrap_convolve8_horiz_neon_10, wrap_convolve8_avg_horiz_neon_10,
+ wrap_convolve8_vert_neon_10, wrap_convolve8_avg_vert_neon_10,
+ wrap_convolve8_neon_10, wrap_convolve8_avg_neon_10, 10);
+const ConvolveFunctions convolve12_neon(
+ wrap_convolve_copy_neon_12, wrap_convolve_avg_neon_12,
+ wrap_convolve8_horiz_neon_12, wrap_convolve8_avg_horiz_neon_12,
+ wrap_convolve8_vert_neon_12, wrap_convolve8_avg_vert_neon_12,
+ wrap_convolve8_neon_12, wrap_convolve8_avg_neon_12,
+ wrap_convolve8_horiz_neon_12, wrap_convolve8_avg_horiz_neon_12,
+ wrap_convolve8_vert_neon_12, wrap_convolve8_avg_vert_neon_12,
+ wrap_convolve8_neon_12, wrap_convolve8_avg_neon_12, 12);
+const ConvolveParam kArrayConvolve_neon[] = { ALL_SIZES(convolve8_neon),
+ ALL_SIZES(convolve10_neon),
+ ALL_SIZES(convolve12_neon) };
+#else
+const ConvolveFunctions convolve8_neon(
+ vpx_convolve_copy_neon, vpx_convolve_avg_neon, vpx_convolve8_horiz_neon,
+ vpx_convolve8_avg_horiz_neon, vpx_convolve8_vert_neon,
+ vpx_convolve8_avg_vert_neon, vpx_convolve8_neon, vpx_convolve8_avg_neon,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_neon, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve_neon[] = { ALL_SIZES(convolve8_neon) };
+#endif // CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(NEON, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve_neon));
+#endif // HAVE_NEON
+
+#if HAVE_DSPR2
+const ConvolveFunctions convolve8_dspr2(
+ vpx_convolve_copy_dspr2, vpx_convolve_avg_dspr2, vpx_convolve8_horiz_dspr2,
+ vpx_convolve8_avg_horiz_dspr2, vpx_convolve8_vert_dspr2,
+ vpx_convolve8_avg_vert_dspr2, vpx_convolve8_dspr2, vpx_convolve8_avg_dspr2,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_dspr2[] = { ALL_SIZES(convolve8_dspr2) };
+INSTANTIATE_TEST_SUITE_P(DSPR2, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve8_dspr2));
+#endif // HAVE_DSPR2
+
+#if HAVE_MSA
+const ConvolveFunctions convolve8_msa(
+ vpx_convolve_copy_msa, vpx_convolve_avg_msa, vpx_convolve8_horiz_msa,
+ vpx_convolve8_avg_horiz_msa, vpx_convolve8_vert_msa,
+ vpx_convolve8_avg_vert_msa, vpx_convolve8_msa, vpx_convolve8_avg_msa,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_msa, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_msa[] = { ALL_SIZES(convolve8_msa) };
+INSTANTIATE_TEST_SUITE_P(MSA, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve8_msa));
+#endif // HAVE_MSA
+
+#if HAVE_LSX
+const ConvolveFunctions convolve8_lsx(
+ vpx_convolve_copy_lsx, vpx_convolve_avg_lsx, vpx_convolve8_horiz_lsx,
+ vpx_convolve8_avg_horiz_lsx, vpx_convolve8_vert_lsx,
+ vpx_convolve8_avg_vert_lsx, vpx_convolve8_lsx, vpx_convolve8_avg_lsx,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_lsx[] = { ALL_SIZES(convolve8_lsx) };
+INSTANTIATE_TEST_SUITE_P(LSX, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve8_lsx));
+#endif // HAVE_LSX
+
+#if HAVE_VSX
+const ConvolveFunctions convolve8_vsx(
+ vpx_convolve_copy_vsx, vpx_convolve_avg_vsx, vpx_convolve8_horiz_vsx,
+ vpx_convolve8_avg_horiz_vsx, vpx_convolve8_vert_vsx,
+ vpx_convolve8_avg_vert_vsx, vpx_convolve8_vsx, vpx_convolve8_avg_vsx,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+const ConvolveParam kArrayConvolve_vsx[] = { ALL_SIZES(convolve8_vsx) };
+INSTANTIATE_TEST_SUITE_P(VSX, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve_vsx));
+#endif // HAVE_VSX
+
+#if HAVE_MMI
+const ConvolveFunctions convolve8_mmi(
+ vpx_convolve_copy_c, vpx_convolve_avg_mmi, vpx_convolve8_horiz_mmi,
+ vpx_convolve8_avg_horiz_mmi, vpx_convolve8_vert_mmi,
+ vpx_convolve8_avg_vert_mmi, vpx_convolve8_mmi, vpx_convolve8_avg_mmi,
+ vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c, vpx_scaled_vert_c,
+ vpx_scaled_avg_vert_c, vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+const ConvolveParam kArrayConvolve_mmi[] = { ALL_SIZES(convolve8_mmi) };
+INSTANTIATE_TEST_SUITE_P(MMI, ConvolveTest,
+ ::testing::ValuesIn(kArrayConvolve_mmi));
+#endif // HAVE_MMI
+} // namespace
diff --git a/media/libvpx/libvpx/test/cpu_speed_test.cc b/media/libvpx/libvpx/test/cpu_speed_test.cc
new file mode 100644
index 0000000000..a7623f09ac
--- /dev/null
+++ b/media/libvpx/libvpx/test/cpu_speed_test.cc
@@ -0,0 +1,156 @@
+/*
+ * 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"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+
+namespace {
+
+const int kMaxPSNR = 100;
+
+class CpuSpeedTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ CpuSpeedTest()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
+ set_cpu_used_(GET_PARAM(2)), min_psnr_(kMaxPSNR),
+ tune_content_(VP9E_CONTENT_DEFAULT) {}
+ virtual ~CpuSpeedTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_end_usage = VPX_VBR;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ }
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) { min_psnr_ = kMaxPSNR; }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->data.psnr.psnr[0] < min_psnr_) min_psnr_ = pkt->data.psnr.psnr[0];
+ }
+
+ ::libvpx_test::TestMode encoding_mode_;
+ int set_cpu_used_;
+ double min_psnr_;
+ int tune_content_;
+};
+
+TEST_P(CpuSpeedTest, TestQ0) {
+ // Validate that this non multiple of 64 wide clip encodes and decodes
+ // without a mismatch when passing in a very low max q. This pushes
+ // the encoder to producing lots of big partitions which will likely
+ // extend into the border and test the border condition.
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 400;
+ cfg_.rc_max_quantizer = 0;
+ cfg_.rc_min_quantizer = 0;
+
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 20);
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ EXPECT_GE(min_psnr_, kMaxPSNR);
+}
+
+TEST_P(CpuSpeedTest, TestScreencastQ0) {
+ ::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25);
+ cfg_.g_timebase = video.timebase();
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 400;
+ cfg_.rc_max_quantizer = 0;
+ cfg_.rc_min_quantizer = 0;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ EXPECT_GE(min_psnr_, kMaxPSNR);
+}
+
+TEST_P(CpuSpeedTest, TestTuneScreen) {
+ ::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25);
+ cfg_.g_timebase = video.timebase();
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_minsection_pct = 2000;
+ cfg_.rc_target_bitrate = 2000;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_min_quantizer = 0;
+ tune_content_ = VP9E_CONTENT_SCREEN;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(CpuSpeedTest, TestEncodeHighBitrate) {
+ // Validate that this non multiple of 64 wide clip encodes and decodes
+ // without a mismatch when passing in a very low max q. This pushes
+ // the encoder to producing lots of big partitions which will likely
+ // extend into the border and test the border condition.
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 12000;
+ cfg_.rc_max_quantizer = 10;
+ cfg_.rc_min_quantizer = 0;
+
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 20);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(CpuSpeedTest, TestLowBitrate) {
+ // Validate that this clip encodes and decodes without a mismatch
+ // when passing in a very high min q. This pushes the encoder to producing
+ // lots of small partitions which might will test the other condition.
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 200;
+ cfg_.rc_min_quantizer = 40;
+
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 20);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(CpuSpeedTest,
+ ::testing::Values(::libvpx_test::kTwoPassGood,
+ ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime),
+ ::testing::Range(0, 10));
+} // namespace
diff --git a/media/libvpx/libvpx/test/cq_test.cc b/media/libvpx/libvpx/test/cq_test.cc
new file mode 100644
index 0000000000..292adb0d04
--- /dev/null
+++ b/media/libvpx/libvpx/test/cq_test.cc
@@ -0,0 +1,131 @@
+/*
+ * 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 <cmath>
+#include <map>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+// CQ level range: [kCQLevelMin, kCQLevelMax).
+const int kCQLevelMin = 4;
+const int kCQLevelMax = 63;
+const int kCQLevelStep = 8;
+const unsigned int kCQTargetBitrate = 2000;
+
+class CQTest : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ // maps the cqlevel to the bitrate produced.
+ typedef std::map<int, uint32_t> BitrateMap;
+
+ static void SetUpTestSuite() { bitrates_.clear(); }
+
+ static void TearDownTestSuite() {
+ ASSERT_TRUE(!HasFailure())
+ << "skipping bitrate validation due to earlier failure.";
+ uint32_t prev_actual_bitrate = kCQTargetBitrate;
+ for (BitrateMap::const_iterator iter = bitrates_.begin();
+ iter != bitrates_.end(); ++iter) {
+ const uint32_t cq_actual_bitrate = iter->second;
+ EXPECT_LE(cq_actual_bitrate, prev_actual_bitrate)
+ << "cq_level: " << iter->first
+ << ", bitrate should decrease with increase in CQ level.";
+ prev_actual_bitrate = cq_actual_bitrate;
+ }
+ }
+
+ protected:
+ CQTest() : EncoderTest(GET_PARAM(0)), cq_level_(GET_PARAM(1)) {
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ }
+
+ virtual ~CQTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(libvpx_test::kTwoPassGood);
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ file_size_ = 0;
+ psnr_ = 0.0;
+ n_frames_ = 0;
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ if (cfg_.rc_end_usage == VPX_CQ) {
+ encoder->Control(VP8E_SET_CQ_LEVEL, cq_level_);
+ }
+ encoder->Control(VP8E_SET_CPUUSED, 3);
+ }
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ psnr_ += pow(10.0, pkt->data.psnr.psnr[0] / 10.0);
+ n_frames_++;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ file_size_ += pkt->data.frame.sz;
+ }
+
+ double GetLinearPSNROverBitrate() const {
+ double avg_psnr = log10(psnr_ / n_frames_) * 10.0;
+ return pow(10.0, avg_psnr / 10.0) / file_size_;
+ }
+
+ int cq_level() const { return cq_level_; }
+ size_t file_size() const { return file_size_; }
+ int n_frames() const { return n_frames_; }
+
+ static BitrateMap bitrates_;
+
+ private:
+ int cq_level_;
+ size_t file_size_;
+ double psnr_;
+ int n_frames_;
+};
+
+CQTest::BitrateMap CQTest::bitrates_;
+
+TEST_P(CQTest, LinearPSNRIsHigherForCQLevel) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = kCQTargetBitrate;
+ cfg_.g_lag_in_frames = 25;
+
+ cfg_.rc_end_usage = VPX_CQ;
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 30);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double cq_psnr_lin = GetLinearPSNROverBitrate();
+ const unsigned int cq_actual_bitrate =
+ static_cast<unsigned int>(file_size()) * 8 * 30 / (n_frames() * 1000);
+ EXPECT_LE(cq_actual_bitrate, kCQTargetBitrate);
+ bitrates_[cq_level()] = cq_actual_bitrate;
+
+ // try targeting the approximate same bitrate with VBR mode
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_target_bitrate = cq_actual_bitrate;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double vbr_psnr_lin = GetLinearPSNROverBitrate();
+ EXPECT_GE(cq_psnr_lin, vbr_psnr_lin);
+}
+
+VP8_INSTANTIATE_TEST_SUITE(CQTest, ::testing::Range(kCQLevelMin, kCQLevelMax,
+ kCQLevelStep));
+} // namespace
diff --git a/media/libvpx/libvpx/test/cx_set_ref.sh b/media/libvpx/libvpx/test/cx_set_ref.sh
new file mode 100755
index 0000000000..0a3d50ce1f
--- /dev/null
+++ b/media/libvpx/libvpx/test/cx_set_ref.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+##
+## Copyright (c) 2016 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.
+##
+## This file tests the libvpx cx_set_ref example. To add new tests to this
+## file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to cx_set_ref_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+cx_set_ref_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs cx_set_ref and updates the reference frame before encoding frame 90.
+# $1 is the codec name.
+vpx_set_ref() {
+ local codec="$1"
+ local encoder="${LIBVPX_BIN_PATH}/${codec}cx_set_ref${VPX_TEST_EXE_SUFFIX}"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/${codec}cx_set_ref_${codec}.ivf"
+ local ref_frame_num=90
+
+ if [ ! -x "${encoder}" ]; then
+ elog "${encoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" \
+ "${ref_frame_num}" ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+cx_set_ref_vp8() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ vpx_set_ref vp8 || return 1
+ fi
+}
+
+cx_set_ref_vp9() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ vpx_set_ref vp9 || return 1
+ fi
+}
+
+cx_set_ref_tests="cx_set_ref_vp8 cx_set_ref_vp9"
+
+run_tests cx_set_ref_verify_environment "${cx_set_ref_tests}"
diff --git a/media/libvpx/libvpx/test/dct16x16_test.cc b/media/libvpx/libvpx/test/dct16x16_test.cc
new file mode 100644
index 0000000000..4ad2263cfc
--- /dev/null
+++ b/media/libvpx/libvpx/test/dct16x16_test.cc
@@ -0,0 +1,1028 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/msvc.h" // for round()
+#include "vpx_ports/vpx_timer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+const int kNumCoeffs = 256;
+const double C1 = 0.995184726672197;
+const double C2 = 0.98078528040323;
+const double C3 = 0.956940335732209;
+const double C4 = 0.923879532511287;
+const double C5 = 0.881921264348355;
+const double C6 = 0.831469612302545;
+const double C7 = 0.773010453362737;
+const double C8 = 0.707106781186548;
+const double C9 = 0.634393284163646;
+const double C10 = 0.555570233019602;
+const double C11 = 0.471396736825998;
+const double C12 = 0.38268343236509;
+const double C13 = 0.290284677254462;
+const double C14 = 0.195090322016128;
+const double C15 = 0.098017140329561;
+
+void butterfly_16x16_dct_1d(double input[16], double output[16]) {
+ double step[16];
+ double intermediate[16];
+ double temp1, temp2;
+
+ // step 1
+ step[0] = input[0] + input[15];
+ step[1] = input[1] + input[14];
+ step[2] = input[2] + input[13];
+ step[3] = input[3] + input[12];
+ step[4] = input[4] + input[11];
+ step[5] = input[5] + input[10];
+ step[6] = input[6] + input[9];
+ step[7] = input[7] + input[8];
+ step[8] = input[7] - input[8];
+ step[9] = input[6] - input[9];
+ step[10] = input[5] - input[10];
+ step[11] = input[4] - input[11];
+ step[12] = input[3] - input[12];
+ step[13] = input[2] - input[13];
+ step[14] = input[1] - input[14];
+ step[15] = input[0] - input[15];
+
+ // step 2
+ output[0] = step[0] + step[7];
+ output[1] = step[1] + step[6];
+ output[2] = step[2] + step[5];
+ output[3] = step[3] + step[4];
+ output[4] = step[3] - step[4];
+ output[5] = step[2] - step[5];
+ output[6] = step[1] - step[6];
+ output[7] = step[0] - step[7];
+
+ temp1 = step[8] * C7;
+ temp2 = step[15] * C9;
+ output[8] = temp1 + temp2;
+
+ temp1 = step[9] * C11;
+ temp2 = step[14] * C5;
+ output[9] = temp1 - temp2;
+
+ temp1 = step[10] * C3;
+ temp2 = step[13] * C13;
+ output[10] = temp1 + temp2;
+
+ temp1 = step[11] * C15;
+ temp2 = step[12] * C1;
+ output[11] = temp1 - temp2;
+
+ temp1 = step[11] * C1;
+ temp2 = step[12] * C15;
+ output[12] = temp2 + temp1;
+
+ temp1 = step[10] * C13;
+ temp2 = step[13] * C3;
+ output[13] = temp2 - temp1;
+
+ temp1 = step[9] * C5;
+ temp2 = step[14] * C11;
+ output[14] = temp2 + temp1;
+
+ temp1 = step[8] * C9;
+ temp2 = step[15] * C7;
+ output[15] = temp2 - temp1;
+
+ // step 3
+ step[0] = output[0] + output[3];
+ step[1] = output[1] + output[2];
+ step[2] = output[1] - output[2];
+ step[3] = output[0] - output[3];
+
+ temp1 = output[4] * C14;
+ temp2 = output[7] * C2;
+ step[4] = temp1 + temp2;
+
+ temp1 = output[5] * C10;
+ temp2 = output[6] * C6;
+ step[5] = temp1 + temp2;
+
+ temp1 = output[5] * C6;
+ temp2 = output[6] * C10;
+ step[6] = temp2 - temp1;
+
+ temp1 = output[4] * C2;
+ temp2 = output[7] * C14;
+ step[7] = temp2 - temp1;
+
+ step[8] = output[8] + output[11];
+ step[9] = output[9] + output[10];
+ step[10] = output[9] - output[10];
+ step[11] = output[8] - output[11];
+
+ step[12] = output[12] + output[15];
+ step[13] = output[13] + output[14];
+ step[14] = output[13] - output[14];
+ step[15] = output[12] - output[15];
+
+ // step 4
+ output[0] = (step[0] + step[1]);
+ output[8] = (step[0] - step[1]);
+
+ temp1 = step[2] * C12;
+ temp2 = step[3] * C4;
+ temp1 = temp1 + temp2;
+ output[4] = 2 * (temp1 * C8);
+
+ temp1 = step[2] * C4;
+ temp2 = step[3] * C12;
+ temp1 = temp2 - temp1;
+ output[12] = 2 * (temp1 * C8);
+
+ output[2] = 2 * ((step[4] + step[5]) * C8);
+ output[14] = 2 * ((step[7] - step[6]) * C8);
+
+ temp1 = step[4] - step[5];
+ temp2 = step[6] + step[7];
+ output[6] = (temp1 + temp2);
+ output[10] = (temp1 - temp2);
+
+ intermediate[8] = step[8] + step[14];
+ intermediate[9] = step[9] + step[15];
+
+ temp1 = intermediate[8] * C12;
+ temp2 = intermediate[9] * C4;
+ temp1 = temp1 - temp2;
+ output[3] = 2 * (temp1 * C8);
+
+ temp1 = intermediate[8] * C4;
+ temp2 = intermediate[9] * C12;
+ temp1 = temp2 + temp1;
+ output[13] = 2 * (temp1 * C8);
+
+ output[9] = 2 * ((step[10] + step[11]) * C8);
+
+ intermediate[11] = step[10] - step[11];
+ intermediate[12] = step[12] + step[13];
+ intermediate[13] = step[12] - step[13];
+ intermediate[14] = step[8] - step[14];
+ intermediate[15] = step[9] - step[15];
+
+ output[15] = (intermediate[11] + intermediate[12]);
+ output[1] = -(intermediate[11] - intermediate[12]);
+
+ output[7] = 2 * (intermediate[13] * C8);
+
+ temp1 = intermediate[14] * C12;
+ temp2 = intermediate[15] * C4;
+ temp1 = temp1 - temp2;
+ output[11] = -2 * (temp1 * C8);
+
+ temp1 = intermediate[14] * C4;
+ temp2 = intermediate[15] * C12;
+ temp1 = temp2 + temp1;
+ output[5] = 2 * (temp1 * C8);
+}
+
+void reference_16x16_dct_2d(int16_t input[256], double output[256]) {
+ // First transform columns
+ for (int i = 0; i < 16; ++i) {
+ double temp_in[16], temp_out[16];
+ for (int j = 0; j < 16; ++j) temp_in[j] = input[j * 16 + i];
+ butterfly_16x16_dct_1d(temp_in, temp_out);
+ for (int j = 0; j < 16; ++j) output[j * 16 + i] = temp_out[j];
+ }
+ // Then transform rows
+ for (int i = 0; i < 16; ++i) {
+ double temp_in[16], temp_out[16];
+ for (int j = 0; j < 16; ++j) temp_in[j] = output[j + i * 16];
+ butterfly_16x16_dct_1d(temp_in, temp_out);
+ // Scale by some magic number
+ for (int j = 0; j < 16; ++j) output[j + i * 16] = temp_out[j] / 2;
+ }
+}
+
+typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
+ int tx_type);
+typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
+ int tx_type);
+
+typedef std::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param;
+typedef std::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param;
+typedef std::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct16x16Param;
+
+void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride,
+ int /*tx_type*/) {
+ vpx_fdct16x16_c(in, out, stride);
+}
+
+void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
+ int /*tx_type*/) {
+ vpx_idct16x16_256_add_c(in, dest, stride);
+}
+
+void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
+ vp9_fht16x16_c(in, out, stride, tx_type);
+}
+
+void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
+ int tx_type) {
+ vp9_iht16x16_256_add_c(in, dest, stride, tx_type);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct16x16_10(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct16x16_12(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+
+void idct16x16_10_ref(const tran_low_t *in, uint8_t *out, int stride,
+ int /*tx_type*/) {
+ idct16x16_10(in, out, stride);
+}
+
+void idct16x16_12_ref(const tran_low_t *in, uint8_t *out, int stride,
+ int /*tx_type*/) {
+ idct16x16_12(in, out, stride);
+}
+
+void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+ vp9_highbd_iht16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 10);
+}
+
+void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+ vp9_highbd_iht16x16_256_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 12);
+}
+
+#if HAVE_SSE2
+void idct16x16_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_10_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct16x16_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_10_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+
+void idct16x16_256_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_256_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct16x16_256_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_256_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+
+void idct16x16_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_10_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct16x16_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct16x16_10_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+#endif // HAVE_SSE2
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+class Trans16x16TestBase {
+ public:
+ virtual ~Trans16x16TestBase() {}
+
+ protected:
+ virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0;
+
+ virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0;
+
+ void RunAccuracyCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ uint32_t max_error = 0;
+ int64_t total_error = 0;
+ const int count_test_block = 10000;
+ for (int i = 0; i < count_test_block; ++i) {
+ DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ src[j] = rnd.Rand8();
+ dst[j] = rnd.Rand8();
+ test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src16[j] = rnd.Rand16() & mask_;
+ dst16[j] = rnd.Rand16() & mask_;
+ test_input_block[j] = src16[j] - dst16[j];
+#endif
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(
+ RunFwdTxfm(test_input_block, test_temp_block, pitch_));
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int32_t diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const int32_t diff = dst[j] - src[j];
+#endif
+ const uint32_t error = diff * diff;
+ if (max_error < error) max_error = error;
+ total_error += error;
+ }
+ }
+
+ EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error)
+ << "Error: 16x16 FHT/IHT has an individual round trip error > 1";
+
+ EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error)
+ << "Error: 16x16 FHT/IHT has average round trip error > 1 per block";
+ }
+
+ void RunCoeffCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
+ }
+
+ fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
+ ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
+
+ // The minimum quant value is 4.
+ for (int j = 0; j < kNumCoeffs; ++j)
+ EXPECT_EQ(output_block[j], output_ref_block[j]);
+ }
+ }
+
+ void RunMemCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
+ }
+ if (i == 0) {
+ for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = mask_;
+ } else if (i == 1) {
+ for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = -mask_;
+ }
+
+ fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
+ ASM_REGISTER_STATE_CHECK(
+ RunFwdTxfm(input_extreme_block, output_block, pitch_));
+
+ // The minimum quant value is 4.
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ EXPECT_EQ(output_block[j], output_ref_block[j]);
+ EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
+ << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
+ }
+ }
+ }
+
+ void RunQuantCheck(int dc_thred, int ac_thred) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 100000;
+ DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
+ }
+ if (i == 0) {
+ for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = mask_;
+ }
+ if (i == 1) {
+ for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = -mask_;
+ }
+
+ fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
+
+ // clear reconstructed pixel buffers
+ memset(dst, 0, kNumCoeffs * sizeof(uint8_t));
+ memset(ref, 0, kNumCoeffs * sizeof(uint8_t));
+#if CONFIG_VP9_HIGHBITDEPTH
+ memset(dst16, 0, kNumCoeffs * sizeof(uint16_t));
+ memset(ref16, 0, kNumCoeffs * sizeof(uint16_t));
+#endif
+
+ // quantization with maximum allowed step sizes
+ output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred;
+ for (int j = 1; j < kNumCoeffs; ++j) {
+ output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred;
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_);
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ inv_txfm_ref(output_ref_block, CAST_TO_BYTEPTR(ref16), pitch_,
+ tx_type_);
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(output_ref_block, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ for (int j = 0; j < kNumCoeffs; ++j) EXPECT_EQ(ref[j], dst[j]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ for (int j = 0; j < kNumCoeffs; ++j) EXPECT_EQ(ref16[j], dst16[j]);
+#endif
+ }
+ }
+ }
+
+ void RunInvAccuracyCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int i = 0; i < count_test_block; ++i) {
+ double out_r[kNumCoeffs];
+
+ // Initialize a test block with input range [-255, 255].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ src[j] = rnd.Rand8();
+ dst[j] = rnd.Rand8();
+ in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src16[j] = rnd.Rand16() & mask_;
+ dst16[j] = rnd.Rand16() & mask_;
+ in[j] = src16[j] - dst16[j];
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+
+ reference_16x16_dct_2d(in, out_r);
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
+ }
+
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), 16));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const uint32_t diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const uint32_t diff = dst[j] - src[j];
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ const uint32_t error = diff * diff;
+ EXPECT_GE(1u, error)
+ << "Error: 16x16 IDCT has error " << error << " at index " << j;
+ }
+ }
+ }
+
+ void RunSpeedTest() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ int c_sum_time = 0;
+ int simd_sum_time = 0;
+
+ DECLARE_ALIGNED(32, int16_t, input_block[kNumCoeffs]);
+ DECLARE_ALIGNED(32, tran_low_t, output_ref_block[kNumCoeffs]);
+ DECLARE_ALIGNED(32, tran_low_t, output_block[kNumCoeffs]);
+
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
+ }
+
+ vpx_usec_timer timer_c;
+ vpx_usec_timer_start(&timer_c);
+ for (int i = 0; i < count_test_block; ++i) {
+ vpx_fdct16x16_c(input_block, output_ref_block, pitch_);
+ }
+ vpx_usec_timer_mark(&timer_c);
+ c_sum_time += static_cast<int>(vpx_usec_timer_elapsed(&timer_c));
+
+ vpx_usec_timer timer_mod;
+ vpx_usec_timer_start(&timer_mod);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunFwdTxfm(input_block, output_block, pitch_);
+ }
+
+ vpx_usec_timer_mark(&timer_mod);
+ simd_sum_time += static_cast<int>(vpx_usec_timer_elapsed(&timer_mod));
+
+ printf(
+ "c_time = %d \t simd_time = %d \t Gain = %4.2f \n", c_sum_time,
+ simd_sum_time,
+ (static_cast<float>(c_sum_time) / static_cast<float>(simd_sum_time)));
+ }
+
+ void CompareInvReference(IdctFunc ref_txfm, int thresh) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ const int eob = 10;
+ const int16_t *scan = vp9_default_scan_orders[TX_16X16].scan;
+ DECLARE_ALIGNED(32, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int i = 0; i < count_test_block; ++i) {
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (j < eob) {
+ // Random values less than the threshold, either positive or negative
+ coeff[scan[j]] = rnd(thresh) * (1 - 2 * (i % 2));
+ } else {
+ coeff[scan[j]] = 0;
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ dst[j] = 0;
+ ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ dst16[j] = 0;
+ ref16[j] = 0;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ ref_txfm(coeff, ref, pitch_);
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+ } else {
+#if CONFIG_VP9_HIGHBITDEPTH
+ ref_txfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const uint32_t diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
+#else
+ const uint32_t diff = dst[j] - ref[j];
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ const uint32_t error = diff * diff;
+ EXPECT_EQ(0u, error) << "Error: 16x16 IDCT Comparison has error "
+ << error << " at index " << j;
+ }
+ }
+ }
+
+ void RunInvTrans16x16SpeedTest(IdctFunc ref_txfm, int thresh) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ const int eob = 10;
+ const int16_t *scan = vp9_default_scan_orders[TX_16X16].scan;
+ int64_t c_sum_time = 0;
+ int64_t simd_sum_time = 0;
+ DECLARE_ALIGNED(32, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (j < eob) {
+ // Random values less than the threshold, either positive or negative
+ coeff[scan[j]] = rnd(thresh);
+ } else {
+ coeff[scan[j]] = 0;
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ dst[j] = 0;
+ ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ dst16[j] = 0;
+ ref16[j] = 0;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+
+ if (bit_depth_ == VPX_BITS_8) {
+ vpx_usec_timer timer_c;
+ vpx_usec_timer_start(&timer_c);
+ for (int i = 0; i < count_test_block; ++i) {
+ ref_txfm(coeff, ref, pitch_);
+ }
+ vpx_usec_timer_mark(&timer_c);
+ c_sum_time += vpx_usec_timer_elapsed(&timer_c);
+
+ vpx_usec_timer timer_mod;
+ vpx_usec_timer_start(&timer_mod);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunInvTxfm(coeff, dst, pitch_);
+ }
+ vpx_usec_timer_mark(&timer_mod);
+ simd_sum_time += vpx_usec_timer_elapsed(&timer_mod);
+ } else {
+#if CONFIG_VP9_HIGHBITDEPTH
+ vpx_usec_timer timer_c;
+ vpx_usec_timer_start(&timer_c);
+ for (int i = 0; i < count_test_block; ++i) {
+ ref_txfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
+ }
+ vpx_usec_timer_mark(&timer_c);
+ c_sum_time += vpx_usec_timer_elapsed(&timer_c);
+
+ vpx_usec_timer timer_mod;
+ vpx_usec_timer_start(&timer_mod);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_);
+ }
+ vpx_usec_timer_mark(&timer_mod);
+ simd_sum_time += vpx_usec_timer_elapsed(&timer_mod);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ printf(
+ "c_time = %" PRId64 " \t simd_time = %" PRId64 " \t Gain = %4.2f \n",
+ c_sum_time, simd_sum_time,
+ (static_cast<float>(c_sum_time) / static_cast<float>(simd_sum_time)));
+ }
+
+ int pitch_;
+ int tx_type_;
+ vpx_bit_depth_t bit_depth_;
+ int mask_;
+ FhtFunc fwd_txfm_ref;
+ IhtFunc inv_txfm_ref;
+};
+
+class Trans16x16DCT : public Trans16x16TestBase,
+ public ::testing::TestWithParam<Dct16x16Param> {
+ public:
+ virtual ~Trans16x16DCT() {}
+
+ virtual void SetUp() {
+ fwd_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ tx_type_ = GET_PARAM(2);
+ bit_depth_ = GET_PARAM(3);
+ pitch_ = 16;
+ fwd_txfm_ref = fdct16x16_ref;
+ inv_txfm_ref = idct16x16_ref;
+ mask_ = (1 << bit_depth_) - 1;
+#if CONFIG_VP9_HIGHBITDEPTH
+ switch (bit_depth_) {
+ case VPX_BITS_10: inv_txfm_ref = idct16x16_10_ref; break;
+ case VPX_BITS_12: inv_txfm_ref = idct16x16_12_ref; break;
+ default: inv_txfm_ref = idct16x16_ref; break;
+ }
+#else
+ inv_txfm_ref = idct16x16_ref;
+#endif
+ }
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+ fwd_txfm_(in, out, stride);
+ }
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride);
+ }
+
+ FdctFunc fwd_txfm_;
+ IdctFunc inv_txfm_;
+};
+
+TEST_P(Trans16x16DCT, AccuracyCheck) { RunAccuracyCheck(); }
+
+TEST_P(Trans16x16DCT, CoeffCheck) { RunCoeffCheck(); }
+
+TEST_P(Trans16x16DCT, MemCheck) { RunMemCheck(); }
+
+TEST_P(Trans16x16DCT, QuantCheck) {
+ // Use maximally allowed quantization step sizes for DC and AC
+ // coefficients respectively.
+ RunQuantCheck(1336, 1828);
+}
+
+TEST_P(Trans16x16DCT, InvAccuracyCheck) { RunInvAccuracyCheck(); }
+
+TEST_P(Trans16x16DCT, DISABLED_Speed) { RunSpeedTest(); }
+
+class Trans16x16HT : public Trans16x16TestBase,
+ public ::testing::TestWithParam<Ht16x16Param> {
+ public:
+ virtual ~Trans16x16HT() {}
+
+ virtual void SetUp() {
+ fwd_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ tx_type_ = GET_PARAM(2);
+ bit_depth_ = GET_PARAM(3);
+ pitch_ = 16;
+ fwd_txfm_ref = fht16x16_ref;
+ inv_txfm_ref = iht16x16_ref;
+ mask_ = (1 << bit_depth_) - 1;
+#if CONFIG_VP9_HIGHBITDEPTH
+ switch (bit_depth_) {
+ case VPX_BITS_10: inv_txfm_ref = iht16x16_10; break;
+ case VPX_BITS_12: inv_txfm_ref = iht16x16_12; break;
+ default: inv_txfm_ref = iht16x16_ref; break;
+ }
+#else
+ inv_txfm_ref = iht16x16_ref;
+#endif
+ }
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+ fwd_txfm_(in, out, stride, tx_type_);
+ }
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride, tx_type_);
+ }
+
+ FhtFunc fwd_txfm_;
+ IhtFunc inv_txfm_;
+};
+
+TEST_P(Trans16x16HT, AccuracyCheck) { RunAccuracyCheck(); }
+
+TEST_P(Trans16x16HT, CoeffCheck) { RunCoeffCheck(); }
+
+TEST_P(Trans16x16HT, MemCheck) { RunMemCheck(); }
+
+TEST_P(Trans16x16HT, QuantCheck) {
+ // The encoder skips any non-DC intra prediction modes,
+ // when the quantization step size goes beyond 988.
+ RunQuantCheck(429, 729);
+}
+
+class InvTrans16x16DCT : public Trans16x16TestBase,
+ public ::testing::TestWithParam<Idct16x16Param> {
+ public:
+ virtual ~InvTrans16x16DCT() {}
+
+ virtual void SetUp() {
+ ref_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ thresh_ = GET_PARAM(2);
+ bit_depth_ = GET_PARAM(3);
+ pitch_ = 16;
+ mask_ = (1 << bit_depth_) - 1;
+ }
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunFwdTxfm(int16_t * /*in*/, tran_low_t * /*out*/, int /*stride*/) {}
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride);
+ }
+
+ IdctFunc ref_txfm_;
+ IdctFunc inv_txfm_;
+ int thresh_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InvTrans16x16DCT);
+
+TEST_P(InvTrans16x16DCT, CompareReference) {
+ CompareInvReference(ref_txfm_, thresh_);
+}
+
+TEST_P(InvTrans16x16DCT, DISABLED_Speed) {
+ RunInvTrans16x16SpeedTest(ref_txfm_, thresh_);
+}
+
+using std::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, Trans16x16DCT,
+ ::testing::Values(
+ make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_10, 0, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_12, 0, VPX_BITS_12),
+ make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_SUITE_P(C, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_c,
+ &vpx_idct16x16_256_add_c,
+ 0, VPX_BITS_8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, Trans16x16HT,
+ ::testing::Values(
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 0, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 1, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 2, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 3, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 0, VPX_BITS_12),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 1, VPX_BITS_12),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 2, VPX_BITS_12),
+ make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 3, VPX_BITS_12),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ C, Trans16x16HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(C, InvTrans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_idct16x16_256_add_c,
+ &vpx_idct16x16_256_add_c,
+ 6225, VPX_BITS_8)));
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_neon,
+ &vpx_idct16x16_256_add_neon, 0, VPX_BITS_8)));
+#endif // HAVE_NEON && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_NEON && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Trans16x16DCT,
+ ::testing::Values(
+ make_tuple(&vpx_highbd_fdct16x16_neon, &idct16x16_10, 0, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct16x16_neon, &idct16x16_12, 0, VPX_BITS_12),
+ make_tuple(&vpx_fdct16x16_neon, &vpx_idct16x16_256_add_c, 0,
+ VPX_BITS_8)));
+#endif // HAVE_NEON && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_sse2,
+ &vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Trans16x16HT,
+ ::testing::Values(make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
+ 0, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
+ 1, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
+ 2, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2,
+ 3, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(SSE2, InvTrans16x16DCT,
+ ::testing::Values(make_tuple(
+ &vpx_idct16x16_256_add_c,
+ &vpx_idct16x16_256_add_sse2, 6225, VPX_BITS_8)));
+#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_avx2,
+ &vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(AVX2, InvTrans16x16DCT,
+ ::testing::Values(make_tuple(
+ &vpx_idct16x16_256_add_c,
+ &vpx_idct16x16_256_add_avx2, 6225, VPX_BITS_8)));
+#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Trans16x16DCT,
+ ::testing::Values(
+ make_tuple(&vpx_highbd_fdct16x16_sse2, &idct16x16_10, 0, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_256_add_10_sse2, 0,
+ VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct16x16_sse2, &idct16x16_12, 0, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_256_add_12_sse2, 0,
+ VPX_BITS_12),
+ make_tuple(&vpx_fdct16x16_sse2, &vpx_idct16x16_256_add_c, 0,
+ VPX_BITS_8)));
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Trans16x16HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 3,
+ VPX_BITS_8)));
+// Optimizations take effect at a threshold of 3155, so we use a value close to
+// that to test both branches.
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, InvTrans16x16DCT,
+ ::testing::Values(make_tuple(&idct16x16_10_add_10_c,
+ &idct16x16_10_add_10_sse2, 3167, VPX_BITS_10),
+ make_tuple(&idct16x16_10, &idct16x16_256_add_10_sse2,
+ 3167, VPX_BITS_10),
+ make_tuple(&idct16x16_10_add_12_c,
+ &idct16x16_10_add_12_sse2, 3167, VPX_BITS_12),
+ make_tuple(&idct16x16_12, &idct16x16_256_add_12_sse2,
+ 3167, VPX_BITS_12)));
+#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ MSA, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_msa, &vpx_idct16x16_256_add_msa,
+ 0, VPX_BITS_8)));
+INSTANTIATE_TEST_SUITE_P(
+ MSA, Trans16x16HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 3,
+ VPX_BITS_8)));
+#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ VSX, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_vsx,
+ 0, VPX_BITS_8)));
+#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(LSX, Trans16x16DCT,
+ ::testing::Values(make_tuple(&vpx_fdct16x16_lsx,
+ &vpx_idct16x16_256_add_c,
+ 0, VPX_BITS_8)));
+#endif // HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+} // namespace
diff --git a/media/libvpx/libvpx/test/dct32x32_test.cc b/media/libvpx/libvpx/test/dct32x32_test.cc
new file mode 100644
index 0000000000..1167038b5f
--- /dev/null
+++ b/media/libvpx/libvpx/test/dct32x32_test.cc
@@ -0,0 +1,605 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/msvc.h" // for round()
+#include "vpx_ports/vpx_timer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+const int kNumCoeffs = 1024;
+const double kPi = 3.141592653589793238462643383279502884;
+void reference_32x32_dct_1d(const double in[32], double out[32]) {
+ const double kInvSqrt2 = 0.707106781186547524400844362104;
+ for (int k = 0; k < 32; k++) {
+ out[k] = 0.0;
+ for (int n = 0; n < 32; n++) {
+ out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 64.0);
+ }
+ if (k == 0) out[k] = out[k] * kInvSqrt2;
+ }
+}
+
+void reference_32x32_dct_2d(const int16_t input[kNumCoeffs],
+ double output[kNumCoeffs]) {
+ // First transform columns
+ for (int i = 0; i < 32; ++i) {
+ double temp_in[32], temp_out[32];
+ for (int j = 0; j < 32; ++j) temp_in[j] = input[j * 32 + i];
+ reference_32x32_dct_1d(temp_in, temp_out);
+ for (int j = 0; j < 32; ++j) output[j * 32 + i] = temp_out[j];
+ }
+ // Then transform rows
+ for (int i = 0; i < 32; ++i) {
+ double temp_in[32], temp_out[32];
+ for (int j = 0; j < 32; ++j) temp_in[j] = output[j + i * 32];
+ reference_32x32_dct_1d(temp_in, temp_out);
+ // Scale by some magic number
+ for (int j = 0; j < 32; ++j) output[j + i * 32] = temp_out[j] / 4;
+ }
+}
+
+typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
+
+typedef std::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t>
+ Trans32x32Param;
+
+typedef std::tuple<InvTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t, int, int>
+ InvTrans32x32Param;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct32x32_10(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct32x32_1024_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct32x32_12(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct32x32_1024_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+class Trans32x32Test : public AbstractBench,
+ public ::testing::TestWithParam<Trans32x32Param> {
+ public:
+ virtual ~Trans32x32Test() {}
+ virtual void SetUp() {
+ fwd_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ version_ = GET_PARAM(2); // 0: high precision forward transform
+ // 1: low precision version for rd loop
+ bit_depth_ = GET_PARAM(3);
+ mask_ = (1 << bit_depth_) - 1;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ int version_;
+ vpx_bit_depth_t bit_depth_;
+ int mask_;
+ FwdTxfmFunc fwd_txfm_;
+ InvTxfmFunc inv_txfm_;
+
+ int16_t *bench_in_;
+ tran_low_t *bench_out_;
+ virtual void Run();
+};
+
+void Trans32x32Test::Run() { fwd_txfm_(bench_in_, bench_out_, 32); }
+
+TEST_P(Trans32x32Test, AccuracyCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ uint32_t max_error = 0;
+ int64_t total_error = 0;
+ const int count_test_block = 10000;
+ DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ src[j] = rnd.Rand8();
+ dst[j] = rnd.Rand8();
+ test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src16[j] = rnd.Rand16() & mask_;
+ dst16[j] = rnd.Rand16() & mask_;
+ test_input_block[j] = src16[j] - dst16[j];
+#endif
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(fwd_txfm_(test_input_block, test_temp_block, 32));
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(
+ inv_txfm_(test_temp_block, CAST_TO_BYTEPTR(dst16), 32));
+#endif
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int32_t diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const int32_t diff = dst[j] - src[j];
+#endif
+ const uint32_t error = diff * diff;
+ if (max_error < error) max_error = error;
+ total_error += error;
+ }
+ }
+
+ if (version_ == 1) {
+ max_error /= 2;
+ total_error /= 45;
+ }
+
+ EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error)
+ << "Error: 32x32 FDCT/IDCT has an individual round-trip error > 1";
+
+ EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error)
+ << "Error: 32x32 FDCT/IDCT has average round-trip error > 1 per block";
+}
+
+TEST_P(Trans32x32Test, CoeffCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+
+ DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
+ }
+
+ const int stride = 32;
+ vpx_fdct32x32_c(input_block, output_ref_block, stride);
+ ASM_REGISTER_STATE_CHECK(fwd_txfm_(input_block, output_block, stride));
+
+ if (version_ == 0) {
+ for (int j = 0; j < kNumCoeffs; ++j)
+ EXPECT_EQ(output_block[j], output_ref_block[j])
+ << "Error: 32x32 FDCT versions have mismatched coefficients";
+ } else {
+ for (int j = 0; j < kNumCoeffs; ++j)
+ EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
+ << "Error: 32x32 FDCT rd has mismatched coefficients";
+ }
+ }
+}
+
+TEST_P(Trans32x32Test, MemCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 2000;
+
+ DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ input_extreme_block[j] = rnd.Rand8() & 1 ? mask_ : -mask_;
+ }
+ if (i == 0) {
+ for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = mask_;
+ } else if (i == 1) {
+ for (int j = 0; j < kNumCoeffs; ++j) input_extreme_block[j] = -mask_;
+ }
+
+ const int stride = 32;
+ vpx_fdct32x32_c(input_extreme_block, output_ref_block, stride);
+ ASM_REGISTER_STATE_CHECK(
+ fwd_txfm_(input_extreme_block, output_block, stride));
+
+ // The minimum quant value is 4.
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (version_ == 0) {
+ EXPECT_EQ(output_block[j], output_ref_block[j])
+ << "Error: 32x32 FDCT versions have mismatched coefficients";
+ } else {
+ EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
+ << "Error: 32x32 FDCT rd has mismatched coefficients";
+ }
+ EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_ref_block[j]))
+ << "Error: 32x32 FDCT C has coefficient larger than 4*DCT_MAX_VALUE";
+ EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
+ << "Error: 32x32 FDCT has coefficient larger than "
+ << "4*DCT_MAX_VALUE";
+ }
+ }
+}
+
+TEST_P(Trans32x32Test, DISABLED_Speed) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+ DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+ bench_in_ = input_extreme_block;
+ bench_out_ = output_block;
+
+ RunNTimes(INT16_MAX);
+ PrintMedian("32x32");
+}
+
+TEST_P(Trans32x32Test, InverseAccuracy) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+ for (int i = 0; i < count_test_block; ++i) {
+ double out_r[kNumCoeffs];
+
+ // Initialize a test block with input range [-255, 255]
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ src[j] = rnd.Rand8();
+ dst[j] = rnd.Rand8();
+ in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src16[j] = rnd.Rand16() & mask_;
+ dst16[j] = rnd.Rand16() & mask_;
+ in[j] = src16[j] - dst16[j];
+#endif
+ }
+ }
+
+ reference_32x32_dct_2d(in, out_r);
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CAST_TO_BYTEPTR(dst16), 32));
+#endif
+ }
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const int diff = dst[j] - src[j];
+#endif
+ const int error = diff * diff;
+ EXPECT_GE(1, error) << "Error: 32x32 IDCT has error " << error
+ << " at index " << j;
+ }
+ }
+}
+
+class InvTrans32x32Test : public ::testing::TestWithParam<InvTrans32x32Param> {
+ public:
+ virtual ~InvTrans32x32Test() {}
+ virtual void SetUp() {
+ ref_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ version_ = GET_PARAM(2); // 0: high precision forward transform
+ // 1: low precision version for rd loop
+ bit_depth_ = GET_PARAM(3);
+ eob_ = GET_PARAM(4);
+ thresh_ = GET_PARAM(4);
+ mask_ = (1 << bit_depth_) - 1;
+ pitch_ = 32;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunRefTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ ref_txfm_(out, dst, stride);
+ }
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride);
+ }
+ int version_;
+ vpx_bit_depth_t bit_depth_;
+ int mask_;
+ int eob_;
+ int thresh_;
+
+ InvTxfmFunc ref_txfm_;
+ InvTxfmFunc inv_txfm_;
+ int pitch_;
+
+ void RunInvTrans32x32SpeedTest() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ int64_t c_sum_time = 0;
+ int64_t simd_sum_time = 0;
+ const int16_t *scan = vp9_default_scan_orders[TX_32X32].scan;
+ DECLARE_ALIGNED(32, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (j < eob_) {
+ // Random values less than the threshold, either positive or negative
+ coeff[scan[j]] = rnd(thresh_);
+ } else {
+ coeff[scan[j]] = 0;
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ dst[j] = 0;
+ ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ dst16[j] = 0;
+ ref16[j] = 0;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+
+ if (bit_depth_ == VPX_BITS_8) {
+ vpx_usec_timer timer_c;
+ vpx_usec_timer_start(&timer_c);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunRefTxfm(coeff, ref, pitch_);
+ }
+ vpx_usec_timer_mark(&timer_c);
+ c_sum_time += vpx_usec_timer_elapsed(&timer_c);
+
+ vpx_usec_timer timer_mod;
+ vpx_usec_timer_start(&timer_mod);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunInvTxfm(coeff, dst, pitch_);
+ }
+ vpx_usec_timer_mark(&timer_mod);
+ simd_sum_time += vpx_usec_timer_elapsed(&timer_mod);
+ } else {
+#if CONFIG_VP9_HIGHBITDEPTH
+ vpx_usec_timer timer_c;
+ vpx_usec_timer_start(&timer_c);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunRefTxfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
+ }
+ vpx_usec_timer_mark(&timer_c);
+ c_sum_time += vpx_usec_timer_elapsed(&timer_c);
+
+ vpx_usec_timer timer_mod;
+ vpx_usec_timer_start(&timer_mod);
+ for (int i = 0; i < count_test_block; ++i) {
+ RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_);
+ }
+ vpx_usec_timer_mark(&timer_mod);
+ simd_sum_time += vpx_usec_timer_elapsed(&timer_mod);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ printf(
+ "c_time = %" PRId64 " \t simd_time = %" PRId64 " \t Gain = %4.2f \n",
+ c_sum_time, simd_sum_time,
+ (static_cast<float>(c_sum_time) / static_cast<float>(simd_sum_time)));
+ }
+
+ void CompareInvReference32x32() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ const int eob = 31;
+ const int16_t *scan = vp9_default_scan_orders[TX_32X32].scan;
+ DECLARE_ALIGNED(32, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int i = 0; i < count_test_block; ++i) {
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (j < eob) {
+ coeff[scan[j]] = rnd.Rand8Extremes();
+ } else {
+ coeff[scan[j]] = 0;
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ dst[j] = 0;
+ ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ dst16[j] = 0;
+ ref16[j] = 0;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ RunRefTxfm(coeff, ref, pitch_);
+ RunInvTxfm(coeff, dst, pitch_);
+ } else {
+#if CONFIG_VP9_HIGHBITDEPTH
+ RunRefTxfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const uint32_t diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
+#else
+ const uint32_t diff = dst[j] - ref[j];
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ const uint32_t error = diff * diff;
+ EXPECT_EQ(0u, error) << "Error: 32x32 IDCT Comparison has error "
+ << error << " at index " << j;
+ }
+ }
+ }
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InvTrans32x32Test);
+
+TEST_P(InvTrans32x32Test, DISABLED_Speed) { RunInvTrans32x32SpeedTest(); }
+TEST_P(InvTrans32x32Test, CompareReference) { CompareInvReference32x32(); }
+
+using std::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, Trans32x32Test,
+ ::testing::Values(
+ make_tuple(&vpx_highbd_fdct32x32_c, &idct32x32_10, 0, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct32x32_rd_c, &idct32x32_10, 1, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct32x32_c, &idct32x32_12, 0, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct32x32_rd_c, &idct32x32_12, 1, VPX_BITS_12),
+ make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_c, 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_c, &vpx_idct32x32_1024_add_c, 1,
+ VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ C, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_c, 0,
+ VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_c, &vpx_idct32x32_1024_add_c,
+ 1, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ C, InvTrans32x32Test,
+ ::testing::Values(
+ (make_tuple(&vpx_idct32x32_1024_add_c, &vpx_idct32x32_1024_add_c, 0,
+ VPX_BITS_8, 32, 6225)),
+ make_tuple(&vpx_idct32x32_135_add_c, &vpx_idct32x32_135_add_c, 0,
+ VPX_BITS_8, 16, 6255)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_neon,
+ &vpx_idct32x32_1024_add_neon, 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_neon,
+ &vpx_idct32x32_1024_add_neon, 1, VPX_BITS_8)));
+#endif // HAVE_NEON && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_sse2,
+ &vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_sse2,
+ &vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, InvTrans32x32Test,
+ ::testing::Values(
+ (make_tuple(&vpx_idct32x32_1024_add_c, &vpx_idct32x32_1024_add_sse2, 0,
+ VPX_BITS_8, 32, 6225)),
+ make_tuple(&vpx_idct32x32_135_add_c, &vpx_idct32x32_135_add_sse2, 0,
+ VPX_BITS_8, 16, 6225)));
+#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Trans32x32Test,
+ ::testing::Values(
+ make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_10, 0, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct32x32_rd_sse2, &idct32x32_10, 1,
+ VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_12, 0, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct32x32_rd_sse2, &idct32x32_12, 1,
+ VPX_BITS_12),
+ make_tuple(&vpx_fdct32x32_sse2, &vpx_idct32x32_1024_add_c, 0,
+ VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_sse2, &vpx_idct32x32_1024_add_c, 1,
+ VPX_BITS_8)));
+#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_avx2,
+ &vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_avx2,
+ &vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, InvTrans32x32Test,
+ ::testing::Values(
+ (make_tuple(&vpx_idct32x32_1024_add_c, &vpx_idct32x32_1024_add_avx2, 0,
+ VPX_BITS_8, 32, 6225)),
+ make_tuple(&vpx_idct32x32_135_add_c, &vpx_idct32x32_135_add_avx2, 0,
+ VPX_BITS_8, 16, 6225)));
+#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ MSA, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_msa,
+ &vpx_idct32x32_1024_add_msa, 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_msa,
+ &vpx_idct32x32_1024_add_msa, 1, VPX_BITS_8)));
+#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ VSX, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_c, &vpx_idct32x32_1024_add_vsx,
+ 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_vsx,
+ &vpx_idct32x32_1024_add_vsx, 1, VPX_BITS_8)));
+#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ LSX, Trans32x32Test,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_lsx,
+ &vpx_idct32x32_1024_add_lsx, 0, VPX_BITS_8),
+ make_tuple(&vpx_fdct32x32_rd_lsx,
+ &vpx_idct32x32_1024_add_lsx, 1, VPX_BITS_8)));
+#endif // HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+} // namespace
diff --git a/media/libvpx/libvpx/test/dct_partial_test.cc b/media/libvpx/libvpx/test/dct_partial_test.cc
new file mode 100644
index 0000000000..e57fa0f48b
--- /dev/null
+++ b/media/libvpx/libvpx/test/dct_partial_test.cc
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2017 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/buffer.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_dsp/vpx_dsp_common.h"
+
+using libvpx_test::ACMRandom;
+using libvpx_test::Buffer;
+using std::make_tuple;
+using std::tuple;
+
+namespace {
+typedef void (*PartialFdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+
+typedef tuple<PartialFdctFunc, int /* size */, vpx_bit_depth_t>
+ PartialFdctParam;
+
+tran_low_t partial_fdct_ref(const Buffer<int16_t> &in, int size) {
+ int64_t sum = 0;
+ if (in.TopLeftPixel() != nullptr) {
+ for (int y = 0; y < size; ++y) {
+ for (int x = 0; x < size; ++x) {
+ sum += in.TopLeftPixel()[y * in.stride() + x];
+ }
+ }
+ } else {
+ assert(0);
+ }
+
+ switch (size) {
+ case 4: sum *= 2; break;
+ case 8: /*sum = sum;*/ break;
+ case 16: sum >>= 1; break;
+ case 32: sum >>= 3; break;
+ }
+
+ return static_cast<tran_low_t>(sum);
+}
+
+class PartialFdctTest : public ::testing::TestWithParam<PartialFdctParam> {
+ public:
+ PartialFdctTest() {
+ fwd_txfm_ = GET_PARAM(0);
+ size_ = GET_PARAM(1);
+ bit_depth_ = GET_PARAM(2);
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunTest() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int16_t maxvalue =
+ clip_pixel_highbd(std::numeric_limits<int16_t>::max(), bit_depth_);
+ const int16_t minvalue = -maxvalue;
+ Buffer<int16_t> input_block =
+ Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
+ ASSERT_TRUE(input_block.Init());
+ Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
+ ASSERT_TRUE(output_block.Init());
+
+ if (output_block.TopLeftPixel() != nullptr) {
+ for (int i = 0; i < 100; ++i) {
+ if (i == 0) {
+ input_block.Set(maxvalue);
+ } else if (i == 1) {
+ input_block.Set(minvalue);
+ } else {
+ input_block.Set(&rnd, minvalue, maxvalue);
+ }
+
+ ASM_REGISTER_STATE_CHECK(fwd_txfm_(input_block.TopLeftPixel(),
+ output_block.TopLeftPixel(),
+ input_block.stride()));
+
+ EXPECT_EQ(partial_fdct_ref(input_block, size_),
+ output_block.TopLeftPixel()[0]);
+ }
+ } else {
+ assert(0);
+ }
+ }
+
+ PartialFdctFunc fwd_txfm_;
+ vpx_bit_depth_t bit_depth_;
+ int size_;
+};
+
+TEST_P(PartialFdctTest, PartialFdctTest) { RunTest(); }
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_highbd_fdct32x32_1_c, 32, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct32x32_1_c, 32, VPX_BITS_10),
+ make_tuple(&vpx_fdct32x32_1_c, 32, VPX_BITS_8),
+ make_tuple(&vpx_highbd_fdct16x16_1_c, 16, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct16x16_1_c, 16, VPX_BITS_10),
+ make_tuple(&vpx_fdct16x16_1_c, 16, VPX_BITS_8),
+ make_tuple(&vpx_highbd_fdct8x8_1_c, 8, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct8x8_1_c, 8, VPX_BITS_10),
+ make_tuple(&vpx_fdct8x8_1_c, 8, VPX_BITS_8),
+ make_tuple(&vpx_fdct4x4_1_c, 4, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ C, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_1_c, 32, VPX_BITS_8),
+ make_tuple(&vpx_fdct16x16_1_c, 16, VPX_BITS_8),
+ make_tuple(&vpx_fdct8x8_1_c, 8, VPX_BITS_8),
+ make_tuple(&vpx_fdct4x4_1_c, 4, VPX_BITS_8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2, 32, VPX_BITS_8),
+ make_tuple(&vpx_fdct16x16_1_sse2, 16, VPX_BITS_8),
+ make_tuple(&vpx_fdct8x8_1_sse2, 8, VPX_BITS_8),
+ make_tuple(&vpx_fdct4x4_1_sse2, 4, VPX_BITS_8)));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ NEON, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_highbd_fdct32x32_1_neon, 32, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct32x32_1_neon, 32, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct32x32_1_neon, 32, VPX_BITS_8),
+ make_tuple(&vpx_highbd_fdct16x16_1_neon, 16, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct16x16_1_neon, 16, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct16x16_1_neon, 16, VPX_BITS_8),
+ make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_12),
+ make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_10),
+ make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_8),
+ make_tuple(&vpx_fdct4x4_1_neon, 4, VPX_BITS_12),
+ make_tuple(&vpx_fdct4x4_1_neon, 4, VPX_BITS_10),
+ make_tuple(&vpx_fdct4x4_1_neon, 4, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ NEON, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_1_neon, 32, VPX_BITS_8),
+ make_tuple(&vpx_fdct16x16_1_neon, 16, VPX_BITS_8),
+ make_tuple(&vpx_fdct8x8_1_neon, 8, VPX_BITS_8),
+ make_tuple(&vpx_fdct4x4_1_neon, 4, VPX_BITS_8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_NEON
+
+#if HAVE_MSA
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(MSA, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_1_msa, 8,
+ VPX_BITS_8)));
+#else // !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ MSA, PartialFdctTest,
+ ::testing::Values(make_tuple(&vpx_fdct32x32_1_msa, 32, VPX_BITS_8),
+ make_tuple(&vpx_fdct16x16_1_msa, 16, VPX_BITS_8),
+ make_tuple(&vpx_fdct8x8_1_msa, 8, VPX_BITS_8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_MSA
+} // namespace
diff --git a/media/libvpx/libvpx/test/dct_test.cc b/media/libvpx/libvpx/test/dct_test.cc
new file mode 100644
index 0000000000..235c407237
--- /dev/null
+++ b/media/libvpx/libvpx/test/dct_test.cc
@@ -0,0 +1,790 @@
+/*
+ * Copyright (c) 2017 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/buffer.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+using libvpx_test::Buffer;
+using std::make_tuple;
+using std::tuple;
+
+namespace {
+typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
+ int tx_type);
+typedef void (*FhtFuncRef)(const Buffer<int16_t> &in, Buffer<tran_low_t> *out,
+ int size, int tx_type);
+typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
+ int tx_type);
+typedef void (*IhtWithBdFunc)(const tran_low_t *in, uint8_t *out, int stride,
+ int tx_type, int bd);
+
+template <FdctFunc fn>
+void fdct_wrapper(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
+ (void)tx_type;
+ fn(in, out, stride);
+}
+
+template <IdctFunc fn>
+void idct_wrapper(const tran_low_t *in, uint8_t *out, int stride, int tx_type,
+ int bd) {
+ (void)tx_type;
+ (void)bd;
+ fn(in, out, stride);
+}
+
+template <IhtFunc fn>
+void iht_wrapper(const tran_low_t *in, uint8_t *out, int stride, int tx_type,
+ int bd) {
+ (void)bd;
+ fn(in, out, stride, tx_type);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+typedef void (*HighbdIdctFunc)(const tran_low_t *in, uint16_t *out, int stride,
+ int bd);
+
+typedef void (*HighbdIhtFunc)(const tran_low_t *in, uint16_t *out, int stride,
+ int tx_type, int bd);
+
+template <HighbdIdctFunc fn>
+void highbd_idct_wrapper(const tran_low_t *in, uint8_t *out, int stride,
+ int tx_type, int bd) {
+ (void)tx_type;
+ fn(in, CAST_TO_SHORTPTR(out), stride, bd);
+}
+
+template <HighbdIhtFunc fn>
+void highbd_iht_wrapper(const tran_low_t *in, uint8_t *out, int stride,
+ int tx_type, int bd) {
+ fn(in, CAST_TO_SHORTPTR(out), stride, tx_type, bd);
+}
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+struct FuncInfo {
+ FhtFunc ft_func;
+ IhtWithBdFunc it_func;
+ int size;
+ int pixel_size;
+};
+
+/* forward transform, inverse transform, size, transform type, bit depth */
+typedef tuple<int, const FuncInfo *, int, vpx_bit_depth_t> DctParam;
+
+void fdct_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
+ int /*tx_type*/) {
+ const int16_t *i = in.TopLeftPixel();
+ const int i_stride = in.stride();
+ tran_low_t *o = out->TopLeftPixel();
+ if (size == 4) {
+ vpx_fdct4x4_c(i, o, i_stride);
+ } else if (size == 8) {
+ vpx_fdct8x8_c(i, o, i_stride);
+ } else if (size == 16) {
+ vpx_fdct16x16_c(i, o, i_stride);
+ } else if (size == 32) {
+ vpx_fdct32x32_c(i, o, i_stride);
+ }
+}
+
+void fht_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
+ int tx_type) {
+ const int16_t *i = in.TopLeftPixel();
+ const int i_stride = in.stride();
+ tran_low_t *o = out->TopLeftPixel();
+ if (size == 4) {
+ vp9_fht4x4_c(i, o, i_stride, tx_type);
+ } else if (size == 8) {
+ vp9_fht8x8_c(i, o, i_stride, tx_type);
+ } else if (size == 16) {
+ vp9_fht16x16_c(i, o, i_stride, tx_type);
+ }
+}
+
+void fwht_ref(const Buffer<int16_t> &in, Buffer<tran_low_t> *out, int size,
+ int /*tx_type*/) {
+ ASSERT_EQ(size, 4);
+ vp9_fwht4x4_c(in.TopLeftPixel(), out->TopLeftPixel(), in.stride());
+}
+
+class TransTestBase : public ::testing::TestWithParam<DctParam> {
+ public:
+ virtual void SetUp() {
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ const int idx = GET_PARAM(0);
+ const FuncInfo *func_info = &(GET_PARAM(1)[idx]);
+ tx_type_ = GET_PARAM(2);
+ bit_depth_ = GET_PARAM(3);
+ fwd_txfm_ = func_info->ft_func;
+ inv_txfm_ = func_info->it_func;
+ size_ = func_info->size;
+ pixel_size_ = func_info->pixel_size;
+ max_pixel_value_ = (1 << bit_depth_) - 1;
+
+ // Randomize stride_ to a value less than or equal to 1024
+ stride_ = rnd_(1024) + 1;
+ if (stride_ < size_) {
+ stride_ = size_;
+ }
+ // Align stride_ to 16 if it's bigger than 16.
+ if (stride_ > 16) {
+ stride_ &= ~15;
+ }
+
+ block_size_ = size_ * stride_;
+
+ src_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(16, pixel_size_ * block_size_));
+ ASSERT_NE(src_, nullptr);
+ dst_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(16, pixel_size_ * block_size_));
+ ASSERT_NE(dst_, nullptr);
+ }
+
+ virtual void TearDown() {
+ vpx_free(src_);
+ src_ = nullptr;
+ vpx_free(dst_);
+ dst_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ void InitMem() {
+ if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
+ if (pixel_size_ == 1) {
+ for (int j = 0; j < block_size_; ++j) {
+ src_[j] = rnd_.Rand16() & max_pixel_value_;
+ }
+ for (int j = 0; j < block_size_; ++j) {
+ dst_[j] = rnd_.Rand16() & max_pixel_value_;
+ }
+ } else {
+ ASSERT_EQ(pixel_size_, 2);
+ uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
+ uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
+ for (int j = 0; j < block_size_; ++j) {
+ src[j] = rnd_.Rand16() & max_pixel_value_;
+ }
+ for (int j = 0; j < block_size_; ++j) {
+ dst[j] = rnd_.Rand16() & max_pixel_value_;
+ }
+ }
+ }
+
+ void RunFwdTxfm(const Buffer<int16_t> &in, Buffer<tran_low_t> *out) {
+ fwd_txfm_(in.TopLeftPixel(), out->TopLeftPixel(), in.stride(), tx_type_);
+ }
+
+ void RunInvTxfm(const Buffer<tran_low_t> &in, uint8_t *out) {
+ inv_txfm_(in.TopLeftPixel(), out, stride_, tx_type_, bit_depth_);
+ }
+
+ protected:
+ void RunAccuracyCheck(int limit) {
+ if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ Buffer<int16_t> test_input_block =
+ Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
+ ASSERT_TRUE(test_input_block.Init());
+ ASSERT_NE(test_input_block.TopLeftPixel(), nullptr);
+ Buffer<tran_low_t> test_temp_block =
+ Buffer<tran_low_t>(size_, size_, 0, 16);
+ ASSERT_TRUE(test_temp_block.Init());
+ uint32_t max_error = 0;
+ int64_t total_error = 0;
+ const int count_test_block = 10000;
+ for (int i = 0; i < count_test_block; ++i) {
+ InitMem();
+ for (int h = 0; h < size_; ++h) {
+ for (int w = 0; w < size_; ++w) {
+ if (pixel_size_ == 1) {
+ test_input_block.TopLeftPixel()[h * test_input_block.stride() + w] =
+ src_[h * stride_ + w] - dst_[h * stride_ + w];
+ } else {
+ ASSERT_EQ(pixel_size_, 2);
+ const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
+ const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
+ test_input_block.TopLeftPixel()[h * test_input_block.stride() + w] =
+ src[h * stride_ + w] - dst[h * stride_ + w];
+ }
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, &test_temp_block));
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst_));
+
+ for (int h = 0; h < size_; ++h) {
+ for (int w = 0; w < size_; ++w) {
+ int diff;
+ if (pixel_size_ == 1) {
+ diff = dst_[h * stride_ + w] - src_[h * stride_ + w];
+ } else {
+ ASSERT_EQ(pixel_size_, 2);
+ const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
+ const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
+ diff = dst[h * stride_ + w] - src[h * stride_ + w];
+ }
+ const uint32_t error = diff * diff;
+ if (max_error < error) max_error = error;
+ total_error += error;
+ }
+ }
+ }
+
+ EXPECT_GE(static_cast<uint32_t>(limit), max_error)
+ << "Error: " << size_ << "x" << size_
+ << " transform/inverse transform has an individual round trip error > "
+ << limit;
+
+ EXPECT_GE(count_test_block * limit, total_error)
+ << "Error: " << size_ << "x" << size_
+ << " transform/inverse transform has average round trip error > "
+ << limit << " per block";
+ }
+
+ void RunCoeffCheck() {
+ if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 5000;
+ Buffer<int16_t> input_block =
+ Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
+ ASSERT_TRUE(input_block.Init());
+ Buffer<tran_low_t> output_ref_block = Buffer<tran_low_t>(size_, size_, 0);
+ ASSERT_TRUE(output_ref_block.Init());
+ Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
+ ASSERT_TRUE(output_block.Init());
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-max_pixel_value_,
+ // max_pixel_value_].
+ input_block.Set(&rnd, -max_pixel_value_, max_pixel_value_);
+
+ fwd_txfm_ref(input_block, &output_ref_block, size_, tx_type_);
+ ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, &output_block));
+
+ // The minimum quant value is 4.
+ EXPECT_TRUE(output_block.CheckValues(output_ref_block));
+ if (::testing::Test::HasFailure()) {
+ printf("Size: %d Transform type: %d\n", size_, tx_type_);
+ output_block.PrintDifference(output_ref_block);
+ return;
+ }
+ }
+ }
+
+ void RunMemCheck() {
+ if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 5000;
+ Buffer<int16_t> input_extreme_block =
+ Buffer<int16_t>(size_, size_, 8, size_ == 4 ? 0 : 16);
+ ASSERT_TRUE(input_extreme_block.Init());
+ Buffer<tran_low_t> output_ref_block = Buffer<tran_low_t>(size_, size_, 0);
+ ASSERT_TRUE(output_ref_block.Init());
+ Buffer<tran_low_t> output_block = Buffer<tran_low_t>(size_, size_, 0, 16);
+ ASSERT_TRUE(output_block.Init());
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with -max_pixel_value_ or max_pixel_value_.
+ if (i == 0) {
+ input_extreme_block.Set(max_pixel_value_);
+ } else if (i == 1) {
+ input_extreme_block.Set(-max_pixel_value_);
+ } else {
+ ASSERT_NE(input_extreme_block.TopLeftPixel(), nullptr);
+ for (int h = 0; h < size_; ++h) {
+ for (int w = 0; w < size_; ++w) {
+ input_extreme_block
+ .TopLeftPixel()[h * input_extreme_block.stride() + w] =
+ rnd.Rand8() % 2 ? max_pixel_value_ : -max_pixel_value_;
+ }
+ }
+ }
+
+ fwd_txfm_ref(input_extreme_block, &output_ref_block, size_, tx_type_);
+ ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, &output_block));
+
+ // The minimum quant value is 4.
+ EXPECT_TRUE(output_block.CheckValues(output_ref_block));
+ ASSERT_NE(output_block.TopLeftPixel(), nullptr);
+ for (int h = 0; h < size_; ++h) {
+ for (int w = 0; w < size_; ++w) {
+ EXPECT_GE(
+ 4 * DCT_MAX_VALUE << (bit_depth_ - 8),
+ abs(output_block.TopLeftPixel()[h * output_block.stride() + w]))
+ << "Error: " << size_ << "x" << size_
+ << " transform has coefficient larger than 4*DCT_MAX_VALUE"
+ << " at " << w << "," << h;
+ if (::testing::Test::HasFailure()) {
+ printf("Size: %d Transform type: %d\n", size_, tx_type_);
+ output_block.DumpBuffer();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ void RunInvAccuracyCheck(int limit) {
+ if (pixel_size_ == 1 && bit_depth_ > VPX_BITS_8) return;
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ Buffer<int16_t> in = Buffer<int16_t>(size_, size_, 4);
+ ASSERT_TRUE(in.Init());
+ Buffer<tran_low_t> coeff = Buffer<tran_low_t>(size_, size_, 0, 16);
+ ASSERT_TRUE(coeff.Init());
+
+ for (int i = 0; i < count_test_block; ++i) {
+ InitMem();
+ ASSERT_NE(in.TopLeftPixel(), nullptr);
+ // Initialize a test block with input range [-max_pixel_value_,
+ // max_pixel_value_].
+ for (int h = 0; h < size_; ++h) {
+ for (int w = 0; w < size_; ++w) {
+ if (pixel_size_ == 1) {
+ in.TopLeftPixel()[h * in.stride() + w] =
+ src_[h * stride_ + w] - dst_[h * stride_ + w];
+ } else {
+ ASSERT_EQ(pixel_size_, 2);
+ const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
+ const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
+ in.TopLeftPixel()[h * in.stride() + w] =
+ src[h * stride_ + w] - dst[h * stride_ + w];
+ }
+ }
+ }
+
+ fwd_txfm_ref(in, &coeff, size_, tx_type_);
+
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst_));
+
+ for (int h = 0; h < size_; ++h) {
+ for (int w = 0; w < size_; ++w) {
+ int diff;
+ if (pixel_size_ == 1) {
+ diff = dst_[h * stride_ + w] - src_[h * stride_ + w];
+ } else {
+ ASSERT_EQ(pixel_size_, 2);
+ const uint16_t *const src = reinterpret_cast<uint16_t *>(src_);
+ const uint16_t *const dst = reinterpret_cast<uint16_t *>(dst_);
+ diff = dst[h * stride_ + w] - src[h * stride_ + w];
+ }
+ const uint32_t error = diff * diff;
+ EXPECT_GE(static_cast<uint32_t>(limit), error)
+ << "Error: " << size_ << "x" << size_
+ << " inverse transform has error " << error << " at " << w << ","
+ << h;
+ if (::testing::Test::HasFailure()) {
+ printf("Size: %d Transform type: %d\n", size_, tx_type_);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ FhtFunc fwd_txfm_;
+ FhtFuncRef fwd_txfm_ref;
+ IhtWithBdFunc inv_txfm_;
+ ACMRandom rnd_;
+ uint8_t *src_;
+ uint8_t *dst_;
+ vpx_bit_depth_t bit_depth_;
+ int tx_type_;
+ int max_pixel_value_;
+ int size_;
+ int stride_;
+ int pixel_size_;
+ int block_size_;
+};
+
+/* -------------------------------------------------------------------------- */
+
+class TransDCT : public TransTestBase {
+ public:
+ TransDCT() { fwd_txfm_ref = fdct_ref; }
+};
+
+TEST_P(TransDCT, AccuracyCheck) {
+ int t = 1;
+ if (size_ == 16 && bit_depth_ > 10 && pixel_size_ == 2) {
+ t = 2;
+ } else if (size_ == 32 && bit_depth_ > 10 && pixel_size_ == 2) {
+ t = 7;
+ }
+ RunAccuracyCheck(t);
+}
+
+TEST_P(TransDCT, CoeffCheck) { RunCoeffCheck(); }
+
+TEST_P(TransDCT, MemCheck) { RunMemCheck(); }
+
+TEST_P(TransDCT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
+
+static const FuncInfo dct_c_func_info[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ { &fdct_wrapper<vpx_highbd_fdct4x4_c>,
+ &highbd_idct_wrapper<vpx_highbd_idct4x4_16_add_c>, 4, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct8x8_c>,
+ &highbd_idct_wrapper<vpx_highbd_idct8x8_64_add_c>, 8, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct16x16_c>,
+ &highbd_idct_wrapper<vpx_highbd_idct16x16_256_add_c>, 16, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct32x32_c>,
+ &highbd_idct_wrapper<vpx_highbd_idct32x32_1024_add_c>, 32, 2 },
+#endif
+ { &fdct_wrapper<vpx_fdct4x4_c>, &idct_wrapper<vpx_idct4x4_16_add_c>, 4, 1 },
+ { &fdct_wrapper<vpx_fdct8x8_c>, &idct_wrapper<vpx_idct8x8_64_add_c>, 8, 1 },
+ { &fdct_wrapper<vpx_fdct16x16_c>, &idct_wrapper<vpx_idct16x16_256_add_c>, 16,
+ 1 },
+ { &fdct_wrapper<vpx_fdct32x32_c>, &idct_wrapper<vpx_idct32x32_1024_add_c>, 32,
+ 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ C, TransDCT,
+ ::testing::Combine(
+ ::testing::Range(0, static_cast<int>(sizeof(dct_c_func_info) /
+ sizeof(dct_c_func_info[0]))),
+ ::testing::Values(dct_c_func_info), ::testing::Values(0),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
+
+#if !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2
+static const FuncInfo dct_sse2_func_info[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ { &fdct_wrapper<vpx_highbd_fdct4x4_sse2>,
+ &highbd_idct_wrapper<vpx_highbd_idct4x4_16_add_sse2>, 4, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct8x8_sse2>,
+ &highbd_idct_wrapper<vpx_highbd_idct8x8_64_add_sse2>, 8, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct16x16_sse2>,
+ &highbd_idct_wrapper<vpx_highbd_idct16x16_256_add_sse2>, 16, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct32x32_sse2>,
+ &highbd_idct_wrapper<vpx_highbd_idct32x32_1024_add_sse2>, 32, 2 },
+#endif
+ { &fdct_wrapper<vpx_fdct4x4_sse2>, &idct_wrapper<vpx_idct4x4_16_add_sse2>, 4,
+ 1 },
+ { &fdct_wrapper<vpx_fdct8x8_sse2>, &idct_wrapper<vpx_idct8x8_64_add_sse2>, 8,
+ 1 },
+ { &fdct_wrapper<vpx_fdct16x16_sse2>,
+ &idct_wrapper<vpx_idct16x16_256_add_sse2>, 16, 1 },
+ { &fdct_wrapper<vpx_fdct32x32_sse2>,
+ &idct_wrapper<vpx_idct32x32_1024_add_sse2>, 32, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, TransDCT,
+ ::testing::Combine(
+ ::testing::Range(0, static_cast<int>(sizeof(dct_sse2_func_info) /
+ sizeof(dct_sse2_func_info[0]))),
+ ::testing::Values(dct_sse2_func_info), ::testing::Values(0),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH && VPX_ARCH_X86_64
+// vpx_fdct8x8_ssse3 is only available in 64 bit builds.
+static const FuncInfo dct_ssse3_func_info = {
+ &fdct_wrapper<vpx_fdct8x8_ssse3>, &idct_wrapper<vpx_idct8x8_64_add_sse2>, 8, 1
+};
+
+// TODO(johannkoenig): high bit depth fdct8x8.
+INSTANTIATE_TEST_SUITE_P(SSSE3, TransDCT,
+ ::testing::Values(make_tuple(0, &dct_ssse3_func_info,
+ 0, VPX_BITS_8)));
+#endif // HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH && VPX_ARCH_X86_64
+
+#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo dct_avx2_func_info = {
+ &fdct_wrapper<vpx_fdct32x32_avx2>, &idct_wrapper<vpx_idct32x32_1024_add_sse2>,
+ 32, 1
+};
+
+// TODO(johannkoenig): high bit depth fdct32x32.
+INSTANTIATE_TEST_SUITE_P(AVX2, TransDCT,
+ ::testing::Values(make_tuple(0, &dct_avx2_func_info, 0,
+ VPX_BITS_8)));
+#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON
+#if CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo dct_neon_func_info[] = {
+ { &fdct_wrapper<vpx_highbd_fdct4x4_neon>,
+ &highbd_idct_wrapper<vpx_highbd_idct4x4_16_add_neon>, 4, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct8x8_neon>,
+ &highbd_idct_wrapper<vpx_highbd_idct8x8_64_add_neon>, 8, 2 },
+ { &fdct_wrapper<vpx_highbd_fdct16x16_neon>,
+ &highbd_idct_wrapper<vpx_highbd_idct16x16_256_add_neon>, 16, 2 },
+ /* { &fdct_wrapper<vpx_highbd_fdct32x32_neon>,
+ &highbd_idct_wrapper<vpx_highbd_idct32x32_1024_add_neon>, 32, 2 },*/
+};
+#else
+static const FuncInfo dct_neon_func_info[4] = {
+ { &fdct_wrapper<vpx_fdct4x4_neon>, &idct_wrapper<vpx_idct4x4_16_add_neon>, 4,
+ 1 },
+ { &fdct_wrapper<vpx_fdct8x8_neon>, &idct_wrapper<vpx_idct8x8_64_add_neon>, 8,
+ 1 },
+ { &fdct_wrapper<vpx_fdct16x16_neon>,
+ &idct_wrapper<vpx_idct16x16_256_add_neon>, 16, 1 },
+ { &fdct_wrapper<vpx_fdct32x32_neon>,
+ &idct_wrapper<vpx_idct32x32_1024_add_neon>, 32, 1 }
+};
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, TransDCT,
+ ::testing::Combine(
+ ::testing::Range(0, static_cast<int>(sizeof(dct_neon_func_info) /
+ sizeof(dct_neon_func_info[0]))),
+ ::testing::Values(dct_neon_func_info), ::testing::Values(0),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
+#endif // HAVE_NEON
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo dct_msa_func_info[4] = {
+ { &fdct_wrapper<vpx_fdct4x4_msa>, &idct_wrapper<vpx_idct4x4_16_add_msa>, 4,
+ 1 },
+ { &fdct_wrapper<vpx_fdct8x8_msa>, &idct_wrapper<vpx_idct8x8_64_add_msa>, 8,
+ 1 },
+ { &fdct_wrapper<vpx_fdct16x16_msa>, &idct_wrapper<vpx_idct16x16_256_add_msa>,
+ 16, 1 },
+ { &fdct_wrapper<vpx_fdct32x32_msa>, &idct_wrapper<vpx_idct32x32_1024_add_msa>,
+ 32, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, TransDCT,
+ ::testing::Combine(::testing::Range(0, 4),
+ ::testing::Values(dct_msa_func_info),
+ ::testing::Values(0), ::testing::Values(VPX_BITS_8)));
+#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo dct_vsx_func_info = {
+ &fdct_wrapper<vpx_fdct4x4_c>, &idct_wrapper<vpx_idct4x4_16_add_vsx>, 4, 1
+};
+
+INSTANTIATE_TEST_SUITE_P(VSX, TransDCT,
+ ::testing::Values(make_tuple(0, &dct_vsx_func_info, 0,
+ VPX_BITS_8)));
+#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH &&
+
+#if HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo dct_lsx_func_info[4] = {
+ { &fdct_wrapper<vpx_fdct4x4_lsx>, &idct_wrapper<vpx_idct4x4_16_add_c>, 4, 1 },
+ { &fdct_wrapper<vpx_fdct8x8_lsx>, &idct_wrapper<vpx_idct8x8_64_add_c>, 8, 1 },
+ { &fdct_wrapper<vpx_fdct16x16_lsx>, &idct_wrapper<vpx_idct16x16_256_add_c>,
+ 16, 1 },
+ { &fdct_wrapper<vpx_fdct32x32_lsx>, &idct_wrapper<vpx_idct32x32_1024_add_lsx>,
+ 32, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ LSX, TransDCT,
+ ::testing::Combine(::testing::Range(0, 4),
+ ::testing::Values(dct_lsx_func_info),
+ ::testing::Values(0), ::testing::Values(VPX_BITS_8)));
+#endif // HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH
+
+#endif // !CONFIG_EMULATE_HARDWARE
+
+/* -------------------------------------------------------------------------- */
+
+class TransHT : public TransTestBase {
+ public:
+ TransHT() { fwd_txfm_ref = fht_ref; }
+};
+
+TEST_P(TransHT, AccuracyCheck) {
+ RunAccuracyCheck(size_ == 16 && bit_depth_ > 10 && pixel_size_ == 2 ? 2 : 1);
+}
+
+TEST_P(TransHT, CoeffCheck) { RunCoeffCheck(); }
+
+TEST_P(TransHT, MemCheck) { RunMemCheck(); }
+
+TEST_P(TransHT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
+
+static const FuncInfo ht_c_func_info[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ { &vp9_highbd_fht4x4_c, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_c>, 4,
+ 2 },
+ { &vp9_highbd_fht8x8_c, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_c>, 8,
+ 2 },
+ { &vp9_highbd_fht16x16_c, &highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_c>,
+ 16, 2 },
+#endif
+ { &vp9_fht4x4_c, &iht_wrapper<vp9_iht4x4_16_add_c>, 4, 1 },
+ { &vp9_fht8x8_c, &iht_wrapper<vp9_iht8x8_64_add_c>, 8, 1 },
+ { &vp9_fht16x16_c, &iht_wrapper<vp9_iht16x16_256_add_c>, 16, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ C, TransHT,
+ ::testing::Combine(
+ ::testing::Range(0, static_cast<int>(sizeof(ht_c_func_info) /
+ sizeof(ht_c_func_info[0]))),
+ ::testing::Values(ht_c_func_info), ::testing::Range(0, 4),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
+
+#if !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_NEON
+
+static const FuncInfo ht_neon_func_info[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ { &vp9_highbd_fht4x4_c, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_neon>, 4,
+ 2 },
+ { &vp9_highbd_fht4x4_neon, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_neon>,
+ 4, 2 },
+ { &vp9_highbd_fht8x8_c, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_neon>, 8,
+ 2 },
+ { &vp9_highbd_fht8x8_neon, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_neon>,
+ 8, 2 },
+ { &vp9_highbd_fht16x16_c,
+ &highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_neon>, 16, 2 },
+ { &vp9_highbd_fht16x16_neon,
+ &highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_neon>, 16, 2 },
+#endif
+ { &vp9_fht4x4_c, &iht_wrapper<vp9_iht4x4_16_add_neon>, 4, 1 },
+ { &vp9_fht4x4_neon, &iht_wrapper<vp9_iht4x4_16_add_neon>, 4, 1 },
+ { &vp9_fht8x8_c, &iht_wrapper<vp9_iht8x8_64_add_neon>, 8, 1 },
+ { &vp9_fht8x8_neon, &iht_wrapper<vp9_iht8x8_64_add_neon>, 8, 1 },
+ { &vp9_fht16x16_c, &iht_wrapper<vp9_iht16x16_256_add_neon>, 16, 1 },
+ { &vp9_fht16x16_neon, &iht_wrapper<vp9_iht16x16_256_add_neon>, 16, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, TransHT,
+ ::testing::Combine(
+ ::testing::Range(0, static_cast<int>(sizeof(ht_neon_func_info) /
+ sizeof(ht_neon_func_info[0]))),
+ ::testing::Values(ht_neon_func_info), ::testing::Range(0, 4),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
+#endif // HAVE_NEON
+
+#if HAVE_SSE2
+
+static const FuncInfo ht_sse2_func_info[3] = {
+ { &vp9_fht4x4_sse2, &iht_wrapper<vp9_iht4x4_16_add_sse2>, 4, 1 },
+ { &vp9_fht8x8_sse2, &iht_wrapper<vp9_iht8x8_64_add_sse2>, 8, 1 },
+ { &vp9_fht16x16_sse2, &iht_wrapper<vp9_iht16x16_256_add_sse2>, 16, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, TransHT,
+ ::testing::Combine(::testing::Range(0, 3),
+ ::testing::Values(ht_sse2_func_info),
+ ::testing::Range(0, 4), ::testing::Values(VPX_BITS_8)));
+#endif // HAVE_SSE2
+
+#if HAVE_SSE4_1 && CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo ht_sse4_1_func_info[3] = {
+ { &vp9_highbd_fht4x4_c, &highbd_iht_wrapper<vp9_highbd_iht4x4_16_add_sse4_1>,
+ 4, 2 },
+ { vp9_highbd_fht8x8_c, &highbd_iht_wrapper<vp9_highbd_iht8x8_64_add_sse4_1>,
+ 8, 2 },
+ { &vp9_highbd_fht16x16_c,
+ &highbd_iht_wrapper<vp9_highbd_iht16x16_256_add_sse4_1>, 16, 2 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE4_1, TransHT,
+ ::testing::Combine(::testing::Range(0, 3),
+ ::testing::Values(ht_sse4_1_func_info),
+ ::testing::Range(0, 4),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10,
+ VPX_BITS_12)));
+#endif // HAVE_SSE4_1 && CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_VSX && !CONFIG_EMULATE_HARDWARE && !CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo ht_vsx_func_info[3] = {
+ { &vp9_fht4x4_c, &iht_wrapper<vp9_iht4x4_16_add_vsx>, 4, 1 },
+ { &vp9_fht8x8_c, &iht_wrapper<vp9_iht8x8_64_add_vsx>, 8, 1 },
+ { &vp9_fht16x16_c, &iht_wrapper<vp9_iht16x16_256_add_vsx>, 16, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(VSX, TransHT,
+ ::testing::Combine(::testing::Range(0, 3),
+ ::testing::Values(ht_vsx_func_info),
+ ::testing::Range(0, 4),
+ ::testing::Values(VPX_BITS_8)));
+#endif // HAVE_VSX
+#endif // !CONFIG_EMULATE_HARDWARE
+
+/* -------------------------------------------------------------------------- */
+
+class TransWHT : public TransTestBase {
+ public:
+ TransWHT() { fwd_txfm_ref = fwht_ref; }
+};
+
+TEST_P(TransWHT, AccuracyCheck) { RunAccuracyCheck(0); }
+
+TEST_P(TransWHT, CoeffCheck) { RunCoeffCheck(); }
+
+TEST_P(TransWHT, MemCheck) { RunMemCheck(); }
+
+TEST_P(TransWHT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
+
+static const FuncInfo wht_c_func_info[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ { &fdct_wrapper<vp9_highbd_fwht4x4_c>,
+ &highbd_idct_wrapper<vpx_highbd_iwht4x4_16_add_c>, 4, 2 },
+#endif
+ { &fdct_wrapper<vp9_fwht4x4_c>, &idct_wrapper<vpx_iwht4x4_16_add_c>, 4, 1 }
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ C, TransWHT,
+ ::testing::Combine(
+ ::testing::Range(0, static_cast<int>(sizeof(wht_c_func_info) /
+ sizeof(wht_c_func_info[0]))),
+ ::testing::Values(wht_c_func_info), ::testing::Values(0),
+ ::testing::Values(VPX_BITS_8, VPX_BITS_10, VPX_BITS_12)));
+
+#if HAVE_SSE2 && !CONFIG_EMULATE_HARDWARE
+static const FuncInfo wht_sse2_func_info = {
+ &fdct_wrapper<vp9_fwht4x4_sse2>, &idct_wrapper<vpx_iwht4x4_16_add_sse2>, 4, 1
+};
+
+INSTANTIATE_TEST_SUITE_P(SSE2, TransWHT,
+ ::testing::Values(make_tuple(0, &wht_sse2_func_info, 0,
+ VPX_BITS_8)));
+#endif // HAVE_SSE2 && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_VSX && !CONFIG_EMULATE_HARDWARE && !CONFIG_VP9_HIGHBITDEPTH
+static const FuncInfo wht_vsx_func_info = {
+ &fdct_wrapper<vp9_fwht4x4_c>, &idct_wrapper<vpx_iwht4x4_16_add_vsx>, 4, 1
+};
+
+INSTANTIATE_TEST_SUITE_P(VSX, TransWHT,
+ ::testing::Values(make_tuple(0, &wht_vsx_func_info, 0,
+ VPX_BITS_8)));
+#endif // HAVE_VSX && !CONFIG_EMULATE_HARDWARE
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/decode_api_test.cc b/media/libvpx/libvpx/test/decode_api_test.cc
new file mode 100644
index 0000000000..9e82ace1b8
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_api_test.cc
@@ -0,0 +1,215 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "test/ivf_video_source.h"
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
+namespace {
+
+#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
+
+TEST(DecodeAPI, InvalidParams) {
+ static const vpx_codec_iface_t *kCodecs[] = {
+#if CONFIG_VP8_DECODER
+ &vpx_codec_vp8_dx_algo,
+#endif
+#if CONFIG_VP9_DECODER
+ &vpx_codec_vp9_dx_algo,
+#endif
+ };
+ uint8_t buf[1] = { 0 };
+ vpx_codec_ctx_t dec;
+
+ EXPECT_EQ(vpx_codec_dec_init(nullptr, nullptr, nullptr, 0),
+ VPX_CODEC_INVALID_PARAM);
+ EXPECT_EQ(vpx_codec_dec_init(&dec, nullptr, nullptr, 0),
+ VPX_CODEC_INVALID_PARAM);
+ EXPECT_EQ(vpx_codec_decode(nullptr, nullptr, 0, nullptr, 0),
+ VPX_CODEC_INVALID_PARAM);
+ EXPECT_EQ(vpx_codec_decode(nullptr, buf, 0, nullptr, 0),
+ VPX_CODEC_INVALID_PARAM);
+ EXPECT_EQ(vpx_codec_decode(nullptr, buf, NELEMENTS(buf), nullptr, 0),
+ VPX_CODEC_INVALID_PARAM);
+ EXPECT_EQ(vpx_codec_decode(nullptr, nullptr, NELEMENTS(buf), nullptr, 0),
+ VPX_CODEC_INVALID_PARAM);
+ EXPECT_EQ(vpx_codec_destroy(nullptr), VPX_CODEC_INVALID_PARAM);
+ EXPECT_NE(vpx_codec_error(nullptr), nullptr);
+ EXPECT_EQ(vpx_codec_error_detail(nullptr), nullptr);
+
+ for (int i = 0; i < NELEMENTS(kCodecs); ++i) {
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_dec_init(nullptr, kCodecs[i], nullptr, 0));
+
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, kCodecs[i], nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
+ vpx_codec_decode(&dec, buf, NELEMENTS(buf), nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_decode(&dec, nullptr, NELEMENTS(buf), nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_decode(&dec, buf, 0, nullptr, 0));
+
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+ }
+}
+
+#if CONFIG_VP8_DECODER
+TEST(DecodeAPI, OptionalParams) {
+ vpx_codec_ctx_t dec;
+
+#if CONFIG_ERROR_CONCEALMENT
+ EXPECT_EQ(VPX_CODEC_OK,
+ vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, nullptr,
+ VPX_CODEC_USE_ERROR_CONCEALMENT));
+#else
+ EXPECT_EQ(VPX_CODEC_INCAPABLE,
+ vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, nullptr,
+ VPX_CODEC_USE_ERROR_CONCEALMENT));
+#endif // CONFIG_ERROR_CONCEALMENT
+}
+#endif // CONFIG_VP8_DECODER
+
+#if CONFIG_VP9_DECODER
+// Test VP9 codec controls after a decode error to ensure the code doesn't
+// misbehave.
+void TestVp9Controls(vpx_codec_ctx_t *dec) {
+ static const int kControls[] = { VP8D_GET_LAST_REF_UPDATES,
+ VP8D_GET_FRAME_CORRUPTED,
+ VP9D_GET_DISPLAY_SIZE, VP9D_GET_FRAME_SIZE };
+ int val[2];
+
+ for (int i = 0; i < NELEMENTS(kControls); ++i) {
+ const vpx_codec_err_t res = vpx_codec_control_(dec, kControls[i], val);
+ switch (kControls[i]) {
+ case VP8D_GET_FRAME_CORRUPTED:
+ EXPECT_EQ(VPX_CODEC_ERROR, res) << kControls[i];
+ break;
+ default: EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i]; break;
+ }
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_control_(dec, kControls[i], nullptr));
+ }
+
+ vp9_ref_frame_t ref;
+ ref.idx = 0;
+ EXPECT_EQ(VPX_CODEC_ERROR, vpx_codec_control(dec, VP9_GET_REFERENCE, &ref));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_control(dec, VP9_GET_REFERENCE, nullptr));
+
+ vpx_ref_frame_t ref_copy;
+ const int width = 352;
+ const int height = 288;
+ EXPECT_NE(vpx_img_alloc(&ref_copy.img, VPX_IMG_FMT_I420, width, height, 1),
+ nullptr);
+ ref_copy.frame_type = VP8_LAST_FRAME;
+ EXPECT_EQ(VPX_CODEC_ERROR,
+ vpx_codec_control(dec, VP8_COPY_REFERENCE, &ref_copy));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_control(dec, VP8_COPY_REFERENCE, nullptr));
+ vpx_img_free(&ref_copy.img);
+}
+
+TEST(DecodeAPI, Vp9InvalidDecode) {
+ const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
+ const char filename[] =
+ "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf";
+ libvpx_test::IVFVideoSource video(filename);
+ video.Init();
+ video.Begin();
+ ASSERT_TRUE(!HasFailure());
+
+ vpx_codec_ctx_t dec;
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, nullptr, 0));
+ const uint32_t frame_size = static_cast<uint32_t>(video.frame_size());
+#if CONFIG_VP9_HIGHBITDEPTH
+ EXPECT_EQ(VPX_CODEC_MEM_ERROR,
+ vpx_codec_decode(&dec, video.cxdata(), frame_size, nullptr, 0));
+#else
+ EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
+ vpx_codec_decode(&dec, video.cxdata(), frame_size, nullptr, 0));
+#endif
+ vpx_codec_iter_t iter = nullptr;
+ EXPECT_EQ(nullptr, vpx_codec_get_frame(&dec, &iter));
+
+ TestVp9Controls(&dec);
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+}
+
+void TestPeekInfo(const uint8_t *const data, uint32_t data_sz,
+ uint32_t peek_size) {
+ const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
+ // Verify behavior of vpx_codec_decode. vpx_codec_decode doesn't even get
+ // to decoder_peek_si_internal on frames of size < 8.
+ if (data_sz >= 8) {
+ vpx_codec_ctx_t dec;
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, nullptr, 0));
+ EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM
+ : VPX_CODEC_CORRUPT_FRAME,
+ vpx_codec_decode(&dec, data, data_sz, nullptr, 0));
+ vpx_codec_iter_t iter = nullptr;
+ EXPECT_EQ(nullptr, vpx_codec_get_frame(&dec, &iter));
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+ }
+
+ // Verify behavior of vpx_codec_peek_stream_info.
+ vpx_codec_stream_info_t si;
+ si.sz = sizeof(si);
+ EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM : VPX_CODEC_OK,
+ vpx_codec_peek_stream_info(codec, data, data_sz, &si));
+}
+
+TEST(DecodeAPI, Vp9PeekStreamInfo) {
+ // The first 9 bytes are valid and the rest of the bytes are made up. Until
+ // size 10, this should return VPX_CODEC_UNSUP_BITSTREAM and after that it
+ // should return VPX_CODEC_CORRUPT_FRAME.
+ const uint8_t data[32] = {
+ 0x85, 0xa4, 0xc1, 0xa1, 0x38, 0x81, 0xa3, 0x49, 0x83, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+
+ for (uint32_t data_sz = 1; data_sz <= 32; ++data_sz) {
+ TestPeekInfo(data, data_sz, 10);
+ }
+}
+
+TEST(DecodeAPI, Vp9PeekStreamInfoTruncated) {
+ // This profile 1 header requires 10.25 bytes, ensure
+ // vpx_codec_peek_stream_info doesn't over read.
+ const uint8_t profile1_data[10] = { 0xa4, 0xe9, 0x30, 0x68, 0x53,
+ 0xe9, 0x30, 0x68, 0x53, 0x04 };
+
+ for (uint32_t data_sz = 1; data_sz <= 10; ++data_sz) {
+ TestPeekInfo(profile1_data, data_sz, 11);
+ }
+}
+#endif // CONFIG_VP9_DECODER
+
+TEST(DecodeAPI, HighBitDepthCapability) {
+// VP8 should not claim VP9 HBD as a capability.
+#if CONFIG_VP8_DECODER
+ const vpx_codec_caps_t vp8_caps = vpx_codec_get_caps(&vpx_codec_vp8_dx_algo);
+ EXPECT_EQ(vp8_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
+#endif
+
+#if CONFIG_VP9_DECODER
+ const vpx_codec_caps_t vp9_caps = vpx_codec_get_caps(&vpx_codec_vp9_dx_algo);
+#if CONFIG_VP9_HIGHBITDEPTH
+ EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, VPX_CODEC_CAP_HIGHBITDEPTH);
+#else
+ EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
+#endif
+#endif
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/decode_corrupted.cc b/media/libvpx/libvpx/test/decode_corrupted.cc
new file mode 100644
index 0000000000..31e1da69cc
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_corrupted.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018 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 <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/i420_video_source.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+class DecodeCorruptedFrameTest
+ : public ::libvpx_test::EncoderTest,
+ public ::testing::TestWithParam<
+ std::tuple<const libvpx_test::CodecFactory *> > {
+ public:
+ DecodeCorruptedFrameTest() : EncoderTest(GET_PARAM(0)) {}
+
+ protected:
+ virtual ~DecodeCorruptedFrameTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+
+ // Set small key frame distance such that we insert more key frames.
+ cfg_.kf_max_dist = 3;
+ dec_cfg_.threads = 1;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) encoder->Control(VP8E_SET_CPUUSED, 7);
+ }
+
+ virtual void MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {}
+
+ virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook(
+ const vpx_codec_cx_pkt_t *pkt) {
+ // Don't edit frame packet on key frame.
+ if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) return pkt;
+ if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return pkt;
+
+ memcpy(&modified_pkt_, pkt, sizeof(*pkt));
+
+ // Halve the size so it's corrupted to decoder.
+ modified_pkt_.data.frame.sz = modified_pkt_.data.frame.sz / 2;
+
+ return &modified_pkt_;
+ }
+
+ virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+ const libvpx_test::VideoSource & /*video*/,
+ libvpx_test::Decoder *decoder) {
+ EXPECT_NE(res_dec, VPX_CODEC_MEM_ERROR) << decoder->DecodeError();
+ return VPX_CODEC_MEM_ERROR != res_dec;
+ }
+
+ vpx_codec_cx_pkt_t modified_pkt_;
+};
+
+TEST_P(DecodeCorruptedFrameTest, DecodeCorruptedFrame) {
+ cfg_.rc_target_bitrate = 200;
+ cfg_.g_error_resilient = 0;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+#if CONFIG_VP9
+INSTANTIATE_TEST_SUITE_P(
+ VP9, DecodeCorruptedFrameTest,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
+#endif // CONFIG_VP9
+
+#if CONFIG_VP8
+INSTANTIATE_TEST_SUITE_P(
+ VP8, DecodeCorruptedFrameTest,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP8)));
+#endif // CONFIG_VP8
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/decode_perf_test.cc b/media/libvpx/libvpx/test/decode_perf_test.cc
new file mode 100644
index 0000000000..e07a667440
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_perf_test.cc
@@ -0,0 +1,263 @@
+/*
+ * 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 <string>
+#include <tuple>
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/webm_video_source.h"
+#include "vpx_ports/vpx_timer.h"
+#include "./ivfenc.h"
+#include "./vpx_version.h"
+
+using std::make_tuple;
+
+namespace {
+
+#define VIDEO_NAME 0
+#define THREADS 1
+
+const double kUsecsInSec = 1000000.0;
+const char kNewEncodeOutputFile[] = "new_encode.ivf";
+
+/*
+ DecodePerfTest takes a tuple of filename + number of threads to decode with
+ */
+typedef std::tuple<const char *, unsigned> DecodePerfParam;
+
+const DecodePerfParam kVP9DecodePerfVectors[] = {
+ make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),
+ make_tuple("vp90-2-bbb_640x360_tile_1x2_337kbps.webm", 2),
+ make_tuple("vp90-2-bbb_854x480_tile_1x2_651kbps.webm", 2),
+ make_tuple("vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm", 4),
+ make_tuple("vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm", 1),
+ make_tuple("vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm", 4),
+ make_tuple("vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm", 4),
+ make_tuple("vp90-2-sintel_426x182_tile_1x1_171kbps.webm", 1),
+ make_tuple("vp90-2-sintel_640x272_tile_1x2_318kbps.webm", 2),
+ make_tuple("vp90-2-sintel_854x364_tile_1x2_621kbps.webm", 2),
+ make_tuple("vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm", 4),
+ make_tuple("vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm", 4),
+ make_tuple("vp90-2-tos_426x178_tile_1x1_181kbps.webm", 1),
+ make_tuple("vp90-2-tos_640x266_tile_1x2_336kbps.webm", 2),
+ make_tuple("vp90-2-tos_854x356_tile_1x2_656kbps.webm", 2),
+ make_tuple("vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm", 2),
+ make_tuple("vp90-2-tos_1280x534_tile_1x4_1306kbps.webm", 4),
+ make_tuple("vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm", 4),
+ make_tuple("vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm", 4),
+};
+
+/*
+ In order to reflect real world performance as much as possible, Perf tests
+ *DO NOT* do any correctness checks. Please run them alongside correctness
+ tests to ensure proper codec integrity. Furthermore, in this test we
+ deliberately limit the amount of system calls we make to avoid OS
+ preemption.
+
+ TODO(joshualitt) create a more detailed perf measurement test to collect
+ power/temp/min max frame decode times/etc
+ */
+
+class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {};
+
+TEST_P(DecodePerfTest, PerfTest) {
+ const char *const video_name = GET_PARAM(VIDEO_NAME);
+ const unsigned threads = GET_PARAM(THREADS);
+
+ libvpx_test::WebMVideoSource video(video_name);
+ video.Init();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ cfg.threads = threads;
+ libvpx_test::VP9Decoder decoder(cfg, 0);
+
+ vpx_usec_timer t;
+ vpx_usec_timer_start(&t);
+
+ for (video.Begin(); video.cxdata() != nullptr; video.Next()) {
+ decoder.DecodeFrame(video.cxdata(), video.frame_size());
+ }
+
+ vpx_usec_timer_mark(&t);
+ const double elapsed_secs = double(vpx_usec_timer_elapsed(&t)) / kUsecsInSec;
+ const unsigned frames = video.frame_number();
+ const double fps = double(frames) / elapsed_secs;
+
+ printf("{\n");
+ printf("\t\"type\" : \"decode_perf_test\",\n");
+ printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
+ printf("\t\"videoName\" : \"%s\",\n", video_name);
+ printf("\t\"threadCount\" : %u,\n", threads);
+ printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
+ printf("\t\"totalFrames\" : %u,\n", frames);
+ printf("\t\"framesPerSecond\" : %f\n", fps);
+ printf("}\n");
+}
+
+INSTANTIATE_TEST_SUITE_P(VP9, DecodePerfTest,
+ ::testing::ValuesIn(kVP9DecodePerfVectors));
+
+class VP9NewEncodeDecodePerfTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ VP9NewEncodeDecodePerfTest()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)), speed_(0),
+ outfile_(0), out_frames_(0) {}
+
+ virtual ~VP9NewEncodeDecodePerfTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_resize_allowed = 0;
+ cfg_.rc_end_usage = VPX_VBR;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, speed_);
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
+ }
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ const std::string data_path = getenv("LIBVPX_TEST_DATA_PATH");
+ const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile;
+ outfile_ = fopen(path_to_source.c_str(), "wb");
+ ASSERT_NE(outfile_, nullptr);
+ }
+
+ virtual void EndPassHook() {
+ if (outfile_ != nullptr) {
+ if (!fseek(outfile_, 0, SEEK_SET)) {
+ ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
+ }
+ fclose(outfile_);
+ outfile_ = nullptr;
+ }
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ ++out_frames_;
+
+ // Write initial file header if first frame.
+ if (pkt->data.frame.pts == 0) {
+ ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
+ }
+
+ // Write frame header and data.
+ ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz);
+ ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_),
+ pkt->data.frame.sz);
+ }
+
+ virtual bool DoDecode() const { return false; }
+
+ void set_speed(unsigned int speed) { speed_ = speed; }
+
+ private:
+ libvpx_test::TestMode encoding_mode_;
+ uint32_t speed_;
+ FILE *outfile_;
+ uint32_t out_frames_;
+};
+
+struct EncodePerfTestVideo {
+ EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
+ uint32_t bitrate_, int frames_)
+ : name(name_), width(width_), height(height_), bitrate(bitrate_),
+ frames(frames_) {}
+ const char *name;
+ uint32_t width;
+ uint32_t height;
+ uint32_t bitrate;
+ int frames;
+};
+
+const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
+ EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
+};
+
+TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
+ SetUp();
+
+ // TODO(JBB): Make this work by going through the set of given files.
+ const int i = 0;
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ const char *video_name = kVP9EncodePerfTestVectors[i].name;
+ libvpx_test::I420VideoSource video(
+ video_name, kVP9EncodePerfTestVectors[i].width,
+ kVP9EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0,
+ kVP9EncodePerfTestVectors[i].frames);
+ set_speed(2);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ const uint32_t threads = 4;
+
+ libvpx_test::IVFVideoSource decode_video(kNewEncodeOutputFile);
+ decode_video.Init();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ cfg.threads = threads;
+ libvpx_test::VP9Decoder decoder(cfg, 0);
+
+ vpx_usec_timer t;
+ vpx_usec_timer_start(&t);
+
+ for (decode_video.Begin(); decode_video.cxdata() != nullptr;
+ decode_video.Next()) {
+ decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size());
+ }
+
+ vpx_usec_timer_mark(&t);
+ const double elapsed_secs =
+ static_cast<double>(vpx_usec_timer_elapsed(&t)) / kUsecsInSec;
+ const unsigned decode_frames = decode_video.frame_number();
+ const double fps = static_cast<double>(decode_frames) / elapsed_secs;
+
+ printf("{\n");
+ printf("\t\"type\" : \"decode_perf_test\",\n");
+ printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
+ printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile);
+ printf("\t\"threadCount\" : %u,\n", threads);
+ printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
+ printf("\t\"totalFrames\" : %u,\n", decode_frames);
+ printf("\t\"framesPerSecond\" : %f\n", fps);
+ printf("}\n");
+}
+
+VP9_INSTANTIATE_TEST_SUITE(VP9NewEncodeDecodePerfTest,
+ ::testing::Values(::libvpx_test::kTwoPassGood));
+} // namespace
diff --git a/media/libvpx/libvpx/test/decode_svc_test.cc b/media/libvpx/libvpx/test/decode_svc_test.cc
new file mode 100644
index 0000000000..ec9935da79
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_svc_test.cc
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016 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 <memory>
+#include <string>
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+
+namespace {
+
+const unsigned int kNumFrames = 19;
+
+class DecodeSvcTest : public ::libvpx_test::DecoderTest,
+ public ::libvpx_test::CodecTestWithParam<const char *> {
+ protected:
+ DecodeSvcTest() : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)) {}
+ virtual ~DecodeSvcTest() {}
+
+ virtual void PreDecodeFrameHook(
+ const libvpx_test::CompressedVideoSource &video,
+ libvpx_test::Decoder *decoder) {
+ if (video.frame_number() == 0)
+ decoder->Control(VP9_DECODE_SVC_SPATIAL_LAYER, spatial_layer_);
+ }
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ const unsigned int frame_number) {
+ ASSERT_EQ(img.d_w, width_);
+ ASSERT_EQ(img.d_h, height_);
+ total_frames_ = frame_number;
+ }
+
+ int spatial_layer_;
+ unsigned int width_;
+ unsigned int height_;
+ unsigned int total_frames_;
+};
+
+// SVC test vector is 1280x720, with 3 spatial layers, and 20 frames.
+
+// Decode the SVC test vector, which has 3 spatial layers, and decode up to
+// spatial layer 0. Verify the resolution of each decoded frame and the total
+// number of frames decoded. This results in 1/4x1/4 resolution (320x180).
+TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer0) {
+ const std::string filename = GET_PARAM(1);
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+ total_frames_ = 0;
+ spatial_layer_ = 0;
+ width_ = 320;
+ height_ = 180;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ ASSERT_EQ(total_frames_, kNumFrames);
+}
+
+// Decode the SVC test vector, which has 3 spatial layers, and decode up to
+// spatial layer 1. Verify the resolution of each decoded frame and the total
+// number of frames decoded. This results in 1/2x1/2 resolution (640x360).
+TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer1) {
+ const std::string filename = GET_PARAM(1);
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+ total_frames_ = 0;
+ spatial_layer_ = 1;
+ width_ = 640;
+ height_ = 360;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ ASSERT_EQ(total_frames_, kNumFrames);
+}
+
+// Decode the SVC test vector, which has 3 spatial layers, and decode up to
+// spatial layer 2. Verify the resolution of each decoded frame and the total
+// number of frames decoded. This results in the full resolution (1280x720).
+TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer2) {
+ const std::string filename = GET_PARAM(1);
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+ total_frames_ = 0;
+ spatial_layer_ = 2;
+ width_ = 1280;
+ height_ = 720;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ ASSERT_EQ(total_frames_, kNumFrames);
+}
+
+// Decode the SVC test vector, which has 3 spatial layers, and decode up to
+// spatial layer 10. Verify the resolution of each decoded frame and the total
+// number of frames decoded. This is beyond the number of spatial layers, so
+// the decoding should result in the full resolution (1280x720).
+TEST_P(DecodeSvcTest, DecodeSvcTestUpToSpatialLayer10) {
+ const std::string filename = GET_PARAM(1);
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+ total_frames_ = 0;
+ spatial_layer_ = 10;
+ width_ = 1280;
+ height_ = 720;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ ASSERT_EQ(total_frames_, kNumFrames);
+}
+
+VP9_INSTANTIATE_TEST_SUITE(
+ DecodeSvcTest, ::testing::ValuesIn(libvpx_test::kVP9TestVectorsSvc,
+ libvpx_test::kVP9TestVectorsSvc +
+ libvpx_test::kNumVP9TestVectorsSvc));
+} // namespace
diff --git a/media/libvpx/libvpx/test/decode_test_driver.cc b/media/libvpx/libvpx/test/decode_test_driver.cc
new file mode 100644
index 0000000000..773d673d37
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_test_driver.cc
@@ -0,0 +1,119 @@
+/*
+ * 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"
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/register_state_check.h"
+#include "test/video_source.h"
+
+namespace libvpx_test {
+
+const char kVP8Name[] = "WebM Project VP8";
+
+vpx_codec_err_t Decoder::PeekStream(const uint8_t *cxdata, size_t size,
+ vpx_codec_stream_info_t *stream_info) {
+ return vpx_codec_peek_stream_info(
+ CodecInterface(), cxdata, static_cast<unsigned int>(size), stream_info);
+}
+
+vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size) {
+ return DecodeFrame(cxdata, size, nullptr);
+}
+
+vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size,
+ void *user_priv) {
+ vpx_codec_err_t res_dec;
+ InitOnce();
+ API_REGISTER_STATE_CHECK(
+ res_dec = vpx_codec_decode(
+ &decoder_, cxdata, static_cast<unsigned int>(size), user_priv, 0));
+ return res_dec;
+}
+
+bool Decoder::IsVP8() const {
+ const char *codec_name = GetDecoderName();
+ return strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0;
+}
+
+void DecoderTest::HandlePeekResult(Decoder *const decoder,
+ CompressedVideoSource *video,
+ const vpx_codec_err_t res_peek) {
+ const bool is_vp8 = decoder->IsVP8();
+ if (is_vp8) {
+ /* Vp8's implementation of PeekStream returns an error if the frame you
+ * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first
+ * frame, which must be a keyframe. */
+ if (video->frame_number() == 0) {
+ ASSERT_EQ(VPX_CODEC_OK, res_peek)
+ << "Peek return failed: " << vpx_codec_err_to_string(res_peek);
+ }
+ } else {
+ /* The Vp9 implementation of PeekStream returns an error only if the
+ * data passed to it isn't a valid Vp9 chunk. */
+ ASSERT_EQ(VPX_CODEC_OK, res_peek)
+ << "Peek return failed: " << vpx_codec_err_to_string(res_peek);
+ }
+}
+
+void DecoderTest::RunLoop(CompressedVideoSource *video,
+ const vpx_codec_dec_cfg_t &dec_cfg) {
+ Decoder *const decoder = codec_->CreateDecoder(dec_cfg, flags_);
+ ASSERT_NE(decoder, nullptr);
+ bool end_of_file = false;
+
+ // Decode frames.
+ for (video->Begin(); !::testing::Test::HasFailure() && !end_of_file;
+ video->Next()) {
+ PreDecodeFrameHook(*video, decoder);
+
+ vpx_codec_stream_info_t stream_info;
+ stream_info.sz = sizeof(stream_info);
+
+ if (video->cxdata() != nullptr) {
+ const vpx_codec_err_t res_peek = decoder->PeekStream(
+ video->cxdata(), video->frame_size(), &stream_info);
+ HandlePeekResult(decoder, video, res_peek);
+ ASSERT_FALSE(::testing::Test::HasFailure());
+
+ vpx_codec_err_t res_dec =
+ decoder->DecodeFrame(video->cxdata(), video->frame_size());
+ if (!HandleDecodeResult(res_dec, *video, decoder)) break;
+ } else {
+ // Signal end of the file to the decoder.
+ const vpx_codec_err_t res_dec = decoder->DecodeFrame(nullptr, 0);
+ ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+ end_of_file = true;
+ }
+
+ DxDataIterator dec_iter = decoder->GetDxData();
+ const vpx_image_t *img = nullptr;
+
+ // Get decompressed data
+ while (!::testing::Test::HasFailure() && (img = dec_iter.Next())) {
+ DecompressedFrameHook(*img, video->frame_number());
+ }
+ }
+ delete decoder;
+}
+
+void DecoderTest::RunLoop(CompressedVideoSource *video) {
+ vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+ RunLoop(video, dec_cfg);
+}
+
+void DecoderTest::set_cfg(const vpx_codec_dec_cfg_t &dec_cfg) {
+ memcpy(&cfg_, &dec_cfg, sizeof(cfg_));
+}
+
+void DecoderTest::set_flags(const vpx_codec_flags_t flags) { flags_ = flags; }
+
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/decode_test_driver.h b/media/libvpx/libvpx/test/decode_test_driver.h
new file mode 100644
index 0000000000..f446ab4664
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_test_driver.h
@@ -0,0 +1,162 @@
+/*
+ * 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 VPX_TEST_DECODE_TEST_DRIVER_H_
+#define VPX_TEST_DECODE_TEST_DRIVER_H_
+#include <cstring>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "vpx/vpx_decoder.h"
+
+namespace libvpx_test {
+
+class CodecFactory;
+class CompressedVideoSource;
+
+// Provides an object to handle decoding output
+class DxDataIterator {
+ public:
+ explicit DxDataIterator(vpx_codec_ctx_t *decoder)
+ : decoder_(decoder), iter_(nullptr) {}
+
+ const vpx_image_t *Next() { return vpx_codec_get_frame(decoder_, &iter_); }
+
+ private:
+ vpx_codec_ctx_t *decoder_;
+ vpx_codec_iter_t iter_;
+};
+
+// Provides a simplified interface to manage one video decoding.
+// Similar to Encoder class, the exact services should be added
+// as more tests are added.
+class Decoder {
+ public:
+ explicit Decoder(vpx_codec_dec_cfg_t cfg)
+ : cfg_(cfg), flags_(0), init_done_(false) {
+ memset(&decoder_, 0, sizeof(decoder_));
+ }
+
+ Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag)
+ : cfg_(cfg), flags_(flag), init_done_(false) {
+ memset(&decoder_, 0, sizeof(decoder_));
+ }
+
+ virtual ~Decoder() { vpx_codec_destroy(&decoder_); }
+
+ vpx_codec_err_t PeekStream(const uint8_t *cxdata, size_t size,
+ vpx_codec_stream_info_t *stream_info);
+
+ vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size);
+
+ vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size,
+ void *user_priv);
+
+ DxDataIterator GetDxData() { return DxDataIterator(&decoder_); }
+
+ void Control(int ctrl_id, int arg) { Control(ctrl_id, arg, VPX_CODEC_OK); }
+
+ void Control(int ctrl_id, const void *arg) {
+ InitOnce();
+ const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+ }
+
+ void Control(int ctrl_id, int arg, vpx_codec_err_t expected_value) {
+ InitOnce();
+ const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
+ ASSERT_EQ(expected_value, res) << DecodeError();
+ }
+
+ const char *DecodeError() {
+ const char *detail = vpx_codec_error_detail(&decoder_);
+ return detail ? detail : vpx_codec_error(&decoder_);
+ }
+
+ // Passes the external frame buffer information to libvpx.
+ vpx_codec_err_t SetFrameBufferFunctions(
+ vpx_get_frame_buffer_cb_fn_t cb_get,
+ vpx_release_frame_buffer_cb_fn_t cb_release, void *user_priv) {
+ InitOnce();
+ return vpx_codec_set_frame_buffer_functions(&decoder_, cb_get, cb_release,
+ user_priv);
+ }
+
+ const char *GetDecoderName() const {
+ return vpx_codec_iface_name(CodecInterface());
+ }
+
+ bool IsVP8() const;
+
+ vpx_codec_ctx_t *GetDecoder() { return &decoder_; }
+
+ protected:
+ virtual vpx_codec_iface_t *CodecInterface() const = 0;
+
+ void InitOnce() {
+ if (!init_done_) {
+ const vpx_codec_err_t res =
+ vpx_codec_dec_init(&decoder_, CodecInterface(), &cfg_, flags_);
+ ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+ init_done_ = true;
+ }
+ }
+
+ vpx_codec_ctx_t decoder_;
+ vpx_codec_dec_cfg_t cfg_;
+ vpx_codec_flags_t flags_;
+ bool init_done_;
+};
+
+// Common test functionality for all Decoder tests.
+class DecoderTest {
+ public:
+ // Main decoding loop
+ virtual void RunLoop(CompressedVideoSource *video);
+ virtual void RunLoop(CompressedVideoSource *video,
+ const vpx_codec_dec_cfg_t &dec_cfg);
+
+ virtual void set_cfg(const vpx_codec_dec_cfg_t &dec_cfg);
+ virtual void set_flags(const vpx_codec_flags_t flags);
+
+ // Hook to be called before decompressing every frame.
+ virtual void PreDecodeFrameHook(const CompressedVideoSource & /*video*/,
+ Decoder * /*decoder*/) {}
+
+ // Hook to be called to handle decode result. Return true to continue.
+ virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+ const CompressedVideoSource & /*video*/,
+ Decoder *decoder) {
+ EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+ return VPX_CODEC_OK == res_dec;
+ }
+
+ // Hook to be called on every decompressed frame.
+ virtual void DecompressedFrameHook(const vpx_image_t & /*img*/,
+ const unsigned int /*frame_number*/) {}
+
+ // Hook to be called on peek result
+ virtual void HandlePeekResult(Decoder *const decoder,
+ CompressedVideoSource *video,
+ const vpx_codec_err_t res_peek);
+
+ protected:
+ explicit DecoderTest(const CodecFactory *codec)
+ : codec_(codec), cfg_(), flags_(0) {}
+
+ virtual ~DecoderTest() {}
+
+ const CodecFactory *codec_;
+ vpx_codec_dec_cfg_t cfg_;
+ vpx_codec_flags_t flags_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_DECODE_TEST_DRIVER_H_
diff --git a/media/libvpx/libvpx/test/decode_to_md5.sh b/media/libvpx/libvpx/test/decode_to_md5.sh
new file mode 100755
index 0000000000..15eee39fac
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_to_md5.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx decode_to_md5 example. To add new tests to this
+## file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to decode_to_md5_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+# $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+decode_to_md5_verify_environment() {
+ if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs decode_to_md5 on $1 and captures the md5 sum for the final frame. $2 is
+# interpreted as codec name and used solely to name the output file. $3 is the
+# expected md5 sum: It must match that of the final frame.
+decode_to_md5() {
+ local decoder="${LIBVPX_BIN_PATH}/decode_to_md5${VPX_TEST_EXE_SUFFIX}"
+ local input_file="$1"
+ local codec="$2"
+ local expected_md5="$3"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/decode_to_md5_${codec}"
+
+ if [ ! -x "${decoder}" ]; then
+ elog "${decoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+
+ local md5_last_frame="$(tail -n1 "${output_file}" | awk '{print $1}')"
+ local actual_md5="$(echo "${md5_last_frame}" | awk '{print $1}')"
+ [ "${actual_md5}" = "${expected_md5}" ] || return 1
+}
+
+decode_to_md5_vp8() {
+ # expected MD5 sum for the last frame.
+ local expected_md5="56794d911b02190212bca92f88ad60c6"
+
+ if [ "$(vp8_decode_available)" = "yes" ]; then
+ decode_to_md5 "${VP8_IVF_FILE}" "vp8" "${expected_md5}"
+ fi
+}
+
+decode_to_md5_vp9() {
+ # expected MD5 sum for the last frame.
+ local expected_md5="2952c0eae93f3dadd1aa84c50d3fd6d2"
+
+ if [ "$(vp9_decode_available)" = "yes" ]; then
+ decode_to_md5 "${VP9_IVF_FILE}" "vp9" "${expected_md5}"
+ fi
+}
+
+decode_to_md5_tests="decode_to_md5_vp8
+ decode_to_md5_vp9"
+
+run_tests decode_to_md5_verify_environment "${decode_to_md5_tests}"
diff --git a/media/libvpx/libvpx/test/decode_with_drops.sh b/media/libvpx/libvpx/test/decode_with_drops.sh
new file mode 100755
index 0000000000..2c826045b3
--- /dev/null
+++ b/media/libvpx/libvpx/test/decode_with_drops.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx decode_with_drops example. To add new tests to
+## this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to decode_with_drops_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+# $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+decode_with_drops_verify_environment() {
+ if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs decode_with_drops on $1, $2 is interpreted as codec name and used solely
+# to name the output file. $3 is the drop mode, and is passed directly to
+# decode_with_drops.
+decode_with_drops() {
+ local decoder="${LIBVPX_BIN_PATH}/decode_with_drops${VPX_TEST_EXE_SUFFIX}"
+ local input_file="$1"
+ local codec="$2"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/decode_with_drops_${codec}"
+ local drop_mode="$3"
+
+ if [ ! -x "${decoder}" ]; then
+ elog "${decoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+ "${drop_mode}" ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+# Decodes $VP8_IVF_FILE while dropping frames, twice: once in sequence mode,
+# and once in pattern mode.
+# Note: This test assumes that $VP8_IVF_FILE has exactly 29 frames, and could
+# break if the file is modified.
+decode_with_drops_vp8() {
+ if [ "$(vp8_decode_available)" = "yes" ]; then
+ # Test sequence mode: Drop frames 2-28.
+ decode_with_drops "${VP8_IVF_FILE}" "vp8" "2-28" || return 1
+
+ # Test pattern mode: Drop 3 of every 4 frames.
+ decode_with_drops "${VP8_IVF_FILE}" "vp8" "3/4" || return 1
+ fi
+}
+
+# Decodes $VP9_IVF_FILE while dropping frames, twice: once in sequence mode,
+# and once in pattern mode.
+# Note: This test assumes that $VP9_IVF_FILE has exactly 20 frames, and could
+# break if the file is modified.
+decode_with_drops_vp9() {
+ if [ "$(vp9_decode_available)" = "yes" ]; then
+ # Test sequence mode: Drop frames 2-28.
+ decode_with_drops "${VP9_IVF_FILE}" "vp9" "2-19" || return 1
+
+ # Test pattern mode: Drop 3 of every 4 frames.
+ decode_with_drops "${VP9_IVF_FILE}" "vp9" "3/4" || return 1
+ fi
+}
+
+decode_with_drops_tests="decode_with_drops_vp8
+ decode_with_drops_vp9"
+
+run_tests decode_with_drops_verify_environment "${decode_with_drops_tests}"
diff --git a/media/libvpx/libvpx/test/encode_api_test.cc b/media/libvpx/libvpx/test/encode_api_test.cc
new file mode 100644
index 0000000000..77a1fc4ba3
--- /dev/null
+++ b/media/libvpx/libvpx/test/encode_api_test.cc
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2016 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 <cstring>
+#include <initializer_list>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/video_source.h"
+
+#include "./vpx_config.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+namespace {
+
+const vpx_codec_iface_t *kCodecIfaces[] = {
+#if CONFIG_VP8_ENCODER
+ &vpx_codec_vp8_cx_algo,
+#endif
+#if CONFIG_VP9_ENCODER
+ &vpx_codec_vp9_cx_algo,
+#endif
+};
+
+bool IsVP9(const vpx_codec_iface_t *iface) {
+ static const char kVP9Name[] = "WebM Project VP9";
+ return strncmp(kVP9Name, vpx_codec_iface_name(iface), sizeof(kVP9Name) - 1) ==
+ 0;
+}
+
+TEST(EncodeAPI, InvalidParams) {
+ uint8_t buf[1] = { 0 };
+ vpx_image_t img;
+ vpx_codec_ctx_t enc;
+ vpx_codec_enc_cfg_t cfg;
+
+ EXPECT_EQ(&img, vpx_img_wrap(&img, VPX_IMG_FMT_I420, 1, 1, 1, buf));
+
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_init(nullptr, nullptr, nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_init(&enc, nullptr, nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_encode(nullptr, nullptr, 0, 0, 0, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_encode(nullptr, &img, 0, 0, 0, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(nullptr));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_config_default(nullptr, nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_config_default(nullptr, &cfg, 0));
+ EXPECT_NE(vpx_codec_error(nullptr), nullptr);
+
+ for (const auto *iface : kCodecIfaces) {
+ SCOPED_TRACE(vpx_codec_iface_name(iface));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_init(nullptr, iface, nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_init(&enc, iface, nullptr, 0));
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_config_default(iface, &cfg, 1));
+
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(iface, &cfg, 0));
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, iface, &cfg, 0));
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, nullptr, 0, 0, 0, 0));
+
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc));
+ }
+}
+
+TEST(EncodeAPI, HighBitDepthCapability) {
+// VP8 should not claim VP9 HBD as a capability.
+#if CONFIG_VP8_ENCODER
+ const vpx_codec_caps_t vp8_caps = vpx_codec_get_caps(&vpx_codec_vp8_cx_algo);
+ EXPECT_EQ(vp8_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
+#endif
+
+#if CONFIG_VP9_ENCODER
+ const vpx_codec_caps_t vp9_caps = vpx_codec_get_caps(&vpx_codec_vp9_cx_algo);
+#if CONFIG_VP9_HIGHBITDEPTH
+ EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, VPX_CODEC_CAP_HIGHBITDEPTH);
+#else
+ EXPECT_EQ(vp9_caps & VPX_CODEC_CAP_HIGHBITDEPTH, 0);
+#endif
+#endif
+}
+
+#if CONFIG_VP8_ENCODER
+TEST(EncodeAPI, ImageSizeSetting) {
+ const int width = 711;
+ const int height = 360;
+ const int bps = 12;
+ vpx_image_t img;
+ vpx_codec_ctx_t enc;
+ vpx_codec_enc_cfg_t cfg;
+ uint8_t *img_buf = reinterpret_cast<uint8_t *>(
+ calloc(width * height * bps / 8, sizeof(*img_buf)));
+ vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &cfg, 0);
+
+ cfg.g_w = width;
+ cfg.g_h = height;
+
+ vpx_img_wrap(&img, VPX_IMG_FMT_I420, width, height, 1, img_buf);
+
+ vpx_codec_enc_init(&enc, vpx_codec_vp8_cx(), &cfg, 0);
+
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, &img, 0, 1, 0, 0));
+
+ free(img_buf);
+
+ vpx_codec_destroy(&enc);
+}
+#endif
+
+// Set up 2 spatial streams with 2 temporal layers per stream, and generate
+// invalid configuration by setting the temporal layer rate allocation
+// (ts_target_bitrate[]) to 0 for both layers. This should fail independent of
+// CONFIG_MULTI_RES_ENCODING.
+TEST(EncodeAPI, MultiResEncode) {
+ const int width = 1280;
+ const int height = 720;
+ const int width_down = width / 2;
+ const int height_down = height / 2;
+ const int target_bitrate = 1000;
+ const int framerate = 30;
+
+ for (const auto *iface : kCodecIfaces) {
+ vpx_codec_ctx_t enc[2];
+ vpx_codec_enc_cfg_t cfg[2];
+ vpx_rational_t dsf[2] = { { 2, 1 }, { 2, 1 } };
+
+ memset(enc, 0, sizeof(enc));
+
+ for (int i = 0; i < 2; i++) {
+ vpx_codec_enc_config_default(iface, &cfg[i], 0);
+ }
+
+ /* Highest-resolution encoder settings */
+ cfg[0].g_w = width;
+ cfg[0].g_h = height;
+ cfg[0].rc_dropframe_thresh = 0;
+ cfg[0].rc_end_usage = VPX_CBR;
+ cfg[0].rc_resize_allowed = 0;
+ cfg[0].rc_min_quantizer = 2;
+ cfg[0].rc_max_quantizer = 56;
+ cfg[0].rc_undershoot_pct = 100;
+ cfg[0].rc_overshoot_pct = 15;
+ cfg[0].rc_buf_initial_sz = 500;
+ cfg[0].rc_buf_optimal_sz = 600;
+ cfg[0].rc_buf_sz = 1000;
+ cfg[0].g_error_resilient = 1; /* Enable error resilient mode */
+ cfg[0].g_lag_in_frames = 0;
+
+ cfg[0].kf_mode = VPX_KF_AUTO;
+ cfg[0].kf_min_dist = 3000;
+ cfg[0].kf_max_dist = 3000;
+
+ cfg[0].rc_target_bitrate = target_bitrate; /* Set target bitrate */
+ cfg[0].g_timebase.num = 1; /* Set fps */
+ cfg[0].g_timebase.den = framerate;
+
+ memcpy(&cfg[1], &cfg[0], sizeof(cfg[0]));
+ cfg[1].rc_target_bitrate = 500;
+ cfg[1].g_w = width_down;
+ cfg[1].g_h = height_down;
+
+ for (int i = 0; i < 2; i++) {
+ cfg[i].ts_number_layers = 2;
+ cfg[i].ts_periodicity = 2;
+ cfg[i].ts_rate_decimator[0] = 2;
+ cfg[i].ts_rate_decimator[1] = 1;
+ cfg[i].ts_layer_id[0] = 0;
+ cfg[i].ts_layer_id[1] = 1;
+ // Invalid parameters.
+ cfg[i].ts_target_bitrate[0] = 0;
+ cfg[i].ts_target_bitrate[1] = 0;
+ }
+
+ // VP9 should report incapable, VP8 invalid for all configurations.
+ EXPECT_EQ(IsVP9(iface) ? VPX_CODEC_INCAPABLE : VPX_CODEC_INVALID_PARAM,
+ vpx_codec_enc_init_multi(&enc[0], iface, &cfg[0], 2, 0, &dsf[0]));
+
+ for (int i = 0; i < 2; i++) {
+ vpx_codec_destroy(&enc[i]);
+ }
+ }
+}
+
+TEST(EncodeAPI, SetRoi) {
+ static struct {
+ const vpx_codec_iface_t *iface;
+ int ctrl_id;
+ } kCodecs[] = {
+#if CONFIG_VP8_ENCODER
+ { &vpx_codec_vp8_cx_algo, VP8E_SET_ROI_MAP },
+#endif
+#if CONFIG_VP9_ENCODER
+ { &vpx_codec_vp9_cx_algo, VP9E_SET_ROI_MAP },
+#endif
+ };
+ constexpr int kWidth = 64;
+ constexpr int kHeight = 64;
+
+ for (const auto &codec : kCodecs) {
+ SCOPED_TRACE(vpx_codec_iface_name(codec.iface));
+ vpx_codec_ctx_t enc;
+ vpx_codec_enc_cfg_t cfg;
+
+ EXPECT_EQ(vpx_codec_enc_config_default(codec.iface, &cfg, 0), VPX_CODEC_OK);
+ cfg.g_w = kWidth;
+ cfg.g_h = kHeight;
+ EXPECT_EQ(vpx_codec_enc_init(&enc, codec.iface, &cfg, 0), VPX_CODEC_OK);
+
+ vpx_roi_map_t roi = {};
+ uint8_t roi_map[kWidth * kHeight] = {};
+ if (IsVP9(codec.iface)) {
+ roi.rows = (cfg.g_w + 7) >> 3;
+ roi.cols = (cfg.g_h + 7) >> 3;
+ } else {
+ roi.rows = (cfg.g_w + 15) >> 4;
+ roi.cols = (cfg.g_h + 15) >> 4;
+ }
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), VPX_CODEC_OK);
+
+ roi.roi_map = roi_map;
+ // VP8 only. This value isn't range checked.
+ roi.static_threshold[1] = 1000;
+ roi.static_threshold[2] = UINT_MAX / 2 + 1;
+ roi.static_threshold[3] = UINT_MAX;
+
+ for (const auto delta : { -63, -1, 0, 1, 63 }) {
+ for (int i = 0; i < 8; ++i) {
+ roi.delta_q[i] = delta;
+ roi.delta_lf[i] = delta;
+ // VP9 only.
+ roi.skip[i] ^= 1;
+ roi.ref_frame[i] = (roi.ref_frame[i] + 1) % 4;
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), VPX_CODEC_OK);
+ }
+ }
+
+ vpx_codec_err_t expected_error;
+ for (const auto delta : { -64, 64, INT_MIN, INT_MAX }) {
+ expected_error = VPX_CODEC_INVALID_PARAM;
+ for (int i = 0; i < 8; ++i) {
+ roi.delta_q[i] = delta;
+ // The max segment count for VP8 is 4, the remainder of the entries are
+ // ignored.
+ if (i >= 4 && !IsVP9(codec.iface)) expected_error = VPX_CODEC_OK;
+
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), expected_error)
+ << "delta_q[" << i << "]: " << delta;
+ roi.delta_q[i] = 0;
+
+ roi.delta_lf[i] = delta;
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), expected_error)
+ << "delta_lf[" << i << "]: " << delta;
+ roi.delta_lf[i] = 0;
+ }
+ }
+
+ // VP8 should ignore skip[] and ref_frame[] values.
+ expected_error =
+ IsVP9(codec.iface) ? VPX_CODEC_INVALID_PARAM : VPX_CODEC_OK;
+ for (const auto skip : { -2, 2, INT_MIN, INT_MAX }) {
+ for (int i = 0; i < 8; ++i) {
+ roi.skip[i] = skip;
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), expected_error)
+ << "skip[" << i << "]: " << skip;
+ roi.skip[i] = 0;
+ }
+ }
+
+ // VP9 allows negative values to be used to disable segmentation.
+ for (int ref_frame = -3; ref_frame < 0; ++ref_frame) {
+ for (int i = 0; i < 8; ++i) {
+ roi.ref_frame[i] = ref_frame;
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), VPX_CODEC_OK)
+ << "ref_frame[" << i << "]: " << ref_frame;
+ roi.ref_frame[i] = 0;
+ }
+ }
+
+ for (const auto ref_frame : { 4, INT_MIN, INT_MAX }) {
+ for (int i = 0; i < 8; ++i) {
+ roi.ref_frame[i] = ref_frame;
+ EXPECT_EQ(vpx_codec_control_(&enc, codec.ctrl_id, &roi), expected_error)
+ << "ref_frame[" << i << "]: " << ref_frame;
+ roi.ref_frame[i] = 0;
+ }
+ }
+
+ EXPECT_EQ(vpx_codec_destroy(&enc), VPX_CODEC_OK);
+ }
+}
+
+void InitCodec(const vpx_codec_iface_t &iface, int width, int height,
+ vpx_codec_ctx_t *enc, vpx_codec_enc_cfg_t *cfg) {
+ cfg->g_w = width;
+ cfg->g_h = height;
+ cfg->g_lag_in_frames = 0;
+ cfg->g_pass = VPX_RC_ONE_PASS;
+ ASSERT_EQ(vpx_codec_enc_init(enc, &iface, cfg, 0), VPX_CODEC_OK);
+
+ ASSERT_EQ(vpx_codec_control_(enc, VP8E_SET_CPUUSED, 2), VPX_CODEC_OK);
+}
+
+// Encodes 1 frame of size |cfg.g_w| x |cfg.g_h| setting |enc|'s configuration
+// to |cfg|.
+void EncodeWithConfig(const vpx_codec_enc_cfg_t &cfg, vpx_codec_ctx_t *enc) {
+ libvpx_test::DummyVideoSource video;
+ video.SetSize(cfg.g_w, cfg.g_h);
+ video.Begin();
+ EXPECT_EQ(vpx_codec_enc_config_set(enc, &cfg), VPX_CODEC_OK)
+ << vpx_codec_error_detail(enc);
+
+ EXPECT_EQ(vpx_codec_encode(enc, video.img(), video.pts(), video.duration(),
+ /*flags=*/0, VPX_DL_GOOD_QUALITY),
+ VPX_CODEC_OK)
+ << vpx_codec_error_detail(enc);
+}
+
+TEST(EncodeAPI, ConfigChangeThreadCount) {
+ constexpr int kWidth = 1920;
+ constexpr int kHeight = 1080;
+
+ for (const auto *iface : kCodecIfaces) {
+ SCOPED_TRACE(vpx_codec_iface_name(iface));
+ for (int i = 0; i < (IsVP9(iface) ? 2 : 1); ++i) {
+ vpx_codec_enc_cfg_t cfg = {};
+ struct Encoder {
+ ~Encoder() { EXPECT_EQ(vpx_codec_destroy(&ctx), VPX_CODEC_OK); }
+ vpx_codec_ctx_t ctx = {};
+ } enc;
+
+ ASSERT_EQ(vpx_codec_enc_config_default(iface, &cfg, 0), VPX_CODEC_OK);
+ EXPECT_NO_FATAL_FAILURE(
+ InitCodec(*iface, kWidth, kHeight, &enc.ctx, &cfg));
+ if (IsVP9(iface)) {
+ EXPECT_EQ(vpx_codec_control_(&enc.ctx, VP9E_SET_TILE_COLUMNS, 6),
+ VPX_CODEC_OK);
+ EXPECT_EQ(vpx_codec_control_(&enc.ctx, VP9E_SET_ROW_MT, i),
+ VPX_CODEC_OK);
+ }
+
+ for (const auto threads : { 1, 4, 8, 6, 2, 1 }) {
+ cfg.g_threads = threads;
+ EXPECT_NO_FATAL_FAILURE(EncodeWithConfig(cfg, &enc.ctx))
+ << "iteration: " << i << " threads: " << threads;
+ }
+ }
+ }
+}
+
+TEST(EncodeAPI, ConfigResizeChangeThreadCount) {
+ constexpr int kInitWidth = 1024;
+ constexpr int kInitHeight = 1024;
+
+ for (const auto *iface : kCodecIfaces) {
+ SCOPED_TRACE(vpx_codec_iface_name(iface));
+ for (int i = 0; i < (IsVP9(iface) ? 2 : 1); ++i) {
+ vpx_codec_enc_cfg_t cfg = {};
+ struct Encoder {
+ ~Encoder() { EXPECT_EQ(vpx_codec_destroy(&ctx), VPX_CODEC_OK); }
+ vpx_codec_ctx_t ctx = {};
+ } enc;
+
+ ASSERT_EQ(vpx_codec_enc_config_default(iface, &cfg, 0), VPX_CODEC_OK);
+ // Start in threaded mode to ensure resolution and thread related
+ // allocations are updated correctly across changes in resolution and
+ // thread counts. See https://crbug.com/1486441.
+ cfg.g_threads = 4;
+ EXPECT_NO_FATAL_FAILURE(
+ InitCodec(*iface, kInitWidth, kInitHeight, &enc.ctx, &cfg));
+ if (IsVP9(iface)) {
+ EXPECT_EQ(vpx_codec_control_(&enc.ctx, VP9E_SET_TILE_COLUMNS, 6),
+ VPX_CODEC_OK);
+ EXPECT_EQ(vpx_codec_control_(&enc.ctx, VP9E_SET_ROW_MT, i),
+ VPX_CODEC_OK);
+ }
+
+ cfg.g_w = 1000;
+ cfg.g_h = 608;
+ EXPECT_EQ(vpx_codec_enc_config_set(&enc.ctx, &cfg), VPX_CODEC_OK)
+ << vpx_codec_error_detail(&enc.ctx);
+
+ cfg.g_w = 16;
+ cfg.g_h = 720;
+
+ for (const auto threads : { 1, 4, 8, 6, 2, 1 }) {
+ cfg.g_threads = threads;
+ EXPECT_NO_FATAL_FAILURE(EncodeWithConfig(cfg, &enc.ctx))
+ << "iteration: " << i << " threads: " << threads;
+ }
+ }
+ }
+}
+
+#if CONFIG_VP9_ENCODER
+class EncodeApiGetTplStatsTest
+ : public ::libvpx_test::EncoderTest,
+ public ::testing::TestWithParam<const libvpx_test::CodecFactory *> {
+ public:
+ EncodeApiGetTplStatsTest() : EncoderTest(GetParam()) {}
+ ~EncodeApiGetTplStatsTest() override {}
+
+ protected:
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_TPL, 1);
+ }
+ }
+
+ vpx_codec_err_t AllocateTplList(VpxTplGopStats *data) {
+ // Allocate MAX_ARF_GOP_SIZE (50) * sizeof(VpxTplFrameStats) that will be
+ // filled by VP9E_GET_TPL_STATS.
+ // MAX_ARF_GOP_SIZE is used here because the test doesn't know the size of
+ // each GOP before getting TPL stats from the encoder.
+ data->size = 50;
+ data->frame_stats_list =
+ static_cast<VpxTplFrameStats *>(calloc(50, sizeof(VpxTplFrameStats)));
+ if (data->frame_stats_list == nullptr) return VPX_CODEC_MEM_ERROR;
+ return VPX_CODEC_OK;
+ }
+
+ void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) override {
+ ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
+ while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+ switch (pkt->kind) {
+ case VPX_CODEC_CX_FRAME_PKT: {
+ VpxTplGopStats tpl_stats;
+ EXPECT_EQ(AllocateTplList(&tpl_stats), VPX_CODEC_OK);
+ encoder->Control(VP9E_GET_TPL_STATS, &tpl_stats);
+ bool stats_not_all_zero = false;
+ for (int i = 0; i < tpl_stats.size; i++) {
+ VpxTplFrameStats *frame_stats_list = tpl_stats.frame_stats_list;
+ if (frame_stats_list[i].frame_width != 0) {
+ ASSERT_EQ(frame_stats_list[i].frame_width, width_);
+ ASSERT_EQ(frame_stats_list[i].frame_height, height_);
+ ASSERT_GT(frame_stats_list[i].num_blocks, 0);
+ ASSERT_NE(frame_stats_list[i].block_stats_list, nullptr);
+ stats_not_all_zero = true;
+ }
+ }
+ ASSERT_TRUE(stats_not_all_zero);
+ // Free the memory right away now as this is only a test.
+ free(tpl_stats.frame_stats_list);
+ break;
+ }
+ default: break;
+ }
+ }
+ }
+
+ int width_;
+ int height_;
+};
+
+TEST_P(EncodeApiGetTplStatsTest, GetTplStats) {
+ cfg_.g_lag_in_frames = 25;
+ width_ = 352;
+ height_ = 288;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", width_,
+ height_, 30, 1, 0, 50);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9, EncodeApiGetTplStatsTest,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
+#endif // CONFIG_VP9_ENCODER
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/encode_perf_test.cc b/media/libvpx/libvpx/test/encode_perf_test.cc
new file mode 100644
index 0000000000..142a55952b
--- /dev/null
+++ b/media/libvpx/libvpx/test/encode_perf_test.cc
@@ -0,0 +1,188 @@
+/*
+ * 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 <string>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "./vpx_version.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vpx_ports/vpx_timer.h"
+
+namespace {
+
+const int kMaxPsnr = 100;
+const double kUsecsInSec = 1000000.0;
+
+struct EncodePerfTestVideo {
+ EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
+ uint32_t bitrate_, int frames_)
+ : name(name_), width(width_), height(height_), bitrate(bitrate_),
+ frames(frames_) {}
+ const char *name;
+ uint32_t width;
+ uint32_t height;
+ uint32_t bitrate;
+ int frames;
+};
+
+const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
+ EncodePerfTestVideo("desktop_640_360_30.yuv", 640, 360, 200, 2484),
+ EncodePerfTestVideo("kirland_640_480_30.yuv", 640, 480, 200, 300),
+ EncodePerfTestVideo("macmarcomoving_640_480_30.yuv", 640, 480, 200, 987),
+ EncodePerfTestVideo("macmarcostationary_640_480_30.yuv", 640, 480, 200, 718),
+ EncodePerfTestVideo("niklas_640_480_30.yuv", 640, 480, 200, 471),
+ EncodePerfTestVideo("tacomanarrows_640_480_30.yuv", 640, 480, 200, 300),
+ EncodePerfTestVideo("tacomasmallcameramovement_640_480_30.yuv", 640, 480, 200,
+ 300),
+ EncodePerfTestVideo("thaloundeskmtg_640_480_30.yuv", 640, 480, 200, 300),
+ EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
+};
+
+const int kEncodePerfTestSpeeds[] = { 5, 6, 7, 8, 9 };
+const int kEncodePerfTestThreads[] = { 1, 2, 4 };
+
+#define NELEMENTS(x) (sizeof((x)) / sizeof((x)[0]))
+
+class VP9EncodePerfTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ VP9EncodePerfTest()
+ : EncoderTest(GET_PARAM(0)), min_psnr_(kMaxPsnr), nframes_(0),
+ encoding_mode_(GET_PARAM(1)), speed_(0), threads_(1) {}
+
+ virtual ~VP9EncodePerfTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_resize_allowed = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_error_resilient = 1;
+ cfg_.g_threads = threads_;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ const int log2_tile_columns = 3;
+ encoder->Control(VP8E_SET_CPUUSED, speed_);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, log2_tile_columns);
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 0);
+ }
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ min_psnr_ = kMaxPsnr;
+ nframes_ = 0;
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->data.psnr.psnr[0] < min_psnr_) {
+ min_psnr_ = pkt->data.psnr.psnr[0];
+ }
+ }
+
+ // for performance reasons don't decode
+ virtual bool DoDecode() const { return false; }
+
+ double min_psnr() const { return min_psnr_; }
+
+ void set_speed(unsigned int speed) { speed_ = speed; }
+
+ void set_threads(unsigned int threads) { threads_ = threads; }
+
+ private:
+ double min_psnr_;
+ unsigned int nframes_;
+ libvpx_test::TestMode encoding_mode_;
+ unsigned speed_;
+ unsigned int threads_;
+};
+
+TEST_P(VP9EncodePerfTest, PerfTest) {
+ for (size_t i = 0; i < NELEMENTS(kVP9EncodePerfTestVectors); ++i) {
+ for (size_t j = 0; j < NELEMENTS(kEncodePerfTestSpeeds); ++j) {
+ for (size_t k = 0; k < NELEMENTS(kEncodePerfTestThreads); ++k) {
+ if (kVP9EncodePerfTestVectors[i].width < 512 &&
+ kEncodePerfTestThreads[k] > 1) {
+ continue;
+ } else if (kVP9EncodePerfTestVectors[i].width < 1024 &&
+ kEncodePerfTestThreads[k] > 2) {
+ continue;
+ }
+
+ set_threads(kEncodePerfTestThreads[k]);
+ SetUp();
+
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ const unsigned frames = kVP9EncodePerfTestVectors[i].frames;
+ const char *video_name = kVP9EncodePerfTestVectors[i].name;
+ libvpx_test::I420VideoSource video(
+ video_name, kVP9EncodePerfTestVectors[i].width,
+ kVP9EncodePerfTestVectors[i].height, timebase.den, timebase.num, 0,
+ kVP9EncodePerfTestVectors[i].frames);
+ set_speed(kEncodePerfTestSpeeds[j]);
+
+ vpx_usec_timer t;
+ vpx_usec_timer_start(&t);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ vpx_usec_timer_mark(&t);
+ const double elapsed_secs = vpx_usec_timer_elapsed(&t) / kUsecsInSec;
+ const double fps = frames / elapsed_secs;
+ const double minimum_psnr = min_psnr();
+ std::string display_name(video_name);
+ if (kEncodePerfTestThreads[k] > 1) {
+ char thread_count[32];
+ snprintf(thread_count, sizeof(thread_count), "_t-%d",
+ kEncodePerfTestThreads[k]);
+ display_name += thread_count;
+ }
+
+ printf("{\n");
+ printf("\t\"type\" : \"encode_perf_test\",\n");
+ printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
+ printf("\t\"videoName\" : \"%s\",\n", display_name.c_str());
+ printf("\t\"encodeTimeSecs\" : %f,\n", elapsed_secs);
+ printf("\t\"totalFrames\" : %u,\n", frames);
+ printf("\t\"framesPerSecond\" : %f,\n", fps);
+ printf("\t\"minPsnr\" : %f,\n", minimum_psnr);
+ printf("\t\"speed\" : %d,\n", kEncodePerfTestSpeeds[j]);
+ printf("\t\"threads\" : %d\n", kEncodePerfTestThreads[k]);
+ printf("}\n");
+ }
+ }
+ }
+}
+
+VP9_INSTANTIATE_TEST_SUITE(VP9EncodePerfTest,
+ ::testing::Values(::libvpx_test::kRealTime));
+} // namespace
diff --git a/media/libvpx/libvpx/test/encode_test_driver.cc b/media/libvpx/libvpx/test/encode_test_driver.cc
new file mode 100644
index 0000000000..d3feeee34d
--- /dev/null
+++ b/media/libvpx/libvpx/test/encode_test_driver.cc
@@ -0,0 +1,269 @@
+/*
+ * 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 <memory>
+#include <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/encode_test_driver.h"
+#include "test/register_state_check.h"
+#include "test/video_source.h"
+
+namespace libvpx_test {
+void Encoder::InitEncoder(VideoSource *video) {
+ vpx_codec_err_t res;
+ const vpx_image_t *img = video->img();
+
+ if (video->img() && !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_, CodecInterface(), &cfg_, init_flags_);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+
+#if CONFIG_VP9_ENCODER
+ if (CodecInterface() == &vpx_codec_vp9_cx_algo) {
+ // Default to 1 tile column for VP9.
+ const int log2_tile_columns = 0;
+ res = vpx_codec_control_(&encoder_, VP9E_SET_TILE_COLUMNS,
+ log2_tile_columns);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ } else
+#endif
+ {
+#if CONFIG_VP8_ENCODER
+ ASSERT_EQ(&vpx_codec_vp8_cx_algo, CodecInterface())
+ << "Unknown Codec Interface";
+#endif
+ }
+ }
+}
+
+void Encoder::EncodeFrame(VideoSource *video,
+ const vpx_enc_frame_flags_t frame_flags) {
+ if (video->img()) {
+ EncodeFrameInternal(*video, frame_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,
+ const vpx_enc_frame_flags_t frame_flags) {
+ vpx_codec_err_t res;
+ const vpx_image_t *img = video.img();
+
+ // 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
+ API_REGISTER_STATE_CHECK(res = vpx_codec_encode(&encoder_, img, video.pts(),
+ video.duration(), frame_flags,
+ deadline_));
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+}
+
+void Encoder::Flush() {
+ const vpx_codec_err_t res =
+ vpx_codec_encode(&encoder_, nullptr, 0, 0, 0, deadline_);
+ if (!encoder_.priv)
+ ASSERT_EQ(VPX_CODEC_ERROR, res) << EncoderError();
+ else
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+}
+
+void EncoderTest::InitializeConfig() {
+ const vpx_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0);
+ dec_cfg_ = vpx_codec_dec_cfg_t();
+ ASSERT_EQ(VPX_CODEC_OK, res);
+}
+
+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;
+ }
+}
+// The function should return "true" most of the time, therefore no early
+// break-out is implemented within the match checking process.
+static bool compare_img(const vpx_image_t *img1, const vpx_image_t *img2) {
+ bool match = (img1->fmt == img2->fmt) && (img1->cs == img2->cs) &&
+ (img1->d_w == img2->d_w) && (img1->d_h == img2->d_h);
+
+ if (!match) return false;
+
+ const unsigned int width_y = img1->d_w;
+ const unsigned int height_y = img1->d_h;
+ unsigned int i;
+ for (i = 0; i < height_y; ++i) {
+ match = (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
+ img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
+ width_y) == 0) &&
+ match;
+ }
+ const unsigned int width_uv = (img1->d_w + 1) >> 1;
+ const unsigned int height_uv = (img1->d_h + 1) >> 1;
+ for (i = 0; i < height_uv; ++i) {
+ match = (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
+ img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
+ width_uv) == 0) &&
+ match;
+ }
+ for (i = 0; i < height_uv; ++i) {
+ match = (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
+ img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
+ width_uv) == 0) &&
+ match;
+ }
+ return match;
+}
+
+void EncoderTest::MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {
+ ASSERT_TRUE(0) << "Encode/Decode mismatch found";
+}
+
+void EncoderTest::RunLoop(VideoSource *video) {
+ vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+
+ stats_.Reset();
+
+ ASSERT_TRUE(passes_ == 1 || passes_ == 2);
+ for (unsigned int pass = 0; pass < passes_; pass++) {
+ vpx_codec_pts_t last_pts = 0;
+
+ 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);
+ std::unique_ptr<Encoder> encoder(
+ codec_->CreateEncoder(cfg_, deadline_, init_flags_, &stats_));
+ ASSERT_NE(encoder.get(), nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(video->Begin());
+ encoder->InitEncoder(video);
+ ASSERT_FALSE(::testing::Test::HasFatalFailure());
+
+ unsigned long dec_init_flags = 0; // NOLINT
+ // Use fragment decoder if encoder outputs partitions.
+ // NOTE: fragment decoder and partition encoder are only supported by VP8.
+ if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) {
+ dec_init_flags |= VPX_CODEC_USE_INPUT_FRAGMENTS;
+ }
+ std::unique_ptr<Decoder> decoder(
+ codec_->CreateDecoder(dec_cfg, dec_init_flags));
+ bool again;
+ for (again = true; again; video->Next()) {
+ again = (video->img() != nullptr);
+
+ PreEncodeFrameHook(video);
+ PreEncodeFrameHook(video, encoder.get());
+ encoder->EncodeFrame(video, frame_flags_);
+
+ PostEncodeFrameHook(encoder.get());
+
+ CxDataIterator iter = encoder->GetCxData();
+
+ bool has_cxdata = false;
+ bool has_dxdata = false;
+ while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+ pkt = MutateEncoderOutputHook(pkt);
+ again = true;
+ switch (pkt->kind) {
+ case VPX_CODEC_CX_FRAME_PKT:
+ has_cxdata = true;
+ if (decoder != nullptr && DoDecode()) {
+ PreDecodeFrameHook(video, decoder.get());
+ vpx_codec_err_t res_dec = decoder->DecodeFrame(
+ (const uint8_t *)pkt->data.frame.buf, pkt->data.frame.sz);
+
+ if (!HandleDecodeResult(res_dec, *video, decoder.get())) break;
+
+ has_dxdata = true;
+ }
+ ASSERT_GE(pkt->data.frame.pts, last_pts);
+ last_pts = pkt->data.frame.pts;
+ FramePktHook(pkt);
+ break;
+
+ case VPX_CODEC_PSNR_PKT: PSNRPktHook(pkt); break;
+
+ case VPX_CODEC_STATS_PKT: StatsPktHook(pkt); break;
+
+ default: break;
+ }
+ }
+
+ // Flush the decoder when there are no more fragments.
+ if ((init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) {
+ const vpx_codec_err_t res_dec = decoder->DecodeFrame(nullptr, 0);
+ if (!HandleDecodeResult(res_dec, *video, decoder.get())) break;
+ }
+
+ if (has_dxdata && has_cxdata) {
+ const vpx_image_t *img_enc = encoder->GetPreviewFrame();
+ DxDataIterator dec_iter = decoder->GetDxData();
+ const vpx_image_t *img_dec = dec_iter.Next();
+ if (img_enc && img_dec) {
+ const bool res = compare_img(img_enc, img_dec);
+ if (!res) { // Mismatch
+ MismatchHook(img_enc, img_dec);
+ }
+ }
+ if (img_dec) DecompressedFrameHook(*img_dec, video->pts());
+ }
+ if (!Continue()) break;
+ }
+
+ EndPassHook();
+
+ if (!Continue()) break;
+ }
+}
+
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/encode_test_driver.h b/media/libvpx/libvpx/test/encode_test_driver.h
new file mode 100644
index 0000000000..922c49f420
--- /dev/null
+++ b/media/libvpx/libvpx/test/encode_test_driver.h
@@ -0,0 +1,302 @@
+/*
+ * 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 VPX_TEST_ENCODE_TEST_DRIVER_H_
+#define VPX_TEST_ENCODE_TEST_DRIVER_H_
+
+#include <string>
+#include <vector>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+#include "vpx/vpx_encoder.h"
+
+namespace libvpx_test {
+
+class CodecFactory;
+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)
+
+#define ONE_PASS_TEST_MODES \
+ ::testing::Values(::libvpx_test::kRealTime, ::libvpx_test::kOnePassGood, \
+ ::libvpx_test::kOnePassBest)
+
+#define TWO_PASS_TEST_MODES \
+ ::testing::Values(::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_(nullptr) {}
+
+ 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;
+ }
+
+ void Reset() { buffer_.clear(); }
+
+ 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,
+ const unsigned long init_flags, TwopassStatsStore *stats)
+ : cfg_(cfg), deadline_(deadline), init_flags_(init_flags), stats_(stats) {
+ memset(&encoder_, 0, sizeof(encoder_));
+ }
+
+ virtual ~Encoder() { vpx_codec_destroy(&encoder_); }
+
+ CxDataIterator GetCxData() { return CxDataIterator(&encoder_); }
+
+ void InitEncoder(VideoSource *video);
+
+ const vpx_image_t *GetPreviewFrame() {
+ return vpx_codec_get_preview_frame(&encoder_);
+ }
+ // This is a thin wrapper around vpx_codec_encode(), so refer to
+ // vpx_encoder.h for its semantics.
+ void EncodeFrame(VideoSource *video, vpx_enc_frame_flags_t frame_flags);
+
+ // Convenience wrapper for EncodeFrame()
+ void EncodeFrame(VideoSource *video) { EncodeFrame(video, 0); }
+
+ void Control(int ctrl_id, int arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, int *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, struct vpx_scaling_mode *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, struct vpx_svc_layer_id *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, struct vpx_svc_ref_frame_config *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, struct vpx_svc_frame_drop *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, struct vpx_svc_spatial_layer_sync *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+#if CONFIG_VP9_ENCODER
+ void Control(int ctrl_id, vpx_rc_funcs_t *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, VpxTplGopStats *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+#endif // CONFIG_VP9_ENCODER
+
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
+ void Control(int ctrl_id, vpx_active_map_t *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+
+ void Control(int ctrl_id, vpx_roi_map_t *arg) {
+ const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ }
+#endif
+ void Config(const vpx_codec_enc_cfg_t *cfg) {
+ const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg);
+ ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+ cfg_ = *cfg;
+ }
+
+ void set_deadline(unsigned long deadline) { deadline_ = deadline; }
+
+ protected:
+ virtual vpx_codec_iface_t *CodecInterface() const = 0;
+
+ 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,
+ vpx_enc_frame_flags_t frame_flags);
+
+ // Flush the encoder on EOS
+ void Flush();
+
+ vpx_codec_ctx_t encoder_;
+ vpx_codec_enc_cfg_t cfg_;
+ unsigned long deadline_;
+ unsigned long init_flags_;
+ 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:
+ explicit EncoderTest(const CodecFactory *codec)
+ : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0) {
+ // Default to 1 thread.
+ cfg_.g_threads = 1;
+ }
+
+ virtual ~EncoderTest() {}
+
+ // Initialize the cfg_ member with the default configuration.
+ void InitializeConfig();
+
+ // Map the TestMode enum to the deadline_ and passes_ variables.
+ void SetMode(TestMode mode);
+
+ // Set encoder flag.
+ void set_init_flags(unsigned long flag) { // NOLINT(runtime/int)
+ init_flags_ = flag;
+ }
+
+ // 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*/) {}
+ virtual void PreEncodeFrameHook(VideoSource * /*video*/,
+ Encoder * /*encoder*/) {}
+
+ virtual void PreDecodeFrameHook(VideoSource * /*video*/,
+ Decoder * /*decoder*/) {}
+
+ virtual void PostEncodeFrameHook(Encoder * /*encoder*/) {}
+
+ // Hook to be called on every compressed data packet.
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}
+
+ // Hook to be called on every PSNR packet.
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}
+
+ // Hook to be called on every first pass stats packet.
+ virtual void StatsPktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {}
+
+ // Hook to determine whether the encode loop should continue.
+ virtual bool Continue() const {
+ return !(::testing::Test::HasFatalFailure() || abort_);
+ }
+
+ const CodecFactory *codec_;
+ // Hook to determine whether to decode frame after encoding
+ virtual bool DoDecode() const { return 1; }
+
+ // Hook to handle encode/decode mismatch
+ virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2);
+
+ // Hook to be called on every decompressed frame.
+ virtual void DecompressedFrameHook(const vpx_image_t & /*img*/,
+ vpx_codec_pts_t /*pts*/) {}
+
+ // Hook to be called to handle decode result. Return true to continue.
+ virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+ const VideoSource & /*video*/,
+ Decoder *decoder) {
+ EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+ return VPX_CODEC_OK == res_dec;
+ }
+
+ // Hook that can modify the encoder's output data
+ virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook(
+ const vpx_codec_cx_pkt_t *pkt) {
+ return pkt;
+ }
+
+ bool abort_;
+ vpx_codec_enc_cfg_t cfg_;
+ vpx_codec_dec_cfg_t dec_cfg_;
+ unsigned int passes_;
+ unsigned long deadline_;
+ TwopassStatsStore stats_;
+ unsigned long init_flags_;
+ vpx_enc_frame_flags_t frame_flags_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_ENCODE_TEST_DRIVER_H_
diff --git a/media/libvpx/libvpx/test/error_resilience_test.cc b/media/libvpx/libvpx/test/error_resilience_test.cc
new file mode 100644
index 0000000000..45138f14b9
--- /dev/null
+++ b/media/libvpx/libvpx/test/error_resilience_test.cc
@@ -0,0 +1,582 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+const int kMaxErrorFrames = 12;
+const int kMaxDroppableFrames = 12;
+
+class ErrorResilienceTestLarge
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
+ protected:
+ ErrorResilienceTestLarge()
+ : EncoderTest(GET_PARAM(0)), svc_support_(GET_PARAM(2)), psnr_(0.0),
+ nframes_(0), mismatch_psnr_(0.0), mismatch_nframes_(0),
+ encoding_mode_(GET_PARAM(1)) {
+ Reset();
+ }
+
+ virtual ~ErrorResilienceTestLarge() {}
+
+ void Reset() {
+ error_nframes_ = 0;
+ droppable_nframes_ = 0;
+ pattern_switch_ = 0;
+ }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ psnr_ = 0.0;
+ nframes_ = 0;
+ mismatch_psnr_ = 0.0;
+ mismatch_nframes_ = 0;
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ psnr_ += pkt->data.psnr.psnr[0];
+ nframes_++;
+ }
+
+ //
+ // Frame flags and layer id for temporal layers.
+ // For two layers, test pattern is:
+ // 1 3
+ // 0 2 .....
+ // LAST is updated on base/layer 0, GOLDEN updated on layer 1.
+ // Non-zero pattern_switch parameter means pattern will switch to
+ // not using LAST for frame_num >= pattern_switch.
+ int SetFrameFlags(int frame_num, int num_temp_layers, int pattern_switch) {
+ int frame_flags = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ if (frame_num < pattern_switch || pattern_switch == 0) {
+ // Layer 0: predict from LAST and ARF, update LAST.
+ frame_flags =
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+ } else {
+ // Layer 0: predict from GF and ARF, update GF.
+ frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
+ VP8_EFLAG_NO_UPD_ARF;
+ }
+ } else {
+ if (frame_num < pattern_switch || pattern_switch == 0) {
+ // Layer 1: predict from L, GF, and ARF, update GF.
+ frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+ } else {
+ // Layer 1: predict from GF and ARF, update GF.
+ frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
+ VP8_EFLAG_NO_UPD_ARF;
+ }
+ }
+ }
+ return frame_flags;
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video) {
+ frame_flags_ &=
+ ~(VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF);
+ // For temporal layer case.
+ if (cfg_.ts_number_layers > 1) {
+ frame_flags_ =
+ SetFrameFlags(video->frame(), cfg_.ts_number_layers, pattern_switch_);
+ for (unsigned int i = 0; i < droppable_nframes_; ++i) {
+ if (droppable_frames_[i] == video->frame()) {
+ std::cout << "Encoding droppable frame: " << droppable_frames_[i]
+ << "\n";
+ }
+ }
+ } else {
+ if (droppable_nframes_ > 0 &&
+ (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
+ for (unsigned int i = 0; i < droppable_nframes_; ++i) {
+ if (droppable_frames_[i] == video->frame()) {
+ std::cout << "Encoding droppable frame: " << droppable_frames_[i]
+ << "\n";
+ frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+ VP8_EFLAG_NO_UPD_ARF);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ double GetAveragePsnr() const {
+ if (nframes_) return psnr_ / nframes_;
+ return 0.0;
+ }
+
+ double GetAverageMismatchPsnr() const {
+ if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_;
+ return 0.0;
+ }
+
+ virtual bool DoDecode() const {
+ if (error_nframes_ > 0 &&
+ (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
+ for (unsigned int i = 0; i < error_nframes_; ++i) {
+ if (error_frames_[i] == nframes_ - 1) {
+ std::cout << " Skipping decoding frame: "
+ << error_frames_[i] << "\n";
+ return 0;
+ }
+ }
+ }
+ return 1;
+ }
+
+ virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
+ double mismatch_psnr = compute_psnr(img1, img2);
+ mismatch_psnr_ += mismatch_psnr;
+ ++mismatch_nframes_;
+ // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
+ }
+
+ void SetErrorFrames(int num, unsigned int *list) {
+ if (num > kMaxErrorFrames) {
+ num = kMaxErrorFrames;
+ } else if (num < 0) {
+ num = 0;
+ }
+ error_nframes_ = num;
+ for (unsigned int i = 0; i < error_nframes_; ++i) {
+ error_frames_[i] = list[i];
+ }
+ }
+
+ void SetDroppableFrames(int num, unsigned int *list) {
+ if (num > kMaxDroppableFrames) {
+ num = kMaxDroppableFrames;
+ } else if (num < 0) {
+ num = 0;
+ }
+ droppable_nframes_ = num;
+ for (unsigned int i = 0; i < droppable_nframes_; ++i) {
+ droppable_frames_[i] = list[i];
+ }
+ }
+
+ unsigned int GetMismatchFrames() { return mismatch_nframes_; }
+
+ void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
+
+ bool svc_support_;
+
+ private:
+ double psnr_;
+ unsigned int nframes_;
+ unsigned int error_nframes_;
+ unsigned int droppable_nframes_;
+ unsigned int pattern_switch_;
+ double mismatch_psnr_;
+ unsigned int mismatch_nframes_;
+ unsigned int error_frames_[kMaxErrorFrames];
+ unsigned int droppable_frames_[kMaxDroppableFrames];
+ libvpx_test::TestMode encoding_mode_;
+};
+
+TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 2000;
+ cfg_.g_lag_in_frames = 10;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 30);
+
+ // Error resilient mode OFF.
+ cfg_.g_error_resilient = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double psnr_resilience_off = GetAveragePsnr();
+ EXPECT_GT(psnr_resilience_off, 25.0);
+
+ // Error resilient mode ON.
+ cfg_.g_error_resilient = 1;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double psnr_resilience_on = GetAveragePsnr();
+ EXPECT_GT(psnr_resilience_on, 25.0);
+
+ // Test that turning on error resilient mode hurts by 10% at most.
+ if (psnr_resilience_off > 0.0) {
+ const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
+ EXPECT_GE(psnr_ratio, 0.9);
+ EXPECT_LE(psnr_ratio, 1.1);
+ }
+}
+
+// Check for successful decoding and no encoder/decoder mismatch
+// if we lose (i.e., drop before decoding) a set of droppable
+// frames (i.e., frames that don't update any reference buffers).
+// Check both isolated and consecutive loss.
+TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 500;
+ // FIXME(debargha): Fix this to work for any lag.
+ // Currently this test only works for lag = 0
+ cfg_.g_lag_in_frames = 0;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 40);
+
+ // Error resilient mode ON.
+ cfg_.g_error_resilient = 1;
+ cfg_.kf_mode = VPX_KF_DISABLED;
+
+ // Set an arbitrary set of error frames same as droppable frames.
+ // In addition to isolated loss/drop, add a long consecutive series
+ // (of size 9) of dropped frames.
+ unsigned int num_droppable_frames = 11;
+ unsigned int droppable_frame_list[] = { 5, 16, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30 };
+ SetDroppableFrames(num_droppable_frames, droppable_frame_list);
+ SetErrorFrames(num_droppable_frames, droppable_frame_list);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Test that no mismatches have been found
+ std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
+ EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
+
+ // Reset previously set of error/droppable frames.
+ Reset();
+
+#if 0
+ // TODO(jkoleszar): This test is disabled for the time being as too
+ // sensitive. It's not clear how to set a reasonable threshold for
+ // this behavior.
+
+ // Now set an arbitrary set of error frames that are non-droppable
+ unsigned int num_error_frames = 3;
+ unsigned int error_frame_list[] = {3, 10, 20};
+ SetErrorFrames(num_error_frames, error_frame_list);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ // Test that dropping an arbitrary set of inter frames does not hurt too much
+ // Note the Average Mismatch PSNR is the average of the PSNR between
+ // decoded frame and encoder's version of the same frame for all frames
+ // with mismatch.
+ const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
+ std::cout << " Mismatch PSNR: "
+ << psnr_resilience_mismatch << "\n";
+ EXPECT_GT(psnr_resilience_mismatch, 20.0);
+#endif
+}
+
+// Check for successful decoding and no encoder/decoder mismatch
+// if we lose (i.e., drop before decoding) the enhancement layer frames for a
+// two layer temporal pattern. The base layer does not predict from the top
+// layer, so successful decoding is expected.
+TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
+ // This test doesn't run if SVC is not supported.
+ if (!svc_support_) return;
+
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = 0;
+
+ cfg_.rc_end_usage = VPX_CBR;
+ // 2 Temporal layers, no spatial layers, CBR mode.
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 2;
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+ cfg_.ts_periodicity = 2;
+ cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 40);
+
+ // Error resilient mode ON.
+ cfg_.g_error_resilient = 1;
+ cfg_.kf_mode = VPX_KF_DISABLED;
+ SetPatternSwitch(0);
+
+ // The odd frames are the enhancement layer for 2 layer pattern, so set
+ // those frames as droppable. Drop the last 7 frames.
+ unsigned int num_droppable_frames = 7;
+ unsigned int droppable_frame_list[] = { 27, 29, 31, 33, 35, 37, 39 };
+ SetDroppableFrames(num_droppable_frames, droppable_frame_list);
+ SetErrorFrames(num_droppable_frames, droppable_frame_list);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Test that no mismatches have been found
+ std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
+ EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
+
+ // Reset previously set of error/droppable frames.
+ Reset();
+}
+
+// Check for successful decoding and no encoder/decoder mismatch
+// for a two layer temporal pattern, where at some point in the
+// sequence, the LAST ref is not used anymore.
+TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
+ // This test doesn't run if SVC is not supported.
+ if (!svc_support_) return;
+
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = 0;
+
+ cfg_.rc_end_usage = VPX_CBR;
+ // 2 Temporal layers, no spatial layers, CBR mode.
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 2;
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+ cfg_.ts_periodicity = 2;
+ cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 100);
+
+ // Error resilient mode ON.
+ cfg_.g_error_resilient = 1;
+ cfg_.kf_mode = VPX_KF_DISABLED;
+ SetPatternSwitch(60);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Test that no mismatches have been found
+ std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
+ EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
+
+ // Reset previously set of error/droppable frames.
+ Reset();
+}
+
+class ErrorResilienceTestLargeCodecControls
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ ErrorResilienceTestLargeCodecControls()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)) {
+ Reset();
+ }
+
+ virtual ~ErrorResilienceTestLargeCodecControls() {}
+
+ void Reset() {
+ last_pts_ = 0;
+ tot_frame_number_ = 0;
+ // For testing up to 3 layers.
+ for (int i = 0; i < 3; ++i) {
+ bits_total_[i] = 0;
+ }
+ duration_ = 0.0;
+ }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ }
+
+ //
+ // Frame flags and layer id for temporal layers.
+ //
+
+ // For two layers, test pattern is:
+ // 1 3
+ // 0 2 .....
+ // For three layers, test pattern is:
+ // 1 3 5 7
+ // 2 6
+ // 0 4 ....
+ // LAST is always update on base/layer 0, GOLDEN is updated on layer 1,
+ // and ALTREF is updated on top layer for 3 layer pattern.
+ int SetFrameFlags(int frame_num, int num_temp_layers) {
+ int frame_flags = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ // Layer 0: predict from L and ARF, update L.
+ frame_flags =
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+ } else {
+ // Layer 1: predict from L, G and ARF, and update G.
+ frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+ VP8_EFLAG_NO_UPD_ENTROPY;
+ }
+ } else if (num_temp_layers == 3) {
+ if (frame_num % 4 == 0) {
+ // Layer 0: predict from L, update L.
+ frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+ } else if ((frame_num - 2) % 4 == 0) {
+ // Layer 1: predict from L, G, update G.
+ frame_flags =
+ VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
+ } else if ((frame_num - 1) % 2 == 0) {
+ // Layer 2: predict from L, G, ARF; update ARG.
+ frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+ }
+ }
+ return frame_flags;
+ }
+
+ int SetLayerId(int frame_num, int num_temp_layers) {
+ int layer_id = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ layer_id = 0;
+ } else {
+ layer_id = 1;
+ }
+ } else if (num_temp_layers == 3) {
+ if (frame_num % 4 == 0) {
+ layer_id = 0;
+ } else if ((frame_num - 2) % 4 == 0) {
+ layer_id = 1;
+ } else if ((frame_num - 1) % 2 == 0) {
+ layer_id = 2;
+ }
+ }
+ return layer_id;
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (cfg_.ts_number_layers > 1) {
+ int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
+ int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
+ if (video->frame() > 0) {
+ encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
+ encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
+ }
+ const vpx_rational_t tb = video->timebase();
+ timebase_ = static_cast<double>(tb.num) / tb.den;
+ duration_ = 0;
+ return;
+ }
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ // Time since last timestamp = duration.
+ vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+ if (duration > 1) {
+ // Update counter for total number of frames (#frames input to encoder).
+ // Needed for setting the proper layer_id below.
+ tot_frame_number_ += static_cast<int>(duration - 1);
+ }
+ int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
+ const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
+ // Update the total encoded bits. For temporal layers, update the cumulative
+ // encoded bits per layer.
+ for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
+ bits_total_[i] += frame_size_in_bits;
+ }
+ // Update the most recent pts.
+ last_pts_ = pkt->data.frame.pts;
+ ++tot_frame_number_;
+ }
+
+ virtual void EndPassHook() {
+ duration_ = (last_pts_ + 1) * timebase_;
+ if (cfg_.ts_number_layers > 1) {
+ for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
+ ++layer) {
+ if (bits_total_[layer]) {
+ // Effective file datarate:
+ effective_datarate_[layer] =
+ (bits_total_[layer] / 1000.0) / duration_;
+ }
+ }
+ }
+ }
+
+ double effective_datarate_[3];
+
+ private:
+ libvpx_test::TestMode encoding_mode_;
+ vpx_codec_pts_t last_pts_;
+ double timebase_;
+ int64_t bits_total_[3];
+ double duration_;
+ int tot_frame_number_;
+};
+
+// Check two codec controls used for:
+// (1) for setting temporal layer id, and (2) for settings encoder flags.
+// This test invokes those controls for each frame, and verifies encoder/decoder
+// mismatch and basic rate control response.
+// TODO(marpan): Maybe move this test to datarate_test.cc.
+TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.kf_mode = VPX_KF_DISABLED;
+ cfg_.g_error_resilient = 1;
+
+ // 3 Temporal layers. Framerate decimation (4, 2, 1).
+ cfg_.ts_number_layers = 3;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.ts_periodicity = 4;
+ cfg_.ts_layer_id[0] = 0;
+ cfg_.ts_layer_id[1] = 2;
+ cfg_.ts_layer_id[2] = 1;
+ cfg_.ts_layer_id[3] = 2;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 200);
+ for (int i = 200; i <= 800; i += 200) {
+ cfg_.rc_target_bitrate = i;
+ Reset();
+ // 40-20-40 bitrate allocation for 3 temporal layers.
+ cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+ ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
+ << " The datarate for the file is lower than target by too much, "
+ "for layer: "
+ << j;
+ ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
+ << " The datarate for the file is greater than target by too much, "
+ "for layer: "
+ << j;
+ }
+ }
+}
+
+VP8_INSTANTIATE_TEST_SUITE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
+ ::testing::Values(true));
+VP8_INSTANTIATE_TEST_SUITE(ErrorResilienceTestLargeCodecControls,
+ ONE_PASS_TEST_MODES);
+VP9_INSTANTIATE_TEST_SUITE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
+ ::testing::Values(true));
+} // namespace
diff --git a/media/libvpx/libvpx/test/examples.sh b/media/libvpx/libvpx/test/examples.sh
new file mode 100755
index 0000000000..629f04239c
--- /dev/null
+++ b/media/libvpx/libvpx/test/examples.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file runs all of the tests for the libvpx examples.
+##
+. $(dirname $0)/tools_common.sh
+
+example_tests=$(ls $(dirname $0)/*.sh)
+
+# List of script names to exclude.
+exclude_list="examples stress tools_common"
+
+# Filter out the scripts in $exclude_list.
+for word in ${exclude_list}; do
+ example_tests=$(filter_strings "${example_tests}" "${word}" exclude)
+done
+
+for test in ${example_tests}; do
+ # Source each test script so that exporting variables can be avoided.
+ VPX_TEST_NAME="$(basename ${test%.*})"
+ . "${test}"
+done
diff --git a/media/libvpx/libvpx/test/external_frame_buffer_test.cc b/media/libvpx/libvpx/test/external_frame_buffer_test.cc
new file mode 100644
index 0000000000..3bd4a1c473
--- /dev/null
+++ b/media/libvpx/libvpx/test/external_frame_buffer_test.cc
@@ -0,0 +1,519 @@
+/*
+ * 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 <memory>
+#include <string>
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+
+namespace {
+
+const int kVideoNameParam = 1;
+
+struct ExternalFrameBuffer {
+ uint8_t *data;
+ size_t size;
+ int in_use;
+};
+
+// Class to manipulate a list of external frame buffers.
+class ExternalFrameBufferList {
+ public:
+ ExternalFrameBufferList()
+ : num_buffers_(0), num_used_buffers_(0), ext_fb_list_(nullptr) {}
+
+ virtual ~ExternalFrameBufferList() {
+ for (int i = 0; i < num_buffers_; ++i) {
+ delete[] ext_fb_list_[i].data;
+ }
+ delete[] ext_fb_list_;
+ }
+
+ // Creates the list to hold the external buffers. Returns true on success.
+ bool CreateBufferList(int num_buffers) {
+ if (num_buffers < 0) return false;
+
+ num_buffers_ = num_buffers;
+ ext_fb_list_ = new ExternalFrameBuffer[num_buffers_];
+ EXPECT_NE(ext_fb_list_, nullptr);
+ memset(ext_fb_list_, 0, sizeof(ext_fb_list_[0]) * num_buffers_);
+ return true;
+ }
+
+ // Searches the frame buffer list for a free frame buffer. Makes sure
+ // that the frame buffer is at least |min_size| in bytes. Marks that the
+ // frame buffer is in use by libvpx. Finally sets |fb| to point to the
+ // external frame buffer. Returns < 0 on an error.
+ int GetFreeFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
+ EXPECT_NE(fb, nullptr);
+ const int idx = FindFreeBufferIndex();
+ if (idx == num_buffers_) return -1;
+
+ if (ext_fb_list_[idx].size < min_size) {
+ delete[] ext_fb_list_[idx].data;
+ ext_fb_list_[idx].data = new uint8_t[min_size];
+ memset(ext_fb_list_[idx].data, 0, min_size);
+ ext_fb_list_[idx].size = min_size;
+ }
+
+ SetFrameBuffer(idx, fb);
+
+ num_used_buffers_++;
+ return 0;
+ }
+
+ // Test function that will not allocate any data for the frame buffer.
+ // Returns < 0 on an error.
+ int GetZeroFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
+ EXPECT_NE(fb, nullptr);
+ const int idx = FindFreeBufferIndex();
+ if (idx == num_buffers_) return -1;
+
+ if (ext_fb_list_[idx].size < min_size) {
+ delete[] ext_fb_list_[idx].data;
+ ext_fb_list_[idx].data = nullptr;
+ ext_fb_list_[idx].size = min_size;
+ }
+
+ SetFrameBuffer(idx, fb);
+ return 0;
+ }
+
+ // Marks the external frame buffer that |fb| is pointing to as free.
+ // Returns < 0 on an error.
+ int ReturnFrameBuffer(vpx_codec_frame_buffer_t *fb) {
+ if (fb == nullptr) {
+ EXPECT_NE(fb, nullptr);
+ return -1;
+ }
+ ExternalFrameBuffer *const ext_fb =
+ reinterpret_cast<ExternalFrameBuffer *>(fb->priv);
+ if (ext_fb == nullptr) {
+ EXPECT_NE(ext_fb, nullptr);
+ return -1;
+ }
+ EXPECT_EQ(1, ext_fb->in_use);
+ ext_fb->in_use = 0;
+ num_used_buffers_--;
+ return 0;
+ }
+
+ // Checks that the vpx_image_t data is contained within the external frame
+ // buffer private data passed back in the vpx_image_t.
+ void CheckImageFrameBuffer(const vpx_image_t *img) {
+ if (img->fb_priv != nullptr) {
+ const struct ExternalFrameBuffer *const ext_fb =
+ reinterpret_cast<ExternalFrameBuffer *>(img->fb_priv);
+
+ ASSERT_TRUE(img->planes[0] >= ext_fb->data &&
+ img->planes[0] < (ext_fb->data + ext_fb->size));
+ }
+ }
+
+ int num_used_buffers() const { return num_used_buffers_; }
+
+ private:
+ // Returns the index of the first free frame buffer. Returns |num_buffers_|
+ // if there are no free frame buffers.
+ int FindFreeBufferIndex() {
+ int i;
+ // Find a free frame buffer.
+ for (i = 0; i < num_buffers_; ++i) {
+ if (!ext_fb_list_[i].in_use) break;
+ }
+ return i;
+ }
+
+ // Sets |fb| to an external frame buffer. idx is the index into the frame
+ // buffer list.
+ void SetFrameBuffer(int idx, vpx_codec_frame_buffer_t *fb) {
+ ASSERT_NE(fb, nullptr);
+ fb->data = ext_fb_list_[idx].data;
+ fb->size = ext_fb_list_[idx].size;
+ ASSERT_EQ(0, ext_fb_list_[idx].in_use);
+ ext_fb_list_[idx].in_use = 1;
+ fb->priv = &ext_fb_list_[idx];
+ }
+
+ int num_buffers_;
+ int num_used_buffers_;
+ ExternalFrameBuffer *ext_fb_list_;
+};
+
+#if CONFIG_WEBM_IO
+
+// Callback used by libvpx to request the application to return a frame
+// buffer of at least |min_size| in bytes.
+int get_vp9_frame_buffer(void *user_priv, size_t min_size,
+ vpx_codec_frame_buffer_t *fb) {
+ ExternalFrameBufferList *const fb_list =
+ reinterpret_cast<ExternalFrameBufferList *>(user_priv);
+ return fb_list->GetFreeFrameBuffer(min_size, fb);
+}
+
+// Callback used by libvpx to tell the application that |fb| is not needed
+// anymore.
+int release_vp9_frame_buffer(void *user_priv, vpx_codec_frame_buffer_t *fb) {
+ ExternalFrameBufferList *const fb_list =
+ reinterpret_cast<ExternalFrameBufferList *>(user_priv);
+ return fb_list->ReturnFrameBuffer(fb);
+}
+
+// Callback will not allocate data for frame buffer.
+int get_vp9_zero_frame_buffer(void *user_priv, size_t min_size,
+ vpx_codec_frame_buffer_t *fb) {
+ ExternalFrameBufferList *const fb_list =
+ reinterpret_cast<ExternalFrameBufferList *>(user_priv);
+ return fb_list->GetZeroFrameBuffer(min_size, fb);
+}
+
+// Callback will allocate one less byte than |min_size|.
+int get_vp9_one_less_byte_frame_buffer(void *user_priv, size_t min_size,
+ vpx_codec_frame_buffer_t *fb) {
+ ExternalFrameBufferList *const fb_list =
+ reinterpret_cast<ExternalFrameBufferList *>(user_priv);
+ return fb_list->GetFreeFrameBuffer(min_size - 1, fb);
+}
+
+// Callback will not release the external frame buffer.
+int do_not_release_vp9_frame_buffer(void *user_priv,
+ vpx_codec_frame_buffer_t *fb) {
+ (void)user_priv;
+ (void)fb;
+ return 0;
+}
+
+#endif // CONFIG_WEBM_IO
+
+// Class for testing passing in external frame buffers to libvpx.
+class ExternalFrameBufferMD5Test
+ : public ::libvpx_test::DecoderTest,
+ public ::libvpx_test::CodecTestWithParam<const char *> {
+ protected:
+ ExternalFrameBufferMD5Test()
+ : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
+ md5_file_(nullptr), num_buffers_(0) {}
+
+ virtual ~ExternalFrameBufferMD5Test() {
+ if (md5_file_ != nullptr) fclose(md5_file_);
+ }
+
+ virtual void PreDecodeFrameHook(
+ const libvpx_test::CompressedVideoSource &video,
+ libvpx_test::Decoder *decoder) {
+ if (num_buffers_ > 0 && video.frame_number() == 0) {
+ // Have libvpx use frame buffers we create.
+ ASSERT_TRUE(fb_list_.CreateBufferList(num_buffers_));
+ ASSERT_EQ(VPX_CODEC_OK,
+ decoder->SetFrameBufferFunctions(GetVP9FrameBuffer,
+ ReleaseVP9FrameBuffer, this));
+ }
+ }
+
+ void OpenMD5File(const std::string &md5_file_name_) {
+ md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+ ASSERT_NE(md5_file_, nullptr)
+ << "Md5 file open failed. Filename: " << md5_file_name_;
+ }
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ const unsigned int frame_number) {
+ ASSERT_NE(md5_file_, nullptr);
+ char expected_md5[33];
+ char junk[128];
+
+ // Read correct md5 checksums.
+ const int res = fscanf(md5_file_, "%s %s", expected_md5, junk);
+ ASSERT_NE(EOF, res) << "Read md5 data failed";
+ expected_md5[32] = '\0';
+
+ ::libvpx_test::MD5 md5_res;
+ md5_res.Add(&img);
+ const char *const actual_md5 = md5_res.Get();
+
+ // Check md5 match.
+ ASSERT_STREQ(expected_md5, actual_md5)
+ << "Md5 checksums don't match: frame number = " << frame_number;
+ }
+
+ // Callback to get a free external frame buffer. Return value < 0 is an
+ // error.
+ static int GetVP9FrameBuffer(void *user_priv, size_t min_size,
+ vpx_codec_frame_buffer_t *fb) {
+ ExternalFrameBufferMD5Test *const md5Test =
+ reinterpret_cast<ExternalFrameBufferMD5Test *>(user_priv);
+ return md5Test->fb_list_.GetFreeFrameBuffer(min_size, fb);
+ }
+
+ // Callback to release an external frame buffer. Return value < 0 is an
+ // error.
+ static int ReleaseVP9FrameBuffer(void *user_priv,
+ vpx_codec_frame_buffer_t *fb) {
+ ExternalFrameBufferMD5Test *const md5Test =
+ reinterpret_cast<ExternalFrameBufferMD5Test *>(user_priv);
+ return md5Test->fb_list_.ReturnFrameBuffer(fb);
+ }
+
+ void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; }
+ int num_buffers() const { return num_buffers_; }
+
+ private:
+ FILE *md5_file_;
+ int num_buffers_;
+ ExternalFrameBufferList fb_list_;
+};
+
+#if CONFIG_WEBM_IO
+const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
+const char kVP9NonRefTestFile[] = "vp90-2-22-svc_1280x720_1.webm";
+
+// Class for testing passing in external frame buffers to libvpx.
+class ExternalFrameBufferTest : public ::testing::Test {
+ protected:
+ ExternalFrameBufferTest()
+ : video_(nullptr), decoder_(nullptr), num_buffers_(0) {}
+
+ virtual void SetUp() {
+ video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
+ ASSERT_NE(video_, nullptr);
+ video_->Init();
+ video_->Begin();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+ ASSERT_NE(decoder_, nullptr);
+ }
+
+ virtual void TearDown() {
+ delete decoder_;
+ decoder_ = nullptr;
+ delete video_;
+ video_ = nullptr;
+ }
+
+ // Passes the external frame buffer information to libvpx.
+ vpx_codec_err_t SetFrameBufferFunctions(
+ int num_buffers, vpx_get_frame_buffer_cb_fn_t cb_get,
+ vpx_release_frame_buffer_cb_fn_t cb_release) {
+ if (num_buffers > 0) {
+ num_buffers_ = num_buffers;
+ EXPECT_TRUE(fb_list_.CreateBufferList(num_buffers_));
+ }
+
+ return decoder_->SetFrameBufferFunctions(cb_get, cb_release, &fb_list_);
+ }
+
+ vpx_codec_err_t DecodeOneFrame() {
+ const vpx_codec_err_t res =
+ decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+ CheckDecodedFrames();
+ if (res == VPX_CODEC_OK) video_->Next();
+ return res;
+ }
+
+ vpx_codec_err_t DecodeRemainingFrames() {
+ for (; video_->cxdata() != nullptr; video_->Next()) {
+ const vpx_codec_err_t res =
+ decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+ if (res != VPX_CODEC_OK) return res;
+ CheckDecodedFrames();
+ }
+ return VPX_CODEC_OK;
+ }
+
+ void CheckDecodedFrames() {
+ libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
+ const vpx_image_t *img = nullptr;
+
+ // Get decompressed data
+ while ((img = dec_iter.Next()) != nullptr) {
+ fb_list_.CheckImageFrameBuffer(img);
+ }
+ }
+
+ libvpx_test::WebMVideoSource *video_;
+ libvpx_test::VP9Decoder *decoder_;
+ int num_buffers_;
+ ExternalFrameBufferList fb_list_;
+};
+
+class ExternalFrameBufferNonRefTest : public ExternalFrameBufferTest {
+ protected:
+ virtual void SetUp() {
+ video_ = new libvpx_test::WebMVideoSource(kVP9NonRefTestFile);
+ ASSERT_NE(video_, nullptr);
+ video_->Init();
+ video_->Begin();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+ ASSERT_NE(decoder_, nullptr);
+ }
+
+ virtual void CheckFrameBufferRelease() {
+ TearDown();
+ ASSERT_EQ(0, fb_list_.num_used_buffers());
+ }
+};
+#endif // CONFIG_WEBM_IO
+
+// This test runs through the set of test vectors, and decodes them.
+// Libvpx will call into the application to allocate a frame buffer when
+// needed. The md5 checksums are computed for each frame in the video file.
+// If md5 checksums match the correct md5 data, then the test is passed.
+// Otherwise, the test failed.
+TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
+ const std::string filename = GET_PARAM(kVideoNameParam);
+
+ // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+ // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
+ const int jitter_buffers = 4;
+ const int num_buffers =
+ VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+ set_num_buffers(num_buffers);
+
+#if CONFIG_VP8_DECODER
+ // Tell compiler we are not using kVP8TestVectors.
+ (void)libvpx_test::kVP8TestVectors;
+#endif
+
+ // Open compressed video file.
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ if (filename.substr(filename.length() - 3, 3) == "ivf") {
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ } else {
+#if CONFIG_WEBM_IO
+ video.reset(new libvpx_test::WebMVideoSource(filename));
+#else
+ fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+ filename.c_str());
+ return;
+#endif
+ }
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+
+ // Construct md5 file name.
+ const std::string md5_filename = filename + ".md5";
+ OpenMD5File(md5_filename);
+
+ // Decode frame, and check the md5 matching.
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+#if CONFIG_WEBM_IO
+TEST_F(ExternalFrameBufferTest, MinFrameBuffers) {
+ // Minimum number of external frame buffers for VP9 is
+ // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS.
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(VPX_CODEC_OK,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+ release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, EightJitterBuffers) {
+ // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+ // #VPX_MAXIMUM_WORK_BUFFERS + eight jitter buffers.
+ const int jitter_buffers = 8;
+ const int num_buffers =
+ VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+ ASSERT_EQ(VPX_CODEC_OK,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+ release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NotEnoughBuffers) {
+ // Minimum number of external frame buffers for VP9 is
+ // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. Most files will
+ // only use 5 frame buffers at one time.
+ const int num_buffers = 2;
+ ASSERT_EQ(VPX_CODEC_OK,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+ release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
+ // Only run this on long clips. Decoding a very short clip will return
+ // VPX_CODEC_OK even with only 2 buffers.
+ ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NoRelease) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(VPX_CODEC_OK,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+ do_not_release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
+ ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NullRealloc) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(VPX_CODEC_OK,
+ SetFrameBufferFunctions(num_buffers, get_vp9_zero_frame_buffer,
+ release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
+}
+
+TEST_F(ExternalFrameBufferTest, ReallocOneLessByte) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(VPX_CODEC_OK, SetFrameBufferFunctions(
+ num_buffers, get_vp9_one_less_byte_frame_buffer,
+ release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
+}
+
+TEST_F(ExternalFrameBufferTest, NullGetFunction) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(
+ VPX_CODEC_INVALID_PARAM,
+ SetFrameBufferFunctions(num_buffers, nullptr, release_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferTest, NullReleaseFunction) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(
+ VPX_CODEC_INVALID_PARAM,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer, nullptr));
+}
+
+TEST_F(ExternalFrameBufferTest, SetAfterDecode) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
+ ASSERT_EQ(VPX_CODEC_ERROR,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+ release_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferNonRefTest, ReleaseNonRefFrameBuffer) {
+ const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+ ASSERT_EQ(VPX_CODEC_OK,
+ SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+ release_vp9_frame_buffer));
+ ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+ CheckFrameBufferRelease();
+}
+#endif // CONFIG_WEBM_IO
+
+VP9_INSTANTIATE_TEST_SUITE(
+ ExternalFrameBufferMD5Test,
+ ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
+ libvpx_test::kVP9TestVectors +
+ libvpx_test::kNumVP9TestVectors));
+} // namespace
diff --git a/media/libvpx/libvpx/test/fdct8x8_test.cc b/media/libvpx/libvpx/test/fdct8x8_test.cc
new file mode 100644
index 0000000000..fcc84690a0
--- /dev/null
+++ b/media/libvpx/libvpx/test/fdct8x8_test.cc
@@ -0,0 +1,778 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+const int kNumCoeffs = 64;
+const double kPi = 3.141592653589793238462643383279502884;
+
+const int kSignBiasMaxDiff255 = 1500;
+const int kSignBiasMaxDiff15 = 10000;
+
+typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
+ int tx_type);
+typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
+ int tx_type);
+
+typedef std::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param;
+typedef std::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param;
+typedef std::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param;
+
+void reference_8x8_dct_1d(const double in[8], double out[8]) {
+ const double kInvSqrt2 = 0.707106781186547524400844362104;
+ for (int k = 0; k < 8; k++) {
+ out[k] = 0.0;
+ for (int n = 0; n < 8; n++) {
+ out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 16.0);
+ }
+ if (k == 0) out[k] = out[k] * kInvSqrt2;
+ }
+}
+
+void reference_8x8_dct_2d(const int16_t input[kNumCoeffs],
+ double output[kNumCoeffs]) {
+ // First transform columns
+ for (int i = 0; i < 8; ++i) {
+ double temp_in[8], temp_out[8];
+ for (int j = 0; j < 8; ++j) temp_in[j] = input[j * 8 + i];
+ reference_8x8_dct_1d(temp_in, temp_out);
+ for (int j = 0; j < 8; ++j) output[j * 8 + i] = temp_out[j];
+ }
+ // Then transform rows
+ for (int i = 0; i < 8; ++i) {
+ double temp_in[8], temp_out[8];
+ for (int j = 0; j < 8; ++j) temp_in[j] = output[j + i * 8];
+ reference_8x8_dct_1d(temp_in, temp_out);
+ // Scale by some magic number
+ for (int j = 0; j < 8; ++j) output[j + i * 8] = temp_out[j] * 2;
+ }
+}
+
+void fdct8x8_ref(const int16_t *in, tran_low_t *out, int stride,
+ int /*tx_type*/) {
+ vpx_fdct8x8_c(in, out, stride);
+}
+
+void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
+ vp9_fht8x8_c(in, out, stride, tx_type);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct8x8_10(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct8x8_12(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+
+void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+ vp9_highbd_iht8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 10);
+}
+
+void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+ vp9_highbd_iht8x8_64_add_c(in, CAST_TO_SHORTPTR(out), stride, tx_type, 12);
+}
+
+#if HAVE_SSE2
+
+void idct8x8_12_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_12_add_c(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct8x8_12_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_12_add_c(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+
+void idct8x8_12_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_12_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct8x8_12_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_12_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+
+void idct8x8_64_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_64_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 10);
+}
+
+void idct8x8_64_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+ vpx_highbd_idct8x8_64_add_sse2(in, CAST_TO_SHORTPTR(out), stride, 12);
+}
+#endif // HAVE_SSE2
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+class FwdTrans8x8TestBase {
+ public:
+ virtual ~FwdTrans8x8TestBase() {}
+
+ protected:
+ virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0;
+ virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0;
+
+ void RunSignBiasCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
+ DECLARE_ALIGNED(16, tran_low_t, test_output_block[64]);
+ int count_sign_block[64][2];
+ const int count_test_block = 100000;
+
+ memset(count_sign_block, 0, sizeof(count_sign_block));
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-255, 255].
+ for (int j = 0; j < 64; ++j) {
+ test_input_block[j] = ((rnd.Rand16() >> (16 - bit_depth_)) & mask_) -
+ ((rnd.Rand16() >> (16 - bit_depth_)) & mask_);
+ }
+ ASM_REGISTER_STATE_CHECK(
+ RunFwdTxfm(test_input_block, test_output_block, pitch_));
+
+ for (int j = 0; j < 64; ++j) {
+ if (test_output_block[j] < 0) {
+ ++count_sign_block[j][0];
+ } else if (test_output_block[j] > 0) {
+ ++count_sign_block[j][1];
+ }
+ }
+ }
+
+ for (int j = 0; j < 64; ++j) {
+ const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
+ const int max_diff = kSignBiasMaxDiff255;
+ ASSERT_LT(diff, max_diff << (bit_depth_ - 8))
+ << "Error: 8x8 FDCT/FHT has a sign bias > "
+ << 1. * max_diff / count_test_block * 100 << "%"
+ << " for input range [-255, 255] at index " << j
+ << " count0: " << count_sign_block[j][0]
+ << " count1: " << count_sign_block[j][1] << " diff: " << diff;
+ }
+
+ memset(count_sign_block, 0, sizeof(count_sign_block));
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_ / 16, mask_ / 16].
+ for (int j = 0; j < 64; ++j) {
+ test_input_block[j] =
+ ((rnd.Rand16() & mask_) >> 4) - ((rnd.Rand16() & mask_) >> 4);
+ }
+ ASM_REGISTER_STATE_CHECK(
+ RunFwdTxfm(test_input_block, test_output_block, pitch_));
+
+ for (int j = 0; j < 64; ++j) {
+ if (test_output_block[j] < 0) {
+ ++count_sign_block[j][0];
+ } else if (test_output_block[j] > 0) {
+ ++count_sign_block[j][1];
+ }
+ }
+ }
+
+ for (int j = 0; j < 64; ++j) {
+ const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
+ const int max_diff = kSignBiasMaxDiff15;
+ ASSERT_LT(diff, max_diff << (bit_depth_ - 8))
+ << "Error: 8x8 FDCT/FHT has a sign bias > "
+ << 1. * max_diff / count_test_block * 100 << "%"
+ << " for input range [-15, 15] at index " << j
+ << " count0: " << count_sign_block[j][0]
+ << " count1: " << count_sign_block[j][1] << " diff: " << diff;
+ }
+ }
+
+ void RunRoundTripErrorCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ int max_error = 0;
+ int total_error = 0;
+ const int count_test_block = 100000;
+ DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
+ DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]);
+ DECLARE_ALIGNED(16, uint8_t, dst[64]);
+ DECLARE_ALIGNED(16, uint8_t, src[64]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[64]);
+ DECLARE_ALIGNED(16, uint16_t, src16[64]);
+#endif
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < 64; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ src[j] = rnd.Rand8();
+ dst[j] = rnd.Rand8();
+ test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src16[j] = rnd.Rand16() & mask_;
+ dst16[j] = rnd.Rand16() & mask_;
+ test_input_block[j] = src16[j] - dst16[j];
+#endif
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(
+ RunFwdTxfm(test_input_block, test_temp_block, pitch_));
+ for (int j = 0; j < 64; ++j) {
+ if (test_temp_block[j] > 0) {
+ test_temp_block[j] += 2;
+ test_temp_block[j] /= 4;
+ test_temp_block[j] *= 4;
+ } else {
+ test_temp_block[j] -= 2;
+ test_temp_block[j] /= 4;
+ test_temp_block[j] *= 4;
+ }
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif
+ }
+
+ for (int j = 0; j < 64; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const int diff = dst[j] - src[j];
+#endif
+ const int error = diff * diff;
+ if (max_error < error) max_error = error;
+ total_error += error;
+ }
+ }
+
+ ASSERT_GE(1 << 2 * (bit_depth_ - 8), max_error)
+ << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
+ << " roundtrip error > 1";
+
+ ASSERT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
+ << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
+ << "error > 1/5 per block";
+ }
+
+ void RunExtremalCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ int max_error = 0;
+ int total_error = 0;
+ int total_coeff_error = 0;
+ const int count_test_block = 100000;
+ DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
+ DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]);
+ DECLARE_ALIGNED(16, tran_low_t, ref_temp_block[64]);
+ DECLARE_ALIGNED(16, uint8_t, dst[64]);
+ DECLARE_ALIGNED(16, uint8_t, src[64]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[64]);
+ DECLARE_ALIGNED(16, uint16_t, src16[64]);
+#endif
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < 64; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ if (i == 0) {
+ src[j] = 255;
+ dst[j] = 0;
+ } else if (i == 1) {
+ src[j] = 0;
+ dst[j] = 255;
+ } else {
+ src[j] = rnd.Rand8() % 2 ? 255 : 0;
+ dst[j] = rnd.Rand8() % 2 ? 255 : 0;
+ }
+ test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ if (i == 0) {
+ src16[j] = mask_;
+ dst16[j] = 0;
+ } else if (i == 1) {
+ src16[j] = 0;
+ dst16[j] = mask_;
+ } else {
+ src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
+ dst16[j] = rnd.Rand8() % 2 ? mask_ : 0;
+ }
+ test_input_block[j] = src16[j] - dst16[j];
+#endif
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(
+ RunFwdTxfm(test_input_block, test_temp_block, pitch_));
+ ASM_REGISTER_STATE_CHECK(
+ fwd_txfm_ref(test_input_block, ref_temp_block, pitch_, tx_type_));
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(test_temp_block, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif
+ }
+
+ for (int j = 0; j < 64; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const int diff = dst[j] - src[j];
+#endif
+ const int error = diff * diff;
+ if (max_error < error) max_error = error;
+ total_error += error;
+
+ const int coeff_diff = test_temp_block[j] - ref_temp_block[j];
+ total_coeff_error += abs(coeff_diff);
+ }
+
+ ASSERT_GE(1 << 2 * (bit_depth_ - 8), max_error)
+ << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
+ << " an individual roundtrip error > 1";
+
+ ASSERT_GE((count_test_block << 2 * (bit_depth_ - 8)) / 5, total_error)
+ << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
+ << " roundtrip error > 1/5 per block";
+
+ ASSERT_EQ(0, total_coeff_error)
+ << "Error: Extremal 8x8 FDCT/FHT has"
+ << " overflow issues in the intermediate steps > 1";
+ }
+ }
+
+ void RunInvAccuracyCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+#endif
+
+ for (int i = 0; i < count_test_block; ++i) {
+ double out_r[kNumCoeffs];
+
+ // Initialize a test block with input range [-255, 255].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (bit_depth_ == VPX_BITS_8) {
+ src[j] = rnd.Rand8() % 2 ? 255 : 0;
+ dst[j] = src[j] > 0 ? 0 : 255;
+ in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
+ dst16[j] = src16[j] > 0 ? 0 : mask_;
+ in[j] = src16[j] - dst16[j];
+#endif
+ }
+ }
+
+ reference_8x8_dct_2d(in, out_r);
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
+ }
+
+ if (bit_depth_ == VPX_BITS_8) {
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+ const int diff = dst[j] - src[j];
+#endif
+ const uint32_t error = diff * diff;
+ ASSERT_GE(1u << 2 * (bit_depth_ - 8), error)
+ << "Error: 8x8 IDCT has error " << error << " at index " << j;
+ }
+ }
+ }
+
+ void RunFwdAccuracyCheck() {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 1000;
+ DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, coeff_r[kNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ double out_r[kNumCoeffs];
+
+ // Initialize a test block with input range [-mask_, mask_].
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ in[j] = rnd.Rand8() % 2 == 0 ? mask_ : -mask_;
+ }
+
+ RunFwdTxfm(in, coeff, pitch_);
+ reference_8x8_dct_2d(in, out_r);
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ coeff_r[j] = static_cast<tran_low_t>(round(out_r[j]));
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ const int32_t diff = coeff[j] - coeff_r[j];
+ const uint32_t error = diff * diff;
+ ASSERT_GE(9u << 2 * (bit_depth_ - 8), error)
+ << "Error: 8x8 DCT has error " << error << " at index " << j;
+ }
+ }
+ }
+
+ void CompareInvReference(IdctFunc ref_txfm, int thresh) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ const int eob = 12;
+ DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+ DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif
+ const int16_t *scan = vp9_default_scan_orders[TX_8X8].scan;
+
+ for (int i = 0; i < count_test_block; ++i) {
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ if (j < eob) {
+ // Random values less than the threshold, either positive or negative
+ coeff[scan[j]] = rnd(thresh) * (1 - 2 * (i % 2));
+ } else {
+ coeff[scan[j]] = 0;
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ dst[j] = 0;
+ ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ dst16[j] = 0;
+ ref16[j] = 0;
+#endif
+ }
+ }
+ if (bit_depth_ == VPX_BITS_8) {
+ ref_txfm(coeff, ref, pitch_);
+ ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ ref_txfm(coeff, CAST_TO_BYTEPTR(ref16), pitch_);
+ ASM_REGISTER_STATE_CHECK(
+ RunInvTxfm(coeff, CAST_TO_BYTEPTR(dst16), pitch_));
+#endif
+ }
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+ const int diff =
+ bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
+#else
+ const int diff = dst[j] - ref[j];
+#endif
+ const uint32_t error = diff * diff;
+ ASSERT_EQ(0u, error)
+ << "Error: 8x8 IDCT has error " << error << " at index " << j;
+ }
+ }
+ }
+ int pitch_;
+ int tx_type_;
+ FhtFunc fwd_txfm_ref;
+ vpx_bit_depth_t bit_depth_;
+ int mask_;
+};
+
+class FwdTrans8x8DCT : public FwdTrans8x8TestBase,
+ public ::testing::TestWithParam<Dct8x8Param> {
+ public:
+ virtual ~FwdTrans8x8DCT() {}
+
+ virtual void SetUp() {
+ fwd_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ tx_type_ = GET_PARAM(2);
+ pitch_ = 8;
+ fwd_txfm_ref = fdct8x8_ref;
+ bit_depth_ = GET_PARAM(3);
+ mask_ = (1 << bit_depth_) - 1;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+ fwd_txfm_(in, out, stride);
+ }
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride);
+ }
+
+ FdctFunc fwd_txfm_;
+ IdctFunc inv_txfm_;
+};
+
+TEST_P(FwdTrans8x8DCT, SignBiasCheck) { RunSignBiasCheck(); }
+
+TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) { RunRoundTripErrorCheck(); }
+
+TEST_P(FwdTrans8x8DCT, ExtremalCheck) { RunExtremalCheck(); }
+
+TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) { RunFwdAccuracyCheck(); }
+
+TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) { RunInvAccuracyCheck(); }
+
+class FwdTrans8x8HT : public FwdTrans8x8TestBase,
+ public ::testing::TestWithParam<Ht8x8Param> {
+ public:
+ virtual ~FwdTrans8x8HT() {}
+
+ virtual void SetUp() {
+ fwd_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ tx_type_ = GET_PARAM(2);
+ pitch_ = 8;
+ fwd_txfm_ref = fht8x8_ref;
+ bit_depth_ = GET_PARAM(3);
+ mask_ = (1 << bit_depth_) - 1;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+ fwd_txfm_(in, out, stride, tx_type_);
+ }
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride, tx_type_);
+ }
+
+ FhtFunc fwd_txfm_;
+ IhtFunc inv_txfm_;
+};
+
+TEST_P(FwdTrans8x8HT, SignBiasCheck) { RunSignBiasCheck(); }
+
+TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) { RunRoundTripErrorCheck(); }
+
+TEST_P(FwdTrans8x8HT, ExtremalCheck) { RunExtremalCheck(); }
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+class InvTrans8x8DCT : public FwdTrans8x8TestBase,
+ public ::testing::TestWithParam<Idct8x8Param> {
+ public:
+ virtual ~InvTrans8x8DCT() {}
+
+ virtual void SetUp() {
+ ref_txfm_ = GET_PARAM(0);
+ inv_txfm_ = GET_PARAM(1);
+ thresh_ = GET_PARAM(2);
+ pitch_ = 8;
+ bit_depth_ = GET_PARAM(3);
+ mask_ = (1 << bit_depth_) - 1;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+ inv_txfm_(out, dst, stride);
+ }
+ void RunFwdTxfm(int16_t * /*out*/, tran_low_t * /*dst*/, int /*stride*/) {}
+
+ IdctFunc ref_txfm_;
+ IdctFunc inv_txfm_;
+ int thresh_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InvTrans8x8DCT);
+
+TEST_P(InvTrans8x8DCT, CompareReference) {
+ CompareInvReference(ref_txfm_, thresh_);
+}
+#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+using std::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, FwdTrans8x8DCT,
+ ::testing::Values(
+ make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8),
+ make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_10, 0, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_12, 0, VPX_BITS_12)));
+#else
+INSTANTIATE_TEST_SUITE_P(C, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_c,
+ &vpx_idct8x8_64_add_c, 0,
+ VPX_BITS_8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ C, FwdTrans8x8HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 0, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 1, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 2, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 3, VPX_BITS_10),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 0, VPX_BITS_12),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 1, VPX_BITS_12),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 2, VPX_BITS_12),
+ make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 3, VPX_BITS_12),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ C, FwdTrans8x8HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(NEON, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_neon,
+ &vpx_idct8x8_64_add_neon,
+ 0, VPX_BITS_8)));
+
+#if !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ NEON, FwdTrans8x8HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 3, VPX_BITS_8)));
+#endif // !CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_NEON && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(SSE2, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_sse2,
+ &vpx_idct8x8_64_add_sse2,
+ 0, VPX_BITS_8)));
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, FwdTrans8x8HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 3, VPX_BITS_8)));
+#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_c, 0,
+ VPX_BITS_8),
+ make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_64_add_10_sse2,
+ 12, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct8x8_sse2,
+ &idct8x8_64_add_10_sse2, 12, VPX_BITS_10),
+ make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_64_add_12_sse2,
+ 12, VPX_BITS_12),
+ make_tuple(&vpx_highbd_fdct8x8_sse2,
+ &idct8x8_64_add_12_sse2, 12, VPX_BITS_12)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, FwdTrans8x8HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
+
+// Optimizations take effect at a threshold of 6201, so we use a value close to
+// that to test both branches.
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, InvTrans8x8DCT,
+ ::testing::Values(
+ make_tuple(&idct8x8_12_add_10_c, &idct8x8_12_add_10_sse2, 6225,
+ VPX_BITS_10),
+ make_tuple(&idct8x8_10, &idct8x8_64_add_10_sse2, 6225, VPX_BITS_10),
+ make_tuple(&idct8x8_12_add_12_c, &idct8x8_12_add_12_sse2, 6225,
+ VPX_BITS_12),
+ make_tuple(&idct8x8_12, &idct8x8_64_add_12_sse2, 6225, VPX_BITS_12)));
+#endif // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSSE3 && VPX_ARCH_X86_64 && !CONFIG_VP9_HIGHBITDEPTH && \
+ !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(SSSE3, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_ssse3,
+ &vpx_idct8x8_64_add_sse2,
+ 0, VPX_BITS_8)));
+#endif
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(MSA, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_msa,
+ &vpx_idct8x8_64_add_msa,
+ 0, VPX_BITS_8)));
+INSTANTIATE_TEST_SUITE_P(
+ MSA, FwdTrans8x8HT,
+ ::testing::Values(
+ make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 0, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 1, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 2, VPX_BITS_8),
+ make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 3, VPX_BITS_8)));
+#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(VSX, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_c,
+ &vpx_idct8x8_64_add_vsx,
+ 0, VPX_BITS_8)));
+#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_SUITE_P(LSX, FwdTrans8x8DCT,
+ ::testing::Values(make_tuple(&vpx_fdct8x8_lsx,
+ &vpx_idct8x8_64_add_c, 0,
+ VPX_BITS_8)));
+#endif // HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+} // namespace
diff --git a/media/libvpx/libvpx/test/frame_size_tests.cc b/media/libvpx/libvpx/test/frame_size_tests.cc
new file mode 100644
index 0000000000..8a0eb71ba0
--- /dev/null
+++ b/media/libvpx/libvpx/test/frame_size_tests.cc
@@ -0,0 +1,216 @@
+/*
+ * 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 <memory>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/register_state_check.h"
+#include "test/video_source.h"
+
+namespace {
+
+class EncoderWithExpectedError : public ::libvpx_test::Encoder {
+ public:
+ EncoderWithExpectedError(vpx_codec_enc_cfg_t cfg,
+ unsigned long deadline, // NOLINT
+ const unsigned long init_flags, // NOLINT
+ ::libvpx_test::TwopassStatsStore *stats)
+ : ::libvpx_test::Encoder(cfg, deadline, init_flags, stats) {}
+ // This overrides with expected error code.
+ void EncodeFrame(::libvpx_test::VideoSource *video,
+ const unsigned long frame_flags, // NOLINT
+ const vpx_codec_err_t expected_err) {
+ if (video->img()) {
+ EncodeFrameInternal(*video, frame_flags, expected_err);
+ } else {
+ Flush();
+ }
+
+ // Handle twopass stats
+ ::libvpx_test::CxDataIterator iter = GetCxData();
+
+ while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+ if (pkt->kind != VPX_CODEC_STATS_PKT) continue;
+
+ stats_->Append(*pkt);
+ }
+ }
+
+ protected:
+ void EncodeFrameInternal(const ::libvpx_test::VideoSource &video,
+ const unsigned long frame_flags, // NOLINT
+ const vpx_codec_err_t expected_err) {
+ vpx_codec_err_t res;
+ const vpx_image_t *img = video.img();
+
+ // 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(res, VPX_CODEC_OK) << EncoderError();
+ }
+
+ // Encode the frame
+ API_REGISTER_STATE_CHECK(res = vpx_codec_encode(&encoder_, img, video.pts(),
+ video.duration(),
+ frame_flags, deadline_));
+ ASSERT_EQ(expected_err, res) << EncoderError();
+ }
+
+ virtual vpx_codec_iface_t *CodecInterface() const {
+#if CONFIG_VP9_ENCODER
+ return &vpx_codec_vp9_cx_algo;
+#else
+ return nullptr;
+#endif
+ }
+};
+
+class VP9FrameSizeTestsLarge : public ::libvpx_test::EncoderTest,
+ public ::testing::Test {
+ protected:
+ VP9FrameSizeTestsLarge()
+ : EncoderTest(&::libvpx_test::kVP9), expected_res_(VPX_CODEC_OK) {}
+ virtual ~VP9FrameSizeTestsLarge() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+ const libvpx_test::VideoSource & /*video*/,
+ libvpx_test::Decoder *decoder) {
+ EXPECT_EQ(expected_res_, res_dec) << decoder->DecodeError();
+ return !::testing::Test::HasFailure();
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, 7);
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+
+ using ::libvpx_test::EncoderTest::RunLoop;
+ virtual void RunLoop(::libvpx_test::VideoSource *video,
+ const vpx_codec_err_t expected_err) {
+ stats_.Reset();
+
+ ASSERT_TRUE(passes_ == 1 || passes_ == 2);
+ for (unsigned int pass = 0; pass < passes_; pass++) {
+ vpx_codec_pts_t last_pts = 0;
+
+ 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);
+ std::unique_ptr<EncoderWithExpectedError> encoder(
+ new EncoderWithExpectedError(cfg_, deadline_, init_flags_, &stats_));
+ ASSERT_NE(encoder.get(), nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(video->Begin());
+ encoder->InitEncoder(video);
+ ASSERT_FALSE(::testing::Test::HasFatalFailure());
+ for (bool again = true; again; video->Next()) {
+ again = (video->img() != nullptr);
+
+ PreEncodeFrameHook(video, encoder.get());
+ encoder->EncodeFrame(video, frame_flags_, expected_err);
+
+ PostEncodeFrameHook(encoder.get());
+
+ ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
+
+ while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+ pkt = MutateEncoderOutputHook(pkt);
+ again = true;
+ switch (pkt->kind) {
+ case VPX_CODEC_CX_FRAME_PKT:
+ ASSERT_GE(pkt->data.frame.pts, last_pts);
+ last_pts = pkt->data.frame.pts;
+ FramePktHook(pkt);
+ break;
+
+ case VPX_CODEC_PSNR_PKT: PSNRPktHook(pkt); break;
+ case VPX_CODEC_STATS_PKT: StatsPktHook(pkt); break;
+ default: break;
+ }
+ }
+
+ if (!Continue()) break;
+ }
+
+ EndPassHook();
+
+ if (!Continue()) break;
+ }
+ }
+
+ vpx_codec_err_t expected_res_;
+};
+
+TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) {
+ ::libvpx_test::RandomVideoSource video;
+
+#if CONFIG_SIZE_LIMIT
+ video.SetSize(DECODE_WIDTH_LIMIT + 16, DECODE_HEIGHT_LIMIT + 16);
+ video.set_limit(2);
+ expected_res_ = VPX_CODEC_MEM_ERROR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video, expected_res_));
+#endif
+}
+
+TEST_F(VP9FrameSizeTestsLarge, ValidSizes) {
+ ::libvpx_test::RandomVideoSource video;
+
+#if CONFIG_SIZE_LIMIT
+ video.SetSize(DECODE_WIDTH_LIMIT, DECODE_HEIGHT_LIMIT);
+ video.set_limit(2);
+ expected_res_ = VPX_CODEC_OK;
+ ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
+#else
+// This test produces a pretty large single frame allocation, (roughly
+// 25 megabits). The encoder allocates a good number of these frames
+// one for each lag in frames (for 2 pass), and then one for each possible
+// reference buffer (8) - we can end up with up to 30 buffers of roughly this
+// size or almost 1 gig of memory.
+// In total the allocations will exceed 2GiB which may cause a failure with
+// mingw + wine, use a smaller size in that case.
+#if defined(_WIN32) && !defined(_WIN64) || defined(__OS2__)
+ video.SetSize(4096, 3072);
+#else
+ video.SetSize(4096, 4096);
+#endif
+ video.set_limit(2);
+ expected_res_ = VPX_CODEC_OK;
+ ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
+#endif
+}
+
+TEST_F(VP9FrameSizeTestsLarge, OneByOneVideo) {
+ ::libvpx_test::RandomVideoSource video;
+
+ video.SetSize(1, 1);
+ video.set_limit(2);
+ expected_res_ = VPX_CODEC_OK;
+ ASSERT_NO_FATAL_FAILURE(::libvpx_test::EncoderTest::RunLoop(&video));
+}
+} // namespace
diff --git a/media/libvpx/libvpx/test/hadamard_test.cc b/media/libvpx/libvpx/test/hadamard_test.cc
new file mode 100644
index 0000000000..9f6c99f3c4
--- /dev/null
+++ b/media/libvpx/libvpx/test/hadamard_test.cc
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2016 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 <algorithm>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "vpx_ports/vpx_timer.h"
+
+#include "test/acm_random.h"
+#include "test/register_state_check.h"
+
+namespace {
+
+using ::libvpx_test::ACMRandom;
+
+typedef void (*HadamardFunc)(const int16_t *a, ptrdiff_t a_stride,
+ tran_low_t *b);
+
+void hadamard_loop(const tran_low_t *a, tran_low_t *out) {
+ tran_low_t b[8];
+ for (int i = 0; i < 8; i += 2) {
+ b[i + 0] = a[i * 8] + a[(i + 1) * 8];
+ b[i + 1] = a[i * 8] - a[(i + 1) * 8];
+ }
+ tran_low_t c[8];
+ for (int i = 0; i < 8; i += 4) {
+ c[i + 0] = b[i + 0] + b[i + 2];
+ c[i + 1] = b[i + 1] + b[i + 3];
+ c[i + 2] = b[i + 0] - b[i + 2];
+ c[i + 3] = b[i + 1] - b[i + 3];
+ }
+ out[0] = c[0] + c[4];
+ out[7] = c[1] + c[5];
+ out[3] = c[2] + c[6];
+ out[4] = c[3] + c[7];
+ out[2] = c[0] - c[4];
+ out[6] = c[1] - c[5];
+ out[1] = c[2] - c[6];
+ out[5] = c[3] - c[7];
+}
+
+void reference_hadamard8x8(const int16_t *a, int a_stride, tran_low_t *b) {
+ tran_low_t input[64];
+ tran_low_t buf[64];
+ for (int i = 0; i < 8; ++i) {
+ for (int j = 0; j < 8; ++j) {
+ input[i * 8 + j] = static_cast<tran_low_t>(a[i * a_stride + j]);
+ }
+ }
+ for (int i = 0; i < 8; ++i) hadamard_loop(input + i, buf + i * 8);
+ for (int i = 0; i < 8; ++i) hadamard_loop(buf + i, b + i * 8);
+}
+
+void reference_hadamard16x16(const int16_t *a, int a_stride, tran_low_t *b) {
+ /* The source is a 16x16 block. The destination is rearranged to 8x32.
+ * Input is 9 bit. */
+ reference_hadamard8x8(a + 0 + 0 * a_stride, a_stride, b + 0);
+ reference_hadamard8x8(a + 8 + 0 * a_stride, a_stride, b + 64);
+ reference_hadamard8x8(a + 0 + 8 * a_stride, a_stride, b + 128);
+ reference_hadamard8x8(a + 8 + 8 * a_stride, a_stride, b + 192);
+
+ /* Overlay the 8x8 blocks and combine. */
+ for (int i = 0; i < 64; ++i) {
+ /* 8x8 steps the range up to 15 bits. */
+ const tran_low_t a0 = b[0];
+ const tran_low_t a1 = b[64];
+ const tran_low_t a2 = b[128];
+ const tran_low_t a3 = b[192];
+
+ /* Prevent the result from escaping int16_t. */
+ const tran_low_t b0 = (a0 + a1) >> 1;
+ const tran_low_t b1 = (a0 - a1) >> 1;
+ const tran_low_t b2 = (a2 + a3) >> 1;
+ const tran_low_t b3 = (a2 - a3) >> 1;
+
+ /* Store a 16 bit value. */
+ b[0] = b0 + b2;
+ b[64] = b1 + b3;
+ b[128] = b0 - b2;
+ b[192] = b1 - b3;
+
+ ++b;
+ }
+}
+
+void reference_hadamard32x32(const int16_t *a, int a_stride, tran_low_t *b) {
+ reference_hadamard16x16(a + 0 + 0 * a_stride, a_stride, b + 0);
+ reference_hadamard16x16(a + 16 + 0 * a_stride, a_stride, b + 256);
+ reference_hadamard16x16(a + 0 + 16 * a_stride, a_stride, b + 512);
+ reference_hadamard16x16(a + 16 + 16 * a_stride, a_stride, b + 768);
+
+ for (int i = 0; i < 256; ++i) {
+ const tran_low_t a0 = b[0];
+ const tran_low_t a1 = b[256];
+ const tran_low_t a2 = b[512];
+ const tran_low_t a3 = b[768];
+
+ const tran_low_t b0 = (a0 + a1) >> 2;
+ const tran_low_t b1 = (a0 - a1) >> 2;
+ const tran_low_t b2 = (a2 + a3) >> 2;
+ const tran_low_t b3 = (a2 - a3) >> 2;
+
+ b[0] = b0 + b2;
+ b[256] = b1 + b3;
+ b[512] = b0 - b2;
+ b[768] = b1 - b3;
+
+ ++b;
+ }
+}
+
+struct HadamardFuncWithSize {
+ HadamardFuncWithSize(HadamardFunc f, int s) : func(f), block_size(s) {}
+ HadamardFunc func;
+ int block_size;
+};
+
+std::ostream &operator<<(std::ostream &os, const HadamardFuncWithSize &hfs) {
+ return os << "block size: " << hfs.block_size;
+}
+
+class HadamardTestBase : public ::testing::TestWithParam<HadamardFuncWithSize> {
+ public:
+ virtual void SetUp() {
+ h_func_ = GetParam().func;
+ bwh_ = GetParam().block_size;
+ block_size_ = bwh_ * bwh_;
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ virtual int16_t Rand() = 0;
+
+ void ReferenceHadamard(const int16_t *a, int a_stride, tran_low_t *b,
+ int bwh) {
+ if (bwh == 32)
+ reference_hadamard32x32(a, a_stride, b);
+ else if (bwh == 16)
+ reference_hadamard16x16(a, a_stride, b);
+ else
+ reference_hadamard8x8(a, a_stride, b);
+ }
+
+ void CompareReferenceRandom() {
+ const int kMaxBlockSize = 32 * 32;
+ DECLARE_ALIGNED(16, int16_t, a[kMaxBlockSize]);
+ DECLARE_ALIGNED(16, tran_low_t, b[kMaxBlockSize]);
+ memset(a, 0, sizeof(a));
+ memset(b, 0, sizeof(b));
+
+ tran_low_t b_ref[kMaxBlockSize];
+ memset(b_ref, 0, sizeof(b_ref));
+
+ for (int i = 0; i < block_size_; ++i) a[i] = Rand();
+
+ ReferenceHadamard(a, bwh_, b_ref, bwh_);
+ ASM_REGISTER_STATE_CHECK(h_func_(a, bwh_, b));
+
+ // The order of the output is not important. Sort before checking.
+ std::sort(b, b + block_size_);
+ std::sort(b_ref, b_ref + block_size_);
+ EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
+ }
+
+ void VaryStride() {
+ const int kMaxBlockSize = 32 * 32;
+ DECLARE_ALIGNED(16, int16_t, a[kMaxBlockSize * 8]);
+ DECLARE_ALIGNED(16, tran_low_t, b[kMaxBlockSize]);
+ memset(a, 0, sizeof(a));
+ for (int i = 0; i < block_size_ * 8; ++i) a[i] = Rand();
+
+ tran_low_t b_ref[kMaxBlockSize];
+ for (int i = 8; i < 64; i += 8) {
+ memset(b, 0, sizeof(b));
+ memset(b_ref, 0, sizeof(b_ref));
+
+ ReferenceHadamard(a, i, b_ref, bwh_);
+ ASM_REGISTER_STATE_CHECK(h_func_(a, i, b));
+
+ // The order of the output is not important. Sort before checking.
+ std::sort(b, b + block_size_);
+ std::sort(b_ref, b_ref + block_size_);
+ EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
+ }
+ }
+
+ void SpeedTest(int times) {
+ const int kMaxBlockSize = 32 * 32;
+ DECLARE_ALIGNED(16, int16_t, input[kMaxBlockSize]);
+ DECLARE_ALIGNED(16, tran_low_t, output[kMaxBlockSize]);
+ memset(input, 1, sizeof(input));
+ memset(output, 0, sizeof(output));
+
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < times; ++i) {
+ h_func_(input, bwh_, output);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("Hadamard%dx%d[%12d runs]: %d us\n", bwh_, bwh_, times,
+ elapsed_time);
+ }
+
+ protected:
+ int bwh_;
+ int block_size_;
+ HadamardFunc h_func_;
+ ACMRandom rnd_;
+};
+
+class HadamardLowbdTest : public HadamardTestBase {
+ protected:
+ virtual int16_t Rand() { return rnd_.Rand9Signed(); }
+};
+
+TEST_P(HadamardLowbdTest, CompareReferenceRandom) { CompareReferenceRandom(); }
+
+TEST_P(HadamardLowbdTest, VaryStride) { VaryStride(); }
+
+TEST_P(HadamardLowbdTest, DISABLED_Speed) {
+ SpeedTest(10);
+ SpeedTest(10000);
+ SpeedTest(10000000);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ C, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_c, 8),
+ HadamardFuncWithSize(&vpx_hadamard_16x16_c, 16),
+ HadamardFuncWithSize(&vpx_hadamard_32x32_c, 32)));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_sse2, 8),
+ HadamardFuncWithSize(&vpx_hadamard_16x16_sse2, 16),
+ HadamardFuncWithSize(&vpx_hadamard_32x32_sse2, 32)));
+#endif // HAVE_SSE2
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_16x16_avx2, 16),
+ HadamardFuncWithSize(&vpx_hadamard_32x32_avx2, 32)));
+#endif // HAVE_AVX2
+
+#if HAVE_SSSE3 && VPX_ARCH_X86_64
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_ssse3, 8)));
+#endif // HAVE_SSSE3 && VPX_ARCH_X86_64
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_neon, 8),
+ HadamardFuncWithSize(&vpx_hadamard_16x16_neon, 16),
+ HadamardFuncWithSize(&vpx_hadamard_32x32_neon, 32)));
+#endif // HAVE_NEON
+
+// TODO(jingning): Remove highbitdepth flag when the SIMD functions are
+// in place and turn on the unit test.
+#if !CONFIG_VP9_HIGHBITDEPTH
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_msa, 8),
+ HadamardFuncWithSize(&vpx_hadamard_16x16_msa, 16)));
+#endif // HAVE_MSA
+#endif // !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_VSX
+INSTANTIATE_TEST_SUITE_P(
+ VSX, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_vsx, 8),
+ HadamardFuncWithSize(&vpx_hadamard_16x16_vsx, 16)));
+#endif // HAVE_VSX
+
+#if HAVE_LSX
+INSTANTIATE_TEST_SUITE_P(
+ LSX, HadamardLowbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_lsx, 8),
+ HadamardFuncWithSize(&vpx_hadamard_16x16_lsx, 16)));
+#endif // HAVE_LSX
+
+#if CONFIG_VP9_HIGHBITDEPTH
+class HadamardHighbdTest : public HadamardTestBase {
+ protected:
+ virtual int16_t Rand() { return rnd_.Rand13Signed(); }
+};
+
+TEST_P(HadamardHighbdTest, CompareReferenceRandom) { CompareReferenceRandom(); }
+
+TEST_P(HadamardHighbdTest, VaryStride) { VaryStride(); }
+
+TEST_P(HadamardHighbdTest, DISABLED_Speed) {
+ SpeedTest(10);
+ SpeedTest(10000);
+ SpeedTest(10000000);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ C, HadamardHighbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_highbd_hadamard_8x8_c, 8),
+ HadamardFuncWithSize(&vpx_highbd_hadamard_16x16_c, 16),
+ HadamardFuncWithSize(&vpx_highbd_hadamard_32x32_c, 32)));
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, HadamardHighbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_highbd_hadamard_8x8_avx2, 8),
+ HadamardFuncWithSize(&vpx_highbd_hadamard_16x16_avx2, 16),
+ HadamardFuncWithSize(&vpx_highbd_hadamard_32x32_avx2,
+ 32)));
+#endif // HAVE_AVX2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, HadamardHighbdTest,
+ ::testing::Values(HadamardFuncWithSize(&vpx_highbd_hadamard_8x8_neon, 8),
+ HadamardFuncWithSize(&vpx_highbd_hadamard_16x16_neon, 16),
+ HadamardFuncWithSize(&vpx_highbd_hadamard_32x32_neon,
+ 32)));
+#endif
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+} // namespace
diff --git a/media/libvpx/libvpx/test/i420_video_source.h b/media/libvpx/libvpx/test/i420_video_source.h
new file mode 100644
index 0000000000..97473b5c2f
--- /dev/null
+++ b/media/libvpx/libvpx/test/i420_video_source.h
@@ -0,0 +1,33 @@
+/*
+ * 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 VPX_TEST_I420_VIDEO_SOURCE_H_
+#define VPX_TEST_I420_VIDEO_SOURCE_H_
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include "test/yuv_video_source.h"
+
+namespace libvpx_test {
+
+// This class extends VideoSource to allow parsing of raw yv12
+// so that we can do actual file encodes.
+class I420VideoSource : public YUVVideoSource {
+ public:
+ I420VideoSource(const std::string &file_name, unsigned int width,
+ unsigned int height, int rate_numerator, int rate_denominator,
+ unsigned int start, int limit)
+ : YUVVideoSource(file_name, VPX_IMG_FMT_I420, width, height,
+ rate_numerator, rate_denominator, start, limit) {}
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_I420_VIDEO_SOURCE_H_
diff --git a/media/libvpx/libvpx/test/idct8x8_test.cc b/media/libvpx/libvpx/test/idct8x8_test.cc
new file mode 100644
index 0000000000..7951bb93c9
--- /dev/null
+++ b/media/libvpx/libvpx/test/idct8x8_test.cc
@@ -0,0 +1,87 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/msvc.h" // for round()
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+void reference_dct_1d(double input[8], double output[8]) {
+ const double kPi = 3.141592653589793238462643383279502884;
+ const double kInvSqrt2 = 0.707106781186547524400844362104;
+ for (int k = 0; k < 8; k++) {
+ output[k] = 0.0;
+ for (int n = 0; n < 8; n++) {
+ output[k] += input[n] * cos(kPi * (2 * n + 1) * k / 16.0);
+ }
+ if (k == 0) output[k] = output[k] * kInvSqrt2;
+ }
+}
+
+void reference_dct_2d(int16_t input[64], double output[64]) {
+ // First transform columns
+ for (int i = 0; i < 8; ++i) {
+ double temp_in[8], temp_out[8];
+ for (int j = 0; j < 8; ++j) temp_in[j] = input[j * 8 + i];
+ reference_dct_1d(temp_in, temp_out);
+ for (int j = 0; j < 8; ++j) output[j * 8 + i] = temp_out[j];
+ }
+ // Then transform rows
+ for (int i = 0; i < 8; ++i) {
+ double temp_in[8], temp_out[8];
+ for (int j = 0; j < 8; ++j) temp_in[j] = output[j + i * 8];
+ reference_dct_1d(temp_in, temp_out);
+ for (int j = 0; j < 8; ++j) output[j + i * 8] = temp_out[j];
+ }
+ // Scale by some magic number
+ for (int i = 0; i < 64; ++i) output[i] *= 2;
+}
+
+TEST(VP9Idct8x8Test, AccuracyCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 10000;
+ for (int i = 0; i < count_test_block; ++i) {
+ int16_t input[64];
+ tran_low_t coeff[64];
+ double output_r[64];
+ uint8_t dst[64], src[64];
+
+ for (int j = 0; j < 64; ++j) {
+ src[j] = rnd.Rand8();
+ dst[j] = rnd.Rand8();
+ }
+ // Initialize a test block with input range [-255, 255].
+ for (int j = 0; j < 64; ++j) input[j] = src[j] - dst[j];
+
+ reference_dct_2d(input, output_r);
+ for (int j = 0; j < 64; ++j) {
+ coeff[j] = static_cast<tran_low_t>(round(output_r[j]));
+ }
+ vpx_idct8x8_64_add_c(coeff, dst, 8);
+ for (int j = 0; j < 64; ++j) {
+ const int diff = dst[j] - src[j];
+ const int error = diff * diff;
+ EXPECT_GE(1, error) << "Error: 8x8 FDCT/IDCT has error " << error
+ << " at index " << j;
+ }
+ }
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/idct_test.cc b/media/libvpx/libvpx/test/idct_test.cc
new file mode 100644
index 0000000000..1b9532e1c1
--- /dev/null
+++ b/media/libvpx/libvpx/test/idct_test.cc
@@ -0,0 +1,180 @@
+/*
+ * 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 "./vpx_config.h"
+#include "./vp8_rtcd.h"
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/buffer.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "vpx/vpx_integer.h"
+
+typedef void (*IdctFunc)(int16_t *input, unsigned char *pred_ptr,
+ int pred_stride, unsigned char *dst_ptr,
+ int dst_stride);
+namespace {
+
+using libvpx_test::Buffer;
+
+class IDCTTest : public ::testing::TestWithParam<IdctFunc> {
+ protected:
+ virtual void SetUp() {
+ UUT = GetParam();
+
+ input = new Buffer<int16_t>(4, 4, 0);
+ ASSERT_NE(input, nullptr);
+ ASSERT_TRUE(input->Init());
+ predict = new Buffer<uint8_t>(4, 4, 3);
+ ASSERT_NE(predict, nullptr);
+ ASSERT_TRUE(predict->Init());
+ output = new Buffer<uint8_t>(4, 4, 3);
+ ASSERT_NE(output, nullptr);
+ ASSERT_TRUE(output->Init());
+ }
+
+ virtual void TearDown() {
+ delete input;
+ delete predict;
+ delete output;
+ libvpx_test::ClearSystemState();
+ }
+
+ IdctFunc UUT;
+ Buffer<int16_t> *input;
+ Buffer<uint8_t> *predict;
+ Buffer<uint8_t> *output;
+};
+
+TEST_P(IDCTTest, TestAllZeros) {
+ // When the input is '0' the output will be '0'.
+ input->Set(0);
+ predict->Set(0);
+ output->Set(0);
+
+ ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
+ predict->stride(), output->TopLeftPixel(),
+ output->stride()));
+
+ ASSERT_TRUE(input->CheckValues(0));
+ ASSERT_TRUE(input->CheckPadding());
+ ASSERT_TRUE(output->CheckValues(0));
+ ASSERT_TRUE(output->CheckPadding());
+}
+
+TEST_P(IDCTTest, TestAllOnes) {
+ input->Set(0);
+ ASSERT_NE(input->TopLeftPixel(), nullptr);
+ // When the first element is '4' it will fill the output buffer with '1'.
+ input->TopLeftPixel()[0] = 4;
+ predict->Set(0);
+ output->Set(0);
+
+ ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
+ predict->stride(), output->TopLeftPixel(),
+ output->stride()));
+
+ ASSERT_TRUE(output->CheckValues(1));
+ ASSERT_TRUE(output->CheckPadding());
+}
+
+TEST_P(IDCTTest, TestAddOne) {
+ // Set the transform output to '1' and make sure it gets added to the
+ // prediction buffer.
+ input->Set(0);
+ ASSERT_NE(input->TopLeftPixel(), nullptr);
+ input->TopLeftPixel()[0] = 4;
+ output->Set(0);
+
+ uint8_t *pred = predict->TopLeftPixel();
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ pred[y * predict->stride() + x] = y * 4 + x;
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
+ predict->stride(), output->TopLeftPixel(),
+ output->stride()));
+
+ uint8_t const *out = output->TopLeftPixel();
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ EXPECT_EQ(1 + y * 4 + x, out[y * output->stride() + x]);
+ }
+ }
+
+ if (HasFailure()) {
+ output->DumpBuffer();
+ }
+
+ ASSERT_TRUE(output->CheckPadding());
+}
+
+TEST_P(IDCTTest, TestWithData) {
+ // Test a single known input.
+ predict->Set(0);
+
+ int16_t *in = input->TopLeftPixel();
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ in[y * input->stride() + x] = y * 4 + x;
+ }
+ }
+
+ ASM_REGISTER_STATE_CHECK(UUT(input->TopLeftPixel(), predict->TopLeftPixel(),
+ predict->stride(), output->TopLeftPixel(),
+ output->stride()));
+
+ uint8_t *out = output->TopLeftPixel();
+ for (int y = 0; y < 4; ++y) {
+ for (int x = 0; x < 4; ++x) {
+ switch (y * 4 + x) {
+ case 0: EXPECT_EQ(11, out[y * output->stride() + x]); break;
+ case 2:
+ case 5:
+ case 8: EXPECT_EQ(3, out[y * output->stride() + x]); break;
+ case 10: EXPECT_EQ(1, out[y * output->stride() + x]); break;
+ default: EXPECT_EQ(0, out[y * output->stride() + x]);
+ }
+ }
+ }
+
+ if (HasFailure()) {
+ output->DumpBuffer();
+ }
+
+ ASSERT_TRUE(output->CheckPadding());
+}
+
+INSTANTIATE_TEST_SUITE_P(C, IDCTTest,
+ ::testing::Values(vp8_short_idct4x4llm_c));
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, IDCTTest,
+ ::testing::Values(vp8_short_idct4x4llm_neon));
+#endif // HAVE_NEON
+
+#if HAVE_MMX
+INSTANTIATE_TEST_SUITE_P(MMX, IDCTTest,
+ ::testing::Values(vp8_short_idct4x4llm_mmx));
+#endif // HAVE_MMX
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(MSA, IDCTTest,
+ ::testing::Values(vp8_short_idct4x4llm_msa));
+#endif // HAVE_MSA
+
+#if HAVE_MMI
+INSTANTIATE_TEST_SUITE_P(MMI, IDCTTest,
+ ::testing::Values(vp8_short_idct4x4llm_mmi));
+#endif // HAVE_MMI
+} // namespace
diff --git a/media/libvpx/libvpx/test/invalid_file_test.cc b/media/libvpx/libvpx/test/invalid_file_test.cc
new file mode 100644
index 0000000000..762d585f59
--- /dev/null
+++ b/media/libvpx/libvpx/test/invalid_file_test.cc
@@ -0,0 +1,221 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+struct DecodeParam {
+ int threads;
+ const char *filename;
+};
+
+std::ostream &operator<<(std::ostream &os, const DecodeParam &dp) {
+ return os << "threads: " << dp.threads << " file: " << dp.filename;
+}
+
+class InvalidFileTest : public ::libvpx_test::DecoderTest,
+ public ::libvpx_test::CodecTestWithParam<DecodeParam> {
+ protected:
+ InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(nullptr) {}
+
+ virtual ~InvalidFileTest() {
+ if (res_file_ != nullptr) fclose(res_file_);
+ }
+
+ void OpenResFile(const std::string &res_file_name_) {
+ res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
+ ASSERT_NE(res_file_, nullptr)
+ << "Result file open failed. Filename: " << res_file_name_;
+ }
+
+ virtual bool HandleDecodeResult(
+ const vpx_codec_err_t res_dec,
+ const libvpx_test::CompressedVideoSource &video,
+ libvpx_test::Decoder *decoder) {
+ EXPECT_NE(res_file_, nullptr);
+ int expected_res_dec;
+
+ // Read integer result.
+ const int res = fscanf(res_file_, "%d", &expected_res_dec);
+ EXPECT_NE(res, EOF) << "Read result data failed";
+
+ // Check results match.
+ const DecodeParam input = GET_PARAM(1);
+ if (input.threads > 1) {
+ // The serial decode check is too strict for tile-threaded decoding as
+ // there is no guarantee on the decode order nor which specific error
+ // will take precedence. Currently a tile-level error is not forwarded so
+ // the frame will simply be marked corrupt.
+ EXPECT_TRUE(res_dec == expected_res_dec ||
+ res_dec == VPX_CODEC_CORRUPT_FRAME)
+ << "Results don't match: frame number = " << video.frame_number()
+ << ". (" << decoder->DecodeError()
+ << "). Expected: " << expected_res_dec << " or "
+ << VPX_CODEC_CORRUPT_FRAME;
+ } else {
+ EXPECT_EQ(expected_res_dec, res_dec)
+ << "Results don't match: frame number = " << video.frame_number()
+ << ". (" << decoder->DecodeError() << ")";
+ }
+
+ return !HasFailure();
+ }
+
+ void RunTest() {
+ const DecodeParam input = GET_PARAM(1);
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ cfg.threads = input.threads;
+ const std::string filename = input.filename;
+
+ // Open compressed video file.
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ if (filename.substr(filename.length() - 3, 3) == "ivf") {
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+#if CONFIG_WEBM_IO
+ video.reset(new libvpx_test::WebMVideoSource(filename));
+#else
+ fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+ filename.c_str());
+ return;
+#endif
+ }
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+
+ // Construct result file name. The file holds a list of expected integer
+ // results, one for each decoded frame. Any result that doesn't match
+ // the files list will cause a test failure.
+ const std::string res_filename = filename + ".res";
+ OpenResFile(res_filename);
+
+ // Decode frame, and check the md5 matching.
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get(), cfg));
+ }
+
+ private:
+ FILE *res_file_;
+};
+
+TEST_P(InvalidFileTest, ReturnCode) { RunTest(); }
+
+#if CONFIG_VP8_DECODER
+const DecodeParam kVP8InvalidFileTests[] = {
+ { 1, "invalid-bug-1443.ivf" },
+ { 1, "invalid-bug-148271109.ivf" },
+ { 1, "invalid-token-partition.ivf" },
+ { 1, "invalid-vp80-00-comprehensive-s17661_r01-05_b6-.ivf" },
+};
+
+VP8_INSTANTIATE_TEST_SUITE(InvalidFileTest,
+ ::testing::ValuesIn(kVP8InvalidFileTests));
+#endif // CONFIG_VP8_DECODER
+
+#if CONFIG_VP9_DECODER
+const DecodeParam kVP9InvalidFileTests[] = {
+ { 1, "invalid-vp90-02-v2.webm" },
+#if CONFIG_VP9_HIGHBITDEPTH
+ { 1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf" },
+ { 1,
+ "invalid-vp90-2-21-resize_inter_320x180_5_3-4.webm.ivf.s45551_r01-05_b6-."
+ "ivf" },
+#endif
+ { 1, "invalid-vp90-03-v3.webm" },
+ { 1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf" },
+ { 1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf" },
+// This file will cause a large allocation which is expected to fail in 32-bit
+// environments. Test x86 for coverage purposes as the allocation failure will
+// be in platform agnostic code.
+#if VPX_ARCH_X86
+ { 1, "invalid-vp90-2-00-quantizer-63.ivf.kf_65527x61446.ivf" },
+#endif
+ { 1, "invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf" },
+ { 1, "invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf" },
+ { 1, "invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf" },
+ { 1, "invalid-vp91-2-mixedrefcsp-444to420.ivf" },
+ { 1, "invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf" },
+ { 1, "invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf" },
+ { 1, "invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf" },
+ { 1,
+ "invalid-vp90-2-10-show-existing-frame.webm.ivf.s180315_r01-05_b6-.ivf" },
+ { 1, "invalid-crbug-667044.webm" },
+};
+
+VP9_INSTANTIATE_TEST_SUITE(InvalidFileTest,
+ ::testing::ValuesIn(kVP9InvalidFileTests));
+#endif // CONFIG_VP9_DECODER
+
+// This class will include test vectors that are expected to fail
+// peek. However they are still expected to have no fatal failures.
+class InvalidFileInvalidPeekTest : public InvalidFileTest {
+ protected:
+ InvalidFileInvalidPeekTest() : InvalidFileTest() {}
+ virtual void HandlePeekResult(libvpx_test::Decoder *const /*decoder*/,
+ libvpx_test::CompressedVideoSource * /*video*/,
+ const vpx_codec_err_t /*res_peek*/) {}
+};
+
+TEST_P(InvalidFileInvalidPeekTest, ReturnCode) { RunTest(); }
+
+#if CONFIG_VP8_DECODER
+const DecodeParam kVP8InvalidPeekTests[] = {
+ { 1, "invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf" },
+};
+
+VP8_INSTANTIATE_TEST_SUITE(InvalidFileInvalidPeekTest,
+ ::testing::ValuesIn(kVP8InvalidPeekTests));
+#endif // CONFIG_VP8_DECODER
+
+#if CONFIG_VP9_DECODER
+const DecodeParam kVP9InvalidFileInvalidPeekTests[] = {
+ { 1, "invalid-vp90-01-v3.webm" },
+};
+
+VP9_INSTANTIATE_TEST_SUITE(
+ InvalidFileInvalidPeekTest,
+ ::testing::ValuesIn(kVP9InvalidFileInvalidPeekTests));
+
+const DecodeParam kMultiThreadedVP9InvalidFileTests[] = {
+ { 4, "invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm" },
+ { 4,
+ "invalid-"
+ "vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf" },
+ { 4,
+ "invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf" },
+ { 2, "invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf" },
+ { 4, "invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf" },
+ { 2, "invalid-crbug-629481.webm" },
+ { 3, "invalid-crbug-1558.ivf" },
+ { 4, "invalid-crbug-1562.ivf" },
+};
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9MultiThreaded, InvalidFileTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
+ ::testing::ValuesIn(kMultiThreadedVP9InvalidFileTests)));
+#endif // CONFIG_VP9_DECODER
+} // namespace
diff --git a/media/libvpx/libvpx/test/ivf_video_source.h b/media/libvpx/libvpx/test/ivf_video_source.h
new file mode 100644
index 0000000000..a8ac4f154c
--- /dev/null
+++ b/media/libvpx/libvpx/test/ivf_video_source.h
@@ -0,0 +1,106 @@
+/*
+ * 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 VPX_TEST_IVF_VIDEO_SOURCE_H_
+#define VPX_TEST_IVF_VIDEO_SOURCE_H_
+#include <cstdio>
+#include <cstdlib>
+#include <new>
+#include <string>
+#include "test/video_source.h"
+
+namespace libvpx_test {
+const unsigned int kCodeBufferSize = 256 * 1024 * 1024;
+const unsigned int kIvfFileHdrSize = 32;
+const unsigned int kIvfFrameHdrSize = 12;
+
+static unsigned int MemGetLe32(const uint8_t *mem) {
+ return (mem[3] << 24) | (mem[2] << 16) | (mem[1] << 8) | (mem[0]);
+}
+
+// This class extends VideoSource to allow parsing of ivf files,
+// so that we can do actual file decodes.
+class IVFVideoSource : public CompressedVideoSource {
+ public:
+ explicit IVFVideoSource(const std::string &file_name)
+ : file_name_(file_name), input_file_(nullptr),
+ compressed_frame_buf_(nullptr), frame_sz_(0), frame_(0),
+ end_of_file_(false) {}
+
+ virtual ~IVFVideoSource() {
+ delete[] compressed_frame_buf_;
+
+ if (input_file_) fclose(input_file_);
+ }
+
+ virtual void Init() {
+ // Allocate a buffer for read in the compressed video frame.
+ compressed_frame_buf_ = new uint8_t[libvpx_test::kCodeBufferSize];
+ ASSERT_NE(compressed_frame_buf_, nullptr) << "Allocate frame buffer failed";
+ }
+
+ virtual void Begin() {
+ input_file_ = OpenTestDataFile(file_name_);
+ ASSERT_NE(input_file_, nullptr)
+ << "Input file open failed. Filename: " << file_name_;
+
+ // Read file header
+ uint8_t file_hdr[kIvfFileHdrSize];
+ ASSERT_EQ(kIvfFileHdrSize, fread(file_hdr, 1, kIvfFileHdrSize, input_file_))
+ << "File header read failed.";
+ // Check file header
+ ASSERT_TRUE(file_hdr[0] == 'D' && file_hdr[1] == 'K' &&
+ file_hdr[2] == 'I' && file_hdr[3] == 'F')
+ << "Input is not an IVF file.";
+
+ FillFrame();
+ }
+
+ virtual void Next() {
+ ++frame_;
+ FillFrame();
+ }
+
+ void FillFrame() {
+ ASSERT_NE(input_file_, nullptr);
+ uint8_t frame_hdr[kIvfFrameHdrSize];
+ // Check frame header and read a frame from input_file.
+ if (fread(frame_hdr, 1, kIvfFrameHdrSize, input_file_) !=
+ kIvfFrameHdrSize) {
+ end_of_file_ = true;
+ } else {
+ end_of_file_ = false;
+
+ frame_sz_ = MemGetLe32(frame_hdr);
+ ASSERT_LE(frame_sz_, kCodeBufferSize)
+ << "Frame is too big for allocated code buffer";
+ ASSERT_EQ(frame_sz_,
+ fread(compressed_frame_buf_, 1, frame_sz_, input_file_))
+ << "Failed to read complete frame";
+ }
+ }
+
+ virtual const uint8_t *cxdata() const {
+ return end_of_file_ ? nullptr : compressed_frame_buf_;
+ }
+ virtual size_t frame_size() const { return frame_sz_; }
+ virtual unsigned int frame_number() const { return frame_; }
+
+ protected:
+ std::string file_name_;
+ FILE *input_file_;
+ uint8_t *compressed_frame_buf_;
+ size_t frame_sz_;
+ unsigned int frame_;
+ bool end_of_file_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_IVF_VIDEO_SOURCE_H_
diff --git a/media/libvpx/libvpx/test/keyframe_test.cc b/media/libvpx/libvpx/test/keyframe_test.cc
new file mode 100644
index 0000000000..a13dec9ce2
--- /dev/null
+++ b/media/libvpx/libvpx/test/keyframe_test.cc
@@ -0,0 +1,149 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class KeyframeTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ KeyframeTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~KeyframeTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ kf_count_ = 0;
+ kf_count_max_ = INT_MAX;
+ kf_do_force_kf_ = false;
+ set_cpu_used_ = 0;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (kf_do_force_kf_) {
+ frame_flags_ = (video->frame() % 3) ? 0 : VPX_EFLAG_FORCE_KF;
+ }
+ if (set_cpu_used_ && video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ }
+ }
+
+ 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_;
+ int set_cpu_used_;
+};
+
+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));
+
+ // In realtime mode - auto placed keyframes are exceedingly rare, don't
+ // bother with this check if(GetParam() > 0)
+ if (GET_PARAM(1) > 0) {
+ 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>::const_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>::const_iterator iter = kf_pts_list_.begin();
+ iter != kf_pts_list_.end(); ++iter) {
+ ASSERT_EQ(0, *iter % 25) << "Unexpected keyframe at frame " << *iter;
+ }
+}
+
+TEST_P(KeyframeTest, TestAutoKeyframe) {
+ cfg_.kf_mode = VPX_KF_AUTO;
+ kf_do_force_kf_ = false;
+
+ // Force a deterministic speed step in Real Time mode, as the faster modes
+ // may not produce a keyframe like we expect. This is necessary when running
+ // on very slow environments (like Valgrind). The step -11 was determined
+ // experimentally as the fastest mode that still throws the keyframe.
+ if (deadline_ == VPX_DL_REALTIME) set_cpu_used_ = -11;
+
+ // This clip has a cut scene every 30 frames -> Frame 0, 30, 60, 90, 120.
+ // I check only the first 40 frames to make sure there's a keyframe at frame
+ // 0 and 30.
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 40);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ // In realtime mode - auto placed keyframes are exceedingly rare, don't
+ // bother with this check
+ if (GET_PARAM(1) > 0) {
+ EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes ";
+ }
+
+ // Verify that keyframes match the file keyframes in the file.
+ for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+ iter != kf_pts_list_.end(); ++iter) {
+ if (deadline_ == VPX_DL_REALTIME && *iter > 0)
+ EXPECT_EQ(0, (*iter - 1) % 30)
+ << "Unexpected keyframe at frame " << *iter;
+ else
+ EXPECT_EQ(0, *iter % 30) << "Unexpected keyframe at frame " << *iter;
+ }
+}
+
+VP8_INSTANTIATE_TEST_SUITE(KeyframeTest, ALL_TEST_MODES);
+} // namespace
diff --git a/media/libvpx/libvpx/test/level_test.cc b/media/libvpx/libvpx/test/level_test.cc
new file mode 100644
index 0000000000..038d75f44f
--- /dev/null
+++ b/media/libvpx/libvpx/test/level_test.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2016 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"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+class LevelTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ LevelTest()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
+ cpu_used_(GET_PARAM(2)), min_gf_internal_(24), target_level_(0),
+ level_(0) {}
+ virtual ~LevelTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_end_usage = VPX_VBR;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ }
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_target_bitrate = 400;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_min_quantizer = 0;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ encoder->Control(VP9E_SET_TARGET_LEVEL, target_level_);
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_gf_internal_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+ encoder->Control(VP9E_GET_LEVEL, &level_);
+ ASSERT_LE(level_, 51);
+ ASSERT_GE(level_, 0);
+ }
+
+ ::libvpx_test::TestMode encoding_mode_;
+ int cpu_used_;
+ int min_gf_internal_;
+ int target_level_;
+ int level_;
+};
+
+TEST_P(LevelTest, TestTargetLevel11Large) {
+ ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 60);
+ target_level_ = 11;
+ cfg_.rc_target_bitrate = 150;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(target_level_, level_);
+}
+
+TEST_P(LevelTest, TestTargetLevel20Large) {
+ ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 60);
+ target_level_ = 20;
+ cfg_.rc_target_bitrate = 1200;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(target_level_, level_);
+}
+
+TEST_P(LevelTest, TestTargetLevel31Large) {
+ ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
+ ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, 30,
+ 1, 0, 60);
+ target_level_ = 31;
+ cfg_.rc_target_bitrate = 8000;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(target_level_, level_);
+}
+
+// Test for keeping level stats only
+TEST_P(LevelTest, TestTargetLevel0) {
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 40);
+ target_level_ = 0;
+ min_gf_internal_ = 4;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(11, level_);
+
+ cfg_.rc_target_bitrate = 1600;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(20, level_);
+}
+
+// Test for level control being turned off
+TEST_P(LevelTest, TestTargetLevel255) {
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+ 30);
+ target_level_ = 255;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(LevelTest, TestTargetLevelApi) {
+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, 1);
+ static const vpx_codec_iface_t *codec = &vpx_codec_vp9_cx_algo;
+ vpx_codec_ctx_t enc;
+ vpx_codec_enc_cfg_t cfg;
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(codec, &cfg, 0));
+ cfg.rc_target_bitrate = 100;
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, codec, &cfg, 0));
+ for (int level = 0; level <= 256; ++level) {
+ if (level == 10 || level == 11 || level == 20 || level == 21 ||
+ level == 30 || level == 31 || level == 40 || level == 41 ||
+ level == 50 || level == 51 || level == 52 || level == 60 ||
+ level == 61 || level == 62 || level == 0 || level == 1 || level == 255)
+ EXPECT_EQ(VPX_CODEC_OK,
+ vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level));
+ else
+ EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+ vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level));
+ }
+ EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(LevelTest,
+ ::testing::Values(::libvpx_test::kTwoPassGood,
+ ::libvpx_test::kOnePassGood),
+ ::testing::Range(0, 9));
+} // namespace
diff --git a/media/libvpx/libvpx/test/lpf_test.cc b/media/libvpx/libvpx/test/lpf_test.cc
new file mode 100644
index 0000000000..4cc99a6db4
--- /dev/null
+++ b/media/libvpx/libvpx/test/lpf_test.cc
@@ -0,0 +1,721 @@
+/*
+ * 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 <cmath>
+#include <cstdlib>
+#include <string>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_loopfilter.h"
+#include "vpx/vpx_integer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+// Horizontally and Vertically need 32x32: 8 Coeffs preceeding filtered section
+// 16 Coefs within filtered section
+// 8 Coeffs following filtered section
+const int kNumCoeffs = 1024;
+
+const int number_of_iterations = 10000;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+typedef uint16_t Pixel;
+#define PIXEL_WIDTH 16
+
+typedef void (*loop_op_t)(Pixel *s, int p, const uint8_t *blimit,
+ const uint8_t *limit, const uint8_t *thresh, int bd);
+typedef void (*dual_loop_op_t)(Pixel *s, int p, const uint8_t *blimit0,
+ const uint8_t *limit0, const uint8_t *thresh0,
+ const uint8_t *blimit1, const uint8_t *limit1,
+ const uint8_t *thresh1, int bd);
+#else
+typedef uint8_t Pixel;
+#define PIXEL_WIDTH 8
+
+typedef void (*loop_op_t)(Pixel *s, int p, const uint8_t *blimit,
+ const uint8_t *limit, const uint8_t *thresh);
+typedef void (*dual_loop_op_t)(Pixel *s, int p, const uint8_t *blimit0,
+ const uint8_t *limit0, const uint8_t *thresh0,
+ const uint8_t *blimit1, const uint8_t *limit1,
+ const uint8_t *thresh1);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+typedef std::tuple<loop_op_t, loop_op_t, int> loop8_param_t;
+typedef std::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t;
+
+void InitInput(Pixel *s, Pixel *ref_s, ACMRandom *rnd, const uint8_t limit,
+ const int mask, const int32_t p, const int i) {
+ uint16_t tmp_s[kNumCoeffs];
+
+ for (int j = 0; j < kNumCoeffs;) {
+ const uint8_t val = rnd->Rand8();
+ if (val & 0x80) { // 50% chance to choose a new value.
+ tmp_s[j] = rnd->Rand16();
+ j++;
+ } else { // 50% chance to repeat previous value in row X times.
+ int k = 0;
+ while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
+ if (j < 1) {
+ tmp_s[j] = rnd->Rand16();
+ } else if (val & 0x20) { // Increment by a value within the limit.
+ tmp_s[j] = static_cast<uint16_t>(tmp_s[j - 1] + (limit - 1));
+ } else { // Decrement by a value within the limit.
+ tmp_s[j] = static_cast<uint16_t>(tmp_s[j - 1] - (limit - 1));
+ }
+ j++;
+ }
+ }
+ }
+
+ for (int j = 0; j < kNumCoeffs;) {
+ const uint8_t val = rnd->Rand8();
+ if (val & 0x80) {
+ j++;
+ } else { // 50% chance to repeat previous value in column X times.
+ int k = 0;
+ while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
+ if (j < 1) {
+ tmp_s[j] = rnd->Rand16();
+ } else if (val & 0x20) { // Increment by a value within the limit.
+ tmp_s[(j % 32) * 32 + j / 32] = static_cast<uint16_t>(
+ tmp_s[((j - 1) % 32) * 32 + (j - 1) / 32] + (limit - 1));
+ } else { // Decrement by a value within the limit.
+ tmp_s[(j % 32) * 32 + j / 32] = static_cast<uint16_t>(
+ tmp_s[((j - 1) % 32) * 32 + (j - 1) / 32] - (limit - 1));
+ }
+ j++;
+ }
+ }
+ }
+
+ for (int j = 0; j < kNumCoeffs; j++) {
+ if (i % 2) {
+ s[j] = tmp_s[j] & mask;
+ } else {
+ s[j] = tmp_s[p * (j % p) + j / p] & mask;
+ }
+ ref_s[j] = s[j];
+ }
+}
+
+uint8_t GetOuterThresh(ACMRandom *rnd) {
+ return static_cast<uint8_t>(rnd->RandRange(3 * MAX_LOOP_FILTER + 5));
+}
+
+uint8_t GetInnerThresh(ACMRandom *rnd) {
+ return static_cast<uint8_t>(rnd->RandRange(MAX_LOOP_FILTER + 1));
+}
+
+uint8_t GetHevThresh(ACMRandom *rnd) {
+ return static_cast<uint8_t>(rnd->RandRange(MAX_LOOP_FILTER + 1) >> 4);
+}
+
+class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> {
+ public:
+ virtual ~Loop8Test6Param() {}
+ virtual void SetUp() {
+ loopfilter_op_ = GET_PARAM(0);
+ ref_loopfilter_op_ = GET_PARAM(1);
+ bit_depth_ = GET_PARAM(2);
+ mask_ = (1 << bit_depth_) - 1;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ int bit_depth_;
+ int mask_;
+ loop_op_t loopfilter_op_;
+ loop_op_t ref_loopfilter_op_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Loop8Test6Param);
+
+#if HAVE_NEON || HAVE_SSE2 || (HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH) || \
+ (HAVE_DSPR2 || HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH)
+class Loop8Test9Param : public ::testing::TestWithParam<dualloop8_param_t> {
+ public:
+ virtual ~Loop8Test9Param() {}
+ virtual void SetUp() {
+ loopfilter_op_ = GET_PARAM(0);
+ ref_loopfilter_op_ = GET_PARAM(1);
+ bit_depth_ = GET_PARAM(2);
+ mask_ = (1 << bit_depth_) - 1;
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ int bit_depth_;
+ int mask_;
+ dual_loop_op_t loopfilter_op_;
+ dual_loop_op_t ref_loopfilter_op_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(Loop8Test9Param);
+#endif // HAVE_NEON || HAVE_SSE2 || (HAVE_DSPR2 || HAVE_MSA &&
+ // (!CONFIG_VP9_HIGHBITDEPTH) || (HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH))
+
+TEST_P(Loop8Test6Param, OperationCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = number_of_iterations;
+ const int32_t p = kNumCoeffs / 32;
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
+ int err_count_total = 0;
+ int first_failure = -1;
+ for (int i = 0; i < count_test_block; ++i) {
+ int err_count = 0;
+ uint8_t tmp = GetOuterThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetInnerThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetHevThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ InitInput(s, ref_s, &rnd, *limit, mask_, p, i);
+#if CONFIG_VP9_HIGHBITDEPTH
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_);
+ ASM_REGISTER_STATE_CHECK(
+ loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_));
+#else
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh);
+ ASM_REGISTER_STATE_CHECK(
+ loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ err_count += ref_s[j] != s[j];
+ }
+ if (err_count && !err_count_total) {
+ first_failure = i;
+ }
+ err_count_total += err_count;
+ }
+ EXPECT_EQ(0, err_count_total)
+ << "Error: Loop8Test6Param, C output doesn't match SSE2 "
+ "loopfilter output. "
+ << "First failed at test case " << first_failure;
+}
+
+TEST_P(Loop8Test6Param, ValueCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = number_of_iterations;
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
+ int err_count_total = 0;
+ int first_failure = -1;
+
+ // NOTE: The code in vp9_loopfilter.c:update_sharpness computes mblim as a
+ // function of sharpness_lvl and the loopfilter lvl as:
+ // block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4));
+ // ...
+ // memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit),
+ // SIMD_WIDTH);
+ // This means that the largest value for mblim will occur when sharpness_lvl
+ // is equal to 0, and lvl is equal to its greatest value (MAX_LOOP_FILTER).
+ // In this case block_inside_limit will be equal to MAX_LOOP_FILTER and
+ // therefore mblim will be equal to (2 * (lvl + 2) + block_inside_limit) =
+ // 2 * (MAX_LOOP_FILTER + 2) + MAX_LOOP_FILTER = 3 * MAX_LOOP_FILTER + 4
+
+ for (int i = 0; i < count_test_block; ++i) {
+ int err_count = 0;
+ uint8_t tmp = GetOuterThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ blimit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetInnerThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ limit[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetHevThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ thresh[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ int32_t p = kNumCoeffs / 32;
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ s[j] = rnd.Rand16() & mask_;
+ ref_s[j] = s[j];
+ }
+#if CONFIG_VP9_HIGHBITDEPTH
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_);
+ ASM_REGISTER_STATE_CHECK(
+ loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bit_depth_));
+#else
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh);
+ ASM_REGISTER_STATE_CHECK(
+ loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ err_count += ref_s[j] != s[j];
+ }
+ if (err_count && !err_count_total) {
+ first_failure = i;
+ }
+ err_count_total += err_count;
+ }
+ EXPECT_EQ(0, err_count_total)
+ << "Error: Loop8Test6Param, C output doesn't match SSE2 "
+ "loopfilter output. "
+ << "First failed at test case " << first_failure;
+}
+
+#if HAVE_NEON || HAVE_SSE2 || (HAVE_LSX && (!CONFIG_VP9_HIGHBITDEPTH)) || \
+ (HAVE_DSPR2 || HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH))
+TEST_P(Loop8Test9Param, OperationCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = number_of_iterations;
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
+ int err_count_total = 0;
+ int first_failure = -1;
+ for (int i = 0; i < count_test_block; ++i) {
+ int err_count = 0;
+ uint8_t tmp = GetOuterThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetInnerThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetHevThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetOuterThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetInnerThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetHevThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ int32_t p = kNumCoeffs / 32;
+ const uint8_t limit = *limit0 < *limit1 ? *limit0 : *limit1;
+ InitInput(s, ref_s, &rnd, limit, mask_, p, i);
+#if CONFIG_VP9_HIGHBITDEPTH
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
+ limit1, thresh1, bit_depth_);
+ ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
+ thresh0, blimit1, limit1, thresh1,
+ bit_depth_));
+#else
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
+ limit1, thresh1);
+ ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
+ thresh0, blimit1, limit1, thresh1));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ err_count += ref_s[j] != s[j];
+ }
+ if (err_count && !err_count_total) {
+ first_failure = i;
+ }
+ err_count_total += err_count;
+ }
+ EXPECT_EQ(0, err_count_total)
+ << "Error: Loop8Test9Param, C output doesn't match SSE2 "
+ "loopfilter output. "
+ << "First failed at test case " << first_failure;
+}
+
+TEST_P(Loop8Test9Param, ValueCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = number_of_iterations;
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, s[kNumCoeffs]);
+ DECLARE_ALIGNED(PIXEL_WIDTH, Pixel, ref_s[kNumCoeffs]);
+ int err_count_total = 0;
+ int first_failure = -1;
+ for (int i = 0; i < count_test_block; ++i) {
+ int err_count = 0;
+ uint8_t tmp = GetOuterThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ blimit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetInnerThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ limit0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetHevThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ thresh0[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetOuterThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ blimit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetInnerThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ limit1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ tmp = GetHevThresh(&rnd);
+ DECLARE_ALIGNED(16, const uint8_t,
+ thresh1[16]) = { tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+ tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp };
+ int32_t p = kNumCoeffs / 32; // TODO(pdlf) can we have non-square here?
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ s[j] = rnd.Rand16() & mask_;
+ ref_s[j] = s[j];
+ }
+#if CONFIG_VP9_HIGHBITDEPTH
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
+ limit1, thresh1, bit_depth_);
+ ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
+ thresh0, blimit1, limit1, thresh1,
+ bit_depth_));
+#else
+ ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0, blimit1,
+ limit1, thresh1);
+ ASM_REGISTER_STATE_CHECK(loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
+ thresh0, blimit1, limit1, thresh1));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+ for (int j = 0; j < kNumCoeffs; ++j) {
+ err_count += ref_s[j] != s[j];
+ }
+ if (err_count && !err_count_total) {
+ first_failure = i;
+ }
+ err_count_total += err_count;
+ }
+ EXPECT_EQ(0, err_count_total)
+ << "Error: Loop8Test9Param, C output doesn't match SSE2"
+ "loopfilter output. "
+ << "First failed at test case " << first_failure;
+}
+#endif // HAVE_NEON || HAVE_SSE2 || (HAVE_DSPR2 || HAVE_MSA &&
+ // (!CONFIG_VP9_HIGHBITDEPTH)) || (HAVE_LSX &&
+ // (!CONFIG_VP9_HIGHBITDEPTH))
+
+using std::make_tuple;
+
+#if HAVE_SSE2
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Loop8Test6Param,
+ ::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
+ &vpx_highbd_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
+ &vpx_highbd_lpf_vertical_4_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
+ &vpx_highbd_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
+ &vpx_highbd_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_dual_sse2,
+ &vpx_highbd_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
+ &vpx_highbd_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
+ &vpx_highbd_lpf_vertical_16_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
+ &vpx_highbd_lpf_horizontal_4_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
+ &vpx_highbd_lpf_vertical_4_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
+ &vpx_highbd_lpf_horizontal_8_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
+ &vpx_highbd_lpf_horizontal_16_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_dual_sse2,
+ &vpx_highbd_lpf_horizontal_16_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
+ &vpx_highbd_lpf_vertical_8_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
+ &vpx_highbd_lpf_vertical_16_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
+ &vpx_highbd_lpf_horizontal_4_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
+ &vpx_highbd_lpf_vertical_4_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
+ &vpx_highbd_lpf_horizontal_8_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_sse2,
+ &vpx_highbd_lpf_horizontal_16_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_dual_sse2,
+ &vpx_highbd_lpf_horizontal_16_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
+ &vpx_highbd_lpf_vertical_8_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
+ &vpx_highbd_lpf_vertical_16_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
+ &vpx_highbd_lpf_vertical_16_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
+ &vpx_highbd_lpf_vertical_16_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
+ &vpx_highbd_lpf_vertical_16_dual_c, 12)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Loop8Test6Param,
+ ::testing::Values(
+ make_tuple(&vpx_lpf_horizontal_4_sse2, &vpx_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_sse2, &vpx_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_sse2, &vpx_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dual_sse2,
+ &vpx_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_sse2, &vpx_lpf_vertical_4_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_sse2, &vpx_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_sse2, &vpx_lpf_vertical_16_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_dual_sse2, &vpx_lpf_vertical_16_dual_c,
+ 8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif
+
+#if HAVE_AVX2 && (!CONFIG_VP9_HIGHBITDEPTH)
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, Loop8Test6Param,
+ ::testing::Values(make_tuple(&vpx_lpf_horizontal_16_avx2,
+ &vpx_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dual_avx2,
+ &vpx_lpf_horizontal_16_dual_c, 8)));
+#endif
+
+#if HAVE_SSE2
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
+ &vpx_highbd_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
+ &vpx_highbd_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
+ &vpx_highbd_lpf_vertical_4_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
+ &vpx_highbd_lpf_vertical_8_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
+ &vpx_highbd_lpf_horizontal_4_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
+ &vpx_highbd_lpf_horizontal_8_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
+ &vpx_highbd_lpf_vertical_4_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
+ &vpx_highbd_lpf_vertical_8_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
+ &vpx_highbd_lpf_horizontal_4_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
+ &vpx_highbd_lpf_horizontal_8_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
+ &vpx_highbd_lpf_vertical_4_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
+ &vpx_highbd_lpf_vertical_8_dual_c, 12)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_sse2,
+ &vpx_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_dual_sse2,
+ &vpx_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_dual_sse2,
+ &vpx_lpf_vertical_4_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_dual_sse2,
+ &vpx_lpf_vertical_8_dual_c, 8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif
+
+#if HAVE_NEON
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Loop8Test6Param,
+ ::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_neon,
+ &vpx_highbd_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_neon,
+ &vpx_highbd_lpf_horizontal_4_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_neon,
+ &vpx_highbd_lpf_horizontal_4_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_neon,
+ &vpx_highbd_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_neon,
+ &vpx_highbd_lpf_horizontal_8_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_neon,
+ &vpx_highbd_lpf_horizontal_8_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_neon,
+ &vpx_highbd_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_neon,
+ &vpx_highbd_lpf_horizontal_16_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_neon,
+ &vpx_highbd_lpf_horizontal_16_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_dual_neon,
+ &vpx_highbd_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_dual_neon,
+ &vpx_highbd_lpf_horizontal_16_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_16_dual_neon,
+ &vpx_highbd_lpf_horizontal_16_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_4_neon,
+ &vpx_highbd_lpf_vertical_4_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_4_neon,
+ &vpx_highbd_lpf_vertical_4_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_4_neon,
+ &vpx_highbd_lpf_vertical_4_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_8_neon,
+ &vpx_highbd_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_8_neon,
+ &vpx_highbd_lpf_vertical_8_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_8_neon,
+ &vpx_highbd_lpf_vertical_8_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_16_neon,
+ &vpx_highbd_lpf_vertical_16_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_16_neon,
+ &vpx_highbd_lpf_vertical_16_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_16_neon,
+ &vpx_highbd_lpf_vertical_16_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_16_dual_neon,
+ &vpx_highbd_lpf_vertical_16_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_16_dual_neon,
+ &vpx_highbd_lpf_vertical_16_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_16_dual_neon,
+ &vpx_highbd_lpf_vertical_16_dual_c, 12)));
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_highbd_lpf_horizontal_4_dual_neon,
+ &vpx_highbd_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_dual_neon,
+ &vpx_highbd_lpf_horizontal_4_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_4_dual_neon,
+ &vpx_highbd_lpf_horizontal_4_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_dual_neon,
+ &vpx_highbd_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_dual_neon,
+ &vpx_highbd_lpf_horizontal_8_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_horizontal_8_dual_neon,
+ &vpx_highbd_lpf_horizontal_8_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_4_dual_neon,
+ &vpx_highbd_lpf_vertical_4_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_4_dual_neon,
+ &vpx_highbd_lpf_vertical_4_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_4_dual_neon,
+ &vpx_highbd_lpf_vertical_4_dual_c, 12),
+ make_tuple(&vpx_highbd_lpf_vertical_8_dual_neon,
+ &vpx_highbd_lpf_vertical_8_dual_c, 8),
+ make_tuple(&vpx_highbd_lpf_vertical_8_dual_neon,
+ &vpx_highbd_lpf_vertical_8_dual_c, 10),
+ make_tuple(&vpx_highbd_lpf_vertical_8_dual_neon,
+ &vpx_highbd_lpf_vertical_8_dual_c, 12)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Loop8Test6Param,
+ ::testing::Values(
+ make_tuple(&vpx_lpf_horizontal_16_neon, &vpx_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dual_neon,
+ &vpx_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_neon, &vpx_lpf_vertical_16_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_dual_neon, &vpx_lpf_vertical_16_dual_c,
+ 8),
+ make_tuple(&vpx_lpf_horizontal_8_neon, &vpx_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_neon, &vpx_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_lpf_horizontal_4_neon, &vpx_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_neon, &vpx_lpf_vertical_4_c, 8)));
+INSTANTIATE_TEST_SUITE_P(
+ NEON, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_lpf_horizontal_8_dual_neon,
+ &vpx_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_dual_neon,
+ &vpx_lpf_vertical_8_dual_c, 8),
+ make_tuple(&vpx_lpf_horizontal_4_dual_neon,
+ &vpx_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_dual_neon,
+ &vpx_lpf_vertical_4_dual_c, 8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_NEON
+
+#if HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ DSPR2, Loop8Test6Param,
+ ::testing::Values(
+ make_tuple(&vpx_lpf_horizontal_4_dspr2, &vpx_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_dspr2, &vpx_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dspr2, &vpx_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dual_dspr2,
+ &vpx_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_dspr2, &vpx_lpf_vertical_4_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_dspr2, &vpx_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_dspr2, &vpx_lpf_vertical_16_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_dual_dspr2, &vpx_lpf_vertical_16_dual_c,
+ 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ DSPR2, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_dspr2,
+ &vpx_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_dual_dspr2,
+ &vpx_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_dual_dspr2,
+ &vpx_lpf_vertical_4_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_dual_dspr2,
+ &vpx_lpf_vertical_8_dual_c, 8)));
+#endif // HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
+INSTANTIATE_TEST_SUITE_P(
+ MSA, Loop8Test6Param,
+ ::testing::Values(
+ make_tuple(&vpx_lpf_horizontal_4_msa, &vpx_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_msa, &vpx_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_msa, &vpx_lpf_horizontal_16_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dual_msa,
+ &vpx_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_msa, &vpx_lpf_vertical_4_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_msa, &vpx_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_msa, &vpx_lpf_vertical_16_c, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_msa,
+ &vpx_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_dual_msa,
+ &vpx_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_dual_msa,
+ &vpx_lpf_vertical_4_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_dual_msa,
+ &vpx_lpf_vertical_8_dual_c, 8)));
+#endif // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
+
+#if HAVE_LSX && (!CONFIG_VP9_HIGHBITDEPTH)
+INSTANTIATE_TEST_SUITE_P(
+ LSX, Loop8Test6Param,
+ ::testing::Values(
+ make_tuple(&vpx_lpf_horizontal_4_lsx, &vpx_lpf_horizontal_4_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_lsx, &vpx_lpf_horizontal_8_c, 8),
+ make_tuple(&vpx_lpf_horizontal_16_dual_lsx,
+ &vpx_lpf_horizontal_16_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_lsx, &vpx_lpf_vertical_4_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_lsx, &vpx_lpf_vertical_8_c, 8),
+ make_tuple(&vpx_lpf_vertical_16_dual_lsx, &vpx_lpf_vertical_16_dual_c,
+ 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ LSX, Loop8Test9Param,
+ ::testing::Values(make_tuple(&vpx_lpf_horizontal_4_dual_lsx,
+ &vpx_lpf_horizontal_4_dual_c, 8),
+ make_tuple(&vpx_lpf_horizontal_8_dual_lsx,
+ &vpx_lpf_horizontal_8_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_4_dual_lsx,
+ &vpx_lpf_vertical_4_dual_c, 8),
+ make_tuple(&vpx_lpf_vertical_8_dual_lsx,
+ &vpx_lpf_vertical_8_dual_c, 8)));
+#endif // HAVE_LSX && (!CONFIG_VP9_HIGHBITDEPTH)
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/md5_helper.h b/media/libvpx/libvpx/test/md5_helper.h
new file mode 100644
index 0000000000..9095d96a8a
--- /dev/null
+++ b/media/libvpx/libvpx/test/md5_helper.h
@@ -0,0 +1,75 @@
+/*
+ * 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 VPX_TEST_MD5_HELPER_H_
+#define VPX_TEST_MD5_HELPER_H_
+
+#include "./md5_utils.h"
+#include "vpx/vpx_decoder.h"
+
+namespace libvpx_test {
+class MD5 {
+ public:
+ MD5() { MD5Init(&md5_); }
+
+ void Add(const vpx_image_t *img) {
+ for (int plane = 0; plane < 3; ++plane) {
+ const uint8_t *buf = img->planes[plane];
+ // Calculate the width and height to do the md5 check. For the chroma
+ // plane, we never want to round down and thus skip a pixel so if
+ // we are shifting by 1 (chroma_shift) we add 1 before doing the shift.
+ // This works only for chroma_shift of 0 and 1.
+ const int bytes_per_sample =
+ (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
+ const int h =
+ plane ? (img->d_h + img->y_chroma_shift) >> img->y_chroma_shift
+ : img->d_h;
+ const int w =
+ (plane ? (img->d_w + img->x_chroma_shift) >> img->x_chroma_shift
+ : img->d_w) *
+ bytes_per_sample;
+
+ for (int y = 0; y < h; ++y) {
+ MD5Update(&md5_, buf, w);
+ buf += img->stride[plane];
+ }
+ }
+ }
+
+ void Add(const uint8_t *data, size_t size) {
+ MD5Update(&md5_, data, static_cast<uint32_t>(size));
+ }
+
+ const char *Get() {
+ static const char hex[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+ };
+ uint8_t tmp[16];
+ MD5Context ctx_tmp = md5_;
+
+ MD5Final(tmp, &ctx_tmp);
+ for (int i = 0; i < 16; i++) {
+ res_[i * 2 + 0] = hex[tmp[i] >> 4];
+ res_[i * 2 + 1] = hex[tmp[i] & 0xf];
+ }
+ res_[32] = 0;
+
+ return res_;
+ }
+
+ protected:
+ char res_[33];
+ MD5Context md5_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_MD5_HELPER_H_
diff --git a/media/libvpx/libvpx/test/minmax_test.cc b/media/libvpx/libvpx/test/minmax_test.cc
new file mode 100644
index 0000000000..e710af6991
--- /dev/null
+++ b/media/libvpx/libvpx/test/minmax_test.cc
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2016 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 <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+#include "test/acm_random.h"
+#include "test/register_state_check.h"
+
+namespace {
+
+using ::libvpx_test::ACMRandom;
+
+typedef void (*MinMaxFunc)(const uint8_t *a, int a_stride, const uint8_t *b,
+ int b_stride, int *min, int *max);
+
+class MinMaxTest : public ::testing::TestWithParam<MinMaxFunc> {
+ public:
+ virtual void SetUp() {
+ mm_func_ = GetParam();
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ protected:
+ MinMaxFunc mm_func_;
+ ACMRandom rnd_;
+};
+
+void reference_minmax(const uint8_t *a, int a_stride, const uint8_t *b,
+ int b_stride, int *min_ret, int *max_ret) {
+ int min = 255;
+ int max = 0;
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ const int diff = abs(a[i * a_stride + j] - b[i * b_stride + j]);
+ if (min > diff) min = diff;
+ if (max < diff) max = diff;
+ }
+ }
+
+ *min_ret = min;
+ *max_ret = max;
+}
+
+TEST_P(MinMaxTest, MinValue) {
+ for (int i = 0; i < 64; i++) {
+ uint8_t a[64], b[64];
+ memset(a, 0, sizeof(a));
+ memset(b, 255, sizeof(b));
+ b[i] = i; // Set a minimum difference of i.
+
+ int min, max;
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+ EXPECT_EQ(255, max);
+ EXPECT_EQ(i, min);
+ }
+}
+
+TEST_P(MinMaxTest, MaxValue) {
+ for (int i = 0; i < 64; i++) {
+ uint8_t a[64], b[64];
+ memset(a, 0, sizeof(a));
+ memset(b, 0, sizeof(b));
+ b[i] = i; // Set a maximum difference of i.
+
+ int min, max;
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+ EXPECT_EQ(i, max);
+ EXPECT_EQ(0, min);
+ }
+}
+
+TEST_P(MinMaxTest, CompareReference) {
+ uint8_t a[64], b[64];
+ for (int j = 0; j < 64; j++) {
+ a[j] = rnd_.Rand8();
+ b[j] = rnd_.Rand8();
+ }
+
+ int min_ref, max_ref, min, max;
+ reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+ EXPECT_EQ(max_ref, max);
+ EXPECT_EQ(min_ref, min);
+}
+
+TEST_P(MinMaxTest, CompareReferenceAndVaryStride) {
+ uint8_t a[8 * 64], b[8 * 64];
+ for (int i = 0; i < 8 * 64; i++) {
+ a[i] = rnd_.Rand8();
+ b[i] = rnd_.Rand8();
+ }
+ for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
+ for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
+ int min_ref, max_ref, min, max;
+ reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
+ EXPECT_EQ(max_ref, max)
+ << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
+ EXPECT_EQ(min_ref, min)
+ << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
+ }
+ }
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+
+using HBDMinMaxTest = MinMaxTest;
+
+void highbd_reference_minmax(const uint8_t *a, int a_stride, const uint8_t *b,
+ int b_stride, int *min_ret, int *max_ret) {
+ int min = 65535;
+ int max = 0;
+ const uint16_t *a_ptr = CONVERT_TO_SHORTPTR(a);
+ const uint16_t *b_ptr = CONVERT_TO_SHORTPTR(b);
+ for (int i = 0; i < 8; i++) {
+ for (int j = 0; j < 8; j++) {
+ const int diff = abs(a_ptr[i * a_stride + j] - b_ptr[i * b_stride + j]);
+ if (min > diff) min = diff;
+ if (max < diff) max = diff;
+ }
+ }
+
+ *min_ret = min;
+ *max_ret = max;
+}
+
+TEST_P(HBDMinMaxTest, MinValue) {
+ uint8_t *a = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
+ uint8_t *b = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
+ for (int i = 0; i < 64; i++) {
+ vpx_memset16(CONVERT_TO_SHORTPTR(a), 0, 64);
+ vpx_memset16(CONVERT_TO_SHORTPTR(b), 65535, 64);
+ CONVERT_TO_SHORTPTR(b)[i] = i; // Set a minimum difference of i.
+
+ int min, max;
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+ EXPECT_EQ(65535, max);
+ EXPECT_EQ(i, min);
+ }
+ vpx_free(CONVERT_TO_SHORTPTR(a));
+ vpx_free(CONVERT_TO_SHORTPTR(b));
+}
+
+TEST_P(HBDMinMaxTest, MaxValue) {
+ uint8_t *a = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
+ uint8_t *b = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
+ for (int i = 0; i < 64; i++) {
+ vpx_memset16(CONVERT_TO_SHORTPTR(a), 0, 64);
+ vpx_memset16(CONVERT_TO_SHORTPTR(b), 0, 64);
+ CONVERT_TO_SHORTPTR(b)[i] = i; // Set a minimum difference of i.
+
+ int min, max;
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+ EXPECT_EQ(i, max);
+ EXPECT_EQ(0, min);
+ }
+ vpx_free(CONVERT_TO_SHORTPTR(a));
+ vpx_free(CONVERT_TO_SHORTPTR(b));
+}
+
+TEST_P(HBDMinMaxTest, CompareReference) {
+ uint8_t *a = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
+ uint8_t *b = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc(64 * sizeof(uint16_t))));
+ for (int j = 0; j < 64; j++) {
+ CONVERT_TO_SHORTPTR(a)[j] = rnd_.Rand16();
+ CONVERT_TO_SHORTPTR(b)[j] = rnd_.Rand16();
+ }
+
+ int min_ref, max_ref, min, max;
+ highbd_reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+ vpx_free(CONVERT_TO_SHORTPTR(a));
+ vpx_free(CONVERT_TO_SHORTPTR(b));
+ EXPECT_EQ(max_ref, max);
+ EXPECT_EQ(min_ref, min);
+}
+
+TEST_P(HBDMinMaxTest, CompareReferenceAndVaryStride) {
+ uint8_t *a = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc((8 * 64) * sizeof(uint16_t))));
+ uint8_t *b = CONVERT_TO_BYTEPTR(
+ reinterpret_cast<uint16_t *>(vpx_malloc((8 * 64) * sizeof(uint16_t))));
+ for (int i = 0; i < 8 * 64; i++) {
+ CONVERT_TO_SHORTPTR(a)[i] = rnd_.Rand16();
+ CONVERT_TO_SHORTPTR(b)[i] = rnd_.Rand16();
+ }
+ for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
+ for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
+ int min_ref, max_ref, min, max;
+ highbd_reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
+ ASM_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
+ EXPECT_EQ(max_ref, max)
+ << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
+ EXPECT_EQ(min_ref, min)
+ << "when a_stride = " << a_stride << " and b_stride = " << b_stride;
+ }
+ }
+ vpx_free(CONVERT_TO_SHORTPTR(a));
+ vpx_free(CONVERT_TO_SHORTPTR(b));
+}
+#endif
+
+INSTANTIATE_TEST_SUITE_P(C, MinMaxTest, ::testing::Values(&vpx_minmax_8x8_c));
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(C, HBDMinMaxTest,
+ ::testing::Values(&vpx_highbd_minmax_8x8_c));
+#endif
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(SSE2, MinMaxTest,
+ ::testing::Values(&vpx_minmax_8x8_sse2));
+#endif
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, MinMaxTest,
+ ::testing::Values(&vpx_minmax_8x8_neon));
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(NEON, HBDMinMaxTest,
+ ::testing::Values(&vpx_highbd_minmax_8x8_neon));
+#endif
+#endif
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(MSA, MinMaxTest,
+ ::testing::Values(&vpx_minmax_8x8_msa));
+#endif
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/non_greedy_mv_test.cc b/media/libvpx/libvpx/test/non_greedy_mv_test.cc
new file mode 100644
index 0000000000..927029de45
--- /dev/null
+++ b/media/libvpx/libvpx/test/non_greedy_mv_test.cc
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2019 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 <math.h>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vp9/encoder/vp9_non_greedy_mv.h"
+#include "./vpx_dsp_rtcd.h"
+
+namespace {
+
+static void read_in_mf(const char *filename, int *rows_ptr, int *cols_ptr,
+ MV **buffer_ptr) {
+ FILE *input = fopen(filename, "rb");
+ int row, col;
+ int idx;
+
+ ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl;
+
+ fscanf(input, "%d,%d\n", rows_ptr, cols_ptr);
+
+ *buffer_ptr = (MV *)malloc((*rows_ptr) * (*cols_ptr) * sizeof(MV));
+
+ for (idx = 0; idx < (*rows_ptr) * (*cols_ptr); ++idx) {
+ fscanf(input, "%d,%d;", &row, &col);
+ (*buffer_ptr)[idx].row = row;
+ (*buffer_ptr)[idx].col = col;
+ }
+ fclose(input);
+}
+
+static void read_in_local_var(const char *filename, int *rows_ptr,
+ int *cols_ptr,
+ int (**M_ptr)[MF_LOCAL_STRUCTURE_SIZE]) {
+ FILE *input = fopen(filename, "rb");
+ int M00, M01, M10, M11;
+ int idx;
+ int int_type;
+
+ ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl;
+
+ fscanf(input, "%d,%d\n", rows_ptr, cols_ptr);
+
+ *M_ptr = (int(*)[MF_LOCAL_STRUCTURE_SIZE])malloc(
+ (*rows_ptr) * (*cols_ptr) * MF_LOCAL_STRUCTURE_SIZE * sizeof(int_type));
+
+ for (idx = 0; idx < (*rows_ptr) * (*cols_ptr); ++idx) {
+ fscanf(input, "%d,%d,%d,%d;", &M00, &M01, &M10, &M11);
+ (*M_ptr)[idx][0] = M00;
+ (*M_ptr)[idx][1] = M01;
+ (*M_ptr)[idx][2] = M10;
+ (*M_ptr)[idx][3] = M11;
+ }
+ fclose(input);
+}
+
+static void compare_mf(const MV *mf1, const MV *mf2, int rows, int cols,
+ float *mean_ptr, float *std_ptr) {
+ float float_type;
+ float *diffs = (float *)malloc(rows * cols * sizeof(float_type));
+ int idx;
+ float accu = 0.0f;
+ for (idx = 0; idx < rows * cols; ++idx) {
+ MV mv1 = mf1[idx];
+ MV mv2 = mf2[idx];
+ float row_diff2 = (float)((mv1.row - mv2.row) * (mv1.row - mv2.row));
+ float col_diff2 = (float)((mv1.col - mv2.col) * (mv1.col - mv2.col));
+ diffs[idx] = sqrt(row_diff2 + col_diff2);
+ accu += diffs[idx];
+ }
+ *mean_ptr = accu / rows / cols;
+ *std_ptr = 0;
+ for (idx = 0; idx < rows * cols; ++idx) {
+ *std_ptr += (diffs[idx] - (*mean_ptr)) * (diffs[idx] - (*mean_ptr));
+ }
+ *std_ptr = sqrt(*std_ptr / rows / cols);
+ free(diffs);
+}
+
+static void load_frame_info(const char *filename,
+ YV12_BUFFER_CONFIG *ref_frame_ptr) {
+ FILE *input = fopen(filename, "rb");
+ int idx;
+ uint8_t data_type;
+
+ ASSERT_NE(input, nullptr) << "Cannot open file: " << filename << std::endl;
+
+ fscanf(input, "%d,%d\n", &(ref_frame_ptr->y_height),
+ &(ref_frame_ptr->y_width));
+
+ ref_frame_ptr->y_buffer = (uint8_t *)malloc(
+ (ref_frame_ptr->y_width) * (ref_frame_ptr->y_height) * sizeof(data_type));
+
+ for (idx = 0; idx < (ref_frame_ptr->y_width) * (ref_frame_ptr->y_height);
+ ++idx) {
+ int value;
+ fscanf(input, "%d,", &value);
+ ref_frame_ptr->y_buffer[idx] = (uint8_t)value;
+ }
+
+ ref_frame_ptr->y_stride = ref_frame_ptr->y_width;
+ fclose(input);
+}
+
+static int compare_local_var(const int (*local_var1)[MF_LOCAL_STRUCTURE_SIZE],
+ const int (*local_var2)[MF_LOCAL_STRUCTURE_SIZE],
+ int rows, int cols) {
+ int diff = 0;
+ int outter_idx, inner_idx;
+ for (outter_idx = 0; outter_idx < rows * cols; ++outter_idx) {
+ for (inner_idx = 0; inner_idx < MF_LOCAL_STRUCTURE_SIZE; ++inner_idx) {
+ diff += abs(local_var1[outter_idx][inner_idx] -
+ local_var2[outter_idx][inner_idx]);
+ }
+ }
+ return diff / rows / cols;
+}
+
+TEST(non_greedy_mv, smooth_mf) {
+ const char *search_mf_file = "non_greedy_mv_test_files/exhaust_16x16.txt";
+ const char *local_var_file = "non_greedy_mv_test_files/localVar_16x16.txt";
+ const char *estimation_file = "non_greedy_mv_test_files/estimation_16x16.txt";
+ const char *ground_truth_file =
+ "non_greedy_mv_test_files/ground_truth_16x16.txt";
+ BLOCK_SIZE bsize = BLOCK_32X32;
+ MV *search_mf = nullptr;
+ MV *smooth_mf = nullptr;
+ MV *estimation = nullptr;
+ MV *ground_truth = nullptr;
+ int(*local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr;
+ int rows = 0, cols = 0;
+
+ int alpha = 100, max_iter = 100;
+
+ read_in_mf(search_mf_file, &rows, &cols, &search_mf);
+ read_in_local_var(local_var_file, &rows, &cols, &local_var);
+ read_in_mf(estimation_file, &rows, &cols, &estimation);
+ read_in_mf(ground_truth_file, &rows, &cols, &ground_truth);
+
+ float sm_mean, sm_std;
+ float est_mean, est_std;
+
+ smooth_mf = (MV *)malloc(rows * cols * sizeof(MV));
+ vp9_get_smooth_motion_field(search_mf, local_var, rows, cols, bsize, alpha,
+ max_iter, smooth_mf);
+
+ compare_mf(smooth_mf, ground_truth, rows, cols, &sm_mean, &sm_std);
+ compare_mf(smooth_mf, estimation, rows, cols, &est_mean, &est_std);
+
+ EXPECT_LE(sm_mean, 3);
+ EXPECT_LE(est_mean, 2);
+
+ free(search_mf);
+ free(local_var);
+ free(estimation);
+ free(ground_truth);
+ free(smooth_mf);
+}
+
+TEST(non_greedy_mv, local_var) {
+ const char *ref_frame_file = "non_greedy_mv_test_files/ref_frame_16x16.txt";
+ const char *cur_frame_file = "non_greedy_mv_test_files/cur_frame_16x16.txt";
+ const char *gt_local_var_file = "non_greedy_mv_test_files/localVar_16x16.txt";
+ const char *search_mf_file = "non_greedy_mv_test_files/exhaust_16x16.txt";
+ BLOCK_SIZE bsize = BLOCK_16X16;
+ int(*gt_local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr;
+ int(*est_local_var)[MF_LOCAL_STRUCTURE_SIZE] = nullptr;
+ YV12_BUFFER_CONFIG ref_frame, cur_frame;
+ int rows, cols;
+ MV *search_mf;
+ int int_type;
+ int local_var_diff;
+ vp9_variance_fn_ptr_t fn;
+
+ load_frame_info(ref_frame_file, &ref_frame);
+ load_frame_info(cur_frame_file, &cur_frame);
+ read_in_mf(search_mf_file, &rows, &cols, &search_mf);
+
+ fn.sdf = vpx_sad16x16;
+ est_local_var = (int(*)[MF_LOCAL_STRUCTURE_SIZE])malloc(
+ rows * cols * MF_LOCAL_STRUCTURE_SIZE * sizeof(int_type));
+ vp9_get_local_structure(&cur_frame, &ref_frame, search_mf, &fn, rows, cols,
+ bsize, est_local_var);
+ read_in_local_var(gt_local_var_file, &rows, &cols, &gt_local_var);
+
+ local_var_diff = compare_local_var(est_local_var, gt_local_var, rows, cols);
+
+ EXPECT_LE(local_var_diff, 1);
+
+ free(gt_local_var);
+ free(est_local_var);
+ free(ref_frame.y_buffer);
+}
+} // namespace
diff --git a/media/libvpx/libvpx/test/partial_idct_test.cc b/media/libvpx/libvpx/test/partial_idct_test.cc
new file mode 100644
index 0000000000..7eb888a586
--- /dev/null
+++ b/media/libvpx/libvpx/test/partial_idct_test.cc
@@ -0,0 +1,973 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_blockd.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/vpx_timer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*InvTxfmWithBdFunc)(const tran_low_t *in, uint8_t *out,
+ int stride, int bd);
+
+template <InvTxfmFunc fn>
+void wrapper(const tran_low_t *in, uint8_t *out, int stride, int bd) {
+ (void)bd;
+ fn(in, out, stride);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+typedef void (*InvTxfmHighbdFunc)(const tran_low_t *in, uint16_t *out,
+ int stride, int bd);
+template <InvTxfmHighbdFunc fn>
+void highbd_wrapper(const tran_low_t *in, uint8_t *out, int stride, int bd) {
+ fn(in, CAST_TO_SHORTPTR(out), stride, bd);
+}
+#endif
+
+typedef std::tuple<FwdTxfmFunc, InvTxfmWithBdFunc, InvTxfmWithBdFunc, TX_SIZE,
+ int, int, int>
+ PartialInvTxfmParam;
+const int kMaxNumCoeffs = 1024;
+const int kCountTestBlock = 1000;
+
+class PartialIDctTest : public ::testing::TestWithParam<PartialInvTxfmParam> {
+ public:
+ virtual ~PartialIDctTest() {}
+ virtual void SetUp() {
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ fwd_txfm_ = GET_PARAM(0);
+ full_inv_txfm_ = GET_PARAM(1);
+ partial_inv_txfm_ = GET_PARAM(2);
+ tx_size_ = GET_PARAM(3);
+ last_nonzero_ = GET_PARAM(4);
+ bit_depth_ = GET_PARAM(5);
+ pixel_size_ = GET_PARAM(6);
+ mask_ = (1 << bit_depth_) - 1;
+
+ switch (tx_size_) {
+ case TX_4X4: size_ = 4; break;
+ case TX_8X8: size_ = 8; break;
+ case TX_16X16: size_ = 16; break;
+ case TX_32X32: size_ = 32; break;
+ default: FAIL() << "Wrong Size!"; break;
+ }
+
+ // Randomize stride_ to a value less than or equal to 1024
+ stride_ = rnd_(1024) + 1;
+ if (stride_ < size_) {
+ stride_ = size_;
+ }
+ // Align stride_ to 16 if it's bigger than 16.
+ if (stride_ > 16) {
+ stride_ &= ~15;
+ }
+
+ input_block_size_ = size_ * size_;
+ output_block_size_ = size_ * stride_;
+
+ input_block_ = reinterpret_cast<tran_low_t *>(
+ vpx_memalign(16, sizeof(*input_block_) * input_block_size_));
+ output_block_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(16, pixel_size_ * output_block_size_));
+ output_block_ref_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(16, pixel_size_ * output_block_size_));
+ }
+
+ virtual void TearDown() {
+ vpx_free(input_block_);
+ input_block_ = nullptr;
+ vpx_free(output_block_);
+ output_block_ = nullptr;
+ vpx_free(output_block_ref_);
+ output_block_ref_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ void InitMem() {
+ memset(input_block_, 0, sizeof(*input_block_) * input_block_size_);
+ if (pixel_size_ == 1) {
+ for (int j = 0; j < output_block_size_; ++j) {
+ output_block_[j] = output_block_ref_[j] = rnd_.Rand16() & mask_;
+ }
+ } else {
+ ASSERT_EQ(2, pixel_size_);
+ uint16_t *const output = reinterpret_cast<uint16_t *>(output_block_);
+ uint16_t *const output_ref =
+ reinterpret_cast<uint16_t *>(output_block_ref_);
+ for (int j = 0; j < output_block_size_; ++j) {
+ output[j] = output_ref[j] = rnd_.Rand16() & mask_;
+ }
+ }
+ }
+
+ void InitInput() {
+ const int64_t max_coeff = (32766 << (bit_depth_ - 8)) / 4;
+ int64_t max_energy_leftover = max_coeff * max_coeff;
+ for (int j = 0; j < last_nonzero_; ++j) {
+ tran_low_t coeff = static_cast<tran_low_t>(
+ sqrt(1.0 * max_energy_leftover) * (rnd_.Rand16() - 32768) / 65536);
+ max_energy_leftover -= static_cast<int64_t>(coeff) * coeff;
+ if (max_energy_leftover < 0) {
+ max_energy_leftover = 0;
+ coeff = 0;
+ }
+ input_block_[vp9_default_scan_orders[tx_size_].scan[j]] = coeff;
+ }
+ }
+
+ void PrintDiff() {
+ if (memcmp(output_block_ref_, output_block_,
+ pixel_size_ * output_block_size_)) {
+ uint16_t ref, opt;
+ for (int y = 0; y < size_; y++) {
+ for (int x = 0; x < size_; x++) {
+ if (pixel_size_ == 1) {
+ ref = output_block_ref_[y * stride_ + x];
+ opt = output_block_[y * stride_ + x];
+ } else {
+ ref = reinterpret_cast<uint16_t *>(
+ output_block_ref_)[y * stride_ + x];
+ opt = reinterpret_cast<uint16_t *>(output_block_)[y * stride_ + x];
+ }
+ if (ref != opt) {
+ printf("dest[%d][%d] diff:%6d (ref),%6d (opt)\n", y, x, ref, opt);
+ }
+ }
+ }
+
+ printf("\ninput_block_:\n");
+ for (int y = 0; y < size_; y++) {
+ for (int x = 0; x < size_; x++) {
+ printf("%6d,", input_block_[y * size_ + x]);
+ }
+ printf("\n");
+ }
+ }
+ }
+
+ protected:
+ int last_nonzero_;
+ TX_SIZE tx_size_;
+ tran_low_t *input_block_;
+ uint8_t *output_block_;
+ uint8_t *output_block_ref_;
+ int size_;
+ int stride_;
+ int pixel_size_;
+ int input_block_size_;
+ int output_block_size_;
+ int bit_depth_;
+ int mask_;
+ FwdTxfmFunc fwd_txfm_;
+ InvTxfmWithBdFunc full_inv_txfm_;
+ InvTxfmWithBdFunc partial_inv_txfm_;
+ ACMRandom rnd_;
+};
+
+TEST_P(PartialIDctTest, RunQuantCheck) {
+ const int count_test_block = (size_ != 4) ? kCountTestBlock : 65536;
+ DECLARE_ALIGNED(16, int16_t, input_extreme_block[kMaxNumCoeffs]);
+ DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kMaxNumCoeffs]);
+
+ InitMem();
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-mask_, mask_].
+ if (size_ != 4) {
+ if (i == 0) {
+ for (int k = 0; k < input_block_size_; ++k) {
+ input_extreme_block[k] = mask_;
+ }
+ } else if (i == 1) {
+ for (int k = 0; k < input_block_size_; ++k) {
+ input_extreme_block[k] = -mask_;
+ }
+ } else {
+ for (int k = 0; k < input_block_size_; ++k) {
+ input_extreme_block[k] = rnd_.Rand8() % 2 ? mask_ : -mask_;
+ }
+ }
+ } else {
+ // Try all possible combinations.
+ for (int k = 0; k < input_block_size_; ++k) {
+ input_extreme_block[k] = (i & (1 << k)) ? mask_ : -mask_;
+ }
+ }
+
+ fwd_txfm_(input_extreme_block, output_ref_block, size_);
+
+ // quantization with minimum allowed step sizes
+ input_block_[0] = (output_ref_block[0] / 4) * 4;
+ for (int k = 1; k < last_nonzero_; ++k) {
+ const int pos = vp9_default_scan_orders[tx_size_].scan[k];
+ input_block_[pos] = (output_ref_block[pos] / 4) * 4;
+ }
+
+ ASM_REGISTER_STATE_CHECK(
+ full_inv_txfm_(input_block_, output_block_ref_, stride_, bit_depth_));
+ ASM_REGISTER_STATE_CHECK(
+ partial_inv_txfm_(input_block_, output_block_, stride_, bit_depth_));
+ ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
+ pixel_size_ * output_block_size_))
+ << "Error: partial inverse transform produces different results";
+ }
+}
+
+TEST_P(PartialIDctTest, ResultsMatch) {
+ for (int i = 0; i < kCountTestBlock; ++i) {
+ InitMem();
+ InitInput();
+
+ ASM_REGISTER_STATE_CHECK(
+ full_inv_txfm_(input_block_, output_block_ref_, stride_, bit_depth_));
+ ASM_REGISTER_STATE_CHECK(
+ partial_inv_txfm_(input_block_, output_block_, stride_, bit_depth_));
+ ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
+ pixel_size_ * output_block_size_))
+ << "Error: partial inverse transform produces different results";
+ }
+}
+
+TEST_P(PartialIDctTest, AddOutputBlock) {
+ for (int i = 0; i < kCountTestBlock; ++i) {
+ InitMem();
+ for (int j = 0; j < last_nonzero_; ++j) {
+ input_block_[vp9_default_scan_orders[tx_size_].scan[j]] = 10;
+ }
+
+ ASM_REGISTER_STATE_CHECK(
+ full_inv_txfm_(input_block_, output_block_ref_, stride_, bit_depth_));
+ ASM_REGISTER_STATE_CHECK(
+ partial_inv_txfm_(input_block_, output_block_, stride_, bit_depth_));
+ ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
+ pixel_size_ * output_block_size_))
+ << "Error: Transform results are not correctly added to output.";
+ }
+}
+
+TEST_P(PartialIDctTest, SingleExtremeCoeff) {
+ const int16_t max_coeff = std::numeric_limits<int16_t>::max();
+ const int16_t min_coeff = std::numeric_limits<int16_t>::min();
+ for (int i = 0; i < last_nonzero_; ++i) {
+ memset(input_block_, 0, sizeof(*input_block_) * input_block_size_);
+ // Run once for min and once for max.
+ for (int j = 0; j < 2; ++j) {
+ const int coeff = j ? min_coeff : max_coeff;
+
+ memset(output_block_, 0, pixel_size_ * output_block_size_);
+ memset(output_block_ref_, 0, pixel_size_ * output_block_size_);
+ input_block_[vp9_default_scan_orders[tx_size_].scan[i]] = coeff;
+
+ ASM_REGISTER_STATE_CHECK(
+ full_inv_txfm_(input_block_, output_block_ref_, stride_, bit_depth_));
+ ASM_REGISTER_STATE_CHECK(
+ partial_inv_txfm_(input_block_, output_block_, stride_, bit_depth_));
+ ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
+ pixel_size_ * output_block_size_))
+ << "Error: Fails with single coeff of " << coeff << " at " << i
+ << ".";
+ }
+ }
+}
+
+TEST_P(PartialIDctTest, DISABLED_Speed) {
+ // Keep runtime stable with transform size.
+ const int kCountSpeedTestBlock = 500000000 / input_block_size_;
+ InitMem();
+ InitInput();
+
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ ASM_REGISTER_STATE_CHECK(
+ full_inv_txfm_(input_block_, output_block_ref_, stride_, bit_depth_));
+ }
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ partial_inv_txfm_(input_block_, output_block_, stride_, bit_depth_);
+ }
+ libvpx_test::ClearSystemState();
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+ printf("idct%dx%d_%d (%s %d) time: %5d ms\n", size_, size_, last_nonzero_,
+ (pixel_size_ == 1) ? "bitdepth" : "high bitdepth", bit_depth_,
+ elapsed_time);
+ ASSERT_EQ(0, memcmp(output_block_ref_, output_block_,
+ pixel_size_ * output_block_size_))
+ << "Error: partial inverse transform produces different results";
+}
+
+using std::make_tuple;
+
+const PartialInvTxfmParam c_partial_idct_tests[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>, TX_32X32, 1024, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>, TX_32X32, 1024, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>, TX_32X32, 1024, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>, TX_32X32, 135, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>, TX_32X32, 135, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>, TX_32X32, 135, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>, TX_32X32, 34, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>, TX_32X32, 34, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>, TX_32X32, 34, 12, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>, TX_32X32, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>, TX_32X32, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>, TX_32X32, 1, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>, TX_16X16, 256, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>, TX_16X16, 256, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>, TX_16X16, 256, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>, TX_16X16, 38, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>, TX_16X16, 38, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>, TX_16X16, 38, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>, TX_16X16, 10, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>, TX_16X16, 10, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>, TX_16X16, 10, 12, 2),
+ make_tuple(&vpx_highbd_fdct16x16_c,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>, TX_16X16, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct16x16_c,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>, TX_16X16, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct16x16_c,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>, TX_16X16, 1, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>, TX_8X8, 64, 8, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>, TX_8X8, 64, 10, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>, TX_8X8, 64, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>, TX_8X8, 12, 8, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>, TX_8X8, 12, 10, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>, TX_8X8, 12, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>, TX_8X8, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>, TX_8X8, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>, TX_8X8, 1, 12, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>, TX_4X4, 16, 8, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>, TX_4X4, 16, 10, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>, TX_4X4, 16, 12, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>, TX_4X4, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>, TX_4X4, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>, TX_4X4, 1, 12, 2),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1024_add_c>, TX_32X32, 1024, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_135_add_c>, TX_32X32, 135, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_34_add_c>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1_add_c>, TX_32X32, 1, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_256_add_c>, TX_16X16, 256, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_38_add_c>, TX_16X16, 38, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_10_add_c>, TX_16X16, 10, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_1_add_c>, TX_16X16, 1, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_64_add_c>, TX_8X8, 64, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_12_add_c>, TX_8X8, 12, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_1_add_c>, TX_8X8, 1, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_16_add_c>,
+ &wrapper<vpx_idct4x4_16_add_c>, TX_4X4, 16, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_16_add_c>,
+ &wrapper<vpx_idct4x4_1_add_c>, TX_4X4, 1, 8, 1)
+};
+
+INSTANTIATE_TEST_SUITE_P(C, PartialIDctTest,
+ ::testing::ValuesIn(c_partial_idct_tests));
+
+#if !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_NEON
+const PartialInvTxfmParam neon_partial_idct_tests[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_neon>, TX_32X32,
+ 1024, 8, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_neon>, TX_32X32,
+ 1024, 10, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_neon>, TX_32X32,
+ 1024, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_neon>, TX_32X32, 135, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_neon>, TX_32X32, 135, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_neon>, TX_32X32, 135, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_neon>, TX_32X32, 34, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_neon>, TX_32X32, 34, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_neon>, TX_32X32, 34, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_neon>, TX_32X32, 1, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_neon>, TX_32X32, 1, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_neon>, TX_32X32, 1, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_neon>, TX_16X16, 256, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_neon>, TX_16X16, 256, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_neon>, TX_16X16, 256, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_neon>, TX_16X16, 38, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_neon>, TX_16X16, 38, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_neon>, TX_16X16, 38, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_neon>, TX_16X16, 10, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_neon>, TX_16X16, 10, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_neon>, TX_16X16, 10, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_neon>, TX_16X16, 1, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_neon>, TX_16X16, 1, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_neon>, TX_16X16, 1, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_neon>, TX_8X8, 64, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_neon>, TX_8X8, 64, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_neon>, TX_8X8, 64, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_neon>, TX_8X8, 12, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_neon>, TX_8X8, 12, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_neon>, TX_8X8, 12, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_neon>, TX_8X8, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_neon>, TX_8X8, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_neon>, TX_8X8, 1, 12, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_neon>, TX_4X4, 16, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_neon>, TX_4X4, 16, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_neon>, TX_4X4, 16, 12, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_neon>, TX_4X4, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_neon>, TX_4X4, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_neon>, TX_4X4, 1, 12, 2),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1024_add_neon>, TX_32X32, 1024, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_135_add_c>,
+ &wrapper<vpx_idct32x32_135_add_neon>, TX_32X32, 135, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_34_add_c>,
+ &wrapper<vpx_idct32x32_34_add_neon>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1_add_c>,
+ &wrapper<vpx_idct32x32_1_add_neon>, TX_32X32, 1, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_256_add_neon>, TX_16X16, 256, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_38_add_c>,
+ &wrapper<vpx_idct16x16_38_add_neon>, TX_16X16, 38, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_10_add_c>,
+ &wrapper<vpx_idct16x16_10_add_neon>, TX_16X16, 10, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_1_add_c>,
+ &wrapper<vpx_idct16x16_1_add_neon>, TX_16X16, 1, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_64_add_neon>, TX_8X8, 64, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_12_add_c>,
+ &wrapper<vpx_idct8x8_12_add_neon>, TX_8X8, 12, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_1_add_c>,
+ &wrapper<vpx_idct8x8_1_add_neon>, TX_8X8, 1, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_16_add_c>,
+ &wrapper<vpx_idct4x4_16_add_neon>, TX_4X4, 16, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_1_add_c>,
+ &wrapper<vpx_idct4x4_1_add_neon>, TX_4X4, 1, 8, 1)
+};
+
+INSTANTIATE_TEST_SUITE_P(NEON, PartialIDctTest,
+ ::testing::ValuesIn(neon_partial_idct_tests));
+#endif // HAVE_NEON
+
+#if HAVE_SSE2
+// 32x32_135_ is implemented using the 1024 version.
+const PartialInvTxfmParam sse2_partial_idct_tests[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_sse2>, TX_32X32,
+ 1024, 8, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_sse2>, TX_32X32,
+ 1024, 10, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_sse2>, TX_32X32,
+ 1024, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_sse2>, TX_32X32, 135, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_sse2>, TX_32X32, 135, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_sse2>, TX_32X32, 135, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_sse2>, TX_32X32, 34, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_sse2>, TX_32X32, 34, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_sse2>, TX_32X32, 34, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_sse2>, TX_32X32, 1, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_sse2>, TX_32X32, 1, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1_add_sse2>, TX_32X32, 1, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_sse2>, TX_16X16, 256, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_sse2>, TX_16X16, 256, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_sse2>, TX_16X16, 256, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_sse2>, TX_16X16, 38, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_sse2>, TX_16X16, 38, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_sse2>, TX_16X16, 38, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_sse2>, TX_16X16, 10, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_sse2>, TX_16X16, 10, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_sse2>, TX_16X16, 10, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_sse2>, TX_16X16, 1, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_sse2>, TX_16X16, 1, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_1_add_sse2>, TX_16X16, 1, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_sse2>, TX_8X8, 64, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_sse2>, TX_8X8, 64, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_sse2>, TX_8X8, 64, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_sse2>, TX_8X8, 12, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_sse2>, TX_8X8, 12, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_sse2>, TX_8X8, 12, 12, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_sse2>, TX_8X8, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_sse2>, TX_8X8, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_1_add_sse2>, TX_8X8, 1, 12, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_sse2>, TX_4X4, 16, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_sse2>, TX_4X4, 16, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_sse2>, TX_4X4, 16, 12, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_sse2>, TX_4X4, 1, 8, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_sse2>, TX_4X4, 1, 10, 2),
+ make_tuple(&vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_1_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_1_add_sse2>, TX_4X4, 1, 12, 2),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1024_add_sse2>, TX_32X32, 1024, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_135_add_c>,
+ &wrapper<vpx_idct32x32_135_add_sse2>, TX_32X32, 135, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_34_add_c>,
+ &wrapper<vpx_idct32x32_34_add_sse2>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1_add_c>,
+ &wrapper<vpx_idct32x32_1_add_sse2>, TX_32X32, 1, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_256_add_sse2>, TX_16X16, 256, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_38_add_c>,
+ &wrapper<vpx_idct16x16_38_add_sse2>, TX_16X16, 38, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_10_add_c>,
+ &wrapper<vpx_idct16x16_10_add_sse2>, TX_16X16, 10, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_1_add_c>,
+ &wrapper<vpx_idct16x16_1_add_sse2>, TX_16X16, 1, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_64_add_sse2>, TX_8X8, 64, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_12_add_c>,
+ &wrapper<vpx_idct8x8_12_add_sse2>, TX_8X8, 12, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_1_add_c>,
+ &wrapper<vpx_idct8x8_1_add_sse2>, TX_8X8, 1, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_16_add_c>,
+ &wrapper<vpx_idct4x4_16_add_sse2>, TX_4X4, 16, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_1_add_c>,
+ &wrapper<vpx_idct4x4_1_add_sse2>, TX_4X4, 1, 8, 1)
+};
+
+INSTANTIATE_TEST_SUITE_P(SSE2, PartialIDctTest,
+ ::testing::ValuesIn(sse2_partial_idct_tests));
+
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+const PartialInvTxfmParam ssse3_partial_idct_tests[] = {
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_135_add_c>,
+ &wrapper<vpx_idct32x32_135_add_ssse3>, TX_32X32, 135, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_34_add_c>,
+ &wrapper<vpx_idct32x32_34_add_ssse3>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_12_add_c>,
+ &wrapper<vpx_idct8x8_12_add_ssse3>, TX_8X8, 12, 8, 1)
+};
+
+INSTANTIATE_TEST_SUITE_P(SSSE3, PartialIDctTest,
+ ::testing::ValuesIn(ssse3_partial_idct_tests));
+#endif // HAVE_SSSE3
+
+#if HAVE_SSE4_1 && CONFIG_VP9_HIGHBITDEPTH
+const PartialInvTxfmParam sse4_1_partial_idct_tests[] = {
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_sse4_1>, TX_32X32,
+ 1024, 8, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_sse4_1>, TX_32X32,
+ 1024, 10, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_1024_add_sse4_1>, TX_32X32,
+ 1024, 12, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_sse4_1>, TX_32X32,
+ 135, 8, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_sse4_1>, TX_32X32,
+ 135, 10, 2),
+ make_tuple(&vpx_highbd_fdct32x32_c,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_135_add_sse4_1>, TX_32X32,
+ 135, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_sse4_1>, TX_32X32, 34, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_sse4_1>, TX_32X32, 34, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct32x32_c, &highbd_wrapper<vpx_highbd_idct32x32_34_add_c>,
+ &highbd_wrapper<vpx_highbd_idct32x32_34_add_sse4_1>, TX_32X32, 34, 12, 2),
+ make_tuple(&vpx_highbd_fdct16x16_c,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_sse4_1>, TX_16X16,
+ 256, 8, 2),
+ make_tuple(&vpx_highbd_fdct16x16_c,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_sse4_1>, TX_16X16,
+ 256, 10, 2),
+ make_tuple(&vpx_highbd_fdct16x16_c,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_256_add_sse4_1>, TX_16X16,
+ 256, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_sse4_1>, TX_16X16, 38, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_sse4_1>, TX_16X16, 38, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_38_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_38_add_sse4_1>, TX_16X16, 38, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_sse4_1>, TX_16X16, 10, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_sse4_1>, TX_16X16, 10, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct16x16_c, &highbd_wrapper<vpx_highbd_idct16x16_10_add_c>,
+ &highbd_wrapper<vpx_highbd_idct16x16_10_add_sse4_1>, TX_16X16, 10, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_sse4_1>, TX_8X8, 64, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_sse4_1>, TX_8X8, 64, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_64_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_64_add_sse4_1>, TX_8X8, 64, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_sse4_1>, TX_8X8, 12, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_sse4_1>, TX_8X8, 12, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct8x8_c, &highbd_wrapper<vpx_highbd_idct8x8_12_add_c>,
+ &highbd_wrapper<vpx_highbd_idct8x8_12_add_sse4_1>, TX_8X8, 12, 12, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_sse4_1>, TX_4X4, 16, 8, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_sse4_1>, TX_4X4, 16, 10, 2),
+ make_tuple(
+ &vpx_highbd_fdct4x4_c, &highbd_wrapper<vpx_highbd_idct4x4_16_add_c>,
+ &highbd_wrapper<vpx_highbd_idct4x4_16_add_sse4_1>, TX_4X4, 16, 12, 2)
+};
+
+INSTANTIATE_TEST_SUITE_P(SSE4_1, PartialIDctTest,
+ ::testing::ValuesIn(sse4_1_partial_idct_tests));
+#endif // HAVE_SSE4_1 && CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
+const PartialInvTxfmParam dspr2_partial_idct_tests[] = {
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1024_add_dspr2>, TX_32X32, 1024, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_34_add_c>,
+ &wrapper<vpx_idct32x32_34_add_dspr2>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1_add_c>,
+ &wrapper<vpx_idct32x32_1_add_dspr2>, TX_32X32, 1, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_256_add_dspr2>, TX_16X16, 256, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_10_add_c>,
+ &wrapper<vpx_idct16x16_10_add_dspr2>, TX_16X16, 10, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_1_add_c>,
+ &wrapper<vpx_idct16x16_1_add_dspr2>, TX_16X16, 1, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_64_add_dspr2>, TX_8X8, 64, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_12_add_c>,
+ &wrapper<vpx_idct8x8_12_add_dspr2>, TX_8X8, 12, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_1_add_c>,
+ &wrapper<vpx_idct8x8_1_add_dspr2>, TX_8X8, 1, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_16_add_c>,
+ &wrapper<vpx_idct4x4_16_add_dspr2>, TX_4X4, 16, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_1_add_c>,
+ &wrapper<vpx_idct4x4_1_add_dspr2>, TX_4X4, 1, 8, 1)
+};
+
+INSTANTIATE_TEST_SUITE_P(DSPR2, PartialIDctTest,
+ ::testing::ValuesIn(dspr2_partial_idct_tests));
+#endif // HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
+// 32x32_135_ is implemented using the 1024 version.
+const PartialInvTxfmParam msa_partial_idct_tests[] = {
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1024_add_msa>, TX_32X32, 1024, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_34_add_c>,
+ &wrapper<vpx_idct32x32_34_add_msa>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1_add_c>,
+ &wrapper<vpx_idct32x32_1_add_msa>, TX_32X32, 1, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_256_add_c>,
+ &wrapper<vpx_idct16x16_256_add_msa>, TX_16X16, 256, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_10_add_c>,
+ &wrapper<vpx_idct16x16_10_add_msa>, TX_16X16, 10, 8, 1),
+ make_tuple(&vpx_fdct16x16_c, &wrapper<vpx_idct16x16_1_add_c>,
+ &wrapper<vpx_idct16x16_1_add_msa>, TX_16X16, 1, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_64_add_c>,
+ &wrapper<vpx_idct8x8_64_add_msa>, TX_8X8, 64, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_12_add_c>,
+ &wrapper<vpx_idct8x8_12_add_msa>, TX_8X8, 12, 8, 1),
+ make_tuple(&vpx_fdct8x8_c, &wrapper<vpx_idct8x8_1_add_c>,
+ &wrapper<vpx_idct8x8_1_add_msa>, TX_8X8, 1, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_16_add_c>,
+ &wrapper<vpx_idct4x4_16_add_msa>, TX_4X4, 16, 8, 1),
+ make_tuple(&vpx_fdct4x4_c, &wrapper<vpx_idct4x4_1_add_c>,
+ &wrapper<vpx_idct4x4_1_add_msa>, TX_4X4, 1, 8, 1)
+};
+
+INSTANTIATE_TEST_SUITE_P(MSA, PartialIDctTest,
+ ::testing::ValuesIn(msa_partial_idct_tests));
+#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH
+const PartialInvTxfmParam lsx_partial_idct_tests[] = {
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1024_add_c>,
+ &wrapper<vpx_idct32x32_1024_add_lsx>, TX_32X32, 1024, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_34_add_c>,
+ &wrapper<vpx_idct32x32_34_add_lsx>, TX_32X32, 34, 8, 1),
+ make_tuple(&vpx_fdct32x32_c, &wrapper<vpx_idct32x32_1_add_c>,
+ &wrapper<vpx_idct32x32_1_add_lsx>, TX_32X32, 1, 8, 1),
+};
+
+INSTANTIATE_TEST_SUITE_P(LSX, PartialIDctTest,
+ ::testing::ValuesIn(lsx_partial_idct_tests));
+#endif // HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH
+
+#endif // !CONFIG_EMULATE_HARDWARE
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/postproc.sh b/media/libvpx/libvpx/test/postproc.sh
new file mode 100755
index 0000000000..91ca9b26fe
--- /dev/null
+++ b/media/libvpx/libvpx/test/postproc.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx postproc example code. To add new tests to this
+## file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to postproc_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+# $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+postproc_verify_environment() {
+ if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs postproc using $1 as input file. $2 is the codec name, and is used
+# solely to name the output file.
+postproc() {
+ local decoder="${LIBVPX_BIN_PATH}/postproc${VPX_TEST_EXE_SUFFIX}"
+ local input_file="$1"
+ local codec="$2"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/postproc_${codec}.raw"
+
+ if [ ! -x "${decoder}" ]; then
+ elog "${decoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+postproc_vp8() {
+ if [ "$(vp8_decode_available)" = "yes" ]; then
+ postproc "${VP8_IVF_FILE}" vp8 || return 1
+ fi
+}
+
+postproc_vp9() {
+ if [ "$(vpx_config_option_enabled CONFIG_VP9_POSTPROC)" = "yes" ]; then
+ if [ "$(vp9_decode_available)" = "yes" ]; then
+ postproc "${VP9_IVF_FILE}" vp9 || return 1
+ fi
+ fi
+}
+
+postproc_tests="postproc_vp8
+ postproc_vp9"
+
+run_tests postproc_verify_environment "${postproc_tests}"
diff --git a/media/libvpx/libvpx/test/pp_filter_test.cc b/media/libvpx/libvpx/test/pp_filter_test.cc
new file mode 100644
index 0000000000..27d5ffa907
--- /dev/null
+++ b/media/libvpx/libvpx/test/pp_filter_test.cc
@@ -0,0 +1,575 @@
+/*
+ * 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 <limits.h>
+
+#include <memory>
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/buffer.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+using libvpx_test::ACMRandom;
+using libvpx_test::Buffer;
+
+typedef void (*VpxPostProcDownAndAcrossMbRowFunc)(
+ unsigned char *src_ptr, unsigned char *dst_ptr, int src_pixels_per_line,
+ int dst_pixels_per_line, int cols, unsigned char *flimit, int size);
+
+typedef void (*VpxMbPostProcAcrossIpFunc)(unsigned char *src, int pitch,
+ int rows, int cols, int flimit);
+
+typedef void (*VpxMbPostProcDownFunc)(unsigned char *dst, int pitch, int rows,
+ int cols, int flimit);
+
+namespace {
+// Compute the filter level used in post proc from the loop filter strength
+int q2mbl(int x) {
+ if (x < 20) x = 20;
+
+ x = 50 + (x - 50) * 10 / 8;
+ return x * x / 3;
+}
+
+class VpxPostProcDownAndAcrossMbRowTest
+ : public AbstractBench,
+ public ::testing::TestWithParam<VpxPostProcDownAndAcrossMbRowFunc> {
+ public:
+ VpxPostProcDownAndAcrossMbRowTest()
+ : mb_post_proc_down_and_across_(GetParam()) {}
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ virtual void Run();
+
+ const VpxPostProcDownAndAcrossMbRowFunc mb_post_proc_down_and_across_;
+ // Size of the underlying data block that will be filtered.
+ int block_width_;
+ int block_height_;
+ Buffer<uint8_t> *src_image_;
+ Buffer<uint8_t> *dst_image_;
+ uint8_t *flimits_;
+};
+
+void VpxPostProcDownAndAcrossMbRowTest::Run() {
+ mb_post_proc_down_and_across_(
+ src_image_->TopLeftPixel(), dst_image_->TopLeftPixel(),
+ src_image_->stride(), dst_image_->stride(), block_width_, flimits_, 16);
+}
+
+// Test routine for the VPx post-processing function
+// vpx_post_proc_down_and_across_mb_row_c.
+
+TEST_P(VpxPostProcDownAndAcrossMbRowTest, CheckFilterOutput) {
+ // Size of the underlying data block that will be filtered.
+ block_width_ = 16;
+ block_height_ = 16;
+
+ // 5-tap filter needs 2 padding rows above and below the block in the input.
+ Buffer<uint8_t> src_image = Buffer<uint8_t>(block_width_, block_height_, 2);
+ ASSERT_TRUE(src_image.Init());
+
+ // Filter extends output block by 8 samples at left and right edges.
+ // Though the left padding is only 8 bytes, the assembly code tries to
+ // read 16 bytes before the pointer.
+ Buffer<uint8_t> dst_image =
+ Buffer<uint8_t>(block_width_, block_height_, 8, 16, 8, 8);
+ ASSERT_TRUE(dst_image.Init());
+
+ flimits_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_width_));
+ (void)memset(flimits_, 255, block_width_);
+
+ // Initialize pixels in the input:
+ // block pixels to value 1,
+ // border pixels to value 10.
+ src_image.SetPadding(10);
+ src_image.Set(1);
+
+ // Initialize pixels in the output to 99.
+ dst_image.Set(99);
+
+ ASM_REGISTER_STATE_CHECK(mb_post_proc_down_and_across_(
+ src_image.TopLeftPixel(), dst_image.TopLeftPixel(), src_image.stride(),
+ dst_image.stride(), block_width_, flimits_, 16));
+
+ static const uint8_t kExpectedOutput[] = { 4, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 3, 4 };
+
+ uint8_t *pixel_ptr = dst_image.TopLeftPixel();
+ for (int i = 0; i < block_height_; ++i) {
+ for (int j = 0; j < block_width_; ++j) {
+ ASSERT_EQ(kExpectedOutput[i], pixel_ptr[j])
+ << "at (" << i << ", " << j << ")";
+ }
+ pixel_ptr += dst_image.stride();
+ }
+
+ vpx_free(flimits_);
+}
+
+TEST_P(VpxPostProcDownAndAcrossMbRowTest, CheckCvsAssembly) {
+ // Size of the underlying data block that will be filtered.
+ // Y blocks are always a multiple of 16 wide and exactly 16 high. U and V
+ // blocks are always a multiple of 8 wide and exactly 8 high.
+ block_width_ = 136;
+ block_height_ = 16;
+
+ // 5-tap filter needs 2 padding rows above and below the block in the input.
+ // SSE2 reads in blocks of 16. Pad an extra 8 in case the width is not %16.
+ Buffer<uint8_t> src_image =
+ Buffer<uint8_t>(block_width_, block_height_, 2, 2, 10, 2);
+ ASSERT_TRUE(src_image.Init());
+
+ // Filter extends output block by 8 samples at left and right edges.
+ // Though the left padding is only 8 bytes, there is 'above' padding as well
+ // so when the assembly code tries to read 16 bytes before the pointer it is
+ // not a problem.
+ // SSE2 reads in blocks of 16. Pad an extra 8 in case the width is not %16.
+ Buffer<uint8_t> dst_image =
+ Buffer<uint8_t>(block_width_, block_height_, 8, 8, 16, 8);
+ ASSERT_TRUE(dst_image.Init());
+ Buffer<uint8_t> dst_image_ref =
+ Buffer<uint8_t>(block_width_, block_height_, 8);
+ ASSERT_TRUE(dst_image_ref.Init());
+
+ // Filter values are set in blocks of 16 for Y and 8 for U/V. Each macroblock
+ // can have a different filter. SSE2 assembly reads flimits in blocks of 16 so
+ // it must be padded out.
+ const int flimits_width = block_width_ % 16 ? block_width_ + 8 : block_width_;
+ flimits_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, flimits_width));
+
+ ACMRandom rnd;
+ rnd.Reset(ACMRandom::DeterministicSeed());
+ // Initialize pixels in the input:
+ // block pixels to random values.
+ // border pixels to value 10.
+ src_image.SetPadding(10);
+ src_image.Set(&rnd, &ACMRandom::Rand8);
+
+ for (int blocks = 0; blocks < block_width_; blocks += 8) {
+ (void)memset(flimits_, 0, sizeof(*flimits_) * flimits_width);
+
+ for (int f = 0; f < 255; f++) {
+ (void)memset(flimits_ + blocks, f, sizeof(*flimits_) * 8);
+ dst_image.Set(0);
+ dst_image_ref.Set(0);
+
+ vpx_post_proc_down_and_across_mb_row_c(
+ src_image.TopLeftPixel(), dst_image_ref.TopLeftPixel(),
+ src_image.stride(), dst_image_ref.stride(), block_width_, flimits_,
+ block_height_);
+ ASM_REGISTER_STATE_CHECK(mb_post_proc_down_and_across_(
+ src_image.TopLeftPixel(), dst_image.TopLeftPixel(),
+ src_image.stride(), dst_image.stride(), block_width_, flimits_,
+ block_height_));
+
+ ASSERT_TRUE(dst_image.CheckValues(dst_image_ref));
+ }
+ }
+
+ vpx_free(flimits_);
+}
+
+TEST_P(VpxPostProcDownAndAcrossMbRowTest, DISABLED_Speed) {
+ // Size of the underlying data block that will be filtered.
+ block_width_ = 16;
+ block_height_ = 16;
+
+ // 5-tap filter needs 2 padding rows above and below the block in the input.
+ Buffer<uint8_t> src_image = Buffer<uint8_t>(block_width_, block_height_, 2);
+ ASSERT_TRUE(src_image.Init());
+ this->src_image_ = &src_image;
+
+ // Filter extends output block by 8 samples at left and right edges.
+ // Though the left padding is only 8 bytes, the assembly code tries to
+ // read 16 bytes before the pointer.
+ Buffer<uint8_t> dst_image =
+ Buffer<uint8_t>(block_width_, block_height_, 8, 16, 8, 8);
+ ASSERT_TRUE(dst_image.Init());
+ this->dst_image_ = &dst_image;
+
+ flimits_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_width_));
+ (void)memset(flimits_, 255, block_width_);
+
+ // Initialize pixels in the input:
+ // block pixels to value 1,
+ // border pixels to value 10.
+ src_image.SetPadding(10);
+ src_image.Set(1);
+
+ // Initialize pixels in the output to 99.
+ dst_image.Set(99);
+
+ RunNTimes(INT16_MAX);
+ PrintMedian("16x16");
+
+ vpx_free(flimits_);
+}
+
+class VpxMbPostProcAcrossIpTest
+ : public AbstractBench,
+ public ::testing::TestWithParam<VpxMbPostProcAcrossIpFunc> {
+ public:
+ VpxMbPostProcAcrossIpTest()
+ : rows_(16), cols_(16), mb_post_proc_across_ip_(GetParam()),
+ src_(Buffer<uint8_t>(rows_, cols_, 8, 8, 17, 8)) {}
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ virtual void Run();
+
+ void SetCols(unsigned char *s, int rows, int cols, int src_width) {
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < cols; c++) {
+ s[c] = c;
+ }
+ s += src_width;
+ }
+ }
+
+ void RunComparison(const unsigned char *expected_output, unsigned char *src_c,
+ int rows, int cols, int src_pitch) {
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < cols; c++) {
+ ASSERT_EQ(expected_output[c], src_c[c])
+ << "at (" << r << ", " << c << ")";
+ }
+ src_c += src_pitch;
+ }
+ }
+
+ void RunFilterLevel(unsigned char *s, int rows, int cols, int src_width,
+ int filter_level, const unsigned char *expected_output) {
+ ASM_REGISTER_STATE_CHECK(
+ GetParam()(s, src_width, rows, cols, filter_level));
+ RunComparison(expected_output, s, rows, cols, src_width);
+ }
+
+ const int rows_;
+ const int cols_;
+ const VpxMbPostProcAcrossIpFunc mb_post_proc_across_ip_;
+ Buffer<uint8_t> src_;
+};
+
+void VpxMbPostProcAcrossIpTest::Run() {
+ mb_post_proc_across_ip_(src_.TopLeftPixel(), src_.stride(), rows_, cols_,
+ q2mbl(0));
+}
+
+TEST_P(VpxMbPostProcAcrossIpTest, CheckLowFilterOutput) {
+ ASSERT_TRUE(src_.Init());
+ src_.SetPadding(10);
+ SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
+
+ Buffer<uint8_t> expected_output = Buffer<uint8_t>(cols_, rows_, 0);
+ ASSERT_TRUE(expected_output.Init());
+ SetCols(expected_output.TopLeftPixel(), rows_, cols_,
+ expected_output.stride());
+
+ RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), q2mbl(0),
+ expected_output.TopLeftPixel());
+}
+
+TEST_P(VpxMbPostProcAcrossIpTest, CheckMediumFilterOutput) {
+ ASSERT_TRUE(src_.Init());
+ src_.SetPadding(10);
+ SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
+
+ static const unsigned char kExpectedOutput[] = {
+ 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 13
+ };
+
+ RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), q2mbl(70),
+ kExpectedOutput);
+}
+
+TEST_P(VpxMbPostProcAcrossIpTest, CheckHighFilterOutput) {
+ ASSERT_TRUE(src_.Init());
+ src_.SetPadding(10);
+ SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
+
+ static const unsigned char kExpectedOutput[] = {
+ 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 13
+ };
+
+ RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), INT_MAX,
+ kExpectedOutput);
+
+ SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
+
+ RunFilterLevel(src_.TopLeftPixel(), rows_, cols_, src_.stride(), q2mbl(100),
+ kExpectedOutput);
+}
+
+TEST_P(VpxMbPostProcAcrossIpTest, CheckCvsAssembly) {
+ Buffer<uint8_t> c_mem = Buffer<uint8_t>(cols_, rows_, 8, 8, 17, 8);
+ ASSERT_TRUE(c_mem.Init());
+ Buffer<uint8_t> asm_mem = Buffer<uint8_t>(cols_, rows_, 8, 8, 17, 8);
+ ASSERT_TRUE(asm_mem.Init());
+
+ // When level >= 100, the filter behaves the same as the level = INT_MAX
+ // When level < 20, it behaves the same as the level = 0
+ for (int level = 0; level < 100; level++) {
+ c_mem.SetPadding(10);
+ asm_mem.SetPadding(10);
+ SetCols(c_mem.TopLeftPixel(), rows_, cols_, c_mem.stride());
+ SetCols(asm_mem.TopLeftPixel(), rows_, cols_, asm_mem.stride());
+
+ vpx_mbpost_proc_across_ip_c(c_mem.TopLeftPixel(), c_mem.stride(), rows_,
+ cols_, q2mbl(level));
+ ASM_REGISTER_STATE_CHECK(GetParam()(
+ asm_mem.TopLeftPixel(), asm_mem.stride(), rows_, cols_, q2mbl(level)));
+
+ ASSERT_TRUE(asm_mem.CheckValues(c_mem));
+ }
+}
+
+TEST_P(VpxMbPostProcAcrossIpTest, DISABLED_Speed) {
+ ASSERT_TRUE(src_.Init());
+ src_.SetPadding(10);
+
+ SetCols(src_.TopLeftPixel(), rows_, cols_, src_.stride());
+
+ RunNTimes(100000);
+ PrintMedian("16x16");
+}
+
+class VpxMbPostProcDownTest
+ : public AbstractBench,
+ public ::testing::TestWithParam<VpxMbPostProcDownFunc> {
+ public:
+ VpxMbPostProcDownTest()
+ : rows_(16), cols_(16), mb_post_proc_down_(GetParam()),
+ src_c_(Buffer<uint8_t>(rows_, cols_, 8, 8, 8, 17)) {}
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ virtual void Run();
+
+ void SetRows(unsigned char *src_c, int rows, int cols, int src_width) {
+ for (int r = 0; r < rows; r++) {
+ memset(src_c, r, cols);
+ src_c += src_width;
+ }
+ }
+
+ void RunComparison(const unsigned char *expected_output, unsigned char *src_c,
+ int rows, int cols, int src_pitch) {
+ for (int r = 0; r < rows; r++) {
+ for (int c = 0; c < cols; c++) {
+ ASSERT_EQ(expected_output[r * rows + c], src_c[c])
+ << "at (" << r << ", " << c << ")";
+ }
+ src_c += src_pitch;
+ }
+ }
+
+ void RunFilterLevel(unsigned char *s, int rows, int cols, int src_width,
+ int filter_level, const unsigned char *expected_output) {
+ ASM_REGISTER_STATE_CHECK(
+ mb_post_proc_down_(s, src_width, rows, cols, filter_level));
+ RunComparison(expected_output, s, rows, cols, src_width);
+ }
+
+ const int rows_;
+ const int cols_;
+ const VpxMbPostProcDownFunc mb_post_proc_down_;
+ Buffer<uint8_t> src_c_;
+};
+
+void VpxMbPostProcDownTest::Run() {
+ mb_post_proc_down_(src_c_.TopLeftPixel(), src_c_.stride(), rows_, cols_,
+ q2mbl(0));
+}
+
+TEST_P(VpxMbPostProcDownTest, CheckHighFilterOutput) {
+ ASSERT_TRUE(src_c_.Init());
+ src_c_.SetPadding(10);
+
+ SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
+
+ static const unsigned char kExpectedOutput[] = {
+ 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 3, 3, 3,
+ 4, 4, 3, 4, 4, 3, 3, 4, 5, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4,
+ 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 8, 9, 9, 8, 8, 8, 9,
+ 9, 8, 9, 9, 8, 8, 8, 9, 9, 10, 10, 9, 9, 9, 10, 10, 9, 10, 10,
+ 9, 9, 9, 10, 10, 10, 11, 10, 10, 10, 11, 10, 11, 10, 11, 10, 10, 10, 11,
+ 10, 11, 11, 11, 11, 11, 11, 11, 12, 11, 11, 11, 11, 11, 11, 11, 12, 11, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 12,
+ 13, 12, 13, 12, 12, 12, 13, 12, 13, 12, 13, 12, 13, 13, 13, 14, 13, 13, 13,
+ 13, 13, 13, 13, 14, 13, 13, 13, 13
+ };
+
+ RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(), INT_MAX,
+ kExpectedOutput);
+
+ src_c_.SetPadding(10);
+ SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
+ RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(),
+ q2mbl(100), kExpectedOutput);
+}
+
+TEST_P(VpxMbPostProcDownTest, CheckMediumFilterOutput) {
+ ASSERT_TRUE(src_c_.Init());
+ src_c_.SetPadding(10);
+
+ SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
+
+ static const unsigned char kExpectedOutput[] = {
+ 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 13, 12,
+ 13, 12, 13, 12, 12, 12, 13, 12, 13, 12, 13, 12, 13, 13, 13, 14, 13, 13, 13,
+ 13, 13, 13, 13, 14, 13, 13, 13, 13
+ };
+
+ RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(),
+ q2mbl(70), kExpectedOutput);
+}
+
+TEST_P(VpxMbPostProcDownTest, CheckLowFilterOutput) {
+ ASSERT_TRUE(src_c_.Init());
+ src_c_.SetPadding(10);
+
+ SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
+
+ std::unique_ptr<unsigned char[]> expected_output(
+ new unsigned char[rows_ * cols_]);
+ ASSERT_NE(expected_output, nullptr);
+ SetRows(expected_output.get(), rows_, cols_, cols_);
+
+ RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(), q2mbl(0),
+ expected_output.get());
+}
+
+TEST_P(VpxMbPostProcDownTest, CheckCvsAssembly) {
+ ACMRandom rnd;
+ rnd.Reset(ACMRandom::DeterministicSeed());
+
+ ASSERT_TRUE(src_c_.Init());
+ Buffer<uint8_t> src_asm = Buffer<uint8_t>(cols_, rows_, 8, 8, 8, 17);
+ ASSERT_TRUE(src_asm.Init());
+
+ for (int level = 0; level < 100; level++) {
+ src_c_.SetPadding(10);
+ src_asm.SetPadding(10);
+ src_c_.Set(&rnd, &ACMRandom::Rand8);
+ src_asm.CopyFrom(src_c_);
+
+ vpx_mbpost_proc_down_c(src_c_.TopLeftPixel(), src_c_.stride(), rows_, cols_,
+ q2mbl(level));
+ ASM_REGISTER_STATE_CHECK(mb_post_proc_down_(
+ src_asm.TopLeftPixel(), src_asm.stride(), rows_, cols_, q2mbl(level)));
+ ASSERT_TRUE(src_asm.CheckValues(src_c_));
+
+ src_c_.SetPadding(10);
+ src_asm.SetPadding(10);
+ src_c_.Set(&rnd, &ACMRandom::Rand8Extremes);
+ src_asm.CopyFrom(src_c_);
+
+ vpx_mbpost_proc_down_c(src_c_.TopLeftPixel(), src_c_.stride(), rows_, cols_,
+ q2mbl(level));
+ ASM_REGISTER_STATE_CHECK(mb_post_proc_down_(
+ src_asm.TopLeftPixel(), src_asm.stride(), rows_, cols_, q2mbl(level)));
+ ASSERT_TRUE(src_asm.CheckValues(src_c_));
+ }
+}
+
+TEST_P(VpxMbPostProcDownTest, DISABLED_Speed) {
+ ASSERT_TRUE(src_c_.Init());
+ src_c_.SetPadding(10);
+
+ SetRows(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride());
+
+ RunNTimes(100000);
+ PrintMedian("16x16");
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxPostProcDownAndAcrossMbRowTest,
+ ::testing::Values(vpx_post_proc_down_and_across_mb_row_c));
+
+INSTANTIATE_TEST_SUITE_P(C, VpxMbPostProcAcrossIpTest,
+ ::testing::Values(vpx_mbpost_proc_across_ip_c));
+
+INSTANTIATE_TEST_SUITE_P(C, VpxMbPostProcDownTest,
+ ::testing::Values(vpx_mbpost_proc_down_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxPostProcDownAndAcrossMbRowTest,
+ ::testing::Values(vpx_post_proc_down_and_across_mb_row_sse2));
+
+INSTANTIATE_TEST_SUITE_P(SSE2, VpxMbPostProcAcrossIpTest,
+ ::testing::Values(vpx_mbpost_proc_across_ip_sse2));
+
+INSTANTIATE_TEST_SUITE_P(SSE2, VpxMbPostProcDownTest,
+ ::testing::Values(vpx_mbpost_proc_down_sse2));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxPostProcDownAndAcrossMbRowTest,
+ ::testing::Values(vpx_post_proc_down_and_across_mb_row_neon));
+
+INSTANTIATE_TEST_SUITE_P(NEON, VpxMbPostProcAcrossIpTest,
+ ::testing::Values(vpx_mbpost_proc_across_ip_neon));
+
+INSTANTIATE_TEST_SUITE_P(NEON, VpxMbPostProcDownTest,
+ ::testing::Values(vpx_mbpost_proc_down_neon));
+#endif // HAVE_NEON
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, VpxPostProcDownAndAcrossMbRowTest,
+ ::testing::Values(vpx_post_proc_down_and_across_mb_row_msa));
+
+INSTANTIATE_TEST_SUITE_P(MSA, VpxMbPostProcAcrossIpTest,
+ ::testing::Values(vpx_mbpost_proc_across_ip_msa));
+
+INSTANTIATE_TEST_SUITE_P(MSA, VpxMbPostProcDownTest,
+ ::testing::Values(vpx_mbpost_proc_down_msa));
+#endif // HAVE_MSA
+
+#if HAVE_VSX
+INSTANTIATE_TEST_SUITE_P(
+ VSX, VpxPostProcDownAndAcrossMbRowTest,
+ ::testing::Values(vpx_post_proc_down_and_across_mb_row_vsx));
+
+INSTANTIATE_TEST_SUITE_P(VSX, VpxMbPostProcAcrossIpTest,
+ ::testing::Values(vpx_mbpost_proc_across_ip_vsx));
+
+INSTANTIATE_TEST_SUITE_P(VSX, VpxMbPostProcDownTest,
+ ::testing::Values(vpx_mbpost_proc_down_vsx));
+#endif // HAVE_VSX
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/predict_test.cc b/media/libvpx/libvpx/test/predict_test.cc
new file mode 100644
index 0000000000..7472970576
--- /dev/null
+++ b/media/libvpx/libvpx/test/predict_test.cc
@@ -0,0 +1,406 @@
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp8_rtcd.h"
+#include "./vpx_config.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/msvc.h"
+
+namespace {
+
+using libvpx_test::ACMRandom;
+using std::make_tuple;
+
+typedef void (*PredictFunc)(uint8_t *src_ptr, int src_pixels_per_line,
+ int xoffset, int yoffset, uint8_t *dst_ptr,
+ int dst_pitch);
+
+typedef std::tuple<int, int, PredictFunc> PredictParam;
+
+class PredictTestBase : public AbstractBench,
+ public ::testing::TestWithParam<PredictParam> {
+ public:
+ PredictTestBase()
+ : width_(GET_PARAM(0)), height_(GET_PARAM(1)), predict_(GET_PARAM(2)),
+ src_(nullptr), padded_dst_(nullptr), dst_(nullptr), dst_c_(nullptr) {}
+
+ virtual void SetUp() {
+ src_ = new uint8_t[kSrcSize];
+ ASSERT_NE(src_, nullptr);
+
+ // padded_dst_ provides a buffer of kBorderSize around the destination
+ // memory to facilitate detecting out of bounds writes.
+ dst_stride_ = kBorderSize + width_ + kBorderSize;
+ padded_dst_size_ = dst_stride_ * (kBorderSize + height_ + kBorderSize);
+ padded_dst_ =
+ reinterpret_cast<uint8_t *>(vpx_memalign(16, padded_dst_size_));
+ ASSERT_NE(padded_dst_, nullptr);
+ dst_ = padded_dst_ + (kBorderSize * dst_stride_) + kBorderSize;
+
+ dst_c_ = new uint8_t[16 * 16];
+ ASSERT_NE(dst_c_, nullptr);
+
+ memset(src_, 0, kSrcSize);
+ memset(padded_dst_, 128, padded_dst_size_);
+ memset(dst_c_, 0, 16 * 16);
+ }
+
+ virtual void TearDown() {
+ delete[] src_;
+ src_ = nullptr;
+ vpx_free(padded_dst_);
+ padded_dst_ = nullptr;
+ dst_ = nullptr;
+ delete[] dst_c_;
+ dst_c_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ // Make reference arrays big enough for 16x16 functions. Six-tap filters need
+ // 5 extra pixels outside of the macroblock.
+ static const int kSrcStride = 21;
+ static const int kSrcSize = kSrcStride * kSrcStride;
+ static const int kBorderSize = 16;
+
+ int width_;
+ int height_;
+ PredictFunc predict_;
+ uint8_t *src_;
+ uint8_t *padded_dst_;
+ uint8_t *dst_;
+ int padded_dst_size_;
+ uint8_t *dst_c_;
+ int dst_stride_;
+
+ bool CompareBuffers(const uint8_t *a, int a_stride, const uint8_t *b,
+ int b_stride) const {
+ for (int height = 0; height < height_; ++height) {
+ EXPECT_EQ(0, memcmp(a + height * a_stride, b + height * b_stride,
+ sizeof(*a) * width_))
+ << "Row " << height << " does not match.";
+ }
+
+ return !HasFailure();
+ }
+
+ // Given a block of memory 'a' with size 'a_size', determine if all regions
+ // excepting block 'b' described by 'b_stride', 'b_height', and 'b_width'
+ // match pixel value 'c'.
+ bool CheckBorder(const uint8_t *a, int a_size, const uint8_t *b, int b_width,
+ int b_height, int b_stride, uint8_t c) const {
+ const uint8_t *a_end = a + a_size;
+ const int b_size = (b_stride * b_height) + b_width;
+ const uint8_t *b_end = b + b_size;
+ const int left_border = (b_stride - b_width) / 2;
+ const int right_border = left_border + ((b_stride - b_width) % 2);
+
+ EXPECT_GE(b - left_border, a) << "'b' does not start within 'a'";
+ EXPECT_LE(b_end + right_border, a_end) << "'b' does not end within 'a'";
+
+ // Top border.
+ for (int pixel = 0; pixel < b - a - left_border; ++pixel) {
+ EXPECT_EQ(c, a[pixel]) << "Mismatch at " << pixel << " in top border.";
+ }
+
+ // Left border.
+ for (int height = 0; height < b_height; ++height) {
+ for (int width = left_border; width > 0; --width) {
+ EXPECT_EQ(c, b[height * b_stride - width])
+ << "Mismatch at row " << height << " column " << left_border - width
+ << " in left border.";
+ }
+ }
+
+ // Right border.
+ for (int height = 0; height < b_height; ++height) {
+ for (int width = b_width; width < b_width + right_border; ++width) {
+ EXPECT_EQ(c, b[height * b_stride + width])
+ << "Mismatch at row " << height << " column " << width - b_width
+ << " in right border.";
+ }
+ }
+
+ // Bottom border.
+ for (int pixel = static_cast<int>(b - a + b_size); pixel < a_size;
+ ++pixel) {
+ EXPECT_EQ(c, a[pixel]) << "Mismatch at " << pixel << " in bottom border.";
+ }
+
+ return !HasFailure();
+ }
+
+ void TestWithRandomData(PredictFunc reference) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+ // Run tests for almost all possible offsets.
+ for (int xoffset = 0; xoffset < 8; ++xoffset) {
+ for (int yoffset = 0; yoffset < 8; ++yoffset) {
+ if (xoffset == 0 && yoffset == 0) {
+ // This represents a copy which is not required to be handled by this
+ // module.
+ continue;
+ }
+
+ for (int i = 0; i < kSrcSize; ++i) {
+ src_[i] = rnd.Rand8();
+ }
+ reference(&src_[kSrcStride * 2 + 2], kSrcStride, xoffset, yoffset,
+ dst_c_, 16);
+
+ ASM_REGISTER_STATE_CHECK(predict_(&src_[kSrcStride * 2 + 2], kSrcStride,
+ xoffset, yoffset, dst_, dst_stride_));
+
+ ASSERT_TRUE(CompareBuffers(dst_c_, 16, dst_, dst_stride_));
+ ASSERT_TRUE(CheckBorder(padded_dst_, padded_dst_size_, dst_, width_,
+ height_, dst_stride_, 128));
+ }
+ }
+ }
+
+ void TestWithUnalignedDst(PredictFunc reference) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+ // Only the 4x4 need to be able to handle unaligned writes.
+ if (width_ == 4 && height_ == 4) {
+ for (int xoffset = 0; xoffset < 8; ++xoffset) {
+ for (int yoffset = 0; yoffset < 8; ++yoffset) {
+ if (xoffset == 0 && yoffset == 0) {
+ continue;
+ }
+ for (int i = 0; i < kSrcSize; ++i) {
+ src_[i] = rnd.Rand8();
+ }
+ reference(&src_[kSrcStride * 2 + 2], kSrcStride, xoffset, yoffset,
+ dst_c_, 16);
+
+ for (int i = 1; i < 4; ++i) {
+ memset(padded_dst_, 128, padded_dst_size_);
+
+ ASM_REGISTER_STATE_CHECK(predict_(&src_[kSrcStride * 2 + 2],
+ kSrcStride, xoffset, yoffset,
+ dst_ + i, dst_stride_ + i));
+
+ ASSERT_TRUE(CompareBuffers(dst_c_, 16, dst_ + i, dst_stride_ + i));
+ ASSERT_TRUE(CheckBorder(padded_dst_, padded_dst_size_, dst_ + i,
+ width_, height_, dst_stride_ + i, 128));
+ }
+ }
+ }
+ }
+ }
+
+ void Run() {
+ for (int xoffset = 0; xoffset < 8; ++xoffset) {
+ for (int yoffset = 0; yoffset < 8; ++yoffset) {
+ if (xoffset == 0 && yoffset == 0) {
+ continue;
+ }
+
+ predict_(&src_[kSrcStride * 2 + 2], kSrcStride, xoffset, yoffset, dst_,
+ dst_stride_);
+ }
+ }
+ }
+}; // namespace
+
+class SixtapPredictTest : public PredictTestBase {};
+
+TEST_P(SixtapPredictTest, TestWithRandomData) {
+ TestWithRandomData(vp8_sixtap_predict16x16_c);
+}
+TEST_P(SixtapPredictTest, TestWithUnalignedDst) {
+ TestWithUnalignedDst(vp8_sixtap_predict16x16_c);
+}
+
+TEST_P(SixtapPredictTest, TestWithPresetData) {
+ // Test input
+ static const uint8_t kTestData[kSrcSize] = {
+ 184, 4, 191, 82, 92, 41, 0, 1, 226, 236, 172, 20, 182, 42, 226,
+ 177, 79, 94, 77, 179, 203, 206, 198, 22, 192, 19, 75, 17, 192, 44,
+ 233, 120, 48, 168, 203, 141, 210, 203, 143, 180, 184, 59, 201, 110, 102,
+ 171, 32, 182, 10, 109, 105, 213, 60, 47, 236, 253, 67, 55, 14, 3,
+ 99, 247, 124, 148, 159, 71, 34, 114, 19, 177, 38, 203, 237, 239, 58,
+ 83, 155, 91, 10, 166, 201, 115, 124, 5, 163, 104, 2, 231, 160, 16,
+ 234, 4, 8, 103, 153, 167, 174, 187, 26, 193, 109, 64, 141, 90, 48,
+ 200, 174, 204, 36, 184, 114, 237, 43, 238, 242, 207, 86, 245, 182, 247,
+ 6, 161, 251, 14, 8, 148, 182, 182, 79, 208, 120, 188, 17, 6, 23,
+ 65, 206, 197, 13, 242, 126, 128, 224, 170, 110, 211, 121, 197, 200, 47,
+ 188, 207, 208, 184, 221, 216, 76, 148, 143, 156, 100, 8, 89, 117, 14,
+ 112, 183, 221, 54, 197, 208, 180, 69, 176, 94, 180, 131, 215, 121, 76,
+ 7, 54, 28, 216, 238, 249, 176, 58, 142, 64, 215, 242, 72, 49, 104,
+ 87, 161, 32, 52, 216, 230, 4, 141, 44, 181, 235, 224, 57, 195, 89,
+ 134, 203, 144, 162, 163, 126, 156, 84, 185, 42, 148, 145, 29, 221, 194,
+ 134, 52, 100, 166, 105, 60, 140, 110, 201, 184, 35, 181, 153, 93, 121,
+ 243, 227, 68, 131, 134, 232, 2, 35, 60, 187, 77, 209, 76, 106, 174,
+ 15, 241, 227, 115, 151, 77, 175, 36, 187, 121, 221, 223, 47, 118, 61,
+ 168, 105, 32, 237, 236, 167, 213, 238, 202, 17, 170, 24, 226, 247, 131,
+ 145, 6, 116, 117, 121, 11, 194, 41, 48, 126, 162, 13, 93, 209, 131,
+ 154, 122, 237, 187, 103, 217, 99, 60, 200, 45, 78, 115, 69, 49, 106,
+ 200, 194, 112, 60, 56, 234, 72, 251, 19, 120, 121, 182, 134, 215, 135,
+ 10, 114, 2, 247, 46, 105, 209, 145, 165, 153, 191, 243, 12, 5, 36,
+ 119, 206, 231, 231, 11, 32, 209, 83, 27, 229, 204, 149, 155, 83, 109,
+ 35, 93, 223, 37, 84, 14, 142, 37, 160, 52, 191, 96, 40, 204, 101,
+ 77, 67, 52, 53, 43, 63, 85, 253, 147, 113, 226, 96, 6, 125, 179,
+ 115, 161, 17, 83, 198, 101, 98, 85, 139, 3, 137, 75, 99, 178, 23,
+ 201, 255, 91, 253, 52, 134, 60, 138, 131, 208, 251, 101, 48, 2, 227,
+ 228, 118, 132, 245, 202, 75, 91, 44, 160, 231, 47, 41, 50, 147, 220,
+ 74, 92, 219, 165, 89, 16
+ };
+
+ // Expected results for xoffset = 2 and yoffset = 2.
+ static const int kExpectedDstStride = 16;
+ static const uint8_t kExpectedDst[256] = {
+ 117, 102, 74, 135, 42, 98, 175, 206, 70, 73, 222, 197, 50, 24, 39,
+ 49, 38, 105, 90, 47, 169, 40, 171, 215, 200, 73, 109, 141, 53, 85,
+ 177, 164, 79, 208, 124, 89, 212, 18, 81, 145, 151, 164, 217, 153, 91,
+ 154, 102, 102, 159, 75, 164, 152, 136, 51, 213, 219, 186, 116, 193, 224,
+ 186, 36, 231, 208, 84, 211, 155, 167, 35, 59, 42, 76, 216, 149, 73,
+ 201, 78, 149, 184, 100, 96, 196, 189, 198, 188, 235, 195, 117, 129, 120,
+ 129, 49, 25, 133, 113, 69, 221, 114, 70, 143, 99, 157, 108, 189, 140,
+ 78, 6, 55, 65, 240, 255, 245, 184, 72, 90, 100, 116, 131, 39, 60,
+ 234, 167, 33, 160, 88, 185, 200, 157, 159, 176, 127, 151, 138, 102, 168,
+ 106, 170, 86, 82, 219, 189, 76, 33, 115, 197, 106, 96, 198, 136, 97,
+ 141, 237, 151, 98, 137, 191, 185, 2, 57, 95, 142, 91, 255, 185, 97,
+ 137, 76, 162, 94, 173, 131, 193, 161, 81, 106, 72, 135, 222, 234, 137,
+ 66, 137, 106, 243, 210, 147, 95, 15, 137, 110, 85, 66, 16, 96, 167,
+ 147, 150, 173, 203, 140, 118, 196, 84, 147, 160, 19, 95, 101, 123, 74,
+ 132, 202, 82, 166, 12, 131, 166, 189, 170, 159, 85, 79, 66, 57, 152,
+ 132, 203, 194, 0, 1, 56, 146, 180, 224, 156, 28, 83, 181, 79, 76,
+ 80, 46, 160, 175, 59, 106, 43, 87, 75, 136, 85, 189, 46, 71, 200,
+ 90
+ };
+
+ ASM_REGISTER_STATE_CHECK(
+ predict_(const_cast<uint8_t *>(kTestData) + kSrcStride * 2 + 2,
+ kSrcStride, 2, 2, dst_, dst_stride_));
+
+ ASSERT_TRUE(
+ CompareBuffers(kExpectedDst, kExpectedDstStride, dst_, dst_stride_));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ C, SixtapPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_c),
+ make_tuple(8, 8, &vp8_sixtap_predict8x8_c),
+ make_tuple(8, 4, &vp8_sixtap_predict8x4_c),
+ make_tuple(4, 4, &vp8_sixtap_predict4x4_c)));
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, SixtapPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_neon),
+ make_tuple(8, 8, &vp8_sixtap_predict8x8_neon),
+ make_tuple(8, 4, &vp8_sixtap_predict8x4_neon),
+ make_tuple(4, 4, &vp8_sixtap_predict4x4_neon)));
+#endif
+#if HAVE_MMX
+INSTANTIATE_TEST_SUITE_P(
+ MMX, SixtapPredictTest,
+ ::testing::Values(make_tuple(4, 4, &vp8_sixtap_predict4x4_mmx)));
+#endif
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, SixtapPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_sse2),
+ make_tuple(8, 8, &vp8_sixtap_predict8x8_sse2),
+ make_tuple(8, 4, &vp8_sixtap_predict8x4_sse2)));
+#endif
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, SixtapPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_ssse3),
+ make_tuple(8, 8, &vp8_sixtap_predict8x8_ssse3),
+ make_tuple(8, 4, &vp8_sixtap_predict8x4_ssse3),
+ make_tuple(4, 4, &vp8_sixtap_predict4x4_ssse3)));
+#endif
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, SixtapPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_msa),
+ make_tuple(8, 8, &vp8_sixtap_predict8x8_msa),
+ make_tuple(8, 4, &vp8_sixtap_predict8x4_msa),
+ make_tuple(4, 4, &vp8_sixtap_predict4x4_msa)));
+#endif
+
+#if HAVE_MMI
+INSTANTIATE_TEST_SUITE_P(
+ MMI, SixtapPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_mmi),
+ make_tuple(8, 8, &vp8_sixtap_predict8x8_mmi),
+ make_tuple(8, 4, &vp8_sixtap_predict8x4_mmi),
+ make_tuple(4, 4, &vp8_sixtap_predict4x4_mmi)));
+#endif
+
+class BilinearPredictTest : public PredictTestBase {};
+
+TEST_P(BilinearPredictTest, TestWithRandomData) {
+ TestWithRandomData(vp8_bilinear_predict16x16_c);
+}
+TEST_P(BilinearPredictTest, TestWithUnalignedDst) {
+ TestWithUnalignedDst(vp8_bilinear_predict16x16_c);
+}
+TEST_P(BilinearPredictTest, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 5000000 / (width_ * height_);
+ RunNTimes(kCountSpeedTestBlock);
+
+ char title[16];
+ snprintf(title, sizeof(title), "%dx%d", width_, height_);
+ PrintMedian(title);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ C, BilinearPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_c),
+ make_tuple(8, 8, &vp8_bilinear_predict8x8_c),
+ make_tuple(8, 4, &vp8_bilinear_predict8x4_c),
+ make_tuple(4, 4, &vp8_bilinear_predict4x4_c)));
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, BilinearPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_neon),
+ make_tuple(8, 8, &vp8_bilinear_predict8x8_neon),
+ make_tuple(8, 4, &vp8_bilinear_predict8x4_neon),
+ make_tuple(4, 4, &vp8_bilinear_predict4x4_neon)));
+#endif
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, BilinearPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_sse2),
+ make_tuple(8, 8, &vp8_bilinear_predict8x8_sse2),
+ make_tuple(8, 4, &vp8_bilinear_predict8x4_sse2),
+ make_tuple(4, 4, &vp8_bilinear_predict4x4_sse2)));
+#endif
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, BilinearPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_ssse3),
+ make_tuple(8, 8, &vp8_bilinear_predict8x8_ssse3)));
+#endif
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, BilinearPredictTest,
+ ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_msa),
+ make_tuple(8, 8, &vp8_bilinear_predict8x8_msa),
+ make_tuple(8, 4, &vp8_bilinear_predict8x4_msa),
+ make_tuple(4, 4, &vp8_bilinear_predict4x4_msa)));
+#endif
+} // namespace
diff --git a/media/libvpx/libvpx/test/quantize_test.cc b/media/libvpx/libvpx/test/quantize_test.cc
new file mode 100644
index 0000000000..57309e8102
--- /dev/null
+++ b/media/libvpx/libvpx/test/quantize_test.cc
@@ -0,0 +1,234 @@
+/*
+ * 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 <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp8_rtcd.h"
+#include "./vpx_config.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp8/common/blockd.h"
+#include "vp8/common/onyx.h"
+#include "vp8/encoder/block.h"
+#include "vp8/encoder/onyx_int.h"
+#include "vp8/encoder/quantize.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+const int kNumBlocks = 25;
+const int kNumBlockEntries = 16;
+
+typedef void (*VP8Quantize)(BLOCK *b, BLOCKD *d);
+
+typedef std::tuple<VP8Quantize, VP8Quantize> VP8QuantizeParam;
+
+using libvpx_test::ACMRandom;
+using std::make_tuple;
+
+// Create and populate a VP8_COMP instance which has a complete set of
+// quantization inputs as well as a second MACROBLOCKD for output.
+class QuantizeTestBase {
+ public:
+ virtual ~QuantizeTestBase() {
+ vp8_remove_compressor(&vp8_comp_);
+ vp8_comp_ = nullptr;
+ vpx_free(macroblockd_dst_);
+ macroblockd_dst_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ void SetupCompressor() {
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+
+ // The full configuration is necessary to generate the quantization tables.
+ VP8_CONFIG vp8_config;
+ memset(&vp8_config, 0, sizeof(vp8_config));
+
+ vp8_comp_ = vp8_create_compressor(&vp8_config);
+
+ // Set the tables based on a quantizer of 0.
+ vp8_set_quantizer(vp8_comp_, 0);
+
+ // Set up all the block/blockd pointers for the mb in vp8_comp_.
+ vp8cx_frame_init_quantizer(vp8_comp_);
+
+ // Copy macroblockd from the reference to get pre-set-up dequant values.
+ macroblockd_dst_ = reinterpret_cast<MACROBLOCKD *>(
+ vpx_memalign(32, sizeof(*macroblockd_dst_)));
+ memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_));
+ // Fix block pointers - currently they point to the blocks in the reference
+ // structure.
+ vp8_setup_block_dptrs(macroblockd_dst_);
+ }
+
+ void UpdateQuantizer(int q) {
+ vp8_set_quantizer(vp8_comp_, q);
+
+ memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_));
+ vp8_setup_block_dptrs(macroblockd_dst_);
+ }
+
+ void FillCoeffConstant(int16_t c) {
+ for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) {
+ vp8_comp_->mb.coeff[i] = c;
+ }
+ }
+
+ void FillCoeffRandom() {
+ for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) {
+ vp8_comp_->mb.coeff[i] = rnd_.Rand8();
+ }
+ }
+
+ void CheckOutput() {
+ EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.qcoeff, macroblockd_dst_->qcoeff,
+ sizeof(*macroblockd_dst_->qcoeff) * kNumBlocks *
+ kNumBlockEntries))
+ << "qcoeff mismatch";
+ EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.dqcoeff, macroblockd_dst_->dqcoeff,
+ sizeof(*macroblockd_dst_->dqcoeff) * kNumBlocks *
+ kNumBlockEntries))
+ << "dqcoeff mismatch";
+ EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.eobs, macroblockd_dst_->eobs,
+ sizeof(*macroblockd_dst_->eobs) * kNumBlocks))
+ << "eobs mismatch";
+ }
+
+ VP8_COMP *vp8_comp_;
+ MACROBLOCKD *macroblockd_dst_;
+
+ private:
+ ACMRandom rnd_;
+};
+
+class QuantizeTest : public QuantizeTestBase,
+ public ::testing::TestWithParam<VP8QuantizeParam>,
+ public AbstractBench {
+ protected:
+ virtual void SetUp() {
+ SetupCompressor();
+ asm_quant_ = GET_PARAM(0);
+ c_quant_ = GET_PARAM(1);
+ }
+
+ virtual void Run() {
+ asm_quant_(&vp8_comp_->mb.block[0], &macroblockd_dst_->block[0]);
+ }
+
+ void RunComparison() {
+ for (int i = 0; i < kNumBlocks; ++i) {
+ ASM_REGISTER_STATE_CHECK(
+ c_quant_(&vp8_comp_->mb.block[i], &vp8_comp_->mb.e_mbd.block[i]));
+ ASM_REGISTER_STATE_CHECK(
+ asm_quant_(&vp8_comp_->mb.block[i], &macroblockd_dst_->block[i]));
+ }
+
+ CheckOutput();
+ }
+
+ private:
+ VP8Quantize asm_quant_;
+ VP8Quantize c_quant_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(QuantizeTest);
+
+TEST_P(QuantizeTest, TestZeroInput) {
+ FillCoeffConstant(0);
+ RunComparison();
+}
+
+TEST_P(QuantizeTest, TestLargeNegativeInput) {
+ FillCoeffConstant(0);
+ // Generate a qcoeff which contains 512/-512 (0x0100/0xFE00) to catch issues
+ // like BUG=883 where the constant being compared was incorrectly initialized.
+ vp8_comp_->mb.coeff[0] = -8191;
+ RunComparison();
+}
+
+TEST_P(QuantizeTest, TestRandomInput) {
+ FillCoeffRandom();
+ RunComparison();
+}
+
+TEST_P(QuantizeTest, TestMultipleQ) {
+ for (int q = 0; q < QINDEX_RANGE; ++q) {
+ UpdateQuantizer(q);
+ FillCoeffRandom();
+ RunComparison();
+ }
+}
+
+TEST_P(QuantizeTest, DISABLED_Speed) {
+ FillCoeffRandom();
+
+ RunNTimes(10000000);
+ PrintMedian("vp8 quantize");
+}
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, QuantizeTest,
+ ::testing::Values(
+ make_tuple(&vp8_fast_quantize_b_sse2, &vp8_fast_quantize_b_c),
+ make_tuple(&vp8_regular_quantize_b_sse2, &vp8_regular_quantize_b_c)));
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, QuantizeTest,
+ ::testing::Values(make_tuple(&vp8_fast_quantize_b_ssse3,
+ &vp8_fast_quantize_b_c)));
+#endif // HAVE_SSSE3
+
+#if HAVE_SSE4_1
+INSTANTIATE_TEST_SUITE_P(
+ SSE4_1, QuantizeTest,
+ ::testing::Values(make_tuple(&vp8_regular_quantize_b_sse4_1,
+ &vp8_regular_quantize_b_c)));
+#endif // HAVE_SSE4_1
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, QuantizeTest,
+ ::testing::Values(make_tuple(&vp8_fast_quantize_b_neon,
+ &vp8_fast_quantize_b_c)));
+#endif // HAVE_NEON
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, QuantizeTest,
+ ::testing::Values(
+ make_tuple(&vp8_fast_quantize_b_msa, &vp8_fast_quantize_b_c),
+ make_tuple(&vp8_regular_quantize_b_msa, &vp8_regular_quantize_b_c)));
+#endif // HAVE_MSA
+
+#if HAVE_MMI
+INSTANTIATE_TEST_SUITE_P(
+ MMI, QuantizeTest,
+ ::testing::Values(
+ make_tuple(&vp8_fast_quantize_b_mmi, &vp8_fast_quantize_b_c),
+ make_tuple(&vp8_regular_quantize_b_mmi, &vp8_regular_quantize_b_c)));
+#endif // HAVE_MMI
+
+#if HAVE_LSX
+INSTANTIATE_TEST_SUITE_P(
+ LSX, QuantizeTest,
+ ::testing::Values(make_tuple(&vp8_regular_quantize_b_lsx,
+ &vp8_regular_quantize_b_c)));
+#endif // HAVE_LSX
+} // namespace
diff --git a/media/libvpx/libvpx/test/realtime_test.cc b/media/libvpx/libvpx/test/realtime_test.cc
new file mode 100644
index 0000000000..c5de2dcb35
--- /dev/null
+++ b/media/libvpx/libvpx/test/realtime_test.cc
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016 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 <limits.h>
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace {
+
+const int kVideoSourceWidth = 320;
+const int kVideoSourceHeight = 240;
+const int kFramesToEncode = 2;
+
+class RealtimeTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ RealtimeTest() : EncoderTest(GET_PARAM(0)), frame_packets_(0) {}
+ ~RealtimeTest() override {}
+
+ void SetUp() override {
+ InitializeConfig();
+ cfg_.g_lag_in_frames = 0;
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ void BeginPassHook(unsigned int /*pass*/) override {
+#if !CONFIG_REALTIME_ONLY
+ // TODO(tomfinegan): We're changing the pass value here to make sure
+ // we get frames when real time mode is combined with |g_pass| set to
+ // VPX_RC_FIRST_PASS. This is necessary because EncoderTest::RunLoop() sets
+ // the pass value based on the mode passed into EncoderTest::SetMode(),
+ // which overrides the one specified in SetUp() above.
+ cfg_.g_pass = VPX_RC_FIRST_PASS;
+#endif
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0 && set_cpu_used_) {
+ encoder->Control(VP8E_SET_CPUUSED, 8);
+ }
+ }
+
+ void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) override {
+ frame_packets_++;
+ }
+
+ bool IsVP9() const {
+#if CONFIG_VP9_ENCODER
+ return codec_ == &libvpx_test::kVP9;
+#else
+ return false;
+#endif
+ }
+
+ void TestIntegerOverflow(unsigned int width, unsigned int height) {
+ ::libvpx_test::RandomVideoSource video;
+ video.SetSize(width, height);
+ video.set_limit(20);
+ cfg_.rc_target_bitrate = UINT_MAX;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void TestEncode() {
+ ::libvpx_test::RandomVideoSource video;
+ video.SetSize(kVideoSourceWidth, kVideoSourceHeight);
+ video.set_limit(kFramesToEncode);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ EXPECT_EQ(kFramesToEncode, frame_packets_);
+ }
+
+ int frame_packets_;
+ bool set_cpu_used_ = true;
+};
+
+TEST_P(RealtimeTest, RealtimeFirstPassProducesFrames) { TestEncode(); }
+
+TEST_P(RealtimeTest, RealtimeDefaultCpuUsed) {
+ set_cpu_used_ = false;
+ TestEncode();
+}
+
+TEST_P(RealtimeTest, IntegerOverflow) { TestIntegerOverflow(2048, 2048); }
+
+TEST_P(RealtimeTest, IntegerOverflowLarge) {
+ if (IsVP9()) {
+#if VPX_ARCH_X86_64
+ TestIntegerOverflow(16384, 16384);
+#else
+ TestIntegerOverflow(4096, 4096);
+#endif
+ } else {
+ GTEST_SKIP()
+ << "TODO(https://crbug.com/webm/1748,https://crbug.com/webm/1751):"
+ << " Enable this test after bitstream errors & undefined sanitizer "
+ "warnings are fixed.";
+ // TestIntegerOverflow(16383, 16383);
+ }
+}
+
+VP8_INSTANTIATE_TEST_SUITE(RealtimeTest,
+ ::testing::Values(::libvpx_test::kRealTime));
+VP9_INSTANTIATE_TEST_SUITE(RealtimeTest,
+ ::testing::Values(::libvpx_test::kRealTime));
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/register_state_check.h b/media/libvpx/libvpx/test/register_state_check.h
new file mode 100644
index 0000000000..ede86ef52f
--- /dev/null
+++ b/media/libvpx/libvpx/test/register_state_check.h
@@ -0,0 +1,205 @@
+/*
+ * 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 VPX_TEST_REGISTER_STATE_CHECK_H_
+#define VPX_TEST_REGISTER_STATE_CHECK_H_
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "vpx/vpx_integer.h"
+
+// ASM_REGISTER_STATE_CHECK(asm_function)
+// Minimally validates the environment pre & post function execution. This
+// variant should be used with assembly functions which are not expected to
+// fully restore the system state. See platform implementations of
+// RegisterStateCheck for details.
+//
+// API_REGISTER_STATE_CHECK(api_function)
+// Performs all the checks done by ASM_REGISTER_STATE_CHECK() and any
+// additional checks to ensure the environment is in a consistent state pre &
+// post function execution. This variant should be used with API functions.
+// See platform implementations of RegisterStateCheckXXX for details.
+//
+
+#if defined(_WIN64) && VPX_ARCH_X86_64
+
+#undef NOMINMAX
+#define NOMINMAX
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <intrin.h>
+#include <windows.h>
+#include <winnt.h>
+
+inline bool operator==(const M128A &lhs, const M128A &rhs) {
+ return (lhs.Low == rhs.Low && lhs.High == rhs.High);
+}
+
+namespace libvpx_test {
+
+// Compares the state of xmm[6-15] at construction with their state at
+// destruction. These registers should be preserved by the callee on
+// Windows x64.
+class RegisterStateCheck {
+ public:
+ RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
+ ~RegisterStateCheck() { Check(); }
+
+ private:
+ static bool StoreRegisters(CONTEXT *const context) {
+ const HANDLE this_thread = GetCurrentThread();
+ EXPECT_NE(this_thread, nullptr);
+ context->ContextFlags = CONTEXT_FLOATING_POINT;
+ const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
+ EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
+ return context_saved;
+ }
+
+ // Compares the register state. Returns true if the states match.
+ void Check() const {
+ ASSERT_TRUE(initialized_);
+ CONTEXT post_context;
+ ASSERT_TRUE(StoreRegisters(&post_context));
+
+ const M128A *xmm_pre = &pre_context_.Xmm6;
+ const M128A *xmm_post = &post_context.Xmm6;
+ for (int i = 6; i <= 15; ++i) {
+ EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
+ ++xmm_pre;
+ ++xmm_post;
+ }
+ }
+
+ bool initialized_;
+ CONTEXT pre_context_;
+};
+
+#define ASM_REGISTER_STATE_CHECK(statement) \
+ do { \
+ { \
+ libvpx_test::RegisterStateCheck reg_check; \
+ statement; \
+ } \
+ _ReadWriteBarrier(); \
+ } while (false)
+
+} // namespace libvpx_test
+
+#elif defined(CONFIG_SHARED) && defined(HAVE_NEON_ASM) && \
+ defined(CONFIG_VP9) && !CONFIG_SHARED && HAVE_NEON_ASM && CONFIG_VP9
+
+extern "C" {
+// Save the d8-d15 registers into store.
+void vpx_push_neon(int64_t *store);
+}
+
+namespace libvpx_test {
+
+// Compares the state of d8-d15 at construction with their state at
+// destruction. These registers should be preserved by the callee on
+// arm platform.
+class RegisterStateCheck {
+ public:
+ RegisterStateCheck() { vpx_push_neon(pre_store_); }
+ ~RegisterStateCheck() { Check(); }
+
+ private:
+ // Compares the register state. Returns true if the states match.
+ void Check() const {
+ int64_t post_store[8];
+ vpx_push_neon(post_store);
+ for (int i = 0; i < 8; ++i) {
+ EXPECT_EQ(pre_store_[i], post_store[i])
+ << "d" << i + 8 << " has been modified";
+ }
+ }
+
+ int64_t pre_store_[8];
+};
+
+#if defined(__GNUC__)
+#define ASM_REGISTER_STATE_CHECK(statement) \
+ do { \
+ { \
+ libvpx_test::RegisterStateCheck reg_check; \
+ statement; \
+ } \
+ __asm__ volatile("" ::: "memory"); \
+ } while (false)
+#else
+#define ASM_REGISTER_STATE_CHECK(statement) \
+ do { \
+ libvpx_test::RegisterStateCheck reg_check; \
+ statement; \
+ } while (false)
+#endif
+
+} // namespace libvpx_test
+
+#else
+
+namespace libvpx_test {
+
+class RegisterStateCheck {};
+#define ASM_REGISTER_STATE_CHECK(statement) statement
+
+} // namespace libvpx_test
+
+#endif // _WIN64 && VPX_ARCH_X86_64
+
+#if VPX_ARCH_X86 || VPX_ARCH_X86_64
+#if defined(__GNUC__)
+
+namespace libvpx_test {
+
+// Checks the FPU tag word pre/post execution to ensure emms has been called.
+class RegisterStateCheckMMX {
+ public:
+ RegisterStateCheckMMX() {
+ __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_));
+ }
+ ~RegisterStateCheckMMX() { Check(); }
+
+ private:
+ // Checks the FPU tag word pre/post execution, returning false if not cleared
+ // to 0xffff.
+ void Check() const {
+ EXPECT_EQ(0xffff, pre_fpu_env_[4])
+ << "FPU was in an inconsistent state prior to call";
+
+ uint16_t post_fpu_env[14];
+ __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env));
+ EXPECT_EQ(0xffff, post_fpu_env[4])
+ << "FPU was left in an inconsistent state after call";
+ }
+
+ uint16_t pre_fpu_env_[14];
+};
+
+#define API_REGISTER_STATE_CHECK(statement) \
+ do { \
+ { \
+ libvpx_test::RegisterStateCheckMMX reg_check_mmx; \
+ ASM_REGISTER_STATE_CHECK(statement); \
+ } \
+ __asm__ volatile("" ::: "memory"); \
+ } while (false)
+
+} // namespace libvpx_test
+
+#endif // __GNUC__
+#endif // VPX_ARCH_X86 || VPX_ARCH_X86_64
+
+#ifndef API_REGISTER_STATE_CHECK
+#define API_REGISTER_STATE_CHECK ASM_REGISTER_STATE_CHECK
+#endif
+
+#endif // VPX_TEST_REGISTER_STATE_CHECK_H_
diff --git a/media/libvpx/libvpx/test/resize_test.cc b/media/libvpx/libvpx/test/resize_test.cc
new file mode 100644
index 0000000000..715bb9d70f
--- /dev/null
+++ b/media/libvpx/libvpx/test/resize_test.cc
@@ -0,0 +1,788 @@
+/*
+ * 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 <stdio.h>
+
+#include <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/video_source.h"
+#include "test/util.h"
+
+// Enable(1) or Disable(0) writing of the compressed bitstream.
+#define WRITE_COMPRESSED_STREAM 0
+
+namespace {
+
+#if WRITE_COMPRESSED_STREAM
+static void mem_put_le16(char *const mem, const unsigned int val) {
+ mem[0] = val;
+ mem[1] = val >> 8;
+}
+
+static void mem_put_le32(char *const mem, const unsigned int val) {
+ mem[0] = val;
+ mem[1] = val >> 8;
+ mem[2] = val >> 16;
+ mem[3] = val >> 24;
+}
+
+static void write_ivf_file_header(const vpx_codec_enc_cfg_t *const cfg,
+ int frame_cnt, FILE *const outfile) {
+ char header[32];
+
+ header[0] = 'D';
+ header[1] = 'K';
+ header[2] = 'I';
+ header[3] = 'F';
+ mem_put_le16(header + 4, 0); /* version */
+ mem_put_le16(header + 6, 32); /* headersize */
+ mem_put_le32(header + 8, 0x30395056); /* fourcc (vp9) */
+ mem_put_le16(header + 12, cfg->g_w); /* width */
+ mem_put_le16(header + 14, cfg->g_h); /* height */
+ mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
+ mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
+ mem_put_le32(header + 24, frame_cnt); /* length */
+ mem_put_le32(header + 28, 0); /* unused */
+
+ (void)fwrite(header, 1, 32, outfile);
+}
+
+static void write_ivf_frame_size(FILE *const outfile, const size_t size) {
+ char header[4];
+ mem_put_le32(header, static_cast<unsigned int>(size));
+ (void)fwrite(header, 1, 4, outfile);
+}
+
+static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt,
+ FILE *const outfile) {
+ char header[12];
+ vpx_codec_pts_t pts;
+
+ if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
+
+ pts = pkt->data.frame.pts;
+ mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz));
+ mem_put_le32(header + 4, pts & 0xFFFFFFFF);
+ mem_put_le32(header + 8, pts >> 32);
+
+ (void)fwrite(header, 1, 12, outfile);
+}
+#endif // WRITE_COMPRESSED_STREAM
+
+const unsigned int kInitialWidth = 320;
+const unsigned int kInitialHeight = 240;
+
+struct FrameInfo {
+ FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
+ : pts(_pts), w(_w), h(_h) {}
+
+ vpx_codec_pts_t pts;
+ unsigned int w;
+ unsigned int h;
+};
+
+void ScaleForFrameNumber(unsigned int frame, unsigned int initial_w,
+ unsigned int initial_h, unsigned int *w,
+ unsigned int *h, bool flag_codec,
+ bool smaller_width_larger_size_) {
+ *w = initial_w;
+ *h = initial_h;
+
+ if (smaller_width_larger_size_) {
+ if (frame < 30) {
+ return;
+ }
+ if (frame < 100) {
+ *w = initial_w * 7 / 10;
+ *h = initial_h * 16 / 10;
+ return;
+ }
+ return;
+ }
+ if (frame < 10) {
+ return;
+ }
+ if (frame < 20) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 30) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 40) {
+ return;
+ }
+ if (frame < 50) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 60) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 70) {
+ return;
+ }
+ if (frame < 80) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 90) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 100) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 110) {
+ return;
+ }
+ if (frame < 120) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 130) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 140) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 150) {
+ return;
+ }
+ if (frame < 160) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 170) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 180) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 190) {
+ return;
+ }
+ if (frame < 200) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 210) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 220) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 230) {
+ return;
+ }
+ if (frame < 240) {
+ *w = initial_w * 3 / 4;
+ *h = initial_h * 3 / 4;
+ return;
+ }
+ if (frame < 250) {
+ *w = initial_w / 2;
+ *h = initial_h / 2;
+ return;
+ }
+ if (frame < 260) {
+ return;
+ }
+ // Go down very low.
+ if (frame < 270) {
+ *w = initial_w / 4;
+ *h = initial_h / 4;
+ return;
+ }
+ if (flag_codec == 1) {
+ // Cases that only works for VP9.
+ // For VP9: Swap width and height of original.
+ if (frame < 320) {
+ return;
+ }
+ }
+}
+
+class ResizingVideoSource : public ::libvpx_test::DummyVideoSource {
+ public:
+ ResizingVideoSource() {
+ SetSize(kInitialWidth, kInitialHeight);
+ limit_ = 350;
+ smaller_width_larger_size_ = false;
+ }
+ bool flag_codec_;
+ bool smaller_width_larger_size_;
+ virtual ~ResizingVideoSource() {}
+
+ protected:
+ virtual void Next() {
+ ++frame_;
+ unsigned int width = 0;
+ unsigned int height = 0;
+ ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height,
+ flag_codec_, smaller_width_larger_size_);
+ SetSize(width, height);
+ FillFrame();
+ }
+};
+
+class ResizeTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ ResizeTest() : EncoderTest(GET_PARAM(0)) {}
+
+ virtual ~ResizeTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ ASSERT_NE(static_cast<int>(pkt->data.frame.width[0]), 0);
+ ASSERT_NE(static_cast<int>(pkt->data.frame.height[0]), 0);
+ encode_frame_width_.push_back(pkt->data.frame.width[0]);
+ encode_frame_height_.push_back(pkt->data.frame.height[0]);
+ }
+
+ unsigned int GetFrameWidth(size_t idx) const {
+ return encode_frame_width_[idx];
+ }
+
+ unsigned int GetFrameHeight(size_t idx) const {
+ return encode_frame_height_[idx];
+ }
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ vpx_codec_pts_t pts) {
+ frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
+ }
+
+ std::vector<FrameInfo> frame_info_list_;
+ std::vector<unsigned int> encode_frame_width_;
+ std::vector<unsigned int> encode_frame_height_;
+};
+
+TEST_P(ResizeTest, TestExternalResizeWorks) {
+ ResizingVideoSource video;
+ video.flag_codec_ = false;
+ video.smaller_width_larger_size_ = false;
+ cfg_.g_lag_in_frames = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ const unsigned int frame = static_cast<unsigned>(info->pts);
+ unsigned int expected_w;
+ unsigned int expected_h;
+ const size_t idx = info - frame_info_list_.begin();
+ ASSERT_EQ(info->w, GetFrameWidth(idx));
+ ASSERT_EQ(info->h, GetFrameHeight(idx));
+ ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
+ &expected_h, video.flag_codec_,
+ video.smaller_width_larger_size_);
+ EXPECT_EQ(expected_w, info->w)
+ << "Frame " << frame << " had unexpected width";
+ EXPECT_EQ(expected_h, info->h)
+ << "Frame " << frame << " had unexpected height";
+ }
+}
+
+const unsigned int kStepDownFrame = 3;
+const unsigned int kStepUpFrame = 6;
+
+class ResizeInternalTest : public ResizeTest {
+ protected:
+#if WRITE_COMPRESSED_STREAM
+ ResizeInternalTest()
+ : ResizeTest(), frame0_psnr_(0.0), outfile_(nullptr), out_frames_(0) {}
+#else
+ ResizeInternalTest() : ResizeTest(), frame0_psnr_(0.0) {}
+#endif
+
+ virtual ~ResizeInternalTest() {}
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+#if WRITE_COMPRESSED_STREAM
+ outfile_ = fopen("vp90-2-05-resize.ivf", "wb");
+#endif
+ }
+
+ virtual void EndPassHook() {
+#if WRITE_COMPRESSED_STREAM
+ if (outfile_) {
+ if (!fseek(outfile_, 0, SEEK_SET))
+ write_ivf_file_header(&cfg_, out_frames_, outfile_);
+ fclose(outfile_);
+ outfile_ = nullptr;
+ }
+#endif
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (change_config_) {
+ int new_q = 60;
+ if (video->frame() == 0) {
+ struct vpx_scaling_mode mode = { VP8E_ONETWO, VP8E_ONETWO };
+ encoder->Control(VP8E_SET_SCALEMODE, &mode);
+ }
+ if (video->frame() == 1) {
+ struct vpx_scaling_mode mode = { VP8E_NORMAL, VP8E_NORMAL };
+ encoder->Control(VP8E_SET_SCALEMODE, &mode);
+ cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
+ encoder->Config(&cfg_);
+ }
+ } else {
+ if (video->frame() == kStepDownFrame) {
+ struct vpx_scaling_mode mode = { VP8E_FOURFIVE, VP8E_THREEFIVE };
+ encoder->Control(VP8E_SET_SCALEMODE, &mode);
+ }
+ if (video->frame() == kStepUpFrame) {
+ struct vpx_scaling_mode mode = { VP8E_NORMAL, VP8E_NORMAL };
+ encoder->Control(VP8E_SET_SCALEMODE, &mode);
+ }
+ }
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
+ EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
+ }
+
+#if WRITE_COMPRESSED_STREAM
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ ++out_frames_;
+
+ // Write initial file header if first frame.
+ if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
+
+ // Write frame header and data.
+ write_ivf_frame_header(pkt, outfile_);
+ (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
+ }
+#endif
+
+ double frame0_psnr_;
+ bool change_config_;
+#if WRITE_COMPRESSED_STREAM
+ FILE *outfile_;
+ unsigned int out_frames_;
+#endif
+};
+
+TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 10);
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ change_config_ = false;
+
+ // q picked such that initial keyframe on this clip is ~30dB PSNR
+ cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
+
+ // If the number of frames being encoded is smaller than g_lag_in_frames
+ // the encoded frame is unavailable using the current API. Comparing
+ // frames to detect mismatch would then not be possible. Set
+ // g_lag_in_frames = 0 to get around this.
+ cfg_.g_lag_in_frames = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ const vpx_codec_pts_t pts = info->pts;
+ if (pts >= kStepDownFrame && pts < kStepUpFrame) {
+ ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
+ ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
+ } else {
+ EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
+ EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
+ }
+ }
+}
+
+TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) {
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 10);
+ cfg_.g_w = 352;
+ cfg_.g_h = 288;
+ change_config_ = true;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+class ResizeRealtimeTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ ResizeRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~ResizeRealtimeTest() {}
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ }
+
+ if (change_bitrate_ && video->frame() == 120) {
+ change_bitrate_ = false;
+ cfg_.rc_target_bitrate = 500;
+ encoder->Config(&cfg_);
+ }
+ }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ set_cpu_used_ = GET_PARAM(2);
+ }
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ vpx_codec_pts_t pts) {
+ frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
+ }
+
+ virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
+ double mismatch_psnr = compute_psnr(img1, img2);
+ mismatch_psnr_ += mismatch_psnr;
+ ++mismatch_nframes_;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ ASSERT_NE(static_cast<int>(pkt->data.frame.width[0]), 0);
+ ASSERT_NE(static_cast<int>(pkt->data.frame.height[0]), 0);
+ encode_frame_width_.push_back(pkt->data.frame.width[0]);
+ encode_frame_height_.push_back(pkt->data.frame.height[0]);
+ }
+
+ unsigned int GetMismatchFrames() { return mismatch_nframes_; }
+
+ unsigned int GetFrameWidth(size_t idx) const {
+ return encode_frame_width_[idx];
+ }
+
+ unsigned int GetFrameHeight(size_t idx) const {
+ return encode_frame_height_[idx];
+ }
+
+ void DefaultConfig() {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.kf_mode = VPX_KF_AUTO;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
+ // Enable dropped frames.
+ cfg_.rc_dropframe_thresh = 1;
+ // Enable error_resilience mode.
+ cfg_.g_error_resilient = 1;
+ // Enable dynamic resizing.
+ cfg_.rc_resize_allowed = 1;
+ // Run at low bitrate.
+ cfg_.rc_target_bitrate = 200;
+ }
+
+ std::vector<FrameInfo> frame_info_list_;
+ int set_cpu_used_;
+ bool change_bitrate_;
+ double mismatch_psnr_;
+ int mismatch_nframes_;
+ std::vector<unsigned int> encode_frame_width_;
+ std::vector<unsigned int> encode_frame_height_;
+};
+
+TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
+ ResizingVideoSource video;
+ video.flag_codec_ = true;
+ video.smaller_width_larger_size_ = false;
+ DefaultConfig();
+ // Disable internal resize for this test.
+ cfg_.rc_resize_allowed = 0;
+ change_bitrate_ = false;
+ mismatch_psnr_ = 0.0;
+ mismatch_nframes_ = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ const unsigned int frame = static_cast<unsigned>(info->pts);
+ unsigned int expected_w;
+ unsigned int expected_h;
+ ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
+ &expected_h, video.flag_codec_,
+ video.smaller_width_larger_size_);
+ EXPECT_EQ(expected_w, info->w)
+ << "Frame " << frame << " had unexpected width";
+ EXPECT_EQ(expected_h, info->h)
+ << "Frame " << frame << " had unexpected height";
+ EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ }
+}
+
+// TODO(https://crbug.com/webm/1642): This causes a segfault in
+// init_encode_frame_mb_context().
+TEST_P(ResizeRealtimeTest, DISABLED_TestExternalResizeSmallerWidthBiggerSize) {
+ ResizingVideoSource video;
+ video.flag_codec_ = true;
+ video.smaller_width_larger_size_ = true;
+ DefaultConfig();
+ // Disable internal resize for this test.
+ cfg_.rc_resize_allowed = 0;
+ change_bitrate_ = false;
+ mismatch_psnr_ = 0.0;
+ mismatch_nframes_ = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ const unsigned int frame = static_cast<unsigned>(info->pts);
+ unsigned int expected_w;
+ unsigned int expected_h;
+ ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, &expected_w,
+ &expected_h, video.flag_codec_,
+ video.smaller_width_larger_size_);
+ EXPECT_EQ(expected_w, info->w)
+ << "Frame " << frame << " had unexpected width";
+ EXPECT_EQ(expected_h, info->h)
+ << "Frame " << frame << " had unexpected height";
+ EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+ }
+}
+
+// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
+// Run at low bitrate, with resize_allowed = 1, and verify that we get
+// one resize down event.
+TEST_P(ResizeRealtimeTest, TestInternalResizeDown) {
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 299);
+ DefaultConfig();
+ cfg_.g_w = 640;
+ cfg_.g_h = 480;
+ change_bitrate_ = false;
+ mismatch_psnr_ = 0.0;
+ mismatch_nframes_ = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ unsigned int last_w = cfg_.g_w;
+ unsigned int last_h = cfg_.g_h;
+ int resize_count = 0;
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ if (info->w != last_w || info->h != last_h) {
+ // Verify that resize down occurs.
+ ASSERT_LT(info->w, last_w);
+ ASSERT_LT(info->h, last_h);
+ last_w = info->w;
+ last_h = info->h;
+ resize_count++;
+ }
+ }
+
+#if CONFIG_VP9_DECODER
+ // Verify that we get 1 resize down event in this test.
+ ASSERT_EQ(1, resize_count) << "Resizing should occur.";
+ EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+#else
+ printf("Warning: VP9 decoder unavailable, unable to check resize count!\n");
+#endif
+}
+
+// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
+// Start at low target bitrate, raise the bitrate in the middle of the clip,
+// scaling-up should occur after bitrate changed.
+TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ DefaultConfig();
+ cfg_.g_w = 640;
+ cfg_.g_h = 480;
+ change_bitrate_ = true;
+ mismatch_psnr_ = 0.0;
+ mismatch_nframes_ = 0;
+ // Disable dropped frames.
+ cfg_.rc_dropframe_thresh = 0;
+ // Starting bitrate low.
+ cfg_.rc_target_bitrate = 80;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ unsigned int last_w = cfg_.g_w;
+ unsigned int last_h = cfg_.g_h;
+ int resize_count = 0;
+ for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+ info != frame_info_list_.end(); ++info) {
+ const size_t idx = info - frame_info_list_.begin();
+ ASSERT_EQ(info->w, GetFrameWidth(idx));
+ ASSERT_EQ(info->h, GetFrameHeight(idx));
+ if (info->w != last_w || info->h != last_h) {
+ resize_count++;
+ if (resize_count <= 2) {
+ // Verify that resize down occurs.
+ ASSERT_LT(info->w, last_w);
+ ASSERT_LT(info->h, last_h);
+ } else if (resize_count > 2) {
+ // Verify that resize up occurs.
+ ASSERT_GT(info->w, last_w);
+ ASSERT_GT(info->h, last_h);
+ }
+ last_w = info->w;
+ last_h = info->h;
+ }
+ }
+
+#if CONFIG_VP9_DECODER
+ // Verify that we get 4 resize events in this test.
+ ASSERT_EQ(resize_count, 4) << "Resizing should occur twice.";
+ EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+#else
+ printf("Warning: VP9 decoder unavailable, unable to check resize count!\n");
+#endif
+}
+
+vpx_img_fmt_t CspForFrameNumber(int frame) {
+ if (frame < 10) return VPX_IMG_FMT_I420;
+ if (frame < 20) return VPX_IMG_FMT_I444;
+ return VPX_IMG_FMT_I420;
+}
+
+class ResizeCspTest : public ResizeTest {
+ protected:
+#if WRITE_COMPRESSED_STREAM
+ ResizeCspTest()
+ : ResizeTest(), frame0_psnr_(0.0), outfile_(nullptr), out_frames_(0) {}
+#else
+ ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
+#endif
+
+ virtual ~ResizeCspTest() {}
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+#if WRITE_COMPRESSED_STREAM
+ outfile_ = fopen("vp91-2-05-cspchape.ivf", "wb");
+#endif
+ }
+
+ virtual void EndPassHook() {
+#if WRITE_COMPRESSED_STREAM
+ if (outfile_) {
+ if (!fseek(outfile_, 0, SEEK_SET))
+ write_ivf_file_header(&cfg_, out_frames_, outfile_);
+ fclose(outfile_);
+ outfile_ = nullptr;
+ }
+#endif
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (CspForFrameNumber(video->frame()) != VPX_IMG_FMT_I420 &&
+ cfg_.g_profile != 1) {
+ cfg_.g_profile = 1;
+ encoder->Config(&cfg_);
+ }
+ if (CspForFrameNumber(video->frame()) == VPX_IMG_FMT_I420 &&
+ cfg_.g_profile != 0) {
+ cfg_.g_profile = 0;
+ encoder->Config(&cfg_);
+ }
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (frame0_psnr_ == 0.) frame0_psnr_ = pkt->data.psnr.psnr[0];
+ EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
+ }
+
+#if WRITE_COMPRESSED_STREAM
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ ++out_frames_;
+
+ // Write initial file header if first frame.
+ if (pkt->data.frame.pts == 0) write_ivf_file_header(&cfg_, 0, outfile_);
+
+ // Write frame header and data.
+ write_ivf_frame_header(pkt, outfile_);
+ (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
+ }
+#endif
+
+ double frame0_psnr_;
+#if WRITE_COMPRESSED_STREAM
+ FILE *outfile_;
+ unsigned int out_frames_;
+#endif
+};
+
+class ResizingCspVideoSource : public ::libvpx_test::DummyVideoSource {
+ public:
+ ResizingCspVideoSource() {
+ SetSize(kInitialWidth, kInitialHeight);
+ limit_ = 30;
+ }
+
+ virtual ~ResizingCspVideoSource() {}
+
+ protected:
+ virtual void Next() {
+ ++frame_;
+ SetImageFormat(CspForFrameNumber(frame_));
+ FillFrame();
+ }
+};
+
+TEST_P(ResizeCspTest, TestResizeCspWorks) {
+ ResizingCspVideoSource video;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
+ cfg_.g_lag_in_frames = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP8_INSTANTIATE_TEST_SUITE(ResizeTest, ONE_PASS_TEST_MODES);
+VP9_INSTANTIATE_TEST_SUITE(ResizeTest, ONE_PASS_TEST_MODES);
+VP9_INSTANTIATE_TEST_SUITE(ResizeInternalTest,
+ ::testing::Values(::libvpx_test::kOnePassBest));
+VP9_INSTANTIATE_TEST_SUITE(ResizeRealtimeTest,
+ ::testing::Values(::libvpx_test::kRealTime),
+ ::testing::Range(5, 9));
+VP9_INSTANTIATE_TEST_SUITE(ResizeCspTest,
+ ::testing::Values(::libvpx_test::kRealTime));
+} // namespace
diff --git a/media/libvpx/libvpx/test/resize_util.sh b/media/libvpx/libvpx/test/resize_util.sh
new file mode 100755
index 0000000000..a9b0f81e2b
--- /dev/null
+++ b/media/libvpx/libvpx/test/resize_util.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx resize_util example code. To add new tests to
+## this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to resize_util_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+resize_util_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Resizes $YUV_RAW_INPUT using the resize_util example. $1 is the output
+# dimensions that will be passed to resize_util.
+resize_util() {
+ local resizer="${LIBVPX_BIN_PATH}/resize_util${VPX_TEST_EXE_SUFFIX}"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/resize_util.raw"
+ local frames_to_resize="10"
+ local target_dimensions="$1"
+
+ # resize_util is available only when CONFIG_SHARED is disabled.
+ if [ -z "$(vpx_config_option_enabled CONFIG_SHARED)" ]; then
+ if [ ! -x "${resizer}" ]; then
+ elog "${resizer} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${resizer}" "${YUV_RAW_INPUT}" \
+ "${YUV_RAW_INPUT_WIDTH}x${YUV_RAW_INPUT_HEIGHT}" \
+ "${target_dimensions}" "${output_file}" ${frames_to_resize} \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+ fi
+}
+
+# Halves each dimension of $YUV_RAW_INPUT using resize_util().
+resize_down() {
+ local target_width=$((${YUV_RAW_INPUT_WIDTH} / 2))
+ local target_height=$((${YUV_RAW_INPUT_HEIGHT} / 2))
+
+ resize_util "${target_width}x${target_height}"
+}
+
+# Doubles each dimension of $YUV_RAW_INPUT using resize_util().
+resize_up() {
+ local target_width=$((${YUV_RAW_INPUT_WIDTH} * 2))
+ local target_height=$((${YUV_RAW_INPUT_HEIGHT} * 2))
+
+ resize_util "${target_width}x${target_height}"
+}
+
+resize_util_tests="resize_down
+ resize_up"
+
+run_tests resize_util_verify_environment "${resize_util_tests}"
diff --git a/media/libvpx/libvpx/test/sad_test.cc b/media/libvpx/libvpx/test/sad_test.cc
new file mode 100644
index 0000000000..92b3a14d68
--- /dev/null
+++ b/media/libvpx/libvpx/test/sad_test.cc
@@ -0,0 +1,2004 @@
+/*
+ * 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 <string.h>
+#include <limits.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/msvc.h"
+#include "vpx_ports/vpx_timer.h"
+
+// const[expr] should be sufficient for DECLARE_ALIGNED but early
+// implementations of c++11 appear to have some issues with it.
+#define kDataAlignment 32
+
+template <typename Function>
+struct TestParams {
+ TestParams(int w, int h, Function f, int bd = -1)
+ : width(w), height(h), bit_depth(bd), func(f) {}
+ int width, height, bit_depth;
+ Function func;
+};
+
+typedef unsigned int (*SadMxNFunc)(const uint8_t *src_ptr, int src_stride,
+ const uint8_t *ref_ptr, int ref_stride);
+typedef TestParams<SadMxNFunc> SadMxNParam;
+
+typedef unsigned int (*SadSkipMxNFunc)(const uint8_t *src_ptr, int src_stride,
+ const uint8_t *ref_ptr, int ref_stride);
+typedef TestParams<SadSkipMxNFunc> SadSkipMxNParam;
+
+typedef unsigned int (*SadMxNAvgFunc)(const uint8_t *src_ptr, int src_stride,
+ const uint8_t *ref_ptr, int ref_stride,
+ const uint8_t *second_pred);
+typedef TestParams<SadMxNAvgFunc> SadMxNAvgParam;
+
+typedef void (*SadMxNx4Func)(const uint8_t *src_ptr, int src_stride,
+ const uint8_t *const ref_ptr[], int ref_stride,
+ unsigned int *sad_array);
+typedef TestParams<SadMxNx4Func> SadMxNx4Param;
+
+typedef void (*SadSkipMxNx4Func)(const uint8_t *src_ptr, int src_stride,
+ const uint8_t *const ref_ptr[], int ref_stride,
+ unsigned int *sad_array);
+typedef TestParams<SadSkipMxNx4Func> SadSkipMxNx4Param;
+
+typedef void (*SadMxNx8Func)(const uint8_t *src_ptr, int src_stride,
+ const uint8_t *ref_ptr, int ref_stride,
+ unsigned int *sad_array);
+
+using libvpx_test::ACMRandom;
+
+namespace {
+template <typename ParamType>
+class SADTestBase : public ::testing::TestWithParam<ParamType> {
+ public:
+ explicit SADTestBase(const ParamType &params) : params_(params) {}
+
+ virtual void SetUp() {
+ source_data8_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBlockSize));
+ reference_data8_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize));
+ second_pred8_ =
+ reinterpret_cast<uint8_t *>(vpx_memalign(kDataAlignment, 64 * 64));
+ source_data16_ = reinterpret_cast<uint16_t *>(
+ vpx_memalign(kDataAlignment, kDataBlockSize * sizeof(uint16_t)));
+ reference_data16_ = reinterpret_cast<uint16_t *>(
+ vpx_memalign(kDataAlignment, kDataBufferSize * sizeof(uint16_t)));
+ second_pred16_ = reinterpret_cast<uint16_t *>(
+ vpx_memalign(kDataAlignment, 64 * 64 * sizeof(uint16_t)));
+
+ if (params_.bit_depth == -1) {
+ use_high_bit_depth_ = false;
+ bit_depth_ = VPX_BITS_8;
+ source_data_ = source_data8_;
+ reference_data_ = reference_data8_;
+ second_pred_ = second_pred8_;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ use_high_bit_depth_ = true;
+ bit_depth_ = static_cast<vpx_bit_depth_t>(params_.bit_depth);
+ source_data_ = CONVERT_TO_BYTEPTR(source_data16_);
+ reference_data_ = CONVERT_TO_BYTEPTR(reference_data16_);
+ second_pred_ = CONVERT_TO_BYTEPTR(second_pred16_);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ mask_ = (1 << bit_depth_) - 1;
+ source_stride_ = (params_.width + 63) & ~63;
+ reference_stride_ = params_.width * 2;
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ virtual void TearDown() {
+ vpx_free(source_data8_);
+ source_data8_ = nullptr;
+ vpx_free(reference_data8_);
+ reference_data8_ = nullptr;
+ vpx_free(second_pred8_);
+ second_pred8_ = nullptr;
+ vpx_free(source_data16_);
+ source_data16_ = nullptr;
+ vpx_free(reference_data16_);
+ reference_data16_ = nullptr;
+ vpx_free(second_pred16_);
+ second_pred16_ = nullptr;
+
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ // Handle blocks up to 4 blocks 64x64 with stride up to 128
+ // crbug.com/webm/1660
+ static const int kDataBlockSize = 64 * 128;
+ static const int kDataBufferSize = 4 * kDataBlockSize;
+
+ int GetBlockRefOffset(int block_idx) const {
+ return block_idx * kDataBlockSize;
+ }
+
+ uint8_t *GetReferenceFromOffset(int ref_offset) const {
+ assert((params_.height - 1) * reference_stride_ + params_.width - 1 +
+ ref_offset <
+ kDataBufferSize);
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (use_high_bit_depth_) {
+ return CONVERT_TO_BYTEPTR(CONVERT_TO_SHORTPTR(reference_data_) +
+ ref_offset);
+ }
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ return reference_data_ + ref_offset;
+ }
+
+ uint8_t *GetReference(int block_idx) const {
+ return GetReferenceFromOffset(GetBlockRefOffset(block_idx));
+ }
+
+ // Sum of Absolute Differences. Given two blocks, calculate the absolute
+ // difference between two pixels in the same relative location; accumulate.
+ uint32_t ReferenceSAD(int ref_offset) const {
+ uint32_t sad = 0;
+ const uint8_t *const reference8 = GetReferenceFromOffset(ref_offset);
+ const uint8_t *const source8 = source_data_;
+#if CONFIG_VP9_HIGHBITDEPTH
+ const uint16_t *const reference16 =
+ CONVERT_TO_SHORTPTR(GetReferenceFromOffset(ref_offset));
+ const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ for (int h = 0; h < params_.height; ++h) {
+ for (int w = 0; w < params_.width; ++w) {
+ if (!use_high_bit_depth_) {
+ sad += abs(source8[h * source_stride_ + w] -
+ reference8[h * reference_stride_ + w]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ sad += abs(source16[h * source_stride_ + w] -
+ reference16[h * reference_stride_ + w]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ return sad;
+ }
+
+ // Sum of Absolute Differences Skip rows. Given two blocks, calculate the
+ // absolute difference between two pixels in the same relative location every
+ // other row; accumulate and double the result at the end.
+ uint32_t ReferenceSADSkip(int ref_offset) const {
+ uint32_t sad = 0;
+ const uint8_t *const reference8 = GetReferenceFromOffset(ref_offset);
+ const uint8_t *const source8 = source_data_;
+#if CONFIG_VP9_HIGHBITDEPTH
+ const uint16_t *const reference16 =
+ CONVERT_TO_SHORTPTR(GetReferenceFromOffset(ref_offset));
+ const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ for (int h = 0; h < params_.height; h += 2) {
+ for (int w = 0; w < params_.width; ++w) {
+ if (!use_high_bit_depth_) {
+ sad += abs(source8[h * source_stride_ + w] -
+ reference8[h * reference_stride_ + w]);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ sad += abs(source16[h * source_stride_ + w] -
+ reference16[h * reference_stride_ + w]);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ return sad * 2;
+ }
+
+ // Sum of Absolute Differences Average. Given two blocks, and a prediction
+ // calculate the absolute difference between one pixel and average of the
+ // corresponding and predicted pixels; accumulate.
+ unsigned int ReferenceSADavg(int block_idx) const {
+ unsigned int sad = 0;
+ const uint8_t *const reference8 = GetReference(block_idx);
+ const uint8_t *const source8 = source_data_;
+ const uint8_t *const second_pred8 = second_pred_;
+#if CONFIG_VP9_HIGHBITDEPTH
+ const uint16_t *const reference16 =
+ CONVERT_TO_SHORTPTR(GetReference(block_idx));
+ const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_);
+ const uint16_t *const second_pred16 = CONVERT_TO_SHORTPTR(second_pred_);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ for (int h = 0; h < params_.height; ++h) {
+ for (int w = 0; w < params_.width; ++w) {
+ if (!use_high_bit_depth_) {
+ const int tmp = second_pred8[h * params_.width + w] +
+ reference8[h * reference_stride_ + w];
+ const uint8_t comp_pred = ROUND_POWER_OF_TWO(tmp, 1);
+ sad += abs(source8[h * source_stride_ + w] - comp_pred);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ const int tmp = second_pred16[h * params_.width + w] +
+ reference16[h * reference_stride_ + w];
+ const uint16_t comp_pred = ROUND_POWER_OF_TWO(tmp, 1);
+ sad += abs(source16[h * source_stride_ + w] - comp_pred);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ return sad;
+ }
+
+ void FillConstant(uint8_t *data, int stride, uint16_t fill_constant) const {
+ uint8_t *data8 = data;
+#if CONFIG_VP9_HIGHBITDEPTH
+ uint16_t *data16 = CONVERT_TO_SHORTPTR(data);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ for (int h = 0; h < params_.height; ++h) {
+ for (int w = 0; w < params_.width; ++w) {
+ if (!use_high_bit_depth_) {
+ data8[h * stride + w] = static_cast<uint8_t>(fill_constant);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ data16[h * stride + w] = fill_constant;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ }
+
+ void FillRandomWH(uint8_t *data, int stride, int w, int h) {
+ uint8_t *data8 = data;
+#if CONFIG_VP9_HIGHBITDEPTH
+ uint16_t *data16 = CONVERT_TO_SHORTPTR(data);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ for (int r = 0; r < h; ++r) {
+ for (int c = 0; c < w; ++c) {
+ if (!use_high_bit_depth_) {
+ data8[r * stride + c] = rnd_.Rand8();
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ data16[r * stride + c] = rnd_.Rand16() & mask_;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ }
+
+ void FillRandom(uint8_t *data, int stride) {
+ FillRandomWH(data, stride, params_.width, params_.height);
+ }
+
+ uint32_t mask_;
+ vpx_bit_depth_t bit_depth_;
+ int source_stride_;
+ int reference_stride_;
+ bool use_high_bit_depth_;
+
+ uint8_t *source_data_;
+ uint8_t *reference_data_;
+ uint8_t *second_pred_;
+ uint8_t *source_data8_;
+ uint8_t *reference_data8_;
+ uint8_t *second_pred8_;
+ uint16_t *source_data16_;
+ uint16_t *reference_data16_;
+ uint16_t *second_pred16_;
+
+ ACMRandom rnd_;
+ ParamType params_;
+};
+
+class SADx4Test : public SADTestBase<SadMxNx4Param> {
+ public:
+ SADx4Test() : SADTestBase(GetParam()) {}
+
+ protected:
+ void SADs(unsigned int *results) const {
+ const uint8_t *references[] = { GetReference(0), GetReference(1),
+ GetReference(2), GetReference(3) };
+
+ ASM_REGISTER_STATE_CHECK(params_.func(
+ source_data_, source_stride_, references, reference_stride_, results));
+ }
+
+ void CheckSADs() const {
+ uint32_t reference_sad;
+ DECLARE_ALIGNED(kDataAlignment, uint32_t, exp_sad[4]);
+
+ SADs(exp_sad);
+ for (int block = 0; block < 4; ++block) {
+ reference_sad = ReferenceSAD(GetBlockRefOffset(block));
+
+ EXPECT_EQ(reference_sad, exp_sad[block]) << "block " << block;
+ }
+ }
+};
+
+class SADSkipx4Test : public SADTestBase<SadMxNx4Param> {
+ public:
+ SADSkipx4Test() : SADTestBase(GetParam()) {}
+
+ protected:
+ void SADs(unsigned int *results) const {
+ const uint8_t *references[] = { GetReference(0), GetReference(1),
+ GetReference(2), GetReference(3) };
+
+ ASM_REGISTER_STATE_CHECK(params_.func(
+ source_data_, source_stride_, references, reference_stride_, results));
+ }
+
+ void CheckSADs() const {
+ uint32_t reference_sad;
+ DECLARE_ALIGNED(kDataAlignment, uint32_t, exp_sad[4]);
+
+ SADs(exp_sad);
+ for (int block = 0; block < 4; ++block) {
+ reference_sad = ReferenceSADSkip(GetBlockRefOffset(block));
+
+ EXPECT_EQ(reference_sad, exp_sad[block]) << "block " << block;
+ }
+ }
+};
+
+class SADTest : public AbstractBench, public SADTestBase<SadMxNParam> {
+ public:
+ SADTest() : SADTestBase(GetParam()) {}
+
+ protected:
+ unsigned int SAD(int block_idx) const {
+ unsigned int ret;
+ const uint8_t *const reference = GetReference(block_idx);
+
+ ASM_REGISTER_STATE_CHECK(ret = params_.func(source_data_, source_stride_,
+ reference, reference_stride_));
+ return ret;
+ }
+
+ void CheckSAD() const {
+ const unsigned int reference_sad = ReferenceSAD(GetBlockRefOffset(0));
+ const unsigned int exp_sad = SAD(0);
+
+ ASSERT_EQ(reference_sad, exp_sad);
+ }
+
+ void Run() override {
+ params_.func(source_data_, source_stride_, reference_data_,
+ reference_stride_);
+ }
+};
+
+class SADSkipTest : public AbstractBench, public SADTestBase<SadMxNParam> {
+ public:
+ SADSkipTest() : SADTestBase(GetParam()) {}
+
+ protected:
+ unsigned int SAD(int block_idx) const {
+ unsigned int ret;
+ const uint8_t *const reference = GetReference(block_idx);
+
+ ASM_REGISTER_STATE_CHECK(ret = params_.func(source_data_, source_stride_,
+ reference, reference_stride_));
+ return ret;
+ }
+
+ void CheckSAD() const {
+ const unsigned int reference_sad = ReferenceSADSkip(GetBlockRefOffset(0));
+ const unsigned int exp_sad = SAD(0);
+
+ ASSERT_EQ(reference_sad, exp_sad);
+ }
+
+ void Run() override {
+ params_.func(source_data_, source_stride_, reference_data_,
+ reference_stride_);
+ }
+};
+
+class SADavgTest : public AbstractBench, public SADTestBase<SadMxNAvgParam> {
+ public:
+ SADavgTest() : SADTestBase(GetParam()) {}
+
+ protected:
+ unsigned int SAD_avg(int block_idx) const {
+ unsigned int ret;
+ const uint8_t *const reference = GetReference(block_idx);
+
+ ASM_REGISTER_STATE_CHECK(ret = params_.func(source_data_, source_stride_,
+ reference, reference_stride_,
+ second_pred_));
+ return ret;
+ }
+
+ void CheckSAD() const {
+ const unsigned int reference_sad = ReferenceSADavg(0);
+ const unsigned int exp_sad = SAD_avg(0);
+
+ ASSERT_EQ(reference_sad, exp_sad);
+ }
+
+ void Run() override {
+ params_.func(source_data_, source_stride_, reference_data_,
+ reference_stride_, second_pred_);
+ }
+};
+
+TEST_P(SADTest, MaxRef) {
+ FillConstant(source_data_, source_stride_, 0);
+ FillConstant(reference_data_, reference_stride_, mask_);
+ CheckSAD();
+}
+
+TEST_P(SADTest, MaxSrc) {
+ FillConstant(source_data_, source_stride_, mask_);
+ FillConstant(reference_data_, reference_stride_, 0);
+ CheckSAD();
+}
+
+TEST_P(SADTest, ShortRef) {
+ const int tmp_stride = reference_stride_;
+ reference_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ CheckSAD();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADTest, UnalignedRef) {
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ const int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ CheckSAD();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADTest, ShortSrc) {
+ const int tmp_stride = source_stride_;
+ source_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ CheckSAD();
+ source_stride_ = tmp_stride;
+}
+
+TEST_P(SADTest, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 50000000 / (params_.width * params_.height);
+ FillRandom(source_data_, source_stride_);
+
+ RunNTimes(kCountSpeedTestBlock);
+
+ char title[16];
+ snprintf(title, sizeof(title), "%dx%d", params_.width, params_.height);
+ PrintMedian(title);
+}
+
+TEST_P(SADSkipTest, MaxRef) {
+ FillConstant(source_data_, source_stride_, 0);
+ FillConstant(reference_data_, reference_stride_, mask_);
+ CheckSAD();
+}
+
+TEST_P(SADSkipTest, MaxSrc) {
+ FillConstant(source_data_, source_stride_, mask_);
+ FillConstant(reference_data_, reference_stride_, 0);
+ CheckSAD();
+}
+
+TEST_P(SADSkipTest, ShortRef) {
+ const int tmp_stride = reference_stride_;
+ reference_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ CheckSAD();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipTest, UnalignedRef) {
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ const int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ CheckSAD();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipTest, ShortSrc) {
+ const int tmp_stride = source_stride_;
+ source_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ CheckSAD();
+ source_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipTest, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 50000000 / (params_.width * params_.height);
+ FillRandom(source_data_, source_stride_);
+
+ RunNTimes(kCountSpeedTestBlock);
+
+ char title[16];
+ snprintf(title, sizeof(title), "%dx%d", params_.width, params_.height);
+ PrintMedian(title);
+}
+
+TEST_P(SADavgTest, MaxRef) {
+ FillConstant(source_data_, source_stride_, 0);
+ FillConstant(reference_data_, reference_stride_, mask_);
+ FillConstant(second_pred_, params_.width, 0);
+ CheckSAD();
+}
+TEST_P(SADavgTest, MaxSrc) {
+ FillConstant(source_data_, source_stride_, mask_);
+ FillConstant(reference_data_, reference_stride_, 0);
+ FillConstant(second_pred_, params_.width, 0);
+ CheckSAD();
+}
+
+TEST_P(SADavgTest, ShortRef) {
+ const int tmp_stride = reference_stride_;
+ reference_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ FillRandom(second_pred_, params_.width);
+ CheckSAD();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADavgTest, UnalignedRef) {
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ const int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ FillRandom(second_pred_, params_.width);
+ CheckSAD();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADavgTest, ShortSrc) {
+ const int tmp_stride = source_stride_;
+ source_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ FillRandom(second_pred_, params_.width);
+ CheckSAD();
+ source_stride_ = tmp_stride;
+}
+
+TEST_P(SADavgTest, DISABLED_Speed) {
+ const int kCountSpeedTestBlock = 50000000 / (params_.width * params_.height);
+ FillRandom(source_data_, source_stride_);
+ FillRandom(reference_data_, reference_stride_);
+ FillRandom(second_pred_, params_.width);
+
+ RunNTimes(kCountSpeedTestBlock);
+
+ char title[16];
+ snprintf(title, sizeof(title), "%dx%d", params_.width, params_.height);
+ PrintMedian(title);
+}
+
+TEST_P(SADx4Test, MaxRef) {
+ FillConstant(source_data_, source_stride_, 0);
+ FillConstant(GetReference(0), reference_stride_, mask_);
+ FillConstant(GetReference(1), reference_stride_, mask_);
+ FillConstant(GetReference(2), reference_stride_, mask_);
+ FillConstant(GetReference(3), reference_stride_, mask_);
+ CheckSADs();
+}
+
+TEST_P(SADx4Test, MaxSrc) {
+ FillConstant(source_data_, source_stride_, mask_);
+ FillConstant(GetReference(0), reference_stride_, 0);
+ FillConstant(GetReference(1), reference_stride_, 0);
+ FillConstant(GetReference(2), reference_stride_, 0);
+ FillConstant(GetReference(3), reference_stride_, 0);
+ CheckSADs();
+}
+
+TEST_P(SADx4Test, ShortRef) {
+ int tmp_stride = reference_stride_;
+ reference_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, UnalignedRef) {
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, ShortSrc) {
+ int tmp_stride = source_stride_;
+ source_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ source_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, SrcAlignedByWidth) {
+ uint8_t *tmp_source_data = source_data_;
+ source_data_ += params_.width;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ source_data_ = tmp_source_data;
+}
+
+TEST_P(SADx4Test, DISABLED_Speed) {
+ int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ const int kCountSpeedTestBlock = 500000000 / (params_.width * params_.height);
+ uint32_t reference_sad[4];
+ DECLARE_ALIGNED(kDataAlignment, uint32_t, exp_sad[4]);
+ vpx_usec_timer timer;
+ for (int block = 0; block < 4; ++block) {
+ reference_sad[block] = ReferenceSAD(GetBlockRefOffset(block));
+ }
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ SADs(exp_sad);
+ }
+ vpx_usec_timer_mark(&timer);
+ for (int block = 0; block < 4; ++block) {
+ EXPECT_EQ(reference_sad[block], exp_sad[block]) << "block " << block;
+ }
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+ printf("sad%dx%dx4 (%2dbit) time: %5d ms\n", params_.width, params_.height,
+ bit_depth_, elapsed_time);
+
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipx4Test, MaxRef) {
+ FillConstant(source_data_, source_stride_, 0);
+ FillConstant(GetReference(0), reference_stride_, mask_);
+ FillConstant(GetReference(1), reference_stride_, mask_);
+ FillConstant(GetReference(2), reference_stride_, mask_);
+ FillConstant(GetReference(3), reference_stride_, mask_);
+ CheckSADs();
+}
+
+TEST_P(SADSkipx4Test, MaxSrc) {
+ FillConstant(source_data_, source_stride_, mask_);
+ FillConstant(GetReference(0), reference_stride_, 0);
+ FillConstant(GetReference(1), reference_stride_, 0);
+ FillConstant(GetReference(2), reference_stride_, 0);
+ FillConstant(GetReference(3), reference_stride_, 0);
+ CheckSADs();
+}
+
+TEST_P(SADSkipx4Test, ShortRef) {
+ int tmp_stride = reference_stride_;
+ reference_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipx4Test, UnalignedRef) {
+ // The reference frame, but not the source frame, may be unaligned for
+ // certain types of searches.
+ int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipx4Test, ShortSrc) {
+ int tmp_stride = source_stride_;
+ source_stride_ >>= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ source_stride_ = tmp_stride;
+}
+
+TEST_P(SADSkipx4Test, SrcAlignedByWidth) {
+ uint8_t *tmp_source_data = source_data_;
+ source_data_ += params_.width;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ CheckSADs();
+ source_data_ = tmp_source_data;
+}
+
+TEST_P(SADSkipx4Test, DISABLED_Speed) {
+ int tmp_stride = reference_stride_;
+ reference_stride_ -= 1;
+ FillRandom(source_data_, source_stride_);
+ FillRandom(GetReference(0), reference_stride_);
+ FillRandom(GetReference(1), reference_stride_);
+ FillRandom(GetReference(2), reference_stride_);
+ FillRandom(GetReference(3), reference_stride_);
+ const int kCountSpeedTestBlock = 500000000 / (params_.width * params_.height);
+ uint32_t reference_sad[4];
+ DECLARE_ALIGNED(kDataAlignment, uint32_t, exp_sad[4]);
+ vpx_usec_timer timer;
+ for (int block = 0; block < 4; ++block) {
+ reference_sad[block] = ReferenceSADSkip(GetBlockRefOffset(block));
+ }
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ SADs(exp_sad);
+ }
+ vpx_usec_timer_mark(&timer);
+ for (int block = 0; block < 4; ++block) {
+ EXPECT_EQ(reference_sad[block], exp_sad[block]) << "block " << block;
+ }
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+ printf("sad%dx%dx4 (%2dbit) time: %5d ms\n", params_.width, params_.height,
+ bit_depth_, elapsed_time);
+
+ reference_stride_ = tmp_stride;
+}
+
+//------------------------------------------------------------------------------
+// C functions
+const SadMxNParam c_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_c),
+ SadMxNParam(64, 32, &vpx_sad64x32_c),
+ SadMxNParam(32, 64, &vpx_sad32x64_c),
+ SadMxNParam(32, 32, &vpx_sad32x32_c),
+ SadMxNParam(32, 16, &vpx_sad32x16_c),
+ SadMxNParam(16, 32, &vpx_sad16x32_c),
+ SadMxNParam(16, 16, &vpx_sad16x16_c),
+ SadMxNParam(16, 8, &vpx_sad16x8_c),
+ SadMxNParam(8, 16, &vpx_sad8x16_c),
+ SadMxNParam(8, 8, &vpx_sad8x8_c),
+ SadMxNParam(8, 4, &vpx_sad8x4_c),
+ SadMxNParam(4, 8, &vpx_sad4x8_c),
+ SadMxNParam(4, 4, &vpx_sad4x4_c),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_c, 8),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_c, 8),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_c, 8),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_c, 8),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_c, 8),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_c, 8),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_c, 8),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_c, 8),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_c, 8),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_c, 8),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_c, 8),
+ SadMxNParam(4, 8, &vpx_highbd_sad4x8_c, 8),
+ SadMxNParam(4, 4, &vpx_highbd_sad4x4_c, 8),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_c, 10),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_c, 10),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_c, 10),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_c, 10),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_c, 10),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_c, 10),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_c, 10),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_c, 10),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_c, 10),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_c, 10),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_c, 10),
+ SadMxNParam(4, 8, &vpx_highbd_sad4x8_c, 10),
+ SadMxNParam(4, 4, &vpx_highbd_sad4x4_c, 10),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_c, 12),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_c, 12),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_c, 12),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_c, 12),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_c, 12),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_c, 12),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_c, 12),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_c, 12),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_c, 12),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_c, 12),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_c, 12),
+ SadMxNParam(4, 8, &vpx_highbd_sad4x8_c, 12),
+ SadMxNParam(4, 4, &vpx_highbd_sad4x4_c, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(C, SADTest, ::testing::ValuesIn(c_tests));
+
+const SadSkipMxNParam skip_c_tests[] = {
+ SadSkipMxNParam(64, 64, &vpx_sad_skip_64x64_c),
+ SadSkipMxNParam(64, 32, &vpx_sad_skip_64x32_c),
+ SadSkipMxNParam(32, 64, &vpx_sad_skip_32x64_c),
+ SadSkipMxNParam(32, 32, &vpx_sad_skip_32x32_c),
+ SadSkipMxNParam(32, 16, &vpx_sad_skip_32x16_c),
+ SadSkipMxNParam(16, 32, &vpx_sad_skip_16x32_c),
+ SadSkipMxNParam(16, 16, &vpx_sad_skip_16x16_c),
+ SadSkipMxNParam(16, 8, &vpx_sad_skip_16x8_c),
+ SadSkipMxNParam(8, 16, &vpx_sad_skip_8x16_c),
+ SadSkipMxNParam(8, 8, &vpx_sad_skip_8x8_c),
+ SadSkipMxNParam(4, 8, &vpx_sad_skip_4x8_c),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_c, 8),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_c, 8),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_c, 8),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_c, 8),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_c, 8),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_c, 8),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_c, 8),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_c, 8),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_c, 8),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_c, 8),
+ SadSkipMxNParam(4, 8, &vpx_highbd_sad_skip_4x8_c, 8),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_c, 10),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_c, 10),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_c, 10),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_c, 10),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_c, 10),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_c, 10),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_c, 10),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_c, 10),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_c, 10),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_c, 10),
+ SadSkipMxNParam(4, 8, &vpx_highbd_sad_skip_4x8_c, 10),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_c, 12),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_c, 12),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_c, 12),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_c, 12),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_c, 12),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_c, 12),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_c, 12),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_c, 12),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_c, 12),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_c, 12),
+ SadSkipMxNParam(4, 8, &vpx_highbd_sad_skip_4x8_c, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(C, SADSkipTest, ::testing::ValuesIn(skip_c_tests));
+
+const SadMxNAvgParam avg_c_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_c),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_c),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_c),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_c),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_c),
+ SadMxNAvgParam(16, 32, &vpx_sad16x32_avg_c),
+ SadMxNAvgParam(16, 16, &vpx_sad16x16_avg_c),
+ SadMxNAvgParam(16, 8, &vpx_sad16x8_avg_c),
+ SadMxNAvgParam(8, 16, &vpx_sad8x16_avg_c),
+ SadMxNAvgParam(8, 8, &vpx_sad8x8_avg_c),
+ SadMxNAvgParam(8, 4, &vpx_sad8x4_avg_c),
+ SadMxNAvgParam(4, 8, &vpx_sad4x8_avg_c),
+ SadMxNAvgParam(4, 4, &vpx_sad4x4_avg_c),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_c, 8),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_c, 8),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_c, 8),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_c, 8),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_c, 8),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_c, 8),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_c, 8),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_c, 8),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_c, 8),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_c, 8),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_c, 8),
+ SadMxNAvgParam(4, 8, &vpx_highbd_sad4x8_avg_c, 8),
+ SadMxNAvgParam(4, 4, &vpx_highbd_sad4x4_avg_c, 8),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_c, 10),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_c, 10),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_c, 10),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_c, 10),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_c, 10),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_c, 10),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_c, 10),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_c, 10),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_c, 10),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_c, 10),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_c, 10),
+ SadMxNAvgParam(4, 8, &vpx_highbd_sad4x8_avg_c, 10),
+ SadMxNAvgParam(4, 4, &vpx_highbd_sad4x4_avg_c, 10),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_c, 12),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_c, 12),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_c, 12),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_c, 12),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_c, 12),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_c, 12),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_c, 12),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_c, 12),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_c, 12),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_c, 12),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_c, 12),
+ SadMxNAvgParam(4, 8, &vpx_highbd_sad4x8_avg_c, 12),
+ SadMxNAvgParam(4, 4, &vpx_highbd_sad4x4_avg_c, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(C, SADavgTest, ::testing::ValuesIn(avg_c_tests));
+
+const SadMxNx4Param x4d_c_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_c),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_c),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_c),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_c),
+ SadMxNx4Param(32, 16, &vpx_sad32x16x4d_c),
+ SadMxNx4Param(16, 32, &vpx_sad16x32x4d_c),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_c),
+ SadMxNx4Param(16, 8, &vpx_sad16x8x4d_c),
+ SadMxNx4Param(8, 16, &vpx_sad8x16x4d_c),
+ SadMxNx4Param(8, 8, &vpx_sad8x8x4d_c),
+ SadMxNx4Param(8, 4, &vpx_sad8x4x4d_c),
+ SadMxNx4Param(4, 8, &vpx_sad4x8x4d_c),
+ SadMxNx4Param(4, 4, &vpx_sad4x4x4d_c),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_c, 8),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_c, 8),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_c, 8),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_c, 8),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_c, 8),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_c, 8),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_c, 8),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_c, 8),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_c, 8),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_c, 8),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_c, 8),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_c, 8),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_c, 8),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_c, 10),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_c, 10),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_c, 10),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_c, 10),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_c, 10),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_c, 10),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_c, 10),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_c, 10),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_c, 10),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_c, 10),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_c, 10),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_c, 10),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_c, 10),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_c, 12),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_c, 12),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_c, 12),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_c, 12),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_c, 12),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_c, 12),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_c, 12),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_c, 12),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_c, 12),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_c, 12),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_c, 12),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_c, 12),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_c, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(C, SADx4Test, ::testing::ValuesIn(x4d_c_tests));
+
+const SadSkipMxNx4Param skip_x4d_c_tests[] = {
+ SadSkipMxNx4Param(64, 64, &vpx_sad_skip_64x64x4d_c),
+ SadSkipMxNx4Param(64, 32, &vpx_sad_skip_64x32x4d_c),
+ SadSkipMxNx4Param(32, 64, &vpx_sad_skip_32x64x4d_c),
+ SadSkipMxNx4Param(32, 32, &vpx_sad_skip_32x32x4d_c),
+ SadSkipMxNx4Param(32, 16, &vpx_sad_skip_32x16x4d_c),
+ SadSkipMxNx4Param(16, 32, &vpx_sad_skip_16x32x4d_c),
+ SadSkipMxNx4Param(16, 16, &vpx_sad_skip_16x16x4d_c),
+ SadSkipMxNx4Param(16, 8, &vpx_sad_skip_16x8x4d_c),
+ SadSkipMxNx4Param(8, 16, &vpx_sad_skip_8x16x4d_c),
+ SadSkipMxNx4Param(8, 8, &vpx_sad_skip_8x8x4d_c),
+ SadSkipMxNx4Param(4, 8, &vpx_sad_skip_4x8x4d_c),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_c, 8),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_c, 8),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_c, 8),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_c, 8),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_c, 8),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_c, 8),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_c, 8),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_c, 8),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_c, 8),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_c, 8),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_c, 8),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_c, 10),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_c, 10),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_c, 10),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_c, 10),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_c, 10),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_c, 10),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_c, 10),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_c, 10),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_c, 10),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_c, 10),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_c, 10),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_c, 12),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_c, 12),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_c, 12),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_c, 12),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_c, 12),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_c, 12),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_c, 12),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_c, 12),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_c, 12),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_c, 12),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_c, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(C, SADSkipx4Test,
+ ::testing::ValuesIn(skip_x4d_c_tests));
+
+//------------------------------------------------------------------------------
+// ARM functions
+#if HAVE_NEON
+const SadMxNParam neon_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_neon),
+ SadMxNParam(64, 32, &vpx_sad64x32_neon),
+ SadMxNParam(32, 32, &vpx_sad32x32_neon),
+ SadMxNParam(16, 32, &vpx_sad16x32_neon),
+ SadMxNParam(16, 16, &vpx_sad16x16_neon),
+ SadMxNParam(16, 8, &vpx_sad16x8_neon),
+ SadMxNParam(8, 16, &vpx_sad8x16_neon),
+ SadMxNParam(8, 8, &vpx_sad8x8_neon),
+ SadMxNParam(8, 4, &vpx_sad8x4_neon),
+ SadMxNParam(4, 8, &vpx_sad4x8_neon),
+ SadMxNParam(4, 4, &vpx_sad4x4_neon),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNParam(4, 4, &vpx_highbd_sad4x4_neon, 8),
+ SadMxNParam(4, 8, &vpx_highbd_sad4x8_neon, 8),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_neon, 8),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_neon, 8),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_neon, 8),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_neon, 8),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_neon, 8),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_neon, 8),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_neon, 8),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_neon, 8),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_neon, 8),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_neon, 8),
+ SadMxNParam(4, 4, &vpx_highbd_sad4x4_neon, 10),
+ SadMxNParam(4, 8, &vpx_highbd_sad4x8_neon, 10),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_neon, 10),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_neon, 10),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_neon, 10),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_neon, 10),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_neon, 10),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_neon, 10),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_neon, 10),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_neon, 10),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_neon, 10),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_neon, 10),
+ SadMxNParam(4, 4, &vpx_highbd_sad4x4_neon, 12),
+ SadMxNParam(4, 8, &vpx_highbd_sad4x8_neon, 12),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_neon, 12),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_neon, 12),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_neon, 12),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_neon, 12),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_neon, 12),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_neon, 12),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_neon, 12),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_neon, 12),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_neon, 12),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_neon, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+};
+INSTANTIATE_TEST_SUITE_P(NEON, SADTest, ::testing::ValuesIn(neon_tests));
+
+const SadSkipMxNParam skip_neon_tests[] = {
+ SadSkipMxNParam(64, 64, &vpx_sad_skip_64x64_neon),
+ SadSkipMxNParam(64, 32, &vpx_sad_skip_64x32_neon),
+ SadSkipMxNParam(32, 64, &vpx_sad_skip_32x64_neon),
+ SadSkipMxNParam(32, 32, &vpx_sad_skip_32x32_neon),
+ SadSkipMxNParam(32, 16, &vpx_sad_skip_32x16_neon),
+ SadSkipMxNParam(16, 32, &vpx_sad_skip_16x32_neon),
+ SadSkipMxNParam(16, 16, &vpx_sad_skip_16x16_neon),
+ SadSkipMxNParam(16, 8, &vpx_sad_skip_16x8_neon),
+ SadSkipMxNParam(8, 16, &vpx_sad_skip_8x16_neon),
+ SadSkipMxNParam(8, 8, &vpx_sad_skip_8x8_neon),
+ SadSkipMxNParam(8, 4, &vpx_sad_skip_8x4_neon),
+ SadSkipMxNParam(4, 8, &vpx_sad_skip_4x8_neon),
+ SadSkipMxNParam(4, 4, &vpx_sad_skip_4x4_neon),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNParam(4, 4, &vpx_highbd_sad_skip_4x4_neon, 8),
+ SadSkipMxNParam(4, 8, &vpx_highbd_sad_skip_4x8_neon, 8),
+ SadSkipMxNParam(8, 4, &vpx_highbd_sad_skip_8x4_neon, 8),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_neon, 8),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_neon, 8),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_neon, 8),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_neon, 8),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_neon, 8),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_neon, 8),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_neon, 8),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_neon, 8),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_neon, 8),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_neon, 8),
+ SadSkipMxNParam(4, 4, &vpx_highbd_sad_skip_4x4_neon, 10),
+ SadSkipMxNParam(4, 8, &vpx_highbd_sad_skip_4x8_neon, 10),
+ SadSkipMxNParam(8, 4, &vpx_highbd_sad_skip_8x4_neon, 10),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_neon, 10),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_neon, 10),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_neon, 10),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_neon, 10),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_neon, 10),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_neon, 10),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_neon, 10),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_neon, 10),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_neon, 10),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_neon, 10),
+ SadSkipMxNParam(4, 4, &vpx_highbd_sad_skip_4x4_neon, 12),
+ SadSkipMxNParam(4, 8, &vpx_highbd_sad_skip_4x8_neon, 12),
+ SadSkipMxNParam(8, 4, &vpx_highbd_sad_skip_8x4_neon, 12),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_neon, 12),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_neon, 12),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_neon, 12),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_neon, 12),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_neon, 12),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_neon, 12),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_neon, 12),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_neon, 12),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_neon, 12),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_neon, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(NEON, SADSkipTest,
+ ::testing::ValuesIn(skip_neon_tests));
+
+const SadMxNAvgParam avg_neon_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_neon),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_neon),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_neon),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_neon),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_neon),
+ SadMxNAvgParam(16, 32, &vpx_sad16x32_avg_neon),
+ SadMxNAvgParam(16, 16, &vpx_sad16x16_avg_neon),
+ SadMxNAvgParam(16, 8, &vpx_sad16x8_avg_neon),
+ SadMxNAvgParam(8, 16, &vpx_sad8x16_avg_neon),
+ SadMxNAvgParam(8, 8, &vpx_sad8x8_avg_neon),
+ SadMxNAvgParam(8, 4, &vpx_sad8x4_avg_neon),
+ SadMxNAvgParam(4, 8, &vpx_sad4x8_avg_neon),
+ SadMxNAvgParam(4, 4, &vpx_sad4x4_avg_neon),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNAvgParam(4, 4, &vpx_highbd_sad4x4_avg_neon, 8),
+ SadMxNAvgParam(4, 8, &vpx_highbd_sad4x8_avg_neon, 8),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_neon, 8),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_neon, 8),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_neon, 8),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_neon, 8),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_neon, 8),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_neon, 8),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_neon, 8),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_neon, 8),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_neon, 8),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_neon, 8),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_neon, 8),
+ SadMxNAvgParam(4, 4, &vpx_highbd_sad4x4_avg_neon, 10),
+ SadMxNAvgParam(4, 8, &vpx_highbd_sad4x8_avg_neon, 10),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_neon, 10),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_neon, 10),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_neon, 10),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_neon, 10),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_neon, 10),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_neon, 10),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_neon, 10),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_neon, 10),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_neon, 10),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_neon, 10),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_neon, 10),
+ SadMxNAvgParam(4, 4, &vpx_highbd_sad4x4_avg_neon, 12),
+ SadMxNAvgParam(4, 8, &vpx_highbd_sad4x8_avg_neon, 12),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_neon, 12),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_neon, 12),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_neon, 12),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_neon, 12),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_neon, 12),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_neon, 12),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_neon, 12),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_neon, 12),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_neon, 12),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_neon, 12),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_neon, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(NEON, SADavgTest, ::testing::ValuesIn(avg_neon_tests));
+
+const SadMxNx4Param x4d_neon_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_neon),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_neon),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_neon),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_neon),
+ SadMxNx4Param(32, 16, &vpx_sad32x16x4d_neon),
+ SadMxNx4Param(16, 32, &vpx_sad16x32x4d_neon),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_neon),
+ SadMxNx4Param(16, 8, &vpx_sad16x8x4d_neon),
+ SadMxNx4Param(8, 16, &vpx_sad8x16x4d_neon),
+ SadMxNx4Param(8, 8, &vpx_sad8x8x4d_neon),
+ SadMxNx4Param(8, 4, &vpx_sad8x4x4d_neon),
+ SadMxNx4Param(4, 8, &vpx_sad4x8x4d_neon),
+ SadMxNx4Param(4, 4, &vpx_sad4x4x4d_neon),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_neon, 8),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_neon, 8),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_neon, 8),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_neon, 8),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_neon, 8),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_neon, 8),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_neon, 8),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_neon, 8),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_neon, 8),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_neon, 8),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_neon, 8),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_neon, 8),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_neon, 10),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_neon, 10),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_neon, 10),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_neon, 10),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_neon, 10),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_neon, 10),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_neon, 10),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_neon, 10),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_neon, 10),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_neon, 10),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_neon, 10),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_neon, 10),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_neon, 12),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_neon, 12),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_neon, 12),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_neon, 12),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_neon, 12),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_neon, 12),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_neon, 12),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_neon, 12),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_neon, 12),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_neon, 12),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_neon, 12),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_neon, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(NEON, SADx4Test, ::testing::ValuesIn(x4d_neon_tests));
+
+const SadSkipMxNx4Param skip_x4d_neon_tests[] = {
+ SadSkipMxNx4Param(64, 64, &vpx_sad_skip_64x64x4d_neon),
+ SadSkipMxNx4Param(64, 32, &vpx_sad_skip_64x32x4d_neon),
+ SadSkipMxNx4Param(32, 64, &vpx_sad_skip_32x64x4d_neon),
+ SadSkipMxNx4Param(32, 32, &vpx_sad_skip_32x32x4d_neon),
+ SadSkipMxNx4Param(32, 16, &vpx_sad_skip_32x16x4d_neon),
+ SadSkipMxNx4Param(16, 32, &vpx_sad_skip_16x32x4d_neon),
+ SadSkipMxNx4Param(16, 16, &vpx_sad_skip_16x16x4d_neon),
+ SadSkipMxNx4Param(16, 8, &vpx_sad_skip_16x8x4d_neon),
+ SadSkipMxNx4Param(8, 16, &vpx_sad_skip_8x16x4d_neon),
+ SadSkipMxNx4Param(8, 8, &vpx_sad_skip_8x8x4d_neon),
+ SadSkipMxNx4Param(8, 4, &vpx_sad_skip_8x4x4d_neon),
+ SadSkipMxNx4Param(4, 8, &vpx_sad_skip_4x8x4d_neon),
+ SadSkipMxNx4Param(4, 4, &vpx_sad_skip_4x4x4d_neon),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNx4Param(4, 4, &vpx_highbd_sad_skip_4x4x4d_neon, 8),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_neon, 8),
+ SadSkipMxNx4Param(8, 4, &vpx_highbd_sad_skip_8x4x4d_neon, 8),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_neon, 8),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_neon, 8),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_neon, 8),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_neon, 8),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_neon, 8),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_neon, 8),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_neon, 8),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_neon, 8),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_neon, 8),
+ SadSkipMxNx4Param(4, 4, &vpx_highbd_sad_skip_4x4x4d_neon, 10),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_neon, 10),
+ SadSkipMxNx4Param(8, 4, &vpx_highbd_sad_skip_8x4x4d_neon, 10),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_neon, 10),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_neon, 10),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_neon, 10),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_neon, 10),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_neon, 10),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_neon, 10),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_neon, 10),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_neon, 10),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_neon, 10),
+ SadSkipMxNx4Param(4, 4, &vpx_highbd_sad_skip_4x4x4d_neon, 12),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_neon, 12),
+ SadSkipMxNx4Param(8, 4, &vpx_highbd_sad_skip_8x4x4d_neon, 12),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_neon, 12),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_neon, 12),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_neon, 12),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_neon, 12),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_neon, 12),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_neon, 12),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_neon, 12),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_neon, 12),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_neon, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(NEON, SADSkipx4Test,
+ ::testing::ValuesIn(skip_x4d_neon_tests));
+#endif // HAVE_NEON
+
+//------------------------------------------------------------------------------
+// x86 functions
+#if HAVE_SSE2
+const SadMxNParam sse2_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_sse2),
+ SadMxNParam(64, 32, &vpx_sad64x32_sse2),
+ SadMxNParam(32, 64, &vpx_sad32x64_sse2),
+ SadMxNParam(32, 32, &vpx_sad32x32_sse2),
+ SadMxNParam(32, 16, &vpx_sad32x16_sse2),
+ SadMxNParam(16, 32, &vpx_sad16x32_sse2),
+ SadMxNParam(16, 16, &vpx_sad16x16_sse2),
+ SadMxNParam(16, 8, &vpx_sad16x8_sse2),
+ SadMxNParam(8, 16, &vpx_sad8x16_sse2),
+ SadMxNParam(8, 8, &vpx_sad8x8_sse2),
+ SadMxNParam(8, 4, &vpx_sad8x4_sse2),
+ SadMxNParam(4, 8, &vpx_sad4x8_sse2),
+ SadMxNParam(4, 4, &vpx_sad4x4_sse2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_sse2, 8),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_sse2, 8),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_sse2, 8),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_sse2, 8),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_sse2, 8),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_sse2, 8),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_sse2, 8),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_sse2, 8),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_sse2, 8),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_sse2, 8),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_sse2, 8),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_sse2, 10),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_sse2, 10),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_sse2, 10),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_sse2, 10),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_sse2, 10),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_sse2, 10),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_sse2, 10),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_sse2, 10),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_sse2, 10),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_sse2, 10),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_sse2, 10),
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_sse2, 12),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_sse2, 12),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_sse2, 12),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_sse2, 12),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_sse2, 12),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_sse2, 12),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_sse2, 12),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_sse2, 12),
+ SadMxNParam(8, 16, &vpx_highbd_sad8x16_sse2, 12),
+ SadMxNParam(8, 8, &vpx_highbd_sad8x8_sse2, 12),
+ SadMxNParam(8, 4, &vpx_highbd_sad8x4_sse2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(SSE2, SADTest, ::testing::ValuesIn(sse2_tests));
+
+const SadSkipMxNParam skip_sse2_tests[] = {
+ SadSkipMxNParam(64, 64, &vpx_sad_skip_64x64_sse2),
+ SadSkipMxNParam(64, 32, &vpx_sad_skip_64x32_sse2),
+ SadSkipMxNParam(32, 64, &vpx_sad_skip_32x64_sse2),
+ SadSkipMxNParam(32, 32, &vpx_sad_skip_32x32_sse2),
+ SadSkipMxNParam(32, 16, &vpx_sad_skip_32x16_sse2),
+ SadSkipMxNParam(16, 32, &vpx_sad_skip_16x32_sse2),
+ SadSkipMxNParam(16, 16, &vpx_sad_skip_16x16_sse2),
+ SadSkipMxNParam(16, 8, &vpx_sad_skip_16x8_sse2),
+ SadSkipMxNParam(8, 16, &vpx_sad_skip_8x16_sse2),
+ SadSkipMxNParam(8, 8, &vpx_sad_skip_8x8_sse2),
+ SadSkipMxNParam(4, 8, &vpx_sad_skip_4x8_sse2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_sse2, 8),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_sse2, 8),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_sse2, 8),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_sse2, 8),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_sse2, 8),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_sse2, 8),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_sse2, 8),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_sse2, 8),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_sse2, 8),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_sse2, 8),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_sse2, 10),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_sse2, 10),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_sse2, 10),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_sse2, 10),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_sse2, 10),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_sse2, 10),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_sse2, 10),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_sse2, 10),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_sse2, 10),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_sse2, 10),
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_sse2, 12),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_sse2, 12),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_sse2, 12),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_sse2, 12),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_sse2, 12),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_sse2, 12),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_sse2, 12),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_sse2, 12),
+ SadSkipMxNParam(8, 16, &vpx_highbd_sad_skip_8x16_sse2, 12),
+ SadSkipMxNParam(8, 8, &vpx_highbd_sad_skip_8x8_sse2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(SSE2, SADSkipTest,
+ ::testing::ValuesIn(skip_sse2_tests));
+
+const SadMxNAvgParam avg_sse2_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_sse2),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_sse2),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_sse2),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_sse2),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_sse2),
+ SadMxNAvgParam(16, 32, &vpx_sad16x32_avg_sse2),
+ SadMxNAvgParam(16, 16, &vpx_sad16x16_avg_sse2),
+ SadMxNAvgParam(16, 8, &vpx_sad16x8_avg_sse2),
+ SadMxNAvgParam(8, 16, &vpx_sad8x16_avg_sse2),
+ SadMxNAvgParam(8, 8, &vpx_sad8x8_avg_sse2),
+ SadMxNAvgParam(8, 4, &vpx_sad8x4_avg_sse2),
+ SadMxNAvgParam(4, 8, &vpx_sad4x8_avg_sse2),
+ SadMxNAvgParam(4, 4, &vpx_sad4x4_avg_sse2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_sse2, 8),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_sse2, 8),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_sse2, 8),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_sse2, 8),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_sse2, 8),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_sse2, 8),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_sse2, 8),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_sse2, 8),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_sse2, 8),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_sse2, 8),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_sse2, 8),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_sse2, 10),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_sse2, 10),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_sse2, 10),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_sse2, 10),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_sse2, 10),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_sse2, 10),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_sse2, 10),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_sse2, 10),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_sse2, 10),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_sse2, 10),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_sse2, 10),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_sse2, 12),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_sse2, 12),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_sse2, 12),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_sse2, 12),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_sse2, 12),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_sse2, 12),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_sse2, 12),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_sse2, 12),
+ SadMxNAvgParam(8, 16, &vpx_highbd_sad8x16_avg_sse2, 12),
+ SadMxNAvgParam(8, 8, &vpx_highbd_sad8x8_avg_sse2, 12),
+ SadMxNAvgParam(8, 4, &vpx_highbd_sad8x4_avg_sse2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(SSE2, SADavgTest, ::testing::ValuesIn(avg_sse2_tests));
+
+const SadMxNx4Param x4d_sse2_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_sse2),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_sse2),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_sse2),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_sse2),
+ SadMxNx4Param(32, 16, &vpx_sad32x16x4d_sse2),
+ SadMxNx4Param(16, 32, &vpx_sad16x32x4d_sse2),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_sse2),
+ SadMxNx4Param(16, 8, &vpx_sad16x8x4d_sse2),
+ SadMxNx4Param(8, 16, &vpx_sad8x16x4d_sse2),
+ SadMxNx4Param(8, 8, &vpx_sad8x8x4d_sse2),
+ SadMxNx4Param(8, 4, &vpx_sad8x4x4d_sse2),
+ SadMxNx4Param(4, 8, &vpx_sad4x8x4d_sse2),
+ SadMxNx4Param(4, 4, &vpx_sad4x4x4d_sse2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_sse2, 8),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_sse2, 8),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_sse2, 8),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_sse2, 8),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_sse2, 8),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_sse2, 8),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_sse2, 8),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_sse2, 8),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_sse2, 8),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_sse2, 8),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_sse2, 8),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_sse2, 8),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_sse2, 8),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_sse2, 10),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_sse2, 10),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_sse2, 10),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_sse2, 10),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_sse2, 10),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_sse2, 10),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_sse2, 10),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_sse2, 10),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_sse2, 10),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_sse2, 10),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_sse2, 10),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_sse2, 10),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_sse2, 10),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_sse2, 12),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_sse2, 12),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_sse2, 12),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_sse2, 12),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_sse2, 12),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_sse2, 12),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_sse2, 12),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_sse2, 12),
+ SadMxNx4Param(8, 16, &vpx_highbd_sad8x16x4d_sse2, 12),
+ SadMxNx4Param(8, 8, &vpx_highbd_sad8x8x4d_sse2, 12),
+ SadMxNx4Param(8, 4, &vpx_highbd_sad8x4x4d_sse2, 12),
+ SadMxNx4Param(4, 8, &vpx_highbd_sad4x8x4d_sse2, 12),
+ SadMxNx4Param(4, 4, &vpx_highbd_sad4x4x4d_sse2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(SSE2, SADx4Test, ::testing::ValuesIn(x4d_sse2_tests));
+
+const SadSkipMxNx4Param skip_x4d_sse2_tests[] = {
+ SadSkipMxNx4Param(64, 64, &vpx_sad_skip_64x64x4d_sse2),
+ SadSkipMxNx4Param(64, 32, &vpx_sad_skip_64x32x4d_sse2),
+ SadSkipMxNx4Param(32, 64, &vpx_sad_skip_32x64x4d_sse2),
+ SadSkipMxNx4Param(32, 32, &vpx_sad_skip_32x32x4d_sse2),
+ SadSkipMxNx4Param(32, 16, &vpx_sad_skip_32x16x4d_sse2),
+ SadSkipMxNx4Param(16, 32, &vpx_sad_skip_16x32x4d_sse2),
+ SadSkipMxNx4Param(16, 16, &vpx_sad_skip_16x16x4d_sse2),
+ SadSkipMxNx4Param(16, 8, &vpx_sad_skip_16x8x4d_sse2),
+ SadSkipMxNx4Param(8, 16, &vpx_sad_skip_8x16x4d_sse2),
+ SadSkipMxNx4Param(8, 8, &vpx_sad_skip_8x8x4d_sse2),
+ SadSkipMxNx4Param(4, 8, &vpx_sad_skip_4x8x4d_sse2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_sse2, 8),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_sse2, 8),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_sse2, 8),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_sse2, 8),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_sse2, 8),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_sse2, 8),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_sse2, 8),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_sse2, 8),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_sse2, 8),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_sse2, 8),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_sse2, 8),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_sse2, 10),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_sse2, 10),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_sse2, 10),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_sse2, 10),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_sse2, 10),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_sse2, 10),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_sse2, 10),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_sse2, 10),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_sse2, 10),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_sse2, 10),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_sse2, 10),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_sse2, 12),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_sse2, 12),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_sse2, 12),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_sse2, 12),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_sse2, 12),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_sse2, 12),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_sse2, 12),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_sse2, 12),
+ SadSkipMxNx4Param(8, 16, &vpx_highbd_sad_skip_8x16x4d_sse2, 12),
+ SadSkipMxNx4Param(8, 8, &vpx_highbd_sad_skip_8x8x4d_sse2, 12),
+ SadSkipMxNx4Param(4, 8, &vpx_highbd_sad_skip_4x8x4d_sse2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(SSE2, SADSkipx4Test,
+ ::testing::ValuesIn(skip_x4d_sse2_tests));
+#endif // HAVE_SSE2
+
+#if HAVE_SSE3
+// Only functions are x3, which do not have tests.
+#endif // HAVE_SSE3
+
+#if HAVE_SSSE3
+// Only functions are x3, which do not have tests.
+#endif // HAVE_SSSE3
+
+#if HAVE_AVX2
+const SadMxNParam avx2_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_avx2),
+ SadMxNParam(64, 32, &vpx_sad64x32_avx2),
+ SadMxNParam(32, 64, &vpx_sad32x64_avx2),
+ SadMxNParam(32, 32, &vpx_sad32x32_avx2),
+ SadMxNParam(32, 16, &vpx_sad32x16_avx2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_avx2, 8),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_avx2, 8),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_avx2, 8),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_avx2, 8),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_avx2, 8),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_avx2, 8),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_avx2, 8),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_avx2, 8),
+
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_avx2, 10),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_avx2, 10),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_avx2, 10),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_avx2, 10),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_avx2, 10),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_avx2, 10),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_avx2, 10),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_avx2, 10),
+
+ SadMxNParam(64, 64, &vpx_highbd_sad64x64_avx2, 12),
+ SadMxNParam(64, 32, &vpx_highbd_sad64x32_avx2, 12),
+ SadMxNParam(32, 64, &vpx_highbd_sad32x64_avx2, 12),
+ SadMxNParam(32, 32, &vpx_highbd_sad32x32_avx2, 12),
+ SadMxNParam(32, 16, &vpx_highbd_sad32x16_avx2, 12),
+ SadMxNParam(16, 32, &vpx_highbd_sad16x32_avx2, 12),
+ SadMxNParam(16, 16, &vpx_highbd_sad16x16_avx2, 12),
+ SadMxNParam(16, 8, &vpx_highbd_sad16x8_avx2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(AVX2, SADTest, ::testing::ValuesIn(avx2_tests));
+
+const SadSkipMxNParam skip_avx2_tests[] = {
+ SadSkipMxNParam(64, 64, &vpx_sad_skip_64x64_avx2),
+ SadSkipMxNParam(64, 32, &vpx_sad_skip_64x32_avx2),
+ SadSkipMxNParam(32, 64, &vpx_sad_skip_32x64_avx2),
+ SadSkipMxNParam(32, 32, &vpx_sad_skip_32x32_avx2),
+ SadSkipMxNParam(32, 16, &vpx_sad_skip_32x16_avx2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_avx2, 8),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_avx2, 8),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_avx2, 8),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_avx2, 8),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_avx2, 8),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_avx2, 8),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_avx2, 8),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_avx2, 8),
+
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_avx2, 10),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_avx2, 10),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_avx2, 10),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_avx2, 10),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_avx2, 10),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_avx2, 10),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_avx2, 10),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_avx2, 10),
+
+ SadSkipMxNParam(64, 64, &vpx_highbd_sad_skip_64x64_avx2, 12),
+ SadSkipMxNParam(64, 32, &vpx_highbd_sad_skip_64x32_avx2, 12),
+ SadSkipMxNParam(32, 64, &vpx_highbd_sad_skip_32x64_avx2, 12),
+ SadSkipMxNParam(32, 32, &vpx_highbd_sad_skip_32x32_avx2, 12),
+ SadSkipMxNParam(32, 16, &vpx_highbd_sad_skip_32x16_avx2, 12),
+ SadSkipMxNParam(16, 32, &vpx_highbd_sad_skip_16x32_avx2, 12),
+ SadSkipMxNParam(16, 16, &vpx_highbd_sad_skip_16x16_avx2, 12),
+ SadSkipMxNParam(16, 8, &vpx_highbd_sad_skip_16x8_avx2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(AVX2, SADSkipTest,
+ ::testing::ValuesIn(skip_avx2_tests));
+
+const SadMxNAvgParam avg_avx2_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_avx2),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_avx2),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_avx2),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_avx2),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_avx2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_avx2, 8),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_avx2, 8),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_avx2, 8),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_avx2, 8),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_avx2, 8),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_avx2, 8),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_avx2, 8),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_avx2, 8),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_avx2, 10),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_avx2, 10),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_avx2, 10),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_avx2, 10),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_avx2, 10),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_avx2, 10),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_avx2, 10),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_avx2, 10),
+ SadMxNAvgParam(64, 64, &vpx_highbd_sad64x64_avg_avx2, 12),
+ SadMxNAvgParam(64, 32, &vpx_highbd_sad64x32_avg_avx2, 12),
+ SadMxNAvgParam(32, 64, &vpx_highbd_sad32x64_avg_avx2, 12),
+ SadMxNAvgParam(32, 32, &vpx_highbd_sad32x32_avg_avx2, 12),
+ SadMxNAvgParam(32, 16, &vpx_highbd_sad32x16_avg_avx2, 12),
+ SadMxNAvgParam(16, 32, &vpx_highbd_sad16x32_avg_avx2, 12),
+ SadMxNAvgParam(16, 16, &vpx_highbd_sad16x16_avg_avx2, 12),
+ SadMxNAvgParam(16, 8, &vpx_highbd_sad16x8_avg_avx2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(AVX2, SADavgTest, ::testing::ValuesIn(avg_avx2_tests));
+
+const SadMxNx4Param x4d_avx2_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_avx2),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_avx2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_avx2, 8),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_avx2, 8),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_avx2, 8),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_avx2, 8),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_avx2, 8),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_avx2, 8),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_avx2, 8),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_avx2, 8),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_avx2, 10),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_avx2, 10),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_avx2, 10),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_avx2, 10),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_avx2, 10),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_avx2, 10),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_avx2, 10),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_avx2, 10),
+ SadMxNx4Param(64, 64, &vpx_highbd_sad64x64x4d_avx2, 12),
+ SadMxNx4Param(64, 32, &vpx_highbd_sad64x32x4d_avx2, 12),
+ SadMxNx4Param(32, 64, &vpx_highbd_sad32x64x4d_avx2, 12),
+ SadMxNx4Param(32, 32, &vpx_highbd_sad32x32x4d_avx2, 12),
+ SadMxNx4Param(32, 16, &vpx_highbd_sad32x16x4d_avx2, 12),
+ SadMxNx4Param(16, 32, &vpx_highbd_sad16x32x4d_avx2, 12),
+ SadMxNx4Param(16, 16, &vpx_highbd_sad16x16x4d_avx2, 12),
+ SadMxNx4Param(16, 8, &vpx_highbd_sad16x8x4d_avx2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(AVX2, SADx4Test, ::testing::ValuesIn(x4d_avx2_tests));
+
+const SadSkipMxNx4Param skip_x4d_avx2_tests[] = {
+ SadSkipMxNx4Param(64, 64, &vpx_sad_skip_64x64x4d_avx2),
+ SadSkipMxNx4Param(64, 32, &vpx_sad_skip_64x32x4d_avx2),
+ SadSkipMxNx4Param(32, 64, &vpx_sad_skip_32x64x4d_avx2),
+ SadSkipMxNx4Param(32, 32, &vpx_sad_skip_32x32x4d_avx2),
+ SadSkipMxNx4Param(32, 16, &vpx_sad_skip_32x16x4d_avx2),
+#if CONFIG_VP9_HIGHBITDEPTH
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_avx2, 8),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_avx2, 8),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_avx2, 8),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_avx2, 8),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_avx2, 8),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_avx2, 8),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_avx2, 8),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_avx2, 8),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_avx2, 10),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_avx2, 10),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_avx2, 10),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_avx2, 10),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_avx2, 10),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_avx2, 10),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_avx2, 10),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_avx2, 10),
+ SadSkipMxNx4Param(64, 64, &vpx_highbd_sad_skip_64x64x4d_avx2, 12),
+ SadSkipMxNx4Param(64, 32, &vpx_highbd_sad_skip_64x32x4d_avx2, 12),
+ SadSkipMxNx4Param(32, 64, &vpx_highbd_sad_skip_32x64x4d_avx2, 12),
+ SadSkipMxNx4Param(32, 32, &vpx_highbd_sad_skip_32x32x4d_avx2, 12),
+ SadSkipMxNx4Param(32, 16, &vpx_highbd_sad_skip_32x16x4d_avx2, 12),
+ SadSkipMxNx4Param(16, 32, &vpx_highbd_sad_skip_16x32x4d_avx2, 12),
+ SadSkipMxNx4Param(16, 16, &vpx_highbd_sad_skip_16x16x4d_avx2, 12),
+ SadSkipMxNx4Param(16, 8, &vpx_highbd_sad_skip_16x8x4d_avx2, 12),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_SUITE_P(AVX2, SADSkipx4Test,
+ ::testing::ValuesIn(skip_x4d_avx2_tests));
+
+#endif // HAVE_AVX2
+
+#if HAVE_AVX512
+const SadMxNx4Param x4d_avx512_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_avx512),
+};
+INSTANTIATE_TEST_SUITE_P(AVX512, SADx4Test,
+ ::testing::ValuesIn(x4d_avx512_tests));
+#endif // HAVE_AVX512
+
+//------------------------------------------------------------------------------
+// MIPS functions
+#if HAVE_MSA
+const SadMxNParam msa_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_msa),
+ SadMxNParam(64, 32, &vpx_sad64x32_msa),
+ SadMxNParam(32, 64, &vpx_sad32x64_msa),
+ SadMxNParam(32, 32, &vpx_sad32x32_msa),
+ SadMxNParam(32, 16, &vpx_sad32x16_msa),
+ SadMxNParam(16, 32, &vpx_sad16x32_msa),
+ SadMxNParam(16, 16, &vpx_sad16x16_msa),
+ SadMxNParam(16, 8, &vpx_sad16x8_msa),
+ SadMxNParam(8, 16, &vpx_sad8x16_msa),
+ SadMxNParam(8, 8, &vpx_sad8x8_msa),
+ SadMxNParam(8, 4, &vpx_sad8x4_msa),
+ SadMxNParam(4, 8, &vpx_sad4x8_msa),
+ SadMxNParam(4, 4, &vpx_sad4x4_msa),
+};
+INSTANTIATE_TEST_SUITE_P(MSA, SADTest, ::testing::ValuesIn(msa_tests));
+
+const SadMxNAvgParam avg_msa_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_msa),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_msa),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_msa),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_msa),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_msa),
+ SadMxNAvgParam(16, 32, &vpx_sad16x32_avg_msa),
+ SadMxNAvgParam(16, 16, &vpx_sad16x16_avg_msa),
+ SadMxNAvgParam(16, 8, &vpx_sad16x8_avg_msa),
+ SadMxNAvgParam(8, 16, &vpx_sad8x16_avg_msa),
+ SadMxNAvgParam(8, 8, &vpx_sad8x8_avg_msa),
+ SadMxNAvgParam(8, 4, &vpx_sad8x4_avg_msa),
+ SadMxNAvgParam(4, 8, &vpx_sad4x8_avg_msa),
+ SadMxNAvgParam(4, 4, &vpx_sad4x4_avg_msa),
+};
+INSTANTIATE_TEST_SUITE_P(MSA, SADavgTest, ::testing::ValuesIn(avg_msa_tests));
+
+const SadMxNx4Param x4d_msa_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_msa),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_msa),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_msa),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_msa),
+ SadMxNx4Param(32, 16, &vpx_sad32x16x4d_msa),
+ SadMxNx4Param(16, 32, &vpx_sad16x32x4d_msa),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_msa),
+ SadMxNx4Param(16, 8, &vpx_sad16x8x4d_msa),
+ SadMxNx4Param(8, 16, &vpx_sad8x16x4d_msa),
+ SadMxNx4Param(8, 8, &vpx_sad8x8x4d_msa),
+ SadMxNx4Param(8, 4, &vpx_sad8x4x4d_msa),
+ SadMxNx4Param(4, 8, &vpx_sad4x8x4d_msa),
+ SadMxNx4Param(4, 4, &vpx_sad4x4x4d_msa),
+};
+INSTANTIATE_TEST_SUITE_P(MSA, SADx4Test, ::testing::ValuesIn(x4d_msa_tests));
+#endif // HAVE_MSA
+
+//------------------------------------------------------------------------------
+// VSX functions
+#if HAVE_VSX
+const SadMxNParam vsx_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_vsx),
+ SadMxNParam(64, 32, &vpx_sad64x32_vsx),
+ SadMxNParam(32, 64, &vpx_sad32x64_vsx),
+ SadMxNParam(32, 32, &vpx_sad32x32_vsx),
+ SadMxNParam(32, 16, &vpx_sad32x16_vsx),
+ SadMxNParam(16, 32, &vpx_sad16x32_vsx),
+ SadMxNParam(16, 16, &vpx_sad16x16_vsx),
+ SadMxNParam(16, 8, &vpx_sad16x8_vsx),
+ SadMxNParam(8, 16, &vpx_sad8x16_vsx),
+ SadMxNParam(8, 8, &vpx_sad8x8_vsx),
+ SadMxNParam(8, 4, &vpx_sad8x4_vsx),
+};
+INSTANTIATE_TEST_SUITE_P(VSX, SADTest, ::testing::ValuesIn(vsx_tests));
+
+const SadMxNAvgParam avg_vsx_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_vsx),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_vsx),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_vsx),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_vsx),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_vsx),
+ SadMxNAvgParam(16, 32, &vpx_sad16x32_avg_vsx),
+ SadMxNAvgParam(16, 16, &vpx_sad16x16_avg_vsx),
+ SadMxNAvgParam(16, 8, &vpx_sad16x8_avg_vsx),
+};
+INSTANTIATE_TEST_SUITE_P(VSX, SADavgTest, ::testing::ValuesIn(avg_vsx_tests));
+
+const SadMxNx4Param x4d_vsx_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_vsx),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_vsx),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_vsx),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_vsx),
+ SadMxNx4Param(32, 16, &vpx_sad32x16x4d_vsx),
+ SadMxNx4Param(16, 32, &vpx_sad16x32x4d_vsx),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_vsx),
+ SadMxNx4Param(16, 8, &vpx_sad16x8x4d_vsx),
+};
+INSTANTIATE_TEST_SUITE_P(VSX, SADx4Test, ::testing::ValuesIn(x4d_vsx_tests));
+#endif // HAVE_VSX
+
+//------------------------------------------------------------------------------
+// Loongson functions
+#if HAVE_MMI
+const SadMxNParam mmi_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_mmi),
+ SadMxNParam(64, 32, &vpx_sad64x32_mmi),
+ SadMxNParam(32, 64, &vpx_sad32x64_mmi),
+ SadMxNParam(32, 32, &vpx_sad32x32_mmi),
+ SadMxNParam(32, 16, &vpx_sad32x16_mmi),
+ SadMxNParam(16, 32, &vpx_sad16x32_mmi),
+ SadMxNParam(16, 16, &vpx_sad16x16_mmi),
+ SadMxNParam(16, 8, &vpx_sad16x8_mmi),
+ SadMxNParam(8, 16, &vpx_sad8x16_mmi),
+ SadMxNParam(8, 8, &vpx_sad8x8_mmi),
+ SadMxNParam(8, 4, &vpx_sad8x4_mmi),
+ SadMxNParam(4, 8, &vpx_sad4x8_mmi),
+ SadMxNParam(4, 4, &vpx_sad4x4_mmi),
+};
+INSTANTIATE_TEST_SUITE_P(MMI, SADTest, ::testing::ValuesIn(mmi_tests));
+
+const SadMxNAvgParam avg_mmi_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_mmi),
+ SadMxNAvgParam(64, 32, &vpx_sad64x32_avg_mmi),
+ SadMxNAvgParam(32, 64, &vpx_sad32x64_avg_mmi),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_mmi),
+ SadMxNAvgParam(32, 16, &vpx_sad32x16_avg_mmi),
+ SadMxNAvgParam(16, 32, &vpx_sad16x32_avg_mmi),
+ SadMxNAvgParam(16, 16, &vpx_sad16x16_avg_mmi),
+ SadMxNAvgParam(16, 8, &vpx_sad16x8_avg_mmi),
+ SadMxNAvgParam(8, 16, &vpx_sad8x16_avg_mmi),
+ SadMxNAvgParam(8, 8, &vpx_sad8x8_avg_mmi),
+ SadMxNAvgParam(8, 4, &vpx_sad8x4_avg_mmi),
+ SadMxNAvgParam(4, 8, &vpx_sad4x8_avg_mmi),
+ SadMxNAvgParam(4, 4, &vpx_sad4x4_avg_mmi),
+};
+INSTANTIATE_TEST_SUITE_P(MMI, SADavgTest, ::testing::ValuesIn(avg_mmi_tests));
+
+const SadMxNx4Param x4d_mmi_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_mmi),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_mmi),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_mmi),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_mmi),
+ SadMxNx4Param(32, 16, &vpx_sad32x16x4d_mmi),
+ SadMxNx4Param(16, 32, &vpx_sad16x32x4d_mmi),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_mmi),
+ SadMxNx4Param(16, 8, &vpx_sad16x8x4d_mmi),
+ SadMxNx4Param(8, 16, &vpx_sad8x16x4d_mmi),
+ SadMxNx4Param(8, 8, &vpx_sad8x8x4d_mmi),
+ SadMxNx4Param(8, 4, &vpx_sad8x4x4d_mmi),
+ SadMxNx4Param(4, 8, &vpx_sad4x8x4d_mmi),
+ SadMxNx4Param(4, 4, &vpx_sad4x4x4d_mmi),
+};
+INSTANTIATE_TEST_SUITE_P(MMI, SADx4Test, ::testing::ValuesIn(x4d_mmi_tests));
+#endif // HAVE_MMI
+
+//------------------------------------------------------------------------------
+// loongarch functions
+#if HAVE_LSX
+const SadMxNParam lsx_tests[] = {
+ SadMxNParam(64, 64, &vpx_sad64x64_lsx),
+ SadMxNParam(32, 32, &vpx_sad32x32_lsx),
+ SadMxNParam(16, 16, &vpx_sad16x16_lsx),
+ SadMxNParam(8, 8, &vpx_sad8x8_lsx),
+};
+INSTANTIATE_TEST_SUITE_P(LSX, SADTest, ::testing::ValuesIn(lsx_tests));
+
+const SadMxNAvgParam avg_lsx_tests[] = {
+ SadMxNAvgParam(64, 64, &vpx_sad64x64_avg_lsx),
+ SadMxNAvgParam(32, 32, &vpx_sad32x32_avg_lsx),
+};
+INSTANTIATE_TEST_SUITE_P(LSX, SADavgTest, ::testing::ValuesIn(avg_lsx_tests));
+
+const SadMxNx4Param x4d_lsx_tests[] = {
+ SadMxNx4Param(64, 64, &vpx_sad64x64x4d_lsx),
+ SadMxNx4Param(64, 32, &vpx_sad64x32x4d_lsx),
+ SadMxNx4Param(32, 64, &vpx_sad32x64x4d_lsx),
+ SadMxNx4Param(32, 32, &vpx_sad32x32x4d_lsx),
+ SadMxNx4Param(16, 16, &vpx_sad16x16x4d_lsx),
+ SadMxNx4Param(8, 8, &vpx_sad8x8x4d_lsx),
+};
+INSTANTIATE_TEST_SUITE_P(LSX, SADx4Test, ::testing::ValuesIn(x4d_lsx_tests));
+#endif // HAVE_LSX
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/set_maps.sh b/media/libvpx/libvpx/test/set_maps.sh
new file mode 100755
index 0000000000..f45dc51f49
--- /dev/null
+++ b/media/libvpx/libvpx/test/set_maps.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx set_maps example. To add new tests to this file,
+## do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to set_maps_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required, and set_maps must exist in
+# $LIBVPX_BIN_PATH.
+set_maps_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ if [ -z "$(vpx_tool_path set_maps)" ]; then
+ elog "set_maps not found. It must exist in LIBVPX_BIN_PATH or its parent."
+ return 1
+ fi
+}
+
+# Runs set_maps using the codec specified by $1.
+set_maps() {
+ local encoder="$(vpx_tool_path set_maps)"
+ local codec="$1"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/set_maps_${codec}.ivf"
+
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+set_maps_vp8() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ set_maps vp8 || return 1
+ fi
+}
+
+set_maps_vp9() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ set_maps vp9 || return 1
+ fi
+}
+
+set_maps_tests="set_maps_vp8
+ set_maps_vp9"
+
+run_tests set_maps_verify_environment "${set_maps_tests}"
diff --git a/media/libvpx/libvpx/test/set_roi.cc b/media/libvpx/libvpx/test/set_roi.cc
new file mode 100644
index 0000000000..167cf908fd
--- /dev/null
+++ b/media/libvpx/libvpx/test/set_roi.cc
@@ -0,0 +1,166 @@
+/*
+ * 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 <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
+#include "vp8/encoder/onyx_int.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+TEST(VP8RoiMapTest, ParameterCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ int delta_q[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 };
+ int delta_lf[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 };
+ unsigned int threshold[MAX_MB_SEGMENTS] = { 0, 100, 200, 300 };
+
+ const int internalq_trans[] = {
+ 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19,
+ 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 39, 41,
+ 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 64, 67, 70, 73, 76, 79,
+ 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127,
+ };
+
+ // Initialize elements of cpi with valid defaults.
+ VP8_COMP cpi;
+ cpi.mb.e_mbd.mb_segement_abs_delta = SEGMENT_DELTADATA;
+ cpi.cyclic_refresh_mode_enabled = 0;
+ cpi.mb.e_mbd.segmentation_enabled = 0;
+ cpi.mb.e_mbd.update_mb_segmentation_map = 0;
+ cpi.mb.e_mbd.update_mb_segmentation_data = 0;
+ cpi.common.mb_rows = 240 >> 4;
+ cpi.common.mb_cols = 320 >> 4;
+ const int mbs = (cpi.common.mb_rows * cpi.common.mb_cols);
+ memset(cpi.segment_feature_data, 0, sizeof(cpi.segment_feature_data));
+
+ // Segment map
+ cpi.segmentation_map = reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1));
+
+ // Allocate memory for the source memory map.
+ unsigned char *roi_map =
+ reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1));
+ memset(&roi_map[mbs >> 2], 1, (mbs >> 2));
+ memset(&roi_map[mbs >> 1], 2, (mbs >> 2));
+ memset(&roi_map[mbs - (mbs >> 2)], 3, (mbs >> 2));
+
+ // Do a test call with valid parameters.
+ int roi_retval =
+ vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, cpi.common.mb_cols,
+ delta_q, delta_lf, threshold);
+ EXPECT_EQ(0, roi_retval)
+ << "vp8_set_roimap roi failed with default test parameters";
+
+ // Check that the values in the cpi structure get set as expected.
+ if (roi_retval == 0) {
+ // Check that the segment map got set.
+ const int mapcompare = memcmp(roi_map, cpi.segmentation_map, mbs);
+ EXPECT_EQ(0, mapcompare) << "segment map error";
+
+ // Check the q deltas (note the need to translate into
+ // the interanl range of 0-127.
+ for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
+ const int transq = internalq_trans[abs(delta_q[i])];
+ if (abs(cpi.segment_feature_data[MB_LVL_ALT_Q][i]) != transq) {
+ EXPECT_EQ(transq, cpi.segment_feature_data[MB_LVL_ALT_Q][i])
+ << "segment delta_q error";
+ break;
+ }
+ }
+
+ // Check the loop filter deltas
+ for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
+ if (cpi.segment_feature_data[MB_LVL_ALT_LF][i] != delta_lf[i]) {
+ EXPECT_EQ(delta_lf[i], cpi.segment_feature_data[MB_LVL_ALT_LF][i])
+ << "segment delta_lf error";
+ break;
+ }
+ }
+
+ // Check the breakout thresholds
+ for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
+ unsigned int breakout =
+ static_cast<unsigned int>(cpi.segment_encode_breakout[i]);
+
+ if (threshold[i] != breakout) {
+ EXPECT_EQ(threshold[i], breakout) << "breakout threshold error";
+ break;
+ }
+ }
+
+ // Segmentation, and segmentation update flages should be set.
+ EXPECT_EQ(1, cpi.mb.e_mbd.segmentation_enabled)
+ << "segmentation_enabled error";
+ EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_map)
+ << "update_mb_segmentation_map error";
+ EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_data)
+ << "update_mb_segmentation_data error";
+
+ // Try a range of delta q and lf parameters (some legal, some not)
+ for (int i = 0; i < 1000; ++i) {
+ int rand_deltas[4];
+ int deltas_valid;
+ rand_deltas[0] = rnd(160) - 80;
+ rand_deltas[1] = rnd(160) - 80;
+ rand_deltas[2] = rnd(160) - 80;
+ rand_deltas[3] = rnd(160) - 80;
+
+ deltas_valid =
+ ((abs(rand_deltas[0]) <= 63) && (abs(rand_deltas[1]) <= 63) &&
+ (abs(rand_deltas[2]) <= 63) && (abs(rand_deltas[3]) <= 63))
+ ? 0
+ : -1;
+
+ // Test with random delta q values.
+ roi_retval =
+ vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, cpi.common.mb_cols,
+ rand_deltas, delta_lf, threshold);
+ EXPECT_EQ(deltas_valid, roi_retval) << "dq range check error";
+
+ // One delta_q error shown at a time
+ if (deltas_valid != roi_retval) break;
+
+ // Test with random loop filter values.
+ roi_retval =
+ vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows, cpi.common.mb_cols,
+ delta_q, rand_deltas, threshold);
+ EXPECT_EQ(deltas_valid, roi_retval) << "dlf range check error";
+
+ // One delta loop filter error shown at a time
+ if (deltas_valid != roi_retval) break;
+ }
+
+ // Test invalid number of rows or colums.
+ roi_retval =
+ vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows + 1,
+ cpi.common.mb_cols, delta_q, delta_lf, threshold);
+ EXPECT_EQ(-1, roi_retval) << "MB rows bounds check error";
+
+ roi_retval =
+ vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
+ cpi.common.mb_cols - 1, delta_q, delta_lf, threshold);
+ EXPECT_EQ(-1, roi_retval) << "MB cols bounds check error";
+ }
+
+ // Free allocated memory
+ if (cpi.segmentation_map) vpx_free(cpi.segmentation_map);
+ if (roi_map) vpx_free(roi_map);
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/simple_decoder.sh b/media/libvpx/libvpx/test/simple_decoder.sh
new file mode 100755
index 0000000000..65fc4828ed
--- /dev/null
+++ b/media/libvpx/libvpx/test/simple_decoder.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx simple_decoder example code. To add new tests to
+## this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to simple_decoder_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+# $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+simple_decoder_verify_environment() {
+ if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs simple_decoder using $1 as input file. $2 is the codec name, and is used
+# solely to name the output file.
+simple_decoder() {
+ local decoder="${LIBVPX_BIN_PATH}/simple_decoder${VPX_TEST_EXE_SUFFIX}"
+ local input_file="$1"
+ local codec="$2"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/simple_decoder_${codec}.raw"
+
+ if [ ! -x "${decoder}" ]; then
+ elog "${decoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+simple_decoder_vp8() {
+ if [ "$(vp8_decode_available)" = "yes" ]; then
+ simple_decoder "${VP8_IVF_FILE}" vp8 || return 1
+ fi
+}
+
+simple_decoder_vp9() {
+ if [ "$(vp9_decode_available)" = "yes" ]; then
+ simple_decoder "${VP9_IVF_FILE}" vp9 || return 1
+ fi
+}
+
+simple_decoder_tests="simple_decoder_vp8
+ simple_decoder_vp9"
+
+run_tests simple_decoder_verify_environment "${simple_decoder_tests}"
diff --git a/media/libvpx/libvpx/test/simple_encode_test.cc b/media/libvpx/libvpx/test/simple_encode_test.cc
new file mode 100644
index 0000000000..01fc258566
--- /dev/null
+++ b/media/libvpx/libvpx/test/simple_encode_test.cc
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2019 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 <math.h>
+#include <memory>
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/video_source.h"
+#include "vp9/simple_encode.h"
+
+namespace vp9 {
+namespace {
+
+double GetBitrateInKbps(size_t bit_size, int num_frames, int frame_rate_num,
+ int frame_rate_den) {
+ return static_cast<double>(bit_size) / num_frames * frame_rate_num /
+ frame_rate_den / 1000.0;
+}
+
+// Returns the number of unit in size of 4.
+// For example, if size is 7, return 2.
+int GetNumUnit4x4(int size) { return (size + 3) >> 2; }
+
+class SimpleEncodeTest : public ::testing::Test {
+ protected:
+ const int width_ = 352;
+ const int height_ = 288;
+ const int frame_rate_num_ = 30;
+ const int frame_rate_den_ = 1;
+ const int target_bitrate_ = 1000;
+ const int num_frames_ = 17;
+ const int target_level_ = LEVEL_UNKNOWN;
+ const std::string in_file_path_str_ =
+ libvpx_test::GetDataPath() + "/bus_352x288_420_f20_b8.yuv";
+};
+
+TEST_F(SimpleEncodeTest, ComputeFirstPassStats) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ std::vector<std::vector<double>> frame_stats =
+ simple_encode.ObserveFirstPassStats();
+ EXPECT_EQ(frame_stats.size(), static_cast<size_t>(num_frames_));
+ const size_t data_num = frame_stats[0].size();
+ // Read ObserveFirstPassStats before changing FIRSTPASS_STATS.
+ EXPECT_EQ(data_num, static_cast<size_t>(25));
+ for (size_t i = 0; i < frame_stats.size(); ++i) {
+ EXPECT_EQ(frame_stats[i].size(), data_num);
+ // FIRSTPASS_STATS's first element is frame
+ EXPECT_EQ(frame_stats[i][0], i);
+ // FIRSTPASS_STATS's last element is count, and the count is 1 for single
+ // frame stats
+ EXPECT_EQ(frame_stats[i][data_num - 1], 1);
+ }
+}
+
+TEST_F(SimpleEncodeTest, ObserveFirstPassMotionVectors) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ std::vector<std::vector<MotionVectorInfo>> fps_motion_vectors =
+ simple_encode.ObserveFirstPassMotionVectors();
+ EXPECT_EQ(fps_motion_vectors.size(), static_cast<size_t>(num_frames_));
+ const size_t num_blocks = ((width_ + 15) >> 4) * ((height_ + 15) >> 4);
+ EXPECT_EQ(num_blocks, fps_motion_vectors[0].size());
+ for (size_t i = 0; i < fps_motion_vectors.size(); ++i) {
+ EXPECT_EQ(num_blocks, fps_motion_vectors[i].size());
+ for (size_t j = 0; j < num_blocks; ++j) {
+ const int mv_count = fps_motion_vectors[i][j].mv_count;
+ const int ref_count =
+ (fps_motion_vectors[i][j].ref_frame[0] != kRefFrameTypeNone) +
+ (fps_motion_vectors[i][j].ref_frame[1] != kRefFrameTypeNone);
+ EXPECT_EQ(mv_count, ref_count);
+ }
+ }
+}
+
+TEST_F(SimpleEncodeTest, GetCodingFrameNum) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_EQ(num_coding_frames, 19);
+}
+
+TEST_F(SimpleEncodeTest, EncodeFrame) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_GE(num_coding_frames, num_frames_);
+ simple_encode.StartEncode();
+ size_t total_data_bit_size = 0;
+ int coded_show_frame_count = 0;
+ int frame_coding_index = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ EXPECT_EQ(encode_frame_result.show_idx,
+ encode_frame_list[group_index].show_idx);
+ EXPECT_EQ(encode_frame_result.frame_type,
+ encode_frame_list[group_index].frame_type);
+ EXPECT_EQ(encode_frame_list[group_index].coding_index,
+ frame_coding_index);
+ EXPECT_GE(encode_frame_result.psnr, 34)
+ << "The psnr is supposed to be greater than 34 given the "
+ "target_bitrate 1000 kbps";
+ EXPECT_EQ(encode_frame_result.ref_frame_info,
+ encode_frame_list[group_index].ref_frame_info);
+ total_data_bit_size += encode_frame_result.coding_data_bit_size;
+ ++frame_coding_index;
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ }
+ const double bitrate = GetBitrateInKbps(total_data_bit_size, num_frames_,
+ frame_rate_num_, frame_rate_den_);
+ const double off_target_threshold = 150;
+ EXPECT_LE(fabs(target_bitrate_ - bitrate), off_target_threshold);
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, ObserveKeyFrameMap) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ std::vector<int> key_frame_map = simple_encode.ObserveKeyFrameMap();
+ EXPECT_EQ(key_frame_map.size(), static_cast<size_t>(num_frames_));
+ simple_encode.StartEncode();
+ int coded_show_frame_count = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ if (encode_frame_result.frame_type == kFrameTypeKey) {
+ EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 1);
+ } else {
+ EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 0);
+ }
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ }
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameInfo encode_frame_info = simple_encode.GetNextEncodeFrameInfo();
+ int target_frame_bits;
+ switch (encode_frame_info.frame_type) {
+ case kFrameTypeInter: target_frame_bits = 20000; break;
+ case kFrameTypeKey:
+ case kFrameTypeAltRef:
+ case kFrameTypeGolden: target_frame_bits = 100000; break;
+ case kFrameTypeOverlay: target_frame_bits = 2000; break;
+ default: target_frame_bits = 20000;
+ }
+
+ double percent_diff = 15;
+ if (encode_frame_info.frame_type == kFrameTypeOverlay) {
+ percent_diff = 100;
+ }
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithTargetFrameBits(
+ &encode_frame_result, target_frame_bits, percent_diff);
+ const int recode_count = encode_frame_result.recode_count;
+ // TODO(angiebird): Replace 7 by RATE_CTRL_MAX_RECODE_NUM
+ EXPECT_LE(recode_count, 7);
+ EXPECT_GE(recode_count, 1);
+
+ const double diff = fabs((double)encode_frame_result.coding_data_bit_size -
+ target_frame_bits);
+ EXPECT_LE(diff * 100 / target_frame_bits, percent_diff);
+ }
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, EncodeFrameWithQuantizeIndex) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ const int assigned_quantize_index = 100 + i;
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ assigned_quantize_index);
+ EXPECT_EQ(encode_frame_result.quantize_index, assigned_quantize_index);
+ }
+ simple_encode.EndEncode();
+}
+
+// This test encodes the video using EncodeFrame(), where quantize indexes
+// are selected by vp9 rate control.
+// Encode stats and the quantize_indexes are collected.
+// Then the test encodes the video again using EncodeFrameWithQuantizeIndex()
+// using the quantize indexes collected from the first run.
+// Then test whether the encode stats of the two encoding runs match.
+TEST_F(SimpleEncodeTest, EncodeConsistencyTest) {
+ std::vector<int> quantize_index_list;
+ std::vector<uint64_t> ref_sse_list;
+ std::vector<double> ref_psnr_list;
+ std::vector<size_t> ref_bit_size_list;
+ std::vector<FrameType> ref_frame_type_list;
+ std::vector<int> ref_show_idx_list;
+ {
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ quantize_index_list.push_back(encode_frame_result.quantize_index);
+ ref_sse_list.push_back(encode_frame_result.sse);
+ ref_psnr_list.push_back(encode_frame_result.psnr);
+ ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
+ ref_frame_type_list.push_back(encode_frame_result.frame_type);
+ ref_show_idx_list.push_back(encode_frame_result.show_idx);
+ }
+ simple_encode.EndEncode();
+ }
+ {
+ // The second encode with quantize index got from the first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_EQ(static_cast<size_t>(num_coding_frames),
+ quantize_index_list.size());
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.quantize_index, quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.sse, ref_sse_list[i]);
+ EXPECT_DOUBLE_EQ(encode_frame_result.psnr, ref_psnr_list[i]);
+ EXPECT_EQ(encode_frame_result.coding_data_bit_size, ref_bit_size_list[i]);
+ EXPECT_EQ(encode_frame_result.frame_type, ref_frame_type_list[i]);
+ EXPECT_EQ(encode_frame_result.show_idx, ref_show_idx_list[i]);
+ }
+ simple_encode.EndEncode();
+ }
+}
+
+// Test the information (partition info and motion vector info) stored in
+// encoder is the same between two encode runs.
+TEST_F(SimpleEncodeTest, EncodeConsistencyTest2) {
+ const int num_rows_4x4 = GetNumUnit4x4(width_);
+ const int num_cols_4x4 = GetNumUnit4x4(height_);
+ const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ std::vector<PartitionInfo> partition_info_list(num_units_4x4 *
+ num_coding_frames);
+ std::vector<MotionVectorInfo> motion_vector_info_list(num_units_4x4 *
+ num_coding_frames);
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ partition_info_list[i * num_units_4x4 + j] =
+ encode_frame_result.partition_info[j];
+ motion_vector_info_list[i * num_units_4x4 + j] =
+ encode_frame_result.motion_vector_info[j];
+ }
+ }
+ simple_encode.EndEncode();
+ // The second encode.
+ SimpleEncode simple_encode_2(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode_2.ComputeFirstPassStats();
+ const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum();
+ simple_encode_2.StartEncode();
+ for (int i = 0; i < num_coding_frames_2; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode_2.EncodeFrame(&encode_frame_result);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ EXPECT_EQ(encode_frame_result.partition_info[j].row,
+ partition_info_list[i * num_units_4x4 + j].row);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column,
+ partition_info_list[i * num_units_4x4 + j].column);
+ EXPECT_EQ(encode_frame_result.partition_info[j].row_start,
+ partition_info_list[i * num_units_4x4 + j].row_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column_start,
+ partition_info_list[i * num_units_4x4 + j].column_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].width,
+ partition_info_list[i * num_units_4x4 + j].width);
+ EXPECT_EQ(encode_frame_result.partition_info[j].height,
+ partition_info_list[i * num_units_4x4 + j].height);
+
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_count,
+ motion_vector_info_list[i * num_units_4x4 + j].mv_count);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].ref_frame[0],
+ motion_vector_info_list[i * num_units_4x4 + j].ref_frame[0]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].ref_frame[1],
+ motion_vector_info_list[i * num_units_4x4 + j].ref_frame[1]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_row[0],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_row[0]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_column[0],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_column[0]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_row[1],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_row[1]);
+ EXPECT_EQ(encode_frame_result.motion_vector_info[j].mv_column[1],
+ motion_vector_info_list[i * num_units_4x4 + j].mv_column[1]);
+ }
+ }
+ simple_encode_2.EndEncode();
+}
+
+// Test the information stored in encoder is the same between two encode runs.
+TEST_F(SimpleEncodeTest, EncodeConsistencyTest3) {
+ std::vector<int> quantize_index_list;
+ const int num_rows_4x4 = GetNumUnit4x4(width_);
+ const int num_cols_4x4 = GetNumUnit4x4(height_);
+ const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ std::vector<PartitionInfo> partition_info_list(num_units_4x4 *
+ num_coding_frames);
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ quantize_index_list.push_back(encode_frame_result.quantize_index);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ partition_info_list[i * num_units_4x4 + j] =
+ encode_frame_result.partition_info[j];
+ }
+ }
+ simple_encode.EndEncode();
+ // The second encode.
+ SimpleEncode simple_encode_2(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode_2.ComputeFirstPassStats();
+ const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum();
+ simple_encode_2.StartEncode();
+ for (int i = 0; i < num_coding_frames_2; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode_2.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ quantize_index_list[i]);
+ for (int j = 0; j < num_rows_4x4 * num_cols_4x4; ++j) {
+ EXPECT_EQ(encode_frame_result.partition_info[j].row,
+ partition_info_list[i * num_units_4x4 + j].row);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column,
+ partition_info_list[i * num_units_4x4 + j].column);
+ EXPECT_EQ(encode_frame_result.partition_info[j].row_start,
+ partition_info_list[i * num_units_4x4 + j].row_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].column_start,
+ partition_info_list[i * num_units_4x4 + j].column_start);
+ EXPECT_EQ(encode_frame_result.partition_info[j].width,
+ partition_info_list[i * num_units_4x4 + j].width);
+ EXPECT_EQ(encode_frame_result.partition_info[j].height,
+ partition_info_list[i * num_units_4x4 + j].height);
+ }
+ }
+ simple_encode_2.EndEncode();
+}
+
+// Encode with default VP9 decision first.
+// Get QPs and arf locations from the first encode.
+// Set external arfs and QPs for the second encode.
+// Expect to get matched results.
+TEST_F(SimpleEncodeTest, EncodeConsistencySetExternalGroupOfPicturesMap) {
+ std::vector<int> quantize_index_list;
+ std::vector<uint64_t> ref_sse_list;
+ std::vector<double> ref_psnr_list;
+ std::vector<size_t> ref_bit_size_list;
+ std::vector<int> gop_map(num_frames_, 0);
+ {
+ // The first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ simple_encode.StartEncode();
+
+ int coded_show_frame_count = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ gop_map[coded_show_frame_count] |= kGopMapFlagStart;
+ if (group_of_picture.use_alt_ref) {
+ gop_map[coded_show_frame_count] |= kGopMapFlagUseAltRef;
+ }
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ quantize_index_list.push_back(encode_frame_result.quantize_index);
+ ref_sse_list.push_back(encode_frame_result.sse);
+ ref_psnr_list.push_back(encode_frame_result.psnr);
+ ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size);
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ }
+ simple_encode.EndEncode();
+ }
+ {
+ // The second encode with quantize index got from the first encode.
+ // The external arfs are the same as the first encode.
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_,
+ frame_rate_den_, target_bitrate_, num_frames_,
+ target_level_, in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ simple_encode.SetExternalGroupOfPicturesMap(gop_map.data(), gop_map.size());
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ EXPECT_EQ(static_cast<size_t>(num_coding_frames),
+ quantize_index_list.size());
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrameWithQuantizeIndex(&encode_frame_result,
+ quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.quantize_index, quantize_index_list[i]);
+ EXPECT_EQ(encode_frame_result.sse, ref_sse_list[i]);
+ EXPECT_DOUBLE_EQ(encode_frame_result.psnr, ref_psnr_list[i]);
+ EXPECT_EQ(encode_frame_result.coding_data_bit_size, ref_bit_size_list[i]);
+ }
+ simple_encode.EndEncode();
+ }
+}
+
+TEST_F(SimpleEncodeTest, SetExternalGroupOfPicturesMap) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+
+ std::vector<int> gop_map(num_frames_, 0);
+
+ // Should be the first gop group.
+ gop_map[0] = 0;
+
+ // Second gop group with an alt ref.
+ gop_map[5] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
+
+ // Third gop group without an alt ref.
+ gop_map[10] |= kGopMapFlagStart;
+
+ // Last gop group.
+ gop_map[14] |= kGopMapFlagStart | kGopMapFlagUseAltRef;
+
+ simple_encode.SetExternalGroupOfPicturesMap(gop_map.data(), gop_map.size());
+
+ std::vector<int> observed_gop_map =
+ simple_encode.ObserveExternalGroupOfPicturesMap();
+
+ // First gop group.
+ // There is always a key frame at show_idx 0 and key frame should always be
+ // the start of a gop. We expect ObserveExternalGroupOfPicturesMap() will
+ // insert an extra gop start here.
+ EXPECT_EQ(observed_gop_map[0], kGopMapFlagStart | kGopMapFlagUseAltRef);
+
+ // Second gop group with an alt ref.
+ EXPECT_EQ(observed_gop_map[5], kGopMapFlagStart | kGopMapFlagUseAltRef);
+
+ // Third gop group without an alt ref.
+ EXPECT_EQ(observed_gop_map[10], kGopMapFlagStart);
+
+ // Last gop group. The last gop is not supposed to use an alt ref. We expect
+ // ObserveExternalGroupOfPicturesMap() will remove the alt ref flag here.
+ EXPECT_EQ(observed_gop_map[14], kGopMapFlagStart);
+
+ int ref_gop_show_frame_count_list[4] = { 5, 5, 4, 3 };
+ size_t ref_gop_coded_frame_count_list[4] = { 6, 6, 4, 3 };
+ int gop_count = 0;
+
+ simple_encode.StartEncode();
+ int coded_show_frame_count = 0;
+ while (coded_show_frame_count < num_frames_) {
+ const GroupOfPicture group_of_picture =
+ simple_encode.ObserveGroupOfPicture();
+ const std::vector<EncodeFrameInfo> &encode_frame_list =
+ group_of_picture.encode_frame_list;
+ EXPECT_EQ(encode_frame_list.size(),
+ ref_gop_coded_frame_count_list[gop_count]);
+ EXPECT_EQ(group_of_picture.show_frame_count,
+ ref_gop_show_frame_count_list[gop_count]);
+ for (size_t group_index = 0; group_index < encode_frame_list.size();
+ ++group_index) {
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ }
+ coded_show_frame_count += group_of_picture.show_frame_count;
+ ++gop_count;
+ }
+ EXPECT_EQ(gop_count, 4);
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, GetEncodeFrameInfo) {
+ // Makes sure that the encode_frame_info obtained from GetEncodeFrameInfo()
+ // matches the counterpart in encode_frame_result obtained from EncodeFrame()
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ simple_encode.ComputeFirstPassStats();
+ const int num_coding_frames = simple_encode.GetCodingFrameNum();
+ simple_encode.StartEncode();
+ for (int i = 0; i < num_coding_frames; ++i) {
+ EncodeFrameInfo encode_frame_info = simple_encode.GetNextEncodeFrameInfo();
+ EncodeFrameResult encode_frame_result;
+ simple_encode.EncodeFrame(&encode_frame_result);
+ EXPECT_EQ(encode_frame_info.show_idx, encode_frame_result.show_idx);
+ EXPECT_EQ(encode_frame_info.frame_type, encode_frame_result.frame_type);
+ }
+ simple_encode.EndEncode();
+}
+
+TEST_F(SimpleEncodeTest, GetFramePixelCount) {
+ SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_,
+ target_bitrate_, num_frames_, target_level_,
+ in_file_path_str_.c_str());
+ EXPECT_EQ(simple_encode.GetFramePixelCount(),
+ static_cast<uint64_t>(width_ * height_ * 3 / 2));
+}
+
+} // namespace
+} // namespace vp9
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/media/libvpx/libvpx/test/simple_encoder.sh b/media/libvpx/libvpx/test/simple_encoder.sh
new file mode 100755
index 0000000000..dc7f46ff38
--- /dev/null
+++ b/media/libvpx/libvpx/test/simple_encoder.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx simple_encoder example. To add new tests to this
+## file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to simple_encoder_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+simple_encoder_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs simple_encoder using the codec specified by $1 with a frame limit of 100.
+simple_encoder() {
+ local encoder="${LIBVPX_BIN_PATH}/simple_encoder${VPX_TEST_EXE_SUFFIX}"
+ local codec="$1"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/simple_encoder_${codec}.ivf"
+
+ if [ ! -x "${encoder}" ]; then
+ elog "${encoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" 9999 0 100 \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+simple_encoder_vp8() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ simple_encoder vp8 || return 1
+ fi
+}
+
+simple_encoder_vp9() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ simple_encoder vp9 || return 1
+ fi
+}
+
+simple_encoder_tests="simple_encoder_vp8
+ simple_encoder_vp9"
+
+run_tests simple_encoder_verify_environment "${simple_encoder_tests}"
diff --git a/media/libvpx/libvpx/test/stress.sh b/media/libvpx/libvpx/test/stress.sh
new file mode 100755
index 0000000000..ba79a52ac3
--- /dev/null
+++ b/media/libvpx/libvpx/test/stress.sh
@@ -0,0 +1,183 @@
+#!/bin/sh
+##
+## Copyright (c) 2016 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.
+##
+## This file performs a stress test. It runs (STRESS_ONEPASS_MAX_JOBS,
+## default=5) one, (STRESS_TWOPASS_MAX_JOBS, default=5) two pass &
+## (STRESS_RT_MAX_JOBS, default=5) encodes and (STRESS_<codec>_DECODE_MAX_JOBS,
+## default=30) decodes in parallel.
+
+. $(dirname $0)/tools_common.sh
+
+YUV="${LIBVPX_TEST_DATA_PATH}/niklas_1280_720_30.yuv"
+VP8="${LIBVPX_TEST_DATA_PATH}/tos_vp8.webm"
+VP9="${LIBVPX_TEST_DATA_PATH}/vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm"
+DATA_URL="https://storage.googleapis.com/downloads.webmproject.org/test_data/libvpx/"
+SHA1_FILE="$(dirname $0)/test-data.sha1"
+
+# Set sha1sum to proper sha program (sha1sum, shasum, sha1). This code is
+# cribbed from libs.mk.
+[ -x "$(which sha1sum)" ] && sha1sum=sha1sum
+[ -x "$(which shasum)" ] && sha1sum=shasum
+[ -x "$(which sha1)" ] && sha1sum=sha1
+
+# Download a file from the url and check its sha1sum.
+download_and_check_file() {
+ # Get the file from the file path.
+ local root="${1#${LIBVPX_TEST_DATA_PATH}/}"
+
+ # Download the file using curl. Trap to insure non partial file.
+ (trap "rm -f $1" INT TERM \
+ && eval "curl --retry 1 -L -o $1 ${DATA_URL}${root} ${devnull}")
+
+ # Check the sha1 sum of the file.
+ if [ -n "${sha1sum}" ]; then
+ set -e
+ grep ${root} ${SHA1_FILE} \
+ | (cd ${LIBVPX_TEST_DATA_PATH}; ${sha1sum} -c);
+ fi
+}
+
+# Environment check: Make sure input is available.
+stress_verify_environment() {
+ if [ ! -e "${SHA1_FILE}" ] ; then
+ echo "Missing ${SHA1_FILE}"
+ return 1
+ fi
+ for file in "${YUV}" "${VP8}" "${VP9}"; do
+ if [ ! -e "${file}" ] ; then
+ download_and_check_file "${file}" || return 1
+ fi
+ done
+ if [ ! -e "${YUV}" ] || [ ! -e "${VP8}" ] || [ ! -e "${VP9}" ] ; then
+ elog "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ if [ -z "$(vpx_tool_path vpxenc)" ]; then
+ elog "vpxenc not found. It must exist in LIBVPX_BIN_PATH or its parent."
+ return 1
+ fi
+ if [ -z "$(vpx_tool_path vpxdec)" ]; then
+ elog "vpxdec not found. It must exist in LIBVPX_BIN_PATH or its parent."
+ return 1
+ fi
+}
+
+# This function runs tests on libvpx that run multiple encodes and decodes
+# in parallel in hopes of catching synchronization and/or threading issues.
+stress() {
+ local decoder="$(vpx_tool_path vpxdec)"
+ local encoder="$(vpx_tool_path vpxenc)"
+ local codec="$1"
+ local webm="$2"
+ local decode_count="$3"
+ local threads="$4"
+ local enc_args="$5"
+ local pids=""
+ local rt_max_jobs=${STRESS_RT_MAX_JOBS:-5}
+ local onepass_max_jobs=${STRESS_ONEPASS_MAX_JOBS:-5}
+ local twopass_max_jobs=${STRESS_TWOPASS_MAX_JOBS:-5}
+
+ # Enable job control, so we can run multiple processes.
+ set -m
+
+ # Start $onepass_max_jobs encode jobs in parallel.
+ for i in $(seq ${onepass_max_jobs}); do
+ bitrate=$(($i * 20 + 300))
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "--codec=${codec} -w 1280 -h 720" \
+ "${YUV}" "-t ${threads} --limit=150 --test-decode=fatal --passes=1" \
+ "--target-bitrate=${bitrate} -o ${VPX_TEST_OUTPUT_DIR}/${i}.1pass.webm" \
+ "${enc_args}" ${devnull} &
+ pids="${pids} $!"
+ done
+
+ # Start $twopass_max_jobs encode jobs in parallel.
+ for i in $(seq ${twopass_max_jobs}); do
+ bitrate=$(($i * 20 + 300))
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "--codec=${codec} -w 1280 -h 720" \
+ "${YUV}" "-t ${threads} --limit=150 --test-decode=fatal --passes=2" \
+ "--target-bitrate=${bitrate} -o ${VPX_TEST_OUTPUT_DIR}/${i}.2pass.webm" \
+ "${enc_args}" ${devnull} &
+ pids="${pids} $!"
+ done
+
+ # Start $rt_max_jobs rt encode jobs in parallel.
+ for i in $(seq ${rt_max_jobs}); do
+ bitrate=$(($i * 20 + 300))
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "--codec=${codec} -w 1280 -h 720" \
+ "${YUV}" "-t ${threads} --limit=150 --test-decode=fatal " \
+ "--target-bitrate=${bitrate} --lag-in-frames=0 --error-resilient=1" \
+ "--kf-min-dist=3000 --kf-max-dist=3000 --cpu-used=-6 --static-thresh=1" \
+ "--end-usage=cbr --min-q=2 --max-q=56 --undershoot-pct=100" \
+ "--overshoot-pct=15 --buf-sz=1000 --buf-initial-sz=500" \
+ "--buf-optimal-sz=600 --max-intra-rate=900 --resize-allowed=0" \
+ "--drop-frame=0 --passes=1 --rt --noise-sensitivity=4" \
+ "-o ${VPX_TEST_OUTPUT_DIR}/${i}.rt.webm" ${devnull} &
+ pids="${pids} $!"
+ done
+
+ # Start $decode_count decode jobs in parallel.
+ for i in $(seq "${decode_count}"); do
+ eval "${decoder}" "-t ${threads}" "${webm}" "--noblit" ${devnull} &
+ pids="${pids} $!"
+ done
+
+ # Wait for all parallel jobs to finish.
+ fail=0
+ for job in "${pids}"; do
+ wait $job || fail=$(($fail + 1))
+ done
+ return $fail
+}
+
+vp8_stress_test() {
+ local vp8_max_jobs=${STRESS_VP8_DECODE_MAX_JOBS:-40}
+ if [ "$(vp8_decode_available)" = "yes" -a \
+ "$(vp8_encode_available)" = "yes" ]; then
+ stress vp8 "${VP8}" "${vp8_max_jobs}" 4
+ fi
+}
+
+vp8_stress_test_token_parititions() {
+ local vp8_max_jobs=${STRESS_VP8_DECODE_MAX_JOBS:-40}
+ if [ "$(vp8_decode_available)" = "yes" -a \
+ "$(vp8_encode_available)" = "yes" ]; then
+ for threads in 2 4 8; do
+ for token_partitions in 1 2 3; do
+ stress vp8 "${VP8}" "${vp8_max_jobs}" ${threads} \
+ "--token-parts=$token_partitions"
+ done
+ done
+ fi
+}
+
+vp9_stress() {
+ local vp9_max_jobs=${STRESS_VP9_DECODE_MAX_JOBS:-25}
+
+ if [ "$(vp9_decode_available)" = "yes" -a \
+ "$(vp9_encode_available)" = "yes" ]; then
+ stress vp9 "${VP9}" "${vp9_max_jobs}" "$@"
+ fi
+}
+
+vp9_stress_test() {
+ for threads in 4 8 64; do
+ vp9_stress "$threads" "--row-mt=0"
+ done
+}
+
+vp9_stress_test_row_mt() {
+ for threads in 4 8 64; do
+ vp9_stress "$threads" "--row-mt=1"
+ done
+}
+
+run_tests stress_verify_environment \
+ "vp8_stress_test vp8_stress_test_token_parititions
+ vp9_stress_test vp9_stress_test_row_mt"
diff --git a/media/libvpx/libvpx/test/sum_squares_test.cc b/media/libvpx/libvpx/test/sum_squares_test.cc
new file mode 100644
index 0000000000..df6da84037
--- /dev/null
+++ b/media/libvpx/libvpx/test/sum_squares_test.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016 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 <cmath>
+#include <cstdlib>
+#include <string>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+const int kNumIterations = 10000;
+
+typedef uint64_t (*SSI16Func)(const int16_t *src, int stride, int size);
+typedef std::tuple<SSI16Func, SSI16Func> SumSquaresParam;
+
+class SumSquaresTest : public ::testing::TestWithParam<SumSquaresParam> {
+ public:
+ virtual ~SumSquaresTest() {}
+ virtual void SetUp() {
+ ref_func_ = GET_PARAM(0);
+ tst_func_ = GET_PARAM(1);
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ SSI16Func ref_func_;
+ SSI16Func tst_func_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SumSquaresTest);
+
+TEST_P(SumSquaresTest, OperationCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ DECLARE_ALIGNED(16, int16_t, src[256 * 256]);
+ const int msb = 11; // Up to 12 bit input
+ const int limit = 1 << (msb + 1);
+
+ for (int k = 0; k < kNumIterations; k++) {
+ const int size = 4 << rnd(6); // Up to 128x128
+ int stride = 4 << rnd(7); // Up to 256 stride
+ while (stride < size) { // Make sure it's valid
+ stride = 4 << rnd(7);
+ }
+
+ for (int i = 0; i < size; ++i) {
+ for (int j = 0; j < size; ++j) {
+ src[i * stride + j] = rnd(2) ? rnd(limit) : -rnd(limit);
+ }
+ }
+
+ const uint64_t res_ref = ref_func_(src, stride, size);
+ uint64_t res_tst;
+ ASM_REGISTER_STATE_CHECK(res_tst = tst_func_(src, stride, size));
+
+ ASSERT_EQ(res_ref, res_tst) << "Error: Sum Squares Test"
+ << " C output does not match optimized output.";
+ }
+}
+
+TEST_P(SumSquaresTest, ExtremeValues) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ DECLARE_ALIGNED(16, int16_t, src[256 * 256]);
+ const int msb = 11; // Up to 12 bit input
+ const int limit = 1 << (msb + 1);
+
+ for (int k = 0; k < kNumIterations; k++) {
+ const int size = 4 << rnd(6); // Up to 128x128
+ int stride = 4 << rnd(7); // Up to 256 stride
+ while (stride < size) { // Make sure it's valid
+ stride = 4 << rnd(7);
+ }
+
+ const int val = rnd(2) ? limit - 1 : -(limit - 1);
+ for (int i = 0; i < size; ++i) {
+ for (int j = 0; j < size; ++j) {
+ src[i * stride + j] = val;
+ }
+ }
+
+ const uint64_t res_ref = ref_func_(src, stride, size);
+ uint64_t res_tst;
+ ASM_REGISTER_STATE_CHECK(res_tst = tst_func_(src, stride, size));
+
+ ASSERT_EQ(res_ref, res_tst) << "Error: Sum Squares Test"
+ << " C output does not match optimized output.";
+ }
+}
+
+using std::make_tuple;
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, SumSquaresTest,
+ ::testing::Values(make_tuple(&vpx_sum_squares_2d_i16_c,
+ &vpx_sum_squares_2d_i16_neon)));
+#endif // HAVE_NEON
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, SumSquaresTest,
+ ::testing::Values(make_tuple(&vpx_sum_squares_2d_i16_c,
+ &vpx_sum_squares_2d_i16_sse2)));
+#endif // HAVE_SSE2
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, SumSquaresTest,
+ ::testing::Values(make_tuple(&vpx_sum_squares_2d_i16_c,
+ &vpx_sum_squares_2d_i16_msa)));
+#endif // HAVE_MSA
+} // namespace
diff --git a/media/libvpx/libvpx/test/superframe_test.cc b/media/libvpx/libvpx/test/superframe_test.cc
new file mode 100644
index 0000000000..a5c92e9147
--- /dev/null
+++ b/media/libvpx/libvpx/test/superframe_test.cc
@@ -0,0 +1,102 @@
+/*
+ * 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 <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+const int kTestMode = 0;
+
+typedef std::tuple<libvpx_test::TestMode, int> SuperframeTestParam;
+
+class SuperframeTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<SuperframeTestParam> {
+ protected:
+ SuperframeTest()
+ : EncoderTest(GET_PARAM(0)), modified_buf_(nullptr), last_sf_pts_(0) {}
+ virtual ~SuperframeTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ const SuperframeTestParam input = GET_PARAM(1);
+ const libvpx_test::TestMode mode = std::get<kTestMode>(input);
+ SetMode(mode);
+ sf_count_ = 0;
+ sf_count_max_ = INT_MAX;
+ }
+
+ virtual void TearDown() { delete[] modified_buf_; }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ }
+ }
+
+ virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook(
+ const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return pkt;
+
+ const uint8_t *buffer = reinterpret_cast<uint8_t *>(pkt->data.frame.buf);
+ const uint8_t marker = buffer[pkt->data.frame.sz - 1];
+ const int frames = (marker & 0x7) + 1;
+ const int mag = ((marker >> 3) & 3) + 1;
+ const unsigned int index_sz = 2 + mag * frames;
+ if ((marker & 0xe0) == 0xc0 && pkt->data.frame.sz >= index_sz &&
+ buffer[pkt->data.frame.sz - index_sz] == marker) {
+ // frame is a superframe. strip off the index.
+ if (modified_buf_) delete[] modified_buf_;
+ modified_buf_ = new uint8_t[pkt->data.frame.sz - index_sz];
+ memcpy(modified_buf_, pkt->data.frame.buf, pkt->data.frame.sz - index_sz);
+ modified_pkt_ = *pkt;
+ modified_pkt_.data.frame.buf = modified_buf_;
+ modified_pkt_.data.frame.sz -= index_sz;
+
+ sf_count_++;
+ last_sf_pts_ = pkt->data.frame.pts;
+ return &modified_pkt_;
+ }
+
+ // Make sure we do a few frames after the last SF
+ abort_ |=
+ sf_count_ > sf_count_max_ && pkt->data.frame.pts - last_sf_pts_ >= 5;
+ return pkt;
+ }
+
+ int sf_count_;
+ int sf_count_max_;
+ vpx_codec_cx_pkt_t modified_pkt_;
+ uint8_t *modified_buf_;
+ vpx_codec_pts_t last_sf_pts_;
+};
+
+TEST_P(SuperframeTest, TestSuperframeIndexIsOptional) {
+ sf_count_max_ = 0; // early exit on successful test.
+ cfg_.g_lag_in_frames = 25;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 40);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ EXPECT_EQ(sf_count_, 1);
+}
+
+VP9_INSTANTIATE_TEST_SUITE(
+ SuperframeTest,
+ ::testing::Combine(::testing::Values(::libvpx_test::kTwoPassGood),
+ ::testing::Values(0)));
+} // namespace
diff --git a/media/libvpx/libvpx/test/svc_datarate_test.cc b/media/libvpx/libvpx/test/svc_datarate_test.cc
new file mode 100644
index 0000000000..d571f50860
--- /dev/null
+++ b/media/libvpx/libvpx/test/svc_datarate_test.cc
@@ -0,0 +1,1796 @@
+/*
+ * 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 "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/svc_test.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vp9/common/vp9_onyxc_int.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/bitops.h"
+
+namespace svc_test {
+namespace {
+
+typedef enum {
+ // Inter-layer prediction is on on all frames.
+ INTER_LAYER_PRED_ON,
+ // Inter-layer prediction is off on all frames.
+ INTER_LAYER_PRED_OFF,
+ // Inter-layer prediction is off on non-key frames and non-sync frames.
+ INTER_LAYER_PRED_OFF_NONKEY,
+ // Inter-layer prediction is on on all frames, but constrained such
+ // that any layer S (> 0) can only predict from previous spatial
+ // layer S-1, from the same superframe.
+ INTER_LAYER_PRED_ON_CONSTRAINED
+} INTER_LAYER_PRED;
+
+class DatarateOnePassCbrSvc : public OnePassCbrSvc {
+ public:
+ explicit DatarateOnePassCbrSvc(const ::libvpx_test::CodecFactory *codec)
+ : OnePassCbrSvc(codec) {
+ inter_layer_pred_mode_ = 0;
+ }
+
+ protected:
+ virtual ~DatarateOnePassCbrSvc() {}
+
+ virtual void ResetModel() {
+ last_pts_ = 0;
+ duration_ = 0.0;
+ mismatch_psnr_ = 0.0;
+ mismatch_nframes_ = 0;
+ denoiser_on_ = 0;
+ tune_content_ = 0;
+ base_speed_setting_ = 5;
+ spatial_layer_id_ = 0;
+ temporal_layer_id_ = 0;
+ update_pattern_ = 0;
+ memset(bits_in_buffer_model_, 0, sizeof(bits_in_buffer_model_));
+ memset(bits_total_, 0, sizeof(bits_total_));
+ memset(layer_target_avg_bandwidth_, 0, sizeof(layer_target_avg_bandwidth_));
+ dynamic_drop_layer_ = false;
+ single_layer_resize_ = false;
+ change_bitrate_ = false;
+ last_pts_ref_ = 0;
+ middle_bitrate_ = 0;
+ top_bitrate_ = 0;
+ superframe_count_ = -1;
+ key_frame_spacing_ = 9999;
+ num_nonref_frames_ = 0;
+ layer_framedrop_ = 0;
+ force_key_ = 0;
+ force_key_test_ = 0;
+ insert_layer_sync_ = 0;
+ layer_sync_on_base_ = 0;
+ force_intra_only_frame_ = 0;
+ superframe_has_intra_only_ = 0;
+ use_post_encode_drop_ = 0;
+ denoiser_off_on_ = false;
+ denoiser_enable_layers_ = false;
+ num_resize_down_ = 0;
+ num_resize_up_ = 0;
+ for (int i = 0; i < VPX_MAX_LAYERS; i++) {
+ prev_frame_width[i] = 320;
+ prev_frame_height[i] = 240;
+ }
+ ksvc_flex_noupd_tlenh_ = false;
+ }
+ virtual void BeginPassHook(unsigned int /*pass*/) {}
+
+ // Example pattern for spatial layers and 2 temporal layers used in the
+ // bypass/flexible mode. The pattern corresponds to the pattern
+ // VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
+ // non-flexible mode, except that we disable inter-layer prediction.
+ void set_frame_flags_bypass_mode(int tl, int num_spatial_layers,
+ int is_key_frame,
+ vpx_svc_ref_frame_config_t *ref_frame_config,
+ int noupdate_tlenh) {
+ for (int sl = 0; sl < num_spatial_layers; ++sl)
+ ref_frame_config->update_buffer_slot[sl] = 0;
+
+ for (int sl = 0; sl < num_spatial_layers; ++sl) {
+ if (tl == 0) {
+ ref_frame_config->lst_fb_idx[sl] = sl;
+ if (sl) {
+ if (is_key_frame) {
+ ref_frame_config->lst_fb_idx[sl] = sl - 1;
+ ref_frame_config->gld_fb_idx[sl] = sl;
+ } else {
+ ref_frame_config->gld_fb_idx[sl] = sl - 1;
+ }
+ } else {
+ ref_frame_config->gld_fb_idx[sl] = 0;
+ }
+ ref_frame_config->alt_fb_idx[sl] = 0;
+ } else if (tl == 1) {
+ ref_frame_config->lst_fb_idx[sl] = sl;
+ ref_frame_config->gld_fb_idx[sl] =
+ VPXMIN(REF_FRAMES - 1, num_spatial_layers + sl - 1);
+ ref_frame_config->alt_fb_idx[sl] =
+ VPXMIN(REF_FRAMES - 1, num_spatial_layers + sl);
+ }
+ if (!tl) {
+ if (!sl) {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->lst_fb_idx[sl];
+ } else {
+ if (is_key_frame) {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->gld_fb_idx[sl];
+ } else {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->lst_fb_idx[sl];
+ }
+ }
+ } else if (tl == 1) {
+ if (!sl) {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->alt_fb_idx[sl];
+ } else {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ // Non reference frame on top temporal top spatial.
+ ref_frame_config->update_buffer_slot[sl] = 0;
+ }
+ // Force no update on all spatial layers for temporal enhancement layer
+ // frames.
+ if (noupdate_tlenh) ref_frame_config->update_buffer_slot[sl] = 0;
+ }
+ }
+ }
+
+ void CheckLayerRateTargeting(int num_spatial_layers, int num_temporal_layers,
+ double thresh_overshoot,
+ double thresh_undershoot) const {
+ for (int sl = 0; sl < num_spatial_layers; ++sl)
+ for (int tl = 0; tl < num_temporal_layers; ++tl) {
+ const int layer = sl * num_temporal_layers + tl;
+ ASSERT_GE(cfg_.layer_target_bitrate[layer],
+ file_datarate_[layer] * thresh_overshoot)
+ << " The datarate for the file exceeds the target by too much!";
+ ASSERT_LE(cfg_.layer_target_bitrate[layer],
+ file_datarate_[layer] * thresh_undershoot)
+ << " The datarate for the file is lower than the target by too "
+ "much!";
+ }
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ PreEncodeFrameHookSetup(video, encoder);
+
+ if (video->frame() == 0) {
+ if (force_intra_only_frame_) {
+ // Decoder sets the color_space for Intra-only frames
+ // to BT_601 (see line 1810 in vp9_decodeframe.c).
+ // So set it here in these tess to avoid encoder-decoder
+ // mismatch check on color space setting.
+ encoder->Control(VP9E_SET_COLOR_SPACE, VPX_CS_BT_601);
+ }
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
+ encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_);
+ encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED, inter_layer_pred_mode_);
+
+ if (layer_framedrop_) {
+ vpx_svc_frame_drop_t svc_drop_frame;
+ svc_drop_frame.framedrop_mode = LAYER_DROP;
+ for (int i = 0; i < number_spatial_layers_; i++)
+ svc_drop_frame.framedrop_thresh[i] = 30;
+ svc_drop_frame.max_consec_drop = 30;
+ encoder->Control(VP9E_SET_SVC_FRAME_DROP_LAYER, &svc_drop_frame);
+ }
+
+ if (use_post_encode_drop_) {
+ encoder->Control(VP9E_SET_POSTENCODE_DROP, use_post_encode_drop_);
+ }
+ }
+
+ if (denoiser_off_on_) {
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ // Set inter_layer_pred to INTER_LAYER_PRED_OFF_NONKEY (K-SVC).
+ encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED, 2);
+ if (!denoiser_enable_layers_) {
+ if (video->frame() == 0)
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 0);
+ else if (video->frame() == 100)
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 1);
+ } else {
+ // Cumulative bitrates for top spatial layers, for
+ // 3 temporal layers.
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 0);
+ // Change layer bitrates to set top spatial layer to 0.
+ // This is for 3 spatial 3 temporal layers.
+ // This will trigger skip encoding/dropping of top spatial layer.
+ cfg_.rc_target_bitrate -= cfg_.layer_target_bitrate[8];
+ for (int i = 0; i < 3; i++)
+ bitrate_sl3_[i] = cfg_.layer_target_bitrate[i + 6];
+ cfg_.layer_target_bitrate[6] = 0;
+ cfg_.layer_target_bitrate[7] = 0;
+ cfg_.layer_target_bitrate[8] = 0;
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 100) {
+ // Change layer bitrates to non-zero on top spatial layer.
+ // This will trigger skip encoding of top spatial layer
+ // on key frame (period = 100).
+ for (int i = 0; i < 3; i++)
+ cfg_.layer_target_bitrate[i + 6] = bitrate_sl3_[i];
+ cfg_.rc_target_bitrate += cfg_.layer_target_bitrate[8];
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 120) {
+ // Enable denoiser and top spatial layer after key frame (period is
+ // 100).
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, 1);
+ }
+ }
+ }
+
+ if (ksvc_flex_noupd_tlenh_) {
+ vpx_svc_layer_id_t layer_id;
+ layer_id.spatial_layer_id = 0;
+ layer_id.temporal_layer_id = (video->frame() % 2 != 0);
+ temporal_layer_id_ = layer_id.temporal_layer_id;
+ for (int i = 0; i < number_spatial_layers_; i++) {
+ layer_id.temporal_layer_id_per_spatial[i] = temporal_layer_id_;
+ ref_frame_config_.duration[i] = 1;
+ }
+ encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
+ set_frame_flags_bypass_mode(layer_id.temporal_layer_id,
+ number_spatial_layers_, 0, &ref_frame_config_,
+ 1);
+ encoder->Control(VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_frame_config_);
+ }
+
+ if (update_pattern_ && video->frame() >= 100) {
+ vpx_svc_layer_id_t layer_id;
+ if (video->frame() == 100) {
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+ encoder->Config(&cfg_);
+ }
+ // Set layer id since the pattern changed.
+ layer_id.spatial_layer_id = 0;
+ layer_id.temporal_layer_id = (video->frame() % 2 != 0);
+ temporal_layer_id_ = layer_id.temporal_layer_id;
+ for (int i = 0; i < number_spatial_layers_; i++) {
+ layer_id.temporal_layer_id_per_spatial[i] = temporal_layer_id_;
+ ref_frame_config_.duration[i] = 1;
+ }
+ encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
+ set_frame_flags_bypass_mode(layer_id.temporal_layer_id,
+ number_spatial_layers_, 0, &ref_frame_config_,
+ 0);
+ encoder->Control(VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_frame_config_);
+ }
+
+ if (change_bitrate_ && video->frame() == 200) {
+ duration_ = (last_pts_ + 1) * timebase_;
+ for (int sl = 0; sl < number_spatial_layers_; ++sl) {
+ for (int tl = 0; tl < number_temporal_layers_; ++tl) {
+ const int layer = sl * number_temporal_layers_ + tl;
+ const double file_size_in_kb = bits_total_[layer] / 1000.;
+ file_datarate_[layer] = file_size_in_kb / duration_;
+ }
+ }
+
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_,
+ 0.78, 1.15);
+
+ memset(file_datarate_, 0, sizeof(file_datarate_));
+ memset(bits_total_, 0, sizeof(bits_total_));
+ int64_t bits_in_buffer_model_tmp[VPX_MAX_LAYERS];
+ last_pts_ref_ = last_pts_;
+ // Set new target bitarate.
+ cfg_.rc_target_bitrate = cfg_.rc_target_bitrate >> 1;
+ // Buffer level should not reset on dynamic bitrate change.
+ memcpy(bits_in_buffer_model_tmp, bits_in_buffer_model_,
+ sizeof(bits_in_buffer_model_));
+ AssignLayerBitrates();
+ memcpy(bits_in_buffer_model_, bits_in_buffer_model_tmp,
+ sizeof(bits_in_buffer_model_));
+
+ // Change config to update encoder with new bitrate configuration.
+ encoder->Config(&cfg_);
+ }
+
+ if (dynamic_drop_layer_ && !single_layer_resize_) {
+ if (video->frame() == 0) {
+ // Change layer bitrates to set top layers to 0. This will trigger skip
+ // encoding/dropping of top two spatial layers.
+ cfg_.rc_target_bitrate -=
+ (cfg_.layer_target_bitrate[1] + cfg_.layer_target_bitrate[2]);
+ middle_bitrate_ = cfg_.layer_target_bitrate[1];
+ top_bitrate_ = cfg_.layer_target_bitrate[2];
+ cfg_.layer_target_bitrate[1] = 0;
+ cfg_.layer_target_bitrate[2] = 0;
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 50) {
+ // Change layer bitrates to non-zero on two top spatial layers.
+ // This will trigger skip encoding of top two spatial layers.
+ cfg_.layer_target_bitrate[1] = middle_bitrate_;
+ cfg_.layer_target_bitrate[2] = top_bitrate_;
+ cfg_.rc_target_bitrate +=
+ cfg_.layer_target_bitrate[2] + cfg_.layer_target_bitrate[1];
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 100) {
+ // Change layer bitrates to set top layers to 0. This will trigger skip
+ // encoding/dropping of top two spatial layers.
+ cfg_.rc_target_bitrate -=
+ (cfg_.layer_target_bitrate[1] + cfg_.layer_target_bitrate[2]);
+ middle_bitrate_ = cfg_.layer_target_bitrate[1];
+ top_bitrate_ = cfg_.layer_target_bitrate[2];
+ cfg_.layer_target_bitrate[1] = 0;
+ cfg_.layer_target_bitrate[2] = 0;
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 150) {
+ // Change layer bitrate on second layer to non-zero to start
+ // encoding it again.
+ cfg_.layer_target_bitrate[1] = middle_bitrate_;
+ cfg_.rc_target_bitrate += cfg_.layer_target_bitrate[1];
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 200) {
+ // Change layer bitrate on top layer to non-zero to start
+ // encoding it again.
+ cfg_.layer_target_bitrate[2] = top_bitrate_;
+ cfg_.rc_target_bitrate += cfg_.layer_target_bitrate[2];
+ encoder->Config(&cfg_);
+ }
+ } else if (dynamic_drop_layer_ && single_layer_resize_) {
+ // Change layer bitrates to set top layers to 0. This will trigger skip
+ // encoding/dropping of top spatial layers.
+ if (video->frame() == 2) {
+ cfg_.rc_target_bitrate -=
+ (cfg_.layer_target_bitrate[1] + cfg_.layer_target_bitrate[2]);
+ middle_bitrate_ = cfg_.layer_target_bitrate[1];
+ top_bitrate_ = cfg_.layer_target_bitrate[2];
+ cfg_.layer_target_bitrate[1] = 0;
+ cfg_.layer_target_bitrate[2] = 0;
+ // Set spatial layer 0 to a very low bitrate to trigger resize.
+ cfg_.layer_target_bitrate[0] = 30;
+ cfg_.rc_target_bitrate = cfg_.layer_target_bitrate[0];
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 100) {
+ // Set base spatial layer to very high to go back up to original size.
+ cfg_.layer_target_bitrate[0] = 400;
+ cfg_.rc_target_bitrate = cfg_.layer_target_bitrate[0];
+ encoder->Config(&cfg_);
+ }
+ } else if (!dynamic_drop_layer_ && single_layer_resize_) {
+ if (video->frame() == 2) {
+ cfg_.layer_target_bitrate[0] = 30;
+ cfg_.layer_target_bitrate[1] = 50;
+ cfg_.rc_target_bitrate =
+ (cfg_.layer_target_bitrate[0] + cfg_.layer_target_bitrate[1]);
+ encoder->Config(&cfg_);
+ } else if (video->frame() == 160) {
+ cfg_.layer_target_bitrate[0] = 1500;
+ cfg_.layer_target_bitrate[1] = 2000;
+ cfg_.rc_target_bitrate =
+ (cfg_.layer_target_bitrate[0] + cfg_.layer_target_bitrate[1]);
+ encoder->Config(&cfg_);
+ }
+ }
+ if (force_key_test_ && force_key_) frame_flags_ = VPX_EFLAG_FORCE_KF;
+
+ if (insert_layer_sync_) {
+ vpx_svc_spatial_layer_sync_t svc_layer_sync;
+ svc_layer_sync.base_layer_intra_only = 0;
+ for (int i = 0; i < number_spatial_layers_; i++)
+ svc_layer_sync.spatial_layer_sync[i] = 0;
+ if (force_intra_only_frame_) {
+ superframe_has_intra_only_ = 0;
+ if (video->frame() == 0) {
+ svc_layer_sync.base_layer_intra_only = 1;
+ svc_layer_sync.spatial_layer_sync[0] = 1;
+ encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync);
+ superframe_has_intra_only_ = 1;
+ } else if (video->frame() == 100) {
+ svc_layer_sync.base_layer_intra_only = 1;
+ svc_layer_sync.spatial_layer_sync[0] = 1;
+ encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync);
+ superframe_has_intra_only_ = 1;
+ }
+ } else {
+ layer_sync_on_base_ = 0;
+ if (video->frame() == 150) {
+ svc_layer_sync.spatial_layer_sync[1] = 1;
+ encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync);
+ } else if (video->frame() == 240) {
+ svc_layer_sync.spatial_layer_sync[2] = 1;
+ encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync);
+ } else if (video->frame() == 320) {
+ svc_layer_sync.spatial_layer_sync[0] = 1;
+ layer_sync_on_base_ = 1;
+ encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync);
+ }
+ }
+ }
+
+ const vpx_rational_t tb = video->timebase();
+ timebase_ = static_cast<double>(tb.num) / tb.den;
+ duration_ = 0;
+ }
+
+ vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
+ uint32_t sizes[8], int *count) {
+ uint8_t marker;
+ marker = *(data + data_sz - 1);
+ *count = 0;
+ if ((marker & 0xe0) == 0xc0) {
+ const uint32_t frames = (marker & 0x7) + 1;
+ const uint32_t mag = ((marker >> 3) & 0x3) + 1;
+ const size_t index_sz = 2 + mag * frames;
+ // This chunk is marked as having a superframe index but doesn't have
+ // enough data for it, thus it's an invalid superframe index.
+ if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
+ {
+ const uint8_t marker2 = *(data + data_sz - index_sz);
+ // This chunk is marked as having a superframe index but doesn't have
+ // the matching marker byte at the front of the index therefore it's an
+ // invalid chunk.
+ if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
+ }
+ {
+ uint32_t i, j;
+ const uint8_t *x = &data[data_sz - index_sz + 1];
+ for (i = 0; i < frames; ++i) {
+ uint32_t this_sz = 0;
+
+ for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
+ sizes[i] = this_sz;
+ }
+ *count = frames;
+ }
+ }
+ return VPX_CODEC_OK;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ uint32_t sizes[8] = { 0 };
+ uint32_t sizes_parsed[8] = { 0 };
+ int count = 0;
+ int num_layers_encoded = 0;
+ last_pts_ = pkt->data.frame.pts;
+ const bool key_frame =
+ (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
+ if (key_frame) {
+ // For test that inserts layer sync frames: requesting a layer_sync on
+ // the base layer must force key frame. So if any key frame occurs after
+ // first superframe it must due to layer sync on base spatial layer.
+ if (superframe_count_ > 0 && insert_layer_sync_ &&
+ !force_intra_only_frame_) {
+ ASSERT_EQ(layer_sync_on_base_, 1);
+ }
+ temporal_layer_id_ = 0;
+ superframe_count_ = 0;
+ }
+ parse_superframe_index(static_cast<const uint8_t *>(pkt->data.frame.buf),
+ pkt->data.frame.sz, sizes_parsed, &count);
+ // Count may be less than number of spatial layers because of frame drops.
+ if (number_spatial_layers_ > 1) {
+ for (int sl = 0; sl < number_spatial_layers_; ++sl) {
+ if (pkt->data.frame.spatial_layer_encoded[sl]) {
+ sizes[sl] = sizes_parsed[num_layers_encoded];
+ num_layers_encoded++;
+ }
+ }
+ }
+ // For superframe with Intra-only count will be +1 larger
+ // because of no-show frame.
+ if (force_intra_only_frame_ && superframe_has_intra_only_)
+ ASSERT_EQ(count, num_layers_encoded + 1);
+ else
+ ASSERT_EQ(count, num_layers_encoded);
+
+ // In the constrained frame drop mode, if a given spatial is dropped all
+ // upper layers must be dropped too.
+ if (!layer_framedrop_) {
+ int num_layers_dropped = 0;
+ for (int sl = 0; sl < number_spatial_layers_; ++sl) {
+ if (!pkt->data.frame.spatial_layer_encoded[sl]) {
+ // Check that all upper layers are dropped.
+ num_layers_dropped++;
+ for (int sl2 = sl + 1; sl2 < number_spatial_layers_; ++sl2)
+ ASSERT_EQ(pkt->data.frame.spatial_layer_encoded[sl2], 0);
+ }
+ }
+ if (num_layers_dropped == number_spatial_layers_ - 1)
+ force_key_ = 1;
+ else
+ force_key_ = 0;
+ }
+ // Keep track of number of non-reference frames, needed for mismatch check.
+ // Non-reference frames are top spatial and temporal layer frames,
+ // for TL > 0.
+ if (temporal_layer_id_ == number_temporal_layers_ - 1 &&
+ temporal_layer_id_ > 0 &&
+ pkt->data.frame.spatial_layer_encoded[number_spatial_layers_ - 1])
+ num_nonref_frames_++;
+ for (int sl = 0; sl < number_spatial_layers_; ++sl) {
+ sizes[sl] = sizes[sl] << 3;
+ // Update the total encoded bits per layer.
+ // For temporal layers, update the cumulative encoded bits per layer.
+ for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) {
+ const int layer = sl * number_temporal_layers_ + tl;
+ bits_total_[layer] += static_cast<int64_t>(sizes[sl]);
+ // Update the per-layer buffer level with the encoded frame size.
+ bits_in_buffer_model_[layer] -= static_cast<int64_t>(sizes[sl]);
+ // There should be no buffer underrun, except on the base
+ // temporal layer, since there may be key frames there.
+ // Fo short key frame spacing, buffer can underrun on individual frames.
+ if (!key_frame && tl > 0 && key_frame_spacing_ < 100) {
+ ASSERT_GE(bits_in_buffer_model_[layer], 0)
+ << "Buffer Underrun at frame " << pkt->data.frame.pts;
+ }
+ }
+
+ if (!single_layer_resize_) {
+ unsigned int scaled_width = top_sl_width_ *
+ svc_params_.scaling_factor_num[sl] /
+ svc_params_.scaling_factor_den[sl];
+ if (scaled_width % 2 != 0) scaled_width += 1;
+ ASSERT_EQ(pkt->data.frame.width[sl], scaled_width);
+ unsigned int scaled_height = top_sl_height_ *
+ svc_params_.scaling_factor_num[sl] /
+ svc_params_.scaling_factor_den[sl];
+ if (scaled_height % 2 != 0) scaled_height += 1;
+ ASSERT_EQ(pkt->data.frame.height[sl], scaled_height);
+ } else if (superframe_count_ > 0) {
+ if (pkt->data.frame.width[sl] < prev_frame_width[sl] &&
+ pkt->data.frame.height[sl] < prev_frame_height[sl])
+ num_resize_down_ += 1;
+ if (pkt->data.frame.width[sl] > prev_frame_width[sl] &&
+ pkt->data.frame.height[sl] > prev_frame_height[sl])
+ num_resize_up_ += 1;
+ }
+ prev_frame_width[sl] = pkt->data.frame.width[sl];
+ prev_frame_height[sl] = pkt->data.frame.height[sl];
+ }
+ }
+
+ virtual void EndPassHook() {
+ if (change_bitrate_) last_pts_ = last_pts_ - last_pts_ref_;
+ duration_ = (last_pts_ + 1) * timebase_;
+ for (int sl = 0; sl < number_spatial_layers_; ++sl) {
+ for (int tl = 0; tl < number_temporal_layers_; ++tl) {
+ const int layer = sl * number_temporal_layers_ + tl;
+ const double file_size_in_kb = bits_total_[layer] / 1000.;
+ file_datarate_[layer] = file_size_in_kb / duration_;
+ }
+ }
+ }
+
+ virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
+ // TODO(marpan): Look into why an assert is triggered in compute_psnr
+ // for mismatch frames for the special test case: ksvc_flex_noupd_tlenh.
+ // Has to do with dropped frames in bypass/flexible svc mode.
+ if (!ksvc_flex_noupd_tlenh_) {
+ double mismatch_psnr = compute_psnr(img1, img2);
+ mismatch_psnr_ += mismatch_psnr;
+ ++mismatch_nframes_;
+ }
+ }
+
+ unsigned int GetMismatchFrames() { return mismatch_nframes_; }
+ unsigned int GetNonRefFrames() { return num_nonref_frames_; }
+
+ vpx_codec_pts_t last_pts_;
+ double timebase_;
+ int64_t bits_total_[VPX_MAX_LAYERS];
+ double duration_;
+ double file_datarate_[VPX_MAX_LAYERS];
+ size_t bits_in_last_frame_;
+ double mismatch_psnr_;
+ int denoiser_on_;
+ int tune_content_;
+ int spatial_layer_id_;
+ bool dynamic_drop_layer_;
+ bool single_layer_resize_;
+ unsigned int top_sl_width_;
+ unsigned int top_sl_height_;
+ vpx_svc_ref_frame_config_t ref_frame_config_;
+ int update_pattern_;
+ bool change_bitrate_;
+ vpx_codec_pts_t last_pts_ref_;
+ int middle_bitrate_;
+ int top_bitrate_;
+ int key_frame_spacing_;
+ int layer_framedrop_;
+ int force_key_;
+ int force_key_test_;
+ int inter_layer_pred_mode_;
+ int insert_layer_sync_;
+ int layer_sync_on_base_;
+ int force_intra_only_frame_;
+ int superframe_has_intra_only_;
+ int use_post_encode_drop_;
+ int bitrate_sl3_[3];
+ // Denoiser switched on the fly.
+ bool denoiser_off_on_;
+ // Top layer enabled on the fly.
+ bool denoiser_enable_layers_;
+ int num_resize_up_;
+ int num_resize_down_;
+ unsigned int prev_frame_width[VPX_MAX_LAYERS];
+ unsigned int prev_frame_height[VPX_MAX_LAYERS];
+ bool ksvc_flex_noupd_tlenh_;
+
+ private:
+ virtual void SetConfig(const int num_temporal_layer) {
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ if (num_temporal_layer == 3) {
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.temporal_layering_mode = 3;
+ } else if (num_temporal_layer == 2) {
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+ cfg_.temporal_layering_mode = 2;
+ } else if (num_temporal_layer == 1) {
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.temporal_layering_mode = 0;
+ }
+ }
+
+ unsigned int num_nonref_frames_;
+ unsigned int mismatch_nframes_;
+};
+
+// Params: speed setting.
+class DatarateOnePassCbrSvcSingleBR
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ DatarateOnePassCbrSvcSingleBR() : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcSingleBR() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
+// temporal layers, for 4:4:4 Profile 1.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TL444Profile1) {
+ SetSvcConfig(3, 3);
+ ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
+ cfg_.g_profile = 1;
+ cfg_.g_bit_depth = VPX_BITS_8;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.kf_max_dist = 9999;
+
+ top_sl_width_ = 352;
+ top_sl_height_ = 288;
+ cfg_.rc_target_bitrate = 500;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
+// temporal layers, for 4:2:2 Profile 1.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL3TL422Profile1) {
+ SetSvcConfig(2, 3);
+ ::libvpx_test::Y4mVideoSource video("park_joy_90p_8_422.y4m", 0, 20);
+ cfg_.g_profile = 1;
+ cfg_.g_bit_depth = VPX_BITS_8;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.kf_max_dist = 9999;
+
+ top_sl_width_ = 160;
+ top_sl_height_ = 90;
+ cfg_.rc_target_bitrate = 500;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Use large under/over shoot thresholds as this is a very short clip,
+ // so not good for testing rate-targeting.
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.5,
+ 1.7);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
+// temporal layers, for Profle 2 10bit.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TL10bitProfile2) {
+ SetSvcConfig(3, 3);
+ ::libvpx_test::Y4mVideoSource video("park_joy_90p_10_420_20f.y4m", 0, 20);
+ cfg_.g_profile = 2;
+ cfg_.g_bit_depth = VPX_BITS_10;
+ cfg_.g_input_bit_depth = VPX_BITS_10;
+ if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.kf_max_dist = 9999;
+
+ top_sl_width_ = 160;
+ top_sl_height_ = 90;
+ cfg_.rc_target_bitrate = 500;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // TODO(marpan/jianj): Comment out the rate-target checking for now
+ // as superframe parsing to get frame size needs to be fixed for
+ // high bitdepth.
+ /*
+ // Use large under/over shoot thresholds as this is a very short clip,
+ // so not good for testing rate-targeting.
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.5,
+ 1.7);
+ */
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
+// temporal layers, for Profle 2 12bit.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TL12bitProfile2) {
+ SetSvcConfig(3, 3);
+ ::libvpx_test::Y4mVideoSource video("park_joy_90p_12_420_20f.y4m", 0, 20);
+ cfg_.g_profile = 2;
+ cfg_.g_bit_depth = VPX_BITS_12;
+ cfg_.g_input_bit_depth = VPX_BITS_12;
+ if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.kf_max_dist = 9999;
+
+ top_sl_width_ = 160;
+ top_sl_height_ = 90;
+ cfg_.rc_target_bitrate = 500;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // TODO(marpan/jianj): Comment out the rate-target checking for now
+ // as superframe parsing to get frame size needs to be fixed for
+ // high bitdepth.
+ /*
+ // Use large under/over shoot thresholds as this is a very short clip,
+ // so not good for testing rate-targeting.
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.5,
+ 1.7);
+ */
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+#endif
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 1
+// temporal layer, with screen content mode on and same speed setting for all
+// layers.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL1TLScreenContent1) {
+ SetSvcConfig(2, 1);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.kf_max_dist = 9999;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ cfg_.rc_target_bitrate = 500;
+ ResetModel();
+ tune_content_ = 1;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers, with force key frame after frame drop
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TLForceKey) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ cfg_.rc_target_bitrate = 100;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.25);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
+// 2 temporal layers, with a change on the fly from the fixed SVC pattern to one
+// generate via SVC_SET_REF_FRAME_CONFIG. The new pattern also disables
+// inter-layer prediction.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL2TLDynamicPatternChange) {
+ SetSvcConfig(3, 2);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ cfg_.rc_target_bitrate = 800;
+ ResetModel();
+ // Change SVC pattern on the fly.
+ update_pattern_ = 1;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC with 3 spatial and 3 temporal
+// layers, for inter_layer_pred=OffKey (K-SVC) and on the fly switching
+// of denoiser from off to on (on at frame = 100). Key frame period is set to
+// 1000 so denoise is enabled on non-key.
+TEST_P(DatarateOnePassCbrSvcSingleBR,
+ OnePassCbrSvc3SL3TL_DenoiserOffOnFixedLayers) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 1000;
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280,
+ 720, 30, 1, 0, 300);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ cfg_.rc_target_bitrate = 1000;
+ ResetModel();
+ denoiser_off_on_ = true;
+ denoiser_enable_layers_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Don't check rate targeting on two top spatial layer since they will be
+ // skipped for part of the sequence.
+ CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_,
+ 0.78, 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC with 3 spatial and 3 temporal
+// layers, for inter_layer_pred=OffKey (K-SVC) and on the fly switching
+// of denoiser from off to on, for dynamic layers. Start at 2 spatial layers
+// and enable 3rd spatial layer at frame = 100. Use periodic key frame with
+// period 100 so enabling of spatial layer occurs at key frame. Enable denoiser
+// at frame > 100, after the key frame sync.
+TEST_P(DatarateOnePassCbrSvcSingleBR,
+ OnePassCbrSvc3SL3TL_DenoiserOffOnEnableLayers) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.kf_max_dist = 100;
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280,
+ 720, 30, 1, 0, 300);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ cfg_.rc_target_bitrate = 1000;
+ ResetModel();
+ denoiser_off_on_ = true;
+ denoiser_enable_layers_ = true;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Don't check rate targeting on two top spatial layer since they will be
+ // skipped for part of the sequence.
+ CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_,
+ 0.78, 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC with 3 spatial layers and on
+// the fly switching to 1 and then 2 and back to 3 spatial layers. This switch
+// is done by setting spatial layer bitrates to 0, and then back to non-zero,
+// during the sequence.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL_DisableEnableLayers) {
+ SetSvcConfig(3, 1);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.temporal_layering_mode = 0;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ cfg_.rc_target_bitrate = 800;
+ ResetModel();
+ dynamic_drop_layer_ = true;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Don't check rate targeting on two top spatial layer since they will be
+ // skipped for part of the sequence.
+ CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_,
+ 0.78, 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC with 2 spatial layers and on
+// the fly switching to 1 spatial layer with dynamic resize enabled.
+// The resizer will resize the single layer down and back up again, as the
+// bitrate goes back up.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL_SingleLayerResize) {
+ SetSvcConfig(2, 1);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.temporal_layering_mode = 0;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_resize_allowed = 1;
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280,
+ 720, 15, 1, 0, 300);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ cfg_.rc_target_bitrate = 800;
+ ResetModel();
+ dynamic_drop_layer_ = true;
+ single_layer_resize_ = true;
+ base_speed_setting_ = speed_setting_;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Expect at least one resize down and at least one resize back up.
+ EXPECT_GE(num_resize_down_, 1);
+ EXPECT_GE(num_resize_up_, 1);
+ // Don't check rate targeting on two top spatial layer since they will be
+ // skipped for part of the sequence.
+ CheckLayerRateTargeting(number_spatial_layers_ - 2, number_temporal_layers_,
+ 0.78, 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// For pass CBR SVC with 1 spatial and 2 temporal layers with dynamic resize
+// and denoiser enabled. The resizer will resize the single layer down and back
+// up again, as the bitrate goes back up.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc1SL2TL_DenoiseResize) {
+ SetSvcConfig(1, 2);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.temporal_layering_mode = 2;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_resize_allowed = 1;
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv", 1280,
+ 720, 12, 1, 0, 300);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ cfg_.rc_target_bitrate = 800;
+ ResetModel();
+ dynamic_drop_layer_ = false;
+ single_layer_resize_ = true;
+ denoiser_on_ = 1;
+ base_speed_setting_ = speed_setting_;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Expect at least one resize down and at least one resize back up.
+ EXPECT_GE(num_resize_down_, 1);
+ EXPECT_GE(num_resize_up_, 1);
+}
+
+// Run SVC encoder for 1 temporal layer, 2 spatial layers, with spatial
+// downscale 5x5.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2SL1TL5x5MultipleRuns) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.ss_number_layers = 2;
+ cfg_.ts_number_layers = 1;
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.g_error_resilient = 1;
+ cfg_.g_threads = 3;
+ cfg_.temporal_layering_mode = 0;
+ svc_params_.scaling_factor_num[0] = 256;
+ svc_params_.scaling_factor_den[0] = 1280;
+ svc_params_.scaling_factor_num[1] = 1280;
+ svc_params_.scaling_factor_den[1] = 1280;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.kf_max_dist = 999999;
+ cfg_.kf_min_dist = 0;
+ cfg_.ss_target_bitrate[0] = 300;
+ cfg_.ss_target_bitrate[1] = 1400;
+ cfg_.layer_target_bitrate[0] = 300;
+ cfg_.layer_target_bitrate[1] = 1400;
+ cfg_.rc_target_bitrate = 1700;
+ number_spatial_layers_ = cfg_.ss_number_layers;
+ number_temporal_layers_ = cfg_.ts_number_layers;
+ ResetModel();
+ layer_target_avg_bandwidth_[0] = cfg_.layer_target_bitrate[0] * 1000 / 30;
+ bits_in_buffer_model_[0] =
+ cfg_.layer_target_bitrate[0] * cfg_.rc_buf_initial_sz;
+ layer_target_avg_bandwidth_[1] = cfg_.layer_target_bitrate[1] * 1000 / 30;
+ bits_in_buffer_model_[1] =
+ cfg_.layer_target_bitrate[1] * cfg_.rc_buf_initial_sz;
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Params: speed setting and index for bitrate array.
+class DatarateOnePassCbrSvcMultiBR
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ public:
+ DatarateOnePassCbrSvcMultiBR() : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcMultiBR() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
+// 3 temporal layers. Run CIF clip with 1 thread.
+TEST_P(DatarateOnePassCbrSvcMultiBR, OnePassCbrSvc2SL3TL) {
+ SetSvcConfig(2, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ const int bitrates[3] = { 200, 400, 600 };
+ // TODO(marpan): Check that effective_datarate for each layer hits the
+ // layer target_bitrate.
+ cfg_.rc_target_bitrate = bitrates[GET_PARAM(2)];
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.75,
+ 1.2);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass VBR SVC: 2 spatial layers and
+// 3 temporal layers. Run VGA clip with 1 thread.
+TEST_P(DatarateOnePassCbrSvcMultiBR, OnePassVbrSvc2SL3TL) {
+ SetSvcConfig(2, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_end_usage = VPX_VBR;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ const int bitrates[3] = { 200, 400, 600 };
+ cfg_.rc_target_bitrate = bitrates[GET_PARAM(2)];
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.70,
+ 1.3);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Params: speed setting, layer framedrop control and index for bitrate array.
+class DatarateOnePassCbrSvcFrameDropMultiBR
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWith3Params<int, int, int> {
+ public:
+ DatarateOnePassCbrSvcFrameDropMultiBR()
+ : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcFrameDropMultiBR() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
+// 3 temporal layers. Run HD clip with 4 threads.
+TEST_P(DatarateOnePassCbrSvcFrameDropMultiBR, OnePassCbrSvc2SL3TL4Threads) {
+ SetSvcConfig(2, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 4;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ layer_framedrop_ = 0;
+ const int bitrates[3] = { 200, 400, 600 };
+ cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)];
+ ResetModel();
+ layer_framedrop_ = GET_PARAM(2);
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.64,
+ 1.45);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers. Run HD clip with 4 threads.
+TEST_P(DatarateOnePassCbrSvcFrameDropMultiBR, OnePassCbrSvc3SL3TL4Threads) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 4;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ layer_framedrop_ = 0;
+ const int bitrates[3] = { 200, 400, 600 };
+ cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)];
+ ResetModel();
+ layer_framedrop_ = GET_PARAM(2);
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.58,
+ 1.2);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
+// 2 temporal layers, for KSVC in flexible mode with no update of reference
+// frames for all spatial layers on TL > 0 superframes.
+// Run HD clip with 4 threads.
+TEST_P(DatarateOnePassCbrSvcFrameDropMultiBR, OnePassCbrSvc3SL2TL4ThKSVCFlex) {
+ SetSvcConfig(3, 2);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 4;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ top_sl_width_ = 1280;
+ top_sl_height_ = 720;
+ layer_framedrop_ = 0;
+ const int bitrates[3] = { 200, 400, 600 };
+ cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)];
+ ResetModel();
+ layer_framedrop_ = GET_PARAM(2);
+ AssignLayerBitrates();
+ ksvc_flex_noupd_tlenh_ = true;
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.58,
+ 1.2);
+}
+
+// Params: speed setting, inter-layer prediction mode.
+class DatarateOnePassCbrSvcInterLayerPredSingleBR
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ public:
+ DatarateOnePassCbrSvcInterLayerPredSingleBR()
+ : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcInterLayerPredSingleBR() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ inter_layer_pred_mode_ = GET_PARAM(2);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting with different inter-layer prediction modes for 1
+// pass CBR SVC: 3 spatial layers and 3 temporal layers. Run CIF clip with 1
+// thread.
+TEST_P(DatarateOnePassCbrSvcInterLayerPredSingleBR, OnePassCbrSvc3SL3TL) {
+ // Disable test for inter-layer pred off for now since simulcast_mode fails.
+ if (inter_layer_pred_mode_ == INTER_LAYER_PRED_OFF) return;
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.temporal_layering_mode = 3;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ cfg_.rc_target_bitrate = 800;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check rate targeting with different inter-layer prediction modes for 1 pass
+// CBR SVC: 3 spatial layers and 3 temporal layers, changing the target bitrate
+// at the middle of encoding.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TLDynamicBitrateChange) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ cfg_.rc_target_bitrate = 800;
+ ResetModel();
+ change_bitrate_ = true;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+#if CONFIG_VP9_TEMPORAL_DENOISING
+// Params: speed setting, noise sensitivity, index for bitrate array and inter
+// layer pred mode.
+class DatarateOnePassCbrSvcDenoiser
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWith4Params<int, int, int, int> {
+ public:
+ DatarateOnePassCbrSvcDenoiser() : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcDenoiser() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ inter_layer_pred_mode_ = GET_PARAM(3);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for 1 pass CBR SVC with denoising.
+// 2 spatial layers and 3 temporal layer. Run HD clip with 2 threads.
+TEST_P(DatarateOnePassCbrSvcDenoiser, OnePassCbrSvc2SL3TLDenoiserOn) {
+ SetSvcConfig(2, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 2;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ number_spatial_layers_ = cfg_.ss_number_layers;
+ number_temporal_layers_ = cfg_.ts_number_layers;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ const int bitrates[3] = { 600, 800, 1000 };
+ // TODO(marpan): Check that effective_datarate for each layer hits the
+ // layer target_bitrate.
+ // For SVC, noise_sen = 1 means denoising only the top spatial layer
+ // noise_sen = 2 means denoising the two top spatial layers.
+ cfg_.rc_target_bitrate = bitrates[GET_PARAM(3)];
+ ResetModel();
+ denoiser_on_ = GET_PARAM(2);
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+#endif
+
+// Params: speed setting, key frame dist.
+class DatarateOnePassCbrSvcSmallKF
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ public:
+ DatarateOnePassCbrSvcSmallKF() : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcSmallKF() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
+// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
+TEST_P(DatarateOnePassCbrSvcSmallKF, OnePassCbrSvc3SL3TLSmallKf) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_target_bitrate = 800;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
+ // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
+ const int kf_dist = GET_PARAM(2);
+ cfg_.kf_max_dist = kf_dist;
+ key_frame_spacing_ = kf_dist;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.70,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
+// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
+TEST_P(DatarateOnePassCbrSvcSmallKF, OnePassCbrSvc2SL3TLSmallKf) {
+ SetSvcConfig(2, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_target_bitrate = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
+ // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
+ const int kf_dist = GET_PARAM(2) + 32;
+ cfg_.kf_max_dist = kf_dist;
+ key_frame_spacing_ = kf_dist;
+ ResetModel();
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
+// temporal layers. Run VGA clip with 1 thread, and place layer sync frames:
+// one at middle layer first, then another one for top layer, and another
+// insert for base spatial layer (which forces key frame).
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL3TLSyncFrames) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_target_bitrate = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ ResetModel();
+ insert_layer_sync_ = 1;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.78,
+ 1.15);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Run SVC encoder for 3 spatial layers, 1 temporal layer, with
+// intra-only frame as sync frame on base spatial layer.
+// Intra_only is inserted at start and in middle of sequence.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc3SL1TLSyncWithIntraOnly) {
+ SetSvcConfig(3, 1);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 4;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_target_bitrate = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ ResetModel();
+ insert_layer_sync_ = 1;
+ // Use intra_only frame for sync on base layer.
+ force_intra_only_frame_ = 1;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.73,
+ 1.2);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Run SVC encoder for 2 quality layers (same resolution different,
+// bitrates), 1 temporal layer, with screen content mode.
+TEST_P(DatarateOnePassCbrSvcSingleBR, OnePassCbrSvc2QL1TLScreen) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.ss_number_layers = 2;
+ cfg_.ts_number_layers = 1;
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.temporal_layering_mode = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.g_threads = 2;
+ svc_params_.scaling_factor_num[0] = 1;
+ svc_params_.scaling_factor_den[0] = 1;
+ svc_params_.scaling_factor_num[1] = 1;
+ svc_params_.scaling_factor_den[1] = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ number_spatial_layers_ = cfg_.ss_number_layers;
+ number_temporal_layers_ = cfg_.ts_number_layers;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ top_sl_width_ = 640;
+ top_sl_height_ = 480;
+ ResetModel();
+ tune_content_ = 1;
+ // Set the layer bitrates, for 2 spatial layers, 1 temporal.
+ cfg_.rc_target_bitrate = 400;
+ cfg_.ss_target_bitrate[0] = 100;
+ cfg_.ss_target_bitrate[1] = 300;
+ cfg_.layer_target_bitrate[0] = 100;
+ cfg_.layer_target_bitrate[1] = 300;
+ for (int sl = 0; sl < 2; ++sl) {
+ float layer_framerate = 30.0;
+ layer_target_avg_bandwidth_[sl] = static_cast<int>(
+ cfg_.layer_target_bitrate[sl] * 1000.0 / layer_framerate);
+ bits_in_buffer_model_[sl] =
+ cfg_.layer_target_bitrate[sl] * cfg_.rc_buf_initial_sz;
+ }
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.73,
+ 1.25);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Params: speed setting.
+class DatarateOnePassCbrSvcPostencodeDrop
+ : public DatarateOnePassCbrSvc,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ DatarateOnePassCbrSvcPostencodeDrop() : DatarateOnePassCbrSvc(GET_PARAM(0)) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ }
+ virtual ~DatarateOnePassCbrSvcPostencodeDrop() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ speed_setting_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Run SVC encoder for 2 quality layers (same resolution different,
+// bitrates), 1 temporal layer, with screen content mode.
+TEST_P(DatarateOnePassCbrSvcPostencodeDrop, OnePassCbrSvc2QL1TLScreen) {
+ cfg_.rc_buf_initial_sz = 200;
+ cfg_.rc_buf_optimal_sz = 200;
+ cfg_.rc_buf_sz = 400;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 52;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.ss_number_layers = 2;
+ cfg_.ts_number_layers = 1;
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.temporal_layering_mode = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.g_threads = 2;
+ svc_params_.scaling_factor_num[0] = 1;
+ svc_params_.scaling_factor_den[0] = 1;
+ svc_params_.scaling_factor_num[1] = 1;
+ svc_params_.scaling_factor_den[1] = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ number_spatial_layers_ = cfg_.ss_number_layers;
+ number_temporal_layers_ = cfg_.ts_number_layers;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+ top_sl_width_ = 352;
+ top_sl_height_ = 288;
+ ResetModel();
+ base_speed_setting_ = speed_setting_;
+ tune_content_ = 1;
+ use_post_encode_drop_ = 1;
+ // Set the layer bitrates, for 2 spatial layers, 1 temporal.
+ cfg_.rc_target_bitrate = 400;
+ cfg_.ss_target_bitrate[0] = 100;
+ cfg_.ss_target_bitrate[1] = 300;
+ cfg_.layer_target_bitrate[0] = 100;
+ cfg_.layer_target_bitrate[1] = 300;
+ for (int sl = 0; sl < 2; ++sl) {
+ float layer_framerate = 30.0;
+ layer_target_avg_bandwidth_[sl] = static_cast<int>(
+ cfg_.layer_target_bitrate[sl] * 1000.0 / layer_framerate);
+ bits_in_buffer_model_[sl] =
+ cfg_.layer_target_bitrate[sl] * cfg_.rc_buf_initial_sz;
+ }
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ CheckLayerRateTargeting(number_spatial_layers_, number_temporal_layers_, 0.73,
+ 1.25);
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcSingleBR,
+ ::testing::Range(5, 10));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcPostencodeDrop,
+ ::testing::Range(5, 6));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcInterLayerPredSingleBR,
+ ::testing::Range(5, 10), ::testing::Range(0, 3));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcMultiBR,
+ ::testing::Range(5, 10), ::testing::Range(0, 3));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcFrameDropMultiBR,
+ ::testing::Range(5, 10), ::testing::Range(0, 2),
+ ::testing::Range(0, 3));
+
+#if CONFIG_VP9_TEMPORAL_DENOISING
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcDenoiser,
+ ::testing::Range(5, 10), ::testing::Range(1, 3),
+ ::testing::Range(0, 3), ::testing::Range(0, 4));
+#endif
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateOnePassCbrSvcSmallKF,
+ ::testing::Range(5, 10), ::testing::Range(32, 36));
+} // namespace
+} // namespace svc_test
diff --git a/media/libvpx/libvpx/test/svc_end_to_end_test.cc b/media/libvpx/libvpx/test/svc_end_to_end_test.cc
new file mode 100644
index 0000000000..7300ce6679
--- /dev/null
+++ b/media/libvpx/libvpx/test/svc_end_to_end_test.cc
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 2018 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 "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/svc_test.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vp9/common/vp9_onyxc_int.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/bitops.h"
+
+namespace svc_test {
+namespace {
+
+typedef enum {
+ // Inter-layer prediction is on on all frames.
+ INTER_LAYER_PRED_ON,
+ // Inter-layer prediction is off on all frames.
+ INTER_LAYER_PRED_OFF,
+ // Inter-layer prediction is off on non-key frames and non-sync frames.
+ INTER_LAYER_PRED_OFF_NONKEY,
+ // Inter-layer prediction is on on all frames, but constrained such
+ // that any layer S (> 0) can only predict from previous spatial
+ // layer S-1, from the same superframe.
+ INTER_LAYER_PRED_ON_CONSTRAINED
+} INTER_LAYER_PRED;
+
+class ScalePartitionOnePassCbrSvc
+ : public OnePassCbrSvc,
+ public ::testing::TestWithParam<const ::libvpx_test::CodecFactory *> {
+ public:
+ ScalePartitionOnePassCbrSvc()
+ : OnePassCbrSvc(GetParam()), mismatch_nframes_(0), num_nonref_frames_(0) {
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ protected:
+ virtual ~ScalePartitionOnePassCbrSvc() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ speed_setting_ = 7;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ PreEncodeFrameHookSetup(video, encoder);
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ // Keep track of number of non-reference frames, needed for mismatch check.
+ // Non-reference frames are top spatial and temporal layer frames,
+ // for TL > 0.
+ if (temporal_layer_id_ == number_temporal_layers_ - 1 &&
+ temporal_layer_id_ > 0 &&
+ pkt->data.frame.spatial_layer_encoded[number_spatial_layers_ - 1])
+ num_nonref_frames_++;
+ }
+
+ virtual void MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {
+ ++mismatch_nframes_;
+ }
+
+ virtual void SetConfig(const int /*num_temporal_layer*/) {}
+
+ unsigned int GetMismatchFrames() const { return mismatch_nframes_; }
+ unsigned int GetNonRefFrames() const { return num_nonref_frames_; }
+
+ private:
+ unsigned int mismatch_nframes_;
+ unsigned int num_nonref_frames_;
+};
+
+TEST_P(ScalePartitionOnePassCbrSvc, OnePassCbrSvc3SL3TL1080P) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_target_bitrate = 800;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.temporal_layering_mode = 3;
+ ::libvpx_test::I420VideoSource video(
+ "slides_code_term_web_plot.1920_1080.yuv", 1920, 1080, 30, 1, 0, 100);
+ // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
+ // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Params: Inter layer prediction modes.
+class SyncFrameOnePassCbrSvc : public OnePassCbrSvc,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ SyncFrameOnePassCbrSvc()
+ : OnePassCbrSvc(GET_PARAM(0)), current_video_frame_(0),
+ frame_to_start_decode_(0), frame_to_sync_(0),
+ inter_layer_pred_mode_(GET_PARAM(1)), decode_to_layer_before_sync_(-1),
+ decode_to_layer_after_sync_(-1), denoiser_on_(0),
+ intra_only_test_(false), loopfilter_off_(0), mismatch_nframes_(0),
+ num_nonref_frames_(0) {
+ SetMode(::libvpx_test::kRealTime);
+ memset(&svc_layer_sync_, 0, sizeof(svc_layer_sync_));
+ }
+
+ protected:
+ virtual ~SyncFrameOnePassCbrSvc() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ speed_setting_ = 7;
+ }
+
+ virtual bool DoDecode() const {
+ return current_video_frame_ >= frame_to_start_decode_;
+ }
+
+ // Example pattern for spatial layers and 2 temporal layers used in the
+ // bypass/flexible mode. The pattern corresponds to the pattern
+ // VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
+ // non-flexible mode.
+ void set_frame_flags_bypass_mode(
+ int tl, int num_spatial_layers, int is_key_frame,
+ vpx_svc_ref_frame_config_t *ref_frame_config) {
+ int sl;
+ for (sl = 0; sl < num_spatial_layers; ++sl)
+ ref_frame_config->update_buffer_slot[sl] = 0;
+
+ for (sl = 0; sl < num_spatial_layers; ++sl) {
+ // Set the buffer idx.
+ if (tl == 0) {
+ ref_frame_config->lst_fb_idx[sl] = sl;
+ if (sl) {
+ if (is_key_frame) {
+ ref_frame_config->lst_fb_idx[sl] = sl - 1;
+ ref_frame_config->gld_fb_idx[sl] = sl;
+ } else {
+ ref_frame_config->gld_fb_idx[sl] = sl - 1;
+ }
+ } else {
+ ref_frame_config->gld_fb_idx[sl] = 0;
+ }
+ ref_frame_config->alt_fb_idx[sl] = 0;
+ } else if (tl == 1) {
+ ref_frame_config->lst_fb_idx[sl] = sl;
+ ref_frame_config->gld_fb_idx[sl] =
+ (sl == 0) ? 0 : num_spatial_layers + sl - 1;
+ ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
+ }
+ // Set the reference and update flags.
+ if (!tl) {
+ if (!sl) {
+ // Base spatial and base temporal (sl = 0, tl = 0)
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->lst_fb_idx[sl];
+ } else {
+ if (is_key_frame) {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->gld_fb_idx[sl];
+ } else {
+ // Non-zero spatiall layer.
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 1;
+ ref_frame_config->reference_alt_ref[sl] = 1;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->lst_fb_idx[sl];
+ }
+ }
+ } else if (tl == 1) {
+ if (!sl) {
+ // Base spatial and top temporal (tl = 1)
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 0;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->alt_fb_idx[sl];
+ } else {
+ // Non-zero spatial.
+ if (sl < num_spatial_layers - 1) {
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 1;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ ref_frame_config->update_buffer_slot[sl] |=
+ 1 << ref_frame_config->alt_fb_idx[sl];
+ } else if (sl == num_spatial_layers - 1) {
+ // Top spatial and top temporal (non-reference -- doesn't
+ // update any reference buffers).
+ ref_frame_config->reference_last[sl] = 1;
+ ref_frame_config->reference_golden[sl] = 1;
+ ref_frame_config->reference_alt_ref[sl] = 0;
+ }
+ }
+ }
+ }
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ current_video_frame_ = video->frame();
+ PreEncodeFrameHookSetup(video, encoder);
+ if (video->frame() == 0) {
+ // Do not turn off inter-layer pred completely because simulcast mode
+ // fails.
+ if (inter_layer_pred_mode_ != INTER_LAYER_PRED_OFF)
+ encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED, inter_layer_pred_mode_);
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
+ if (intra_only_test_)
+ // Decoder sets the color_space for Intra-only frames
+ // to BT_601 (see line 1810 in vp9_decodeframe.c).
+ // So set it here in these tess to avoid encoder-decoder
+ // mismatch check on color space setting.
+ encoder->Control(VP9E_SET_COLOR_SPACE, VPX_CS_BT_601);
+
+ encoder->Control(VP9E_SET_DISABLE_LOOPFILTER, loopfilter_off_);
+ }
+ if (flexible_mode_) {
+ vpx_svc_layer_id_t layer_id;
+ layer_id.spatial_layer_id = 0;
+ layer_id.temporal_layer_id = (video->frame() % 2 != 0);
+ temporal_layer_id_ = layer_id.temporal_layer_id;
+ for (int i = 0; i < number_spatial_layers_; i++) {
+ layer_id.temporal_layer_id_per_spatial[i] = temporal_layer_id_;
+ ref_frame_config_.duration[i] = 1;
+ }
+ encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
+ set_frame_flags_bypass_mode(layer_id.temporal_layer_id,
+ number_spatial_layers_, 0,
+ &ref_frame_config_);
+ encoder->Control(VP9E_SET_SVC_REF_FRAME_CONFIG, &ref_frame_config_);
+ }
+ if (video->frame() == frame_to_sync_) {
+ encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync_);
+ }
+ }
+
+#if CONFIG_VP9_DECODER
+ virtual void PreDecodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Decoder *decoder) {
+ if (video->frame() < frame_to_sync_) {
+ if (decode_to_layer_before_sync_ >= 0)
+ decoder->Control(VP9_DECODE_SVC_SPATIAL_LAYER,
+ decode_to_layer_before_sync_);
+ } else {
+ if (decode_to_layer_after_sync_ >= 0) {
+ int decode_to_layer = decode_to_layer_after_sync_;
+ // Overlay frame is additional layer for intra-only.
+ if (video->frame() == frame_to_sync_ && intra_only_test_ &&
+ decode_to_layer_after_sync_ == 0 && number_spatial_layers_ > 1)
+ decode_to_layer += 1;
+ decoder->Control(VP9_DECODE_SVC_SPATIAL_LAYER, decode_to_layer);
+ }
+ }
+ }
+#endif
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ // Keep track of number of non-reference frames, needed for mismatch check.
+ // Non-reference frames are top spatial and temporal layer frames,
+ // for TL > 0.
+ if (temporal_layer_id_ == number_temporal_layers_ - 1 &&
+ temporal_layer_id_ > 0 &&
+ pkt->data.frame.spatial_layer_encoded[number_spatial_layers_ - 1] &&
+ current_video_frame_ >= frame_to_sync_)
+ num_nonref_frames_++;
+
+ if (intra_only_test_ && current_video_frame_ == frame_to_sync_) {
+ // Intra-only frame is only generated for spatial layers > 1 and <= 3,
+ // among other conditions (see constraint in set_intra_only_frame(). If
+ // intra-only is no allowed then encoder will insert key frame instead.
+ const bool key_frame =
+ (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
+ if (number_spatial_layers_ == 1 || number_spatial_layers_ > 3)
+ ASSERT_TRUE(key_frame);
+ else
+ ASSERT_FALSE(key_frame);
+ }
+ }
+
+ virtual void MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {
+ if (current_video_frame_ >= frame_to_sync_) ++mismatch_nframes_;
+ }
+
+ unsigned int GetMismatchFrames() const { return mismatch_nframes_; }
+ unsigned int GetNonRefFrames() const { return num_nonref_frames_; }
+
+ unsigned int current_video_frame_;
+ unsigned int frame_to_start_decode_;
+ unsigned int frame_to_sync_;
+ int inter_layer_pred_mode_;
+ int decode_to_layer_before_sync_;
+ int decode_to_layer_after_sync_;
+ int denoiser_on_;
+ bool intra_only_test_;
+ int loopfilter_off_;
+ vpx_svc_spatial_layer_sync_t svc_layer_sync_;
+ unsigned int mismatch_nframes_;
+ unsigned int num_nonref_frames_;
+ bool flexible_mode_;
+ vpx_svc_ref_frame_config_t ref_frame_config_;
+
+ private:
+ virtual void SetConfig(const int num_temporal_layer) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.kf_max_dist = 9999;
+ if (num_temporal_layer == 3) {
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.temporal_layering_mode = 3;
+ } else if (num_temporal_layer == 2) {
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+ cfg_.temporal_layering_mode = 2;
+ } else if (num_temporal_layer == 1) {
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.temporal_layering_mode = 0;
+ }
+ }
+};
+
+// Test for sync layer for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers. Only start decoding on the sync layer.
+// Full sync: insert key frame on base layer.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc3SL3TLFullSync) {
+ SetSvcConfig(3, 3);
+ // Sync is on base layer so the frame to sync and the frame to start decoding
+ // is the same.
+ frame_to_start_decode_ = 20;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = -1;
+ decode_to_layer_after_sync_ = 2;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 0;
+ svc_layer_sync_.spatial_layer_sync[0] = 1;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Test for sync layer for 1 pass CBR SVC: 2 spatial layers and
+// 3 temporal layers. Decoding QVGA before sync frame and decode up to
+// VGA on and after sync.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc2SL3TLSyncToVGA) {
+ SetSvcConfig(2, 3);
+ frame_to_start_decode_ = 0;
+ frame_to_sync_ = 100;
+ decode_to_layer_before_sync_ = 0;
+ decode_to_layer_after_sync_ = 1;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 0;
+ svc_layer_sync_.spatial_layer_sync[0] = 0;
+ svc_layer_sync_.spatial_layer_sync[1] = 1;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 400;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Test for sync layer for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers. Decoding QVGA and VGA before sync frame and decode up to
+// HD on and after sync.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc3SL3TLSyncToHD) {
+ SetSvcConfig(3, 3);
+ frame_to_start_decode_ = 0;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 1;
+ decode_to_layer_after_sync_ = 2;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 0;
+ svc_layer_sync_.spatial_layer_sync[0] = 0;
+ svc_layer_sync_.spatial_layer_sync[1] = 0;
+ svc_layer_sync_.spatial_layer_sync[2] = 1;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Test for sync layer for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers. Decoding QVGA before sync frame and decode up to
+// HD on and after sync.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc3SL3TLSyncToVGAHD) {
+ SetSvcConfig(3, 3);
+ frame_to_start_decode_ = 0;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 0;
+ decode_to_layer_after_sync_ = 2;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 0;
+ svc_layer_sync_.spatial_layer_sync[0] = 0;
+ svc_layer_sync_.spatial_layer_sync[1] = 1;
+ svc_layer_sync_.spatial_layer_sync[2] = 1;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+#if CONFIG_VP9_TEMPORAL_DENOISING
+// Test for sync layer for 1 pass CBR SVC: 2 spatial layers and
+// 3 temporal layers. Decoding QVGA before sync frame and decode up to
+// VGA on and after sync.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc2SL3TLSyncFrameVGADenoise) {
+ SetSvcConfig(2, 3);
+ frame_to_start_decode_ = 0;
+ frame_to_sync_ = 100;
+ decode_to_layer_before_sync_ = 0;
+ decode_to_layer_after_sync_ = 1;
+
+ denoiser_on_ = 1;
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 0;
+ svc_layer_sync_.spatial_layer_sync[0] = 0;
+ svc_layer_sync_.spatial_layer_sync[1] = 1;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 400;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+#endif
+
+// Encode 3 spatial, 2 temporal layer in flexible mode but don't
+// start decoding. During the sequence insert intra-only on base/qvga
+// layer at frame 20 and start decoding only QVGA layer from there.
+TEST_P(SyncFrameOnePassCbrSvc,
+ OnePassCbrSvc3SL3TLSyncFrameStartDecodeOnIntraOnlyQVGAFlex) {
+ SetSvcConfig(3, 2);
+ frame_to_start_decode_ = 20;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 2;
+ decode_to_layer_after_sync_ = 0;
+ intra_only_test_ = true;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 1;
+ svc_layer_sync_.spatial_layer_sync[0] = 1;
+ svc_layer_sync_.spatial_layer_sync[1] = 0;
+ svc_layer_sync_.spatial_layer_sync[2] = 0;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = true;
+ AssignLayerBitrates();
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Can't check mismatch here because only base is decoded at
+ // frame sync, whereas encoder continues encoding all layers.
+}
+
+// Encode 3 spatial, 3 temporal layer but don't start decoding.
+// During the sequence insert intra-only on base/qvga layer at frame 20
+// and start decoding only QVGA layer from there.
+TEST_P(SyncFrameOnePassCbrSvc,
+ OnePassCbrSvc3SL3TLSyncFrameStartDecodeOnIntraOnlyQVGA) {
+ SetSvcConfig(3, 3);
+ frame_to_start_decode_ = 20;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 2;
+ decode_to_layer_after_sync_ = 0;
+ intra_only_test_ = true;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 1;
+ svc_layer_sync_.spatial_layer_sync[0] = 1;
+ svc_layer_sync_.spatial_layer_sync[1] = 0;
+ svc_layer_sync_.spatial_layer_sync[2] = 0;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ // Can't check mismatch here because only base is decoded at
+ // frame sync, whereas encoder continues encoding all layers.
+}
+
+// Start decoding from beginning of sequence, during sequence insert intra-only
+// on base/qvga layer. Decode all layers.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc3SL3TLSyncFrameIntraOnlyQVGA) {
+ SetSvcConfig(3, 3);
+ frame_to_start_decode_ = 0;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 2;
+ // The superframe containing intra-only layer will have +1 frames. Thus set
+ // the layer to decode after sync frame to +1 from
+ // decode_to_layer_before_sync.
+ decode_to_layer_after_sync_ = 3;
+ intra_only_test_ = true;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 1;
+ svc_layer_sync_.spatial_layer_sync[0] = 1;
+ svc_layer_sync_.spatial_layer_sync[1] = 0;
+ svc_layer_sync_.spatial_layer_sync[2] = 0;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Start decoding from beginning of sequence, during sequence insert intra-only
+// on base/qvga layer and sync_layer on middle/VGA layer. Decode all layers.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc3SL3TLSyncFrameIntraOnlyVGA) {
+ SetSvcConfig(3, 3);
+ frame_to_start_decode_ = 0;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 2;
+ // The superframe containing intra-only layer will have +1 frames. Thus set
+ // the layer to decode after sync frame to +1 from
+ // decode_to_layer_before_sync.
+ decode_to_layer_after_sync_ = 3;
+ intra_only_test_ = true;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 1;
+ svc_layer_sync_.spatial_layer_sync[0] = 1;
+ svc_layer_sync_.spatial_layer_sync[1] = 1;
+ svc_layer_sync_.spatial_layer_sync[2] = 0;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Start decoding from sync frame, insert intra-only on base/qvga layer. Decode
+// all layers. For 1 spatial layer, it inserts a key frame.
+TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc1SL3TLSyncFrameIntraOnlyQVGA) {
+ SetSvcConfig(1, 3);
+ frame_to_start_decode_ = 20;
+ frame_to_sync_ = 20;
+ decode_to_layer_before_sync_ = 0;
+ decode_to_layer_after_sync_ = 0;
+ intra_only_test_ = true;
+
+ // Set up svc layer sync structure.
+ svc_layer_sync_.base_layer_intra_only = 1;
+ svc_layer_sync_.spatial_layer_sync[0] = 1;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+ cfg_.rc_target_bitrate = 600;
+ flexible_mode_ = false;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ // The non-reference frames are expected to be mismatched frames as the
+ // encoder will avoid loopfilter on these frames.
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+#endif
+}
+
+// Params: Loopfilter modes.
+class LoopfilterOnePassCbrSvc : public OnePassCbrSvc,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ LoopfilterOnePassCbrSvc()
+ : OnePassCbrSvc(GET_PARAM(0)), loopfilter_off_(GET_PARAM(1)),
+ mismatch_nframes_(0), num_nonref_frames_(0) {
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ protected:
+ virtual ~LoopfilterOnePassCbrSvc() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ speed_setting_ = 7;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ PreEncodeFrameHookSetup(video, encoder);
+ if (number_temporal_layers_ > 1 || number_spatial_layers_ > 1) {
+ // Consider 3 cases:
+ if (loopfilter_off_ == 0) {
+ // loopfilter is on for all spatial layers on every superrframe.
+ for (int i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
+ svc_params_.loopfilter_ctrl[i] = 0;
+ }
+ } else if (loopfilter_off_ == 1) {
+ // loopfilter is off for non-reference frames for all spatial layers.
+ for (int i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
+ svc_params_.loopfilter_ctrl[i] = 1;
+ }
+ } else {
+ // loopfilter is off for all SL0 frames, and off only for non-reference
+ // frames for SL > 0.
+ svc_params_.loopfilter_ctrl[0] = 2;
+ for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
+ svc_params_.loopfilter_ctrl[i] = 1;
+ }
+ }
+ encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
+ } else if (number_temporal_layers_ == 1 && number_spatial_layers_ == 1) {
+ // For non-SVC mode use the single layer control.
+ encoder->Control(VP9E_SET_DISABLE_LOOPFILTER, loopfilter_off_);
+ }
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ // Keep track of number of non-reference frames, needed for mismatch check.
+ // Non-reference frames are top spatial and temporal layer frames,
+ // for TL > 0.
+ if (temporal_layer_id_ == number_temporal_layers_ - 1 &&
+ temporal_layer_id_ > 0 &&
+ pkt->data.frame.spatial_layer_encoded[number_spatial_layers_ - 1])
+ num_nonref_frames_++;
+ }
+
+ virtual void MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {
+ ++mismatch_nframes_;
+ }
+
+ virtual void SetConfig(const int /*num_temporal_layer*/) {}
+
+ int GetMismatchFrames() const { return mismatch_nframes_; }
+ int GetNonRefFrames() const { return num_nonref_frames_; }
+
+ int loopfilter_off_;
+
+ private:
+ int mismatch_nframes_;
+ int num_nonref_frames_;
+};
+
+TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL1TLLoopfilterOff) {
+ SetSvcConfig(1, 1);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_target_bitrate = 800;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.temporal_layering_mode = 0;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 600;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ if (loopfilter_off_ == 0)
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+ else
+ EXPECT_EQ(GetMismatchFrames(), 0);
+#endif
+}
+
+TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc1SL3TLLoopfilterOff) {
+ SetSvcConfig(1, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_target_bitrate = 800;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.temporal_layering_mode = 3;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 600;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ if (loopfilter_off_ == 0)
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+ else
+ EXPECT_EQ(GetMismatchFrames(), 0);
+#endif
+}
+
+TEST_P(LoopfilterOnePassCbrSvc, OnePassCbrSvc3SL3TLLoopfilterOff) {
+ SetSvcConfig(3, 3);
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_threads = 1;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_target_bitrate = 800;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.temporal_layering_mode = 3;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 600;
+ AssignLayerBitrates();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#if CONFIG_VP9_DECODER
+ if (loopfilter_off_ == 0)
+ EXPECT_EQ(GetNonRefFrames(), GetMismatchFrames());
+ else
+ EXPECT_EQ(GetMismatchFrames(), 0);
+#endif
+}
+
+VP9_INSTANTIATE_TEST_SUITE(SyncFrameOnePassCbrSvc, ::testing::Range(0, 3));
+
+VP9_INSTANTIATE_TEST_SUITE(LoopfilterOnePassCbrSvc, ::testing::Range(0, 3));
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9, ScalePartitionOnePassCbrSvc,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
+
+} // namespace
+} // namespace svc_test
diff --git a/media/libvpx/libvpx/test/svc_test.cc b/media/libvpx/libvpx/test/svc_test.cc
new file mode 100644
index 0000000000..cbc0abe032
--- /dev/null
+++ b/media/libvpx/libvpx/test/svc_test.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2018 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/svc_test.h"
+
+namespace svc_test {
+void OnePassCbrSvc::SetSvcConfig(const int num_spatial_layer,
+ const int num_temporal_layer) {
+ SetConfig(num_temporal_layer);
+ cfg_.ss_number_layers = num_spatial_layer;
+ cfg_.ts_number_layers = num_temporal_layer;
+ if (num_spatial_layer == 1) {
+ svc_params_.scaling_factor_num[0] = 288;
+ svc_params_.scaling_factor_den[0] = 288;
+ } else if (num_spatial_layer == 2) {
+ svc_params_.scaling_factor_num[0] = 144;
+ svc_params_.scaling_factor_den[0] = 288;
+ svc_params_.scaling_factor_num[1] = 288;
+ svc_params_.scaling_factor_den[1] = 288;
+ } else if (num_spatial_layer == 3) {
+ svc_params_.scaling_factor_num[0] = 72;
+ svc_params_.scaling_factor_den[0] = 288;
+ svc_params_.scaling_factor_num[1] = 144;
+ svc_params_.scaling_factor_den[1] = 288;
+ svc_params_.scaling_factor_num[2] = 288;
+ svc_params_.scaling_factor_den[2] = 288;
+ }
+ number_spatial_layers_ = cfg_.ss_number_layers;
+ number_temporal_layers_ = cfg_.ts_number_layers;
+}
+
+void OnePassCbrSvc::PreEncodeFrameHookSetup(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ for (int i = 0; i < VPX_MAX_LAYERS; ++i) {
+ svc_params_.max_quantizers[i] = 63;
+ svc_params_.min_quantizers[i] = 0;
+ }
+ if (number_temporal_layers_ > 1 || number_spatial_layers_ > 1) {
+ svc_params_.speed_per_layer[0] = base_speed_setting_;
+ for (int i = 1; i < VPX_SS_MAX_LAYERS; ++i) {
+ svc_params_.speed_per_layer[i] = speed_setting_;
+ }
+ encoder->Control(VP9E_SET_SVC, 1);
+ encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
+ }
+ encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, get_msb(cfg_.g_threads));
+ encoder->Control(VP9E_SET_ROW_MT, 1);
+ encoder->Control(VP8E_SET_STATIC_THRESHOLD, 1);
+ }
+
+ superframe_count_++;
+ temporal_layer_id_ = 0;
+ if (number_temporal_layers_ == 2) {
+ temporal_layer_id_ = (superframe_count_ % 2 != 0);
+ } else if (number_temporal_layers_ == 3) {
+ if (superframe_count_ % 2 != 0) temporal_layer_id_ = 2;
+ if (superframe_count_ > 1) {
+ if ((superframe_count_ - 2) % 4 == 0) temporal_layer_id_ = 1;
+ }
+ }
+
+ frame_flags_ = 0;
+}
+
+void OnePassCbrSvc::PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+ vpx_svc_layer_id_t layer_id;
+ encoder->Control(VP9E_GET_SVC_LAYER_ID, &layer_id);
+ temporal_layer_id_ = layer_id.temporal_layer_id;
+ for (int sl = 0; sl < number_spatial_layers_; ++sl) {
+ for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) {
+ const int layer = sl * number_temporal_layers_ + tl;
+ bits_in_buffer_model_[layer] +=
+ static_cast<int64_t>(layer_target_avg_bandwidth_[layer]);
+ }
+ }
+}
+
+void OnePassCbrSvc::AssignLayerBitrates() {
+ int sl, spatial_layer_target;
+ int spatial_layers = cfg_.ss_number_layers;
+ int temporal_layers = cfg_.ts_number_layers;
+ float total = 0;
+ float alloc_ratio[VPX_MAX_LAYERS] = { 0 };
+ float framerate = 30.0;
+ for (sl = 0; sl < spatial_layers; ++sl) {
+ if (svc_params_.scaling_factor_den[sl] > 0) {
+ alloc_ratio[sl] =
+ static_cast<float>((svc_params_.scaling_factor_num[sl] * 1.0 /
+ svc_params_.scaling_factor_den[sl]));
+ total += alloc_ratio[sl];
+ }
+ }
+ for (sl = 0; sl < spatial_layers; ++sl) {
+ cfg_.ss_target_bitrate[sl] = spatial_layer_target =
+ static_cast<unsigned int>(cfg_.rc_target_bitrate * alloc_ratio[sl] /
+ total);
+ const int index = sl * temporal_layers;
+ if (cfg_.temporal_layering_mode == 3) {
+ cfg_.layer_target_bitrate[index] = spatial_layer_target >> 1;
+ cfg_.layer_target_bitrate[index + 1] =
+ (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
+ cfg_.layer_target_bitrate[index + 2] = spatial_layer_target;
+ } else if (cfg_.temporal_layering_mode == 2) {
+ cfg_.layer_target_bitrate[index] = spatial_layer_target * 2 / 3;
+ cfg_.layer_target_bitrate[index + 1] = spatial_layer_target;
+ } else if (cfg_.temporal_layering_mode <= 1) {
+ cfg_.layer_target_bitrate[index] = spatial_layer_target;
+ }
+ }
+ for (sl = 0; sl < spatial_layers; ++sl) {
+ for (int tl = 0; tl < temporal_layers; ++tl) {
+ const int layer = sl * temporal_layers + tl;
+ float layer_framerate = framerate;
+ if (temporal_layers == 2 && tl == 0) layer_framerate = framerate / 2;
+ if (temporal_layers == 3 && tl == 0) layer_framerate = framerate / 4;
+ if (temporal_layers == 3 && tl == 1) layer_framerate = framerate / 2;
+ layer_target_avg_bandwidth_[layer] = static_cast<int>(
+ cfg_.layer_target_bitrate[layer] * 1000.0 / layer_framerate);
+ bits_in_buffer_model_[layer] =
+ cfg_.layer_target_bitrate[layer] * cfg_.rc_buf_initial_sz;
+ }
+ }
+}
+} // namespace svc_test
diff --git a/media/libvpx/libvpx/test/svc_test.h b/media/libvpx/libvpx/test/svc_test.h
new file mode 100644
index 0000000000..f1d727fd9d
--- /dev/null
+++ b/media/libvpx/libvpx/test/svc_test.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_TEST_SVC_TEST_H_
+#define VPX_TEST_SVC_TEST_H_
+
+#include "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/bitops.h"
+
+namespace svc_test {
+class OnePassCbrSvc : public ::libvpx_test::EncoderTest {
+ public:
+ explicit OnePassCbrSvc(const ::libvpx_test::CodecFactory *codec)
+ : EncoderTest(codec), base_speed_setting_(0), speed_setting_(0),
+ superframe_count_(0), temporal_layer_id_(0), number_temporal_layers_(0),
+ number_spatial_layers_(0) {
+ memset(&svc_params_, 0, sizeof(svc_params_));
+ memset(bits_in_buffer_model_, 0,
+ sizeof(bits_in_buffer_model_[0]) * VPX_MAX_LAYERS);
+ memset(layer_target_avg_bandwidth_, 0,
+ sizeof(layer_target_avg_bandwidth_[0]) * VPX_MAX_LAYERS);
+ }
+
+ protected:
+ virtual ~OnePassCbrSvc() {}
+
+ virtual void SetConfig(const int num_temporal_layer) = 0;
+
+ virtual void SetSvcConfig(const int num_spatial_layer,
+ const int num_temporal_layer);
+
+ virtual void PreEncodeFrameHookSetup(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder);
+
+ virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder);
+
+ virtual void AssignLayerBitrates();
+
+ virtual void MismatchHook(const vpx_image_t *, const vpx_image_t *) {}
+
+ vpx_svc_extra_cfg_t svc_params_;
+ int64_t bits_in_buffer_model_[VPX_MAX_LAYERS];
+ int layer_target_avg_bandwidth_[VPX_MAX_LAYERS];
+ int base_speed_setting_;
+ int speed_setting_;
+ int superframe_count_;
+ int temporal_layer_id_;
+ int number_temporal_layers_;
+ int number_spatial_layers_;
+};
+} // namespace svc_test
+
+#endif // VPX_TEST_SVC_TEST_H_
diff --git a/media/libvpx/libvpx/test/test-data.mk b/media/libvpx/libvpx/test/test-data.mk
new file mode 100644
index 0000000000..62a9d6ef14
--- /dev/null
+++ b/media/libvpx/libvpx/test/test-data.mk
@@ -0,0 +1,898 @@
+LIBVPX_TEST_SRCS-yes += test-data.mk
+
+# Encoder test source
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288_nv12.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += desktop_office1.1280_720-020.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += slides_code_term_web_plot.1920_1080.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += desktopqvga.320_240.yuv
+
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_420_20f.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_422_20f.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_444_20f.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_440.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_420_20f.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_422_20f.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_444_20f.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_440.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420_a10-1.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_422.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_444.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_440.yuv
+
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_credits.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += noisy_clip_640_360.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += bus_352x288_420_f20_b8.yuv
+
+# Test vectors
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-004.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-004.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-005.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-005.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-006.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-006.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-007.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-007.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-008.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-008.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-009.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-009.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-010.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-010.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-011.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-011.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-012.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-012.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-013.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-013.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-014.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-014.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-015.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-015.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-016.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-016.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-017.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-017.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-018.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-018.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1400.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1400.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1411.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1411.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1416.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1416.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1417.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1417.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1402.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1402.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1412.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1412.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1418.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1418.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1424.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1424.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-01.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-01.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-02.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-02.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-03.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-03.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-04.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-04.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1401.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1401.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1403.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1403.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1407.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1407.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1408.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1408.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1409.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1409.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1410.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1410.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1413.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1413.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1414.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1414.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1415.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1415.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1425.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1425.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1426.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1426.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1427.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1427.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1432.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1432.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1435.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1435.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1436.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1436.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1437.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1437.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1441.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1441.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1442.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1442.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1404.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1404.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1405.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1405.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1406.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1406.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1428.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1428.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1429.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1429.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1430.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1430.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1431.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1431.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1433.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1433.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1434.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1434.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1438.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1438.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1439.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1439.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1440.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1440.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1443.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1443.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-06-smallsize.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-06-smallsize.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-00.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-00.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-01.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-01.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-02.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-02.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-03.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-03.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-04.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-04.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-05.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-05.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-06.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-06.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-07.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-07.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-09.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-09.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-11.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-11.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-12.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-12.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-13.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-13.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-14.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-14.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-15.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-15.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-17.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-17.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-19.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-19.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-20.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-20.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-21.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-21.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-22.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-22.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-23.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-23.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-24.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-24.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-25.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-25.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-26.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-26.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-27.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-27.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-28.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-28.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-29.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-29.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-30.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-30.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-31.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-31.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-33.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-33.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-35.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-35.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-36.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-36.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-37.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-37.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-38.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-38.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-39.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-39.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-40.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-40.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-41.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-41.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-42.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-42.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-43.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-43.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-44.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-44.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-45.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-45.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-46.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-46.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-47.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-47.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-48.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-48.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-49.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-49.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-50.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-50.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-51.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-51.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-52.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-52.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-53.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-53.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-54.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-54.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-55.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-55.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-56.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-56.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-57.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-57.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-58.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-58.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-59.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-59.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-60.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-60.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-61.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-61.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-62.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-62.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-63.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-63.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-3.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-5.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-5.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-6.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-6.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-7.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-7.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-130x132.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-130x132.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x130.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x130.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x132.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x132.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-178x180.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-178x180.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x178.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x178.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x180.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x180.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-lf-1920x1080.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-lf-1920x1080.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-deltaq.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-deltaq.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-352x288.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-352x288.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-05-resize.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-05-resize.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-06-bilinear.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-06-bilinear.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2_frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2_frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4_frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4_frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8_frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8_frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-352x287.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-352x287.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_1.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_1.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_2.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-16-intra-only.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-16-intra-only.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-17-show-existing-frame.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-17-show-existing-frame.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-18-resize.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-18-resize.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-01.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-01.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-02.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-02.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv422.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv422.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv440.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv440.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-01.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-01.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-02.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-02.webm.md5
+ifeq ($(CONFIG_VP9_HIGHBITDEPTH),yes)
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-10bit-yuv420.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-10bit-yuv420.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-12bit-yuv420.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-12bit-yuv420.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv422.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv422.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv422.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv422.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv440.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv440.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv440.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv440.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv444.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv444.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv444.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv444.webm.md5
+endif # CONFIG_VP9_HIGHBITDEPTH
+
+# Invalid files for testing libvpx error checking.
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-1443.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-1443.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-148271109.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-bug-148271109.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-token-partition.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-token-partition.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-s17661_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += invalid-vp80-00-comprehensive-s17661_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v3.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-63.ivf.kf_65527x61446.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-63.ivf.kf_65527x61446.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-10-show-existing-frame.webm.ivf.s180315_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-10-show-existing-frame.webm.ivf.s180315_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-21-resize_inter_320x180_5_3-4.webm.ivf.s45551_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-21-resize_inter_320x180_5_3-4.webm.ivf.s45551_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp91-2-mixedrefcsp-444to420.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp91-2-mixedrefcsp-444to420.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-629481.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-629481.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-1558.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-1558.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-1562.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-1562.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-667044.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-crbug-667044.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += crbug-1539.rawfile
+
+ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
+# Encode / Decode test
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
+# BBB VP9 streams
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_426x240_tile_1x1_180kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_640x360_tile_1x2_337kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_854x480_tile_1x2_651kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm
+# Sintel VP9 streams
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_426x182_tile_1x1_171kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_640x272_tile_1x2_318kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_854x364_tile_1x2_621kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm
+# TOS VP9 streams
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_426x178_tile_1x1_181kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_640x266_tile_1x2_336kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_854x356_tile_1x2_656kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1280x534_tile_1x4_1306kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm
+endif # CONFIG_DECODE_PERF_TESTS
+
+ifeq ($(CONFIG_ENCODE_PERF_TESTS),yes)
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_640_360_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += kirland_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcomoving_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcostationary_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomanarrows_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomasmallcameramovement_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += thaloundeskmtg_640_480_30.yuv
+endif # CONFIG_ENCODE_PERF_TESTS
+
+# sort and remove duplicates
+LIBVPX_TEST_DATA-yes := $(sort $(LIBVPX_TEST_DATA-yes))
+
+# VP9 dynamic resizing test (decoder)
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-22-svc_1280x720_3.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-22-svc_1280x720_3.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-22-svc_1280x720_1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-22-svc_1280x720_1.webm.md5
diff --git a/media/libvpx/libvpx/test/test-data.sha1 b/media/libvpx/libvpx/test/test-data.sha1
new file mode 100644
index 0000000000..55f92a25df
--- /dev/null
+++ b/media/libvpx/libvpx/test/test-data.sha1
@@ -0,0 +1,872 @@
+3eaf216d9fc8b4b9bb8c3956311f49a85974806c *bus_352x288_420_f20_b8.yuv
+d5dfb0151c9051f8c85999255645d7a23916d3c0 *hantro_collage_w352h288.yuv
+b87815bf86020c592ccc7a846ba2e28ec8043902 *hantro_odd.yuv
+76024eb753cdac6a5e5703aaea189d35c3c30ac7 *invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf
+7448d8798a4380162d4b56f9b452e2f6f9e24e7a *invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res
+83f50908c8dc0ef8760595447a2ff7727489542e *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
+456d1493e52d32a5c30edf44a27debc1fa6b253a *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
+c123d1f9f02fb4143abb5e271916e3a3080de8f6 *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
+456d1493e52d32a5c30edf44a27debc1fa6b253a *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
+efafb92b7567bc04c3f1432ea6c268c1c31affd5 *invalid-vp90-2-21-resize_inter_320x180_5_3-4.webm.ivf.s45551_r01-05_b6-.ivf
+5d9474c0309b7ca09a182d888f73b37a8fe1362c *invalid-vp90-2-21-resize_inter_320x180_5_3-4.webm.ivf.s45551_r01-05_b6-.ivf.res
+fe346136b9b8c1e6f6084cc106485706915795e4 *invalid-vp90-01-v3.webm
+5d9474c0309b7ca09a182d888f73b37a8fe1362c *invalid-vp90-01-v3.webm.res
+d78e2fceba5ac942246503ec8366f879c4775ca5 *invalid-vp90-02-v2.webm
+8e2eff4af87d2b561cce2365713269e301457ef3 *invalid-vp90-02-v2.webm.res
+df1a1453feb3c00d7d89746c7003b4163523bff3 *invalid-vp90-03-v3.webm
+4935c62becc68c13642a03db1e6d3e2331c1c612 *invalid-vp90-03-v3.webm.res
+d637297561dd904eb2c97a9015deeb31c4a1e8d2 *invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm
+3a204bdbeaa3c6458b77bcebb8366d107267f55d *invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res
+9aa21d8b2cb9d39abe8a7bb6032dc66955fb4342 *noisy_clip_640_360.y4m
+0936b837708ae68c034719f8e07596021c2c214f *park_joy_90p_10_420_20f.y4m
+5727a853c083c1099f837d27967bc1322d50ed4f *park_joy_90p_10_422_20f.y4m
+e13489470ef8e8b2a871a5640d795a42a39be58d *park_joy_90p_10_444_20f.y4m
+c934da6fb8cc54ee2a8c17c54cf6076dac37ead0 *park_joy_90p_10_440.yuv
+79b0dc1784635a7f291e21c4e8d66a29c496ab99 *park_joy_90p_12_420_20f.y4m
+9cf22b0f809f7464c8b9058f0cfa9d905921cbd1 *park_joy_90p_12_422_20f.y4m
+22b2a4abaecc4a9ade6bb503d25fb82367947e85 *park_joy_90p_12_444_20f.y4m
+82c1bfcca368c2f22bad7d693d690d5499ecdd11 *park_joy_90p_12_440.yuv
+b9e1e90aece2be6e2c90d89e6ab2372d5f8c792d *park_joy_90p_8_420_a10-1.y4m
+4e0eb61e76f0684188d9bc9f3ce61f6b6b77bb2c *park_joy_90p_8_420.y4m
+7a193ff7dfeb96ba5f82b2afd7afa9e1fe83d947 *park_joy_90p_8_422.y4m
+bdb7856e6bc93599bdda05c2e773a9f22b6c6d03 *park_joy_90p_8_444.y4m
+81e1f3843748438b8f2e71db484eb22daf72e939 *park_joy_90p_8_440.yuv
+b1f1c3ec79114b9a0651af24ce634afb44a9a419 *rush_hour_444.y4m
+5184c46ddca8b1fadd16742e8500115bc8f749da *vp80-00-comprehensive-001.ivf
+65bf1bbbced81b97bd030f376d1b7f61a224793f *vp80-00-comprehensive-002.ivf
+906b4c1e99eb734504c504b3f1ad8052137ce672 *vp80-00-comprehensive-003.ivf
+ec144b1af53af895db78355785650b96dd3f0ade *vp80-00-comprehensive-004.ivf
+afc7091785c62f1c121c4554a2830c30704587d9 *vp80-00-comprehensive-005.ivf
+42ea9d55c818145d06a9b633b8e85c6a6164fd3e *vp80-00-comprehensive-006.ivf
+e5b3a73ab79fe024c14309d653d6bed92902ee3b *vp80-00-comprehensive-007.ivf
+f3c50a58875930adfb84525c0ef59d7e4c08540c *vp80-00-comprehensive-008.ivf
+4b2841fdb83db51ae322096ae468bbb9dc2c8362 *vp80-00-comprehensive-009.ivf
+efbff736e3a91ab6a98c5bc2dce65d645944c7b1 *vp80-00-comprehensive-010.ivf
+6b315102cae008d22a3d2c231be92cb704a222f8 *vp80-00-comprehensive-011.ivf
+f3214a4fea14c2d5ec689936c1613f274c859ee8 *vp80-00-comprehensive-012.ivf
+e4094e96d308c8a35b74c480a43d853c5294cd34 *vp80-00-comprehensive-013.ivf
+5b0adfaf60a69e0aaf3ec021a39d0a68fc0e1b5a *vp80-00-comprehensive-014.ivf
+e8467688ddf26b5000664f904faf0d70506aa653 *vp80-00-comprehensive-015.ivf
+aab55582337dfd2a39ff54fb2576a91910d49337 *vp80-00-comprehensive-016.ivf
+1ba24724f80203c9bae4f1d0f99d534721980016 *vp80-00-comprehensive-017.ivf
+143a15512b46f436280ddb4d0e6411eb4af434f2 *vp80-00-comprehensive-018.ivf
+c5baeaf5714fdfb3a8bc960a8e33ac438e83b16b *vp80-01-intra-1400.ivf
+f383955229afe3408453e316d11553d923ca60d5 *vp80-01-intra-1411.ivf
+84e1f4343f174c9f3c83f834bac3196fb325bf2c *vp80-01-intra-1416.ivf
+fb6e712a47dd57a28a3727d2ae2c97a8b7c7ca51 *vp80-01-intra-1417.ivf
+71ea772d3e9d315b8cbecf41207b8a237c34853b *vp80-02-inter-1402.ivf
+d85dbc4271525dcd128c503f936fe69091d1f8d0 *vp80-02-inter-1412.ivf
+d4e5d3ad56511867d025f93724d090f92ba6ec3d *vp80-02-inter-1418.ivf
+91791cbcc37c60f35dbd8090bacb54e5ec6dd4fa *vp80-02-inter-1424.ivf
+17fbfe2fea70f6e2f3fa6ca4efaae6c0b03b5f02 *vp80-03-segmentation-01.ivf
+3c3600dbbcde08e20d54c66fe3b7eadd4f09bdbb *vp80-03-segmentation-02.ivf
+c156778d5340967d4b369c490848076e92f1f875 *vp80-03-segmentation-03.ivf
+d25dcff6c60e87a1af70945b8911b6b4998533b0 *vp80-03-segmentation-04.ivf
+362baba2ce454c9db21218f35e81c27a5ed0b730 *vp80-03-segmentation-1401.ivf
+d223ae7ee748ce07e74c4679bfd219e84aa9f4b0 *vp80-03-segmentation-1403.ivf
+033adf7f3a13836a3f1cffcb87c1972900f2b5c6 *vp80-03-segmentation-1407.ivf
+4d51dfbf9f3e2c590ec99d1d6f59dd731d04375f *vp80-03-segmentation-1408.ivf
+f37a62b197c2600d75e0ccfbb31b60efdedac251 *vp80-03-segmentation-1409.ivf
+eb25bd7bfba5b2f6935018a930f42d123b1e7fcd *vp80-03-segmentation-1410.ivf
+b9d5c436663a30c27cfff84b53a002e501258843 *vp80-03-segmentation-1413.ivf
+6da92b9d1a180cc3a8afe348ab12258f5a37be1a *vp80-03-segmentation-1414.ivf
+a4f5842602886bd669f115f93d8a35c035cb0948 *vp80-03-segmentation-1415.ivf
+f295dceb8ef278b77251b3f9df8aee22e161d547 *vp80-03-segmentation-1425.ivf
+198dbf9f36f733200e432664cc8c5752d59779de *vp80-03-segmentation-1426.ivf
+7704804e32f5de976803929934a7fafe101ac7b0 *vp80-03-segmentation-1427.ivf
+831ccd862ea95ca025d2f3bd8b88678752f5416d *vp80-03-segmentation-1432.ivf
+b3c11978529289f9109f2766fcaba3ebc40e11ef *vp80-03-segmentation-1435.ivf
+a835a731f5520ebfc1002c40121264d0020559ac *vp80-03-segmentation-1436.ivf
+1d1732942f773bb2a5775fcb9689b1579ce28eab *vp80-03-segmentation-1437.ivf
+db04799adfe089dfdf74dbd43cc05ede7161f99e *vp80-03-segmentation-1441.ivf
+7caf39b3f20cfd52b998210878062e52a5edf1e6 *vp80-03-segmentation-1442.ivf
+3607f6bb4ee106c38fa1ea370dc4ff8b8cde2261 *vp80-04-partitions-1404.ivf
+93cc323b6b6867f1b12dd48773424549c6960a6b *vp80-04-partitions-1405.ivf
+047eedb14b865bdac8a3538e63801054e0295e9c *vp80-04-partitions-1406.ivf
+0f1233bd2bc33f56ce5e495dbd455d122339f384 *vp80-05-sharpness-1428.ivf
+51767fc136488a9535c2a4c38067c542ee2048df *vp80-05-sharpness-1429.ivf
+9805aa107672de25d6fb8c35e20d06deca5efe18 *vp80-05-sharpness-1430.ivf
+61db6b965f9c27aebe71b85bf2d5877e58e4bbdf *vp80-05-sharpness-1431.ivf
+10420d266290d2923555f84af38eeb96edbd3ae8 *vp80-05-sharpness-1433.ivf
+3ed24f9a80cddfdf75824ba95cdb4ff9286cb443 *vp80-05-sharpness-1434.ivf
+c87599cbecd72d4cd4f7ace3313b7a6bc6eb8163 *vp80-05-sharpness-1438.ivf
+aff51d865c2621b60510459244ea83e958e4baed *vp80-05-sharpness-1439.ivf
+da386e72b19b5485a6af199c5eb60ef25e510dd1 *vp80-05-sharpness-1440.ivf
+6759a095203d96ccd267ce09b1b050b8cc4c2f1f *vp80-05-sharpness-1443.ivf
+b95d3cc1d0df991e63e150a801710a72f20d9ba0 *vp80-06-smallsize.ivf
+db55ec7fd02c864ba996ff060b25b1e08611330b *vp80-00-comprehensive-001.ivf.md5
+29db0ad011cba1e45f856d5623cd38dac3e3bf19 *vp80-00-comprehensive-002.ivf.md5
+e84f258f69e173e7d68f8f8c037a0a3766902182 *vp80-00-comprehensive-003.ivf.md5
+eb7912eaf69559a16fd82bc3f5fb1524cf4a4466 *vp80-00-comprehensive-004.ivf.md5
+4206f71c94894bd5b5b376f6c09b3817dbc65206 *vp80-00-comprehensive-005.ivf.md5
+4f89b356f6f2fecb928f330a10f804f00f5325f5 *vp80-00-comprehensive-006.ivf.md5
+2813236a32964dd8007e17648bcf035a20fcda6c *vp80-00-comprehensive-007.ivf.md5
+10746c72098f872803c900e17c5680e451f5f498 *vp80-00-comprehensive-008.ivf.md5
+39a23d0692ce64421a7bb7cdf6ccec5928d37fff *vp80-00-comprehensive-009.ivf.md5
+f6e3de8931a0cc659bda8fbc14050346955e72d4 *vp80-00-comprehensive-010.ivf.md5
+101683ec195b6e944f7cd1e468fc8921439363e6 *vp80-00-comprehensive-011.ivf.md5
+1f592751ce46d8688998fa0fa4fbdcda0fd4058c *vp80-00-comprehensive-012.ivf.md5
+6066176f90ca790251e795fca1a5797d59999841 *vp80-00-comprehensive-013.ivf.md5
+2656da94ba93691f23edc4d60b3a09e2be46c217 *vp80-00-comprehensive-014.ivf.md5
+c6e0d5f5d61460c8ac8edfa4e701f10312c03133 *vp80-00-comprehensive-015.ivf.md5
+ee60fee501d8493e34e8d6a1fe315b51ed09b24a *vp80-00-comprehensive-016.ivf.md5
+9f1914ceffcad4546c0a29de3ef591d8bea304dc *vp80-00-comprehensive-017.ivf.md5
+e0305178fe288a9fd8082b39e2d03181edb19054 *vp80-00-comprehensive-018.ivf.md5
+612494da2fa799cc9d76dcdd835ae6c7cb2e5c05 *vp80-01-intra-1400.ivf.md5
+48ea06097ac8269c5e8c2131d3d0639f431fcf0e *vp80-01-intra-1411.ivf.md5
+6e2ab4e7677ad0ba868083ca6bc387ee922b400c *vp80-01-intra-1416.ivf.md5
+eca0a90348959ce3854142f8d8641b13050e8349 *vp80-01-intra-1417.ivf.md5
+920feea203145d5c2258a91c4e6991934a79a99e *vp80-02-inter-1402.ivf.md5
+f71d97909fe2b3dd65be7e1f56c72237f0cef200 *vp80-02-inter-1412.ivf.md5
+e911254569a30bbb2a237ff8b79f69ed9da0672d *vp80-02-inter-1418.ivf.md5
+58c789c50c9bb9cc90580bed291164a0939d28ba *vp80-02-inter-1424.ivf.md5
+ff3e2f441327b9c20a0b37c524e0f5a48a36de7b *vp80-03-segmentation-01.ivf.md5
+0791f417f076a542ae66fbc3426ab4d94cbd6c75 *vp80-03-segmentation-02.ivf.md5
+722e50f1a6a91c34302d68681faffc1c26d1cc57 *vp80-03-segmentation-03.ivf.md5
+c701f1885bcfb27fb8e70cc65606b289172ef889 *vp80-03-segmentation-04.ivf.md5
+f79bc9ec189a2b4807632a3d0c5bf04a178b5300 *vp80-03-segmentation-1401.ivf.md5
+b9aa4c74c0219b639811c44760d0b24cd8bb436a *vp80-03-segmentation-1403.ivf.md5
+70d5a2207ca1891bcaebd5cf6dd88ce8d57b4334 *vp80-03-segmentation-1407.ivf.md5
+265f962ee781531f9a93b9309461316fd32b2a1d *vp80-03-segmentation-1408.ivf.md5
+0c4ecbbd6dc042d30e626d951b65f460dd6cd563 *vp80-03-segmentation-1409.ivf.md5
+cf779af36a937f06570a0fca9db64ba133451dee *vp80-03-segmentation-1410.ivf.md5
+0e6c5036d51ab078842f133934926c598a9cff02 *vp80-03-segmentation-1413.ivf.md5
+eb3930aaf229116c80d507516c34759c3f6cdf69 *vp80-03-segmentation-1414.ivf.md5
+123d6c0f72ee87911c4ae7538e87b7d163b22d6c *vp80-03-segmentation-1415.ivf.md5
+e70551d1a38920e097a5d8782390b79ecaeb7505 *vp80-03-segmentation-1425.ivf.md5
+44e8f4117e46dbb302b2cfd81171cc1a1846e431 *vp80-03-segmentation-1426.ivf.md5
+52636e54aee5f95bbace37021bd67de5db767e9a *vp80-03-segmentation-1427.ivf.md5
+b1ad3eff20215c28e295b15ef3636ed926d59cba *vp80-03-segmentation-1432.ivf.md5
+24c22a552fa28a90e5978f67f57181cc2d7546d7 *vp80-03-segmentation-1435.ivf.md5
+96c49c390abfced18a7a8c9b9ea10af778e10edb *vp80-03-segmentation-1436.ivf.md5
+f95eb6214571434f1f73ab7833b9ccdf47588020 *vp80-03-segmentation-1437.ivf.md5
+1c0700ca27c9b0090a7747a4b0b4dc21d1843181 *vp80-03-segmentation-1441.ivf.md5
+81d4f23ca32667ee958bae579c8f5e97ba72eb97 *vp80-03-segmentation-1442.ivf.md5
+272efcef07a3a30fbca51bfd566063d8258ec0be *vp80-04-partitions-1404.ivf.md5
+66ed219ab812ac801b256d35cf495d193d4cf478 *vp80-04-partitions-1405.ivf.md5
+36083f37f56f502bd60ec5e07502ee9e6b8699b0 *vp80-04-partitions-1406.ivf.md5
+6ca909bf168a64c09415626294665dc1be3d1973 *vp80-05-sharpness-1428.ivf.md5
+1667d2ee2334e5fdea8a8a866f4ccf3cf76f033a *vp80-05-sharpness-1429.ivf.md5
+71bcbe5357d36a19df5b07fbe3e27bffa8893f0a *vp80-05-sharpness-1430.ivf.md5
+89a09b1dffce2d55770a89e58d9925c70ef79bf8 *vp80-05-sharpness-1431.ivf.md5
+08444a18b4e6ba3450c0796dd728d48c399a2dc9 *vp80-05-sharpness-1433.ivf.md5
+6d6223719a90c13e848aa2a8a6642098cdb5977a *vp80-05-sharpness-1434.ivf.md5
+41d70bb5fa45bc88da1604a0af466930b8dd77b5 *vp80-05-sharpness-1438.ivf.md5
+086c56378df81b6cee264d7540a7b8f2b405c7a4 *vp80-05-sharpness-1439.ivf.md5
+d32dc2c4165eb266ea4c23c14a45459b363def32 *vp80-05-sharpness-1440.ivf.md5
+8c69dc3d8e563f56ffab5ad1e400d9e689dd23df *vp80-05-sharpness-1443.ivf.md5
+d6f246df012c241b5fa6c1345019a3703d85c419 *vp80-06-smallsize.ivf.md5
+ce881e567fe1d0fbcb2d3e9e6281a1a8d74d82e0 *vp90-2-00-quantizer-00.webm
+ac5eda33407d0521c7afca43a63fd305c0cd9d13 *vp90-2-00-quantizer-00.webm.md5
+2ca0463f2cfb93d25d7dded174db70b7cb87cb48 *vp90-2-00-quantizer-01.webm
+10d98884fc6d9a5f47a2057922b8e25dd48d7786 *vp90-2-00-quantizer-01.webm.md5
+d80a2920a5e0819d69dcba8fe260c01f820f8982 *vp90-2-00-quantizer-02.webm
+c964c8e5e04165fabbf1c6ee8ee5121d35921965 *vp90-2-00-quantizer-02.webm.md5
+fdef046777b5b75c962b715d809dbe2ea331afb9 *vp90-2-00-quantizer-03.webm
+f270bee0b0c7aa2bf4c5afe098556b4f3f890faf *vp90-2-00-quantizer-03.webm.md5
+66d98609e809394a6ac730787e6724e3badc075a *vp90-2-00-quantizer-04.webm
+427433bfe121c4aea1095ec3124fdc174d200e3a *vp90-2-00-quantizer-04.webm.md5
+e6e42626d8cadf0b5be16313f69212981b96fee5 *vp90-2-00-quantizer-05.webm
+c98f6a9a1af4cfd71416792827304266aad4bd46 *vp90-2-00-quantizer-05.webm.md5
+413ef09b721f5dcec1a96e937a97e5873c2e6db6 *vp90-2-00-quantizer-06.webm
+5080e940a23805c82e578e21b57fc2c511e76376 *vp90-2-00-quantizer-06.webm.md5
+4a50a5f4ac717c30dfaae8bb46702e3542e867de *vp90-2-00-quantizer-07.webm
+76c429a02b56762e10ee4db88729d8834b3a70f4 *vp90-2-00-quantizer-07.webm.md5
+d2f4e464780bf8b7e647efa18ac777a930e62bc0 *vp90-2-00-quantizer-08.webm
+ab94aabf9316111b52d7c531962ed4123313b6ba *vp90-2-00-quantizer-08.webm.md5
+174bc58433936dd79550398d744f1072ce7f5693 *vp90-2-00-quantizer-09.webm
+e1f7690cd83ccc56d045e17cce552544a5f03810 *vp90-2-00-quantizer-09.webm.md5
+52bc1dfd3a97b24d922eb8a31d07527891561f2a *vp90-2-00-quantizer-10.webm
+9b37bed893b5f6a4e12f2aa40f02dd40f944d0f8 *vp90-2-00-quantizer-10.webm.md5
+10031eecafde1e1d8e6323fe2b2a1d7e77a66869 *vp90-2-00-quantizer-11.webm
+fe4620a4bb0e4f5cb9bbfedc4039a22b81b0f5c0 *vp90-2-00-quantizer-11.webm.md5
+78e9f7bb77e8e348155bbdfa12790789d1d50c34 *vp90-2-00-quantizer-12.webm
+0961d060cc8dd469c6dac8d7d75f927c0bb971b8 *vp90-2-00-quantizer-12.webm.md5
+133b77a3bbcef652552d74ffc46afbfe3b8a1cba *vp90-2-00-quantizer-13.webm
+df29e5e0f95772af482f540d776f6b9dea4bfa29 *vp90-2-00-quantizer-13.webm.md5
+27323afdaf8987e025c27129c74c86502315a206 *vp90-2-00-quantizer-14.webm
+ce96a2cc312942f0427a463f15a392870dd69764 *vp90-2-00-quantizer-14.webm.md5
+ab58d0b41037829f6bc993910999f4af0212aafd *vp90-2-00-quantizer-15.webm
+40f700db606501aa7cb49049624cbdde6409b122 *vp90-2-00-quantizer-15.webm.md5
+cd948e66448aafb65998815ce37241f95d7c9ee7 *vp90-2-00-quantizer-16.webm
+039b742d149c945ed79c7b9a6384352852a1c116 *vp90-2-00-quantizer-16.webm.md5
+62f56e663e13c576764e491cf08f19bd46a71999 *vp90-2-00-quantizer-17.webm
+90c5a39bf76e6b3e0a1c0d3e9b68a9fd78be963e *vp90-2-00-quantizer-17.webm.md5
+f26ecad7263cd66a614e53ba5d7c00df181affeb *vp90-2-00-quantizer-18.webm
+cda0a1c0fca2ec2976ae55124a8a67305508bae6 *vp90-2-00-quantizer-18.webm.md5
+94bfc4c04fcfe139a63b98c569e8c14ba98c401f *vp90-2-00-quantizer-19.webm
+5b8ec169ccf67d8a0a8e46a62eb173f5a1dbaf4f *vp90-2-00-quantizer-19.webm.md5
+0ee88e9318985e1e245de78c2c4a665885ab76a7 *vp90-2-00-quantizer-20.webm
+4b26f7edb4fcd3a1b4cce9ba3cb8650e3ee6e063 *vp90-2-00-quantizer-20.webm.md5
+6a995cb2b1db33da8087321df1e646f95c3e32d1 *vp90-2-00-quantizer-21.webm
+e216b4a1eceac03efcc433759be54ab8ea87b24b *vp90-2-00-quantizer-21.webm.md5
+aa7722fc427e7180115f3c9cd96bb6b2768e7296 *vp90-2-00-quantizer-22.webm
+1aa813bd45ae831bf5e79ace4d73dfd25989a07d *vp90-2-00-quantizer-22.webm.md5
+7677e5b929ed6d142041f19b8a9cd5822ee1504a *vp90-2-00-quantizer-23.webm
+0de0af34abd843d5b37e58baf3ed96a6104b64c3 *vp90-2-00-quantizer-23.webm.md5
+b2995cbe1128b2d4926f1b28d01c501ecb6be8c8 *vp90-2-00-quantizer-24.webm
+db6033af2ba2f2bca62468fb4b8808e474f93923 *vp90-2-00-quantizer-24.webm.md5
+8135ba35587fd92cd4667be7896323d9b634401c *vp90-2-00-quantizer-25.webm
+3499e00c2cc15876f61f07e3d3cfca54ebcd98fd *vp90-2-00-quantizer-25.webm.md5
+af0fa2907746db82d345f6d831fcc1b2862a29fb *vp90-2-00-quantizer-26.webm
+cd6fe3d14dab48886ebf65be00e6ed9616ebe5a7 *vp90-2-00-quantizer-26.webm.md5
+bd0002e91323776beb5ff11e06edcf19fc08e9b9 *vp90-2-00-quantizer-27.webm
+fe72154ef196067d6c272521012dd79706496cac *vp90-2-00-quantizer-27.webm.md5
+fc15eb606f81455ff03df16bf3432296b002c43c *vp90-2-00-quantizer-28.webm
+40b2e24b542206a6bfd746ef199e49ccea07678a *vp90-2-00-quantizer-28.webm.md5
+3090bbf913cad0b2eddca7228f5ed51a58378b8d *vp90-2-00-quantizer-29.webm
+eb59745e0912d8ed6c928268bcf265237c9ba93f *vp90-2-00-quantizer-29.webm.md5
+c615abdca9c25e1cb110d908edbedfb3b7c92b91 *vp90-2-00-quantizer-30.webm
+ad0f4fe6733e4e7cdfe8ef8722bb341dcc7538c0 *vp90-2-00-quantizer-30.webm.md5
+037d9f242086cfb085518f6416259defa82d5fc2 *vp90-2-00-quantizer-31.webm
+4654b40792572f0a790874c6347ef9196d86c1a7 *vp90-2-00-quantizer-31.webm.md5
+505899f3f3515044c5c8b3213d9b9d16f614619d *vp90-2-00-quantizer-32.webm
+659a2e6dd02df323f62600626859006640b445df *vp90-2-00-quantizer-32.webm.md5
+8b32ec9c3b7e5ca8ddc6b8aea1c1cb7ca996bccc *vp90-2-00-quantizer-33.webm
+5b175ef1120ddeba4feae1247bf381bbc4e816ce *vp90-2-00-quantizer-33.webm.md5
+4d283755d17e287b1d099a80604398f60d7fb6ea *vp90-2-00-quantizer-34.webm
+22a739de95acfeb27524e3700b8f678a9ad744d8 *vp90-2-00-quantizer-34.webm.md5
+4296f56a892a412d3d4f64824718dd566c4e6459 *vp90-2-00-quantizer-35.webm
+c532c9c8dc7b3506fc6a51e5c20c17ef0ac039e7 *vp90-2-00-quantizer-35.webm.md5
+6f54e11da461e4410dd9075b015e2d9bc1d07dfb *vp90-2-00-quantizer-36.webm
+0b3573f5addea4e3eb11a0b85f068299d5bdad78 *vp90-2-00-quantizer-36.webm.md5
+210581682a26c2c4375efc785c36e07539888bc2 *vp90-2-00-quantizer-37.webm
+2b4fb6f8ba975237858e61cc8f560bcfc87cb38e *vp90-2-00-quantizer-37.webm.md5
+a15ef31283dfc4860f837fe200eb32a445f59629 *vp90-2-00-quantizer-38.webm
+fb76771f3a795054b9936f70da7505c3ac585284 *vp90-2-00-quantizer-38.webm.md5
+1df8433a441412831daae6726df89fa70d21b14d *vp90-2-00-quantizer-39.webm
+39e162c09a20e7e684868097766347014371fee6 *vp90-2-00-quantizer-39.webm.md5
+5330e4788ab9129dbb25a7a7d5411104521248b6 *vp90-2-00-quantizer-40.webm
+872cc0f2cc9dbf000f89eadb4d8f9940e48e00b1 *vp90-2-00-quantizer-40.webm.md5
+d88d03b982889e399a78d7a06eeb1cf30e6c2da2 *vp90-2-00-quantizer-41.webm
+5b4f7217e57fa2a221011d0b32f8d0409496b7b6 *vp90-2-00-quantizer-41.webm.md5
+9e16406e3e26955a6e17d455ef1ef64bbfa26e53 *vp90-2-00-quantizer-42.webm
+0219d090cf37daabe19256ba8e932ba4874b92e4 *vp90-2-00-quantizer-42.webm.md5
+a9b15843486fb05f8cd15437ef279782a42b75db *vp90-2-00-quantizer-43.webm
+3c9b0b4c607f9579a31726bfcf56729334ddc686 *vp90-2-00-quantizer-43.webm.md5
+1dbc931ac446c91eabe7213efff55b596cccf07c *vp90-2-00-quantizer-44.webm
+73bc8f675103abaef3d9f73a2742b3bffd726d23 *vp90-2-00-quantizer-44.webm.md5
+7c6c1be15beb9d6201204b018966c8c4f9777efc *vp90-2-00-quantizer-45.webm
+c907b29da821f790c6748de61f592689312e4e36 *vp90-2-00-quantizer-45.webm.md5
+07b434da1a467580f73b32177ee11b3e00f65a0d *vp90-2-00-quantizer-46.webm
+7b2b7ce60c50bc970bc0ada46d7a7ce440148da3 *vp90-2-00-quantizer-46.webm.md5
+233d0465fb1a6fa36e9f89bd2193ac79bd4d2809 *vp90-2-00-quantizer-47.webm
+527e0a9fb932efe915027ffe077f9e8d3a4fb139 *vp90-2-00-quantizer-47.webm.md5
+719613df7307e205c3fdb6acfb373849c5ab23c7 *vp90-2-00-quantizer-48.webm
+65ab6c9d1b682c183b201c7ff42b90343ce3e304 *vp90-2-00-quantizer-48.webm.md5
+3bf04a598325ed0eabae1598ec7f718f715ec672 *vp90-2-00-quantizer-49.webm
+ac68c4387ce11fcc998d8ba455ab9b2bb361d240 *vp90-2-00-quantizer-49.webm.md5
+d59238fb3a654931c9b65a11e7321b40d1f702e9 *vp90-2-00-quantizer-50.webm
+d0576bfede46fd55659f028f2fd28554ceb3e6cc *vp90-2-00-quantizer-50.webm.md5
+3f579785101d4209360dd96f8c2ffe9beddf3bee *vp90-2-00-quantizer-51.webm
+89fcfe04f4457a7f02ab4a2f94aacbb88aee5789 *vp90-2-00-quantizer-51.webm.md5
+28be5836e2fedefe4babf12fc9b79e460ab0a0f4 *vp90-2-00-quantizer-52.webm
+f3dd52b70c18345fee740220f35da9c4def2017a *vp90-2-00-quantizer-52.webm.md5
+488ad4058c17170665b6acd1021fade9a02771e4 *vp90-2-00-quantizer-53.webm
+1cdcb1d4f3a37cf83ad235eb27ec62ed2a01afc7 *vp90-2-00-quantizer-53.webm.md5
+682978289cb28cc8c9d39bc797300e45d6039de7 *vp90-2-00-quantizer-54.webm
+36c35353f2c03cb099bd710d9994de7d9ed88834 *vp90-2-00-quantizer-54.webm.md5
+c398ce49af762a48f10cc4da9fae0769aae5f226 *vp90-2-00-quantizer-55.webm
+2cf3570542d984f167ab087f59493c7fb47e0ed2 *vp90-2-00-quantizer-55.webm.md5
+3071f18b2fce261aa82d61f81a7ae4ca9a75d0e3 *vp90-2-00-quantizer-56.webm
+d3f93f8272b6de31cffb011a26f11abb514efb12 *vp90-2-00-quantizer-56.webm.md5
+f4e8e14b1f278801a7eb6f11734780a01b1668e9 *vp90-2-00-quantizer-57.webm
+6478fdf1d7faf6db5f19dffc5e1363af358699ee *vp90-2-00-quantizer-57.webm.md5
+307dc264f57cc618fff211fa44d7f52767ed9660 *vp90-2-00-quantizer-58.webm
+cf231d4a52d492fa692ea4194ec5eb7511fec54e *vp90-2-00-quantizer-58.webm.md5
+1fd7cd596170afce2de0b1441b7674bda5723440 *vp90-2-00-quantizer-59.webm
+4681f7ef96f63e085c41bb1a964b0df7e67e0b38 *vp90-2-00-quantizer-59.webm.md5
+34cdcc81c0ba7085aefbb22d7b4aa9bca3dd7c62 *vp90-2-00-quantizer-60.webm
+58691ef53b6b623810e2c57ded374c77535df935 *vp90-2-00-quantizer-60.webm.md5
+e6e812406aab81021bb16e772c1db03f75906cb6 *vp90-2-00-quantizer-61.webm
+76436eace62f08ff92b61a0845e66667a027db1b *vp90-2-00-quantizer-61.webm.md5
+84d811bceed70c950a6a08e572a6e274866e72b1 *vp90-2-00-quantizer-62.webm
+2d937cc011eeddd95222b960982da5cd18db580f *vp90-2-00-quantizer-62.webm.md5
+0912b295ba0ea09359315315ffd67d22d046f883 *vp90-2-00-quantizer-63.webm
+5a829031055d70565f57dbcd47a6ac33619952b3 *vp90-2-00-quantizer-63.webm.md5
+0cf9e5ebe0112bdb47b5887ee5d58eb9d4727c00 *vp90-2-01-sharpness-1.webm
+5a0476be4448bae8f8ca17ea236c98793a755948 *vp90-2-01-sharpness-1.webm.md5
+51e02d7911810cdf5be8b68ac40aedab479a3179 *vp90-2-01-sharpness-2.webm
+a0ca5bc87a5ed7c7051f59078daa0d03be1b45b6 *vp90-2-01-sharpness-2.webm.md5
+0603f8ad239c07a531d948187f4dafcaf51eda8d *vp90-2-01-sharpness-3.webm
+3af8000a69c72fe77881e3176f026c2affb78cc7 *vp90-2-01-sharpness-3.webm.md5
+4ca4839f48146252fb261ed88838d80211804841 *vp90-2-01-sharpness-4.webm
+08832a1494f84fa9edd40e080bcf2c0e80100c76 *vp90-2-01-sharpness-4.webm.md5
+95099dc8f9cbaf9b9a7dd65311923e441ff70731 *vp90-2-01-sharpness-5.webm
+93ceee30c140f0b406726c0d896b9db6031c4c7f *vp90-2-01-sharpness-5.webm.md5
+ceb4116fb7b078d266d153233b6d62a255a34e4c *vp90-2-01-sharpness-6.webm
+da83efe59e537ce538e8b03a6eac63cf25849c9a *vp90-2-01-sharpness-6.webm.md5
+b5f7cd19aece3880f9d616a778e5cc24c6b9b505 *vp90-2-01-sharpness-7.webm
+2957408d20deac8633941a2169f801bae6f086e1 *vp90-2-01-sharpness-7.webm.md5
+ffc096c2ce1050450ad462b5fabd2a5220846319 *vp90-2-02-size-08x08.webm
+e36d2ed6fa2746347710b750586aafa6a01ff3ae *vp90-2-02-size-08x08.webm.md5
+895b986f9fd55cd879472b31c6a06b82094418c8 *vp90-2-02-size-08x10.webm
+079157a19137ccaebba606f2871f45a397347150 *vp90-2-02-size-08x10.webm.md5
+1c5992203e62a2b83040ccbecd748b604e19f4c0 *vp90-2-02-size-08x16.webm
+9aa45ffdf2078f883bbed01450031b691819c144 *vp90-2-02-size-08x16.webm.md5
+d0a8953da1f85f484487408fee5da9e2a8391901 *vp90-2-02-size-08x18.webm
+59a5cc17d354c6a23e5e959d666b1456a5d49c56 *vp90-2-02-size-08x18.webm.md5
+1b13461a9fc65cb041bacfe4ea6f02d363397d61 *vp90-2-02-size-08x32.webm
+2bdddd6878f05d37d84cde056a3f5e7f926ba3d6 *vp90-2-02-size-08x32.webm.md5
+2861f0a0daadb62295b0504a1fbe5b50c79a8f59 *vp90-2-02-size-08x34.webm
+6b5812cfb8a82d378ea2913bf009e93668020147 *vp90-2-02-size-08x34.webm.md5
+02f948216d4246579dc53c47fe55d8fb264ba251 *vp90-2-02-size-08x64.webm
+84b55fdee6d9aa820c7a8c62822446184b191767 *vp90-2-02-size-08x64.webm.md5
+4b011242cbf42516efd2b197baebb61dd34562c9 *vp90-2-02-size-08x66.webm
+6b1fa0a885947b3cc0fe58f75f838e662bd9bb8b *vp90-2-02-size-08x66.webm.md5
+4057796be9dd12df48ab607f502ae6aa70eeeab6 *vp90-2-02-size-10x08.webm
+71c752c51aec9f48de286b93f4c20e9c11cad7d0 *vp90-2-02-size-10x08.webm.md5
+6583c853fa43fc53d51743eac5f3a43a359d45d0 *vp90-2-02-size-10x10.webm
+1da524d24af1944b671d4d3f2b398d6e336584c3 *vp90-2-02-size-10x10.webm.md5
+ba442fc03ccd3a705c64c83b36f5ada67d198874 *vp90-2-02-size-10x16.webm
+7cfd960f232c34c641a4a2a9411b6fd0efb2fc50 *vp90-2-02-size-10x16.webm.md5
+cc92ed40eef14f52e4d080cb2c57939dd8326374 *vp90-2-02-size-10x18.webm
+db5626275cc55ce970b91c995e74f6838d943aca *vp90-2-02-size-10x18.webm.md5
+3a93d501d22325e9fd4c9d8b82e2a432de33c351 *vp90-2-02-size-10x32.webm
+5cae51b0c71cfc131651f345f87583eb2903afaf *vp90-2-02-size-10x32.webm.md5
+50d2f2b15a9a5178153db44a9e03aaf32b227f67 *vp90-2-02-size-10x34.webm
+bb0efe058122641e7f73e94497dda2b9e6c21efd *vp90-2-02-size-10x34.webm.md5
+01624ec173e533e0b33fd9bdb91eb7360c7c9175 *vp90-2-02-size-10x64.webm
+b9c0e3b054463546356acf5157f9be92fd34732f *vp90-2-02-size-10x64.webm.md5
+2942879baf1c09e96b14d0fc84806abfe129c706 *vp90-2-02-size-10x66.webm
+bab5f539c2f91952e187456b4beafbb4c01e25ee *vp90-2-02-size-10x66.webm.md5
+88d2b63ca5e9ee163d8f20e8886f3df3ff301a66 *vp90-2-02-size-16x08.webm
+7f48a0fcf8c25963f3057d7f6669c5f2415834b8 *vp90-2-02-size-16x08.webm.md5
+59261eb34c15ea9b5ddd2d416215c1a8b9e6dc1f *vp90-2-02-size-16x10.webm
+73a7c209a46dd051c9f7339b6e02ccd5b3b9fc81 *vp90-2-02-size-16x10.webm.md5
+066834fef9cf5b9a72932cf4dea5f253e14a976d *vp90-2-02-size-16x16.webm
+faec542f52f37601cb9c480d887ae9355be99372 *vp90-2-02-size-16x16.webm.md5
+195307b4eb3192271ee4a935b0e48deef0c54cc2 *vp90-2-02-size-16x18.webm
+5a92e19e624c0376321d4d0e22c0c91995bc23e1 *vp90-2-02-size-16x18.webm.md5
+14f3f884216d7ae16ec521f024a2f2d31bbf9c1a *vp90-2-02-size-16x32.webm
+ea622d1c817dd174556f7ee7ccfe4942b34d4845 *vp90-2-02-size-16x32.webm.md5
+2e0501100578a5da9dd47e4beea160f945bdd1ba *vp90-2-02-size-16x34.webm
+1b8645ef64239334921c5f56b24ce815e6070b05 *vp90-2-02-size-16x34.webm.md5
+89a6797fbebebe93215f367229a9152277f5dcfe *vp90-2-02-size-16x64.webm
+a03d8c1179ca626a8856fb416d635dbf377979cd *vp90-2-02-size-16x64.webm.md5
+0f3a182e0750fcbae0b9eae80c7a53aabafdd18d *vp90-2-02-size-16x66.webm
+8cb6736dc2d897c1283919a32068af377d66c59c *vp90-2-02-size-16x66.webm.md5
+68fe70dc7914cc1d8d6dcd97388b79196ba3e7f1 *vp90-2-02-size-18x08.webm
+874c7fb505be9db3160c57cb405c4dbd5b990dc2 *vp90-2-02-size-18x08.webm.md5
+0546352dd78496d4dd86c3727ac2ff36c9e72032 *vp90-2-02-size-18x10.webm
+1d80eb36557ea5f25a386495a36f93da0f25316b *vp90-2-02-size-18x10.webm.md5
+60fe99e5f5cc99706efa3e0b894e45cbcf0d6330 *vp90-2-02-size-18x16.webm
+1ab6cdd89a53662995d103546e6611c84f9292ab *vp90-2-02-size-18x16.webm.md5
+f9a8f5fb749d69fd555db6ca093b7f77800c7b4f *vp90-2-02-size-18x18.webm
+ace8a66328f7802b15f9989c2720c029c6abd279 *vp90-2-02-size-18x18.webm.md5
+a197123a527ec25913a9bf52dc8c347749e00045 *vp90-2-02-size-18x32.webm
+34fbd7036752232d1663e70d7f7cdc93f7129202 *vp90-2-02-size-18x32.webm.md5
+f219655a639a774a2c9c0a9f45c28dc0b5e75e24 *vp90-2-02-size-18x34.webm
+2c4d622a9ea548791c1a07903d3702e9774388bb *vp90-2-02-size-18x34.webm.md5
+5308578da48c677d477a5404e19391d1303033c9 *vp90-2-02-size-18x64.webm
+e7fd4462527bac38559518ba80e41847db880f15 *vp90-2-02-size-18x64.webm.md5
+e109a7e013bd179f97e378542e1e81689ed06802 *vp90-2-02-size-18x66.webm
+45c04e422fb383c1f3be04beefaa4490e83bdb1a *vp90-2-02-size-18x66.webm.md5
+38844cae5d99caf445f7de33c3ae78494ce36c01 *vp90-2-02-size-32x08.webm
+ad018be39e493ca2405225034b1a5b7a42af6f3a *vp90-2-02-size-32x08.webm.md5
+7b57eaad55906f9de9903c8657a3fcb2aaf792ea *vp90-2-02-size-32x10.webm
+2294425d4e55d275af5e25a0beac9738a1b4ee73 *vp90-2-02-size-32x10.webm.md5
+f47ca2ced0d47f761bb0a5fdcd911d3f450fdcc1 *vp90-2-02-size-32x16.webm
+ae10981d93913f0ab1f28c1146255e01769aa8c0 *vp90-2-02-size-32x16.webm.md5
+08b23ad838b6cf1fbfe3ad7e7775d95573e815fc *vp90-2-02-size-32x18.webm
+1ba76f4c4a4ac7aabfa3ce195c1b473535eb7cc8 *vp90-2-02-size-32x18.webm.md5
+d5b88ae6c8c25c53dee74d9f1e6ca64244349a57 *vp90-2-02-size-32x32.webm
+e39c067a8ee2da52a51641eb1cb7f8eba935eb6b *vp90-2-02-size-32x32.webm.md5
+529429920dc36bd899059fa75a767f02c8c60874 *vp90-2-02-size-32x34.webm
+56888e7834f52b106e8911e3a7fc0f473b609995 *vp90-2-02-size-32x34.webm.md5
+38e848e160391c2b1a55040aadde613b9f4bf15e *vp90-2-02-size-32x64.webm
+8950485fb3f68b0e8be234db860e4ec5f5490fd0 *vp90-2-02-size-32x64.webm.md5
+5e8670f0b8ec9cefa8795b8959ffbe1a8e1aea94 *vp90-2-02-size-32x66.webm
+225df9d7d72ec711b0b60f4aeb65311c97db054a *vp90-2-02-size-32x66.webm.md5
+695f929e2ce6fb11a1f180322d46c5cb1c97fa61 *vp90-2-02-size-34x08.webm
+5bb4262030018dd01883965c6aa6070185924ef6 *vp90-2-02-size-34x08.webm.md5
+5adf74ec906d2ad3f7526e06bd29f5ad7d966a90 *vp90-2-02-size-34x10.webm
+71c100b437d3e8701632ae8d65c3555339b1c68f *vp90-2-02-size-34x10.webm.md5
+d0918923c987fba2d00193d83797b21289fe54aa *vp90-2-02-size-34x16.webm
+5d5a52f3535b4d2698dd3d87f4a13fdc9b57163d *vp90-2-02-size-34x16.webm.md5
+553ab0042cf87f5e668ec31b2e4b2a4b6ec196fd *vp90-2-02-size-34x18.webm
+a164c7f3c424987df2340496e6a8cf76e973f0f1 *vp90-2-02-size-34x18.webm.md5
+baf3e233634f150de81c18ba5d8848068e1c3c54 *vp90-2-02-size-34x32.webm
+22a79d3bd1c9b85dfe8c70bb2e19f08a92a8be03 *vp90-2-02-size-34x32.webm.md5
+6d50a533774a7167350e4a7ef43c94a5622179a2 *vp90-2-02-size-34x34.webm
+0c099638e79c273546523e06704553e42eb00b00 *vp90-2-02-size-34x34.webm.md5
+698cdd0a5e895cc202c488675e682a8c537ede4f *vp90-2-02-size-34x64.webm
+9317b63987cddab8389510a27b86f9f3d46e3fa5 *vp90-2-02-size-34x64.webm.md5
+4b5335ca06f082b6b69f584eb8e7886bdcafefd3 *vp90-2-02-size-34x66.webm
+e18d68b35428f46a84a947c646804a51ef1d7cec *vp90-2-02-size-34x66.webm.md5
+a54ae7b494906ec928a876e8290e5574f2f9f6a2 *vp90-2-02-size-64x08.webm
+87f9f7087b6489d45e9e4b38ede2c5aef4a4928f *vp90-2-02-size-64x08.webm.md5
+24522c70804a3c23d937df2d829ae63965b23f38 *vp90-2-02-size-64x10.webm
+447ce03938ab53bffcb4a841ee0bfaa90462dcb9 *vp90-2-02-size-64x10.webm.md5
+2a5035d035d214ae614af8051930690ef623989b *vp90-2-02-size-64x16.webm
+84e355761dd2e0361b904c84c52a0dd0384d89cf *vp90-2-02-size-64x16.webm.md5
+3a293ef4e270a19438e59b817fbe5f43eed4d36b *vp90-2-02-size-64x18.webm
+666824e5ba746779eb46079e0631853dcc86d48b *vp90-2-02-size-64x18.webm.md5
+ed32fae837095c9e8fc95d223ec68101812932c2 *vp90-2-02-size-64x32.webm
+97086eadedce1d0d9c072b585ba7b49aec69b1e7 *vp90-2-02-size-64x32.webm.md5
+696c7a7250bdfff594f4dfd88af34239092ecd00 *vp90-2-02-size-64x34.webm
+253a1d38d452e7826b086846c6f872f829c276bb *vp90-2-02-size-64x34.webm.md5
+fc508e0e3c2e6872c60919a60b812c5232e9c2b0 *vp90-2-02-size-64x64.webm
+2cd6ebeca0f82e9f505616825c07950371b905ab *vp90-2-02-size-64x64.webm.md5
+0f8a4fc1d6521187660425c283f08dff8c66e476 *vp90-2-02-size-64x66.webm
+5806be11a1d346be235f88d3683e69f73746166c *vp90-2-02-size-64x66.webm.md5
+273b0c36e3658685cde250408a478116d7ae92f1 *vp90-2-02-size-66x08.webm
+23c3cd0dca20a2f71f036e77ea92025ff4e7a298 *vp90-2-02-size-66x08.webm.md5
+4844c59c3306d1e671bb0568f00e344bf797e66e *vp90-2-02-size-66x10.webm
+e041eaf6841d775f8fde8bbb4949d2733fdaab7f *vp90-2-02-size-66x10.webm.md5
+bdf3f1582b234fcd2805ffec59f9d716a2345302 *vp90-2-02-size-66x16.webm
+2ec85ee18119e6798968571ea6e1b93ca386e3af *vp90-2-02-size-66x16.webm.md5
+0acce9af12b13b025d5274013da7ef6f568f075f *vp90-2-02-size-66x18.webm
+77c4d53e2a5c96b70af9d575fe6811e0f5ee627b *vp90-2-02-size-66x18.webm.md5
+682b36a25774bbdedcd603f504d18eb63f0167d4 *vp90-2-02-size-66x32.webm
+53728fae2a428f16d376a29f341a64ddca97996a *vp90-2-02-size-66x32.webm.md5
+e71b70e901e29eaa6672a6aa4f37f6f5faa02bd6 *vp90-2-02-size-66x34.webm
+f69a6a555e3f614b0a35f9bfc313d8ebb35bc725 *vp90-2-02-size-66x34.webm.md5
+4151b8c29452d5c2266397a7b9bf688899a2937b *vp90-2-02-size-66x64.webm
+69486e7fd9e380b6c97a03d3e167affc79f73840 *vp90-2-02-size-66x64.webm.md5
+68784a1ecac776fe2a3f230345af32f06f123536 *vp90-2-02-size-66x66.webm
+7f008c7f48d55e652fbd6bac405b51e0015c94f2 *vp90-2-02-size-66x66.webm.md5
+7e1bc449231ac1c5c2a11c9a6333b3e828763798 *vp90-2-03-size-196x196.webm
+6788a561466dace32d500194bf042e19cccc35e1 *vp90-2-03-size-196x196.webm.md5
+a170c9a88ec1dd854c7a471ff55fb2a97ac31870 *vp90-2-03-size-196x198.webm
+6bf9d6a8e2bdc5bf4f8a78071a3fed5ca02ad6f2 *vp90-2-03-size-196x198.webm.md5
+68f861d21c4c8b03d572c3d3fcd9f4fbf1f4503f *vp90-2-03-size-196x200.webm
+bbfc260b2bfd872cc6054272bb6b7f959a9e1c6e *vp90-2-03-size-196x200.webm.md5
+fc34889feeca2b7e5b27b4f1ce22d2e2b8e3e4b1 *vp90-2-03-size-196x202.webm
+158ee72af578f39aad0c3b8f4cbed2fc78b57e0f *vp90-2-03-size-196x202.webm.md5
+dd28fb7247af534bdf5e6795a3ac429610489a0b *vp90-2-03-size-196x208.webm
+7546be847efce2d1c0a23f807bfb03f91b764e1e *vp90-2-03-size-196x208.webm.md5
+41d5cf5ed65b722a1b6dc035e67f978ea8ffecf8 *vp90-2-03-size-196x210.webm
+9444fdf632d6a1b6143f4cb10fed8f63c1d67ec1 *vp90-2-03-size-196x210.webm.md5
+5007bc618143437c009d6dde5fc2e86f72d37dc2 *vp90-2-03-size-196x224.webm
+858361d8f79b44df5545feabbc9754ec9ede632f *vp90-2-03-size-196x224.webm.md5
+0bcbe357fbc776c3fa68e7117179574ed7564a44 *vp90-2-03-size-196x226.webm
+72006a5f42031a43d70a2cd9fc1958962a86628f *vp90-2-03-size-196x226.webm.md5
+000239f048cceaac055558e97ef07078ebf65502 *vp90-2-03-size-198x196.webm
+2d6841901b72000c5340f30be602853438c1b787 *vp90-2-03-size-198x196.webm.md5
+ae75b766306a6404c3b3b35a6b6d53633c14fbdb *vp90-2-03-size-198x198.webm
+3f2544b4f3b4b643a98f2c3b15ea5826fc702fa1 *vp90-2-03-size-198x198.webm.md5
+95ffd573fa84ccef1cd59e1583e6054f56a5c83d *vp90-2-03-size-198x200.webm
+5d537e3c9b9c54418c79677543454c4cda3de1af *vp90-2-03-size-198x200.webm.md5
+ecc845bf574375f469bc91bf5c75c79dc00073d6 *vp90-2-03-size-198x202.webm
+1b59f5e111265615a7a459eeda8cc9045178d228 *vp90-2-03-size-198x202.webm.md5
+432fb27144fe421b9f51cf44d2750a26133ed585 *vp90-2-03-size-198x208.webm
+a58a67f4fb357c73ca078aeecbc0f782975630b1 *vp90-2-03-size-198x208.webm.md5
+ff5058e7e6a47435046612afc8536f2040989e6f *vp90-2-03-size-198x210.webm
+18d3be7935e52217e2e9400b6f2c681a9e45dc89 *vp90-2-03-size-198x210.webm.md5
+a0d55263c1ed2c03817454dd4ec4090d36dbc864 *vp90-2-03-size-198x224.webm
+efa366a299817e2da51c00623b165aab9fbb8d91 *vp90-2-03-size-198x224.webm.md5
+ccd142fa2920fc85bb753f049160c1c353ad1574 *vp90-2-03-size-198x226.webm
+534524a0b2dbff852e0b92ef09939db072f83243 *vp90-2-03-size-198x226.webm.md5
+0d483b94ed40abc8ab6e49f960432ee54ad9c7f1 *vp90-2-03-size-200x196.webm
+41795f548181717906e7a504ba551f06c32102ae *vp90-2-03-size-200x196.webm.md5
+f6c2dc54e0989d50f01333fe40c91661fcbf849a *vp90-2-03-size-200x198.webm
+43df5d8c46a40089441392e6d096c588c1079a68 *vp90-2-03-size-200x198.webm.md5
+2f6e9df82e44fc145f0d9212dcccbed3de605e23 *vp90-2-03-size-200x200.webm
+757b2ef96b82093255725bab9690bbafe27f3caf *vp90-2-03-size-200x200.webm.md5
+40c5ea60415642a4a2e75c0d127b06309baadfab *vp90-2-03-size-200x202.webm
+3022c4a1c625b5dc04fdb1052d17d45b4171cfba *vp90-2-03-size-200x202.webm.md5
+6942ed5b27476bb8506d10e600d6ff60887780ca *vp90-2-03-size-200x208.webm
+c4ab8c66f3cf2dc8e8dd7abae9ac21f4d32cd6be *vp90-2-03-size-200x208.webm.md5
+71dbc99b83c49d1da45589b91eabb98e2f4a7b1e *vp90-2-03-size-200x210.webm
+3f0b40da7eef7974b9bc326562f251feb67d9c7c *vp90-2-03-size-200x210.webm.md5
+6b6b8489081cfefb377cc5f18eb754ec2383f655 *vp90-2-03-size-200x224.webm
+a259df2ac0e294492e3f9d4315baa34cab044f04 *vp90-2-03-size-200x224.webm.md5
+c9adc1c9bb07559349a0b054df4af56f7a6edbb9 *vp90-2-03-size-200x226.webm
+714cec61e3575581e4f1a0e3921f4dfdbbd316c5 *vp90-2-03-size-200x226.webm.md5
+f9bdc936bdf53f8be9ce78fecd41a21d31ff3943 *vp90-2-03-size-202x196.webm
+5b8e2e50fcea2c43b12fc067b8a9cc117af77bda *vp90-2-03-size-202x196.webm.md5
+c7b66ea3da87613deb47ff24a111247d3c384fec *vp90-2-03-size-202x198.webm
+517e91204b25586da943556f4adc5951c9be8bee *vp90-2-03-size-202x198.webm.md5
+935ef56b01cfdb4265a7e24696645209ccb20970 *vp90-2-03-size-202x200.webm
+55b8ec4a2513183144a8e27564596c06c7576fce *vp90-2-03-size-202x200.webm.md5
+849acf75e4f1d8d90046704e1103a18c64f30e35 *vp90-2-03-size-202x202.webm
+c79afc6660df2824e7df314e5bfd71f0d8acf76b *vp90-2-03-size-202x202.webm.md5
+17b3a4d55576b770626ccb856b9f1a6c8f6ae476 *vp90-2-03-size-202x208.webm
+0b887ff30409c58f2ccdc3bfacd6be7c69f8997a *vp90-2-03-size-202x208.webm.md5
+032d0ade4230fb2eef6d19915a7a1c9aa4a52617 *vp90-2-03-size-202x210.webm
+f78f8e79533c0c88dd2bfdcec9b1c07848568ece *vp90-2-03-size-202x210.webm.md5
+915a38c31fe425d5b93c837121cfa8082f5ea5bc *vp90-2-03-size-202x224.webm
+bf52a104074d0c5942aa7a5b31e11db47e43d48e *vp90-2-03-size-202x224.webm.md5
+be5cfde35666fa435e47d544d9258215beb1cf29 *vp90-2-03-size-202x226.webm
+2fa2f87502fda756b319389c8975204e130a2e3f *vp90-2-03-size-202x226.webm.md5
+15d908e97862b5b4bf295610df011fb9aa09909b *vp90-2-03-size-208x196.webm
+50c60792305d6a99be376dd596a6ff979325e6cc *vp90-2-03-size-208x196.webm.md5
+a367c7bc9fde56d6f4848cc573c7d4c1ce75e348 *vp90-2-03-size-208x198.webm
+be85fb2c8d435a75484231356f07d06ebddd13cd *vp90-2-03-size-208x198.webm.md5
+05fd46deb7288e7253742091f56e54a9a441a187 *vp90-2-03-size-208x200.webm
+74f8ec3b3a2fe81767ed1ab36a47bc0062d6223c *vp90-2-03-size-208x200.webm.md5
+d8985c4b386513a7385a4b3639bf91e469f1378b *vp90-2-03-size-208x202.webm
+0614a1e8d92048852adcf605a51333f5fabc7f03 *vp90-2-03-size-208x202.webm.md5
+28b002242238479165ba4fb87ee6b442c64b32e4 *vp90-2-03-size-208x208.webm
+37de5aca59bb900228400b0e115d3229edb9dcc0 *vp90-2-03-size-208x208.webm.md5
+c545be0050c2fad7c68427dbf86c62a739e94ab3 *vp90-2-03-size-208x210.webm
+d646eccb3cd578f94b54777e32b88898bef6e17a *vp90-2-03-size-208x210.webm.md5
+63a0cfe295b661026dd7b1bebb67acace1db766f *vp90-2-03-size-208x224.webm
+85c0361d93bf85a335248fef2767ff43eeef23db *vp90-2-03-size-208x224.webm.md5
+f911cc718d66e4fe8a865226088939c9eb1b7825 *vp90-2-03-size-208x226.webm
+a6d583a57876e7b7ec48625b2b2cdbcf70cab837 *vp90-2-03-size-208x226.webm.md5
+5bbb0f36da9a4683cf04e724124d8696332911bf *vp90-2-03-size-210x196.webm
+a3580fc7816d7fbcfb54fdba501cabbd06ba2f1d *vp90-2-03-size-210x196.webm.md5
+8db64d6f9ce36dd382013b42ae4e292deba697bc *vp90-2-03-size-210x198.webm
+eda20f8268c7f4147bead4059e9c4897e09140a9 *vp90-2-03-size-210x198.webm.md5
+ce391505eeaf1d12406563101cd6b2dbbbb44bfc *vp90-2-03-size-210x200.webm
+79d73b7f623082d2a00aa33e95c79d11c7d9c3a8 *vp90-2-03-size-210x200.webm.md5
+852db6fdc206e72391fc69b807f1954934679949 *vp90-2-03-size-210x202.webm
+f69414c5677ed2f2b8b37ae76429e509a92276a5 *vp90-2-03-size-210x202.webm.md5
+c424cc3edd2308da7d33f27acb36b54db5bf2595 *vp90-2-03-size-210x208.webm
+27b18562faa1b3184256f4eae8114b539b3e9d3e *vp90-2-03-size-210x208.webm.md5
+dd029eba719d50a2851592fa8b9b2efe88904930 *vp90-2-03-size-210x210.webm
+c853a1670465eaa04ca31b3511995f1b6ed4f58f *vp90-2-03-size-210x210.webm.md5
+d962e8ae676c54d0c3ea04ec7c04b37ae6a786e3 *vp90-2-03-size-210x224.webm
+93b793e79d987065b39ad8e2e71244368435fc25 *vp90-2-03-size-210x224.webm.md5
+3d0825fe83bcc125be1f78145ff43ca6d7588784 *vp90-2-03-size-210x226.webm
+5230f31a57ca3b5311698a12035d2644533b3ec4 *vp90-2-03-size-210x226.webm.md5
+6622f8bd9279e1ce45509a58a31a990052d45e14 *vp90-2-03-size-224x196.webm
+65411da07f60113f2be05c807879072b161d561e *vp90-2-03-size-224x196.webm.md5
+6744ff2ee2c41eb08c62ff30880833b6d77b585b *vp90-2-03-size-224x198.webm
+46ea3641d41acd4bff347b224646c060d5620385 *vp90-2-03-size-224x198.webm.md5
+8eb91f3416a1404705f370caecd74b2b458351b1 *vp90-2-03-size-224x200.webm
+196aefb854c8b95b9330263d6690b7ee15693ecf *vp90-2-03-size-224x200.webm.md5
+256a5a23ef4e6d5ef2871af5afb8cd13d28cec00 *vp90-2-03-size-224x202.webm
+840ad8455dcf2be378c14b007e66fa642fc8196d *vp90-2-03-size-224x202.webm.md5
+db4606480ab48b96c9a6ff5e639f1f1aea2a12e4 *vp90-2-03-size-224x208.webm
+40b9801d5620467499ac70fa6b7c40aaa5e1c331 *vp90-2-03-size-224x208.webm.md5
+e37159e687fe1cb24cffddfae059301adbaf4212 *vp90-2-03-size-224x210.webm
+1e4acd4b6334ae260c3eed08652d0ba8122073f2 *vp90-2-03-size-224x210.webm.md5
+0de1eb4bb6285ae621e4f2b613d2aa4a8c95a130 *vp90-2-03-size-224x224.webm
+37db449ad86fb286c2c02d94aa8fe0379c05044a *vp90-2-03-size-224x224.webm.md5
+32ebbf903a7d7881bcfe59639f1d472371f3bf27 *vp90-2-03-size-224x226.webm
+5cc3ac5dc9f6912491aa2ddac863f8187f34c569 *vp90-2-03-size-224x226.webm.md5
+9480ff5c2c32b1870ac760c87514912616e6cf01 *vp90-2-03-size-226x196.webm
+fe83655c0f1888f0af7b047785f01ba7ca9f1324 *vp90-2-03-size-226x196.webm.md5
+09cad4221996315cdddad4e502dbfabf53ca1d6a *vp90-2-03-size-226x198.webm
+e3ddfdc650acb95adb45abd9b634e1f09ea8ac96 *vp90-2-03-size-226x198.webm.md5
+c34f49d55fe39e3f0b607e3cc95e30244225cecb *vp90-2-03-size-226x200.webm
+abb83edc868a3523ccd4e5523fac2efbe7c3df1f *vp90-2-03-size-226x200.webm.md5
+d17bc08eedfc60c4c23d576a6c964a21bf854d1f *vp90-2-03-size-226x202.webm
+1d22d2d0f375251c2d5a1acb4714bc35d963865b *vp90-2-03-size-226x202.webm.md5
+9bd537c4f92a25596ccd29fedfe181feac948b92 *vp90-2-03-size-226x208.webm
+6feb0e7325386275719f3511ada9e248a2ae7df4 *vp90-2-03-size-226x208.webm.md5
+4487067f6cedd495b93696b44b37fe0a3e7eda14 *vp90-2-03-size-226x210.webm
+49a8fa87945f47208168d541c068e78d878075d5 *vp90-2-03-size-226x210.webm.md5
+559fea2f8da42b33c1aa1dbc34d1d6781009847a *vp90-2-03-size-226x224.webm
+83c6d8f2969b759e10e5c6542baca1265c874c29 *vp90-2-03-size-226x224.webm.md5
+fe0af2ee47b1e5f6a66db369e2d7e9d870b38dce *vp90-2-03-size-226x226.webm
+94ad19b8b699cea105e2ff18f0df2afd7242bcf7 *vp90-2-03-size-226x226.webm.md5
+52bc1dfd3a97b24d922eb8a31d07527891561f2a *vp90-2-03-size-352x288.webm
+3084d6d0a1eec22e85a394422fbc8faae58930a5 *vp90-2-03-size-352x288.webm.md5
+b6524e4084d15b5d0caaa3d3d1368db30cbee69c *vp90-2-03-deltaq.webm
+65f45ec9a55537aac76104818278e0978f94a678 *vp90-2-03-deltaq.webm.md5
+4dbb87494c7f565ffc266c98d17d0d8c7a5c5aba *vp90-2-05-resize.ivf
+7f6d8879336239a43dbb6c9f13178cb11cf7ed09 *vp90-2-05-resize.ivf.md5
+bf61ddc1f716eba58d4c9837d4e91031d9ce4ffe *vp90-2-06-bilinear.webm
+f6235f937552e11d8eb331ec55da6b3aa596b9ac *vp90-2-06-bilinear.webm.md5
+0c83a1e414fde3bccd6dc451bbaee68e59974c76 *vp90-2-07-frame_parallel.webm
+e5c2c9fb383e5bf3b563480adaeba5b7e3475ecd *vp90-2-07-frame_parallel.webm.md5
+086c7edcffd699ae7d99d710fd7e53b18910ca5b *vp90-2-08-tile_1x2_frame_parallel.webm
+e981ecaabb29a80e0cbc1f4002384965ce8e95bb *vp90-2-08-tile_1x2_frame_parallel.webm.md5
+ed79be026a6f28646c5825da1c12d1fbc70f96a4 *vp90-2-08-tile_1x2.webm
+45b404e025841c9750895fc1a9f6bd384fe6a315 *vp90-2-08-tile_1x2.webm.md5
+cf8ea970c776797aae71dac8317ea926d9431cab *vp90-2-08-tile_1x4_frame_parallel.webm
+a481fbea465010b57af5a19ebf6d4a5cfe5b9278 *vp90-2-08-tile_1x4_frame_parallel.webm.md5
+0203ec456277a01aec401e7fb6c72c9a7e5e3f9d *vp90-2-08-tile_1x4.webm
+c9b237dfcc01c1b414fbcaa481d014a906ef7998 *vp90-2-08-tile_1x4.webm.md5
+20c75157e91ab41f82f70ffa73d5d01df8469287 *vp90-2-08-tile-4x4.webm
+ae7451810247fd13975cc257aa0301ff17102255 *vp90-2-08-tile-4x4.webm.md5
+2ec6e15422ac7a61af072dc5f27fcaf1942ce116 *vp90-2-08-tile-4x1.webm
+0094f5ee5e46345017c30e0aa4835b550212d853 *vp90-2-08-tile-4x1.webm.md5
+edea45dac4a3c2e5372339f8851d24c9bef803d6 *vp90-2-09-subpixel-00.ivf
+5428efc4bf92191faedf4a727fcd1d94966a7abc *vp90-2-09-subpixel-00.ivf.md5
+8cdd435d89029987ee196896e21520e5f879f04d *vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm
+091b373aa2ecb59aa5c647affd5bcafcc7547364 *vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm
+87ee28032b0963a44b73a850fcc816a6dc83efbb *vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm
+c6ce25c4bfd4bdfc2932b70428e3dfe11210ec4f *vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm
+2064bdb22aa71c2691e0469fb62e8087a43f08f8 *vp90-2-bbb_426x240_tile_1x1_180kbps.webm
+8080eda22694910162f0996e8a962612f381a57f *vp90-2-bbb_640x360_tile_1x2_337kbps.webm
+a484b335c27ea189c0f0d77babea4a510ce12d50 *vp90-2-bbb_854x480_tile_1x2_651kbps.webm
+3eacf1f006250be4cc5c92a7ef146e385ee62653 *vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm
+217f089a16447490823127b36ce0d945522accfd *vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm
+eedb3c641e60dacbe082491a16df529a5c9187df *vp90-2-sintel_426x182_tile_1x1_171kbps.webm
+cb7e4955af183dff33bcba0c837f0922ab066400 *vp90-2-sintel_640x272_tile_1x2_318kbps.webm
+48613f9380e2580002f8a09d6e412ea4e89a52b9 *vp90-2-sintel_854x364_tile_1x2_621kbps.webm
+990a91f24dd284562d21d714ae773dff5452cad8 *vp90-2-tos_1280x534_tile_1x4_1306kbps.webm
+aa402217577a659cfc670157735b4b8e9aa670fe *vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm
+b6dd558c90bca466b4bcbd03b3371648186465a7 *vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm
+1a9c2914ba932a38f0a143efc1ad0e318e78888b *vp90-2-tos_426x178_tile_1x1_181kbps.webm
+a3d2b09f24debad4747a1b3066f572be4273bced *vp90-2-tos_640x266_tile_1x2_336kbps.webm
+c64b03b5c090e6888cb39685c31f00a6b79fa45c *vp90-2-tos_854x356_tile_1x2_656kbps.webm
+94b533dbcf94292001e27cc51fec87f9e8c90c0b *vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm
+0e7cd4135b231c9cea8d76c19f9e84b6fd77acec *vp90-2-08-tile_1x8_frame_parallel.webm
+c9b6850af28579b031791066457f4cb40df6e1c7 *vp90-2-08-tile_1x8_frame_parallel.webm.md5
+e448b6e83490bca0f8d58b4f4b1126a17baf4b0c *vp90-2-08-tile_1x8.webm
+5e524165f0397e6141d914f4f0a66267d7658376 *vp90-2-08-tile_1x8.webm.md5
+a34e14923d6d17b1144254d8187d7f85b700a63c *vp90-2-02-size-lf-1920x1080.webm
+e3b28ddcfaeb37fb4d132b93f92642a9ad17c22d *vp90-2-02-size-lf-1920x1080.webm.md5
+d48c5db1b0f8e60521a7c749696b8067886033a3 *vp90-2-09-aq2.webm
+84c1599298aac78f2fc05ae2274575d10569dfa0 *vp90-2-09-aq2.webm.md5
+55fc55ed73d578ed60fad05692579873f8bad758 *vp90-2-09-lf_deltas.webm
+54638c38009198c38c8f3b25c182b709b6c1fd2e *vp90-2-09-lf_deltas.webm.md5
+510d95f3beb3b51c572611fdaeeece12277dac30 *vp90-2-10-show-existing-frame.webm
+14d631096f4bfa2d71f7f739aec1448fb3c33bad *vp90-2-10-show-existing-frame.webm.md5
+d2feea7728e8d2c615981d0f47427a4a5a45d881 *vp90-2-10-show-existing-frame2.webm
+5f7c7811baa3e4f03be1dd78c33971b727846821 *vp90-2-10-show-existing-frame2.webm.md5
+b4318e75f73a6a08992c7326de2fb589c2a794c7 *vp90-2-11-size-351x287.webm
+b3c48382cf7d0454e83a02497c229d27720f9e20 *vp90-2-11-size-351x287.webm.md5
+8e0096475ea2535bac71d3e2fc09e0c451c444df *vp90-2-11-size-351x288.webm
+19e003804ec1dfc5464813b32339a15d5ba7b42f *vp90-2-11-size-351x288.webm.md5
+40cd1d6a188d7a88b21ebac1e573d3f270ab261e *vp90-2-11-size-352x287.webm
+68f515abe3858fc1eded46c8e6b2f727d43b5331 *vp90-2-11-size-352x287.webm.md5
+9a510769ff23db410880ec3029d433e87d17f7fc *vp90-2-12-droppable_1.ivf
+952eaac6eefa6f62179ed1db3e922fd42fecc624 *vp90-2-12-droppable_1.ivf.md5
+9a510769ff23db410880ec3029d433e87d17f7fc *vp90-2-12-droppable_2.ivf
+92a756469fa438220524e7fa6ac1d38c89514d17 *vp90-2-12-droppable_2.ivf.md5
+c21e97e4ba486520118d78b01a5cb6e6dc33e190 *vp90-2-12-droppable_3.ivf
+601abc9e4176c70f82ac0381365e9b151fdd24cd *vp90-2-12-droppable_3.ivf.md5
+61c640dad23cd4f7ad811b867e7b7e3521f4e3ba *vp90-2-13-largescaling.webm
+bca1b02eebdb088fa3f389fe0e7571e75a71f523 *vp90-2-13-largescaling.webm.md5
+c740708fa390806eebaf669909c1285ab464f886 *vp90-2-14-resize-fp-tiles-1-2.webm
+c7b85ffd8e11500f73f52e7dc5a47f57c393d47f *vp90-2-14-resize-fp-tiles-1-2.webm.md5
+ec8faa352a08f7033c60f29f80d505e2d7daa103 *vp90-2-14-resize-fp-tiles-1-4.webm
+6852c783fb421bda5ded3d4c5a3ffc46de03fbc1 *vp90-2-14-resize-fp-tiles-1-4.webm.md5
+8af61853ac0d07c4cb5bf7c2016661ba350b3497 *vp90-2-14-resize-fp-tiles-1-8.webm
+571353bac89fea60b5706073409aa3c0d42aefe9 *vp90-2-14-resize-fp-tiles-1-8.webm.md5
+b1c187ed69931496b82ec194017a79831bafceef *vp90-2-14-resize-fp-tiles-1-16.webm
+1c199a41afe42ce303944d70089eaaa2263b4a09 *vp90-2-14-resize-fp-tiles-1-16.webm.md5
+8eaae5a6f2dff934610b0c7a917d7f583ba74aa5 *vp90-2-14-resize-fp-tiles-2-1.webm
+db18fcf915f7ffaea6c39feab8bda6c1688af011 *vp90-2-14-resize-fp-tiles-2-1.webm.md5
+bc3046d138941e2a20e9ceec0ff6d25c25d12af3 *vp90-2-14-resize-fp-tiles-4-1.webm
+393211b808030d09a79927b17a4374b2f68a60ae *vp90-2-14-resize-fp-tiles-4-1.webm.md5
+6e8f8e31721a0f7f68a2964e36e0e698c2e276b1 *vp90-2-14-resize-fp-tiles-8-1.webm
+491fd3cd78fb0577bfe905bb64bbf64bd7d29140 *vp90-2-14-resize-fp-tiles-8-1.webm.md5
+cc5958da2a7edf739cd2cfeb18bd05e77903087e *vp90-2-14-resize-fp-tiles-16-1.webm
+0b58daf55aaf9063bf5b4fb33393d18b417dc428 *vp90-2-14-resize-fp-tiles-16-1.webm.md5
+821eeecc9d8c6a316134dd42d1ff057787d8047b *vp90-2-14-resize-fp-tiles-2-4.webm
+374c549f2839a3d0b732c4e3650700144037e76c *vp90-2-14-resize-fp-tiles-2-4.webm.md5
+dff8c8e49aacea9f4c7f22cb882da984e2a1b405 *vp90-2-14-resize-fp-tiles-2-8.webm
+e5b8820a7c823b21297d6e889e57ec401882c210 *vp90-2-14-resize-fp-tiles-2-8.webm.md5
+77629e4b23e32896aadf6e994c78bd4ffa1c7797 *vp90-2-14-resize-fp-tiles-2-16.webm
+1937f5df032664ac345d4613ad4417b4967b1230 *vp90-2-14-resize-fp-tiles-2-16.webm.md5
+380ba5702bb1ec7947697314ab0300b5c56a1665 *vp90-2-14-resize-fp-tiles-4-2.webm
+fde7b30d2aa64c1e851a4852f655d79fc542cf66 *vp90-2-14-resize-fp-tiles-4-2.webm.md5
+dc784b258ffa2abc2ae693d11792acf0bb9cb74f *vp90-2-14-resize-fp-tiles-8-2.webm
+edf26f0130aeee8342d49c2c8f0793ad008782d9 *vp90-2-14-resize-fp-tiles-8-2.webm.md5
+8e575789fd63ebf69e8eff1b9a4351a249a73bee *vp90-2-14-resize-fp-tiles-16-2.webm
+b6415318c1c589a1f64b9d569ce3cabbec2e0d52 *vp90-2-14-resize-fp-tiles-16-2.webm.md5
+e3adc944a11c4c5517e63664c84ebb0847b64d81 *vp90-2-14-resize-fp-tiles-4-8.webm
+03cba0532bc90a05b1990db830bf5701e24e7982 *vp90-2-14-resize-fp-tiles-4-8.webm.md5
+3b27a991eb6d78dce38efab35b7db682e8cbbee3 *vp90-2-14-resize-fp-tiles-4-16.webm
+5d16b7f82bf59f802724ddfd97abb487150b1c9d *vp90-2-14-resize-fp-tiles-4-16.webm.md5
+d5fed8c28c1d4c7e232ebbd25cf758757313ed96 *vp90-2-14-resize-fp-tiles-8-4.webm
+5a8ff8a52cbbde7bfab569beb6d971c5f8b904f7 *vp90-2-14-resize-fp-tiles-8-4.webm.md5
+17a5faa023d77ee9dad423a4e0d3145796bbc500 *vp90-2-14-resize-fp-tiles-16-4.webm
+2ef8daa3c3e750fd745130d0a76a39fe86f0448f *vp90-2-14-resize-fp-tiles-16-4.webm.md5
+9361e031f5cc990d8740863e310abb5167ae351e *vp90-2-14-resize-fp-tiles-8-16.webm
+57f13a2197486584f4e1a4f82ad969f3abc5a1a2 *vp90-2-14-resize-fp-tiles-8-16.webm.md5
+5803fc6fcbfb47b7661f3fcc6499158a32b56675 *vp90-2-14-resize-fp-tiles-16-8.webm
+be0fe64a1a4933696ff92d93f9bdecdbd886dc13 *vp90-2-14-resize-fp-tiles-16-8.webm.md5
+0ac0f6d20a0afed77f742a3b9acb59fd7b9cb093 *vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm
+1765315acccfe6cd12230e731369fcb15325ebfa *vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm.md5
+4a2b7a683576fe8e330c7d1c4f098ff4e70a43a8 *vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm
+1ef480392112b3509cb190afbb96f9a38dd9fbac *vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm.md5
+e615575ded499ea1d992f3b38e3baa434509cdcd *vp90-2-15-segkey.webm
+e3ab35d4316c5e81325c50f5236ceca4bc0d35df *vp90-2-15-segkey.webm.md5
+9b7ca2cac09d34c4a5d296c1900f93b1e2f69d0d *vp90-2-15-segkey_adpq.webm
+8f46ba5f785d0c2170591a153e0d0d146a7c8090 *vp90-2-15-segkey_adpq.webm.md5
+698a6910a97486b833073ef0c0b18d75dce57ee8 *vp90-2-16-intra-only.webm
+5661b0168752969f055eec37b05fa9fa947dc7eb *vp90-2-16-intra-only.webm.md5
+c01bb7938f9a9f25e0c37afdec2f2fb73b6cc7fa *vp90-2-17-show-existing-frame.webm
+cc75f351818b9a619818f5cc77b9bc013d0c1e11 *vp90-2-17-show-existing-frame.webm.md5
+013708bd043f0821a3e56fb8404d82e7a0c7af6c *vp91-2-04-yuv422.webm
+1e58a7d23adad830a672f1733c9d2ae17890d59c *vp91-2-04-yuv422.webm.md5
+25d78f28948789d159a9453ebc13048b818251b1 *vp91-2-04-yuv440.webm
+81b3870b27a7f695ef6a43e87ab04bbdb5aee2f5 *vp91-2-04-yuv440.webm.md5
+0321d507ce62dedc8a51b4e9011f7a19aed9c3dc *vp91-2-04-yuv444.webm
+367e423dd41fdb49aa028574a2cfec5c2f325c5c *vp91-2-04-yuv444.webm.md5
+f77673b566f686853adefe0c578ad251b7241281 *vp92-2-20-10bit-yuv420.webm
+abdedfaddacbbe1a15ac7a54e86360f03629fb7a *vp92-2-20-10bit-yuv420.webm.md5
+0c2c355a1b17b28537c5a3b19997c8783b69f1af *vp92-2-20-12bit-yuv420.webm
+afb2c2798703e039189b0a15c8ac5685aa51d33f *vp92-2-20-12bit-yuv420.webm.md5
+0d661bc6e83da33238981481efd1b1802d323d88 *vp93-2-20-10bit-yuv422.webm
+10318907063db22eb02fad332556edbbecd443cc *vp93-2-20-10bit-yuv422.webm.md5
+ebc6be2f7511a0bdeac0b18c67f84ba7168839c7 *vp93-2-20-12bit-yuv422.webm
+235232267c6a1dc8a11e45d600f1c99d2f8b42d4 *vp93-2-20-12bit-yuv422.webm.md5
+f76b11b26d4beaceac7a7e7729dd5054d095164f *vp93-2-20-10bit-yuv440.webm
+757b33b5ac969c5999999488a731a3d1e6d9fb88 *vp93-2-20-10bit-yuv440.webm.md5
+df8807dbd29bec795c2db9c3c18e511fbb988101 *vp93-2-20-12bit-yuv440.webm
+ea4100930c3f59a1c23fbb33ab0ea01151cae159 *vp93-2-20-12bit-yuv440.webm.md5
+189c1b5f404ff41a50a7fc96341085ad541314a9 *vp93-2-20-10bit-yuv444.webm
+2dd0177c2f9d970b6e698892634c653630f91f40 *vp93-2-20-10bit-yuv444.webm.md5
+bd44cf6e1c27343e3639df9ac21346aedd5d6973 *vp93-2-20-12bit-yuv444.webm
+f36e5bdf5ec3213f32c0ddc82f95d82c5133bf27 *vp93-2-20-12bit-yuv444.webm.md5
+eb438c6540eb429f74404eedfa3228d409c57874 *desktop_640_360_30.yuv
+89e70ebd22c27d275fe14dc2f1a41841a6d8b9ab *kirland_640_480_30.yuv
+33c533192759e5bb4f07abfbac389dc259db4686 *macmarcomoving_640_480_30.yuv
+8bfaab121080821b8f03b23467911e59ec59b8fe *macmarcostationary_640_480_30.yuv
+70894878d916a599842d9ad0dcd24e10c13e5467 *niklas_640_480_30.yuv
+8784b6df2d8cc946195a90ac00540500d2e522e4 *tacomanarrows_640_480_30.yuv
+edd86a1f5e62fd9da9a9d46078247759c2638009 *tacomasmallcameramovement_640_480_30.yuv
+9a70e8b7d14fba9234d0e51dce876635413ce444 *thaloundeskmtg_640_480_30.yuv
+e7d315dbf4f3928779e0dc624311196d44491d32 *niklas_1280_720_30.yuv
+c77e4a26616add298a05dd5d12397be22c0e40c5 *vp90-2-18-resize.ivf
+c12918cf0a716417fba2de35c3fc5ab90e52dfce *vp90-2-18-resize.ivf.md5
+717da707afcaa1f692ff1946f291054eb75a4f06 *screendata.y4m
+b7c1296630cdf1a7ef493d15ff4f9eb2999202f6 *invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf
+0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf.res
+359e138dfb66863828397b77000ea7a83c844d02 *invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf
+bbd33de01c17b165b4ce00308e8a19a942023ab8 *invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf.res
+fac89b5735be8a86b0dc05159f996a5c3208ae32 *invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf
+0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf.res
+4506dfdcdf8ee4250924b075a0dcf1f070f72e5a *invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf
+bcdedaf168ac225575468fda77502d2dc9fd5baa *invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf.res
+65e93f9653bcf65b022f7d225268d1a90a76e7bb *vp90-2-19-skip.webm
+368dccdde5288c13c25695d2eacdc7402cadf613 *vp90-2-19-skip.webm.md5
+ffe460282df2b0e7d4603c2158653ad96f574b02 *vp90-2-19-skip-01.webm
+bd21bc9eda4a4a36b221d71ede3a139fc3c7bd85 *vp90-2-19-skip-01.webm.md5
+178f5bd239e38cc1cc2657a7a5e1a9f52ad2d3fe *vp90-2-19-skip-02.webm
+9020d5e260bd7df08e2b3d4b86f8623cee3daea2 *vp90-2-19-skip-02.webm.md5
+b03c408cf23158638da18dbc3323b99a1635c68a *invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf
+0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf.res
+5e67e24e7f53fd189e565513cef8519b1bd6c712 *invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf
+741158f67c0d9d23726624d06bdc482ad368afc9 *invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf.res
+8b1f7bf7e86c0976d277f60e8fcd9539e75a079a *invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf
+9c6bdf048fb2e66f07d4b4db5b32e6f303bd6109 *invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf.res
+552e372e9b78127389fb06b34545df2cec15ba6d *invalid-vp91-2-mixedrefcsp-444to420.ivf
+a61774cf03fc584bd9f0904fc145253bb8ea6c4c *invalid-vp91-2-mixedrefcsp-444to420.ivf.res
+812d05a64a0d83c1b504d0519927ddc5a2cdb273 *invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf
+1e472baaf5f6113459f0399a38a5a5e68d17799d *invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf.res
+f97088c7359fc8d3d5aa5eafe57bc7308b3ee124 *vp90-2-20-big_superframe-01.webm
+47d7d409785afa33b123376de0c907336e6c7bd7 *vp90-2-20-big_superframe-01.webm.md5
+65ade6d2786209582c50d34cfe22b3cdb033abaf *vp90-2-20-big_superframe-02.webm
+7c0ed8d04c4d06c5411dd2e5de2411d37f092db5 *vp90-2-20-big_superframe-02.webm.md5
+667ec8718c982aef6be07eb94f083c2efb9d2d16 *vp90-2-07-frame_parallel-1.webm
+bfc82bf848e9c05020d61e3ffc1e62f25df81d19 *vp90-2-07-frame_parallel-1.webm.md5
+efd5a51d175cfdacd169ed23477729dc558030dc *invalid-vp90-2-07-frame_parallel-1.webm
+9f912712ec418be69adb910e2ca886a63c4cec08 *invalid-vp90-2-07-frame_parallel-2.webm
+445f5a53ca9555341852997ccdd480a51540bd14 *invalid-vp90-2-07-frame_parallel-3.webm
+d18c90709a0d03c82beadf10898b27d88fff719c *invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf
+d06285d109ecbaef63b0cbcc44d70a129186f51c *invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res
+e60d859b0ef2b331b21740cf6cb83fabe469b079 *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf
+0ae808dca4d3c1152a9576e14830b6faa39f1b4a *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res
+9cfc855459e7549fd015c79e8eca512b2f2cb7e3 *niklas_1280_720_30.y4m
+5b5763b388b1b52a81bb82b39f7ec25c4bd3d0e1 *desktop_credits.y4m
+85771f6ab44e4a0226e206c0cde8351dd5918953 *vp90-2-02-size-130x132.webm
+512dad5eabbed37b4bbbc64ce153f1a5484427b8 *vp90-2-02-size-130x132.webm.md5
+01f7127d40360289db63b27f61cb9afcda350e95 *vp90-2-02-size-132x130.webm
+4a94275328ae076cf60f966c097a8721010fbf5a *vp90-2-02-size-132x130.webm.md5
+f41c0400b5716b4b70552c40dd03d44be131e1cc *vp90-2-02-size-132x132.webm
+1a69e989f697e424bfe3e3e8a77bb0c0992c8e47 *vp90-2-02-size-132x132.webm.md5
+94a5cbfacacba100e0c5f7861c72a1b417feca0f *vp90-2-02-size-178x180.webm
+dedfecf1d784bcf70629592fa5e6f01d5441ccc9 *vp90-2-02-size-178x180.webm.md5
+4828b62478c04014bba3095a83106911a71cf387 *vp90-2-02-size-180x178.webm
+423da2b861050c969d78ed8e8f8f14045d1d8199 *vp90-2-02-size-180x178.webm.md5
+338f7c9282f43e29940f5391118aadd17e4f9234 *vp90-2-02-size-180x180.webm
+6c2ef013392310778dca5dd5351160eca66b0a60 *vp90-2-02-size-180x180.webm.md5
+679fa7d6807e936ff937d7b282e7dbd8ac76447e *vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm
+fc7267ab8fc2bf5d6c234e34ee6c078a967b4888 *vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm.md5
+9d33a137c819792209c5ce4e4e1ee5da73d574fe *vp90-2-14-resize-10frames-fp-tiles-1-2.webm
+0c78a154956a8605d050bdd75e0dcc4d39c040a6 *vp90-2-14-resize-10frames-fp-tiles-1-2.webm.md5
+d6a8d8c57f66a91d23e8e7df480f9ae841e56c37 *vp90-2-14-resize-10frames-fp-tiles-1-4.webm
+e9b4e8c7b33b5fda745d340c3f47e6623ae40cf2 *vp90-2-14-resize-10frames-fp-tiles-1-4.webm.md5
+aa6fe043a0c4a42b49c87ebbe812d4afd9945bec *vp90-2-14-resize-10frames-fp-tiles-1-8.webm
+028520578994c2d013d4c0129033d4f2ff31bbe0 *vp90-2-14-resize-10frames-fp-tiles-1-8.webm.md5
+d1d5463c9ea7b5cc5f609ddedccddf656f348d1a *vp90-2-14-resize-10frames-fp-tiles-2-1.webm
+92d5872f5bdffbed721703b7e959b4f885e3d77a *vp90-2-14-resize-10frames-fp-tiles-2-1.webm.md5
+677cb29de1215d97346015af5807a9b1faad54cf *vp90-2-14-resize-10frames-fp-tiles-2-4.webm
+a5db19f977094ec3fd60b4f7671b3e6740225e12 *vp90-2-14-resize-10frames-fp-tiles-2-4.webm.md5
+cdd3c52ba21067efdbb2de917fe2a965bf27332e *vp90-2-14-resize-10frames-fp-tiles-2-8.webm
+db17ec5d894ea8b8d0b7f32206d0dd3d46dcfa6d *vp90-2-14-resize-10frames-fp-tiles-2-8.webm.md5
+0f6093c472125d05b764d7d1965c1d56771c0ea2 *vp90-2-14-resize-10frames-fp-tiles-4-1.webm
+bc7c79e1bee07926dd970462ce6f64fc30eec3e1 *vp90-2-14-resize-10frames-fp-tiles-4-1.webm.md5
+c5142e2bff4091338196c8ea8bc9266e64f548bc *vp90-2-14-resize-10frames-fp-tiles-4-2.webm
+22aa3dd430b69fd3d92f6561bac86deeed90486d *vp90-2-14-resize-10frames-fp-tiles-4-2.webm.md5
+ede8b1466d2f26e1b1bd9602addb9cd1017e1d8c *vp90-2-14-resize-10frames-fp-tiles-4-8.webm
+508d5ebb9c0eac2a4100281a3ee052ec2fc19217 *vp90-2-14-resize-10frames-fp-tiles-4-8.webm.md5
+2b292e3392854cd1d76ae597a6f53656cf741cfa *vp90-2-14-resize-10frames-fp-tiles-8-1.webm
+1c24e54fa19e94e1722f24676404444e941c3d31 *vp90-2-14-resize-10frames-fp-tiles-8-1.webm.md5
+61beda21064e09634564caa6697ab90bd53c9af7 *vp90-2-14-resize-10frames-fp-tiles-8-2.webm
+9c0657b4d9e1d0e4c9d28a90e5a8630a65519124 *vp90-2-14-resize-10frames-fp-tiles-8-2.webm.md5
+1758c50a11a7c92522749b4a251664705f1f0d4b *vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm
+4f454a06750614314ae15a44087b79016fe2db97 *vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm.md5
+3920c95ba94f1f048a731d9d9b416043b44aa4bd *vp90-2-14-resize-10frames-fp-tiles-8-4.webm
+4eb347a0456d2c49a1e1d8de5aa1c51acc39887e *vp90-2-14-resize-10frames-fp-tiles-8-4.webm.md5
+4b95a74c032a473b6683d7ad5754db1b0ec378e9 *vp90-2-21-resize_inter_1280x720_5_1-2.webm
+a7826dd386bedfe69d02736969bfb47fb6a40a5e *vp90-2-21-resize_inter_1280x720_5_1-2.webm.md5
+5cfff79e82c4d69964ccb8e75b4f0c53b9295167 *vp90-2-21-resize_inter_1280x720_5_3-4.webm
+a18f57db4a25e1f543a99f2ceb182e00db0ee22f *vp90-2-21-resize_inter_1280x720_5_3-4.webm.md5
+d26db0811bf30eb4131d928669713e2485f8e833 *vp90-2-21-resize_inter_1280x720_7_1-2.webm
+fd6f9f332cd5bea4c0f0d57be4297bea493cc5a1 *vp90-2-21-resize_inter_1280x720_7_1-2.webm.md5
+5c7d73d4d268e2ba9593b31cb091fd339505c7fd *vp90-2-21-resize_inter_1280x720_7_3-4.webm
+7bbb949cabc1e70dadcc74582739f63b833034e0 *vp90-2-21-resize_inter_1280x720_7_3-4.webm.md5
+f2d2a41a60eb894aff0c5854afca15931f1445a8 *vp90-2-21-resize_inter_1920x1080_5_1-2.webm
+66d7789992613ac9d678ff905ff1059daa1b89e4 *vp90-2-21-resize_inter_1920x1080_5_1-2.webm.md5
+764edb75fe7dd64e73a1b4f3b4b2b1bf237a4dea *vp90-2-21-resize_inter_1920x1080_5_3-4.webm
+f78bea1075983fd990e7f25d4f31438f9b5efa34 *vp90-2-21-resize_inter_1920x1080_5_3-4.webm.md5
+96496f2ade764a5de9f0c27917c7df1f120fb2ef *vp90-2-21-resize_inter_1920x1080_7_1-2.webm
+2632b635135ed5ecd67fd22dec7990d29c4f4cb5 *vp90-2-21-resize_inter_1920x1080_7_1-2.webm.md5
+74889ea42001bf41428cb742ca74e65129c886dc *vp90-2-21-resize_inter_1920x1080_7_3-4.webm
+d2cf3b25956415bb579d368e7098097e482dd73a *vp90-2-21-resize_inter_1920x1080_7_3-4.webm.md5
+4658986a8ce36ebfcc80a1903e446eaab3985336 *vp90-2-21-resize_inter_320x180_5_1-2.webm
+8a3d8cf325109ffa913cc9426c32eea8c202a09a *vp90-2-21-resize_inter_320x180_5_1-2.webm.md5
+16303aa45176520ee42c2c425247aadc1506b881 *vp90-2-21-resize_inter_320x180_5_3-4.webm
+41cab1ddf7715b680a4dbce42faa9bcd72af4e5c *vp90-2-21-resize_inter_320x180_5_3-4.webm.md5
+56648adcee66dd0e5cb6ac947f5ee1b9cc8ba129 *vp90-2-21-resize_inter_320x180_7_1-2.webm
+70047377787003cc03dda7b2394e6d7eaa666d9e *vp90-2-21-resize_inter_320x180_7_1-2.webm.md5
+d2ff99165488499cc55f75929f1ce5ca9c9e359b *vp90-2-21-resize_inter_320x180_7_3-4.webm
+e69019e378114a4643db283b66d1a7e304761a56 *vp90-2-21-resize_inter_320x180_7_3-4.webm.md5
+4834d129bed0f4289d3a88f2ae3a1736f77621b0 *vp90-2-21-resize_inter_320x240_5_1-2.webm
+a75653c53d22b623c1927fc0088da21dafef21f4 *vp90-2-21-resize_inter_320x240_5_1-2.webm.md5
+19818e1b7fd1c1e63d8873c31b0babe29dd33ba6 *vp90-2-21-resize_inter_320x240_5_3-4.webm
+8d89814ff469a186312111651b16601dfbce4336 *vp90-2-21-resize_inter_320x240_5_3-4.webm.md5
+ac8057bae52498f324ce92a074d5f8207cc4a4a7 *vp90-2-21-resize_inter_320x240_7_1-2.webm
+2643440898c83c08cc47bc744245af696b877c24 *vp90-2-21-resize_inter_320x240_7_1-2.webm.md5
+cf4a4cd38ac8b18c42d8c25a3daafdb39132256b *vp90-2-21-resize_inter_320x240_7_3-4.webm
+70ba8ec9120b26e9b0ffa2c79b432f16cbcb50ec *vp90-2-21-resize_inter_320x240_7_3-4.webm.md5
+669f10409fe1c4a054010162ca47773ea1fdbead *vp90-2-21-resize_inter_640x360_5_1-2.webm
+6355a04249004a35fb386dd1024214234f044383 *vp90-2-21-resize_inter_640x360_5_1-2.webm.md5
+c23763b950b8247c1775d1f8158d93716197676c *vp90-2-21-resize_inter_640x360_5_3-4.webm
+59e6fc381e3ec3b7bdaac586334e0bc944d18fb6 *vp90-2-21-resize_inter_640x360_5_3-4.webm.md5
+71b45cbfdd068baa1f679a69e5e6f421d256a85f *vp90-2-21-resize_inter_640x360_7_1-2.webm
+1416fc761b690c54a955c4cf017fa078520e8c18 *vp90-2-21-resize_inter_640x360_7_1-2.webm.md5
+6c409903279448a697e4db63bab1061784bcd8d2 *vp90-2-21-resize_inter_640x360_7_3-4.webm
+60de1299793433a630b71130cf76c9f5965758e2 *vp90-2-21-resize_inter_640x360_7_3-4.webm.md5
+852b597b8af096d90c80bf0ed6ed3b336b851f19 *vp90-2-21-resize_inter_640x480_5_1-2.webm
+f6856f19236ee46ed462bd0a2e7e72b9c3b9cea6 *vp90-2-21-resize_inter_640x480_5_1-2.webm.md5
+792a16c6f60043bd8dceb515f0b95b8891647858 *vp90-2-21-resize_inter_640x480_5_3-4.webm
+68ffe59877e9a7863805e1c0a3ce18ce037d7c9d *vp90-2-21-resize_inter_640x480_5_3-4.webm.md5
+61e044c4759972a35ea3db8c1478a988910a4ef4 *vp90-2-21-resize_inter_640x480_7_1-2.webm
+7739bfca167b1b43fea72f807f01e097b7cb98d8 *vp90-2-21-resize_inter_640x480_7_1-2.webm.md5
+7291af354b4418917eee00e3a7e366086a0b7a10 *vp90-2-21-resize_inter_640x480_7_3-4.webm
+4a18b09ccb36564193f0215f599d745d95bb558c *vp90-2-21-resize_inter_640x480_7_3-4.webm.md5
+a000d568431d07379dd5a8ec066061c07e560b47 *invalid-vp90-2-00-quantizer-63.ivf.kf_65527x61446.ivf
+1e75aad3433c5c21c194a7b53fc393970f0a8d7f *invalid-vp90-2-00-quantizer-63.ivf.kf_65527x61446.ivf.res
+235182f9a1c5c8841552510dd4288487447bfc40 *invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf
+787f04f0483320d536894282f3358a4f8cac1cf9 *invalid-vp80-00-comprehensive-018.ivf.2kf_0x6.ivf.res
+91d3cefd0deb98f3b0caf3a2d900ec7a7605e53a *invalid-vp90-2-10-show-existing-frame.webm.ivf.s180315_r01-05_b6-.ivf
+1e472baaf5f6113459f0399a38a5a5e68d17799d *invalid-vp90-2-10-show-existing-frame.webm.ivf.s180315_r01-05_b6-.ivf.res
+70057835bf29d14e66699ce5f022df2551fb6b37 *invalid-crbug-629481.webm
+5d9474c0309b7ca09a182d888f73b37a8fe1362c *invalid-crbug-629481.webm.res
+7602e00378161ca36ae93cc6ee12dd30b5ba1e1d *vp90-2-22-svc_1280x720_3.ivf
+02e53e3eefbf25ec0929047fe50876acdeb040bd *vp90-2-22-svc_1280x720_3.ivf.md5
+6fa3d3ac306a3d9ce1d610b78441dc00d2c2d4b9 *tos_vp8.webm
+e402cbbf9e550ae017a1e9f1f73931c1d18474e8 *invalid-crbug-667044.webm
+d3964f9dad9f60363c81b688324d95b4ec7c8038 *invalid-crbug-667044.webm.res
+fd9df7f3f6992af1d7a9dde975c9a0d6f28c053d *invalid-bug-1443.ivf
+fd3020fa6e9ca5966206738654c97dec313b0a95 *invalid-bug-1443.ivf.res
+1a0e405606939f2febab1a21b30c37cb8f2c8cb1 *invalid-token-partition.ivf
+90a8a95e7024f015b87f5483a65036609b3d1b74 *invalid-token-partition.ivf.res
+17696cd21e875f1d6e5d418cbf89feab02c8850a *vp90-2-22-svc_1280x720_1.webm
+e2f9e1e47a791b4e939a9bdc50bf7a25b3761f77 *vp90-2-22-svc_1280x720_1.webm.md5
+a0fbbbc5dd50fd452096f4455a58c1a8c9f66697 *invalid-vp80-00-comprehensive-s17661_r01-05_b6-.ivf
+a61774cf03fc584bd9f0904fc145253bb8ea6c4c *invalid-vp80-00-comprehensive-s17661_r01-05_b6-.ivf.res
+894fae3afee0290546590823974203ab4b8abd95 *crbug-1539.rawfile
+f1026c03efd5da21b381c8eb21f0d64e6d7e4ba3 *invalid-crbug-1558.ivf
+eb198c25f861c3fe2cbd310de11eb96843019345 *invalid-crbug-1558.ivf.res
+c62b005a9fd32c36a1b3f67de6840330f9915e34 *invalid-crbug-1562.ivf
+f0cd8389948ad16085714d96567612136f6a46c5 *invalid-crbug-1562.ivf.res
+bac455906360b45338a16dd626ac5f19bc36a307 *desktop_office1.1280_720-020.yuv
+094be4b80fa30bd227149ea16ab6476d549ea092 *slides_code_term_web_plot.1920_1080.yuv
+518a0be998afece76d3df76047d51e256c591ff2 *invalid-bug-148271109.ivf
+d3964f9dad9f60363c81b688324d95b4ec7c8038 *invalid-bug-148271109.ivf.res
+ad18ca16f0a249fb3b7c38de0d9b327fed273f96 *hantro_collage_w352h288_nv12.yuv
+8a0b2c350539859463d3546a67876c83ff6ff0ac *desktopqvga.320_240.yuv
diff --git a/media/libvpx/libvpx/test/test.mk b/media/libvpx/libvpx/test/test.mk
new file mode 100644
index 0000000000..bbcdd0c6e4
--- /dev/null
+++ b/media/libvpx/libvpx/test/test.mk
@@ -0,0 +1,229 @@
+LIBVPX_TEST_SRCS-yes += acm_random.h
+LIBVPX_TEST_SRCS-yes += bench.h
+LIBVPX_TEST_SRCS-yes += bench.cc
+LIBVPX_TEST_SRCS-yes += buffer.h
+LIBVPX_TEST_SRCS-yes += clear_system_state.h
+LIBVPX_TEST_SRCS-yes += codec_factory.h
+LIBVPX_TEST_SRCS-yes += md5_helper.h
+LIBVPX_TEST_SRCS-yes += register_state_check.h
+LIBVPX_TEST_SRCS-yes += test.mk
+LIBVPX_TEST_SRCS-yes += test_libvpx.cc
+LIBVPX_TEST_SRCS-yes += test_vectors.cc
+LIBVPX_TEST_SRCS-yes += test_vectors.h
+LIBVPX_TEST_SRCS-yes += util.h
+LIBVPX_TEST_SRCS-yes += video_source.h
+
+##
+## BLACK BOX TESTS
+##
+## Black box tests only use the public API.
+##
+LIBVPX_TEST_SRCS-yes += ../md5_utils.h ../md5_utils.c
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ivf_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../y4minput.h ../y4minput.c
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += altref_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += error_resilience_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += i420_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += realtime_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += resize_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += y4m_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += yuv_video_source.h
+
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += config_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += cq_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_datarate_test.cc
+
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += byte_alignment_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += decode_svc_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += user_priv_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_refresh_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += alt_ref_aq_segment_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += aq_segment_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += borders_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += cpu_speed_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += frame_size_tests.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_lossless_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_end_to_end_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += decode_corrupted.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ethread_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_motion_vector_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += level_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_datarate_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_test.h
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_end_to_end_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += timestamp_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_datarate_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ext_ratectrl_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += ../vp9/simple_encode.h
+
+LIBVPX_TEST_SRCS-yes += decode_test_driver.cc
+LIBVPX_TEST_SRCS-yes += decode_test_driver.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_test_driver.cc
+LIBVPX_TEST_SRCS-yes += encode_test_driver.h
+
+## IVF writing.
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += ../ivfenc.c ../ivfenc.h
+
+## Y4m parsing.
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += y4m_test.cc ../y4menc.c ../y4menc.h
+
+## WebM Parsing
+ifeq ($(CONFIG_WEBM_IO), yes)
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvparser.cc
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvreader.cc
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvparser.h
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvreader.h
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/common/webmids.h
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += $(LIBWEBM_PARSER_SRCS)
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../tools_common.h
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../webmdec.cc
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += ../webmdec.h
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += webm_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_skip_loopfilter_test.cc
+endif
+
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += decode_api_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS) += test_vector_test.cc
+
+# Currently we only support decoder perf tests for vp9. Also they read from WebM
+# files, so WebM IO is required.
+ifeq ($(CONFIG_DECODE_PERF_TESTS)$(CONFIG_VP9_DECODER)$(CONFIG_WEBM_IO), \
+ yesyesyes)
+LIBVPX_TEST_SRCS-yes += decode_perf_test.cc
+endif
+
+# encode perf tests are vp9 only
+ifeq ($(CONFIG_ENCODE_PERF_TESTS)$(CONFIG_VP9_ENCODER), yesyes)
+LIBVPX_TEST_SRCS-yes += encode_perf_test.cc
+endif
+
+## Multi-codec blackbox tests.
+ifeq ($(findstring yes,$(CONFIG_VP8_DECODER)$(CONFIG_VP9_DECODER)), yes)
+LIBVPX_TEST_SRCS-yes += invalid_file_test.cc
+endif
+
+##
+## WHITE BOX TESTS
+##
+## Whitebox tests invoke functions not exposed via the public API. Certain
+## shared library builds don't make these functions accessible.
+##
+ifeq ($(CONFIG_SHARED),)
+
+## VP8
+ifeq ($(CONFIG_VP8),yes)
+
+# These tests require both the encoder and decoder to be built.
+ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),yesyes)
+LIBVPX_TEST_SRCS-yes += vp8_boolcoder_test.cc
+LIBVPX_TEST_SRCS-yes += vp8_fragments_test.cc
+endif
+LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += add_noise_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC) += pp_filter_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += vp8_decrypt_test.cc
+ifneq (, $(filter yes, $(HAVE_SSE2) $(HAVE_SSSE3) $(HAVE_SSE4_1) $(HAVE_NEON) \
+ $(HAVE_MSA) $(HAVE_MMI)))
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += quantize_test.cc
+endif
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += set_roi.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += variance_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc
+
+LIBVPX_TEST_SRCS-yes += idct_test.cc
+LIBVPX_TEST_SRCS-yes += predict_test.cc
+LIBVPX_TEST_SRCS-yes += vpx_scale_test.cc
+LIBVPX_TEST_SRCS-yes += vpx_scale_test.h
+
+ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_TEMPORAL_DENOISING),yesyes)
+LIBVPX_TEST_SRCS-$(HAVE_SSE2) += vp8_denoiser_sse2_test.cc
+endif
+
+endif # VP8
+
+## VP9
+ifeq ($(CONFIG_VP9),yes)
+
+# These tests require both the encoder and decoder to be built.
+ifeq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_DECODER),yesyes)
+# IDCT test currently depends on FDCT function
+LIBVPX_TEST_SRCS-yes += idct8x8_test.cc
+LIBVPX_TEST_SRCS-yes += partial_idct_test.cc
+LIBVPX_TEST_SRCS-yes += superframe_test.cc
+LIBVPX_TEST_SRCS-yes += tile_independence_test.cc
+LIBVPX_TEST_SRCS-yes += vp9_boolcoder_test.cc
+LIBVPX_TEST_SRCS-yes += vp9_encoder_parms_get_to_decoder.cc
+LIBVPX_TEST_SRCS-yes += vp9_roi_test.cc
+endif
+
+LIBVPX_TEST_SRCS-yes += convolve_test.cc
+LIBVPX_TEST_SRCS-yes += lpf_test.cc
+LIBVPX_TEST_SRCS-yes += vp9_intrapred_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_decrypt_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_thread_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += avg_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += comp_avg_pred_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct_partial_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct8x8_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += hadamard_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += minmax_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_scale_test.cc
+ifneq ($(CONFIG_REALTIME_ONLY),yes)
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += yuv_temporal_filter_test.cc
+endif
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += variance_test.cc
+ifneq (, $(filter yes, $(HAVE_SSE2) $(HAVE_AVX2) $(HAVE_NEON)))
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_block_error_test.cc
+endif
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_quantize_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_subtract_test.cc
+
+ifeq ($(CONFIG_VP9_ENCODER),yes)
+LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += blockiness_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += consistency_test.cc
+endif
+
+ifeq ($(CONFIG_VP9_ENCODER),yes)
+LIBVPX_TEST_SRCS-$(CONFIG_NON_GREEDY_MV) += non_greedy_mv_test.cc
+endif
+
+ifeq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_TEMPORAL_DENOISING),yesyes)
+LIBVPX_TEST_SRCS-yes += vp9_denoiser_test.cc
+endif
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_arf_freq_test.cc
+
+ifeq ($(CONFIG_VP9_ENCODER),yes)
+SIMPLE_ENCODE_TEST_SRCS-$(CONFIG_RATE_CTRL) := simple_encode_test.cc
+endif
+
+endif # VP9
+
+## Multi-codec / unconditional whitebox tests.
+
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sad_test.cc
+ifneq (, $(filter yes, $(HAVE_NEON) $(HAVE_SSE2) $(HAVE_MSA)))
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sum_squares_test.cc
+endif
+
+TEST_INTRA_PRED_SPEED_SRCS-yes := test_intra_pred_speed.cc
+TEST_INTRA_PRED_SPEED_SRCS-yes += ../md5_utils.h ../md5_utils.c
+
+RC_INTERFACE_TEST_SRCS-yes := test_rc_interface.cc
+RC_INTERFACE_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ratectrl_rtc_test.cc
+RC_INTERFACE_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_ratectrl_rtc_test.cc
+RC_INTERFACE_TEST_SRCS-$(CONFIG_ENCODERS) += encode_test_driver.cc
+RC_INTERFACE_TEST_SRCS-$(CONFIG_ENCODERS) += encode_test_driver.h
+RC_INTERFACE_TEST_SRCS-yes += decode_test_driver.cc
+RC_INTERFACE_TEST_SRCS-yes += decode_test_driver.h
+RC_INTERFACE_TEST_SRCS-yes += codec_factory.h
+
+endif # CONFIG_SHARED
+
+include $(SRC_PATH_BARE)/test/test-data.mk
diff --git a/media/libvpx/libvpx/test/test_intra_pred_speed.cc b/media/libvpx/libvpx/test/test_intra_pred_speed.cc
new file mode 100644
index 0000000000..15303816b9
--- /dev/null
+++ b/media/libvpx/libvpx/test/test_intra_pred_speed.cc
@@ -0,0 +1,601 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+// Test and time VPX intra-predictor functions
+
+#include <stdio.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/md5_helper.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/vpx_timer.h"
+
+// -----------------------------------------------------------------------------
+
+namespace {
+
+typedef void (*VpxPredFunc)(uint8_t *dst, ptrdiff_t y_stride,
+ const uint8_t *above, const uint8_t *left);
+
+const int kBPS = 32;
+const int kTotalPixels = 32 * kBPS;
+const int kNumVp9IntraPredFuncs = 13;
+const char *kVp9IntraPredNames[kNumVp9IntraPredFuncs] = {
+ "DC_PRED", "DC_LEFT_PRED", "DC_TOP_PRED", "DC_128_PRED", "V_PRED",
+ "H_PRED", "D45_PRED", "D135_PRED", "D117_PRED", "D153_PRED",
+ "D207_PRED", "D63_PRED", "TM_PRED"
+};
+
+template <typename Pixel>
+struct IntraPredTestMem {
+ void Init(int block_size, int bd) {
+ libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
+ Pixel *const above = above_mem + 16;
+ const int mask = (1 << bd) - 1;
+ for (int i = 0; i < kTotalPixels; ++i) ref_src[i] = rnd.Rand16() & mask;
+ for (int i = 0; i < kBPS; ++i) left[i] = rnd.Rand16() & mask;
+ for (int i = -1; i < kBPS; ++i) above[i] = rnd.Rand16() & mask;
+
+ // d45/d63 require the top row to be extended.
+ ASSERT_LE(block_size, kBPS);
+ for (int i = block_size; i < 2 * block_size; ++i) {
+ above[i] = above[block_size - 1];
+ }
+ }
+
+ DECLARE_ALIGNED(16, Pixel, src[kTotalPixels]);
+ DECLARE_ALIGNED(16, Pixel, ref_src[kTotalPixels]);
+ DECLARE_ALIGNED(16, Pixel, left[kBPS]);
+ DECLARE_ALIGNED(16, Pixel, above_mem[2 * kBPS + 16]);
+};
+
+typedef IntraPredTestMem<uint8_t> Vp9IntraPredTestMem;
+
+void CheckMd5Signature(const char name[], const char *const signatures[],
+ const void *data, size_t data_size, int elapsed_time,
+ int idx) {
+ libvpx_test::MD5 md5;
+ md5.Add(reinterpret_cast<const uint8_t *>(data), data_size);
+ printf("Mode %s[%12s]: %5d ms MD5: %s\n", name, kVp9IntraPredNames[idx],
+ elapsed_time, md5.Get());
+ EXPECT_STREQ(signatures[idx], md5.Get());
+}
+
+void TestIntraPred(const char name[], VpxPredFunc const *pred_funcs,
+ const char *const signatures[], int block_size) {
+ const int kNumTests = static_cast<int>(
+ 2.e10 / (block_size * block_size * kNumVp9IntraPredFuncs));
+ Vp9IntraPredTestMem intra_pred_test_mem;
+ const uint8_t *const above = intra_pred_test_mem.above_mem + 16;
+
+ intra_pred_test_mem.Init(block_size, 8);
+
+ for (int k = 0; k < kNumVp9IntraPredFuncs; ++k) {
+ if (pred_funcs[k] == nullptr) continue;
+ memcpy(intra_pred_test_mem.src, intra_pred_test_mem.ref_src,
+ sizeof(intra_pred_test_mem.src));
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int num_tests = 0; num_tests < kNumTests; ++num_tests) {
+ pred_funcs[k](intra_pred_test_mem.src, kBPS, above,
+ intra_pred_test_mem.left);
+ }
+ libvpx_test::ClearSystemState();
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+ CheckMd5Signature(name, signatures, intra_pred_test_mem.src,
+ sizeof(intra_pred_test_mem.src), elapsed_time, k);
+ }
+}
+
+void TestIntraPred4(VpxPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "e7ed7353c3383fff942e500e9bfe82fe", "2a4a26fcc6ce005eadc08354d196c8a9",
+ "269d92eff86f315d9c38fe7640d85b15", "ae2960eea9f71ee3dabe08b282ec1773",
+ "6c1abcc44e90148998b51acd11144e9c", "f7bb3186e1ef8a2b326037ff898cad8e",
+ "364c1f3fb2f445f935aec2a70a67eaa4", "141624072a4a56773f68fadbdd07c4a7",
+ "7be49b08687a5f24df3a2c612fca3876", "459bb5d9fd5b238348179c9a22108cd6",
+ "73edb8831bf1bdfce21ae8eaa43b1234", "2e2457f2009c701a355a8b25eb74fcda",
+ "52ae4e8bdbe41494c1f43051d4dd7f0b"
+ };
+ TestIntraPred("Intra4", pred_funcs, kSignatures, 4);
+}
+
+void TestIntraPred8(VpxPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "d8bbae5d6547cfc17e4f5f44c8730e88", "373bab6d931868d41a601d9d88ce9ac3",
+ "6fdd5ff4ff79656c14747598ca9e3706", "d9661c2811d6a73674f40ffb2b841847",
+ "7c722d10b19ccff0b8c171868e747385", "f81dd986eb2b50f750d3a7da716b7e27",
+ "d500f2c8fc78f46a4c74e4dcf51f14fb", "0e3523f9cab2142dd37fd07ec0760bce",
+ "79ac4efe907f0a0f1885d43066cfedee", "19ecf2432ac305057de3b6578474eec6",
+ "4f985b61acc6dd5d2d2585fa89ea2e2d", "f1bb25a9060dd262f405f15a38f5f674",
+ "209ea00801584829e9a0f7be7d4a74ba"
+ };
+ TestIntraPred("Intra8", pred_funcs, kSignatures, 8);
+}
+
+void TestIntraPred16(VpxPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "50971c07ce26977d30298538fffec619", "527a6b9e0dc5b21b98cf276305432bef",
+ "7eff2868f80ebc2c43a4f367281d80f7", "67cd60512b54964ef6aff1bd4816d922",
+ "48371c87dc95c08a33b2048f89cf6468", "b0acf2872ee411d7530af6d2625a7084",
+ "f32aafed4d8d3776ed58bcb6188756d5", "dae208f3dca583529cff49b73f7c4183",
+ "7af66a2f4c8e0b4908e40f047e60c47c", "125e3ab6ab9bc961f183ec366a7afa88",
+ "6b90f25b23983c35386b9fd704427622", "f8d6b11d710edc136a7c62c917435f93",
+ "ed308f18614a362917f411c218aee532"
+ };
+ TestIntraPred("Intra16", pred_funcs, kSignatures, 16);
+}
+
+void TestIntraPred32(VpxPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "a0a618c900e65ae521ccc8af789729f2", "985aaa7c72b4a6c2fb431d32100cf13a",
+ "10662d09febc3ca13ee4e700120daeb5", "b3b01379ba08916ef6b1b35f7d9ad51c",
+ "9f4261755795af97e34679c333ec7004", "bc2c9da91ad97ef0d1610fb0a9041657",
+ "75c79b1362ad18abfcdb1aa0aacfc21d", "4039bb7da0f6860090d3c57b5c85468f",
+ "b29fff7b61804e68383e3a609b33da58", "e1aa5e49067fd8dba66c2eb8d07b7a89",
+ "4e042822909c1c06d3b10a88281df1eb", "72eb9d9e0e67c93f4c66b70348e9fef7",
+ "a22d102bcb51ca798aac12ca4ae8f2e8"
+ };
+ TestIntraPred("Intra32", pred_funcs, kSignatures, 32);
+}
+
+} // namespace
+
+// Defines a test case for |arch| (e.g., C, SSE2, ...) passing the predictors
+// to |test_func|. The test name is 'arch.test_func', e.g., C.TestIntraPred4.
+#define INTRA_PRED_TEST(arch, test_func, dc, dc_left, dc_top, dc_128, v, h, \
+ d45, d135, d117, d153, d207, d63, tm) \
+ TEST(arch, test_func) { \
+ static const VpxPredFunc vpx_intra_pred[] = { \
+ dc, dc_left, dc_top, dc_128, v, h, d45, d135, d117, d153, d207, d63, tm \
+ }; \
+ test_func(vpx_intra_pred); \
+ }
+
+// -----------------------------------------------------------------------------
+
+INTRA_PRED_TEST(C, TestIntraPred4, vpx_dc_predictor_4x4_c,
+ vpx_dc_left_predictor_4x4_c, vpx_dc_top_predictor_4x4_c,
+ vpx_dc_128_predictor_4x4_c, vpx_v_predictor_4x4_c,
+ vpx_h_predictor_4x4_c, vpx_d45_predictor_4x4_c,
+ vpx_d135_predictor_4x4_c, vpx_d117_predictor_4x4_c,
+ vpx_d153_predictor_4x4_c, vpx_d207_predictor_4x4_c,
+ vpx_d63_predictor_4x4_c, vpx_tm_predictor_4x4_c)
+
+INTRA_PRED_TEST(C, TestIntraPred8, vpx_dc_predictor_8x8_c,
+ vpx_dc_left_predictor_8x8_c, vpx_dc_top_predictor_8x8_c,
+ vpx_dc_128_predictor_8x8_c, vpx_v_predictor_8x8_c,
+ vpx_h_predictor_8x8_c, vpx_d45_predictor_8x8_c,
+ vpx_d135_predictor_8x8_c, vpx_d117_predictor_8x8_c,
+ vpx_d153_predictor_8x8_c, vpx_d207_predictor_8x8_c,
+ vpx_d63_predictor_8x8_c, vpx_tm_predictor_8x8_c)
+
+INTRA_PRED_TEST(C, TestIntraPred16, vpx_dc_predictor_16x16_c,
+ vpx_dc_left_predictor_16x16_c, vpx_dc_top_predictor_16x16_c,
+ vpx_dc_128_predictor_16x16_c, vpx_v_predictor_16x16_c,
+ vpx_h_predictor_16x16_c, vpx_d45_predictor_16x16_c,
+ vpx_d135_predictor_16x16_c, vpx_d117_predictor_16x16_c,
+ vpx_d153_predictor_16x16_c, vpx_d207_predictor_16x16_c,
+ vpx_d63_predictor_16x16_c, vpx_tm_predictor_16x16_c)
+
+INTRA_PRED_TEST(C, TestIntraPred32, vpx_dc_predictor_32x32_c,
+ vpx_dc_left_predictor_32x32_c, vpx_dc_top_predictor_32x32_c,
+ vpx_dc_128_predictor_32x32_c, vpx_v_predictor_32x32_c,
+ vpx_h_predictor_32x32_c, vpx_d45_predictor_32x32_c,
+ vpx_d135_predictor_32x32_c, vpx_d117_predictor_32x32_c,
+ vpx_d153_predictor_32x32_c, vpx_d207_predictor_32x32_c,
+ vpx_d63_predictor_32x32_c, vpx_tm_predictor_32x32_c)
+
+#if HAVE_SSE2
+INTRA_PRED_TEST(SSE2, TestIntraPred4, vpx_dc_predictor_4x4_sse2,
+ vpx_dc_left_predictor_4x4_sse2, vpx_dc_top_predictor_4x4_sse2,
+ vpx_dc_128_predictor_4x4_sse2, vpx_v_predictor_4x4_sse2,
+ vpx_h_predictor_4x4_sse2, vpx_d45_predictor_4x4_sse2, nullptr,
+ nullptr, nullptr, vpx_d207_predictor_4x4_sse2, nullptr,
+ vpx_tm_predictor_4x4_sse2)
+
+INTRA_PRED_TEST(SSE2, TestIntraPred8, vpx_dc_predictor_8x8_sse2,
+ vpx_dc_left_predictor_8x8_sse2, vpx_dc_top_predictor_8x8_sse2,
+ vpx_dc_128_predictor_8x8_sse2, vpx_v_predictor_8x8_sse2,
+ vpx_h_predictor_8x8_sse2, vpx_d45_predictor_8x8_sse2, nullptr,
+ nullptr, nullptr, nullptr, nullptr, vpx_tm_predictor_8x8_sse2)
+
+INTRA_PRED_TEST(SSE2, TestIntraPred16, vpx_dc_predictor_16x16_sse2,
+ vpx_dc_left_predictor_16x16_sse2,
+ vpx_dc_top_predictor_16x16_sse2,
+ vpx_dc_128_predictor_16x16_sse2, vpx_v_predictor_16x16_sse2,
+ vpx_h_predictor_16x16_sse2, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_tm_predictor_16x16_sse2)
+
+INTRA_PRED_TEST(SSE2, TestIntraPred32, vpx_dc_predictor_32x32_sse2,
+ vpx_dc_left_predictor_32x32_sse2,
+ vpx_dc_top_predictor_32x32_sse2,
+ vpx_dc_128_predictor_32x32_sse2, vpx_v_predictor_32x32_sse2,
+ vpx_h_predictor_32x32_sse2, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_tm_predictor_32x32_sse2)
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+INTRA_PRED_TEST(SSSE3, TestIntraPred4, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ vpx_d153_predictor_4x4_ssse3, nullptr,
+ vpx_d63_predictor_4x4_ssse3, nullptr)
+INTRA_PRED_TEST(SSSE3, TestIntraPred8, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ vpx_d153_predictor_8x8_ssse3, vpx_d207_predictor_8x8_ssse3,
+ vpx_d63_predictor_8x8_ssse3, nullptr)
+INTRA_PRED_TEST(SSSE3, TestIntraPred16, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_d45_predictor_16x16_ssse3, nullptr,
+ nullptr, vpx_d153_predictor_16x16_ssse3,
+ vpx_d207_predictor_16x16_ssse3, vpx_d63_predictor_16x16_ssse3,
+ nullptr)
+INTRA_PRED_TEST(SSSE3, TestIntraPred32, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_d45_predictor_32x32_ssse3, nullptr,
+ nullptr, vpx_d153_predictor_32x32_ssse3,
+ vpx_d207_predictor_32x32_ssse3, vpx_d63_predictor_32x32_ssse3,
+ nullptr)
+#endif // HAVE_SSSE3
+
+#if HAVE_DSPR2
+INTRA_PRED_TEST(DSPR2, TestIntraPred4, vpx_dc_predictor_4x4_dspr2, nullptr,
+ nullptr, nullptr, nullptr, vpx_h_predictor_4x4_dspr2, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ vpx_tm_predictor_4x4_dspr2)
+INTRA_PRED_TEST(DSPR2, TestIntraPred8, vpx_dc_predictor_8x8_dspr2, nullptr,
+ nullptr, nullptr, nullptr, vpx_h_predictor_8x8_dspr2, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr,
+ vpx_tm_predictor_8x8_c)
+INTRA_PRED_TEST(DSPR2, TestIntraPred16, vpx_dc_predictor_16x16_dspr2, nullptr,
+ nullptr, nullptr, nullptr, vpx_h_predictor_16x16_dspr2, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)
+#endif // HAVE_DSPR2
+
+#if HAVE_NEON
+INTRA_PRED_TEST(NEON, TestIntraPred4, vpx_dc_predictor_4x4_neon,
+ vpx_dc_left_predictor_4x4_neon, vpx_dc_top_predictor_4x4_neon,
+ vpx_dc_128_predictor_4x4_neon, vpx_v_predictor_4x4_neon,
+ vpx_h_predictor_4x4_neon, vpx_d45_predictor_4x4_neon,
+ vpx_d135_predictor_4x4_neon, vpx_d117_predictor_4x4_neon,
+ vpx_d153_predictor_4x4_neon, vpx_d207_predictor_4x4_neon,
+ vpx_d63_predictor_4x4_neon, vpx_tm_predictor_4x4_neon)
+INTRA_PRED_TEST(NEON, TestIntraPred8, vpx_dc_predictor_8x8_neon,
+ vpx_dc_left_predictor_8x8_neon, vpx_dc_top_predictor_8x8_neon,
+ vpx_dc_128_predictor_8x8_neon, vpx_v_predictor_8x8_neon,
+ vpx_h_predictor_8x8_neon, vpx_d45_predictor_8x8_neon,
+ vpx_d135_predictor_8x8_neon, vpx_d117_predictor_8x8_neon,
+ vpx_d153_predictor_8x8_neon, vpx_d207_predictor_8x8_neon,
+ vpx_d63_predictor_8x8_neon, vpx_tm_predictor_8x8_neon)
+INTRA_PRED_TEST(NEON, TestIntraPred16, vpx_dc_predictor_16x16_neon,
+ vpx_dc_left_predictor_16x16_neon,
+ vpx_dc_top_predictor_16x16_neon,
+ vpx_dc_128_predictor_16x16_neon, vpx_v_predictor_16x16_neon,
+ vpx_h_predictor_16x16_neon, vpx_d45_predictor_16x16_neon,
+ vpx_d135_predictor_16x16_neon, vpx_d117_predictor_16x16_neon,
+ vpx_d153_predictor_16x16_neon, vpx_d207_predictor_16x16_neon,
+ vpx_d63_predictor_16x16_neon, vpx_tm_predictor_16x16_neon)
+INTRA_PRED_TEST(NEON, TestIntraPred32, vpx_dc_predictor_32x32_neon,
+ vpx_dc_left_predictor_32x32_neon,
+ vpx_dc_top_predictor_32x32_neon,
+ vpx_dc_128_predictor_32x32_neon, vpx_v_predictor_32x32_neon,
+ vpx_h_predictor_32x32_neon, vpx_d45_predictor_32x32_neon,
+ vpx_d135_predictor_32x32_neon, vpx_d117_predictor_32x32_neon,
+ vpx_d153_predictor_32x32_neon, vpx_d207_predictor_32x32_neon,
+ vpx_d63_predictor_32x32_neon, vpx_tm_predictor_32x32_neon)
+#endif // HAVE_NEON
+
+#if HAVE_MSA
+INTRA_PRED_TEST(MSA, TestIntraPred4, vpx_dc_predictor_4x4_msa,
+ vpx_dc_left_predictor_4x4_msa, vpx_dc_top_predictor_4x4_msa,
+ vpx_dc_128_predictor_4x4_msa, vpx_v_predictor_4x4_msa,
+ vpx_h_predictor_4x4_msa, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_tm_predictor_4x4_msa)
+INTRA_PRED_TEST(MSA, TestIntraPred8, vpx_dc_predictor_8x8_msa,
+ vpx_dc_left_predictor_8x8_msa, vpx_dc_top_predictor_8x8_msa,
+ vpx_dc_128_predictor_8x8_msa, vpx_v_predictor_8x8_msa,
+ vpx_h_predictor_8x8_msa, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_tm_predictor_8x8_msa)
+INTRA_PRED_TEST(MSA, TestIntraPred16, vpx_dc_predictor_16x16_msa,
+ vpx_dc_left_predictor_16x16_msa, vpx_dc_top_predictor_16x16_msa,
+ vpx_dc_128_predictor_16x16_msa, vpx_v_predictor_16x16_msa,
+ vpx_h_predictor_16x16_msa, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_tm_predictor_16x16_msa)
+INTRA_PRED_TEST(MSA, TestIntraPred32, vpx_dc_predictor_32x32_msa,
+ vpx_dc_left_predictor_32x32_msa, vpx_dc_top_predictor_32x32_msa,
+ vpx_dc_128_predictor_32x32_msa, vpx_v_predictor_32x32_msa,
+ vpx_h_predictor_32x32_msa, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_tm_predictor_32x32_msa)
+#endif // HAVE_MSA
+
+#if HAVE_VSX
+// TODO(crbug.com/webm/1522): Fix test failures.
+#if 0
+INTRA_PRED_TEST(VSX, TestIntraPred4, nullptr, nullptr, nullptr, nullptr,
+ nullptr, vpx_h_predictor_4x4_vsx, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, vpx_tm_predictor_4x4_vsx)
+
+INTRA_PRED_TEST(VSX, TestIntraPred8, vpx_dc_predictor_8x8_vsx, nullptr, nullptr,
+ nullptr, nullptr, vpx_h_predictor_8x8_vsx,
+ vpx_d45_predictor_8x8_vsx, nullptr, nullptr, nullptr, nullptr,
+ vpx_d63_predictor_8x8_vsx, vpx_tm_predictor_8x8_vsx)
+#endif
+
+INTRA_PRED_TEST(VSX, TestIntraPred16, vpx_dc_predictor_16x16_vsx,
+ vpx_dc_left_predictor_16x16_vsx, vpx_dc_top_predictor_16x16_vsx,
+ vpx_dc_128_predictor_16x16_vsx, vpx_v_predictor_16x16_vsx,
+ vpx_h_predictor_16x16_vsx, vpx_d45_predictor_16x16_vsx, nullptr,
+ nullptr, nullptr, nullptr, vpx_d63_predictor_16x16_vsx,
+ vpx_tm_predictor_16x16_vsx)
+
+INTRA_PRED_TEST(VSX, TestIntraPred32, vpx_dc_predictor_32x32_vsx,
+ vpx_dc_left_predictor_32x32_vsx, vpx_dc_top_predictor_32x32_vsx,
+ vpx_dc_128_predictor_32x32_vsx, vpx_v_predictor_32x32_vsx,
+ vpx_h_predictor_32x32_vsx, vpx_d45_predictor_32x32_vsx, nullptr,
+ nullptr, nullptr, nullptr, vpx_d63_predictor_32x32_vsx,
+ vpx_tm_predictor_32x32_vsx)
+#endif // HAVE_VSX
+
+// -----------------------------------------------------------------------------
+
+#if CONFIG_VP9_HIGHBITDEPTH
+namespace {
+
+typedef void (*VpxHighbdPredFunc)(uint16_t *dst, ptrdiff_t y_stride,
+ const uint16_t *above, const uint16_t *left,
+ int bd);
+
+typedef IntraPredTestMem<uint16_t> Vp9HighbdIntraPredTestMem;
+
+void TestHighbdIntraPred(const char name[], VpxHighbdPredFunc const *pred_funcs,
+ const char *const signatures[], int block_size) {
+ const int kNumTests = static_cast<int>(
+ 2.e10 / (block_size * block_size * kNumVp9IntraPredFuncs));
+ Vp9HighbdIntraPredTestMem intra_pred_test_mem;
+ const uint16_t *const above = intra_pred_test_mem.above_mem + 16;
+
+ intra_pred_test_mem.Init(block_size, 12);
+
+ for (int k = 0; k < kNumVp9IntraPredFuncs; ++k) {
+ if (pred_funcs[k] == nullptr) continue;
+ memcpy(intra_pred_test_mem.src, intra_pred_test_mem.ref_src,
+ sizeof(intra_pred_test_mem.src));
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int num_tests = 0; num_tests < kNumTests; ++num_tests) {
+ pred_funcs[k](intra_pred_test_mem.src, kBPS, above,
+ intra_pred_test_mem.left, 12);
+ }
+ libvpx_test::ClearSystemState();
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+ CheckMd5Signature(name, signatures, intra_pred_test_mem.src,
+ sizeof(intra_pred_test_mem.src), elapsed_time, k);
+ }
+}
+
+void TestHighbdIntraPred4(VpxHighbdPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "11f74af6c5737df472f3275cbde062fa", "51bea056b6447c93f6eb8f6b7e8f6f71",
+ "27e97f946766331795886f4de04c5594", "53ab15974b049111fb596c5168ec7e3f",
+ "f0b640bb176fbe4584cf3d32a9b0320a", "729783ca909e03afd4b47111c80d967b",
+ "fbf1c30793d9f32812e4d9f905d53530", "293fc903254a33754133314c6cdba81f",
+ "f8074d704233e73dfd35b458c6092374", "aa6363d08544a1ec4da33d7a0be5640d",
+ "462abcfdfa3d087bb33c9a88f2aec491", "863eab65d22550dd44a2397277c1ec71",
+ "23d61df1574d0fa308f9731811047c4b"
+ };
+ TestHighbdIntraPred("Intra4", pred_funcs, kSignatures, 4);
+}
+
+void TestHighbdIntraPred8(VpxHighbdPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "03da8829fe94663047fd108c5fcaa71d", "ecdb37b8120a2d3a4c706b016bd1bfd7",
+ "1d4543ed8d2b9368cb96898095fe8a75", "f791c9a67b913cbd82d9da8ecede30e2",
+ "065c70646f4dbaff913282f55a45a441", "51f87123616662ef7c35691497dfd0ba",
+ "2a5b0131ef4716f098ee65e6df01e3dd", "9ffe186a6bc7db95275f1bbddd6f7aba",
+ "a3258a2eae2e2bd55cb8f71351b22998", "8d909f0a2066e39b3216092c6289ece4",
+ "d183abb30b9f24c886a0517e991b22c7", "702a42fe4c7d665dc561b2aeeb60f311",
+ "7b5dbbbe7ae3a4ac2948731600bde5d6"
+ };
+ TestHighbdIntraPred("Intra8", pred_funcs, kSignatures, 8);
+}
+
+void TestHighbdIntraPred16(VpxHighbdPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "e33cb3f56a878e2fddb1b2fc51cdd275", "c7bff6f04b6052c8ab335d726dbbd52d",
+ "d0b0b47b654a9bcc5c6008110a44589b", "78f5da7b10b2b9ab39f114a33b6254e9",
+ "c78e31d23831abb40d6271a318fdd6f3", "90d1347f4ec9198a0320daecb6ff90b8",
+ "d2c623746cbb64a0c9e29c10f2c57041", "cf28bd387b81ad3e5f1a1c779a4b70a0",
+ "24c304330431ddeaf630f6ce94af2eac", "91a329798036bf64e8e00a87b131b8b1",
+ "d39111f22885307f920796a42084c872", "e2e702f7250ece98dd8f3f2854c31eeb",
+ "e2fb05b01eb8b88549e85641d8ce5b59"
+ };
+ TestHighbdIntraPred("Intra16", pred_funcs, kSignatures, 16);
+}
+
+void TestHighbdIntraPred32(VpxHighbdPredFunc const *pred_funcs) {
+ static const char *const kSignatures[kNumVp9IntraPredFuncs] = {
+ "a3e8056ba7e36628cce4917cd956fedd", "cc7d3024fe8748b512407edee045377e",
+ "2aab0a0f330a1d3e19b8ecb8f06387a3", "a547bc3fb7b06910bf3973122a426661",
+ "26f712514da95042f93d6e8dc8e431dc", "bb08c6e16177081daa3d936538dbc2e3",
+ "8f031af3e2650e89620d8d2c3a843d8b", "42867c8553285e94ee8e4df7abafbda8",
+ "6496bdee96100667833f546e1be3d640", "2ebfa25bf981377e682e580208504300",
+ "3e8ae52fd1f607f348aa4cb436c71ab7", "3d4efe797ca82193613696753ea624c4",
+ "cb8aab6d372278f3131e8d99efde02d9"
+ };
+ TestHighbdIntraPred("Intra32", pred_funcs, kSignatures, 32);
+}
+
+} // namespace
+
+// Defines a test case for |arch| (e.g., C, SSE2, ...) passing the predictors
+// to |test_func|. The test name is 'arch.test_func', e.g., C.TestIntraPred4.
+#define HIGHBD_INTRA_PRED_TEST(arch, test_func, dc, dc_left, dc_top, dc_128, \
+ v, h, d45, d135, d117, d153, d207, d63, tm) \
+ TEST(arch, test_func) { \
+ static const VpxHighbdPredFunc vpx_intra_pred[] = { \
+ dc, dc_left, dc_top, dc_128, v, h, d45, d135, d117, d153, d207, d63, tm \
+ }; \
+ test_func(vpx_intra_pred); \
+ }
+
+// -----------------------------------------------------------------------------
+
+HIGHBD_INTRA_PRED_TEST(
+ C, TestHighbdIntraPred4, vpx_highbd_dc_predictor_4x4_c,
+ vpx_highbd_dc_left_predictor_4x4_c, vpx_highbd_dc_top_predictor_4x4_c,
+ vpx_highbd_dc_128_predictor_4x4_c, vpx_highbd_v_predictor_4x4_c,
+ vpx_highbd_h_predictor_4x4_c, vpx_highbd_d45_predictor_4x4_c,
+ vpx_highbd_d135_predictor_4x4_c, vpx_highbd_d117_predictor_4x4_c,
+ vpx_highbd_d153_predictor_4x4_c, vpx_highbd_d207_predictor_4x4_c,
+ vpx_highbd_d63_predictor_4x4_c, vpx_highbd_tm_predictor_4x4_c)
+
+HIGHBD_INTRA_PRED_TEST(
+ C, TestHighbdIntraPred8, vpx_highbd_dc_predictor_8x8_c,
+ vpx_highbd_dc_left_predictor_8x8_c, vpx_highbd_dc_top_predictor_8x8_c,
+ vpx_highbd_dc_128_predictor_8x8_c, vpx_highbd_v_predictor_8x8_c,
+ vpx_highbd_h_predictor_8x8_c, vpx_highbd_d45_predictor_8x8_c,
+ vpx_highbd_d135_predictor_8x8_c, vpx_highbd_d117_predictor_8x8_c,
+ vpx_highbd_d153_predictor_8x8_c, vpx_highbd_d207_predictor_8x8_c,
+ vpx_highbd_d63_predictor_8x8_c, vpx_highbd_tm_predictor_8x8_c)
+
+HIGHBD_INTRA_PRED_TEST(
+ C, TestHighbdIntraPred16, vpx_highbd_dc_predictor_16x16_c,
+ vpx_highbd_dc_left_predictor_16x16_c, vpx_highbd_dc_top_predictor_16x16_c,
+ vpx_highbd_dc_128_predictor_16x16_c, vpx_highbd_v_predictor_16x16_c,
+ vpx_highbd_h_predictor_16x16_c, vpx_highbd_d45_predictor_16x16_c,
+ vpx_highbd_d135_predictor_16x16_c, vpx_highbd_d117_predictor_16x16_c,
+ vpx_highbd_d153_predictor_16x16_c, vpx_highbd_d207_predictor_16x16_c,
+ vpx_highbd_d63_predictor_16x16_c, vpx_highbd_tm_predictor_16x16_c)
+
+HIGHBD_INTRA_PRED_TEST(
+ C, TestHighbdIntraPred32, vpx_highbd_dc_predictor_32x32_c,
+ vpx_highbd_dc_left_predictor_32x32_c, vpx_highbd_dc_top_predictor_32x32_c,
+ vpx_highbd_dc_128_predictor_32x32_c, vpx_highbd_v_predictor_32x32_c,
+ vpx_highbd_h_predictor_32x32_c, vpx_highbd_d45_predictor_32x32_c,
+ vpx_highbd_d135_predictor_32x32_c, vpx_highbd_d117_predictor_32x32_c,
+ vpx_highbd_d153_predictor_32x32_c, vpx_highbd_d207_predictor_32x32_c,
+ vpx_highbd_d63_predictor_32x32_c, vpx_highbd_tm_predictor_32x32_c)
+
+#if HAVE_SSE2
+HIGHBD_INTRA_PRED_TEST(
+ SSE2, TestHighbdIntraPred4, vpx_highbd_dc_predictor_4x4_sse2,
+ vpx_highbd_dc_left_predictor_4x4_sse2, vpx_highbd_dc_top_predictor_4x4_sse2,
+ vpx_highbd_dc_128_predictor_4x4_sse2, vpx_highbd_v_predictor_4x4_sse2,
+ vpx_highbd_h_predictor_4x4_sse2, nullptr,
+ vpx_highbd_d135_predictor_4x4_sse2, vpx_highbd_d117_predictor_4x4_sse2,
+ vpx_highbd_d153_predictor_4x4_sse2, vpx_highbd_d207_predictor_4x4_sse2,
+ vpx_highbd_d63_predictor_4x4_sse2, vpx_highbd_tm_predictor_4x4_c)
+
+HIGHBD_INTRA_PRED_TEST(
+ SSE2, TestHighbdIntraPred8, vpx_highbd_dc_predictor_8x8_sse2,
+ vpx_highbd_dc_left_predictor_8x8_sse2, vpx_highbd_dc_top_predictor_8x8_sse2,
+ vpx_highbd_dc_128_predictor_8x8_sse2, vpx_highbd_v_predictor_8x8_sse2,
+ vpx_highbd_h_predictor_8x8_sse2, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, vpx_highbd_tm_predictor_8x8_sse2)
+
+HIGHBD_INTRA_PRED_TEST(SSE2, TestHighbdIntraPred16,
+ vpx_highbd_dc_predictor_16x16_sse2,
+ vpx_highbd_dc_left_predictor_16x16_sse2,
+ vpx_highbd_dc_top_predictor_16x16_sse2,
+ vpx_highbd_dc_128_predictor_16x16_sse2,
+ vpx_highbd_v_predictor_16x16_sse2,
+ vpx_highbd_h_predictor_16x16_sse2, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+ vpx_highbd_tm_predictor_16x16_sse2)
+
+HIGHBD_INTRA_PRED_TEST(SSE2, TestHighbdIntraPred32,
+ vpx_highbd_dc_predictor_32x32_sse2,
+ vpx_highbd_dc_left_predictor_32x32_sse2,
+ vpx_highbd_dc_top_predictor_32x32_sse2,
+ vpx_highbd_dc_128_predictor_32x32_sse2,
+ vpx_highbd_v_predictor_32x32_sse2,
+ vpx_highbd_h_predictor_32x32_sse2, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr,
+ vpx_highbd_tm_predictor_32x32_sse2)
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred4, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr,
+ vpx_highbd_d45_predictor_4x4_ssse3, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr)
+HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred8, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr,
+ vpx_highbd_d45_predictor_8x8_ssse3,
+ vpx_highbd_d135_predictor_8x8_ssse3,
+ vpx_highbd_d117_predictor_8x8_ssse3,
+ vpx_highbd_d153_predictor_8x8_ssse3,
+ vpx_highbd_d207_predictor_8x8_ssse3,
+ vpx_highbd_d63_predictor_8x8_ssse3, nullptr)
+HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred16, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr,
+ vpx_highbd_d45_predictor_16x16_ssse3,
+ vpx_highbd_d135_predictor_16x16_ssse3,
+ vpx_highbd_d117_predictor_16x16_ssse3,
+ vpx_highbd_d153_predictor_16x16_ssse3,
+ vpx_highbd_d207_predictor_16x16_ssse3,
+ vpx_highbd_d63_predictor_16x16_ssse3, nullptr)
+HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred32, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr,
+ vpx_highbd_d45_predictor_32x32_ssse3,
+ vpx_highbd_d135_predictor_32x32_ssse3,
+ vpx_highbd_d117_predictor_32x32_ssse3,
+ vpx_highbd_d153_predictor_32x32_ssse3,
+ vpx_highbd_d207_predictor_32x32_ssse3,
+ vpx_highbd_d63_predictor_32x32_ssse3, nullptr)
+#endif // HAVE_SSSE3
+
+#if HAVE_NEON
+HIGHBD_INTRA_PRED_TEST(
+ NEON, TestHighbdIntraPred4, vpx_highbd_dc_predictor_4x4_neon,
+ vpx_highbd_dc_left_predictor_4x4_neon, vpx_highbd_dc_top_predictor_4x4_neon,
+ vpx_highbd_dc_128_predictor_4x4_neon, vpx_highbd_v_predictor_4x4_neon,
+ vpx_highbd_h_predictor_4x4_neon, vpx_highbd_d45_predictor_4x4_neon,
+ vpx_highbd_d135_predictor_4x4_neon, vpx_highbd_d117_predictor_4x4_neon,
+ vpx_highbd_d153_predictor_4x4_neon, vpx_highbd_d207_predictor_4x4_neon,
+ vpx_highbd_d63_predictor_4x4_neon, vpx_highbd_tm_predictor_4x4_neon)
+HIGHBD_INTRA_PRED_TEST(
+ NEON, TestHighbdIntraPred8, vpx_highbd_dc_predictor_8x8_neon,
+ vpx_highbd_dc_left_predictor_8x8_neon, vpx_highbd_dc_top_predictor_8x8_neon,
+ vpx_highbd_dc_128_predictor_8x8_neon, vpx_highbd_v_predictor_8x8_neon,
+ vpx_highbd_h_predictor_8x8_neon, vpx_highbd_d45_predictor_8x8_neon,
+ vpx_highbd_d135_predictor_8x8_neon, vpx_highbd_d117_predictor_8x8_neon,
+ vpx_highbd_d153_predictor_8x8_neon, vpx_highbd_d207_predictor_8x8_neon,
+ vpx_highbd_d63_predictor_8x8_neon, vpx_highbd_tm_predictor_8x8_neon)
+HIGHBD_INTRA_PRED_TEST(
+ NEON, TestHighbdIntraPred16, vpx_highbd_dc_predictor_16x16_neon,
+ vpx_highbd_dc_left_predictor_16x16_neon,
+ vpx_highbd_dc_top_predictor_16x16_neon,
+ vpx_highbd_dc_128_predictor_16x16_neon, vpx_highbd_v_predictor_16x16_neon,
+ vpx_highbd_h_predictor_16x16_neon, vpx_highbd_d45_predictor_16x16_neon,
+ vpx_highbd_d135_predictor_16x16_neon, vpx_highbd_d117_predictor_16x16_neon,
+ vpx_highbd_d153_predictor_16x16_neon, vpx_highbd_d207_predictor_16x16_neon,
+ vpx_highbd_d63_predictor_16x16_neon, vpx_highbd_tm_predictor_16x16_neon)
+HIGHBD_INTRA_PRED_TEST(
+ NEON, TestHighbdIntraPred32, vpx_highbd_dc_predictor_32x32_neon,
+ vpx_highbd_dc_left_predictor_32x32_neon,
+ vpx_highbd_dc_top_predictor_32x32_neon,
+ vpx_highbd_dc_128_predictor_32x32_neon, vpx_highbd_v_predictor_32x32_neon,
+ vpx_highbd_h_predictor_32x32_neon, vpx_highbd_d45_predictor_32x32_neon,
+ vpx_highbd_d135_predictor_32x32_neon, vpx_highbd_d117_predictor_32x32_neon,
+ vpx_highbd_d153_predictor_32x32_neon, vpx_highbd_d207_predictor_32x32_neon,
+ vpx_highbd_d63_predictor_32x32_neon, vpx_highbd_tm_predictor_32x32_neon)
+#endif // HAVE_NEON
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#include "test/test_libvpx.cc"
diff --git a/media/libvpx/libvpx/test/test_libvpx.cc b/media/libvpx/libvpx/test/test_libvpx.cc
new file mode 100644
index 0000000000..222a83f8c7
--- /dev/null
+++ b/media/libvpx/libvpx/test/test_libvpx.cc
@@ -0,0 +1,75 @@
+/*
+ * 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 <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if VPX_ARCH_X86 || VPX_ARCH_X86_64
+#include "vpx_ports/x86.h"
+#endif
+extern "C" {
+#if CONFIG_VP8
+extern void vp8_rtcd();
+#endif // CONFIG_VP8
+#if CONFIG_VP9
+extern void vp9_rtcd();
+#endif // CONFIG_VP9
+extern void vpx_dsp_rtcd();
+extern void vpx_scale_rtcd();
+}
+
+#if VPX_ARCH_X86 || VPX_ARCH_X86_64
+static void append_negative_gtest_filter(const char *str) {
+ std::string filter = ::testing::FLAGS_gtest_filter;
+ // Negative patterns begin with one '-' followed by a ':' separated list.
+ if (filter.find('-') == std::string::npos) filter += '-';
+ filter += str;
+ ::testing::FLAGS_gtest_filter = filter;
+}
+#endif // VPX_ARCH_X86 || VPX_ARCH_X86_64
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+#if VPX_ARCH_X86 || VPX_ARCH_X86_64
+ const int simd_caps = x86_simd_caps();
+ if (!(simd_caps & HAS_MMX)) append_negative_gtest_filter(":MMX.*:MMX/*");
+ if (!(simd_caps & HAS_SSE)) append_negative_gtest_filter(":SSE.*:SSE/*");
+ if (!(simd_caps & HAS_SSE2)) append_negative_gtest_filter(":SSE2.*:SSE2/*");
+ if (!(simd_caps & HAS_SSE3)) append_negative_gtest_filter(":SSE3.*:SSE3/*");
+ if (!(simd_caps & HAS_SSSE3)) {
+ append_negative_gtest_filter(":SSSE3.*:SSSE3/*");
+ }
+ if (!(simd_caps & HAS_SSE4_1)) {
+ append_negative_gtest_filter(":SSE4_1.*:SSE4_1/*");
+ }
+ if (!(simd_caps & HAS_AVX)) append_negative_gtest_filter(":AVX.*:AVX/*");
+ if (!(simd_caps & HAS_AVX2)) append_negative_gtest_filter(":AVX2.*:AVX2/*");
+ if (!(simd_caps & HAS_AVX512)) {
+ append_negative_gtest_filter(":AVX512.*:AVX512/*");
+ }
+#endif // VPX_ARCH_X86 || VPX_ARCH_X86_64
+
+#if !CONFIG_SHARED
+// Shared library builds don't support whitebox tests
+// that exercise internal symbols.
+#if CONFIG_VP8
+ vp8_rtcd();
+#endif // CONFIG_VP8
+#if CONFIG_VP9
+ vp9_rtcd();
+#endif // CONFIG_VP9
+ vpx_dsp_rtcd();
+ vpx_scale_rtcd();
+#endif // !CONFIG_SHARED
+
+ return RUN_ALL_TESTS();
+}
diff --git a/media/libvpx/libvpx/test/test_rc_interface.cc b/media/libvpx/libvpx/test/test_rc_interface.cc
new file mode 100644
index 0000000000..ec75700f73
--- /dev/null
+++ b/media/libvpx/libvpx/test/test_rc_interface.cc
@@ -0,0 +1,6 @@
+#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/media/libvpx/libvpx/test/test_vector_test.cc b/media/libvpx/libvpx/test/test_vector_test.cc
new file mode 100644
index 0000000000..ca990f4dd4
--- /dev/null
+++ b/media/libvpx/libvpx/test/test_vector_test.cc
@@ -0,0 +1,205 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <memory>
+#include <set>
+#include <string>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "../tools_common.h"
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+const int kThreads = 0;
+const int kMtMode = 1;
+const int kFileName = 2;
+
+typedef std::tuple<int, int, const char *> DecodeParam;
+
+class TestVectorTest : public ::libvpx_test::DecoderTest,
+ public ::libvpx_test::CodecTestWithParam<DecodeParam> {
+ protected:
+ TestVectorTest() : DecoderTest(GET_PARAM(0)), md5_file_(nullptr) {
+#if CONFIG_VP9_DECODER
+ resize_clips_.insert(::libvpx_test::kVP9TestVectorsResize,
+ ::libvpx_test::kVP9TestVectorsResize +
+ ::libvpx_test::kNumVP9TestVectorsResize);
+#endif
+ }
+
+ virtual ~TestVectorTest() {
+ if (md5_file_) fclose(md5_file_);
+ }
+
+ void OpenMD5File(const std::string &md5_file_name_) {
+ md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+ ASSERT_NE(md5_file_, nullptr)
+ << "Md5 file open failed. Filename: " << md5_file_name_;
+ }
+
+#if CONFIG_VP9_DECODER
+ virtual void PreDecodeFrameHook(
+ const libvpx_test::CompressedVideoSource &video,
+ libvpx_test::Decoder *decoder) {
+ if (video.frame_number() == 0 && mt_mode_ >= 0) {
+ if (mt_mode_ == 1) {
+ decoder->Control(VP9D_SET_LOOP_FILTER_OPT, 1);
+ decoder->Control(VP9D_SET_ROW_MT, 0);
+ } else if (mt_mode_ == 2) {
+ decoder->Control(VP9D_SET_LOOP_FILTER_OPT, 0);
+ decoder->Control(VP9D_SET_ROW_MT, 1);
+ } else {
+ decoder->Control(VP9D_SET_LOOP_FILTER_OPT, 0);
+ decoder->Control(VP9D_SET_ROW_MT, 0);
+ }
+ }
+ }
+#endif
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ const unsigned int frame_number) {
+ ASSERT_NE(md5_file_, nullptr);
+ char expected_md5[33];
+ char junk[128];
+
+ // Read correct md5 checksums.
+ const int res = fscanf(md5_file_, "%s %s", expected_md5, junk);
+ ASSERT_NE(res, EOF) << "Read md5 data failed";
+ expected_md5[32] = '\0';
+
+ ::libvpx_test::MD5 md5_res;
+ md5_res.Add(&img);
+ const char *actual_md5 = md5_res.Get();
+
+ // Check md5 match.
+ ASSERT_STREQ(expected_md5, actual_md5)
+ << "Md5 checksums don't match: frame number = " << frame_number;
+ }
+
+#if CONFIG_VP9_DECODER
+ std::set<std::string> resize_clips_;
+#endif
+ int mt_mode_;
+
+ private:
+ FILE *md5_file_;
+};
+
+// This test runs through the whole set of test vectors, and decodes them.
+// The md5 checksums are computed for each frame in the video file. If md5
+// checksums match the correct md5 data, then the test is passed. Otherwise,
+// the test failed.
+TEST_P(TestVectorTest, MD5Match) {
+ const DecodeParam input = GET_PARAM(1);
+ const std::string filename = std::get<kFileName>(input);
+ vpx_codec_flags_t flags = 0;
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ char str[256];
+
+ cfg.threads = std::get<kThreads>(input);
+ mt_mode_ = std::get<kMtMode>(input);
+ snprintf(str, sizeof(str) / sizeof(str[0]) - 1,
+ "file: %s threads: %d MT mode: %d", filename.c_str(), cfg.threads,
+ mt_mode_);
+ SCOPED_TRACE(str);
+
+ // Open compressed video file.
+ std::unique_ptr<libvpx_test::CompressedVideoSource> video;
+ if (filename.substr(filename.length() - 3, 3) == "ivf") {
+ video.reset(new libvpx_test::IVFVideoSource(filename));
+ } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+#if CONFIG_WEBM_IO
+ video.reset(new libvpx_test::WebMVideoSource(filename));
+#else
+ fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+ filename.c_str());
+ return;
+#endif
+ }
+ ASSERT_NE(video.get(), nullptr);
+ video->Init();
+
+ // Construct md5 file name.
+ const std::string md5_filename = filename + ".md5";
+ OpenMD5File(md5_filename);
+
+ // Set decode config and flags.
+ set_cfg(cfg);
+ set_flags(flags);
+
+ // Decode frame, and check the md5 matching.
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get(), cfg));
+}
+
+#if CONFIG_VP8_DECODER
+VP8_INSTANTIATE_TEST_SUITE(
+ TestVectorTest,
+ ::testing::Combine(
+ ::testing::Values(1), // Single thread.
+ ::testing::Values(-1), // LPF opt and Row MT is not applicable
+ ::testing::ValuesIn(libvpx_test::kVP8TestVectors,
+ libvpx_test::kVP8TestVectors +
+ libvpx_test::kNumVP8TestVectors)));
+
+// Test VP8 decode in with different numbers of threads.
+INSTANTIATE_TEST_SUITE_P(
+ VP8MultiThreaded, TestVectorTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP8)),
+ ::testing::Combine(
+ ::testing::Range(2, 9), // With 2 ~ 8 threads.
+ ::testing::Values(-1), // LPF opt and Row MT is not applicable
+ ::testing::ValuesIn(libvpx_test::kVP8TestVectors,
+ libvpx_test::kVP8TestVectors +
+ libvpx_test::kNumVP8TestVectors))));
+
+#endif // CONFIG_VP8_DECODER
+
+#if CONFIG_VP9_DECODER
+VP9_INSTANTIATE_TEST_SUITE(
+ TestVectorTest,
+ ::testing::Combine(
+ ::testing::Values(1), // Single thread.
+ ::testing::Values(-1), // LPF opt and Row MT is not applicable
+ ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
+ libvpx_test::kVP9TestVectors +
+ libvpx_test::kNumVP9TestVectors)));
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9MultiThreaded, TestVectorTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
+ ::testing::Combine(
+ ::testing::Range(2, 9), // With 2 ~ 8 threads.
+ ::testing::Range(0, 3), // With multi threads modes 0 ~ 2
+ // 0: LPF opt and Row MT disabled
+ // 1: LPF opt enabled
+ // 2: Row MT enabled
+ ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
+ libvpx_test::kVP9TestVectors +
+ libvpx_test::kNumVP9TestVectors))));
+#endif
+} // namespace
diff --git a/media/libvpx/libvpx/test/test_vectors.cc b/media/libvpx/libvpx/test/test_vectors.cc
new file mode 100644
index 0000000000..3ffc3efc41
--- /dev/null
+++ b/media/libvpx/libvpx/test/test_vectors.cc
@@ -0,0 +1,385 @@
+/*
+ * 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 "test/test_vectors.h"
+
+namespace libvpx_test {
+
+#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
+
+#if CONFIG_VP8_DECODER
+const char *const kVP8TestVectors[] = {
+ "vp80-00-comprehensive-001.ivf", "vp80-00-comprehensive-002.ivf",
+ "vp80-00-comprehensive-003.ivf", "vp80-00-comprehensive-004.ivf",
+ "vp80-00-comprehensive-005.ivf", "vp80-00-comprehensive-006.ivf",
+ "vp80-00-comprehensive-007.ivf", "vp80-00-comprehensive-008.ivf",
+ "vp80-00-comprehensive-009.ivf", "vp80-00-comprehensive-010.ivf",
+ "vp80-00-comprehensive-011.ivf", "vp80-00-comprehensive-012.ivf",
+ "vp80-00-comprehensive-013.ivf", "vp80-00-comprehensive-014.ivf",
+ "vp80-00-comprehensive-015.ivf", "vp80-00-comprehensive-016.ivf",
+ "vp80-00-comprehensive-017.ivf", "vp80-00-comprehensive-018.ivf",
+ "vp80-01-intra-1400.ivf", "vp80-01-intra-1411.ivf",
+ "vp80-01-intra-1416.ivf", "vp80-01-intra-1417.ivf",
+ "vp80-02-inter-1402.ivf", "vp80-02-inter-1412.ivf",
+ "vp80-02-inter-1418.ivf", "vp80-02-inter-1424.ivf",
+ "vp80-03-segmentation-01.ivf", "vp80-03-segmentation-02.ivf",
+ "vp80-03-segmentation-03.ivf", "vp80-03-segmentation-04.ivf",
+ "vp80-03-segmentation-1401.ivf", "vp80-03-segmentation-1403.ivf",
+ "vp80-03-segmentation-1407.ivf", "vp80-03-segmentation-1408.ivf",
+ "vp80-03-segmentation-1409.ivf", "vp80-03-segmentation-1410.ivf",
+ "vp80-03-segmentation-1413.ivf", "vp80-03-segmentation-1414.ivf",
+ "vp80-03-segmentation-1415.ivf", "vp80-03-segmentation-1425.ivf",
+ "vp80-03-segmentation-1426.ivf", "vp80-03-segmentation-1427.ivf",
+ "vp80-03-segmentation-1432.ivf", "vp80-03-segmentation-1435.ivf",
+ "vp80-03-segmentation-1436.ivf", "vp80-03-segmentation-1437.ivf",
+ "vp80-03-segmentation-1441.ivf", "vp80-03-segmentation-1442.ivf",
+ "vp80-04-partitions-1404.ivf", "vp80-04-partitions-1405.ivf",
+ "vp80-04-partitions-1406.ivf", "vp80-05-sharpness-1428.ivf",
+ "vp80-05-sharpness-1429.ivf", "vp80-05-sharpness-1430.ivf",
+ "vp80-05-sharpness-1431.ivf", "vp80-05-sharpness-1433.ivf",
+ "vp80-05-sharpness-1434.ivf", "vp80-05-sharpness-1438.ivf",
+ "vp80-05-sharpness-1439.ivf", "vp80-05-sharpness-1440.ivf",
+ "vp80-05-sharpness-1443.ivf", "vp80-06-smallsize.ivf"
+};
+const int kNumVP8TestVectors = NELEMENTS(kVP8TestVectors);
+#endif // CONFIG_VP8_DECODER
+#if CONFIG_VP9_DECODER
+#define RESIZE_TEST_VECTORS \
+ "vp90-2-21-resize_inter_320x180_5_1-2.webm", \
+ "vp90-2-21-resize_inter_320x180_5_3-4.webm", \
+ "vp90-2-21-resize_inter_320x180_7_1-2.webm", \
+ "vp90-2-21-resize_inter_320x180_7_3-4.webm", \
+ "vp90-2-21-resize_inter_320x240_5_1-2.webm", \
+ "vp90-2-21-resize_inter_320x240_5_3-4.webm", \
+ "vp90-2-21-resize_inter_320x240_7_1-2.webm", \
+ "vp90-2-21-resize_inter_320x240_7_3-4.webm", \
+ "vp90-2-21-resize_inter_640x360_5_1-2.webm", \
+ "vp90-2-21-resize_inter_640x360_5_3-4.webm", \
+ "vp90-2-21-resize_inter_640x360_7_1-2.webm", \
+ "vp90-2-21-resize_inter_640x360_7_3-4.webm", \
+ "vp90-2-21-resize_inter_640x480_5_1-2.webm", \
+ "vp90-2-21-resize_inter_640x480_5_3-4.webm", \
+ "vp90-2-21-resize_inter_640x480_7_1-2.webm", \
+ "vp90-2-21-resize_inter_640x480_7_3-4.webm", \
+ "vp90-2-21-resize_inter_1280x720_5_1-2.webm", \
+ "vp90-2-21-resize_inter_1280x720_5_3-4.webm", \
+ "vp90-2-21-resize_inter_1280x720_7_1-2.webm", \
+ "vp90-2-21-resize_inter_1280x720_7_3-4.webm", \
+ "vp90-2-21-resize_inter_1920x1080_5_1-2.webm", \
+ "vp90-2-21-resize_inter_1920x1080_5_3-4.webm", \
+ "vp90-2-21-resize_inter_1920x1080_7_1-2.webm", \
+ "vp90-2-21-resize_inter_1920x1080_7_3-4.webm",
+
+const char *const kVP9TestVectors[] = {
+ "vp90-2-00-quantizer-00.webm",
+ "vp90-2-00-quantizer-01.webm",
+ "vp90-2-00-quantizer-02.webm",
+ "vp90-2-00-quantizer-03.webm",
+ "vp90-2-00-quantizer-04.webm",
+ "vp90-2-00-quantizer-05.webm",
+ "vp90-2-00-quantizer-06.webm",
+ "vp90-2-00-quantizer-07.webm",
+ "vp90-2-00-quantizer-08.webm",
+ "vp90-2-00-quantizer-09.webm",
+ "vp90-2-00-quantizer-10.webm",
+ "vp90-2-00-quantizer-11.webm",
+ "vp90-2-00-quantizer-12.webm",
+ "vp90-2-00-quantizer-13.webm",
+ "vp90-2-00-quantizer-14.webm",
+ "vp90-2-00-quantizer-15.webm",
+ "vp90-2-00-quantizer-16.webm",
+ "vp90-2-00-quantizer-17.webm",
+ "vp90-2-00-quantizer-18.webm",
+ "vp90-2-00-quantizer-19.webm",
+ "vp90-2-00-quantizer-20.webm",
+ "vp90-2-00-quantizer-21.webm",
+ "vp90-2-00-quantizer-22.webm",
+ "vp90-2-00-quantizer-23.webm",
+ "vp90-2-00-quantizer-24.webm",
+ "vp90-2-00-quantizer-25.webm",
+ "vp90-2-00-quantizer-26.webm",
+ "vp90-2-00-quantizer-27.webm",
+ "vp90-2-00-quantizer-28.webm",
+ "vp90-2-00-quantizer-29.webm",
+ "vp90-2-00-quantizer-30.webm",
+ "vp90-2-00-quantizer-31.webm",
+ "vp90-2-00-quantizer-32.webm",
+ "vp90-2-00-quantizer-33.webm",
+ "vp90-2-00-quantizer-34.webm",
+ "vp90-2-00-quantizer-35.webm",
+ "vp90-2-00-quantizer-36.webm",
+ "vp90-2-00-quantizer-37.webm",
+ "vp90-2-00-quantizer-38.webm",
+ "vp90-2-00-quantizer-39.webm",
+ "vp90-2-00-quantizer-40.webm",
+ "vp90-2-00-quantizer-41.webm",
+ "vp90-2-00-quantizer-42.webm",
+ "vp90-2-00-quantizer-43.webm",
+ "vp90-2-00-quantizer-44.webm",
+ "vp90-2-00-quantizer-45.webm",
+ "vp90-2-00-quantizer-46.webm",
+ "vp90-2-00-quantizer-47.webm",
+ "vp90-2-00-quantizer-48.webm",
+ "vp90-2-00-quantizer-49.webm",
+ "vp90-2-00-quantizer-50.webm",
+ "vp90-2-00-quantizer-51.webm",
+ "vp90-2-00-quantizer-52.webm",
+ "vp90-2-00-quantizer-53.webm",
+ "vp90-2-00-quantizer-54.webm",
+ "vp90-2-00-quantizer-55.webm",
+ "vp90-2-00-quantizer-56.webm",
+ "vp90-2-00-quantizer-57.webm",
+ "vp90-2-00-quantizer-58.webm",
+ "vp90-2-00-quantizer-59.webm",
+ "vp90-2-00-quantizer-60.webm",
+ "vp90-2-00-quantizer-61.webm",
+ "vp90-2-00-quantizer-62.webm",
+ "vp90-2-00-quantizer-63.webm",
+ "vp90-2-01-sharpness-1.webm",
+ "vp90-2-01-sharpness-2.webm",
+ "vp90-2-01-sharpness-3.webm",
+ "vp90-2-01-sharpness-4.webm",
+ "vp90-2-01-sharpness-5.webm",
+ "vp90-2-01-sharpness-6.webm",
+ "vp90-2-01-sharpness-7.webm",
+ "vp90-2-02-size-08x08.webm",
+ "vp90-2-02-size-08x10.webm",
+ "vp90-2-02-size-08x16.webm",
+ "vp90-2-02-size-08x18.webm",
+ "vp90-2-02-size-08x32.webm",
+ "vp90-2-02-size-08x34.webm",
+ "vp90-2-02-size-08x64.webm",
+ "vp90-2-02-size-08x66.webm",
+ "vp90-2-02-size-10x08.webm",
+ "vp90-2-02-size-10x10.webm",
+ "vp90-2-02-size-10x16.webm",
+ "vp90-2-02-size-10x18.webm",
+ "vp90-2-02-size-10x32.webm",
+ "vp90-2-02-size-10x34.webm",
+ "vp90-2-02-size-10x64.webm",
+ "vp90-2-02-size-10x66.webm",
+ "vp90-2-02-size-16x08.webm",
+ "vp90-2-02-size-16x10.webm",
+ "vp90-2-02-size-16x16.webm",
+ "vp90-2-02-size-16x18.webm",
+ "vp90-2-02-size-16x32.webm",
+ "vp90-2-02-size-16x34.webm",
+ "vp90-2-02-size-16x64.webm",
+ "vp90-2-02-size-16x66.webm",
+ "vp90-2-02-size-18x08.webm",
+ "vp90-2-02-size-18x10.webm",
+ "vp90-2-02-size-18x16.webm",
+ "vp90-2-02-size-18x18.webm",
+ "vp90-2-02-size-18x32.webm",
+ "vp90-2-02-size-18x34.webm",
+ "vp90-2-02-size-18x64.webm",
+ "vp90-2-02-size-18x66.webm",
+ "vp90-2-02-size-32x08.webm",
+ "vp90-2-02-size-32x10.webm",
+ "vp90-2-02-size-32x16.webm",
+ "vp90-2-02-size-32x18.webm",
+ "vp90-2-02-size-32x32.webm",
+ "vp90-2-02-size-32x34.webm",
+ "vp90-2-02-size-32x64.webm",
+ "vp90-2-02-size-32x66.webm",
+ "vp90-2-02-size-34x08.webm",
+ "vp90-2-02-size-34x10.webm",
+ "vp90-2-02-size-34x16.webm",
+ "vp90-2-02-size-34x18.webm",
+ "vp90-2-02-size-34x32.webm",
+ "vp90-2-02-size-34x34.webm",
+ "vp90-2-02-size-34x64.webm",
+ "vp90-2-02-size-34x66.webm",
+ "vp90-2-02-size-64x08.webm",
+ "vp90-2-02-size-64x10.webm",
+ "vp90-2-02-size-64x16.webm",
+ "vp90-2-02-size-64x18.webm",
+ "vp90-2-02-size-64x32.webm",
+ "vp90-2-02-size-64x34.webm",
+ "vp90-2-02-size-64x64.webm",
+ "vp90-2-02-size-64x66.webm",
+ "vp90-2-02-size-66x08.webm",
+ "vp90-2-02-size-66x10.webm",
+ "vp90-2-02-size-66x16.webm",
+ "vp90-2-02-size-66x18.webm",
+ "vp90-2-02-size-66x32.webm",
+ "vp90-2-02-size-66x34.webm",
+ "vp90-2-02-size-66x64.webm",
+ "vp90-2-02-size-66x66.webm",
+ "vp90-2-02-size-130x132.webm",
+ "vp90-2-02-size-132x130.webm",
+ "vp90-2-02-size-132x132.webm",
+ "vp90-2-02-size-178x180.webm",
+ "vp90-2-02-size-180x178.webm",
+ "vp90-2-02-size-180x180.webm",
+ "vp90-2-03-size-196x196.webm",
+ "vp90-2-03-size-196x198.webm",
+ "vp90-2-03-size-196x200.webm",
+ "vp90-2-03-size-196x202.webm",
+ "vp90-2-03-size-196x208.webm",
+ "vp90-2-03-size-196x210.webm",
+ "vp90-2-03-size-196x224.webm",
+ "vp90-2-03-size-196x226.webm",
+ "vp90-2-03-size-198x196.webm",
+ "vp90-2-03-size-198x198.webm",
+ "vp90-2-03-size-198x200.webm",
+ "vp90-2-03-size-198x202.webm",
+ "vp90-2-03-size-198x208.webm",
+ "vp90-2-03-size-198x210.webm",
+ "vp90-2-03-size-198x224.webm",
+ "vp90-2-03-size-198x226.webm",
+ "vp90-2-03-size-200x196.webm",
+ "vp90-2-03-size-200x198.webm",
+ "vp90-2-03-size-200x200.webm",
+ "vp90-2-03-size-200x202.webm",
+ "vp90-2-03-size-200x208.webm",
+ "vp90-2-03-size-200x210.webm",
+ "vp90-2-03-size-200x224.webm",
+ "vp90-2-03-size-200x226.webm",
+ "vp90-2-03-size-202x196.webm",
+ "vp90-2-03-size-202x198.webm",
+ "vp90-2-03-size-202x200.webm",
+ "vp90-2-03-size-202x202.webm",
+ "vp90-2-03-size-202x208.webm",
+ "vp90-2-03-size-202x210.webm",
+ "vp90-2-03-size-202x224.webm",
+ "vp90-2-03-size-202x226.webm",
+ "vp90-2-03-size-208x196.webm",
+ "vp90-2-03-size-208x198.webm",
+ "vp90-2-03-size-208x200.webm",
+ "vp90-2-03-size-208x202.webm",
+ "vp90-2-03-size-208x208.webm",
+ "vp90-2-03-size-208x210.webm",
+ "vp90-2-03-size-208x224.webm",
+ "vp90-2-03-size-208x226.webm",
+ "vp90-2-03-size-210x196.webm",
+ "vp90-2-03-size-210x198.webm",
+ "vp90-2-03-size-210x200.webm",
+ "vp90-2-03-size-210x202.webm",
+ "vp90-2-03-size-210x208.webm",
+ "vp90-2-03-size-210x210.webm",
+ "vp90-2-03-size-210x224.webm",
+ "vp90-2-03-size-210x226.webm",
+ "vp90-2-03-size-224x196.webm",
+ "vp90-2-03-size-224x198.webm",
+ "vp90-2-03-size-224x200.webm",
+ "vp90-2-03-size-224x202.webm",
+ "vp90-2-03-size-224x208.webm",
+ "vp90-2-03-size-224x210.webm",
+ "vp90-2-03-size-224x224.webm",
+ "vp90-2-03-size-224x226.webm",
+ "vp90-2-03-size-226x196.webm",
+ "vp90-2-03-size-226x198.webm",
+ "vp90-2-03-size-226x200.webm",
+ "vp90-2-03-size-226x202.webm",
+ "vp90-2-03-size-226x208.webm",
+ "vp90-2-03-size-226x210.webm",
+ "vp90-2-03-size-226x224.webm",
+ "vp90-2-03-size-226x226.webm",
+ "vp90-2-03-size-352x288.webm",
+ "vp90-2-03-deltaq.webm",
+ "vp90-2-05-resize.ivf",
+ "vp90-2-06-bilinear.webm",
+ "vp90-2-07-frame_parallel.webm",
+ "vp90-2-08-tile_1x2_frame_parallel.webm",
+ "vp90-2-08-tile_1x2.webm",
+ "vp90-2-08-tile_1x4_frame_parallel.webm",
+ "vp90-2-08-tile_1x4.webm",
+ "vp90-2-08-tile_1x8_frame_parallel.webm",
+ "vp90-2-08-tile_1x8.webm",
+ "vp90-2-08-tile-4x4.webm",
+ "vp90-2-08-tile-4x1.webm",
+ "vp90-2-09-subpixel-00.ivf",
+ "vp90-2-02-size-lf-1920x1080.webm",
+ "vp90-2-09-aq2.webm",
+ "vp90-2-09-lf_deltas.webm",
+ "vp90-2-10-show-existing-frame.webm",
+ "vp90-2-10-show-existing-frame2.webm",
+ "vp90-2-11-size-351x287.webm",
+ "vp90-2-11-size-351x288.webm",
+ "vp90-2-11-size-352x287.webm",
+ "vp90-2-12-droppable_1.ivf",
+ "vp90-2-12-droppable_2.ivf",
+ "vp90-2-12-droppable_3.ivf",
+#if !CONFIG_SIZE_LIMIT || \
+ (DECODE_WIDTH_LIMIT >= 20400 && DECODE_HEIGHT_LIMIT >= 120)
+ "vp90-2-13-largescaling.webm",
+#endif
+ "vp90-2-14-resize-fp-tiles-1-16.webm",
+ "vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm",
+ "vp90-2-14-resize-fp-tiles-1-2.webm",
+ "vp90-2-14-resize-fp-tiles-1-4.webm",
+ "vp90-2-14-resize-fp-tiles-16-1.webm",
+ "vp90-2-14-resize-fp-tiles-16-2.webm",
+ "vp90-2-14-resize-fp-tiles-16-4.webm",
+ "vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm",
+ "vp90-2-14-resize-fp-tiles-16-8.webm",
+ "vp90-2-14-resize-fp-tiles-1-8.webm",
+ "vp90-2-14-resize-fp-tiles-2-16.webm",
+ "vp90-2-14-resize-fp-tiles-2-1.webm",
+ "vp90-2-14-resize-fp-tiles-2-4.webm",
+ "vp90-2-14-resize-fp-tiles-2-8.webm",
+ "vp90-2-14-resize-fp-tiles-4-16.webm",
+ "vp90-2-14-resize-fp-tiles-4-1.webm",
+ "vp90-2-14-resize-fp-tiles-4-2.webm",
+ "vp90-2-14-resize-fp-tiles-4-8.webm",
+ "vp90-2-14-resize-fp-tiles-8-16.webm",
+ "vp90-2-14-resize-fp-tiles-8-1.webm",
+ "vp90-2-14-resize-fp-tiles-8-2.webm",
+ "vp90-2-14-resize-fp-tiles-8-4.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-1-2.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-1-4.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-1-8.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-2-1.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-2-4.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-2-8.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-4-1.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-4-2.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-4-8.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-8-1.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-8-2.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm",
+ "vp90-2-14-resize-10frames-fp-tiles-8-4.webm",
+ "vp90-2-15-segkey.webm",
+ "vp90-2-15-segkey_adpq.webm",
+ "vp90-2-16-intra-only.webm",
+ "vp90-2-17-show-existing-frame.webm",
+ "vp90-2-18-resize.ivf",
+ "vp90-2-19-skip.webm",
+ "vp90-2-19-skip-01.webm",
+ "vp90-2-19-skip-02.webm",
+ "vp91-2-04-yuv444.webm",
+ "vp91-2-04-yuv422.webm",
+ "vp91-2-04-yuv440.webm",
+#if CONFIG_VP9_HIGHBITDEPTH
+ "vp92-2-20-10bit-yuv420.webm",
+ "vp92-2-20-12bit-yuv420.webm",
+ "vp93-2-20-10bit-yuv422.webm",
+ "vp93-2-20-12bit-yuv422.webm",
+ "vp93-2-20-10bit-yuv440.webm",
+ "vp93-2-20-12bit-yuv440.webm",
+ "vp93-2-20-10bit-yuv444.webm",
+ "vp93-2-20-12bit-yuv444.webm",
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ "vp90-2-20-big_superframe-01.webm",
+ "vp90-2-20-big_superframe-02.webm",
+ "vp90-2-22-svc_1280x720_1.webm",
+ RESIZE_TEST_VECTORS
+};
+const char *const kVP9TestVectorsSvc[] = { "vp90-2-22-svc_1280x720_3.ivf" };
+const int kNumVP9TestVectors = NELEMENTS(kVP9TestVectors);
+const int kNumVP9TestVectorsSvc = NELEMENTS(kVP9TestVectorsSvc);
+const char *const kVP9TestVectorsResize[] = { RESIZE_TEST_VECTORS };
+const int kNumVP9TestVectorsResize = NELEMENTS(kVP9TestVectorsResize);
+#undef RESIZE_TEST_VECTORS
+#endif // CONFIG_VP9_DECODER
+
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/test_vectors.h b/media/libvpx/libvpx/test/test_vectors.h
new file mode 100644
index 0000000000..0a4be0f1a2
--- /dev/null
+++ b/media/libvpx/libvpx/test/test_vectors.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef VPX_TEST_TEST_VECTORS_H_
+#define VPX_TEST_TEST_VECTORS_H_
+
+#include "./vpx_config.h"
+
+namespace libvpx_test {
+
+#if CONFIG_VP8_DECODER
+extern const int kNumVP8TestVectors;
+extern const char *const kVP8TestVectors[];
+#endif
+
+#if CONFIG_VP9_DECODER
+extern const int kNumVP9TestVectors;
+extern const char *const kVP9TestVectors[];
+extern const int kNumVP9TestVectorsSvc;
+extern const char *const kVP9TestVectorsSvc[];
+extern const int kNumVP9TestVectorsResize;
+extern const char *const kVP9TestVectorsResize[];
+#endif // CONFIG_VP9_DECODER
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_TEST_VECTORS_H_
diff --git a/media/libvpx/libvpx/test/tile_independence_test.cc b/media/libvpx/libvpx/test/tile_independence_test.cc
new file mode 100644
index 0000000000..d92c13f88e
--- /dev/null
+++ b/media/libvpx/libvpx/test/tile_independence_test.cc
@@ -0,0 +1,104 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <string>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/md5_helper.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+class TileIndependenceTest : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+ TileIndependenceTest()
+ : EncoderTest(GET_PARAM(0)), md5_fw_order_(), md5_inv_order_(),
+ n_tiles_(GET_PARAM(1)) {
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ cfg.w = 704;
+ cfg.h = 144;
+ cfg.threads = 1;
+ fw_dec_ = codec_->CreateDecoder(cfg, 0);
+ inv_dec_ = codec_->CreateDecoder(cfg, 0);
+ inv_dec_->Control(VP9_INVERT_TILE_DECODE_ORDER, 1);
+ }
+
+ virtual ~TileIndependenceTest() {
+ delete fw_dec_;
+ delete inv_dec_;
+ }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(libvpx_test::kTwoPassGood);
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_TILE_COLUMNS, n_tiles_);
+ }
+ }
+
+ void UpdateMD5(::libvpx_test::Decoder *dec, const vpx_codec_cx_pkt_t *pkt,
+ ::libvpx_test::MD5 *md5) {
+ const vpx_codec_err_t res = dec->DecodeFrame(
+ reinterpret_cast<uint8_t *>(pkt->data.frame.buf), pkt->data.frame.sz);
+ if (res != VPX_CODEC_OK) {
+ abort_ = true;
+ ASSERT_EQ(VPX_CODEC_OK, res);
+ }
+ const vpx_image_t *img = dec->GetDxData().Next();
+ md5->Add(img);
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ UpdateMD5(fw_dec_, pkt, &md5_fw_order_);
+ UpdateMD5(inv_dec_, pkt, &md5_inv_order_);
+ }
+
+ ::libvpx_test::MD5 md5_fw_order_, md5_inv_order_;
+ ::libvpx_test::Decoder *fw_dec_, *inv_dec_;
+
+ private:
+ int n_tiles_;
+};
+
+// run an encode with 2 or 4 tiles, and do the decode both in normal and
+// inverted tile ordering. Ensure that the MD5 of the output in both cases
+// is identical. If so, tiles are considered independent and the test passes.
+TEST_P(TileIndependenceTest, MD5Match) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_end_usage = VPX_VBR;
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 704, 144,
+ timebase.den, timebase.num, 0, 30);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ const char *md5_fw_str = md5_fw_order_.Get();
+ const char *md5_inv_str = md5_inv_order_.Get();
+
+ // could use ASSERT_EQ(!memcmp(.., .., 16) here, but this gives nicer
+ // output if it fails. Not sure if it's helpful since it's really just
+ // a MD5...
+ ASSERT_STREQ(md5_fw_str, md5_inv_str);
+}
+
+VP9_INSTANTIATE_TEST_SUITE(TileIndependenceTest, ::testing::Range(0, 2, 1));
+} // namespace
diff --git a/media/libvpx/libvpx/test/timestamp_test.cc b/media/libvpx/libvpx/test/timestamp_test.cc
new file mode 100644
index 0000000000..645a9f2ff8
--- /dev/null
+++ b/media/libvpx/libvpx/test/timestamp_test.cc
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2019 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/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace {
+
+const int kVideoSourceWidth = 320;
+const int kVideoSourceHeight = 240;
+const int kFramesToEncode = 3;
+
+// A video source that exposes functions to set the timebase, framerate and
+// starting pts.
+class DummyTimebaseVideoSource : public ::libvpx_test::DummyVideoSource {
+ public:
+ // Parameters num and den set the timebase for the video source.
+ DummyTimebaseVideoSource(int num, int den)
+ : timebase_({ num, den }), framerate_numerator_(30),
+ framerate_denominator_(1), starting_pts_(0) {
+ SetSize(kVideoSourceWidth, kVideoSourceHeight);
+ set_limit(kFramesToEncode);
+ }
+
+ void SetFramerate(int numerator, int denominator) {
+ framerate_numerator_ = numerator;
+ framerate_denominator_ = denominator;
+ }
+
+ // Returns one frames duration in timebase units as a double.
+ double FrameDuration() const {
+ return (static_cast<double>(timebase_.den) / timebase_.num) /
+ (static_cast<double>(framerate_numerator_) / framerate_denominator_);
+ }
+
+ virtual vpx_codec_pts_t pts() const {
+ return static_cast<vpx_codec_pts_t>(frame_ * FrameDuration() +
+ starting_pts_ + 0.5);
+ }
+
+ virtual unsigned long duration() const {
+ return static_cast<unsigned long>(FrameDuration() + 0.5);
+ }
+
+ virtual vpx_rational_t timebase() const { return timebase_; }
+
+ void set_starting_pts(int64_t starting_pts) { starting_pts_ = starting_pts; }
+
+ private:
+ vpx_rational_t timebase_;
+ int framerate_numerator_;
+ int framerate_denominator_;
+ int64_t starting_pts_;
+};
+
+class TimestampTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ TimestampTest() : EncoderTest(GET_PARAM(0)) {}
+ virtual ~TimestampTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ }
+};
+
+// Tests encoding in millisecond timebase.
+TEST_P(TimestampTest, EncodeFrames) {
+ DummyTimebaseVideoSource video(1, 1000);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(TimestampTest, TestMicrosecondTimebase) {
+ // Set the timebase to microseconds.
+ DummyTimebaseVideoSource video(1, 1000000);
+ video.set_limit(1);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(TimestampTest, TestVpxRollover) {
+ DummyTimebaseVideoSource video(1, 1000);
+ video.set_starting_pts(922337170351ll);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP8_INSTANTIATE_TEST_SUITE(TimestampTest,
+ ::testing::Values(::libvpx_test::kTwoPassGood));
+VP9_INSTANTIATE_TEST_SUITE(TimestampTest,
+ ::testing::Values(::libvpx_test::kTwoPassGood));
+} // namespace
diff --git a/media/libvpx/libvpx/test/tools_common.sh b/media/libvpx/libvpx/test/tools_common.sh
new file mode 100755
index 0000000000..0e4a0a5c0e
--- /dev/null
+++ b/media/libvpx/libvpx/test/tools_common.sh
@@ -0,0 +1,442 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file contains shell code shared by test scripts for libvpx tools.
+
+# Use $VPX_TEST_TOOLS_COMMON_SH as a pseudo include guard.
+if [ -z "${VPX_TEST_TOOLS_COMMON_SH}" ]; then
+VPX_TEST_TOOLS_COMMON_SH=included
+
+set -e
+devnull='> /dev/null 2>&1'
+VPX_TEST_PREFIX=""
+
+elog() {
+ echo "$@" 1>&2
+}
+
+vlog() {
+ if [ "${VPX_TEST_VERBOSE_OUTPUT}" = "yes" ]; then
+ echo "$@"
+ fi
+}
+
+# Sets $VPX_TOOL_TEST to the name specified by positional parameter one.
+test_begin() {
+ VPX_TOOL_TEST="${1}"
+}
+
+# Clears the VPX_TOOL_TEST variable after confirming that $VPX_TOOL_TEST matches
+# positional parameter one.
+test_end() {
+ if [ "$1" != "${VPX_TOOL_TEST}" ]; then
+ echo "FAIL completed test mismatch!."
+ echo " completed test: ${1}"
+ echo " active test: ${VPX_TOOL_TEST}."
+ return 1
+ fi
+ VPX_TOOL_TEST='<unset>'
+}
+
+# Echoes the target configuration being tested.
+test_configuration_target() {
+ vpx_config_mk="${LIBVPX_CONFIG_PATH}/config.mk"
+ # Find the TOOLCHAIN line, split it using ':=' as the field separator, and
+ # print the last field to get the value. Then pipe the value to tr to consume
+ # any leading/trailing spaces while allowing tr to echo the output to stdout.
+ awk -F ':=' '/TOOLCHAIN/ { print $NF }' "${vpx_config_mk}" | tr -d ' '
+}
+
+# Trap function used for failure reports and tool output directory removal.
+# When the contents of $VPX_TOOL_TEST do not match the string '<unset>', reports
+# failure of test stored in $VPX_TOOL_TEST.
+cleanup() {
+ if [ -n "${VPX_TOOL_TEST}" ] && [ "${VPX_TOOL_TEST}" != '<unset>' ]; then
+ echo "FAIL: $VPX_TOOL_TEST"
+ fi
+ if [ -n "${VPX_TEST_OUTPUT_DIR}" ] && [ -d "${VPX_TEST_OUTPUT_DIR}" ]; then
+ rm -rf "${VPX_TEST_OUTPUT_DIR}"
+ fi
+}
+
+# Echoes the git hash portion of the VERSION_STRING variable defined in
+# $LIBVPX_CONFIG_PATH/config.mk to stdout, or the version number string when
+# no git hash is contained in VERSION_STRING.
+config_hash() {
+ vpx_config_mk="${LIBVPX_CONFIG_PATH}/config.mk"
+ # Find VERSION_STRING line, split it with "-g" and print the last field to
+ # output the git hash to stdout.
+ vpx_version=$(awk -F -g '/VERSION_STRING/ {print $NF}' "${vpx_config_mk}")
+ # Handle two situations here:
+ # 1. The default case: $vpx_version is a git hash, so echo it unchanged.
+ # 2. When being run a non-dev tree, the -g portion is not present in the
+ # version string: It's only the version number.
+ # In this case $vpx_version is something like 'VERSION_STRING=v1.3.0', so
+ # we echo only what is after the '='.
+ echo "${vpx_version##*=}"
+}
+
+# Echoes the short form of the current git hash.
+current_hash() {
+ if git --version > /dev/null 2>&1; then
+ (cd "$(dirname "${0}")"
+ git rev-parse --short HEAD)
+ else
+ # Return the config hash if git is unavailable: Fail silently, git hashes
+ # are used only for warnings.
+ config_hash
+ fi
+}
+
+# Echoes warnings to stdout when git hash in vpx_config.h does not match the
+# current git hash.
+check_git_hashes() {
+ hash_at_configure_time=$(config_hash)
+ hash_now=$(current_hash)
+
+ if [ "${hash_at_configure_time}" != "${hash_now}" ]; then
+ echo "Warning: git hash has changed since last configure."
+ fi
+}
+
+# $1 is the name of an environment variable containing a directory name to
+# test.
+test_env_var_dir() {
+ local dir=$(eval echo "\${$1}")
+ if [ ! -d "${dir}" ]; then
+ elog "'${dir}': No such directory"
+ elog "The $1 environment variable must be set to a valid directory."
+ return 1
+ fi
+}
+
+# This script requires that the LIBVPX_BIN_PATH, LIBVPX_CONFIG_PATH, and
+# LIBVPX_TEST_DATA_PATH variables are in the environment: Confirm that
+# the variables are set and that they all evaluate to directory paths.
+verify_vpx_test_environment() {
+ test_env_var_dir "LIBVPX_BIN_PATH" \
+ && test_env_var_dir "LIBVPX_CONFIG_PATH" \
+ && test_env_var_dir "LIBVPX_TEST_DATA_PATH"
+}
+
+# Greps vpx_config.h in LIBVPX_CONFIG_PATH for positional parameter one, which
+# should be a LIBVPX preprocessor flag. Echoes yes to stdout when the feature
+# is available.
+vpx_config_option_enabled() {
+ vpx_config_option="${1}"
+ vpx_config_file="${LIBVPX_CONFIG_PATH}/vpx_config.h"
+ config_line=$(grep "${vpx_config_option}" "${vpx_config_file}")
+ if echo "${config_line}" | grep -E -q '1$'; then
+ echo yes
+ fi
+}
+
+# Echoes yes when output of test_configuration_target() contains win32 or win64.
+is_windows_target() {
+ if test_configuration_target \
+ | grep -q -e win32 -e win64 > /dev/null 2>&1; then
+ echo yes
+ fi
+}
+
+# Echoes path to $1 when it's executable and exists in ${LIBVPX_BIN_PATH}, or an
+# empty string. Caller is responsible for testing the string once the function
+# returns.
+vpx_tool_path() {
+ local tool_name="$1"
+ local tool_path="${LIBVPX_BIN_PATH}/${tool_name}${VPX_TEST_EXE_SUFFIX}"
+ if [ ! -x "${tool_path}" ]; then
+ # Try one directory up: when running via examples.sh the tool could be in
+ # the parent directory of $LIBVPX_BIN_PATH.
+ tool_path="${LIBVPX_BIN_PATH}/../${tool_name}${VPX_TEST_EXE_SUFFIX}"
+ fi
+
+ if [ ! -x "${tool_path}" ]; then
+ tool_path=""
+ fi
+ echo "${tool_path}"
+}
+
+# Echoes yes to stdout when the file named by positional parameter one exists
+# in LIBVPX_BIN_PATH, and is executable.
+vpx_tool_available() {
+ local tool_name="$1"
+ local tool="${LIBVPX_BIN_PATH}/${tool_name}${VPX_TEST_EXE_SUFFIX}"
+ [ -x "${tool}" ] && echo yes
+}
+
+# Echoes yes to stdout when vpx_config_option_enabled() reports yes for
+# CONFIG_VP8_DECODER.
+vp8_decode_available() {
+ [ "$(vpx_config_option_enabled CONFIG_VP8_DECODER)" = "yes" ] && echo yes
+}
+
+# Echoes yes to stdout when vpx_config_option_enabled() reports yes for
+# CONFIG_VP8_ENCODER.
+vp8_encode_available() {
+ [ "$(vpx_config_option_enabled CONFIG_VP8_ENCODER)" = "yes" ] && echo yes
+}
+
+# Echoes yes to stdout when vpx_config_option_enabled() reports yes for
+# CONFIG_VP9_DECODER.
+vp9_decode_available() {
+ [ "$(vpx_config_option_enabled CONFIG_VP9_DECODER)" = "yes" ] && echo yes
+}
+
+# Echoes yes to stdout when vpx_config_option_enabled() reports yes for
+# CONFIG_VP9_ENCODER.
+vp9_encode_available() {
+ [ "$(vpx_config_option_enabled CONFIG_VP9_ENCODER)" = "yes" ] && echo yes
+}
+
+# Echoes yes to stdout when vpx_config_option_enabled() reports yes for
+# CONFIG_WEBM_IO.
+webm_io_available() {
+ [ "$(vpx_config_option_enabled CONFIG_WEBM_IO)" = "yes" ] && echo yes
+}
+
+# Filters strings from $1 using the filter specified by $2. Filter behavior
+# depends on the presence of $3. When $3 is present, strings that match the
+# filter are excluded. When $3 is omitted, strings matching the filter are
+# included.
+# The filtered result is echoed to stdout.
+filter_strings() {
+ strings=${1}
+ filter=${2}
+ exclude=${3}
+
+ if [ -n "${exclude}" ]; then
+ # When positional parameter three exists the caller wants to remove strings.
+ # Tell grep to invert matches using the -v argument.
+ exclude='-v'
+ else
+ unset exclude
+ fi
+
+ if [ -n "${filter}" ]; then
+ for s in ${strings}; do
+ if echo "${s}" | grep -E -q ${exclude} "${filter}" > /dev/null 2>&1; then
+ filtered_strings="${filtered_strings} ${s}"
+ fi
+ done
+ else
+ filtered_strings="${strings}"
+ fi
+ echo "${filtered_strings}"
+}
+
+# Runs user test functions passed via positional parameters one and two.
+# Functions in positional parameter one are treated as environment verification
+# functions and are run unconditionally. Functions in positional parameter two
+# are run according to the rules specified in vpx_test_usage().
+run_tests() {
+ local env_tests="verify_vpx_test_environment $1"
+ local tests_to_filter="$2"
+ local test_name="${VPX_TEST_NAME}"
+
+ if [ -z "${test_name}" ]; then
+ test_name="$(basename "${0%.*}")"
+ fi
+
+ if [ "${VPX_TEST_RUN_DISABLED_TESTS}" != "yes" ]; then
+ # Filter out DISABLED tests.
+ tests_to_filter=$(filter_strings "${tests_to_filter}" ^DISABLED exclude)
+ fi
+
+ if [ -n "${VPX_TEST_FILTER}" ]; then
+ # Remove tests not matching the user's filter.
+ tests_to_filter=$(filter_strings "${tests_to_filter}" ${VPX_TEST_FILTER})
+ fi
+
+ # User requested test listing: Dump test names and return.
+ if [ "${VPX_TEST_LIST_TESTS}" = "yes" ]; then
+ for test_name in $tests_to_filter; do
+ echo ${test_name}
+ done
+ return
+ fi
+
+ # Don't bother with the environment tests if everything else was disabled.
+ [ -z "${tests_to_filter}" ] && return
+
+ # Combine environment and actual tests.
+ local tests_to_run="${env_tests} ${tests_to_filter}"
+
+ check_git_hashes
+
+ # Run tests.
+ for test in ${tests_to_run}; do
+ test_begin "${test}"
+ vlog " RUN ${test}"
+ "${test}"
+ vlog " PASS ${test}"
+ test_end "${test}"
+ done
+
+ local tested_config="$(test_configuration_target) @ $(current_hash)"
+ echo "${test_name}: Done, all tests pass for ${tested_config}."
+}
+
+vpx_test_usage() {
+cat << EOF
+ Usage: ${0##*/} [arguments]
+ --bin-path <path to libvpx binaries directory>
+ --config-path <path to libvpx config directory>
+ --filter <filter>: User test filter. Only tests matching filter are run.
+ --run-disabled-tests: Run disabled tests.
+ --help: Display this message and exit.
+ --test-data-path <path to libvpx test data directory>
+ --show-program-output: Shows output from all programs being tested.
+ --prefix: Allows for a user specified prefix to be inserted before all test
+ programs. Grants the ability, for example, to run test programs
+ within valgrind.
+ --list-tests: List all test names and exit without actually running tests.
+ --verbose: Verbose output.
+
+ When the --bin-path option is not specified the script attempts to use
+ \$LIBVPX_BIN_PATH and then the current directory.
+
+ When the --config-path option is not specified the script attempts to use
+ \$LIBVPX_CONFIG_PATH and then the current directory.
+
+ When the -test-data-path option is not specified the script attempts to use
+ \$LIBVPX_TEST_DATA_PATH and then the current directory.
+EOF
+}
+
+# Returns non-zero (failure) when required environment variables are empty
+# strings.
+vpx_test_check_environment() {
+ if [ -z "${LIBVPX_BIN_PATH}" ] || \
+ [ -z "${LIBVPX_CONFIG_PATH}" ] || \
+ [ -z "${LIBVPX_TEST_DATA_PATH}" ]; then
+ return 1
+ fi
+}
+
+# Parse the command line.
+while [ -n "$1" ]; do
+ case "$1" in
+ --bin-path)
+ LIBVPX_BIN_PATH="$2"
+ shift
+ ;;
+ --config-path)
+ LIBVPX_CONFIG_PATH="$2"
+ shift
+ ;;
+ --filter)
+ VPX_TEST_FILTER="$2"
+ shift
+ ;;
+ --run-disabled-tests)
+ VPX_TEST_RUN_DISABLED_TESTS=yes
+ ;;
+ --help)
+ vpx_test_usage
+ exit
+ ;;
+ --test-data-path)
+ LIBVPX_TEST_DATA_PATH="$2"
+ shift
+ ;;
+ --prefix)
+ VPX_TEST_PREFIX="$2"
+ shift
+ ;;
+ --verbose)
+ VPX_TEST_VERBOSE_OUTPUT=yes
+ ;;
+ --show-program-output)
+ devnull=
+ ;;
+ --list-tests)
+ VPX_TEST_LIST_TESTS=yes
+ ;;
+ *)
+ vpx_test_usage
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+# Handle running the tests from a build directory without arguments when running
+# the tests on *nix/macosx.
+LIBVPX_BIN_PATH="${LIBVPX_BIN_PATH:-.}"
+LIBVPX_CONFIG_PATH="${LIBVPX_CONFIG_PATH:-.}"
+LIBVPX_TEST_DATA_PATH="${LIBVPX_TEST_DATA_PATH:-.}"
+
+# Create a temporary directory for output files, and a trap to clean it up.
+if [ -n "${TMPDIR}" ]; then
+ VPX_TEST_TEMP_ROOT="${TMPDIR}"
+elif [ -n "${TEMPDIR}" ]; then
+ VPX_TEST_TEMP_ROOT="${TEMPDIR}"
+else
+ VPX_TEST_TEMP_ROOT=/tmp
+fi
+
+VPX_TEST_OUTPUT_DIR="${VPX_TEST_TEMP_ROOT}/vpx_test_$$"
+
+if ! mkdir -p "${VPX_TEST_OUTPUT_DIR}" || \
+ [ ! -d "${VPX_TEST_OUTPUT_DIR}" ]; then
+ echo "${0##*/}: Cannot create output directory, giving up."
+ echo "${0##*/}: VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR}"
+ exit 1
+fi
+
+if [ "$(is_windows_target)" = "yes" ]; then
+ VPX_TEST_EXE_SUFFIX=".exe"
+fi
+
+# Variables shared by tests.
+VP8_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp80-00-comprehensive-001.ivf"
+VP9_IVF_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-09-subpixel-00.ivf"
+
+VP9_WEBM_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-00-quantizer-00.webm"
+VP9_FPM_WEBM_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-07-frame_parallel-1.webm"
+VP9_LT_50_FRAMES_WEBM_FILE="${LIBVPX_TEST_DATA_PATH}/vp90-2-02-size-32x08.webm"
+
+VP9_RAW_FILE="${LIBVPX_TEST_DATA_PATH}/crbug-1539.rawfile"
+
+YUV_RAW_INPUT="${LIBVPX_TEST_DATA_PATH}/hantro_collage_w352h288.yuv"
+YUV_RAW_INPUT_WIDTH=352
+YUV_RAW_INPUT_HEIGHT=288
+
+Y4M_NOSQ_PAR_INPUT="${LIBVPX_TEST_DATA_PATH}/park_joy_90p_8_420_a10-1.y4m"
+Y4M_720P_INPUT="${LIBVPX_TEST_DATA_PATH}/niklas_1280_720_30.y4m"
+Y4M_720P_INPUT_WIDTH=1280
+Y4M_720P_INPUT_HEIGHT=720
+
+# Setup a trap function to clean up after tests complete.
+trap cleanup EXIT
+
+vlog "$(basename "${0%.*}") test configuration:
+ LIBVPX_BIN_PATH=${LIBVPX_BIN_PATH}
+ LIBVPX_CONFIG_PATH=${LIBVPX_CONFIG_PATH}
+ LIBVPX_TEST_DATA_PATH=${LIBVPX_TEST_DATA_PATH}
+ VP8_IVF_FILE=${VP8_IVF_FILE}
+ VP9_IVF_FILE=${VP9_IVF_FILE}
+ VP9_WEBM_FILE=${VP9_WEBM_FILE}
+ VPX_TEST_EXE_SUFFIX=${VPX_TEST_EXE_SUFFIX}
+ VPX_TEST_FILTER=${VPX_TEST_FILTER}
+ VPX_TEST_LIST_TESTS=${VPX_TEST_LIST_TESTS}
+ VPX_TEST_OUTPUT_DIR=${VPX_TEST_OUTPUT_DIR}
+ VPX_TEST_PREFIX=${VPX_TEST_PREFIX}
+ VPX_TEST_RUN_DISABLED_TESTS=${VPX_TEST_RUN_DISABLED_TESTS}
+ VPX_TEST_SHOW_PROGRAM_OUTPUT=${VPX_TEST_SHOW_PROGRAM_OUTPUT}
+ VPX_TEST_TEMP_ROOT=${VPX_TEST_TEMP_ROOT}
+ VPX_TEST_VERBOSE_OUTPUT=${VPX_TEST_VERBOSE_OUTPUT}
+ YUV_RAW_INPUT=${YUV_RAW_INPUT}
+ YUV_RAW_INPUT_WIDTH=${YUV_RAW_INPUT_WIDTH}
+ YUV_RAW_INPUT_HEIGHT=${YUV_RAW_INPUT_HEIGHT}
+ Y4M_NOSQ_PAR_INPUT=${Y4M_NOSQ_PAR_INPUT}"
+
+fi # End $VPX_TEST_TOOLS_COMMON_SH pseudo include guard.
diff --git a/media/libvpx/libvpx/test/twopass_encoder.sh b/media/libvpx/libvpx/test/twopass_encoder.sh
new file mode 100755
index 0000000000..69ecbacd0c
--- /dev/null
+++ b/media/libvpx/libvpx/test/twopass_encoder.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx twopass_encoder example. To add new tests to this
+## file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to twopass_encoder_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+twopass_encoder_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+}
+
+# Runs twopass_encoder using the codec specified by $1 with a frame limit of
+# 100.
+twopass_encoder() {
+ local encoder="${LIBVPX_BIN_PATH}/twopass_encoder${VPX_TEST_EXE_SUFFIX}"
+ local codec="$1"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/twopass_encoder_${codec}.ivf"
+
+ if [ ! -x "${encoder}" ]; then
+ elog "${encoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" 100 \
+ ${devnull} || return 1
+
+ [ -e "${output_file}" ] || return 1
+}
+
+twopass_encoder_vp8() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ twopass_encoder vp8 || return 1
+ fi
+}
+
+twopass_encoder_vp9() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ twopass_encoder vp9 || return 1
+ fi
+}
+
+
+if [ "$(vpx_config_option_enabled CONFIG_REALTIME_ONLY)" != "yes" ]; then
+ twopass_encoder_tests="twopass_encoder_vp8
+ twopass_encoder_vp9"
+
+ run_tests twopass_encoder_verify_environment "${twopass_encoder_tests}"
+fi
diff --git a/media/libvpx/libvpx/test/user_priv_test.cc b/media/libvpx/libvpx/test/user_priv_test.cc
new file mode 100644
index 0000000000..20741f8268
--- /dev/null
+++ b/media/libvpx/libvpx/test/user_priv_test.cc
@@ -0,0 +1,100 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <string>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "test/acm_random.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+#include "vpx/vp8.h"
+
+namespace {
+
+using libvpx_test::ACMRandom;
+using std::string;
+
+#if CONFIG_WEBM_IO
+
+void CheckUserPrivateData(void *user_priv, int *target) {
+ // actual pointer value should be the same as expected.
+ EXPECT_EQ(reinterpret_cast<void *>(target), user_priv)
+ << "user_priv pointer value does not match.";
+}
+
+// Decodes |filename|. Passes in user_priv data when calling DecodeFrame and
+// compares the user_priv from return img with the original user_priv to see if
+// they match. Both the pointer values and the values inside the addresses
+// should match.
+string DecodeFile(const string &filename) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ libvpx_test::WebMVideoSource video(filename);
+ video.Init();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ libvpx_test::VP9Decoder decoder(cfg, 0);
+
+ libvpx_test::MD5 md5;
+ int frame_num = 0;
+ for (video.Begin(); !::testing::Test::HasFailure() && video.cxdata();
+ video.Next()) {
+ void *user_priv = reinterpret_cast<void *>(&frame_num);
+ const vpx_codec_err_t res =
+ decoder.DecodeFrame(video.cxdata(), video.frame_size(),
+ (frame_num == 0) ? nullptr : user_priv);
+ if (res != VPX_CODEC_OK) {
+ EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+ break;
+ }
+ libvpx_test::DxDataIterator dec_iter = decoder.GetDxData();
+ const vpx_image_t *img = nullptr;
+
+ // Get decompressed data.
+ while ((img = dec_iter.Next())) {
+ if (frame_num == 0) {
+ CheckUserPrivateData(img->user_priv, nullptr);
+ } else {
+ CheckUserPrivateData(img->user_priv, &frame_num);
+
+ // Also test ctrl_get_reference api.
+ struct vp9_ref_frame ref = vp9_ref_frame();
+ // Randomly fetch a reference frame.
+ ref.idx = rnd.Rand8() % 3;
+ decoder.Control(VP9_GET_REFERENCE, &ref);
+
+ CheckUserPrivateData(ref.img.user_priv, nullptr);
+ }
+ md5.Add(img);
+ }
+
+ frame_num++;
+ }
+ return string(md5.Get());
+}
+
+TEST(UserPrivTest, VideoDecode) {
+ // no tiles or frame parallel; this exercises the decoding to test the
+ // user_priv.
+ EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc",
+ DecodeFile("vp90-2-03-size-226x226.webm").c_str());
+}
+
+#endif // CONFIG_WEBM_IO
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/util.h b/media/libvpx/libvpx/test/util.h
new file mode 100644
index 0000000000..985f487094
--- /dev/null
+++ b/media/libvpx/libvpx/test/util.h
@@ -0,0 +1,48 @@
+/*
+ * 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 VPX_TEST_UTIL_H_
+#define VPX_TEST_UTIL_H_
+
+#include <stdio.h>
+#include <math.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vpx/vpx_image.h"
+
+// Macros
+#define GET_PARAM(k) std::get<k>(GetParam())
+
+inline double compute_psnr(const vpx_image_t *img1, const vpx_image_t *img2) {
+ assert((img1->fmt == img2->fmt) && (img1->d_w == img2->d_w) &&
+ (img1->d_h == img2->d_h));
+
+ const unsigned int width_y = img1->d_w;
+ const unsigned int height_y = img1->d_h;
+ unsigned int i, j;
+
+ int64_t sqrerr = 0;
+ for (i = 0; i < height_y; ++i) {
+ for (j = 0; j < width_y; ++j) {
+ int64_t d = img1->planes[VPX_PLANE_Y][i * img1->stride[VPX_PLANE_Y] + j] -
+ img2->planes[VPX_PLANE_Y][i * img2->stride[VPX_PLANE_Y] + j];
+ sqrerr += d * d;
+ }
+ }
+ double mse = static_cast<double>(sqrerr) / (width_y * height_y);
+ double psnr = 100.0;
+ if (mse > 0.0) {
+ psnr = 10 * log10(255.0 * 255.0 / mse);
+ }
+ return psnr;
+}
+
+#endif // VPX_TEST_UTIL_H_
diff --git a/media/libvpx/libvpx/test/variance_test.cc b/media/libvpx/libvpx/test/variance_test.cc
new file mode 100644
index 0000000000..df9a1c56f6
--- /dev/null
+++ b/media/libvpx/libvpx/test/variance_test.cc
@@ -0,0 +1,1950 @@
+/*
+ * 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 <cstdlib>
+#include <new>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_dsp/variance.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/vpx_timer.h"
+
+namespace {
+
+typedef unsigned int (*Get4x4SseFunc)(const uint8_t *a, int a_stride,
+ const uint8_t *b, int b_stride);
+typedef unsigned int (*SumOfSquaresFunction)(const int16_t *src);
+
+using libvpx_test::ACMRandom;
+
+// Truncate high bit depth results by downshifting (with rounding) by:
+// 2 * (bit_depth - 8) for sse
+// (bit_depth - 8) for se
+static void RoundHighBitDepth(int bit_depth, int64_t *se, uint64_t *sse) {
+ switch (bit_depth) {
+ case VPX_BITS_12:
+ *sse = (*sse + 128) >> 8;
+ *se = (*se + 8) >> 4;
+ break;
+ case VPX_BITS_10:
+ *sse = (*sse + 8) >> 4;
+ *se = (*se + 2) >> 2;
+ break;
+ case VPX_BITS_8:
+ default: break;
+ }
+}
+
+static unsigned int mb_ss_ref(const int16_t *src) {
+ unsigned int res = 0;
+ for (int i = 0; i < 256; ++i) {
+ res += src[i] * src[i];
+ }
+ return res;
+}
+
+/* Note:
+ * Our codebase calculates the "diff" value in the variance algorithm by
+ * (src - ref).
+ */
+static uint32_t variance_ref(const uint8_t *src, const uint8_t *ref, int l2w,
+ int l2h, int src_stride, int ref_stride,
+ uint32_t *sse_ptr, bool use_high_bit_depth_,
+ vpx_bit_depth_t bit_depth) {
+ int64_t se = 0;
+ uint64_t sse = 0;
+ const int w = 1 << l2w;
+ const int h = 1 << l2h;
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int diff;
+ if (!use_high_bit_depth_) {
+ diff = src[y * src_stride + x] - ref[y * ref_stride + x];
+ se += diff;
+ sse += diff * diff;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ diff = CONVERT_TO_SHORTPTR(src)[y * src_stride + x] -
+ CONVERT_TO_SHORTPTR(ref)[y * ref_stride + x];
+ se += diff;
+ sse += diff * diff;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ RoundHighBitDepth(bit_depth, &se, &sse);
+ *sse_ptr = static_cast<uint32_t>(sse);
+ return static_cast<uint32_t>(
+ sse - ((static_cast<int64_t>(se) * se) >> (l2w + l2h)));
+}
+
+/* The subpel reference functions differ from the codec version in one aspect:
+ * they calculate the bilinear factors directly instead of using a lookup table
+ * and therefore upshift xoff and yoff by 1. Only every other calculated value
+ * is used so the codec version shrinks the table to save space and maintain
+ * compatibility with vp8.
+ */
+static uint32_t subpel_variance_ref(const uint8_t *ref, const uint8_t *src,
+ int l2w, int l2h, int xoff, int yoff,
+ uint32_t *sse_ptr, bool use_high_bit_depth_,
+ vpx_bit_depth_t bit_depth) {
+ int64_t se = 0;
+ uint64_t sse = 0;
+ const int w = 1 << l2w;
+ const int h = 1 << l2h;
+
+ xoff <<= 1;
+ yoff <<= 1;
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ // Bilinear interpolation at a 16th pel step.
+ if (!use_high_bit_depth_) {
+ const int a1 = ref[(w + 1) * (y + 0) + x + 0];
+ const int a2 = ref[(w + 1) * (y + 0) + x + 1];
+ const int b1 = ref[(w + 1) * (y + 1) + x + 0];
+ const int b2 = ref[(w + 1) * (y + 1) + x + 1];
+ const int a = a1 + (((a2 - a1) * xoff + 8) >> 4);
+ const int b = b1 + (((b2 - b1) * xoff + 8) >> 4);
+ const int r = a + (((b - a) * yoff + 8) >> 4);
+ const int diff = r - src[w * y + x];
+ se += diff;
+ sse += diff * diff;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ uint16_t *ref16 = CONVERT_TO_SHORTPTR(ref);
+ uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
+ const int a1 = ref16[(w + 1) * (y + 0) + x + 0];
+ const int a2 = ref16[(w + 1) * (y + 0) + x + 1];
+ const int b1 = ref16[(w + 1) * (y + 1) + x + 0];
+ const int b2 = ref16[(w + 1) * (y + 1) + x + 1];
+ const int a = a1 + (((a2 - a1) * xoff + 8) >> 4);
+ const int b = b1 + (((b2 - b1) * xoff + 8) >> 4);
+ const int r = a + (((b - a) * yoff + 8) >> 4);
+ const int diff = r - src16[w * y + x];
+ se += diff;
+ sse += diff * diff;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ RoundHighBitDepth(bit_depth, &se, &sse);
+ *sse_ptr = static_cast<uint32_t>(sse);
+ return static_cast<uint32_t>(
+ sse - ((static_cast<int64_t>(se) * se) >> (l2w + l2h)));
+}
+
+static uint32_t subpel_avg_variance_ref(const uint8_t *ref, const uint8_t *src,
+ const uint8_t *second_pred, int l2w,
+ int l2h, int xoff, int yoff,
+ uint32_t *sse_ptr,
+ bool use_high_bit_depth,
+ vpx_bit_depth_t bit_depth) {
+ int64_t se = 0;
+ uint64_t sse = 0;
+ const int w = 1 << l2w;
+ const int h = 1 << l2h;
+
+ xoff <<= 1;
+ yoff <<= 1;
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ // bilinear interpolation at a 16th pel step
+ if (!use_high_bit_depth) {
+ const int a1 = ref[(w + 1) * (y + 0) + x + 0];
+ const int a2 = ref[(w + 1) * (y + 0) + x + 1];
+ const int b1 = ref[(w + 1) * (y + 1) + x + 0];
+ const int b2 = ref[(w + 1) * (y + 1) + x + 1];
+ const int a = a1 + (((a2 - a1) * xoff + 8) >> 4);
+ const int b = b1 + (((b2 - b1) * xoff + 8) >> 4);
+ const int r = a + (((b - a) * yoff + 8) >> 4);
+ const int diff =
+ ((r + second_pred[w * y + x] + 1) >> 1) - src[w * y + x];
+ se += diff;
+ sse += diff * diff;
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ const uint16_t *ref16 = CONVERT_TO_SHORTPTR(ref);
+ const uint16_t *src16 = CONVERT_TO_SHORTPTR(src);
+ const uint16_t *sec16 = CONVERT_TO_SHORTPTR(second_pred);
+ const int a1 = ref16[(w + 1) * (y + 0) + x + 0];
+ const int a2 = ref16[(w + 1) * (y + 0) + x + 1];
+ const int b1 = ref16[(w + 1) * (y + 1) + x + 0];
+ const int b2 = ref16[(w + 1) * (y + 1) + x + 1];
+ const int a = a1 + (((a2 - a1) * xoff + 8) >> 4);
+ const int b = b1 + (((b2 - b1) * xoff + 8) >> 4);
+ const int r = a + (((b - a) * yoff + 8) >> 4);
+ const int diff = ((r + sec16[w * y + x] + 1) >> 1) - src16[w * y + x];
+ se += diff;
+ sse += diff * diff;
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ }
+ RoundHighBitDepth(bit_depth, &se, &sse);
+ *sse_ptr = static_cast<uint32_t>(sse);
+ return static_cast<uint32_t>(
+ sse - ((static_cast<int64_t>(se) * se) >> (l2w + l2h)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class SumOfSquaresTest : public ::testing::TestWithParam<SumOfSquaresFunction> {
+ public:
+ SumOfSquaresTest() : func_(GetParam()) {}
+
+ virtual ~SumOfSquaresTest() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ void ConstTest();
+ void RefTest();
+
+ SumOfSquaresFunction func_;
+ ACMRandom rnd_;
+};
+
+void SumOfSquaresTest::ConstTest() {
+ int16_t mem[256];
+ unsigned int res;
+ for (int v = 0; v < 256; ++v) {
+ for (int i = 0; i < 256; ++i) {
+ mem[i] = v;
+ }
+ ASM_REGISTER_STATE_CHECK(res = func_(mem));
+ EXPECT_EQ(256u * (v * v), res);
+ }
+}
+
+void SumOfSquaresTest::RefTest() {
+ int16_t mem[256];
+ for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 256; ++j) {
+ mem[j] = rnd_.Rand8() - rnd_.Rand8();
+ }
+
+ const unsigned int expected = mb_ss_ref(mem);
+ unsigned int res;
+ ASM_REGISTER_STATE_CHECK(res = func_(mem));
+ EXPECT_EQ(expected, res);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Encapsulating struct to store the function to test along with
+// some testing context.
+// Can be used for MSE, SSE, Variance, etc.
+
+template <typename Func>
+struct TestParams {
+ TestParams(int log2w = 0, int log2h = 0, Func function = nullptr,
+ int bit_depth_value = 0)
+ : log2width(log2w), log2height(log2h), func(function) {
+ use_high_bit_depth = (bit_depth_value > 0);
+ if (use_high_bit_depth) {
+ bit_depth = static_cast<vpx_bit_depth_t>(bit_depth_value);
+ } else {
+ bit_depth = VPX_BITS_8;
+ }
+ width = 1 << log2width;
+ height = 1 << log2height;
+ block_size = width * height;
+ mask = (1u << bit_depth) - 1;
+ }
+
+ int log2width, log2height;
+ int width, height;
+ int block_size;
+ Func func;
+ vpx_bit_depth_t bit_depth;
+ bool use_high_bit_depth;
+ uint32_t mask;
+};
+
+template <typename Func>
+std::ostream &operator<<(std::ostream &os, const TestParams<Func> &p) {
+ return os << "log2width/height:" << p.log2width << "/" << p.log2height
+ << " function:" << reinterpret_cast<const void *>(p.func)
+ << " bit-depth:" << p.bit_depth;
+}
+
+// Main class for testing a function type
+template <typename FunctionType>
+class MainTestClass
+ : public ::testing::TestWithParam<TestParams<FunctionType> > {
+ public:
+ virtual void SetUp() {
+ params_ = this->GetParam();
+
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ const size_t unit =
+ use_high_bit_depth() ? sizeof(uint16_t) : sizeof(uint8_t);
+ src_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_size() * unit));
+ ref_ = new uint8_t[block_size() * unit];
+ ASSERT_NE(src_, nullptr);
+ ASSERT_NE(ref_, nullptr);
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (use_high_bit_depth()) {
+ // TODO(skal): remove!
+ src_ = CONVERT_TO_BYTEPTR(src_);
+ ref_ = CONVERT_TO_BYTEPTR(ref_);
+ }
+#endif
+ }
+
+ virtual void TearDown() {
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (use_high_bit_depth()) {
+ // TODO(skal): remove!
+ src_ = reinterpret_cast<uint8_t *>(CONVERT_TO_SHORTPTR(src_));
+ ref_ = reinterpret_cast<uint8_t *>(CONVERT_TO_SHORTPTR(ref_));
+ }
+#endif
+
+ vpx_free(src_);
+ delete[] ref_;
+ src_ = nullptr;
+ ref_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ // We could sub-class MainTestClass into dedicated class for Variance
+ // and MSE/SSE, but it involves a lot of 'this->xxx' dereferencing
+ // to access top class fields xxx. That's cumbersome, so for now we'll just
+ // implement the testing methods here:
+
+ // Variance tests
+ void ZeroTest();
+ void RefTest();
+ void RefStrideTest();
+ void OneQuarterTest();
+ void SpeedTest();
+
+ // MSE/SSE tests
+ void RefTestMse();
+ void RefTestSse();
+ void MaxTestMse();
+ void MaxTestSse();
+
+ protected:
+ ACMRandom rnd_;
+ uint8_t *src_;
+ uint8_t *ref_;
+ TestParams<FunctionType> params_;
+
+ // some relay helpers
+ bool use_high_bit_depth() const { return params_.use_high_bit_depth; }
+ int byte_shift() const { return params_.bit_depth - 8; }
+ int block_size() const { return params_.block_size; }
+ int width() const { return params_.width; }
+ int height() const { return params_.height; }
+ uint32_t mask() const { return params_.mask; }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests related to variance.
+
+template <typename VarianceFunctionType>
+void MainTestClass<VarianceFunctionType>::ZeroTest() {
+ for (int i = 0; i <= 255; ++i) {
+ if (!use_high_bit_depth()) {
+ memset(src_, i, block_size());
+ } else {
+ uint16_t *const src16 = CONVERT_TO_SHORTPTR(src_);
+ for (int k = 0; k < block_size(); ++k) src16[k] = i << byte_shift();
+ }
+ for (int j = 0; j <= 255; ++j) {
+ if (!use_high_bit_depth()) {
+ memset(ref_, j, block_size());
+ } else {
+ uint16_t *const ref16 = CONVERT_TO_SHORTPTR(ref_);
+ for (int k = 0; k < block_size(); ++k) ref16[k] = j << byte_shift();
+ }
+ unsigned int sse, var;
+ ASM_REGISTER_STATE_CHECK(
+ var = params_.func(src_, width(), ref_, width(), &sse));
+ EXPECT_EQ(0u, var) << "src values: " << i << " ref values: " << j;
+ }
+ }
+}
+
+template <typename VarianceFunctionType>
+void MainTestClass<VarianceFunctionType>::RefTest() {
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < block_size(); j++) {
+ if (!use_high_bit_depth()) {
+ src_[j] = rnd_.Rand8();
+ ref_[j] = rnd_.Rand8();
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask();
+ CONVERT_TO_SHORTPTR(ref_)[j] = rnd_.Rand16() & mask();
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ unsigned int sse1, sse2, var1, var2;
+ const int stride = width();
+ ASM_REGISTER_STATE_CHECK(
+ var1 = params_.func(src_, stride, ref_, stride, &sse1));
+ var2 =
+ variance_ref(src_, ref_, params_.log2width, params_.log2height, stride,
+ stride, &sse2, use_high_bit_depth(), params_.bit_depth);
+ EXPECT_EQ(sse1, sse2) << "Error at test index: " << i;
+ EXPECT_EQ(var1, var2) << "Error at test index: " << i;
+ }
+}
+
+template <typename VarianceFunctionType>
+void MainTestClass<VarianceFunctionType>::RefStrideTest() {
+ for (int i = 0; i < 10; ++i) {
+ const int ref_stride = (i & 1) * width();
+ const int src_stride = ((i >> 1) & 1) * width();
+ for (int j = 0; j < block_size(); j++) {
+ const int ref_ind = (j / width()) * ref_stride + j % width();
+ const int src_ind = (j / width()) * src_stride + j % width();
+ if (!use_high_bit_depth()) {
+ src_[src_ind] = rnd_.Rand8();
+ ref_[ref_ind] = rnd_.Rand8();
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ CONVERT_TO_SHORTPTR(src_)[src_ind] = rnd_.Rand16() & mask();
+ CONVERT_TO_SHORTPTR(ref_)[ref_ind] = rnd_.Rand16() & mask();
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ unsigned int sse1, sse2;
+ unsigned int var1, var2;
+
+ ASM_REGISTER_STATE_CHECK(
+ var1 = params_.func(src_, src_stride, ref_, ref_stride, &sse1));
+ var2 = variance_ref(src_, ref_, params_.log2width, params_.log2height,
+ src_stride, ref_stride, &sse2, use_high_bit_depth(),
+ params_.bit_depth);
+ EXPECT_EQ(sse1, sse2) << "Error at test index: " << i;
+ EXPECT_EQ(var1, var2) << "Error at test index: " << i;
+ }
+}
+
+template <typename VarianceFunctionType>
+void MainTestClass<VarianceFunctionType>::OneQuarterTest() {
+ const int half = block_size() / 2;
+ if (!use_high_bit_depth()) {
+ memset(src_, 255, block_size());
+ memset(ref_, 255, half);
+ memset(ref_ + half, 0, half);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ vpx_memset16(CONVERT_TO_SHORTPTR(src_), 255 << byte_shift(), block_size());
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_), 255 << byte_shift(), half);
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_) + half, 0, half);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ unsigned int sse, var, expected;
+ ASM_REGISTER_STATE_CHECK(
+ var = params_.func(src_, width(), ref_, width(), &sse));
+ expected = block_size() * 255 * 255 / 4;
+ EXPECT_EQ(expected, var);
+}
+
+template <typename VarianceFunctionType>
+void MainTestClass<VarianceFunctionType>::SpeedTest() {
+ const int half = block_size() / 2;
+ if (!use_high_bit_depth()) {
+ memset(src_, 255, block_size());
+ memset(ref_, 255, half);
+ memset(ref_ + half, 0, half);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ vpx_memset16(CONVERT_TO_SHORTPTR(src_), 255 << byte_shift(), block_size());
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_), 255 << byte_shift(), half);
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_) + half, 0, half);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ unsigned int sse;
+
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < (1 << 30) / block_size(); ++i) {
+ const uint32_t variance = params_.func(src_, width(), ref_, width(), &sse);
+ // Ignore return value.
+ (void)variance;
+ }
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("Variance %dx%d %dbpp time: %5d ms\n", width(), height(),
+ params_.bit_depth, elapsed_time / 1000);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests related to MSE / SSE.
+
+template <typename FunctionType>
+void MainTestClass<FunctionType>::RefTestMse() {
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < block_size(); ++j) {
+ if (!use_high_bit_depth()) {
+ src_[j] = rnd_.Rand8();
+ ref_[j] = rnd_.Rand8();
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask();
+ CONVERT_TO_SHORTPTR(ref_)[j] = rnd_.Rand16() & mask();
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ }
+ unsigned int sse1, sse2;
+ const int stride = width();
+ ASM_REGISTER_STATE_CHECK(params_.func(src_, stride, ref_, stride, &sse1));
+ variance_ref(src_, ref_, params_.log2width, params_.log2height, stride,
+ stride, &sse2, use_high_bit_depth(), params_.bit_depth);
+ EXPECT_EQ(sse1, sse2);
+ }
+}
+
+template <typename FunctionType>
+void MainTestClass<FunctionType>::RefTestSse() {
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < block_size(); ++j) {
+ src_[j] = rnd_.Rand8();
+ ref_[j] = rnd_.Rand8();
+ }
+ unsigned int sse2;
+ unsigned int var1;
+ const int stride = width();
+ ASM_REGISTER_STATE_CHECK(var1 = params_.func(src_, stride, ref_, stride));
+ variance_ref(src_, ref_, params_.log2width, params_.log2height, stride,
+ stride, &sse2, false, VPX_BITS_8);
+ EXPECT_EQ(var1, sse2);
+ }
+}
+
+template <typename FunctionType>
+void MainTestClass<FunctionType>::MaxTestMse() {
+ if (!use_high_bit_depth()) {
+ memset(src_, 255, block_size());
+ memset(ref_, 0, block_size());
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ vpx_memset16(CONVERT_TO_SHORTPTR(src_), 255 << byte_shift(), block_size());
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_), 0, block_size());
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ unsigned int sse;
+ ASM_REGISTER_STATE_CHECK(params_.func(src_, width(), ref_, width(), &sse));
+ const unsigned int expected = block_size() * 255 * 255;
+ EXPECT_EQ(expected, sse);
+}
+
+template <typename FunctionType>
+void MainTestClass<FunctionType>::MaxTestSse() {
+ memset(src_, 255, block_size());
+ memset(ref_, 0, block_size());
+ unsigned int var;
+ ASM_REGISTER_STATE_CHECK(var = params_.func(src_, width(), ref_, width()));
+ const unsigned int expected = block_size() * 255 * 255;
+ EXPECT_EQ(expected, var);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename FunctionType>
+class SubpelVarianceTest
+ : public ::testing::TestWithParam<TestParams<FunctionType> > {
+ public:
+ virtual void SetUp() {
+ params_ = this->GetParam();
+
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ if (!use_high_bit_depth()) {
+ src_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_size()));
+ sec_ = reinterpret_cast<uint8_t *>(vpx_memalign(16, block_size()));
+ ref_ = reinterpret_cast<uint8_t *>(
+ vpx_malloc(block_size() + width() + height() + 1));
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ src_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
+ vpx_memalign(16, block_size() * sizeof(uint16_t))));
+ sec_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
+ vpx_memalign(16, block_size() * sizeof(uint16_t))));
+ ref_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(vpx_malloc(
+ (block_size() + width() + height() + 1) * sizeof(uint16_t))));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ ASSERT_NE(src_, nullptr);
+ ASSERT_NE(sec_, nullptr);
+ ASSERT_NE(ref_, nullptr);
+ }
+
+ virtual void TearDown() {
+ if (!use_high_bit_depth()) {
+ vpx_free(src_);
+ vpx_free(sec_);
+ vpx_free(ref_);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ vpx_free(CONVERT_TO_SHORTPTR(src_));
+ vpx_free(CONVERT_TO_SHORTPTR(ref_));
+ vpx_free(CONVERT_TO_SHORTPTR(sec_));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ void RefTest();
+ void ExtremeRefTest();
+ void SpeedTest();
+
+ ACMRandom rnd_;
+ uint8_t *src_;
+ uint8_t *ref_;
+ uint8_t *sec_;
+ TestParams<FunctionType> params_;
+
+ // some relay helpers
+ bool use_high_bit_depth() const { return params_.use_high_bit_depth; }
+ int byte_shift() const { return params_.bit_depth - 8; }
+ int block_size() const { return params_.block_size; }
+ int width() const { return params_.width; }
+ int height() const { return params_.height; }
+ uint32_t mask() const { return params_.mask; }
+};
+
+template <typename SubpelVarianceFunctionType>
+void SubpelVarianceTest<SubpelVarianceFunctionType>::RefTest() {
+ for (int x = 0; x < 8; ++x) {
+ for (int y = 0; y < 8; ++y) {
+ if (!use_high_bit_depth()) {
+ for (int j = 0; j < block_size(); j++) {
+ src_[j] = rnd_.Rand8();
+ }
+ for (int j = 0; j < block_size() + width() + height() + 1; j++) {
+ ref_[j] = rnd_.Rand8();
+ }
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ for (int j = 0; j < block_size(); j++) {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask();
+ }
+ for (int j = 0; j < block_size() + width() + height() + 1; j++) {
+ CONVERT_TO_SHORTPTR(ref_)[j] = rnd_.Rand16() & mask();
+ }
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ unsigned int sse1, sse2;
+ unsigned int var1;
+ ASM_REGISTER_STATE_CHECK(
+ var1 = params_.func(ref_, width() + 1, x, y, src_, width(), &sse1));
+ const unsigned int var2 = subpel_variance_ref(
+ ref_, src_, params_.log2width, params_.log2height, x, y, &sse2,
+ use_high_bit_depth(), params_.bit_depth);
+ EXPECT_EQ(sse1, sse2) << "at position " << x << ", " << y;
+ EXPECT_EQ(var1, var2) << "at position " << x << ", " << y;
+ }
+ }
+}
+
+template <typename SubpelVarianceFunctionType>
+void SubpelVarianceTest<SubpelVarianceFunctionType>::ExtremeRefTest() {
+ // Compare against reference.
+ // Src: Set the first half of values to 0, the second half to the maximum.
+ // Ref: Set the first half of values to the maximum, the second half to 0.
+ for (int x = 0; x < 8; ++x) {
+ for (int y = 0; y < 8; ++y) {
+ const int half = block_size() / 2;
+ if (!use_high_bit_depth()) {
+ memset(src_, 0, half);
+ memset(src_ + half, 255, half);
+ memset(ref_, 255, half);
+ memset(ref_ + half, 0, half + width() + height() + 1);
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ vpx_memset16(CONVERT_TO_SHORTPTR(src_), mask(), half);
+ vpx_memset16(CONVERT_TO_SHORTPTR(src_) + half, 0, half);
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_), 0, half);
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_) + half, mask(),
+ half + width() + height() + 1);
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ unsigned int sse1, sse2;
+ unsigned int var1;
+ ASM_REGISTER_STATE_CHECK(
+ var1 = params_.func(ref_, width() + 1, x, y, src_, width(), &sse1));
+ const unsigned int var2 = subpel_variance_ref(
+ ref_, src_, params_.log2width, params_.log2height, x, y, &sse2,
+ use_high_bit_depth(), params_.bit_depth);
+ EXPECT_EQ(sse1, sse2) << "for xoffset " << x << " and yoffset " << y;
+ EXPECT_EQ(var1, var2) << "for xoffset " << x << " and yoffset " << y;
+ }
+ }
+}
+
+template <typename SubpelVarianceFunctionType>
+void SubpelVarianceTest<SubpelVarianceFunctionType>::SpeedTest() {
+ // The only interesting points are 0, 4, and anything else. To make the loops
+ // simple we will use 0, 2 and 4.
+ for (int x = 0; x <= 4; x += 2) {
+ for (int y = 0; y <= 4; y += 2) {
+ if (!use_high_bit_depth()) {
+ memset(src_, 25, block_size());
+ memset(ref_, 50, block_size());
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ vpx_memset16(CONVERT_TO_SHORTPTR(src_), 25, block_size());
+ vpx_memset16(CONVERT_TO_SHORTPTR(ref_), 50, block_size());
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ unsigned int sse;
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < 1000000000 / block_size(); ++i) {
+ const uint32_t variance =
+ params_.func(ref_, width() + 1, x, y, src_, width(), &sse);
+ (void)variance;
+ }
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ printf("SubpelVariance %dx%d xoffset: %d yoffset: %d time: %5d ms\n",
+ width(), height(), x, y, elapsed_time / 1000);
+ }
+ }
+}
+
+template <>
+void SubpelVarianceTest<vpx_subp_avg_variance_fn_t>::RefTest() {
+ for (int x = 0; x < 8; ++x) {
+ for (int y = 0; y < 8; ++y) {
+ if (!use_high_bit_depth()) {
+ for (int j = 0; j < block_size(); j++) {
+ src_[j] = rnd_.Rand8();
+ sec_[j] = rnd_.Rand8();
+ }
+ for (int j = 0; j < block_size() + width() + height() + 1; j++) {
+ ref_[j] = rnd_.Rand8();
+ }
+#if CONFIG_VP9_HIGHBITDEPTH
+ } else {
+ for (int j = 0; j < block_size(); j++) {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask();
+ CONVERT_TO_SHORTPTR(sec_)[j] = rnd_.Rand16() & mask();
+ }
+ for (int j = 0; j < block_size() + width() + height() + 1; j++) {
+ CONVERT_TO_SHORTPTR(ref_)[j] = rnd_.Rand16() & mask();
+ }
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ }
+ uint32_t sse1, sse2;
+ uint32_t var1, var2;
+ ASM_REGISTER_STATE_CHECK(var1 = params_.func(ref_, width() + 1, x, y,
+ src_, width(), &sse1, sec_));
+ var2 = subpel_avg_variance_ref(ref_, src_, sec_, params_.log2width,
+ params_.log2height, x, y, &sse2,
+ use_high_bit_depth(), params_.bit_depth);
+ EXPECT_EQ(sse1, sse2) << "at position " << x << ", " << y;
+ EXPECT_EQ(var1, var2) << "at position " << x << ", " << y;
+ }
+ }
+}
+
+typedef MainTestClass<Get4x4SseFunc> VpxSseTest;
+typedef MainTestClass<vpx_variance_fn_t> VpxMseTest;
+typedef MainTestClass<vpx_variance_fn_t> VpxVarianceTest;
+typedef SubpelVarianceTest<vpx_subpixvariance_fn_t> VpxSubpelVarianceTest;
+typedef SubpelVarianceTest<vpx_subp_avg_variance_fn_t> VpxSubpelAvgVarianceTest;
+
+TEST_P(VpxSseTest, RefSse) { RefTestSse(); }
+TEST_P(VpxSseTest, MaxSse) { MaxTestSse(); }
+TEST_P(VpxMseTest, RefMse) { RefTestMse(); }
+TEST_P(VpxMseTest, MaxMse) { MaxTestMse(); }
+TEST_P(VpxMseTest, DISABLED_Speed) { SpeedTest(); }
+TEST_P(VpxVarianceTest, Zero) { ZeroTest(); }
+TEST_P(VpxVarianceTest, Ref) { RefTest(); }
+TEST_P(VpxVarianceTest, RefStride) { RefStrideTest(); }
+TEST_P(VpxVarianceTest, OneQuarter) { OneQuarterTest(); }
+TEST_P(VpxVarianceTest, DISABLED_Speed) { SpeedTest(); }
+TEST_P(SumOfSquaresTest, Const) { ConstTest(); }
+TEST_P(SumOfSquaresTest, Ref) { RefTest(); }
+TEST_P(VpxSubpelVarianceTest, Ref) { RefTest(); }
+TEST_P(VpxSubpelVarianceTest, ExtremeRef) { ExtremeRefTest(); }
+TEST_P(VpxSubpelVarianceTest, DISABLED_Speed) { SpeedTest(); }
+TEST_P(VpxSubpelAvgVarianceTest, Ref) { RefTest(); }
+
+INSTANTIATE_TEST_SUITE_P(C, SumOfSquaresTest,
+ ::testing::Values(vpx_get_mb_ss_c));
+
+typedef TestParams<Get4x4SseFunc> SseParams;
+INSTANTIATE_TEST_SUITE_P(C, VpxSseTest,
+ ::testing::Values(SseParams(2, 2,
+ &vpx_get4x4sse_cs_c)));
+
+typedef TestParams<vpx_variance_fn_t> MseParams;
+INSTANTIATE_TEST_SUITE_P(C, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_c),
+ MseParams(4, 3, &vpx_mse16x8_c),
+ MseParams(3, 4, &vpx_mse8x16_c),
+ MseParams(3, 3, &vpx_mse8x8_c)));
+
+typedef TestParams<vpx_variance_fn_t> VarianceParams;
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_c),
+ VarianceParams(6, 5, &vpx_variance64x32_c),
+ VarianceParams(5, 6, &vpx_variance32x64_c),
+ VarianceParams(5, 5, &vpx_variance32x32_c),
+ VarianceParams(5, 4, &vpx_variance32x16_c),
+ VarianceParams(4, 5, &vpx_variance16x32_c),
+ VarianceParams(4, 4, &vpx_variance16x16_c),
+ VarianceParams(4, 3, &vpx_variance16x8_c),
+ VarianceParams(3, 4, &vpx_variance8x16_c),
+ VarianceParams(3, 3, &vpx_variance8x8_c),
+ VarianceParams(3, 2, &vpx_variance8x4_c),
+ VarianceParams(2, 3, &vpx_variance4x8_c),
+ VarianceParams(2, 2, &vpx_variance4x4_c)));
+
+typedef TestParams<vpx_subpixvariance_fn_t> SubpelVarianceParams;
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_c, 0),
+ SubpelVarianceParams(6, 5, &vpx_sub_pixel_variance64x32_c, 0),
+ SubpelVarianceParams(5, 6, &vpx_sub_pixel_variance32x64_c, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_c, 0),
+ SubpelVarianceParams(5, 4, &vpx_sub_pixel_variance32x16_c, 0),
+ SubpelVarianceParams(4, 5, &vpx_sub_pixel_variance16x32_c, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_c, 0),
+ SubpelVarianceParams(4, 3, &vpx_sub_pixel_variance16x8_c, 0),
+ SubpelVarianceParams(3, 4, &vpx_sub_pixel_variance8x16_c, 0),
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_c, 0),
+ SubpelVarianceParams(3, 2, &vpx_sub_pixel_variance8x4_c, 0),
+ SubpelVarianceParams(2, 3, &vpx_sub_pixel_variance4x8_c, 0),
+ SubpelVarianceParams(2, 2, &vpx_sub_pixel_variance4x4_c, 0)));
+
+typedef TestParams<vpx_subp_avg_variance_fn_t> SubpelAvgVarianceParams;
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_c, 0),
+ SubpelAvgVarianceParams(6, 5, &vpx_sub_pixel_avg_variance64x32_c, 0),
+ SubpelAvgVarianceParams(5, 6, &vpx_sub_pixel_avg_variance32x64_c, 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_c, 0),
+ SubpelAvgVarianceParams(5, 4, &vpx_sub_pixel_avg_variance32x16_c, 0),
+ SubpelAvgVarianceParams(4, 5, &vpx_sub_pixel_avg_variance16x32_c, 0),
+ SubpelAvgVarianceParams(4, 4, &vpx_sub_pixel_avg_variance16x16_c, 0),
+ SubpelAvgVarianceParams(4, 3, &vpx_sub_pixel_avg_variance16x8_c, 0),
+ SubpelAvgVarianceParams(3, 4, &vpx_sub_pixel_avg_variance8x16_c, 0),
+ SubpelAvgVarianceParams(3, 3, &vpx_sub_pixel_avg_variance8x8_c, 0),
+ SubpelAvgVarianceParams(3, 2, &vpx_sub_pixel_avg_variance8x4_c, 0),
+ SubpelAvgVarianceParams(2, 3, &vpx_sub_pixel_avg_variance4x8_c, 0),
+ SubpelAvgVarianceParams(2, 2, &vpx_sub_pixel_avg_variance4x4_c, 0)));
+
+#if CONFIG_VP9_HIGHBITDEPTH
+typedef MainTestClass<vpx_variance_fn_t> VpxHBDVarianceTest;
+typedef SubpelVarianceTest<vpx_subpixvariance_fn_t> VpxHBDSubpelVarianceTest;
+typedef SubpelVarianceTest<vpx_subp_avg_variance_fn_t>
+ VpxHBDSubpelAvgVarianceTest;
+
+TEST_P(VpxHBDVarianceTest, Zero) { ZeroTest(); }
+TEST_P(VpxHBDVarianceTest, Ref) { RefTest(); }
+TEST_P(VpxHBDVarianceTest, RefStride) { RefStrideTest(); }
+TEST_P(VpxHBDVarianceTest, OneQuarter) { OneQuarterTest(); }
+TEST_P(VpxHBDVarianceTest, DISABLED_Speed) { SpeedTest(); }
+TEST_P(VpxHBDSubpelVarianceTest, Ref) { RefTest(); }
+TEST_P(VpxHBDSubpelVarianceTest, ExtremeRef) { ExtremeRefTest(); }
+TEST_P(VpxHBDSubpelAvgVarianceTest, Ref) { RefTest(); }
+
+typedef MainTestClass<vpx_variance_fn_t> VpxHBDMseTest;
+TEST_P(VpxHBDMseTest, RefMse) { RefTestMse(); }
+TEST_P(VpxHBDMseTest, MaxMse) { MaxTestMse(); }
+TEST_P(VpxHBDMseTest, DISABLED_Speed) { SpeedTest(); }
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxHBDMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_highbd_12_mse16x16_c, VPX_BITS_12),
+ MseParams(4, 3, &vpx_highbd_12_mse16x8_c, VPX_BITS_12),
+ MseParams(3, 4, &vpx_highbd_12_mse8x16_c, VPX_BITS_12),
+ MseParams(3, 3, &vpx_highbd_12_mse8x8_c, VPX_BITS_12),
+ MseParams(4, 4, &vpx_highbd_10_mse16x16_c, VPX_BITS_10),
+ MseParams(4, 3, &vpx_highbd_10_mse16x8_c, VPX_BITS_10),
+ MseParams(3, 4, &vpx_highbd_10_mse8x16_c, VPX_BITS_10),
+ MseParams(3, 3, &vpx_highbd_10_mse8x8_c, VPX_BITS_10),
+ MseParams(4, 4, &vpx_highbd_8_mse16x16_c, VPX_BITS_8),
+ MseParams(4, 3, &vpx_highbd_8_mse16x8_c, VPX_BITS_8),
+ MseParams(3, 4, &vpx_highbd_8_mse8x16_c, VPX_BITS_8),
+ MseParams(3, 3, &vpx_highbd_8_mse8x8_c, VPX_BITS_8)));
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VpxHBDMseTest);
+
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxHBDVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_highbd_12_variance64x64_c, 12),
+ VarianceParams(6, 5, &vpx_highbd_12_variance64x32_c, 12),
+ VarianceParams(5, 6, &vpx_highbd_12_variance32x64_c, 12),
+ VarianceParams(5, 5, &vpx_highbd_12_variance32x32_c, 12),
+ VarianceParams(5, 4, &vpx_highbd_12_variance32x16_c, 12),
+ VarianceParams(4, 5, &vpx_highbd_12_variance16x32_c, 12),
+ VarianceParams(4, 4, &vpx_highbd_12_variance16x16_c, 12),
+ VarianceParams(4, 3, &vpx_highbd_12_variance16x8_c, 12),
+ VarianceParams(3, 4, &vpx_highbd_12_variance8x16_c, 12),
+ VarianceParams(3, 3, &vpx_highbd_12_variance8x8_c, 12),
+ VarianceParams(3, 2, &vpx_highbd_12_variance8x4_c, 12),
+ VarianceParams(2, 3, &vpx_highbd_12_variance4x8_c, 12),
+ VarianceParams(2, 2, &vpx_highbd_12_variance4x4_c, 12),
+ VarianceParams(6, 6, &vpx_highbd_10_variance64x64_c, 10),
+ VarianceParams(6, 5, &vpx_highbd_10_variance64x32_c, 10),
+ VarianceParams(5, 6, &vpx_highbd_10_variance32x64_c, 10),
+ VarianceParams(5, 5, &vpx_highbd_10_variance32x32_c, 10),
+ VarianceParams(5, 4, &vpx_highbd_10_variance32x16_c, 10),
+ VarianceParams(4, 5, &vpx_highbd_10_variance16x32_c, 10),
+ VarianceParams(4, 4, &vpx_highbd_10_variance16x16_c, 10),
+ VarianceParams(4, 3, &vpx_highbd_10_variance16x8_c, 10),
+ VarianceParams(3, 4, &vpx_highbd_10_variance8x16_c, 10),
+ VarianceParams(3, 3, &vpx_highbd_10_variance8x8_c, 10),
+ VarianceParams(3, 2, &vpx_highbd_10_variance8x4_c, 10),
+ VarianceParams(2, 3, &vpx_highbd_10_variance4x8_c, 10),
+ VarianceParams(2, 2, &vpx_highbd_10_variance4x4_c, 10),
+ VarianceParams(6, 6, &vpx_highbd_8_variance64x64_c, 8),
+ VarianceParams(6, 5, &vpx_highbd_8_variance64x32_c, 8),
+ VarianceParams(5, 6, &vpx_highbd_8_variance32x64_c, 8),
+ VarianceParams(5, 5, &vpx_highbd_8_variance32x32_c, 8),
+ VarianceParams(5, 4, &vpx_highbd_8_variance32x16_c, 8),
+ VarianceParams(4, 5, &vpx_highbd_8_variance16x32_c, 8),
+ VarianceParams(4, 4, &vpx_highbd_8_variance16x16_c, 8),
+ VarianceParams(4, 3, &vpx_highbd_8_variance16x8_c, 8),
+ VarianceParams(3, 4, &vpx_highbd_8_variance8x16_c, 8),
+ VarianceParams(3, 3, &vpx_highbd_8_variance8x8_c, 8),
+ VarianceParams(3, 2, &vpx_highbd_8_variance8x4_c, 8),
+ VarianceParams(2, 3, &vpx_highbd_8_variance4x8_c, 8),
+ VarianceParams(2, 2, &vpx_highbd_8_variance4x4_c, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxHBDSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_highbd_8_sub_pixel_variance64x64_c, 8),
+ SubpelVarianceParams(6, 5, &vpx_highbd_8_sub_pixel_variance64x32_c, 8),
+ SubpelVarianceParams(5, 6, &vpx_highbd_8_sub_pixel_variance32x64_c, 8),
+ SubpelVarianceParams(5, 5, &vpx_highbd_8_sub_pixel_variance32x32_c, 8),
+ SubpelVarianceParams(5, 4, &vpx_highbd_8_sub_pixel_variance32x16_c, 8),
+ SubpelVarianceParams(4, 5, &vpx_highbd_8_sub_pixel_variance16x32_c, 8),
+ SubpelVarianceParams(4, 4, &vpx_highbd_8_sub_pixel_variance16x16_c, 8),
+ SubpelVarianceParams(4, 3, &vpx_highbd_8_sub_pixel_variance16x8_c, 8),
+ SubpelVarianceParams(3, 4, &vpx_highbd_8_sub_pixel_variance8x16_c, 8),
+ SubpelVarianceParams(3, 3, &vpx_highbd_8_sub_pixel_variance8x8_c, 8),
+ SubpelVarianceParams(3, 2, &vpx_highbd_8_sub_pixel_variance8x4_c, 8),
+ SubpelVarianceParams(2, 3, &vpx_highbd_8_sub_pixel_variance4x8_c, 8),
+ SubpelVarianceParams(2, 2, &vpx_highbd_8_sub_pixel_variance4x4_c, 8),
+ SubpelVarianceParams(6, 6, &vpx_highbd_10_sub_pixel_variance64x64_c,
+ 10),
+ SubpelVarianceParams(6, 5, &vpx_highbd_10_sub_pixel_variance64x32_c,
+ 10),
+ SubpelVarianceParams(5, 6, &vpx_highbd_10_sub_pixel_variance32x64_c,
+ 10),
+ SubpelVarianceParams(5, 5, &vpx_highbd_10_sub_pixel_variance32x32_c,
+ 10),
+ SubpelVarianceParams(5, 4, &vpx_highbd_10_sub_pixel_variance32x16_c,
+ 10),
+ SubpelVarianceParams(4, 5, &vpx_highbd_10_sub_pixel_variance16x32_c,
+ 10),
+ SubpelVarianceParams(4, 4, &vpx_highbd_10_sub_pixel_variance16x16_c,
+ 10),
+ SubpelVarianceParams(4, 3, &vpx_highbd_10_sub_pixel_variance16x8_c, 10),
+ SubpelVarianceParams(3, 4, &vpx_highbd_10_sub_pixel_variance8x16_c, 10),
+ SubpelVarianceParams(3, 3, &vpx_highbd_10_sub_pixel_variance8x8_c, 10),
+ SubpelVarianceParams(3, 2, &vpx_highbd_10_sub_pixel_variance8x4_c, 10),
+ SubpelVarianceParams(2, 3, &vpx_highbd_10_sub_pixel_variance4x8_c, 10),
+ SubpelVarianceParams(2, 2, &vpx_highbd_10_sub_pixel_variance4x4_c, 10),
+ SubpelVarianceParams(6, 6, &vpx_highbd_12_sub_pixel_variance64x64_c,
+ 12),
+ SubpelVarianceParams(6, 5, &vpx_highbd_12_sub_pixel_variance64x32_c,
+ 12),
+ SubpelVarianceParams(5, 6, &vpx_highbd_12_sub_pixel_variance32x64_c,
+ 12),
+ SubpelVarianceParams(5, 5, &vpx_highbd_12_sub_pixel_variance32x32_c,
+ 12),
+ SubpelVarianceParams(5, 4, &vpx_highbd_12_sub_pixel_variance32x16_c,
+ 12),
+ SubpelVarianceParams(4, 5, &vpx_highbd_12_sub_pixel_variance16x32_c,
+ 12),
+ SubpelVarianceParams(4, 4, &vpx_highbd_12_sub_pixel_variance16x16_c,
+ 12),
+ SubpelVarianceParams(4, 3, &vpx_highbd_12_sub_pixel_variance16x8_c, 12),
+ SubpelVarianceParams(3, 4, &vpx_highbd_12_sub_pixel_variance8x16_c, 12),
+ SubpelVarianceParams(3, 3, &vpx_highbd_12_sub_pixel_variance8x8_c, 12),
+ SubpelVarianceParams(3, 2, &vpx_highbd_12_sub_pixel_variance8x4_c, 12),
+ SubpelVarianceParams(2, 3, &vpx_highbd_12_sub_pixel_variance4x8_c, 12),
+ SubpelVarianceParams(2, 2, &vpx_highbd_12_sub_pixel_variance4x4_c,
+ 12)));
+
+INSTANTIATE_TEST_SUITE_P(
+ C, VpxHBDSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_8_sub_pixel_avg_variance64x64_c, 8),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance64x32_c, 8),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_8_sub_pixel_avg_variance32x64_c, 8),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance32x32_c, 8),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance32x16_c, 8),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance16x32_c, 8),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance16x16_c, 8),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_8_sub_pixel_avg_variance16x8_c, 8),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance8x16_c, 8),
+ SubpelAvgVarianceParams(3, 3, &vpx_highbd_8_sub_pixel_avg_variance8x8_c,
+ 8),
+ SubpelAvgVarianceParams(3, 2, &vpx_highbd_8_sub_pixel_avg_variance8x4_c,
+ 8),
+ SubpelAvgVarianceParams(2, 3, &vpx_highbd_8_sub_pixel_avg_variance4x8_c,
+ 8),
+ SubpelAvgVarianceParams(2, 2, &vpx_highbd_8_sub_pixel_avg_variance4x4_c,
+ 8),
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_10_sub_pixel_avg_variance64x64_c,
+ 10),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance64x32_c,
+ 10),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_10_sub_pixel_avg_variance32x64_c,
+ 10),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance32x32_c,
+ 10),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance32x16_c,
+ 10),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance16x32_c,
+ 10),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance16x16_c,
+ 10),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance16x8_c,
+ 10),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance8x16_c,
+ 10),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance8x8_c, 10),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_10_sub_pixel_avg_variance8x4_c, 10),
+ SubpelAvgVarianceParams(2, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance4x8_c, 10),
+ SubpelAvgVarianceParams(2, 2,
+ &vpx_highbd_10_sub_pixel_avg_variance4x4_c, 10),
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_12_sub_pixel_avg_variance64x64_c,
+ 12),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance64x32_c,
+ 12),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_12_sub_pixel_avg_variance32x64_c,
+ 12),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance32x32_c,
+ 12),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance32x16_c,
+ 12),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance16x32_c,
+ 12),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance16x16_c,
+ 12),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance16x8_c,
+ 12),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance8x16_c,
+ 12),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance8x8_c, 12),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_12_sub_pixel_avg_variance8x4_c, 12),
+ SubpelAvgVarianceParams(2, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance4x8_c, 12),
+ SubpelAvgVarianceParams(2, 2,
+ &vpx_highbd_12_sub_pixel_avg_variance4x4_c,
+ 12)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(SSE2, SumOfSquaresTest,
+ ::testing::Values(vpx_get_mb_ss_sse2));
+
+INSTANTIATE_TEST_SUITE_P(SSE2, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_sse2),
+ MseParams(4, 3, &vpx_mse16x8_sse2),
+ MseParams(3, 4, &vpx_mse8x16_sse2),
+ MseParams(3, 3, &vpx_mse8x8_sse2)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_sse2),
+ VarianceParams(6, 5, &vpx_variance64x32_sse2),
+ VarianceParams(5, 6, &vpx_variance32x64_sse2),
+ VarianceParams(5, 5, &vpx_variance32x32_sse2),
+ VarianceParams(5, 4, &vpx_variance32x16_sse2),
+ VarianceParams(4, 5, &vpx_variance16x32_sse2),
+ VarianceParams(4, 4, &vpx_variance16x16_sse2),
+ VarianceParams(4, 3, &vpx_variance16x8_sse2),
+ VarianceParams(3, 4, &vpx_variance8x16_sse2),
+ VarianceParams(3, 3, &vpx_variance8x8_sse2),
+ VarianceParams(3, 2, &vpx_variance8x4_sse2),
+ VarianceParams(2, 3, &vpx_variance4x8_sse2),
+ VarianceParams(2, 2, &vpx_variance4x4_sse2)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_sse2, 0),
+ SubpelVarianceParams(6, 5, &vpx_sub_pixel_variance64x32_sse2, 0),
+ SubpelVarianceParams(5, 6, &vpx_sub_pixel_variance32x64_sse2, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_sse2, 0),
+ SubpelVarianceParams(5, 4, &vpx_sub_pixel_variance32x16_sse2, 0),
+ SubpelVarianceParams(4, 5, &vpx_sub_pixel_variance16x32_sse2, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_sse2, 0),
+ SubpelVarianceParams(4, 3, &vpx_sub_pixel_variance16x8_sse2, 0),
+ SubpelVarianceParams(3, 4, &vpx_sub_pixel_variance8x16_sse2, 0),
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_sse2, 0),
+ SubpelVarianceParams(3, 2, &vpx_sub_pixel_variance8x4_sse2, 0),
+ SubpelVarianceParams(2, 3, &vpx_sub_pixel_variance4x8_sse2, 0),
+ SubpelVarianceParams(2, 2, &vpx_sub_pixel_variance4x4_sse2, 0)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_sse2, 0),
+ SubpelAvgVarianceParams(6, 5, &vpx_sub_pixel_avg_variance64x32_sse2, 0),
+ SubpelAvgVarianceParams(5, 6, &vpx_sub_pixel_avg_variance32x64_sse2, 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_sse2, 0),
+ SubpelAvgVarianceParams(5, 4, &vpx_sub_pixel_avg_variance32x16_sse2, 0),
+ SubpelAvgVarianceParams(4, 5, &vpx_sub_pixel_avg_variance16x32_sse2, 0),
+ SubpelAvgVarianceParams(4, 4, &vpx_sub_pixel_avg_variance16x16_sse2, 0),
+ SubpelAvgVarianceParams(4, 3, &vpx_sub_pixel_avg_variance16x8_sse2, 0),
+ SubpelAvgVarianceParams(3, 4, &vpx_sub_pixel_avg_variance8x16_sse2, 0),
+ SubpelAvgVarianceParams(3, 3, &vpx_sub_pixel_avg_variance8x8_sse2, 0),
+ SubpelAvgVarianceParams(3, 2, &vpx_sub_pixel_avg_variance8x4_sse2, 0),
+ SubpelAvgVarianceParams(2, 3, &vpx_sub_pixel_avg_variance4x8_sse2, 0),
+ SubpelAvgVarianceParams(2, 2, &vpx_sub_pixel_avg_variance4x4_sse2, 0)));
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxHBDMseTest,
+ ::testing::Values(
+ MseParams(4, 4, &vpx_highbd_12_mse16x16_sse2, VPX_BITS_12),
+ MseParams(3, 3, &vpx_highbd_12_mse8x8_sse2, VPX_BITS_12),
+ MseParams(4, 4, &vpx_highbd_10_mse16x16_sse2, VPX_BITS_10),
+ MseParams(3, 3, &vpx_highbd_10_mse8x8_sse2, VPX_BITS_10),
+ MseParams(4, 4, &vpx_highbd_8_mse16x16_sse2, VPX_BITS_8),
+ MseParams(3, 3, &vpx_highbd_8_mse8x8_sse2, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxHBDVarianceTest,
+ ::testing::Values(
+ VarianceParams(6, 6, &vpx_highbd_12_variance64x64_sse2, 12),
+ VarianceParams(6, 5, &vpx_highbd_12_variance64x32_sse2, 12),
+ VarianceParams(5, 6, &vpx_highbd_12_variance32x64_sse2, 12),
+ VarianceParams(5, 5, &vpx_highbd_12_variance32x32_sse2, 12),
+ VarianceParams(5, 4, &vpx_highbd_12_variance32x16_sse2, 12),
+ VarianceParams(4, 5, &vpx_highbd_12_variance16x32_sse2, 12),
+ VarianceParams(4, 4, &vpx_highbd_12_variance16x16_sse2, 12),
+ VarianceParams(4, 3, &vpx_highbd_12_variance16x8_sse2, 12),
+ VarianceParams(3, 4, &vpx_highbd_12_variance8x16_sse2, 12),
+ VarianceParams(3, 3, &vpx_highbd_12_variance8x8_sse2, 12),
+ VarianceParams(6, 6, &vpx_highbd_10_variance64x64_sse2, 10),
+ VarianceParams(6, 5, &vpx_highbd_10_variance64x32_sse2, 10),
+ VarianceParams(5, 6, &vpx_highbd_10_variance32x64_sse2, 10),
+ VarianceParams(5, 5, &vpx_highbd_10_variance32x32_sse2, 10),
+ VarianceParams(5, 4, &vpx_highbd_10_variance32x16_sse2, 10),
+ VarianceParams(4, 5, &vpx_highbd_10_variance16x32_sse2, 10),
+ VarianceParams(4, 4, &vpx_highbd_10_variance16x16_sse2, 10),
+ VarianceParams(4, 3, &vpx_highbd_10_variance16x8_sse2, 10),
+ VarianceParams(3, 4, &vpx_highbd_10_variance8x16_sse2, 10),
+ VarianceParams(3, 3, &vpx_highbd_10_variance8x8_sse2, 10),
+ VarianceParams(6, 6, &vpx_highbd_8_variance64x64_sse2, 8),
+ VarianceParams(6, 5, &vpx_highbd_8_variance64x32_sse2, 8),
+ VarianceParams(5, 6, &vpx_highbd_8_variance32x64_sse2, 8),
+ VarianceParams(5, 5, &vpx_highbd_8_variance32x32_sse2, 8),
+ VarianceParams(5, 4, &vpx_highbd_8_variance32x16_sse2, 8),
+ VarianceParams(4, 5, &vpx_highbd_8_variance16x32_sse2, 8),
+ VarianceParams(4, 4, &vpx_highbd_8_variance16x16_sse2, 8),
+ VarianceParams(4, 3, &vpx_highbd_8_variance16x8_sse2, 8),
+ VarianceParams(3, 4, &vpx_highbd_8_variance8x16_sse2, 8),
+ VarianceParams(3, 3, &vpx_highbd_8_variance8x8_sse2, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxHBDSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_highbd_12_sub_pixel_variance64x64_sse2,
+ 12),
+ SubpelVarianceParams(6, 5, &vpx_highbd_12_sub_pixel_variance64x32_sse2,
+ 12),
+ SubpelVarianceParams(5, 6, &vpx_highbd_12_sub_pixel_variance32x64_sse2,
+ 12),
+ SubpelVarianceParams(5, 5, &vpx_highbd_12_sub_pixel_variance32x32_sse2,
+ 12),
+ SubpelVarianceParams(5, 4, &vpx_highbd_12_sub_pixel_variance32x16_sse2,
+ 12),
+ SubpelVarianceParams(4, 5, &vpx_highbd_12_sub_pixel_variance16x32_sse2,
+ 12),
+ SubpelVarianceParams(4, 4, &vpx_highbd_12_sub_pixel_variance16x16_sse2,
+ 12),
+ SubpelVarianceParams(4, 3, &vpx_highbd_12_sub_pixel_variance16x8_sse2,
+ 12),
+ SubpelVarianceParams(3, 4, &vpx_highbd_12_sub_pixel_variance8x16_sse2,
+ 12),
+ SubpelVarianceParams(3, 3, &vpx_highbd_12_sub_pixel_variance8x8_sse2,
+ 12),
+ SubpelVarianceParams(3, 2, &vpx_highbd_12_sub_pixel_variance8x4_sse2,
+ 12),
+ SubpelVarianceParams(6, 6, &vpx_highbd_10_sub_pixel_variance64x64_sse2,
+ 10),
+ SubpelVarianceParams(6, 5, &vpx_highbd_10_sub_pixel_variance64x32_sse2,
+ 10),
+ SubpelVarianceParams(5, 6, &vpx_highbd_10_sub_pixel_variance32x64_sse2,
+ 10),
+ SubpelVarianceParams(5, 5, &vpx_highbd_10_sub_pixel_variance32x32_sse2,
+ 10),
+ SubpelVarianceParams(5, 4, &vpx_highbd_10_sub_pixel_variance32x16_sse2,
+ 10),
+ SubpelVarianceParams(4, 5, &vpx_highbd_10_sub_pixel_variance16x32_sse2,
+ 10),
+ SubpelVarianceParams(4, 4, &vpx_highbd_10_sub_pixel_variance16x16_sse2,
+ 10),
+ SubpelVarianceParams(4, 3, &vpx_highbd_10_sub_pixel_variance16x8_sse2,
+ 10),
+ SubpelVarianceParams(3, 4, &vpx_highbd_10_sub_pixel_variance8x16_sse2,
+ 10),
+ SubpelVarianceParams(3, 3, &vpx_highbd_10_sub_pixel_variance8x8_sse2,
+ 10),
+ SubpelVarianceParams(3, 2, &vpx_highbd_10_sub_pixel_variance8x4_sse2,
+ 10),
+ SubpelVarianceParams(6, 6, &vpx_highbd_8_sub_pixel_variance64x64_sse2,
+ 8),
+ SubpelVarianceParams(6, 5, &vpx_highbd_8_sub_pixel_variance64x32_sse2,
+ 8),
+ SubpelVarianceParams(5, 6, &vpx_highbd_8_sub_pixel_variance32x64_sse2,
+ 8),
+ SubpelVarianceParams(5, 5, &vpx_highbd_8_sub_pixel_variance32x32_sse2,
+ 8),
+ SubpelVarianceParams(5, 4, &vpx_highbd_8_sub_pixel_variance32x16_sse2,
+ 8),
+ SubpelVarianceParams(4, 5, &vpx_highbd_8_sub_pixel_variance16x32_sse2,
+ 8),
+ SubpelVarianceParams(4, 4, &vpx_highbd_8_sub_pixel_variance16x16_sse2,
+ 8),
+ SubpelVarianceParams(4, 3, &vpx_highbd_8_sub_pixel_variance16x8_sse2,
+ 8),
+ SubpelVarianceParams(3, 4, &vpx_highbd_8_sub_pixel_variance8x16_sse2,
+ 8),
+ SubpelVarianceParams(3, 3, &vpx_highbd_8_sub_pixel_variance8x8_sse2, 8),
+ SubpelVarianceParams(3, 2, &vpx_highbd_8_sub_pixel_variance8x4_sse2,
+ 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VpxHBDSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_12_sub_pixel_avg_variance64x64_sse2,
+ 12),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance64x32_sse2,
+ 12),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_12_sub_pixel_avg_variance32x64_sse2,
+ 12),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance32x32_sse2,
+ 12),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance32x16_sse2,
+ 12),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance16x32_sse2,
+ 12),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance16x16_sse2,
+ 12),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance16x8_sse2,
+ 12),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance8x16_sse2,
+ 12),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance8x8_sse2,
+ 12),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_12_sub_pixel_avg_variance8x4_sse2,
+ 12),
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_10_sub_pixel_avg_variance64x64_sse2,
+ 10),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance64x32_sse2,
+ 10),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_10_sub_pixel_avg_variance32x64_sse2,
+ 10),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance32x32_sse2,
+ 10),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance32x16_sse2,
+ 10),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance16x32_sse2,
+ 10),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance16x16_sse2,
+ 10),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance16x8_sse2,
+ 10),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance8x16_sse2,
+ 10),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance8x8_sse2,
+ 10),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_10_sub_pixel_avg_variance8x4_sse2,
+ 10),
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_8_sub_pixel_avg_variance64x64_sse2,
+ 8),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance64x32_sse2,
+ 8),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_8_sub_pixel_avg_variance32x64_sse2,
+ 8),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance32x32_sse2,
+ 8),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance32x16_sse2,
+ 8),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance16x32_sse2,
+ 8),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance16x16_sse2,
+ 8),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_8_sub_pixel_avg_variance16x8_sse2,
+ 8),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance8x16_sse2,
+ 8),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_8_sub_pixel_avg_variance8x8_sse2,
+ 8),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_8_sub_pixel_avg_variance8x4_sse2,
+ 8)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_ssse3, 0),
+ SubpelVarianceParams(6, 5, &vpx_sub_pixel_variance64x32_ssse3, 0),
+ SubpelVarianceParams(5, 6, &vpx_sub_pixel_variance32x64_ssse3, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_ssse3, 0),
+ SubpelVarianceParams(5, 4, &vpx_sub_pixel_variance32x16_ssse3, 0),
+ SubpelVarianceParams(4, 5, &vpx_sub_pixel_variance16x32_ssse3, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_ssse3, 0),
+ SubpelVarianceParams(4, 3, &vpx_sub_pixel_variance16x8_ssse3, 0),
+ SubpelVarianceParams(3, 4, &vpx_sub_pixel_variance8x16_ssse3, 0),
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_ssse3, 0),
+ SubpelVarianceParams(3, 2, &vpx_sub_pixel_variance8x4_ssse3, 0),
+ SubpelVarianceParams(2, 3, &vpx_sub_pixel_variance4x8_ssse3, 0),
+ SubpelVarianceParams(2, 2, &vpx_sub_pixel_variance4x4_ssse3, 0)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_ssse3,
+ 0),
+ SubpelAvgVarianceParams(6, 5, &vpx_sub_pixel_avg_variance64x32_ssse3,
+ 0),
+ SubpelAvgVarianceParams(5, 6, &vpx_sub_pixel_avg_variance32x64_ssse3,
+ 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_ssse3,
+ 0),
+ SubpelAvgVarianceParams(5, 4, &vpx_sub_pixel_avg_variance32x16_ssse3,
+ 0),
+ SubpelAvgVarianceParams(4, 5, &vpx_sub_pixel_avg_variance16x32_ssse3,
+ 0),
+ SubpelAvgVarianceParams(4, 4, &vpx_sub_pixel_avg_variance16x16_ssse3,
+ 0),
+ SubpelAvgVarianceParams(4, 3, &vpx_sub_pixel_avg_variance16x8_ssse3, 0),
+ SubpelAvgVarianceParams(3, 4, &vpx_sub_pixel_avg_variance8x16_ssse3, 0),
+ SubpelAvgVarianceParams(3, 3, &vpx_sub_pixel_avg_variance8x8_ssse3, 0),
+ SubpelAvgVarianceParams(3, 2, &vpx_sub_pixel_avg_variance8x4_ssse3, 0),
+ SubpelAvgVarianceParams(2, 3, &vpx_sub_pixel_avg_variance4x8_ssse3, 0),
+ SubpelAvgVarianceParams(2, 2, &vpx_sub_pixel_avg_variance4x4_ssse3,
+ 0)));
+#endif // HAVE_SSSE3
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(AVX2, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_avx2),
+ MseParams(4, 3, &vpx_mse16x8_avx2)));
+
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_avx2),
+ VarianceParams(6, 5, &vpx_variance64x32_avx2),
+ VarianceParams(5, 6, &vpx_variance32x64_avx2),
+ VarianceParams(5, 5, &vpx_variance32x32_avx2),
+ VarianceParams(5, 4, &vpx_variance32x16_avx2),
+ VarianceParams(4, 5, &vpx_variance16x32_avx2),
+ VarianceParams(4, 4, &vpx_variance16x16_avx2),
+ VarianceParams(4, 3, &vpx_variance16x8_avx2),
+ VarianceParams(3, 4, &vpx_variance8x16_avx2),
+ VarianceParams(3, 3, &vpx_variance8x8_avx2),
+ VarianceParams(3, 2, &vpx_variance8x4_avx2)));
+
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_avx2, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_avx2, 0)));
+
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_avx2, 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_avx2,
+ 0)));
+#endif // HAVE_AVX2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, VpxSseTest,
+ ::testing::Values(SseParams(2, 2,
+ &vpx_get4x4sse_cs_neon)));
+
+INSTANTIATE_TEST_SUITE_P(NEON, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_neon),
+ MseParams(4, 3, &vpx_mse16x8_neon),
+ MseParams(3, 4, &vpx_mse8x16_neon),
+ MseParams(3, 3, &vpx_mse8x8_neon)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_neon),
+ VarianceParams(6, 5, &vpx_variance64x32_neon),
+ VarianceParams(5, 6, &vpx_variance32x64_neon),
+ VarianceParams(5, 5, &vpx_variance32x32_neon),
+ VarianceParams(5, 4, &vpx_variance32x16_neon),
+ VarianceParams(4, 5, &vpx_variance16x32_neon),
+ VarianceParams(4, 4, &vpx_variance16x16_neon),
+ VarianceParams(4, 3, &vpx_variance16x8_neon),
+ VarianceParams(3, 4, &vpx_variance8x16_neon),
+ VarianceParams(3, 3, &vpx_variance8x8_neon),
+ VarianceParams(3, 2, &vpx_variance8x4_neon),
+ VarianceParams(2, 3, &vpx_variance4x8_neon),
+ VarianceParams(2, 2, &vpx_variance4x4_neon)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_neon, 0),
+ SubpelVarianceParams(6, 5, &vpx_sub_pixel_variance64x32_neon, 0),
+ SubpelVarianceParams(5, 6, &vpx_sub_pixel_variance32x64_neon, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_neon, 0),
+ SubpelVarianceParams(5, 4, &vpx_sub_pixel_variance32x16_neon, 0),
+ SubpelVarianceParams(4, 5, &vpx_sub_pixel_variance16x32_neon, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_neon, 0),
+ SubpelVarianceParams(4, 3, &vpx_sub_pixel_variance16x8_neon, 0),
+ SubpelVarianceParams(3, 4, &vpx_sub_pixel_variance8x16_neon, 0),
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_neon, 0),
+ SubpelVarianceParams(3, 2, &vpx_sub_pixel_variance8x4_neon, 0),
+ SubpelVarianceParams(2, 3, &vpx_sub_pixel_variance4x8_neon, 0),
+ SubpelVarianceParams(2, 2, &vpx_sub_pixel_variance4x4_neon, 0)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_neon, 0),
+ SubpelAvgVarianceParams(6, 5, &vpx_sub_pixel_avg_variance64x32_neon, 0),
+ SubpelAvgVarianceParams(5, 6, &vpx_sub_pixel_avg_variance32x64_neon, 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_neon, 0),
+ SubpelAvgVarianceParams(5, 4, &vpx_sub_pixel_avg_variance32x16_neon, 0),
+ SubpelAvgVarianceParams(4, 5, &vpx_sub_pixel_avg_variance16x32_neon, 0),
+ SubpelAvgVarianceParams(4, 4, &vpx_sub_pixel_avg_variance16x16_neon, 0),
+ SubpelAvgVarianceParams(4, 3, &vpx_sub_pixel_avg_variance16x8_neon, 0),
+ SubpelAvgVarianceParams(3, 4, &vpx_sub_pixel_avg_variance8x16_neon, 0),
+ SubpelAvgVarianceParams(3, 3, &vpx_sub_pixel_avg_variance8x8_neon, 0),
+ SubpelAvgVarianceParams(3, 2, &vpx_sub_pixel_avg_variance8x4_neon, 0),
+ SubpelAvgVarianceParams(2, 3, &vpx_sub_pixel_avg_variance4x8_neon, 0),
+ SubpelAvgVarianceParams(2, 2, &vpx_sub_pixel_avg_variance4x4_neon, 0)));
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxHBDMseTest,
+ ::testing::Values(
+ MseParams(4, 4, &vpx_highbd_12_mse16x16_neon, VPX_BITS_12),
+ MseParams(4, 3, &vpx_highbd_12_mse16x8_neon, VPX_BITS_12),
+ MseParams(3, 4, &vpx_highbd_12_mse8x16_neon, VPX_BITS_12),
+ MseParams(3, 3, &vpx_highbd_12_mse8x8_neon, VPX_BITS_12),
+ MseParams(4, 4, &vpx_highbd_10_mse16x16_neon, VPX_BITS_10),
+ MseParams(4, 3, &vpx_highbd_10_mse16x8_neon, VPX_BITS_10),
+ MseParams(3, 4, &vpx_highbd_10_mse8x16_neon, VPX_BITS_10),
+ MseParams(3, 3, &vpx_highbd_10_mse8x8_neon, VPX_BITS_10),
+ MseParams(4, 4, &vpx_highbd_8_mse16x16_neon, VPX_BITS_8),
+ MseParams(4, 3, &vpx_highbd_8_mse16x8_neon, VPX_BITS_8),
+ MseParams(3, 4, &vpx_highbd_8_mse8x16_neon, VPX_BITS_8),
+ MseParams(3, 3, &vpx_highbd_8_mse8x8_neon, VPX_BITS_8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxHBDVarianceTest,
+ ::testing::Values(
+ VarianceParams(6, 6, &vpx_highbd_12_variance64x64_neon, 12),
+ VarianceParams(6, 5, &vpx_highbd_12_variance64x32_neon, 12),
+ VarianceParams(5, 6, &vpx_highbd_12_variance32x64_neon, 12),
+ VarianceParams(5, 5, &vpx_highbd_12_variance32x32_neon, 12),
+ VarianceParams(5, 4, &vpx_highbd_12_variance32x16_neon, 12),
+ VarianceParams(4, 5, &vpx_highbd_12_variance16x32_neon, 12),
+ VarianceParams(4, 4, &vpx_highbd_12_variance16x16_neon, 12),
+ VarianceParams(4, 3, &vpx_highbd_12_variance16x8_neon, 12),
+ VarianceParams(3, 4, &vpx_highbd_12_variance8x16_neon, 12),
+ VarianceParams(3, 3, &vpx_highbd_12_variance8x8_neon, 12),
+ VarianceParams(3, 2, &vpx_highbd_12_variance8x4_neon, 12),
+ VarianceParams(2, 3, &vpx_highbd_12_variance4x8_neon, 12),
+ VarianceParams(2, 2, &vpx_highbd_12_variance4x4_neon, 12),
+ VarianceParams(6, 6, &vpx_highbd_10_variance64x64_neon, 10),
+ VarianceParams(6, 5, &vpx_highbd_10_variance64x32_neon, 10),
+ VarianceParams(5, 6, &vpx_highbd_10_variance32x64_neon, 10),
+ VarianceParams(5, 5, &vpx_highbd_10_variance32x32_neon, 10),
+ VarianceParams(5, 4, &vpx_highbd_10_variance32x16_neon, 10),
+ VarianceParams(4, 5, &vpx_highbd_10_variance16x32_neon, 10),
+ VarianceParams(4, 4, &vpx_highbd_10_variance16x16_neon, 10),
+ VarianceParams(4, 3, &vpx_highbd_10_variance16x8_neon, 10),
+ VarianceParams(3, 4, &vpx_highbd_10_variance8x16_neon, 10),
+ VarianceParams(3, 3, &vpx_highbd_10_variance8x8_neon, 10),
+ VarianceParams(3, 2, &vpx_highbd_10_variance8x4_neon, 10),
+ VarianceParams(2, 3, &vpx_highbd_10_variance4x8_neon, 10),
+ VarianceParams(2, 2, &vpx_highbd_10_variance4x4_neon, 10),
+ VarianceParams(6, 6, &vpx_highbd_8_variance64x64_neon, 8),
+ VarianceParams(6, 5, &vpx_highbd_8_variance64x32_neon, 8),
+ VarianceParams(5, 6, &vpx_highbd_8_variance32x64_neon, 8),
+ VarianceParams(5, 5, &vpx_highbd_8_variance32x32_neon, 8),
+ VarianceParams(5, 4, &vpx_highbd_8_variance32x16_neon, 8),
+ VarianceParams(4, 5, &vpx_highbd_8_variance16x32_neon, 8),
+ VarianceParams(4, 4, &vpx_highbd_8_variance16x16_neon, 8),
+ VarianceParams(4, 3, &vpx_highbd_8_variance16x8_neon, 8),
+ VarianceParams(3, 4, &vpx_highbd_8_variance8x16_neon, 8),
+ VarianceParams(3, 3, &vpx_highbd_8_variance8x8_neon, 8),
+ VarianceParams(3, 2, &vpx_highbd_8_variance8x4_neon, 8),
+ VarianceParams(2, 3, &vpx_highbd_8_variance4x8_neon, 8),
+ VarianceParams(2, 2, &vpx_highbd_8_variance4x4_neon, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxHBDSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_highbd_12_sub_pixel_variance64x64_neon,
+ 12),
+ SubpelVarianceParams(6, 5, &vpx_highbd_12_sub_pixel_variance64x32_neon,
+ 12),
+ SubpelVarianceParams(5, 6, &vpx_highbd_12_sub_pixel_variance32x64_neon,
+ 12),
+ SubpelVarianceParams(5, 5, &vpx_highbd_12_sub_pixel_variance32x32_neon,
+ 12),
+ SubpelVarianceParams(5, 4, &vpx_highbd_12_sub_pixel_variance32x16_neon,
+ 12),
+ SubpelVarianceParams(4, 5, &vpx_highbd_12_sub_pixel_variance16x32_neon,
+ 12),
+ SubpelVarianceParams(4, 4, &vpx_highbd_12_sub_pixel_variance16x16_neon,
+ 12),
+ SubpelVarianceParams(4, 3, &vpx_highbd_12_sub_pixel_variance16x8_neon,
+ 12),
+ SubpelVarianceParams(3, 4, &vpx_highbd_12_sub_pixel_variance8x16_neon,
+ 12),
+ SubpelVarianceParams(3, 3, &vpx_highbd_12_sub_pixel_variance8x8_neon,
+ 12),
+ SubpelVarianceParams(3, 2, &vpx_highbd_12_sub_pixel_variance8x4_neon,
+ 12),
+ SubpelVarianceParams(2, 3, &vpx_highbd_12_sub_pixel_variance4x8_neon,
+ 12),
+ SubpelVarianceParams(2, 2, &vpx_highbd_12_sub_pixel_variance4x4_neon,
+ 12),
+ SubpelVarianceParams(6, 6, &vpx_highbd_10_sub_pixel_variance64x64_neon,
+ 10),
+ SubpelVarianceParams(6, 5, &vpx_highbd_10_sub_pixel_variance64x32_neon,
+ 10),
+ SubpelVarianceParams(5, 6, &vpx_highbd_10_sub_pixel_variance32x64_neon,
+ 10),
+ SubpelVarianceParams(5, 5, &vpx_highbd_10_sub_pixel_variance32x32_neon,
+ 10),
+ SubpelVarianceParams(5, 4, &vpx_highbd_10_sub_pixel_variance32x16_neon,
+ 10),
+ SubpelVarianceParams(4, 5, &vpx_highbd_10_sub_pixel_variance16x32_neon,
+ 10),
+ SubpelVarianceParams(4, 4, &vpx_highbd_10_sub_pixel_variance16x16_neon,
+ 10),
+ SubpelVarianceParams(4, 3, &vpx_highbd_10_sub_pixel_variance16x8_neon,
+ 10),
+ SubpelVarianceParams(3, 4, &vpx_highbd_10_sub_pixel_variance8x16_neon,
+ 10),
+ SubpelVarianceParams(3, 3, &vpx_highbd_10_sub_pixel_variance8x8_neon,
+ 10),
+ SubpelVarianceParams(3, 2, &vpx_highbd_10_sub_pixel_variance8x4_neon,
+ 10),
+ SubpelVarianceParams(2, 3, &vpx_highbd_10_sub_pixel_variance4x8_neon,
+ 10),
+ SubpelVarianceParams(2, 2, &vpx_highbd_10_sub_pixel_variance4x4_neon,
+ 10),
+ SubpelVarianceParams(6, 6, &vpx_highbd_8_sub_pixel_variance64x64_neon,
+ 8),
+ SubpelVarianceParams(6, 5, &vpx_highbd_8_sub_pixel_variance64x32_neon,
+ 8),
+ SubpelVarianceParams(5, 6, &vpx_highbd_8_sub_pixel_variance32x64_neon,
+ 8),
+ SubpelVarianceParams(5, 5, &vpx_highbd_8_sub_pixel_variance32x32_neon,
+ 8),
+ SubpelVarianceParams(5, 4, &vpx_highbd_8_sub_pixel_variance32x16_neon,
+ 8),
+ SubpelVarianceParams(4, 5, &vpx_highbd_8_sub_pixel_variance16x32_neon,
+ 8),
+ SubpelVarianceParams(4, 4, &vpx_highbd_8_sub_pixel_variance16x16_neon,
+ 8),
+ SubpelVarianceParams(4, 3, &vpx_highbd_8_sub_pixel_variance16x8_neon,
+ 8),
+ SubpelVarianceParams(3, 4, &vpx_highbd_8_sub_pixel_variance8x16_neon,
+ 8),
+ SubpelVarianceParams(3, 3, &vpx_highbd_8_sub_pixel_variance8x8_neon, 8),
+ SubpelVarianceParams(3, 2, &vpx_highbd_8_sub_pixel_variance8x4_neon, 8),
+ SubpelVarianceParams(2, 3, &vpx_highbd_8_sub_pixel_variance4x8_neon, 8),
+ SubpelVarianceParams(2, 2, &vpx_highbd_8_sub_pixel_variance4x4_neon,
+ 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VpxHBDSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_12_sub_pixel_avg_variance64x64_neon,
+ 12),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance64x32_neon,
+ 12),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_12_sub_pixel_avg_variance32x64_neon,
+ 12),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance32x32_neon,
+ 12),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance32x16_neon,
+ 12),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_12_sub_pixel_avg_variance16x32_neon,
+ 12),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance16x16_neon,
+ 12),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance16x8_neon,
+ 12),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_12_sub_pixel_avg_variance8x16_neon,
+ 12),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance8x8_neon,
+ 12),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_12_sub_pixel_avg_variance8x4_neon,
+ 12),
+ SubpelAvgVarianceParams(2, 3,
+ &vpx_highbd_12_sub_pixel_avg_variance4x8_neon,
+ 12),
+ SubpelAvgVarianceParams(2, 2,
+ &vpx_highbd_12_sub_pixel_avg_variance4x4_neon,
+ 12),
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_10_sub_pixel_avg_variance64x64_neon,
+ 10),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance64x32_neon,
+ 10),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_10_sub_pixel_avg_variance32x64_neon,
+ 10),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance32x32_neon,
+ 10),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance32x16_neon,
+ 10),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_10_sub_pixel_avg_variance16x32_neon,
+ 10),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance16x16_neon,
+ 10),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance16x8_neon,
+ 10),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_10_sub_pixel_avg_variance8x16_neon,
+ 10),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance8x8_neon,
+ 10),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_10_sub_pixel_avg_variance8x4_neon,
+ 10),
+ SubpelAvgVarianceParams(2, 3,
+ &vpx_highbd_10_sub_pixel_avg_variance4x8_neon,
+ 10),
+ SubpelAvgVarianceParams(2, 2,
+ &vpx_highbd_10_sub_pixel_avg_variance4x4_neon,
+ 10),
+ SubpelAvgVarianceParams(6, 6,
+ &vpx_highbd_8_sub_pixel_avg_variance64x64_neon,
+ 8),
+ SubpelAvgVarianceParams(6, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance64x32_neon,
+ 8),
+ SubpelAvgVarianceParams(5, 6,
+ &vpx_highbd_8_sub_pixel_avg_variance32x64_neon,
+ 8),
+ SubpelAvgVarianceParams(5, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance32x32_neon,
+ 8),
+ SubpelAvgVarianceParams(5, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance32x16_neon,
+ 8),
+ SubpelAvgVarianceParams(4, 5,
+ &vpx_highbd_8_sub_pixel_avg_variance16x32_neon,
+ 8),
+ SubpelAvgVarianceParams(4, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance16x16_neon,
+ 8),
+ SubpelAvgVarianceParams(4, 3,
+ &vpx_highbd_8_sub_pixel_avg_variance16x8_neon,
+ 8),
+ SubpelAvgVarianceParams(3, 4,
+ &vpx_highbd_8_sub_pixel_avg_variance8x16_neon,
+ 8),
+ SubpelAvgVarianceParams(3, 3,
+ &vpx_highbd_8_sub_pixel_avg_variance8x8_neon,
+ 8),
+ SubpelAvgVarianceParams(3, 2,
+ &vpx_highbd_8_sub_pixel_avg_variance8x4_neon,
+ 8),
+ SubpelAvgVarianceParams(2, 3,
+ &vpx_highbd_8_sub_pixel_avg_variance4x8_neon,
+ 8),
+ SubpelAvgVarianceParams(2, 2,
+ &vpx_highbd_8_sub_pixel_avg_variance4x4_neon,
+ 8)));
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_NEON
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(MSA, SumOfSquaresTest,
+ ::testing::Values(vpx_get_mb_ss_msa));
+
+INSTANTIATE_TEST_SUITE_P(MSA, VpxSseTest,
+ ::testing::Values(SseParams(2, 2,
+ &vpx_get4x4sse_cs_msa)));
+
+INSTANTIATE_TEST_SUITE_P(MSA, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_msa),
+ MseParams(4, 3, &vpx_mse16x8_msa),
+ MseParams(3, 4, &vpx_mse8x16_msa),
+ MseParams(3, 3, &vpx_mse8x8_msa)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_msa),
+ VarianceParams(6, 5, &vpx_variance64x32_msa),
+ VarianceParams(5, 6, &vpx_variance32x64_msa),
+ VarianceParams(5, 5, &vpx_variance32x32_msa),
+ VarianceParams(5, 4, &vpx_variance32x16_msa),
+ VarianceParams(4, 5, &vpx_variance16x32_msa),
+ VarianceParams(4, 4, &vpx_variance16x16_msa),
+ VarianceParams(4, 3, &vpx_variance16x8_msa),
+ VarianceParams(3, 4, &vpx_variance8x16_msa),
+ VarianceParams(3, 3, &vpx_variance8x8_msa),
+ VarianceParams(3, 2, &vpx_variance8x4_msa),
+ VarianceParams(2, 3, &vpx_variance4x8_msa),
+ VarianceParams(2, 2, &vpx_variance4x4_msa)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(2, 2, &vpx_sub_pixel_variance4x4_msa, 0),
+ SubpelVarianceParams(2, 3, &vpx_sub_pixel_variance4x8_msa, 0),
+ SubpelVarianceParams(3, 2, &vpx_sub_pixel_variance8x4_msa, 0),
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_msa, 0),
+ SubpelVarianceParams(3, 4, &vpx_sub_pixel_variance8x16_msa, 0),
+ SubpelVarianceParams(4, 3, &vpx_sub_pixel_variance16x8_msa, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_msa, 0),
+ SubpelVarianceParams(4, 5, &vpx_sub_pixel_variance16x32_msa, 0),
+ SubpelVarianceParams(5, 4, &vpx_sub_pixel_variance32x16_msa, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_msa, 0),
+ SubpelVarianceParams(5, 6, &vpx_sub_pixel_variance32x64_msa, 0),
+ SubpelVarianceParams(6, 5, &vpx_sub_pixel_variance64x32_msa, 0),
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_msa, 0)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MSA, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_msa, 0),
+ SubpelAvgVarianceParams(6, 5, &vpx_sub_pixel_avg_variance64x32_msa, 0),
+ SubpelAvgVarianceParams(5, 6, &vpx_sub_pixel_avg_variance32x64_msa, 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_msa, 0),
+ SubpelAvgVarianceParams(5, 4, &vpx_sub_pixel_avg_variance32x16_msa, 0),
+ SubpelAvgVarianceParams(4, 5, &vpx_sub_pixel_avg_variance16x32_msa, 0),
+ SubpelAvgVarianceParams(4, 4, &vpx_sub_pixel_avg_variance16x16_msa, 0),
+ SubpelAvgVarianceParams(4, 3, &vpx_sub_pixel_avg_variance16x8_msa, 0),
+ SubpelAvgVarianceParams(3, 4, &vpx_sub_pixel_avg_variance8x16_msa, 0),
+ SubpelAvgVarianceParams(3, 3, &vpx_sub_pixel_avg_variance8x8_msa, 0),
+ SubpelAvgVarianceParams(3, 2, &vpx_sub_pixel_avg_variance8x4_msa, 0),
+ SubpelAvgVarianceParams(2, 3, &vpx_sub_pixel_avg_variance4x8_msa, 0),
+ SubpelAvgVarianceParams(2, 2, &vpx_sub_pixel_avg_variance4x4_msa, 0)));
+#endif // HAVE_MSA
+
+#if HAVE_VSX
+INSTANTIATE_TEST_SUITE_P(VSX, SumOfSquaresTest,
+ ::testing::Values(vpx_get_mb_ss_vsx));
+
+INSTANTIATE_TEST_SUITE_P(VSX, VpxSseTest,
+ ::testing::Values(SseParams(2, 2,
+ &vpx_get4x4sse_cs_vsx)));
+INSTANTIATE_TEST_SUITE_P(VSX, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_vsx),
+ MseParams(4, 3, &vpx_mse16x8_vsx),
+ MseParams(3, 4, &vpx_mse8x16_vsx),
+ MseParams(3, 3, &vpx_mse8x8_vsx)));
+
+INSTANTIATE_TEST_SUITE_P(
+ VSX, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_vsx),
+ VarianceParams(6, 5, &vpx_variance64x32_vsx),
+ VarianceParams(5, 6, &vpx_variance32x64_vsx),
+ VarianceParams(5, 5, &vpx_variance32x32_vsx),
+ VarianceParams(5, 4, &vpx_variance32x16_vsx),
+ VarianceParams(4, 5, &vpx_variance16x32_vsx),
+ VarianceParams(4, 4, &vpx_variance16x16_vsx),
+ VarianceParams(4, 3, &vpx_variance16x8_vsx),
+ VarianceParams(3, 4, &vpx_variance8x16_vsx),
+ VarianceParams(3, 3, &vpx_variance8x8_vsx),
+ VarianceParams(3, 2, &vpx_variance8x4_vsx),
+ VarianceParams(2, 3, &vpx_variance4x8_vsx),
+ VarianceParams(2, 2, &vpx_variance4x4_vsx)));
+#endif // HAVE_VSX
+
+#if HAVE_MMI
+INSTANTIATE_TEST_SUITE_P(MMI, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_mmi),
+ MseParams(4, 3, &vpx_mse16x8_mmi),
+ MseParams(3, 4, &vpx_mse8x16_mmi),
+ MseParams(3, 3, &vpx_mse8x8_mmi)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MMI, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_mmi),
+ VarianceParams(6, 5, &vpx_variance64x32_mmi),
+ VarianceParams(5, 6, &vpx_variance32x64_mmi),
+ VarianceParams(5, 5, &vpx_variance32x32_mmi),
+ VarianceParams(5, 4, &vpx_variance32x16_mmi),
+ VarianceParams(4, 5, &vpx_variance16x32_mmi),
+ VarianceParams(4, 4, &vpx_variance16x16_mmi),
+ VarianceParams(4, 3, &vpx_variance16x8_mmi),
+ VarianceParams(3, 4, &vpx_variance8x16_mmi),
+ VarianceParams(3, 3, &vpx_variance8x8_mmi),
+ VarianceParams(3, 2, &vpx_variance8x4_mmi),
+ VarianceParams(2, 3, &vpx_variance4x8_mmi),
+ VarianceParams(2, 2, &vpx_variance4x4_mmi)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MMI, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(6, 6, &vpx_sub_pixel_variance64x64_mmi, 0),
+ SubpelVarianceParams(6, 5, &vpx_sub_pixel_variance64x32_mmi, 0),
+ SubpelVarianceParams(5, 6, &vpx_sub_pixel_variance32x64_mmi, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_mmi, 0),
+ SubpelVarianceParams(5, 4, &vpx_sub_pixel_variance32x16_mmi, 0),
+ SubpelVarianceParams(4, 5, &vpx_sub_pixel_variance16x32_mmi, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_mmi, 0),
+ SubpelVarianceParams(4, 3, &vpx_sub_pixel_variance16x8_mmi, 0),
+ SubpelVarianceParams(3, 4, &vpx_sub_pixel_variance8x16_mmi, 0),
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_mmi, 0),
+ SubpelVarianceParams(3, 2, &vpx_sub_pixel_variance8x4_mmi, 0),
+ SubpelVarianceParams(2, 3, &vpx_sub_pixel_variance4x8_mmi, 0),
+ SubpelVarianceParams(2, 2, &vpx_sub_pixel_variance4x4_mmi, 0)));
+
+INSTANTIATE_TEST_SUITE_P(
+ MMI, VpxSubpelAvgVarianceTest,
+ ::testing::Values(
+ SubpelAvgVarianceParams(6, 6, &vpx_sub_pixel_avg_variance64x64_mmi, 0),
+ SubpelAvgVarianceParams(6, 5, &vpx_sub_pixel_avg_variance64x32_mmi, 0),
+ SubpelAvgVarianceParams(5, 6, &vpx_sub_pixel_avg_variance32x64_mmi, 0),
+ SubpelAvgVarianceParams(5, 5, &vpx_sub_pixel_avg_variance32x32_mmi, 0),
+ SubpelAvgVarianceParams(5, 4, &vpx_sub_pixel_avg_variance32x16_mmi, 0),
+ SubpelAvgVarianceParams(4, 5, &vpx_sub_pixel_avg_variance16x32_mmi, 0),
+ SubpelAvgVarianceParams(4, 4, &vpx_sub_pixel_avg_variance16x16_mmi, 0),
+ SubpelAvgVarianceParams(4, 3, &vpx_sub_pixel_avg_variance16x8_mmi, 0),
+ SubpelAvgVarianceParams(3, 4, &vpx_sub_pixel_avg_variance8x16_mmi, 0),
+ SubpelAvgVarianceParams(3, 3, &vpx_sub_pixel_avg_variance8x8_mmi, 0),
+ SubpelAvgVarianceParams(3, 2, &vpx_sub_pixel_avg_variance8x4_mmi, 0),
+ SubpelAvgVarianceParams(2, 3, &vpx_sub_pixel_avg_variance4x8_mmi, 0),
+ SubpelAvgVarianceParams(2, 2, &vpx_sub_pixel_avg_variance4x4_mmi, 0)));
+#endif // HAVE_MMI
+
+#if HAVE_LSX
+INSTANTIATE_TEST_SUITE_P(LSX, VpxMseTest,
+ ::testing::Values(MseParams(4, 4, &vpx_mse16x16_lsx)));
+
+INSTANTIATE_TEST_SUITE_P(
+ LSX, VpxVarianceTest,
+ ::testing::Values(VarianceParams(6, 6, &vpx_variance64x64_lsx),
+ VarianceParams(5, 5, &vpx_variance32x32_lsx),
+ VarianceParams(4, 4, &vpx_variance16x16_lsx),
+ VarianceParams(3, 3, &vpx_variance8x8_lsx)));
+
+INSTANTIATE_TEST_SUITE_P(
+ LSX, VpxSubpelVarianceTest,
+ ::testing::Values(
+ SubpelVarianceParams(3, 3, &vpx_sub_pixel_variance8x8_lsx, 0),
+ SubpelVarianceParams(4, 4, &vpx_sub_pixel_variance16x16_lsx, 0),
+ SubpelVarianceParams(5, 5, &vpx_sub_pixel_variance32x32_lsx, 0)));
+
+INSTANTIATE_TEST_SUITE_P(LSX, VpxSubpelAvgVarianceTest,
+ ::testing::Values(SubpelAvgVarianceParams(
+ 6, 6, &vpx_sub_pixel_avg_variance64x64_lsx, 0)));
+#endif
+} // namespace
diff --git a/media/libvpx/libvpx/test/video_source.h b/media/libvpx/libvpx/test/video_source.h
new file mode 100644
index 0000000000..a10ff6fb09
--- /dev/null
+++ b/media/libvpx/libvpx/test/video_source.h
@@ -0,0 +1,283 @@
+/*
+ * 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 VPX_TEST_VIDEO_SOURCE_H_
+#define VPX_TEST_VIDEO_SOURCE_H_
+
+#if defined(_WIN32)
+#undef NOMINMAX
+#define NOMINMAX
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#endif
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <string>
+
+#include "test/acm_random.h"
+#if !defined(_WIN32)
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#endif
+#include "vpx/vpx_encoder.h"
+
+namespace libvpx_test {
+
+// Helper macros to ensure LIBVPX_TEST_DATA_PATH is a quoted string.
+// These are undefined right below GetDataPath
+// NOTE: LIBVPX_TEST_DATA_PATH MUST NOT be a quoted string before
+// Stringification or the GetDataPath will fail at runtime
+#define TO_STRING(S) #S
+#define STRINGIFY(S) TO_STRING(S)
+
+// A simple function to encapsulate cross platform retrieval of test data path
+static std::string GetDataPath() {
+ const char *const data_path = getenv("LIBVPX_TEST_DATA_PATH");
+ if (data_path == nullptr) {
+#ifdef LIBVPX_TEST_DATA_PATH
+ // In some environments, we cannot set environment variables
+ // Instead, we set the data path by using a preprocessor symbol
+ // which can be set from make files
+ return STRINGIFY(LIBVPX_TEST_DATA_PATH);
+#else
+ return ".";
+#endif
+ }
+ return data_path;
+}
+
+// Undefining stringification macros because they are not used elsewhere
+#undef TO_STRING
+#undef STRINGIFY
+
+inline FILE *OpenTestDataFile(const std::string &file_name) {
+ const std::string path_to_source = GetDataPath() + "/" + file_name;
+ return fopen(path_to_source.c_str(), "rb");
+}
+
+static FILE *GetTempOutFile(std::string *file_name) {
+ file_name->clear();
+#if defined(_WIN32)
+ char fname[MAX_PATH];
+ char tmppath[MAX_PATH];
+ if (GetTempPathA(MAX_PATH, tmppath)) {
+ // Assume for now that the filename generated is unique per process
+ if (GetTempFileNameA(tmppath, "lvx", 0, fname)) {
+ file_name->assign(fname);
+ return fopen(fname, "wb+");
+ }
+ }
+ return nullptr;
+#else
+ std::string temp_dir = testing::TempDir();
+ if (temp_dir.empty()) return nullptr;
+ // Versions of testing::TempDir() prior to release-1.11.0-214-g5e6a5336 may
+ // use the value of an environment variable without checking for a trailing
+ // path delimiter.
+ if (temp_dir[temp_dir.size() - 1] != '/') temp_dir += '/';
+ const char name_template[] = "libvpxtest.XXXXXX";
+ std::unique_ptr<char[]> temp_file_name(
+ new char[temp_dir.size() + sizeof(name_template)]);
+ if (temp_file_name == nullptr) return nullptr;
+ memcpy(temp_file_name.get(), temp_dir.data(), temp_dir.size());
+ memcpy(temp_file_name.get() + temp_dir.size(), name_template,
+ sizeof(name_template));
+ const int fd = mkstemp(temp_file_name.get());
+ if (fd == -1) return nullptr;
+ *file_name = temp_file_name.get();
+ return fdopen(fd, "wb+");
+#endif
+}
+
+class TempOutFile {
+ public:
+ TempOutFile() { file_ = GetTempOutFile(&file_name_); }
+ ~TempOutFile() {
+ CloseFile();
+ if (!file_name_.empty()) {
+ EXPECT_EQ(0, remove(file_name_.c_str()));
+ }
+ }
+ FILE *file() { return file_; }
+ const std::string &file_name() { return file_name_; }
+
+ protected:
+ void CloseFile() {
+ if (file_) {
+ fclose(file_);
+ file_ = nullptr;
+ }
+ }
+ FILE *file_;
+ std::string file_name_;
+};
+
+// 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 nullptr 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;
+
+ // Get the current file limit.
+ virtual unsigned int limit() const = 0;
+};
+
+class DummyVideoSource : public VideoSource {
+ public:
+ DummyVideoSource()
+ : img_(nullptr), limit_(100), width_(80), height_(64),
+ format_(VPX_IMG_FMT_I420) {
+ ReallocImage();
+ }
+
+ 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_ : nullptr;
+ }
+
+ // 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_; }
+
+ virtual unsigned int limit() const { return limit_; }
+
+ void set_limit(unsigned int limit) { limit_ = limit; }
+
+ void SetSize(unsigned int width, unsigned int height) {
+ if (width != width_ || height != height_) {
+ width_ = width;
+ height_ = height;
+ ReallocImage();
+ }
+ }
+
+ void SetImageFormat(vpx_img_fmt_t format) {
+ if (format_ != format) {
+ format_ = format;
+ ReallocImage();
+ }
+ }
+
+ protected:
+ virtual void FillFrame() {
+ if (img_) memset(img_->img_data, 0, raw_sz_);
+ }
+
+ void ReallocImage() {
+ vpx_img_free(img_);
+ img_ = vpx_img_alloc(nullptr, format_, width_, height_, 32);
+ ASSERT_NE(img_, nullptr);
+ raw_sz_ = ((img_->w + 31) & ~31u) * img_->h * img_->bps / 8;
+ }
+
+ vpx_image_t *img_;
+ size_t raw_sz_;
+ unsigned int limit_;
+ unsigned int frame_;
+ unsigned int width_;
+ unsigned int height_;
+ vpx_img_fmt_t format_;
+};
+
+class RandomVideoSource : public DummyVideoSource {
+ public:
+ RandomVideoSource(int seed = ACMRandom::DeterministicSeed())
+ : rnd_(seed), seed_(seed) {}
+
+ protected:
+ // Reset the RNG to get a matching stream for the second pass
+ virtual void Begin() {
+ frame_ = 0;
+ rnd_.Reset(seed_);
+ FillFrame();
+ }
+
+ // 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 (img_) {
+ if (frame_ % 30 < 15) {
+ for (size_t i = 0; i < raw_sz_; ++i) img_->img_data[i] = rnd_.Rand8();
+ } else {
+ memset(img_->img_data, 0, raw_sz_);
+ }
+ }
+ }
+
+ ACMRandom rnd_;
+ int seed_;
+};
+
+// Abstract base class for test video sources, which provide a stream of
+// decompressed images to the decoder.
+class CompressedVideoSource {
+ public:
+ virtual ~CompressedVideoSource() {}
+
+ virtual void Init() = 0;
+
+ // Prepare the stream for reading, rewind/open as necessary.
+ virtual void Begin() = 0;
+
+ // Advance the cursor to the next frame
+ virtual void Next() = 0;
+
+ virtual const uint8_t *cxdata() const = 0;
+
+ virtual size_t frame_size() const = 0;
+
+ virtual unsigned int frame_number() const = 0;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_VIDEO_SOURCE_H_
diff --git a/media/libvpx/libvpx/test/vp8_boolcoder_test.cc b/media/libvpx/libvpx/test/vp8_boolcoder_test.cc
new file mode 100644
index 0000000000..c78b0b3b6c
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_boolcoder_test.cc
@@ -0,0 +1,118 @@
+/*
+ * 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 <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/acm_random.h"
+#include "vp8/decoder/dboolhuff.h"
+#include "vp8/encoder/boolhuff.h"
+#include "vpx/vpx_integer.h"
+
+namespace {
+const int num_tests = 10;
+
+// In a real use the 'decrypt_state' parameter will be a pointer to a struct
+// with whatever internal state the decryptor uses. For testing we'll just
+// xor with a constant key, and decrypt_state will point to the start of
+// the original buffer.
+const uint8_t secret_key[16] = {
+ 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+ 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
+};
+
+void encrypt_buffer(uint8_t *buffer, size_t size) {
+ for (size_t i = 0; i < size; ++i) {
+ buffer[i] ^= secret_key[i & 15];
+ }
+}
+
+void test_decrypt_cb(void *decrypt_state, const uint8_t *input, uint8_t *output,
+ int count) {
+ const size_t offset = input - reinterpret_cast<uint8_t *>(decrypt_state);
+ for (int i = 0; i < count; i++) {
+ output[i] = input[i] ^ secret_key[(offset + i) & 15];
+ }
+}
+
+} // namespace
+
+using libvpx_test::ACMRandom;
+
+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 kBitsToTest = 1000;
+ uint8_t probas[kBitsToTest];
+
+ for (int i = 0; i < kBitsToTest; ++i) {
+ const int parity = i & 1;
+ /* clang-format off */
+ 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));
+ /* clang-format on */
+ }
+ for (int bit_method = 0; bit_method <= 3; ++bit_method) {
+ const int random_seed = 6432;
+ const int kBufferSize = 10000;
+ ACMRandom bit_rnd(random_seed);
+ BOOL_CODER bw;
+ uint8_t bw_buffer[kBufferSize];
+ vp8_start_encode(&bw, bw_buffer, bw_buffer + kBufferSize);
+
+ int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
+ for (int i = 0; i < kBitsToTest; ++i) {
+ if (bit_method == 2) {
+ bit = (i & 1);
+ } else if (bit_method == 3) {
+ bit = bit_rnd(2);
+ }
+ vp8_encode_bool(&bw, bit, static_cast<int>(probas[i]));
+ }
+
+ vp8_stop_encode(&bw);
+ // vp8dx_bool_decoder_fill() may read into uninitialized data that
+ // isn't used meaningfully, but may trigger an MSan warning.
+ memset(bw_buffer + bw.pos, 0, sizeof(VP8_BD_VALUE) - 1);
+
+ BOOL_DECODER br;
+ encrypt_buffer(bw_buffer, kBufferSize);
+ vp8dx_start_decode(&br, bw_buffer, kBufferSize, test_decrypt_cb,
+ reinterpret_cast<void *>(bw_buffer));
+ bit_rnd.Reset(random_seed);
+ for (int i = 0; i < kBitsToTest; ++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 << " / " << kBitsToTest
+ << " bit_method: " << bit_method << " method: " << method;
+ }
+ }
+ }
+ }
+}
diff --git a/media/libvpx/libvpx/test/vp8_datarate_test.cc b/media/libvpx/libvpx/test/vp8_datarate_test.cc
new file mode 100644
index 0000000000..64a861d15e
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_datarate_test.cc
@@ -0,0 +1,438 @@
+/*
+ * 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 "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vpx/vpx_codec.h"
+
+namespace {
+
+class DatarateTestLarge
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ public:
+ DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
+
+ virtual ~DatarateTestLarge() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(GET_PARAM(1));
+ set_cpu_used_ = GET_PARAM(2);
+ ResetModel();
+ }
+
+ virtual void ResetModel() {
+ last_pts_ = 0;
+ bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
+ frame_number_ = 0;
+ first_drop_ = 0;
+ bits_total_ = 0;
+ duration_ = 0.0;
+ denoiser_offon_test_ = 0;
+ denoiser_offon_period_ = -1;
+ gf_boost_ = 0;
+ use_roi_ = false;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ encoder->Control(VP8E_SET_GF_CBR_BOOST_PCT, gf_boost_);
+ }
+
+ if (use_roi_) {
+ encoder->Control(VP8E_SET_ROI_MAP, &roi_);
+ }
+
+ if (denoiser_offon_test_) {
+ ASSERT_GT(denoiser_offon_period_, 0)
+ << "denoiser_offon_period_ is not positive.";
+ if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
+ // Flip denoiser_on_ periodically
+ denoiser_on_ ^= 1;
+ }
+ encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
+ }
+
+ const vpx_rational_t tb = video->timebase();
+ timebase_ = static_cast<double>(tb.num) / tb.den;
+ duration_ = 0;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ // Time since last timestamp = duration.
+ vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+
+ // TODO(jimbankoski): Remove these lines when the issue:
+ // http://code.google.com/p/webm/issues/detail?id=496 is fixed.
+ // For now the codec assumes buffer starts at starting buffer rate
+ // plus one frame's time.
+ if (last_pts_ == 0) duration = 1;
+
+ // Add to the buffer the bits we'd expect from a constant bitrate server.
+ bits_in_buffer_model_ += static_cast<int64_t>(
+ duration * timebase_ * cfg_.rc_target_bitrate * 1000);
+
+ /* Test the buffer model here before subtracting the frame. Do so because
+ * the way the leaky bucket model works in libvpx is to allow the buffer to
+ * empty - and then stop showing frames until we've got enough bits to
+ * show one. As noted in comment below (issue 495), this does not currently
+ * apply to key frames. For now exclude key frames in condition below. */
+ const bool key_frame =
+ (pkt->data.frame.flags & VPX_FRAME_IS_KEY) ? true : false;
+ if (!key_frame) {
+ ASSERT_GE(bits_in_buffer_model_, 0)
+ << "Buffer Underrun at frame " << pkt->data.frame.pts;
+ }
+
+ const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
+
+ // Subtract from the buffer the bits associated with a played back frame.
+ bits_in_buffer_model_ -= frame_size_in_bits;
+
+ // Update the running total of bits for end of test datarate checks.
+ bits_total_ += frame_size_in_bits;
+
+ // If first drop not set and we have a drop set it to this time.
+ if (!first_drop_ && duration > 1) first_drop_ = last_pts_ + 1;
+
+ // Update the most recent pts.
+ last_pts_ = pkt->data.frame.pts;
+
+ // We update this so that we can calculate the datarate minus the last
+ // frame encoded in the file.
+ bits_in_last_frame_ = frame_size_in_bits;
+
+ ++frame_number_;
+ }
+
+ virtual void EndPassHook() {
+ if (bits_total_) {
+ const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit
+
+ duration_ = (last_pts_ + 1) * timebase_;
+
+ // Effective file datarate includes the time spent prebuffering.
+ effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0 /
+ (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
+
+ file_datarate_ = file_size_in_kb / duration_;
+ }
+ }
+
+ virtual void DenoiserLevelsTest() {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+ 288, 30, 1, 0, 140);
+ for (int j = 1; j < 5; ++j) {
+ // Run over the denoiser levels.
+ // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
+ // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
+ // denoiserOnAggressive, and denoiserOnAdaptive.
+ denoiser_on_ = j;
+ cfg_.rc_target_bitrate = 300;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+ }
+ }
+
+ virtual void DenoiserOffOnTest() {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+ 288, 30, 1, 0, 299);
+ cfg_.rc_target_bitrate = 300;
+ ResetModel();
+ // The denoiser is off by default.
+ denoiser_on_ = 0;
+ // Set the offon test flag.
+ denoiser_offon_test_ = 1;
+ denoiser_offon_period_ = 100;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+ }
+
+ virtual void BasicBufferModelTest() {
+ denoiser_on_ = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ // 2 pass cbr datarate control has a bug hidden by the small # of
+ // frames selected in this encode. The problem is that even if the buffer is
+ // negative we produce a keyframe on a cutscene. Ignoring datarate
+ // constraints
+ // TODO(jimbankoski): ( Fix when issue
+ // http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+ 288, 30, 1, 0, 140);
+
+ // There is an issue for low bitrates in real-time mode, where the
+ // effective_datarate slightly overshoots the target bitrate.
+ // This is same the issue as noted about (#495).
+ // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
+ // when the issue is resolved.
+ for (int i = 100; i < 800; i += 200) {
+ cfg_.rc_target_bitrate = i;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+ }
+ }
+
+ virtual void ChangingDropFrameThreshTest() {
+ denoiser_on_ = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_max_quantizer = 36;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_target_bitrate = 200;
+ cfg_.kf_mode = VPX_KF_DISABLED;
+
+ const int frame_count = 40;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+ 288, 30, 1, 0, frame_count);
+
+ // Here we check that the first dropped frame gets earlier and earlier
+ // as the drop frame threshold is increased.
+
+ const int kDropFrameThreshTestStep = 30;
+ vpx_codec_pts_t last_drop = frame_count;
+ for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
+ cfg_.rc_dropframe_thresh = i;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_LE(first_drop_, last_drop)
+ << " The first dropped frame for drop_thresh " << i
+ << " > first dropped frame for drop_thresh "
+ << i - kDropFrameThreshTestStep;
+ last_drop = first_drop_;
+ }
+ }
+
+ virtual void DropFramesMultiThreadsTest() {
+ denoiser_on_ = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_threads = 2;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352,
+ 288, 30, 1, 0, 140);
+ cfg_.rc_target_bitrate = 200;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+ }
+
+ vpx_codec_pts_t last_pts_;
+ int64_t bits_in_buffer_model_;
+ double timebase_;
+ int frame_number_;
+ vpx_codec_pts_t first_drop_;
+ int64_t bits_total_;
+ double duration_;
+ double file_datarate_;
+ double effective_datarate_;
+ int64_t bits_in_last_frame_;
+ int denoiser_on_;
+ int denoiser_offon_test_;
+ int denoiser_offon_period_;
+ int set_cpu_used_;
+ int gf_boost_;
+ bool use_roi_;
+ vpx_roi_map_t roi_;
+};
+
+#if CONFIG_TEMPORAL_DENOISING
+// Check basic datarate targeting, for a single bitrate, but loop over the
+// various denoiser settings.
+TEST_P(DatarateTestLarge, DenoiserLevels) { DenoiserLevelsTest(); }
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is off
+// and on.
+TEST_P(DatarateTestLarge, DenoiserOffOn) { DenoiserOffOnTest(); }
+#endif // CONFIG_TEMPORAL_DENOISING
+
+TEST_P(DatarateTestLarge, BasicBufferModel) { BasicBufferModelTest(); }
+
+TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
+ ChangingDropFrameThreshTest();
+}
+
+TEST_P(DatarateTestLarge, DropFramesMultiThreads) {
+ DropFramesMultiThreadsTest();
+}
+
+class DatarateTestRealTime : public DatarateTestLarge {
+ public:
+ virtual ~DatarateTestRealTime() {}
+};
+
+#if CONFIG_TEMPORAL_DENOISING
+// Check basic datarate targeting, for a single bitrate, but loop over the
+// various denoiser settings.
+TEST_P(DatarateTestRealTime, DenoiserLevels) { DenoiserLevelsTest(); }
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is off
+// and on.
+TEST_P(DatarateTestRealTime, DenoiserOffOn) {}
+#endif // CONFIG_TEMPORAL_DENOISING
+
+TEST_P(DatarateTestRealTime, BasicBufferModel) { BasicBufferModelTest(); }
+
+TEST_P(DatarateTestRealTime, ChangingDropFrameThresh) {
+ ChangingDropFrameThreshTest();
+}
+
+TEST_P(DatarateTestRealTime, DropFramesMultiThreads) {
+ DropFramesMultiThreadsTest();
+}
+
+TEST_P(DatarateTestRealTime, RegionOfInterest) {
+ denoiser_on_ = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ // Encode using multiple threads.
+ cfg_.g_threads = 2;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+ cfg_.rc_target_bitrate = 450;
+ cfg_.g_w = 352;
+ cfg_.g_h = 288;
+
+ ResetModel();
+
+ // Set ROI parameters
+ use_roi_ = true;
+ memset(&roi_, 0, sizeof(roi_));
+
+ roi_.rows = (cfg_.g_h + 15) / 16;
+ roi_.cols = (cfg_.g_w + 15) / 16;
+
+ roi_.delta_q[0] = 0;
+ roi_.delta_q[1] = -20;
+ roi_.delta_q[2] = 0;
+ roi_.delta_q[3] = 0;
+
+ roi_.delta_lf[0] = 0;
+ roi_.delta_lf[1] = -20;
+ roi_.delta_lf[2] = 0;
+ roi_.delta_lf[3] = 0;
+
+ roi_.static_threshold[0] = 0;
+ roi_.static_threshold[1] = 1000;
+ roi_.static_threshold[2] = 0;
+ roi_.static_threshold[3] = 0;
+
+ // Use 2 states: 1 is center square, 0 is the rest.
+ roi_.roi_map =
+ (uint8_t *)calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map));
+ for (unsigned int i = 0; i < roi_.rows; ++i) {
+ for (unsigned int j = 0; j < roi_.cols; ++j) {
+ if (i > (roi_.rows >> 2) && i < ((roi_.rows * 3) >> 2) &&
+ j > (roi_.cols >> 2) && j < ((roi_.cols * 3) >> 2)) {
+ roi_.roi_map[i * roi_.cols + j] = 1;
+ }
+ }
+ }
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+
+ free(roi_.roi_map);
+}
+
+TEST_P(DatarateTestRealTime, GFBoost) {
+ denoiser_on_ = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_error_resilient = 0;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+ cfg_.rc_target_bitrate = 300;
+ ResetModel();
+ // Apply a gf boost.
+ gf_boost_ = 50;
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+}
+
+TEST_P(DatarateTestRealTime, NV12) {
+ denoiser_on_ = 0;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_error_resilient = 0;
+ ::libvpx_test::YUVVideoSource video("hantro_collage_w352h288_nv12.yuv",
+ VPX_IMG_FMT_NV12, 352, 288, 30, 1, 0,
+ 100);
+
+ cfg_.rc_target_bitrate = 200;
+ ResetModel();
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.4)
+ << " The datarate for the file missed the target!";
+}
+
+VP8_INSTANTIATE_TEST_SUITE(DatarateTestLarge, ALL_TEST_MODES,
+ ::testing::Values(0));
+VP8_INSTANTIATE_TEST_SUITE(DatarateTestRealTime,
+ ::testing::Values(::libvpx_test::kRealTime),
+ ::testing::Values(-6, -12));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp8_decrypt_test.cc b/media/libvpx/libvpx/test/vp8_decrypt_test.cc
new file mode 100644
index 0000000000..bcac9d1a82
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_decrypt_test.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/ivf_video_source.h"
+
+namespace {
+// In a real use the 'decrypt_state' parameter will be a pointer to a struct
+// with whatever internal state the decryptor uses. For testing we'll just
+// xor with a constant key, and decrypt_state will point to the start of
+// the original buffer.
+const uint8_t test_key[16] = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+ 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0 };
+
+void encrypt_buffer(const uint8_t *src, uint8_t *dst, size_t size,
+ ptrdiff_t offset) {
+ for (size_t i = 0; i < size; ++i) {
+ dst[i] = src[i] ^ test_key[(offset + i) & 15];
+ }
+}
+
+void test_decrypt_cb(void *decrypt_state, const uint8_t *input, uint8_t *output,
+ int count) {
+ encrypt_buffer(input, output, count,
+ input - reinterpret_cast<uint8_t *>(decrypt_state));
+}
+
+} // namespace
+
+namespace libvpx_test {
+
+TEST(TestDecrypt, DecryptWorksVp8) {
+ libvpx_test::IVFVideoSource video("vp80-00-comprehensive-001.ivf");
+ video.Init();
+
+ vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+ VP8Decoder decoder(dec_cfg, 0);
+
+ video.Begin();
+
+ // no decryption
+ vpx_codec_err_t res = decoder.DecodeFrame(video.cxdata(), video.frame_size());
+ ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+
+ // decrypt frame
+ video.Next();
+
+ std::vector<uint8_t> encrypted(video.frame_size());
+ encrypt_buffer(video.cxdata(), &encrypted[0], video.frame_size(), 0);
+ vpx_decrypt_init di = { test_decrypt_cb, &encrypted[0] };
+ decoder.Control(VPXD_SET_DECRYPTOR, &di);
+
+ res = decoder.DecodeFrame(&encrypted[0], encrypted.size());
+ ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+}
+
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/vp8_denoiser_sse2_test.cc b/media/libvpx/libvpx/test/vp8_denoiser_sse2_test.cc
new file mode 100644
index 0000000000..8cb84ddd8e
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_denoiser_sse2_test.cc
@@ -0,0 +1,119 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+
+#include "vp8/encoder/denoising.h"
+#include "vp8/common/reconinter.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+const int kNumPixels = 16 * 16;
+class VP8DenoiserTest : public ::testing::TestWithParam<int> {
+ public:
+ virtual ~VP8DenoiserTest() {}
+
+ virtual void SetUp() { increase_denoising_ = GetParam(); }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ int increase_denoising_;
+};
+
+// TODO(https://crbug.com/webm/1718): This test fails with gcc 8-10.
+#if defined(__GNUC__) && __GNUC__ >= 8
+TEST_P(VP8DenoiserTest, DISABLED_BitexactCheck) {
+#else
+TEST_P(VP8DenoiserTest, BitexactCheck) {
+#endif
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 4000;
+ const int stride = 16;
+
+ // Allocate the space for input and output,
+ // where sig_block_c/_sse2 is the block to be denoised,
+ // mc_avg_block is the denoised reference block,
+ // avg_block_c is the denoised result from C code,
+ // avg_block_sse2 is the denoised result from SSE2 code.
+ DECLARE_ALIGNED(16, uint8_t, sig_block_c[kNumPixels]);
+ // Since in VP8 denoiser, the source signal will be changed,
+ // we need another copy of the source signal as the input of sse2 code.
+ DECLARE_ALIGNED(16, uint8_t, sig_block_sse2[kNumPixels]);
+ DECLARE_ALIGNED(16, uint8_t, mc_avg_block[kNumPixels]);
+ DECLARE_ALIGNED(16, uint8_t, avg_block_c[kNumPixels]);
+ DECLARE_ALIGNED(16, uint8_t, avg_block_sse2[kNumPixels]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Generate random motion magnitude, 20% of which exceed the threshold.
+ const int motion_magnitude_ran =
+ rnd.Rand8() % static_cast<int>(MOTION_MAGNITUDE_THRESHOLD * 1.2);
+
+ // Initialize a test block with random number in range [0, 255].
+ for (int j = 0; j < kNumPixels; ++j) {
+ int temp = 0;
+ sig_block_sse2[j] = sig_block_c[j] = rnd.Rand8();
+ // The pixels in mc_avg_block are generated by adding a random
+ // number in range [-19, 19] to corresponding pixels in sig_block.
+ temp =
+ sig_block_c[j] + (rnd.Rand8() % 2 == 0 ? -1 : 1) * (rnd.Rand8() % 20);
+ // Clip.
+ mc_avg_block[j] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
+ }
+
+ // Test denosiser on Y component.
+ ASM_REGISTER_STATE_CHECK(vp8_denoiser_filter_c(
+ mc_avg_block, stride, avg_block_c, stride, sig_block_c, stride,
+ motion_magnitude_ran, increase_denoising_));
+
+ ASM_REGISTER_STATE_CHECK(vp8_denoiser_filter_sse2(
+ mc_avg_block, stride, avg_block_sse2, stride, sig_block_sse2, stride,
+ motion_magnitude_ran, increase_denoising_));
+
+ // Check bitexactness.
+ for (int h = 0; h < 16; ++h) {
+ for (int w = 0; w < 16; ++w) {
+ ASSERT_EQ(avg_block_c[h * stride + w], avg_block_sse2[h * stride + w]);
+ }
+ }
+
+ // Test denoiser on UV component.
+ ASM_REGISTER_STATE_CHECK(vp8_denoiser_filter_uv_c(
+ mc_avg_block, stride, avg_block_c, stride, sig_block_c, stride,
+ motion_magnitude_ran, increase_denoising_));
+
+ ASM_REGISTER_STATE_CHECK(vp8_denoiser_filter_uv_sse2(
+ mc_avg_block, stride, avg_block_sse2, stride, sig_block_sse2, stride,
+ motion_magnitude_ran, increase_denoising_));
+
+ // Check bitexactness.
+ for (int h = 0; h < 16; ++h) {
+ for (int w = 0; w < 16; ++w) {
+ ASSERT_EQ(avg_block_c[h * stride + w], avg_block_sse2[h * stride + w]);
+ }
+ }
+ }
+}
+
+// Test for all block size.
+INSTANTIATE_TEST_SUITE_P(SSE2, VP8DenoiserTest, ::testing::Values(0, 1));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp8_fdct4x4_test.cc b/media/libvpx/libvpx/test/vp8_fdct4x4_test.cc
new file mode 100644
index 0000000000..1b73a72a01
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_fdct4x4_test.cc
@@ -0,0 +1,211 @@
+/*
+ * 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 <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vp8_rtcd.h"
+#include "test/acm_random.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+namespace {
+
+typedef void (*FdctFunc)(int16_t *a, int16_t *b, int a_stride);
+
+const int cospi8sqrt2minus1 = 20091;
+const int sinpi8sqrt2 = 35468;
+
+void reference_idct4x4(const int16_t *input, int16_t *output) {
+ const int16_t *ip = input;
+ int16_t *op = output;
+
+ for (int i = 0; i < 4; ++i) {
+ const int a1 = ip[0] + ip[8];
+ const int b1 = ip[0] - ip[8];
+ const int temp1 = (ip[4] * sinpi8sqrt2) >> 16;
+ const int temp2 = ip[12] + ((ip[12] * cospi8sqrt2minus1) >> 16);
+ const int c1 = temp1 - temp2;
+ const int temp3 = ip[4] + ((ip[4] * cospi8sqrt2minus1) >> 16);
+ const int temp4 = (ip[12] * sinpi8sqrt2) >> 16;
+ const int d1 = temp3 + temp4;
+ op[0] = a1 + d1;
+ op[12] = a1 - d1;
+ op[4] = b1 + c1;
+ op[8] = b1 - c1;
+ ++ip;
+ ++op;
+ }
+ ip = output;
+ op = output;
+ for (int i = 0; i < 4; ++i) {
+ const int a1 = ip[0] + ip[2];
+ const int b1 = ip[0] - ip[2];
+ const int temp1 = (ip[1] * sinpi8sqrt2) >> 16;
+ const int temp2 = ip[3] + ((ip[3] * cospi8sqrt2minus1) >> 16);
+ const int c1 = temp1 - temp2;
+ const int temp3 = ip[1] + ((ip[1] * cospi8sqrt2minus1) >> 16);
+ const int temp4 = (ip[3] * sinpi8sqrt2) >> 16;
+ const int d1 = temp3 + temp4;
+ op[0] = (a1 + d1 + 4) >> 3;
+ op[3] = (a1 - d1 + 4) >> 3;
+ op[1] = (b1 + c1 + 4) >> 3;
+ op[2] = (b1 - c1 + 4) >> 3;
+ ip += 4;
+ op += 4;
+ }
+}
+
+using libvpx_test::ACMRandom;
+
+class FdctTest : public ::testing::TestWithParam<FdctFunc> {
+ public:
+ virtual void SetUp() {
+ fdct_func_ = GetParam();
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ }
+
+ protected:
+ FdctFunc fdct_func_;
+ ACMRandom rnd_;
+};
+
+TEST_P(FdctTest, SignBiasCheck) {
+ int16_t test_input_block[16];
+ DECLARE_ALIGNED(16, int16_t, test_output_block[16]);
+ const int pitch = 8;
+ int count_sign_block[16][2];
+ const int count_test_block = 1000000;
+
+ memset(count_sign_block, 0, sizeof(count_sign_block));
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-255, 255].
+ for (int j = 0; j < 16; ++j) {
+ test_input_block[j] = rnd_.Rand8() - rnd_.Rand8();
+ }
+
+ fdct_func_(test_input_block, test_output_block, pitch);
+
+ for (int j = 0; j < 16; ++j) {
+ if (test_output_block[j] < 0) {
+ ++count_sign_block[j][0];
+ } else if (test_output_block[j] > 0) {
+ ++count_sign_block[j][1];
+ }
+ }
+ }
+
+ bool bias_acceptable = true;
+ for (int j = 0; j < 16; ++j) {
+ bias_acceptable =
+ bias_acceptable &&
+ (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 10000);
+ }
+
+ EXPECT_EQ(true, bias_acceptable)
+ << "Error: 4x4 FDCT has a sign bias > 1% for input range [-255, 255]";
+
+ memset(count_sign_block, 0, sizeof(count_sign_block));
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Initialize a test block with input range [-15, 15].
+ for (int j = 0; j < 16; ++j) {
+ test_input_block[j] = (rnd_.Rand8() >> 4) - (rnd_.Rand8() >> 4);
+ }
+
+ fdct_func_(test_input_block, test_output_block, pitch);
+
+ for (int j = 0; j < 16; ++j) {
+ if (test_output_block[j] < 0) {
+ ++count_sign_block[j][0];
+ } else if (test_output_block[j] > 0) {
+ ++count_sign_block[j][1];
+ }
+ }
+ }
+
+ bias_acceptable = true;
+ for (int j = 0; j < 16; ++j) {
+ bias_acceptable =
+ bias_acceptable &&
+ (abs(count_sign_block[j][0] - count_sign_block[j][1]) < 100000);
+ }
+
+ EXPECT_EQ(true, bias_acceptable)
+ << "Error: 4x4 FDCT has a sign bias > 10% for input range [-15, 15]";
+}
+
+TEST_P(FdctTest, RoundTripErrorCheck) {
+ int max_error = 0;
+ double total_error = 0;
+ const int count_test_block = 1000000;
+ for (int i = 0; i < count_test_block; ++i) {
+ int16_t test_input_block[16];
+ int16_t test_output_block[16];
+ DECLARE_ALIGNED(16, int16_t, test_temp_block[16]);
+
+ // Initialize a test block with input range [-255, 255].
+ for (int j = 0; j < 16; ++j) {
+ test_input_block[j] = rnd_.Rand8() - rnd_.Rand8();
+ }
+
+ const int pitch = 8;
+ fdct_func_(test_input_block, test_temp_block, pitch);
+ reference_idct4x4(test_temp_block, test_output_block);
+
+ for (int j = 0; j < 16; ++j) {
+ const int diff = test_input_block[j] - test_output_block[j];
+ const int error = diff * diff;
+ if (max_error < error) max_error = error;
+ total_error += error;
+ }
+ }
+
+ EXPECT_GE(1, max_error)
+ << "Error: FDCT/IDCT has an individual roundtrip error > 1";
+
+ EXPECT_GE(count_test_block, total_error)
+ << "Error: FDCT/IDCT has average roundtrip error > 1 per block";
+}
+
+INSTANTIATE_TEST_SUITE_P(C, FdctTest, ::testing::Values(vp8_short_fdct4x4_c));
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, FdctTest,
+ ::testing::Values(vp8_short_fdct4x4_neon));
+#endif // HAVE_NEON
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(SSE2, FdctTest,
+ ::testing::Values(vp8_short_fdct4x4_sse2));
+#endif // HAVE_SSE2
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(MSA, FdctTest,
+ ::testing::Values(vp8_short_fdct4x4_msa));
+#endif // HAVE_MSA
+#if HAVE_MMI
+INSTANTIATE_TEST_SUITE_P(MMI, FdctTest,
+ ::testing::Values(vp8_short_fdct4x4_mmi));
+#endif // HAVE_MMI
+
+#if HAVE_LSX
+INSTANTIATE_TEST_SUITE_P(LSX, FdctTest,
+ ::testing::Values(vp8_short_fdct4x4_lsx));
+#endif // HAVE_LSX
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp8_fragments_test.cc b/media/libvpx/libvpx/test/vp8_fragments_test.cc
new file mode 100644
index 0000000000..6e5baf229d
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_fragments_test.cc
@@ -0,0 +1,36 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/video_source.h"
+
+namespace {
+
+class VP8FragmentsTest : public ::libvpx_test::EncoderTest,
+ public ::testing::Test {
+ protected:
+ VP8FragmentsTest() : EncoderTest(&::libvpx_test::kVP8) {}
+ virtual ~VP8FragmentsTest() {}
+
+ virtual void SetUp() {
+ const unsigned long init_flags = // NOLINT(runtime/int)
+ VPX_CODEC_USE_OUTPUT_PARTITION;
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_init_flags(init_flags);
+ }
+};
+
+TEST_F(VP8FragmentsTest, TestFragmentsEncodeDecode) {
+ ::libvpx_test::RandomVideoSource video;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp8_multi_resolution_encoder.sh b/media/libvpx/libvpx/test/vp8_multi_resolution_encoder.sh
new file mode 100755
index 0000000000..1e96f94cc7
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_multi_resolution_encoder.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx vp8_multi_resolution_encoder example. To add new
+## tests to this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to vp8_mre_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+vp8_multi_resolution_encoder_verify_environment() {
+ if [ "$(vpx_config_option_enabled CONFIG_MULTI_RES_ENCODING)" = "yes" ]; then
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ elog "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ local app="vp8_multi_resolution_encoder"
+ if [ -z "$(vpx_tool_path "${app}")" ]; then
+ elog "${app} not found. It must exist in LIBVPX_BIN_PATH or its parent."
+ return 1
+ fi
+ fi
+}
+
+# Runs vp8_multi_resolution_encoder. Simply forwards all arguments to
+# vp8_multi_resolution_encoder after building path to the executable.
+vp8_mre() {
+ local encoder="$(vpx_tool_path vp8_multi_resolution_encoder)"
+ if [ ! -x "${encoder}" ]; then
+ elog "${encoder} does not exist or is not executable."
+ return 1
+ fi
+
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "$@" ${devnull}
+}
+
+vp8_multi_resolution_encoder_three_formats() {
+ local output_files="${VPX_TEST_OUTPUT_DIR}/vp8_mre_0.ivf
+ ${VPX_TEST_OUTPUT_DIR}/vp8_mre_1.ivf
+ ${VPX_TEST_OUTPUT_DIR}/vp8_mre_2.ivf"
+ local layer_bitrates="150 80 50"
+ local keyframe_insert="200"
+ local temporal_layers="3 3 3"
+ local framerate="30"
+
+ if [ "$(vpx_config_option_enabled CONFIG_MULTI_RES_ENCODING)" = "yes" ]; then
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ # Param order:
+ # Input width
+ # Input height
+ # Framerate
+ # Input file path
+ # Output file names
+ # Layer bitrates
+ # Temporal layers
+ # Keyframe insert
+ # Output PSNR
+ vp8_mre "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" \
+ "${framerate}" \
+ "${YUV_RAW_INPUT}" \
+ ${output_files} \
+ ${layer_bitrates} \
+ ${temporal_layers} \
+ "${keyframe_insert}" \
+ 0 || return 1
+
+ for output_file in ${output_files}; do
+ if [ ! -e "${output_file}" ]; then
+ elog "Missing output file: ${output_file}"
+ return 1
+ fi
+ done
+ fi
+ fi
+}
+
+vp8_mre_tests="vp8_multi_resolution_encoder_three_formats"
+run_tests vp8_multi_resolution_encoder_verify_environment "${vp8_mre_tests}"
diff --git a/media/libvpx/libvpx/test/vp8_ratectrl_rtc_test.cc b/media/libvpx/libvpx/test/vp8_ratectrl_rtc_test.cc
new file mode 100644
index 0000000000..b76bcae11d
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp8_ratectrl_rtc_test.cc
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2021 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 <fstream> // NOLINT
+#include <string>
+
+#include "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/video_source.h"
+#include "vp8/vp8_ratectrl_rtc.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/bitops.h"
+
+namespace {
+
+struct Vp8RCTestVideo {
+ Vp8RCTestVideo() {}
+ Vp8RCTestVideo(const char *name_, int width_, int height_,
+ unsigned int frames_)
+ : name(name_), width(width_), height(height_), frames(frames_) {}
+
+ friend std::ostream &operator<<(std::ostream &os,
+ const Vp8RCTestVideo &video) {
+ os << video.name << " " << video.width << " " << video.height << " "
+ << video.frames;
+ return os;
+ }
+ const char *name;
+ int width;
+ int height;
+ unsigned int frames;
+};
+
+const Vp8RCTestVideo kVp8RCTestVectors[] = {
+ Vp8RCTestVideo("niklas_640_480_30.yuv", 640, 480, 470),
+ Vp8RCTestVideo("desktop_office1.1280_720-020.yuv", 1280, 720, 300),
+};
+
+class Vp8RcInterfaceTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<int, Vp8RCTestVideo> {
+ public:
+ Vp8RcInterfaceTest()
+ : EncoderTest(GET_PARAM(0)), key_interval_(3000), encoder_exit_(false) {}
+ virtual ~Vp8RcInterfaceTest() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ // From error_resilience_test.cc
+ int SetFrameFlags(int frame_num, int num_temp_layers) {
+ int frame_flags = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ // Layer 0: predict from L and ARF, update L.
+ frame_flags =
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+ } else {
+ // Layer 1: predict from L, G and ARF, and update G.
+ frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+ VP8_EFLAG_NO_UPD_ENTROPY;
+ }
+ } else if (num_temp_layers == 3) {
+ if (frame_num % 4 == 0) {
+ // Layer 0: predict from L, update L.
+ frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+ } else if ((frame_num - 2) % 4 == 0) {
+ // Layer 1: predict from L, G, update G.
+ frame_flags =
+ VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
+ } else if ((frame_num - 1) % 2 == 0) {
+ // Layer 2: predict from L, G, ARF; update ARG.
+ frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+ }
+ }
+ return frame_flags;
+ }
+
+ int SetLayerId(int frame_num, int num_temp_layers) {
+ int layer_id = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ layer_id = 0;
+ } else {
+ layer_id = 1;
+ }
+ } else if (num_temp_layers == 3) {
+ if (frame_num % 4 == 0) {
+ layer_id = 0;
+ } else if ((frame_num - 2) % 4 == 0) {
+ layer_id = 1;
+ } else if ((frame_num - 1) % 2 == 0) {
+ layer_id = 2;
+ }
+ }
+ return layer_id;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (rc_cfg_.ts_number_layers > 1) {
+ const int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
+ const int frame_flags =
+ SetFrameFlags(video->frame(), cfg_.ts_number_layers);
+ frame_params_.temporal_layer_id = layer_id;
+ if (video->frame() > 0) {
+ encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
+ encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
+ }
+ } else {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, -6);
+ encoder->Control(VP8E_SET_RTC_EXTERNAL_RATECTRL, 1);
+ encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 1000);
+ } else if (frame_params_.frame_type == libvpx::RcFrameType::kInterFrame) {
+ // Disable golden frame update.
+ frame_flags_ |= VP8_EFLAG_NO_UPD_GF;
+ frame_flags_ |= VP8_EFLAG_NO_UPD_ARF;
+ }
+ }
+ frame_params_.frame_type = video->frame() % key_interval_ == 0
+ ? libvpx::RcFrameType::kKeyFrame
+ : libvpx::RcFrameType::kInterFrame;
+ encoder_exit_ = video->frame() == test_video_.frames;
+ }
+
+ virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+ if (encoder_exit_) {
+ return;
+ }
+ int qp;
+ encoder->Control(VP8E_GET_LAST_QUANTIZER, &qp);
+ rc_api_->ComputeQP(frame_params_);
+ ASSERT_EQ(rc_api_->GetQP(), qp);
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ rc_api_->PostEncodeUpdate(pkt->data.frame.sz);
+ }
+
+ void RunOneLayer() {
+ test_video_ = GET_PARAM(2);
+ target_bitrate_ = GET_PARAM(1);
+ if (test_video_.width == 1280 && target_bitrate_ == 200) return;
+ if (test_video_.width == 640 && target_bitrate_ == 1000) return;
+ SetConfig();
+ rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+
+ ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
+ test_video_.height, 30, 1, 0,
+ test_video_.frames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunPeriodicKey() {
+ test_video_ = GET_PARAM(2);
+ target_bitrate_ = GET_PARAM(1);
+ if (test_video_.width == 1280 && target_bitrate_ == 200) return;
+ if (test_video_.width == 640 && target_bitrate_ == 1000) return;
+ key_interval_ = 100;
+ SetConfig();
+ rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+
+ ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
+ test_video_.height, 30, 1, 0,
+ test_video_.frames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunTemporalLayers2TL() {
+ test_video_ = GET_PARAM(2);
+ target_bitrate_ = GET_PARAM(1);
+ if (test_video_.width == 1280 && target_bitrate_ == 200) return;
+ if (test_video_.width == 640 && target_bitrate_ == 1000) return;
+ SetConfigTemporalLayers(2);
+ rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+
+ ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
+ test_video_.height, 30, 1, 0,
+ test_video_.frames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunTemporalLayers3TL() {
+ test_video_ = GET_PARAM(2);
+ target_bitrate_ = GET_PARAM(1);
+ if (test_video_.width == 1280 && target_bitrate_ == 200) return;
+ if (test_video_.width == 640 && target_bitrate_ == 1000) return;
+ SetConfigTemporalLayers(3);
+ rc_api_ = libvpx::VP8RateControlRTC::Create(rc_cfg_);
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+
+ ::libvpx_test::I420VideoSource video(test_video_.name, test_video_.width,
+ test_video_.height, 30, 1, 0,
+ test_video_.frames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ private:
+ void SetConfig() {
+ rc_cfg_.width = test_video_.width;
+ rc_cfg_.height = test_video_.height;
+ rc_cfg_.max_quantizer = 60;
+ rc_cfg_.min_quantizer = 2;
+ rc_cfg_.target_bandwidth = target_bitrate_;
+ rc_cfg_.buf_initial_sz = 600;
+ rc_cfg_.buf_optimal_sz = 600;
+ rc_cfg_.buf_sz = target_bitrate_;
+ rc_cfg_.undershoot_pct = 50;
+ rc_cfg_.overshoot_pct = 50;
+ rc_cfg_.max_intra_bitrate_pct = 1000;
+ rc_cfg_.framerate = 30.0;
+ rc_cfg_.layer_target_bitrate[0] = target_bitrate_;
+
+ // Encoder settings for ground truth.
+ cfg_.g_w = test_video_.width;
+ cfg_.g_h = test_video_.height;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_buf_initial_sz = 600;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_buf_sz = target_bitrate_;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 60;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.rc_target_bitrate = target_bitrate_;
+ cfg_.kf_min_dist = key_interval_;
+ cfg_.kf_max_dist = key_interval_;
+ }
+
+ void SetConfigTemporalLayers(int temporal_layers) {
+ rc_cfg_.width = test_video_.width;
+ rc_cfg_.height = test_video_.height;
+ rc_cfg_.max_quantizer = 60;
+ rc_cfg_.min_quantizer = 2;
+ rc_cfg_.target_bandwidth = target_bitrate_;
+ rc_cfg_.buf_initial_sz = 600;
+ rc_cfg_.buf_optimal_sz = 600;
+ rc_cfg_.buf_sz = target_bitrate_;
+ rc_cfg_.undershoot_pct = 50;
+ rc_cfg_.overshoot_pct = 50;
+ rc_cfg_.max_intra_bitrate_pct = 1000;
+ rc_cfg_.framerate = 30.0;
+ if (temporal_layers == 2) {
+ rc_cfg_.layer_target_bitrate[0] = 60 * target_bitrate_ / 100;
+ rc_cfg_.layer_target_bitrate[1] = target_bitrate_;
+ rc_cfg_.ts_rate_decimator[0] = 2;
+ rc_cfg_.ts_rate_decimator[1] = 1;
+ } else if (temporal_layers == 3) {
+ rc_cfg_.layer_target_bitrate[0] = 40 * target_bitrate_ / 100;
+ rc_cfg_.layer_target_bitrate[1] = 60 * target_bitrate_ / 100;
+ rc_cfg_.layer_target_bitrate[2] = target_bitrate_;
+ rc_cfg_.ts_rate_decimator[0] = 4;
+ rc_cfg_.ts_rate_decimator[1] = 2;
+ rc_cfg_.ts_rate_decimator[2] = 1;
+ }
+
+ rc_cfg_.ts_number_layers = temporal_layers;
+
+ // Encoder settings for ground truth.
+ cfg_.g_w = test_video_.width;
+ cfg_.g_h = test_video_.height;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_buf_initial_sz = 600;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_buf_sz = target_bitrate_;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 60;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 1;
+ cfg_.rc_target_bitrate = target_bitrate_;
+ cfg_.kf_min_dist = key_interval_;
+ cfg_.kf_max_dist = key_interval_;
+ // 2 Temporal layers, no spatial layers, CBR mode.
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = temporal_layers;
+ if (temporal_layers == 2) {
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+ cfg_.ts_periodicity = 2;
+ cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
+ } else if (temporal_layers == 3) {
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.ts_periodicity = 4;
+ cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
+ }
+ }
+
+ std::unique_ptr<libvpx::VP8RateControlRTC> rc_api_;
+ libvpx::VP8RateControlRtcConfig rc_cfg_;
+ int key_interval_;
+ int target_bitrate_;
+ Vp8RCTestVideo test_video_;
+ libvpx::VP8FrameParamsQpRTC frame_params_;
+ bool encoder_exit_;
+};
+
+TEST_P(Vp8RcInterfaceTest, OneLayer) { RunOneLayer(); }
+
+TEST_P(Vp8RcInterfaceTest, OneLayerPeriodicKey) { RunPeriodicKey(); }
+
+TEST_P(Vp8RcInterfaceTest, TemporalLayers2TL) { RunTemporalLayers2TL(); }
+
+TEST_P(Vp8RcInterfaceTest, TemporalLayers3TL) { RunTemporalLayers3TL(); }
+
+VP8_INSTANTIATE_TEST_SUITE(Vp8RcInterfaceTest,
+ ::testing::Values(200, 400, 1000),
+ ::testing::ValuesIn(kVp8RCTestVectors));
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_arf_freq_test.cc b/media/libvpx/libvpx/test/vp9_arf_freq_test.cc
new file mode 100644
index 0000000000..c7e6f1af02
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_arf_freq_test.cc
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2015 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 <memory>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "test/yuv_video_source.h"
+#include "vp9/encoder/vp9_ratectrl.h"
+
+namespace {
+
+const unsigned int kFrames = 100;
+const int kBitrate = 500;
+
+#define ARF_NOT_SEEN 1000001
+#define ARF_SEEN_ONCE 1000000
+
+typedef struct {
+ const char *filename;
+ unsigned int width;
+ unsigned int height;
+ unsigned int framerate_num;
+ unsigned int framerate_den;
+ unsigned int input_bit_depth;
+ vpx_img_fmt fmt;
+ vpx_bit_depth_t bit_depth;
+ unsigned int profile;
+} TestVideoParam;
+
+typedef struct {
+ libvpx_test::TestMode mode;
+ int cpu_used;
+} TestEncodeParam;
+
+const TestVideoParam kTestVectors[] = {
+ // artificially increase framerate to trigger default check
+ { "hantro_collage_w352h288.yuv", 352, 288, 5000, 1, 8, VPX_IMG_FMT_I420,
+ VPX_BITS_8, 0 },
+ { "hantro_collage_w352h288.yuv", 352, 288, 30, 1, 8, VPX_IMG_FMT_I420,
+ VPX_BITS_8, 0 },
+ { "rush_hour_444.y4m", 352, 288, 30, 1, 8, VPX_IMG_FMT_I444, VPX_BITS_8, 1 },
+#if CONFIG_VP9_HIGHBITDEPTH
+// Add list of profile 2/3 test videos here ...
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+
+const TestEncodeParam kEncodeVectors[] = {
+ { ::libvpx_test::kOnePassGood, 2 }, { ::libvpx_test::kOnePassGood, 5 },
+ { ::libvpx_test::kTwoPassGood, 1 }, { ::libvpx_test::kTwoPassGood, 2 },
+ { ::libvpx_test::kTwoPassGood, 5 }, { ::libvpx_test::kRealTime, 5 },
+};
+
+const int kMinArfVectors[] = {
+ // NOTE: 0 refers to the default built-in logic in:
+ // vp9_rc_get_default_min_gf_interval(...)
+ 0, 4, 8, 12, 15
+};
+
+int is_extension_y4m(const char *filename) {
+ const char *dot = strrchr(filename, '.');
+ if (!dot || dot == filename) {
+ return 0;
+ } else {
+ return !strcmp(dot, ".y4m");
+ }
+}
+
+class ArfFreqTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith3Params<TestVideoParam,
+ TestEncodeParam, int> {
+ protected:
+ ArfFreqTest()
+ : EncoderTest(GET_PARAM(0)), test_video_param_(GET_PARAM(1)),
+ test_encode_param_(GET_PARAM(2)), min_arf_requested_(GET_PARAM(3)) {}
+
+ virtual ~ArfFreqTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(test_encode_param_.mode);
+ if (test_encode_param_.mode != ::libvpx_test::kRealTime) {
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_end_usage = VPX_VBR;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ }
+ dec_cfg_.threads = 4;
+ }
+
+ virtual void BeginPassHook(unsigned int) {
+ min_run_ = ARF_NOT_SEEN;
+ run_of_visible_frames_ = 0;
+ }
+
+ int GetNumFramesInPkt(const vpx_codec_cx_pkt_t *pkt) {
+ const uint8_t *buffer = reinterpret_cast<uint8_t *>(pkt->data.frame.buf);
+ const uint8_t marker = buffer[pkt->data.frame.sz - 1];
+ const int mag = ((marker >> 3) & 3) + 1;
+ int frames = (marker & 0x7) + 1;
+ const unsigned int index_sz = 2 + mag * frames;
+ // Check for superframe or not.
+ // Assume superframe has only one visible frame, the rest being
+ // invisible. If superframe index is not found, then there is only
+ // one frame.
+ if (!((marker & 0xe0) == 0xc0 && pkt->data.frame.sz >= index_sz &&
+ buffer[pkt->data.frame.sz - index_sz] == marker)) {
+ frames = 1;
+ }
+ return frames;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
+ const int frames = GetNumFramesInPkt(pkt);
+ if (frames == 1) {
+ run_of_visible_frames_++;
+ } else if (frames == 2) {
+ if (min_run_ == ARF_NOT_SEEN) {
+ min_run_ = ARF_SEEN_ONCE;
+ } else if (min_run_ == ARF_SEEN_ONCE ||
+ run_of_visible_frames_ < min_run_) {
+ min_run_ = run_of_visible_frames_;
+ }
+ run_of_visible_frames_ = 1;
+ } else {
+ min_run_ = 0;
+ run_of_visible_frames_ = 1;
+ }
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, 4);
+ encoder->Control(VP8E_SET_CPUUSED, test_encode_param_.cpu_used);
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_arf_requested_);
+ if (test_encode_param_.mode != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+ }
+
+ int GetMinVisibleRun() const { return min_run_; }
+
+ int GetMinArfDistanceRequested() const {
+ if (min_arf_requested_) {
+ return min_arf_requested_;
+ } else {
+ return vp9_rc_get_default_min_gf_interval(
+ test_video_param_.width, test_video_param_.height,
+ (double)test_video_param_.framerate_num /
+ test_video_param_.framerate_den);
+ }
+ }
+
+ TestVideoParam test_video_param_;
+ TestEncodeParam test_encode_param_;
+
+ private:
+ int min_arf_requested_;
+ int min_run_;
+ int run_of_visible_frames_;
+};
+
+TEST_P(ArfFreqTest, MinArfFreqTest) {
+ cfg_.rc_target_bitrate = kBitrate;
+ cfg_.g_error_resilient = 0;
+ cfg_.g_profile = test_video_param_.profile;
+ cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
+ cfg_.g_bit_depth = test_video_param_.bit_depth;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ if (is_extension_y4m(test_video_param_.filename)) {
+ video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
+ kFrames));
+ } else {
+ video.reset(new libvpx_test::YUVVideoSource(
+ test_video_param_.filename, test_video_param_.fmt,
+ test_video_param_.width, test_video_param_.height,
+ test_video_param_.framerate_num, test_video_param_.framerate_den, 0,
+ kFrames));
+ }
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ const int min_run = GetMinVisibleRun();
+ const int min_arf_dist_requested = GetMinArfDistanceRequested();
+ if (min_run != ARF_NOT_SEEN && min_run != ARF_SEEN_ONCE) {
+ const int min_arf_dist = min_run + 1;
+ EXPECT_GE(min_arf_dist, min_arf_dist_requested);
+ }
+}
+
+VP9_INSTANTIATE_TEST_SUITE(ArfFreqTest, ::testing::ValuesIn(kTestVectors),
+ ::testing::ValuesIn(kEncodeVectors),
+ ::testing::ValuesIn(kMinArfVectors));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_block_error_test.cc b/media/libvpx/libvpx/test/vp9_block_error_test.cc
new file mode 100644
index 0000000000..9e9595ebe9
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_block_error_test.cc
@@ -0,0 +1,218 @@
+/*
+ * 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 <cmath>
+#include <cstdlib>
+#include <string>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vp9_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_dsp/vpx_dsp_common.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+const int kNumIterations = 1000;
+
+typedef int64_t (*HBDBlockErrorFunc)(const tran_low_t *coeff,
+ const tran_low_t *dqcoeff,
+ intptr_t block_size, int64_t *ssz,
+ int bps);
+
+typedef std::tuple<HBDBlockErrorFunc, HBDBlockErrorFunc, vpx_bit_depth_t>
+ BlockErrorParam;
+
+typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff,
+ const tran_low_t *dqcoeff,
+ intptr_t block_size, int64_t *ssz);
+
+template <BlockErrorFunc fn>
+int64_t BlockError8BitWrapper(const tran_low_t *coeff,
+ const tran_low_t *dqcoeff, intptr_t block_size,
+ int64_t *ssz, int bps) {
+ EXPECT_EQ(bps, 8);
+ return fn(coeff, dqcoeff, block_size, ssz);
+}
+
+class BlockErrorTest : public ::testing::TestWithParam<BlockErrorParam> {
+ public:
+ virtual ~BlockErrorTest() {}
+ virtual void SetUp() {
+ error_block_op_ = GET_PARAM(0);
+ ref_error_block_op_ = GET_PARAM(1);
+ bit_depth_ = GET_PARAM(2);
+ }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ vpx_bit_depth_t bit_depth_;
+ HBDBlockErrorFunc error_block_op_;
+ HBDBlockErrorFunc ref_error_block_op_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlockErrorTest);
+
+TEST_P(BlockErrorTest, OperationCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
+ DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
+ int err_count_total = 0;
+ int first_failure = -1;
+ intptr_t block_size;
+ int64_t ssz;
+ int64_t ret;
+ int64_t ref_ssz;
+ int64_t ref_ret;
+ const int msb = bit_depth_ + 8 - 1;
+ for (int i = 0; i < kNumIterations; ++i) {
+ int err_count = 0;
+ block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
+ for (int j = 0; j < block_size; j++) {
+ // coeff and dqcoeff will always have at least the same sign, and this
+ // can be used for optimization, so generate test input precisely.
+ if (rnd(2)) {
+ // Positive number
+ coeff[j] = rnd(1 << msb);
+ dqcoeff[j] = rnd(1 << msb);
+ } else {
+ // Negative number
+ coeff[j] = -rnd(1 << msb);
+ dqcoeff[j] = -rnd(1 << msb);
+ }
+ }
+ ref_ret =
+ ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
+ ASM_REGISTER_STATE_CHECK(
+ ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
+ err_count += (ref_ret != ret) | (ref_ssz != ssz);
+ if (err_count && !err_count_total) {
+ first_failure = i;
+ }
+ err_count_total += err_count;
+ }
+ EXPECT_EQ(0, err_count_total)
+ << "Error: Error Block Test, C output doesn't match optimized output. "
+ << "First failed at test case " << first_failure;
+}
+
+TEST_P(BlockErrorTest, ExtremeValues) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
+ DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
+ int err_count_total = 0;
+ int first_failure = -1;
+ intptr_t block_size;
+ int64_t ssz;
+ int64_t ret;
+ int64_t ref_ssz;
+ int64_t ref_ret;
+ const int msb = bit_depth_ + 8 - 1;
+ int max_val = ((1 << msb) - 1);
+ for (int i = 0; i < kNumIterations; ++i) {
+ int err_count = 0;
+ int k = (i / 9) % 9;
+
+ // Change the maximum coeff value, to test different bit boundaries
+ if (k == 8 && (i % 9) == 0) {
+ max_val >>= 1;
+ }
+ block_size = 16 << (i % 9); // All block sizes from 4x4, 8x4 ..64x64
+ for (int j = 0; j < block_size; j++) {
+ if (k < 4) {
+ // Test at positive maximum values
+ coeff[j] = k % 2 ? max_val : 0;
+ dqcoeff[j] = (k >> 1) % 2 ? max_val : 0;
+ } else if (k < 8) {
+ // Test at negative maximum values
+ coeff[j] = k % 2 ? -max_val : 0;
+ dqcoeff[j] = (k >> 1) % 2 ? -max_val : 0;
+ } else {
+ if (rnd(2)) {
+ // Positive number
+ coeff[j] = rnd(1 << 14);
+ dqcoeff[j] = rnd(1 << 14);
+ } else {
+ // Negative number
+ coeff[j] = -rnd(1 << 14);
+ dqcoeff[j] = -rnd(1 << 14);
+ }
+ }
+ }
+ ref_ret =
+ ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
+ ASM_REGISTER_STATE_CHECK(
+ ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
+ err_count += (ref_ret != ret) | (ref_ssz != ssz);
+ if (err_count && !err_count_total) {
+ first_failure = i;
+ }
+ err_count_total += err_count;
+ }
+ EXPECT_EQ(0, err_count_total)
+ << "Error: Error Block Test, C output doesn't match optimized output. "
+ << "First failed at test case " << first_failure;
+}
+
+using std::make_tuple;
+
+#if HAVE_SSE2
+const BlockErrorParam sse2_block_error_tests[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vp9_highbd_block_error_sse2, &vp9_highbd_block_error_c,
+ VPX_BITS_10),
+ make_tuple(&vp9_highbd_block_error_sse2, &vp9_highbd_block_error_c,
+ VPX_BITS_12),
+ make_tuple(&vp9_highbd_block_error_sse2, &vp9_highbd_block_error_c,
+ VPX_BITS_8),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&BlockError8BitWrapper<vp9_block_error_sse2>,
+ &BlockError8BitWrapper<vp9_block_error_c>, VPX_BITS_8)
+};
+
+INSTANTIATE_TEST_SUITE_P(SSE2, BlockErrorTest,
+ ::testing::ValuesIn(sse2_block_error_tests));
+#endif // HAVE_SSE2
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, BlockErrorTest,
+ ::testing::Values(make_tuple(&BlockError8BitWrapper<vp9_block_error_avx2>,
+ &BlockError8BitWrapper<vp9_block_error_c>,
+ VPX_BITS_8)));
+#endif // HAVE_AVX2
+
+#if HAVE_NEON
+const BlockErrorParam neon_block_error_tests[] = {
+#if CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&vp9_highbd_block_error_neon, &vp9_highbd_block_error_c,
+ VPX_BITS_10),
+ make_tuple(&vp9_highbd_block_error_neon, &vp9_highbd_block_error_c,
+ VPX_BITS_12),
+ make_tuple(&vp9_highbd_block_error_neon, &vp9_highbd_block_error_c,
+ VPX_BITS_8),
+#endif // CONFIG_VP9_HIGHBITDEPTH
+ make_tuple(&BlockError8BitWrapper<vp9_block_error_neon>,
+ &BlockError8BitWrapper<vp9_block_error_c>, VPX_BITS_8)
+};
+
+INSTANTIATE_TEST_SUITE_P(NEON, BlockErrorTest,
+ ::testing::ValuesIn(neon_block_error_tests));
+#endif // HAVE_NEON
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_boolcoder_test.cc b/media/libvpx/libvpx/test/vp9_boolcoder_test.cc
new file mode 100644
index 0000000000..6ba171a000
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_boolcoder_test.cc
@@ -0,0 +1,92 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/acm_random.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_dsp/bitreader.h"
+#include "vpx_dsp/bitwriter.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+const int num_tests = 10;
+} // namespace
+
+TEST(VP9, 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 kBitsToTest = 1000;
+ uint8_t probas[kBitsToTest];
+
+ for (int i = 0; i < kBitsToTest; ++i) {
+ const int parity = i & 1;
+ /* clang-format off */
+ 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));
+ /* clang-format on */
+ }
+ for (int bit_method = 0; bit_method <= 3; ++bit_method) {
+ const int random_seed = 6432;
+ const int kBufferSize = 10000;
+ ACMRandom bit_rnd(random_seed);
+ vpx_writer bw;
+ uint8_t bw_buffer[kBufferSize];
+ vpx_start_encode(&bw, bw_buffer);
+
+ int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
+ for (int i = 0; i < kBitsToTest; ++i) {
+ if (bit_method == 2) {
+ bit = (i & 1);
+ } else if (bit_method == 3) {
+ bit = bit_rnd(2);
+ }
+ vpx_write(&bw, bit, static_cast<int>(probas[i]));
+ }
+
+ vpx_stop_encode(&bw);
+ // vpx_reader_fill() may read into uninitialized data that
+ // isn't used meaningfully, but may trigger an MSan warning.
+ memset(bw_buffer + bw.pos, 0, sizeof(BD_VALUE) - 1);
+
+ // First bit should be zero
+ GTEST_ASSERT_EQ(bw_buffer[0] & 0x80, 0);
+
+ vpx_reader br;
+ vpx_reader_init(&br, bw_buffer, kBufferSize, nullptr, nullptr);
+ bit_rnd.Reset(random_seed);
+ for (int i = 0; i < kBitsToTest; ++i) {
+ if (bit_method == 2) {
+ bit = (i & 1);
+ } else if (bit_method == 3) {
+ bit = bit_rnd(2);
+ }
+ GTEST_ASSERT_EQ(vpx_read(&br, probas[i]), bit)
+ << "pos: " << i << " / " << kBitsToTest
+ << " bit_method: " << bit_method << " method: " << method;
+ }
+ }
+ }
+ }
+}
diff --git a/media/libvpx/libvpx/test/vp9_datarate_test.cc b/media/libvpx/libvpx/test/vp9_datarate_test.cc
new file mode 100644
index 0000000000..7e91807492
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_datarate_test.cc
@@ -0,0 +1,1096 @@
+/*
+ * 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 "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/bitops.h"
+
+namespace {
+
+class DatarateTestVP9 : public ::libvpx_test::EncoderTest {
+ public:
+ explicit DatarateTestVP9(const ::libvpx_test::CodecFactory *codec)
+ : EncoderTest(codec) {
+ tune_content_ = 0;
+ }
+
+ protected:
+ virtual ~DatarateTestVP9() {}
+
+ virtual void ResetModel() {
+ last_pts_ = 0;
+ bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
+ frame_number_ = 0;
+ tot_frame_number_ = 0;
+ first_drop_ = 0;
+ num_drops_ = 0;
+ aq_mode_ = 3;
+ // Denoiser is off by default.
+ denoiser_on_ = 0;
+ // For testing up to 3 layers.
+ for (int i = 0; i < 3; ++i) {
+ bits_total_[i] = 0;
+ }
+ denoiser_offon_test_ = 0;
+ denoiser_offon_period_ = -1;
+ frame_parallel_decoding_mode_ = 1;
+ delta_q_uv_ = 0;
+ use_roi_ = false;
+ }
+
+ //
+ // Frame flags and layer id for temporal layers.
+ //
+
+ // For two layers, test pattern is:
+ // 1 3
+ // 0 2 .....
+ // For three layers, test pattern is:
+ // 1 3 5 7
+ // 2 6
+ // 0 4 ....
+ // LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
+ // For this 3 layer example, the 2nd enhancement layer (layer 2) updates
+ // the altref frame.
+ static int GetFrameFlags(int frame_num, int num_temp_layers) {
+ int frame_flags = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ // Layer 0: predict from L and ARF, update L.
+ frame_flags =
+ VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+ } else {
+ // Layer 1: predict from L, G and ARF, and update G.
+ frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+ VP8_EFLAG_NO_UPD_ENTROPY;
+ }
+ } else if (num_temp_layers == 3) {
+ if (frame_num % 4 == 0) {
+ // Layer 0: predict from L and ARF; update L.
+ frame_flags =
+ VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
+ } else if ((frame_num - 2) % 4 == 0) {
+ // Layer 1: predict from L, G, ARF; update G.
+ frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+ } else if ((frame_num - 1) % 2 == 0) {
+ // Layer 2: predict from L, G, ARF; update ARF.
+ frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+ }
+ }
+ return frame_flags;
+ }
+
+ static int SetLayerId(int frame_num, int num_temp_layers) {
+ int layer_id = 0;
+ if (num_temp_layers == 2) {
+ if (frame_num % 2 == 0) {
+ layer_id = 0;
+ } else {
+ layer_id = 1;
+ }
+ } else if (num_temp_layers == 3) {
+ if (frame_num % 4 == 0) {
+ layer_id = 0;
+ } else if ((frame_num - 2) % 4 == 0) {
+ layer_id = 1;
+ } else if ((frame_num - 1) % 2 == 0) {
+ layer_id = 2;
+ }
+ }
+ return layer_id;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
+ encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_);
+ }
+
+ if (denoiser_offon_test_) {
+ ASSERT_GT(denoiser_offon_period_, 0)
+ << "denoiser_offon_period_ is not positive.";
+ if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
+ // Flip denoiser_on_ periodically
+ denoiser_on_ ^= 1;
+ }
+ }
+
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, get_msb(cfg_.g_threads));
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
+ frame_parallel_decoding_mode_);
+
+ if (use_roi_) {
+ encoder->Control(VP9E_SET_ROI_MAP, &roi_);
+ encoder->Control(VP9E_SET_AQ_MODE, 0);
+ }
+
+ if (delta_q_uv_ != 0) {
+ encoder->Control(VP9E_SET_DELTA_Q_UV, delta_q_uv_);
+ }
+
+ if (cfg_.ts_number_layers > 1) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_SVC, 1);
+ }
+ if (cfg_.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
+ vpx_svc_layer_id_t layer_id;
+ frame_flags_ = GetFrameFlags(video->frame(), cfg_.ts_number_layers);
+ layer_id.spatial_layer_id = 0;
+ layer_id.temporal_layer_id =
+ SetLayerId(video->frame(), cfg_.ts_number_layers);
+ layer_id.temporal_layer_id_per_spatial[0] =
+ SetLayerId(video->frame(), cfg_.ts_number_layers);
+ encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
+ }
+ }
+ const vpx_rational_t tb = video->timebase();
+ timebase_ = static_cast<double>(tb.num) / tb.den;
+ duration_ = 0;
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ // Time since last timestamp = duration.
+ vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+
+ if (duration > 1) {
+ // If first drop not set and we have a drop set it to this time.
+ if (!first_drop_) first_drop_ = last_pts_ + 1;
+ // Update the number of frame drops.
+ num_drops_ += static_cast<int>(duration - 1);
+ // Update counter for total number of frames (#frames input to encoder).
+ // Needed for setting the proper layer_id below.
+ tot_frame_number_ += static_cast<int>(duration - 1);
+ }
+
+ int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
+
+ // Add to the buffer the bits we'd expect from a constant bitrate server.
+ bits_in_buffer_model_ += static_cast<int64_t>(
+ duration * timebase_ * cfg_.rc_target_bitrate * 1000);
+
+ // Buffer should not go negative.
+ ASSERT_GE(bits_in_buffer_model_, 0)
+ << "Buffer Underrun at frame " << pkt->data.frame.pts;
+
+ const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
+
+ // Update the total encoded bits. For temporal layers, update the cumulative
+ // encoded bits per layer.
+ for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
+ bits_total_[i] += frame_size_in_bits;
+ }
+
+ // Update the most recent pts.
+ last_pts_ = pkt->data.frame.pts;
+ ++frame_number_;
+ ++tot_frame_number_;
+ }
+
+ virtual void EndPassHook() {
+ for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
+ ++layer) {
+ duration_ = (last_pts_ + 1) * timebase_;
+ if (bits_total_[layer]) {
+ // Effective file datarate:
+ effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
+ }
+ }
+ }
+
+ vpx_codec_pts_t last_pts_;
+ double timebase_;
+ int tune_content_;
+ int frame_number_; // Counter for number of non-dropped/encoded frames.
+ int tot_frame_number_; // Counter for total number of input frames.
+ int64_t bits_total_[3];
+ double duration_;
+ double effective_datarate_[3];
+ int set_cpu_used_;
+ int64_t bits_in_buffer_model_;
+ vpx_codec_pts_t first_drop_;
+ int num_drops_;
+ int aq_mode_;
+ int denoiser_on_;
+ int denoiser_offon_test_;
+ int denoiser_offon_period_;
+ int frame_parallel_decoding_mode_;
+ int delta_q_uv_;
+ bool use_roi_;
+ vpx_roi_map_t roi_;
+};
+
+// Params: test mode, speed setting and index for bitrate array.
+class DatarateTestVP9RealTimeMultiBR
+ : public DatarateTestVP9,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ public:
+ DatarateTestVP9RealTimeMultiBR() : DatarateTestVP9(GET_PARAM(0)) {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_cpu_used_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Params: speed setting and index for bitrate array.
+class DatarateTestVP9LargeVBR
+ : public DatarateTestVP9,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ public:
+ DatarateTestVP9LargeVBR() : DatarateTestVP9(GET_PARAM(0)) {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_cpu_used_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for VBR mode with 0 lag.
+TEST_P(DatarateTestVP9LargeVBR, BasicRateTargetingVBRLagZero) {
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_error_resilient = 0;
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.g_lag_in_frames = 0;
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+
+ const int bitrates[2] = { 400, 800 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.36)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic rate targeting for VBR mode with non-zero lag.
+TEST_P(DatarateTestVP9LargeVBR, BasicRateTargetingVBRLagNonZero) {
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_error_resilient = 0;
+ cfg_.rc_end_usage = VPX_VBR;
+ // For non-zero lag, rate control will work (be within bounds) for
+ // real-time mode.
+ if (deadline_ == VPX_DL_REALTIME) {
+ cfg_.g_lag_in_frames = 15;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ }
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+ const int bitrates[2] = { 400, 800 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.35)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic rate targeting for VBR mode with non-zero lag, with
+// frame_parallel_decoding_mode off. This enables the adapt_coeff/mode/mv probs
+// since error_resilience is off.
+TEST_P(DatarateTestVP9LargeVBR, BasicRateTargetingVBRLagNonZeroFrameParDecOff) {
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.g_error_resilient = 0;
+ cfg_.rc_end_usage = VPX_VBR;
+ // For non-zero lag, rate control will work (be within bounds) for
+ // real-time mode.
+ if (deadline_ == VPX_DL_REALTIME) {
+ cfg_.g_lag_in_frames = 15;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ }
+
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+ const int bitrates[2] = { 400, 800 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ frame_parallel_decoding_mode_ = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.35)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic rate targeting for CBR mode.
+TEST_P(DatarateTestVP9RealTimeMultiBR, BasicRateTargeting) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ const int bitrates[4] = { 150, 350, 550, 750 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic rate targeting for CBR mode, with frame_parallel_decoding_mode
+// off( and error_resilience off).
+TEST_P(DatarateTestVP9RealTimeMultiBR, BasicRateTargetingFrameParDecOff) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 0;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ const int bitrates[4] = { 150, 350, 550, 750 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ frame_parallel_decoding_mode_ = 0;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic rate targeting for CBR.
+TEST_P(DatarateTestVP9RealTimeMultiBR, BasicRateTargeting444) {
+ ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
+
+ cfg_.g_profile = 1;
+ cfg_.g_timebase = video.timebase();
+
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ const int bitrates[4] = { 250, 450, 650, 850 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
+ effective_datarate_[0] * 0.80)
+ << " The datarate for the file exceeds the target by too much!";
+ ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
+ effective_datarate_[0] * 1.15)
+ << " The datarate for the file missed the target!"
+ << cfg_.rc_target_bitrate << " " << effective_datarate_;
+}
+
+// Check that (1) the first dropped frame gets earlier and earlier
+// as the drop frame threshold is increased, and (2) that the total number of
+// frame drops does not decrease as we increase frame drop threshold.
+// Use a lower qp-max to force some frame drops.
+TEST_P(DatarateTestVP9RealTimeMultiBR, ChangingDropFrameThresh) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_undershoot_pct = 20;
+ cfg_.rc_undershoot_pct = 20;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 50;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_target_bitrate = 200;
+ cfg_.g_lag_in_frames = 0;
+ // TODO(marpan): Investigate datarate target failures with a smaller keyframe
+ // interval (128).
+ cfg_.kf_max_dist = 9999;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+
+ const int kDropFrameThreshTestStep = 30;
+ const int bitrates[2] = { 50, 150 };
+ const int bitrate_index = GET_PARAM(2);
+ if (bitrate_index > 1) return;
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ vpx_codec_pts_t last_drop = 140;
+ int last_num_drops = 0;
+ for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
+ cfg_.rc_dropframe_thresh = i;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
+ << " The datarate for the file is greater than target by too much!";
+ ASSERT_LE(first_drop_, last_drop)
+ << " The first dropped frame for drop_thresh " << i
+ << " > first dropped frame for drop_thresh "
+ << i - kDropFrameThreshTestStep;
+ ASSERT_GE(num_drops_, last_num_drops * 0.85)
+ << " The number of dropped frames for drop_thresh " << i
+ << " < number of dropped frames for drop_thresh "
+ << i - kDropFrameThreshTestStep;
+ last_drop = first_drop_;
+ last_num_drops = num_drops_;
+ }
+} // namespace
+
+// Check basic rate targeting for 2 temporal layers.
+TEST_P(DatarateTestVP9RealTimeMultiBR, BasicRateTargeting2TemporalLayers) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 2;
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ const int bitrates[4] = { 200, 400, 600, 800 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ // 60-40 bitrate allocation for 2 temporal layers.
+ cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
+ aq_mode_ = 0;
+ if (deadline_ == VPX_DL_REALTIME) {
+ aq_mode_ = 3;
+ cfg_.g_error_resilient = 1;
+ }
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+ ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
+ << " The datarate for the file is lower than target by too much, "
+ "for layer: "
+ << j;
+ ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
+ << " The datarate for the file is greater than target by too much, "
+ "for layer: "
+ << j;
+ }
+}
+
+// Check basic rate targeting for 3 temporal layers.
+TEST_P(DatarateTestVP9RealTimeMultiBR, BasicRateTargeting3TemporalLayers) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 3;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ const int bitrates[4] = { 200, 400, 600, 800 };
+ const int bitrate_index = GET_PARAM(2);
+ cfg_.rc_target_bitrate = bitrates[bitrate_index];
+ ResetModel();
+ // 40-20-40 bitrate allocation for 3 temporal layers.
+ cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+ aq_mode_ = 0;
+ if (deadline_ == VPX_DL_REALTIME) {
+ aq_mode_ = 3;
+ cfg_.g_error_resilient = 1;
+ }
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+ // TODO(yaowu): Work out more stable rc control strategy and
+ // Adjust the thresholds to be tighter than .75.
+ ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
+ << " The datarate for the file is lower than target by too much, "
+ "for layer: "
+ << j;
+ // TODO(yaowu): Work out more stable rc control strategy and
+ // Adjust the thresholds to be tighter than 1.25.
+ ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
+ << " The datarate for the file is greater than target by too much, "
+ "for layer: "
+ << j;
+ }
+}
+
+// Params: speed setting.
+class DatarateTestVP9RealTime : public DatarateTestVP9,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ DatarateTestVP9RealTime() : DatarateTestVP9(GET_PARAM(0)) {}
+ virtual ~DatarateTestVP9RealTime() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_cpu_used_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for CBR mode, with 2 threads and dropped frames.
+TEST_P(DatarateTestVP9RealTime, BasicRateTargetingDropFramesMultiThreads) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ // Encode using multiple threads.
+ cfg_.g_threads = 2;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 200;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic rate targeting for 3 temporal layers, with frame dropping.
+// Only for one (low) bitrate with lower max_quantizer, and somewhat higher
+// frame drop threshold, to force frame dropping.
+TEST_P(DatarateTestVP9RealTime,
+ BasicRateTargeting3TemporalLayersFrameDropping) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ // Set frame drop threshold and rc_max_quantizer to force some frame drops.
+ cfg_.rc_dropframe_thresh = 20;
+ cfg_.rc_max_quantizer = 45;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 3;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+ cfg_.rc_target_bitrate = 200;
+ ResetModel();
+ // 40-20-40 bitrate allocation for 3 temporal layers.
+ cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+ aq_mode_ = 0;
+ if (deadline_ == VPX_DL_REALTIME) {
+ aq_mode_ = 3;
+ cfg_.g_error_resilient = 1;
+ }
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+ ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
+ << " The datarate for the file is lower than target by too much, "
+ "for layer: "
+ << j;
+ ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.20)
+ << " The datarate for the file is greater than target by too much, "
+ "for layer: "
+ << j;
+ // Expect some frame drops in this test: for this 200 frames test,
+ // expect at least 10% and not more than 60% drops.
+ ASSERT_GE(num_drops_, 20);
+ ASSERT_LE(num_drops_, 280);
+ }
+}
+
+// Check VP9 region of interest feature.
+TEST_P(DatarateTestVP9RealTime, RegionOfInterest) {
+ if (deadline_ != VPX_DL_REALTIME || set_cpu_used_ < 5) return;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+
+ cfg_.rc_target_bitrate = 450;
+ cfg_.g_w = 640;
+ cfg_.g_h = 480;
+
+ ResetModel();
+
+ // Set ROI parameters
+ use_roi_ = true;
+ memset(&roi_, 0, sizeof(roi_));
+
+ roi_.rows = (cfg_.g_h + 7) / 8;
+ roi_.cols = (cfg_.g_w + 7) / 8;
+
+ roi_.delta_q[1] = -20;
+ roi_.delta_lf[1] = -20;
+ memset(roi_.ref_frame, -1, sizeof(roi_.ref_frame));
+ roi_.ref_frame[1] = 1;
+
+ // Use 2 states: 1 is center square, 0 is the rest.
+ roi_.roi_map = reinterpret_cast<uint8_t *>(
+ calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map)));
+ ASSERT_NE(roi_.roi_map, nullptr);
+
+ for (unsigned int i = 0; i < roi_.rows; ++i) {
+ for (unsigned int j = 0; j < roi_.cols; ++j) {
+ if (i > (roi_.rows >> 2) && i < ((roi_.rows * 3) >> 2) &&
+ j > (roi_.cols >> 2) && j < ((roi_.cols * 3) >> 2)) {
+ roi_.roi_map[i * roi_.cols + j] = 1;
+ }
+ }
+ }
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_[0] * 0.90)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_[0] * 1.4)
+ << " The datarate for the file missed the target!";
+
+ free(roi_.roi_map);
+}
+
+// Params: speed setting, delta q UV.
+class DatarateTestVP9RealTimeDeltaQUV
+ : public DatarateTestVP9,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ public:
+ DatarateTestVP9RealTimeDeltaQUV() : DatarateTestVP9(GET_PARAM(0)) {}
+ virtual ~DatarateTestVP9RealTimeDeltaQUV() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_cpu_used_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+TEST_P(DatarateTestVP9RealTimeDeltaQUV, DeltaQUV) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+
+ cfg_.rc_target_bitrate = 450;
+ cfg_.g_w = 640;
+ cfg_.g_h = 480;
+
+ ResetModel();
+
+ delta_q_uv_ = GET_PARAM(2);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_[0] * 0.90)
+ << " The datarate for the file exceeds the target!";
+
+ ASSERT_LE(cfg_.rc_target_bitrate, effective_datarate_[0] * 1.4)
+ << " The datarate for the file missed the target!";
+}
+
+// Params: test mode, speed setting and index for bitrate array.
+class DatarateTestVP9PostEncodeDrop
+ : public DatarateTestVP9,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+ DatarateTestVP9PostEncodeDrop() : DatarateTestVP9(GET_PARAM(0)) {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ set_cpu_used_ = GET_PARAM(1);
+ ResetModel();
+ }
+};
+
+// Check basic rate targeting for CBR mode, with 2 threads and dropped frames.
+TEST_P(DatarateTestVP9PostEncodeDrop, PostEncodeDropScreenContent) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 30;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ // Encode using multiple threads.
+ cfg_.g_threads = 2;
+ cfg_.g_error_resilient = 0;
+ tune_content_ = 1;
+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ 30, 1, 0, 300);
+ cfg_.rc_target_bitrate = 300;
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+using libvpx_test::ACMRandom;
+
+class DatarateTestVP9FrameQp
+ : public DatarateTestVP9,
+ public ::testing::TestWithParam<const libvpx_test::CodecFactory *> {
+ public:
+ DatarateTestVP9FrameQp() : DatarateTestVP9(GetParam()), frame_(0) {}
+ virtual ~DatarateTestVP9FrameQp() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ ResetModel();
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ set_cpu_used_ = 7;
+ DatarateTestVP9::PreEncodeFrameHook(video, encoder);
+ frame_qp_ = static_cast<int>(rnd_.RandRange(64));
+ encoder->Control(VP9E_SET_QUANTIZER_ONE_PASS, frame_qp_);
+ frame_++;
+ }
+
+ virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+ int qp = 0;
+ vpx_svc_layer_id_t layer_id;
+ if (frame_ >= total_frame_) return;
+ encoder->Control(VP8E_GET_LAST_QUANTIZER_64, &qp);
+ ASSERT_EQ(frame_qp_, qp);
+ encoder->Control(VP9E_GET_SVC_LAYER_ID, &layer_id);
+ temporal_layer_id_ = layer_id.temporal_layer_id;
+ }
+
+ virtual void MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {
+ if (frame_ >= total_frame_) return;
+ ASSERT_TRUE(cfg_.temporal_layering_mode ==
+ VP9E_TEMPORAL_LAYERING_MODE_0212 &&
+ temporal_layer_id_ == 2);
+ }
+
+ protected:
+ int total_frame_;
+
+ private:
+ ACMRandom rnd_;
+ int frame_qp_;
+ int frame_;
+ int temporal_layer_id_;
+};
+
+TEST_P(DatarateTestVP9FrameQp, VP9SetFrameQp) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ total_frame_ = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, total_frame_);
+ ResetModel();
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(DatarateTestVP9FrameQp, VP9SetFrameQp3TemporalLayersBypass) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 3;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+ cfg_.rc_target_bitrate = 200;
+ total_frame_ = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, total_frame_);
+ ResetModel();
+ cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(DatarateTestVP9FrameQp, VP9SetFrameQp3TemporalLayersFixedMode) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_max_quantizer = 63;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+ cfg_.ss_number_layers = 1;
+ cfg_.ts_number_layers = 3;
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+
+ cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_0212;
+ cfg_.rc_target_bitrate = 200;
+ cfg_.g_error_resilient = 1;
+ total_frame_ = 400;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, total_frame_);
+ ResetModel();
+ cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+ cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+#if CONFIG_VP9_TEMPORAL_DENOISING
+// Params: speed setting.
+class DatarateTestVP9RealTimeDenoiser : public DatarateTestVP9RealTime {
+ public:
+ virtual ~DatarateTestVP9RealTimeDenoiser() {}
+};
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is on.
+TEST_P(DatarateTestVP9RealTimeDenoiser, LowNoise) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+
+ // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
+ // there is only one denoiser mode: denoiserYonly(which is 1),
+ // but may add more modes in the future.
+ cfg_.rc_target_bitrate = 400;
+ ResetModel();
+ // Turn on the denoiser.
+ denoiser_on_ = 1;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is on,
+// for clip with high noise level. Use 2 threads.
+TEST_P(DatarateTestVP9RealTimeDenoiser, HighNoise) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_threads = 2;
+
+ ::libvpx_test::Y4mVideoSource video("noisy_clip_640_360.y4m", 0, 200);
+
+ // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
+ // there is only one denoiser mode: kDenoiserOnYOnly(which is 1),
+ // but may add more modes in the future.
+ cfg_.rc_target_bitrate = 1000;
+ ResetModel();
+ // Turn on the denoiser.
+ denoiser_on_ = 1;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is on,
+// for 1280x720 clip with 4 threads.
+TEST_P(DatarateTestVP9RealTimeDenoiser, 4threads) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_threads = 4;
+
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 300);
+
+ // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
+ // there is only one denoiser mode: denoiserYonly(which is 1),
+ // but may add more modes in the future.
+ cfg_.rc_target_bitrate = 1000;
+ ResetModel();
+ // Turn on the denoiser.
+ denoiser_on_ = 1;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.29)
+ << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is off
+// and on.
+TEST_P(DatarateTestVP9RealTimeDenoiser, DenoiserOffOn) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 1;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+
+ // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
+ // there is only one denoiser mode: denoiserYonly(which is 1),
+ // but may add more modes in the future.
+ cfg_.rc_target_bitrate = 400;
+ ResetModel();
+ // The denoiser is off by default.
+ denoiser_on_ = 0;
+ // Set the offon test flag.
+ denoiser_offon_test_ = 1;
+ denoiser_offon_period_ = 100;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ << " The datarate for the file is lower than target by too much!";
+ ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ << " The datarate for the file is greater than target by too much!";
+}
+#endif // CONFIG_VP9_TEMPORAL_DENOISING
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9RealTimeMultiBR,
+ ::testing::Range(5, 10), ::testing::Range(0, 4));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9LargeVBR, ::testing::Range(5, 9),
+ ::testing::Range(0, 2));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9RealTime, ::testing::Range(5, 10));
+
+#if CONFIG_VP9
+INSTANTIATE_TEST_SUITE_P(
+ VP9, DatarateTestVP9FrameQp,
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
+#endif
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9RealTimeDeltaQUV,
+ ::testing::Range(5, 10),
+ ::testing::Values(-5, -10, -15));
+
+VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9PostEncodeDrop,
+ ::testing::Range(5, 6));
+
+#if CONFIG_VP9_TEMPORAL_DENOISING
+VP9_INSTANTIATE_TEST_SUITE(DatarateTestVP9RealTimeDenoiser,
+ ::testing::Range(5, 10));
+#endif
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_decrypt_test.cc b/media/libvpx/libvpx/test/vp9_decrypt_test.cc
new file mode 100644
index 0000000000..1874d23117
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_decrypt_test.cc
@@ -0,0 +1,69 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/ivf_video_source.h"
+
+namespace {
+// In a real use the 'decrypt_state' parameter will be a pointer to a struct
+// with whatever internal state the decryptor uses. For testing we'll just
+// xor with a constant key, and decrypt_state will point to the start of
+// the original buffer.
+const uint8_t test_key[16] = { 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
+ 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0 };
+
+void encrypt_buffer(const uint8_t *src, uint8_t *dst, size_t size,
+ ptrdiff_t offset) {
+ for (size_t i = 0; i < size; ++i) {
+ dst[i] = src[i] ^ test_key[(offset + i) & 15];
+ }
+}
+
+void test_decrypt_cb(void *decrypt_state, const uint8_t *input, uint8_t *output,
+ int count) {
+ encrypt_buffer(input, output, count,
+ input - reinterpret_cast<uint8_t *>(decrypt_state));
+}
+
+} // namespace
+
+namespace libvpx_test {
+
+TEST(TestDecrypt, DecryptWorksVp9) {
+ libvpx_test::IVFVideoSource video("vp90-2-05-resize.ivf");
+ video.Init();
+
+ vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+ VP9Decoder decoder(dec_cfg, 0);
+
+ video.Begin();
+
+ // no decryption
+ vpx_codec_err_t res = decoder.DecodeFrame(video.cxdata(), video.frame_size());
+ ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+
+ // decrypt frame
+ video.Next();
+
+ std::vector<uint8_t> encrypted(video.frame_size());
+ encrypt_buffer(video.cxdata(), &encrypted[0], video.frame_size(), 0);
+ vpx_decrypt_init di = { test_decrypt_cb, &encrypted[0] };
+ decoder.Control(VPXD_SET_DECRYPTOR, &di);
+
+ res = decoder.DecodeFrame(&encrypted[0], encrypted.size());
+ ASSERT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+}
+
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/vp9_denoiser_test.cc b/media/libvpx/libvpx/test/vp9_denoiser_test.cc
new file mode 100644
index 0000000000..d884b7eb92
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_denoiser_test.cc
@@ -0,0 +1,136 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+
+#include "vpx_scale/yv12config.h"
+#include "vpx/vpx_integer.h"
+#include "vp9/common/vp9_reconinter.h"
+#include "vp9/encoder/vp9_context_tree.h"
+#include "vp9/encoder/vp9_denoiser.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+const int kNumPixels = 64 * 64;
+
+typedef int (*Vp9DenoiserFilterFunc)(const uint8_t *sig, int sig_stride,
+ const uint8_t *mc_avg, int mc_avg_stride,
+ uint8_t *avg, int avg_stride,
+ int increase_denoising, BLOCK_SIZE bs,
+ int motion_magnitude);
+typedef std::tuple<Vp9DenoiserFilterFunc, BLOCK_SIZE> VP9DenoiserTestParam;
+
+class VP9DenoiserTest
+ : public ::testing::Test,
+ public ::testing::WithParamInterface<VP9DenoiserTestParam> {
+ public:
+ virtual ~VP9DenoiserTest() {}
+
+ virtual void SetUp() { bs_ = GET_PARAM(1); }
+
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ BLOCK_SIZE bs_;
+};
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VP9DenoiserTest);
+
+TEST_P(VP9DenoiserTest, BitexactCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int count_test_block = 4000;
+
+ // Allocate the space for input and output,
+ // where sig_block is the block to be denoised,
+ // mc_avg_block is the denoised reference block,
+ // avg_block_c is the denoised result from C code,
+ // avg_block_sse2 is the denoised result from SSE2 code.
+ DECLARE_ALIGNED(16, uint8_t, sig_block[kNumPixels]);
+ DECLARE_ALIGNED(16, uint8_t, mc_avg_block[kNumPixels]);
+ DECLARE_ALIGNED(16, uint8_t, avg_block_c[kNumPixels]);
+ DECLARE_ALIGNED(16, uint8_t, avg_block_sse2[kNumPixels]);
+
+ for (int i = 0; i < count_test_block; ++i) {
+ // Generate random motion magnitude, 20% of which exceed the threshold.
+ const int motion_magnitude_random =
+ rnd.Rand8() % static_cast<int>(MOTION_MAGNITUDE_THRESHOLD * 1.2);
+
+ // Initialize a test block with random number in range [0, 255].
+ for (int j = 0; j < kNumPixels; ++j) {
+ int temp = 0;
+ sig_block[j] = rnd.Rand8();
+ // The pixels in mc_avg_block are generated by adding a random
+ // number in range [-19, 19] to corresponding pixels in sig_block.
+ temp =
+ sig_block[j] + ((rnd.Rand8() % 2 == 0) ? -1 : 1) * (rnd.Rand8() % 20);
+ // Clip.
+ mc_avg_block[j] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
+ }
+
+ ASM_REGISTER_STATE_CHECK(vp9_denoiser_filter_c(sig_block, 64, mc_avg_block,
+ 64, avg_block_c, 64, 0, bs_,
+ motion_magnitude_random));
+
+ ASM_REGISTER_STATE_CHECK(GET_PARAM(0)(sig_block, 64, mc_avg_block, 64,
+ avg_block_sse2, 64, 0, bs_,
+ motion_magnitude_random));
+
+ // Test bitexactness.
+ for (int h = 0; h < (4 << b_height_log2_lookup[bs_]); ++h) {
+ for (int w = 0; w < (4 << b_width_log2_lookup[bs_]); ++w) {
+ EXPECT_EQ(avg_block_c[h * 64 + w], avg_block_sse2[h * 64 + w]);
+ }
+ }
+ }
+}
+
+using std::make_tuple;
+
+// Test for all block size.
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VP9DenoiserTest,
+ ::testing::Values(make_tuple(&vp9_denoiser_filter_sse2, BLOCK_8X8),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_8X16),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_16X8),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_16X16),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_16X32),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_32X16),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_32X32),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_32X64),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_64X32),
+ make_tuple(&vp9_denoiser_filter_sse2, BLOCK_64X64)));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VP9DenoiserTest,
+ ::testing::Values(make_tuple(&vp9_denoiser_filter_neon, BLOCK_8X8),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_8X16),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_16X8),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_16X16),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_16X32),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_32X16),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_32X32),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_32X64),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_64X32),
+ make_tuple(&vp9_denoiser_filter_neon, BLOCK_64X64)));
+#endif
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_encoder_parms_get_to_decoder.cc b/media/libvpx/libvpx/test/vp9_encoder_parms_get_to_decoder.cc
new file mode 100644
index 0000000000..ce2198c592
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_encoder_parms_get_to_decoder.cc
@@ -0,0 +1,153 @@
+/*
+ * 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 <memory>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vp9/vp9_dx_iface.h"
+
+namespace {
+
+const int kCpuUsed = 2;
+
+struct EncodePerfTestVideo {
+ const char *name;
+ uint32_t width;
+ uint32_t height;
+ uint32_t bitrate;
+ int frames;
+};
+
+const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
+ { "niklas_1280_720_30.y4m", 1280, 720, 600, 10 },
+};
+
+struct EncodeParameters {
+ int32_t tile_rows;
+ int32_t tile_cols;
+ int32_t lossless;
+ int32_t error_resilient;
+ int32_t frame_parallel;
+ vpx_color_range_t color_range;
+ vpx_color_space_t cs;
+ int render_size[2];
+ // TODO(JBB): quantizers / bitrate
+};
+
+const EncodeParameters kVP9EncodeParameterSet[] = {
+ { 0, 0, 0, 1, 0, VPX_CR_STUDIO_RANGE, VPX_CS_BT_601, { 0, 0 } },
+ { 0, 0, 0, 0, 0, VPX_CR_FULL_RANGE, VPX_CS_BT_709, { 0, 0 } },
+ { 0, 0, 1, 0, 0, VPX_CR_FULL_RANGE, VPX_CS_BT_2020, { 0, 0 } },
+ { 0, 2, 0, 0, 1, VPX_CR_STUDIO_RANGE, VPX_CS_UNKNOWN, { 640, 480 } },
+ // TODO(JBB): Test profiles (requires more work).
+};
+
+class VpxEncoderParmsGetToDecoder
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<EncodeParameters,
+ EncodePerfTestVideo> {
+ protected:
+ VpxEncoderParmsGetToDecoder()
+ : EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {}
+
+ virtual ~VpxEncoderParmsGetToDecoder() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ cfg_.g_lag_in_frames = 25;
+ cfg_.g_error_resilient = encode_parms.error_resilient;
+ dec_cfg_.threads = 4;
+ test_video_ = GET_PARAM(2);
+ cfg_.rc_target_bitrate = test_video_.bitrate;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_COLOR_SPACE, encode_parms.cs);
+ encoder->Control(VP9E_SET_COLOR_RANGE, encode_parms.color_range);
+ encoder->Control(VP9E_SET_LOSSLESS, encode_parms.lossless);
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
+ encode_parms.frame_parallel);
+ encoder->Control(VP9E_SET_TILE_ROWS, encode_parms.tile_rows);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, encode_parms.tile_cols);
+ encoder->Control(VP8E_SET_CPUUSED, kCpuUsed);
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) {
+ encoder->Control(VP9E_SET_RENDER_SIZE, encode_parms.render_size);
+ }
+ }
+ }
+
+ virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+ const libvpx_test::VideoSource & /*video*/,
+ libvpx_test::Decoder *decoder) {
+ vpx_codec_ctx_t *const vp9_decoder = decoder->GetDecoder();
+ vpx_codec_alg_priv_t *const priv =
+ reinterpret_cast<vpx_codec_alg_priv_t *>(vp9_decoder->priv);
+ VP9_COMMON *const common = &priv->pbi->common;
+
+ if (encode_parms.lossless) {
+ EXPECT_EQ(0, common->base_qindex);
+ EXPECT_EQ(0, common->y_dc_delta_q);
+ EXPECT_EQ(0, common->uv_dc_delta_q);
+ EXPECT_EQ(0, common->uv_ac_delta_q);
+ EXPECT_EQ(ONLY_4X4, common->tx_mode);
+ }
+ EXPECT_EQ(encode_parms.error_resilient, common->error_resilient_mode);
+ if (encode_parms.error_resilient) {
+ EXPECT_EQ(1, common->frame_parallel_decoding_mode);
+ EXPECT_EQ(0, common->use_prev_frame_mvs);
+ } else {
+ EXPECT_EQ(encode_parms.frame_parallel,
+ common->frame_parallel_decoding_mode);
+ }
+ EXPECT_EQ(encode_parms.color_range, common->color_range);
+ EXPECT_EQ(encode_parms.cs, common->color_space);
+ if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) {
+ EXPECT_EQ(encode_parms.render_size[0], common->render_width);
+ EXPECT_EQ(encode_parms.render_size[1], common->render_height);
+ }
+ EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols);
+ EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows);
+
+ EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+ return VPX_CODEC_OK == res_dec;
+ }
+
+ EncodePerfTestVideo test_video_;
+
+ private:
+ EncodeParameters encode_parms;
+};
+
+TEST_P(VpxEncoderParmsGetToDecoder, BitstreamParms) {
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video(
+ new libvpx_test::Y4mVideoSource(test_video_.name, 0, test_video_.frames));
+ ASSERT_NE(video.get(), nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(VpxEncoderParmsGetToDecoder,
+ ::testing::ValuesIn(kVP9EncodeParameterSet),
+ ::testing::ValuesIn(kVP9EncodePerfTestVectors));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_end_to_end_test.cc b/media/libvpx/libvpx/test/vp9_end_to_end_test.cc
new file mode 100644
index 0000000000..7a85db26a4
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_end_to_end_test.cc
@@ -0,0 +1,354 @@
+/*
+ * 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 "memory"
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "test/yuv_video_source.h"
+
+namespace {
+
+const unsigned int kWidth = 160;
+const unsigned int kHeight = 90;
+const unsigned int kFramerate = 50;
+const unsigned int kFrames = 20;
+const int kBitrate = 500;
+// List of psnr thresholds for speed settings 0-7 and 5 encoding modes
+const double kPsnrThreshold[][5] = {
+ { 36.0, 37.0, 37.0, 37.0, 37.0 }, { 35.0, 36.0, 36.0, 36.0, 36.0 },
+ { 34.0, 35.0, 35.0, 35.0, 35.0 }, { 33.0, 34.0, 34.0, 34.0, 34.0 },
+ { 32.0, 33.0, 33.0, 33.0, 33.0 }, { 28.0, 32.0, 32.0, 32.0, 32.0 },
+ { 28.4, 31.0, 31.0, 31.0, 31.0 }, { 27.5, 30.0, 30.0, 30.0, 30.0 },
+};
+
+typedef struct {
+ const char *filename;
+ unsigned int input_bit_depth;
+ vpx_img_fmt fmt;
+ vpx_bit_depth_t bit_depth;
+ unsigned int profile;
+} TestVideoParam;
+
+const TestVideoParam kTestVectors[] = {
+ { "park_joy_90p_8_420.y4m", 8, VPX_IMG_FMT_I420, VPX_BITS_8, 0 },
+ { "park_joy_90p_8_422.y4m", 8, VPX_IMG_FMT_I422, VPX_BITS_8, 1 },
+ { "park_joy_90p_8_444.y4m", 8, VPX_IMG_FMT_I444, VPX_BITS_8, 1 },
+ { "park_joy_90p_8_440.yuv", 8, VPX_IMG_FMT_I440, VPX_BITS_8, 1 },
+#if CONFIG_VP9_HIGHBITDEPTH
+ { "park_joy_90p_10_420_20f.y4m", 10, VPX_IMG_FMT_I42016, VPX_BITS_10, 2 },
+ { "park_joy_90p_10_422_20f.y4m", 10, VPX_IMG_FMT_I42216, VPX_BITS_10, 3 },
+ { "park_joy_90p_10_444_20f.y4m", 10, VPX_IMG_FMT_I44416, VPX_BITS_10, 3 },
+ { "park_joy_90p_10_440.yuv", 10, VPX_IMG_FMT_I44016, VPX_BITS_10, 3 },
+ { "park_joy_90p_12_420_20f.y4m", 12, VPX_IMG_FMT_I42016, VPX_BITS_12, 2 },
+ { "park_joy_90p_12_422_20f.y4m", 12, VPX_IMG_FMT_I42216, VPX_BITS_12, 3 },
+ { "park_joy_90p_12_444_20f.y4m", 12, VPX_IMG_FMT_I44416, VPX_BITS_12, 3 },
+ { "park_joy_90p_12_440.yuv", 12, VPX_IMG_FMT_I44016, VPX_BITS_12, 3 },
+#endif // CONFIG_VP9_HIGHBITDEPTH
+};
+
+const TestVideoParam kTestVectorsNv12[] = {
+ { "hantro_collage_w352h288_nv12.yuv", 8, VPX_IMG_FMT_NV12, VPX_BITS_8, 0 },
+};
+
+// Encoding modes tested
+const libvpx_test::TestMode kEncodingModeVectors[] = {
+ ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime
+};
+
+// Speed settings tested
+const int kCpuUsedVectors[] = { 1, 2, 3, 5, 6, 7 };
+
+int is_extension_y4m(const char *filename) {
+ const char *dot = strrchr(filename, '.');
+ if (!dot || dot == filename) {
+ return 0;
+ } else {
+ return !strcmp(dot, ".y4m");
+ }
+}
+
+class EndToEndTestAdaptiveRDThresh
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<int, int> {
+ protected:
+ EndToEndTestAdaptiveRDThresh()
+ : EncoderTest(GET_PARAM(0)), cpu_used_start_(GET_PARAM(1)),
+ cpu_used_end_(GET_PARAM(2)) {}
+
+ virtual ~EndToEndTestAdaptiveRDThresh() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ dec_cfg_.threads = 4;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_start_);
+ encoder->Control(VP9E_SET_ROW_MT, 1);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
+ }
+ if (video->frame() == 100)
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_end_);
+ }
+
+ private:
+ int cpu_used_start_;
+ int cpu_used_end_;
+};
+
+class EndToEndTestLarge
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode,
+ TestVideoParam, int> {
+ protected:
+ EndToEndTestLarge()
+ : EncoderTest(GET_PARAM(0)), test_video_param_(GET_PARAM(2)),
+ cpu_used_(GET_PARAM(3)), psnr_(0.0), nframes_(0),
+ encoding_mode_(GET_PARAM(1)) {
+ cyclic_refresh_ = 0;
+ denoiser_on_ = 0;
+ }
+
+ virtual ~EndToEndTestLarge() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ cfg_.g_lag_in_frames = 5;
+ cfg_.rc_end_usage = VPX_VBR;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ }
+ dec_cfg_.threads = 4;
+ }
+
+ virtual void BeginPassHook(unsigned int) {
+ psnr_ = 0.0;
+ nframes_ = 0;
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ psnr_ += pkt->data.psnr.psnr[0];
+ nframes_++;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
+ encoder->Control(VP9E_SET_TILE_COLUMNS, 4);
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ } else {
+ encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
+ encoder->Control(VP9E_SET_AQ_MODE, cyclic_refresh_);
+ }
+ }
+ }
+
+ double GetAveragePsnr() const {
+ if (nframes_) return psnr_ / nframes_;
+ return 0.0;
+ }
+
+ double GetPsnrThreshold() {
+ return kPsnrThreshold[cpu_used_][encoding_mode_];
+ }
+
+ TestVideoParam test_video_param_;
+ int cpu_used_;
+ int cyclic_refresh_;
+ int denoiser_on_;
+
+ private:
+ double psnr_;
+ unsigned int nframes_;
+ libvpx_test::TestMode encoding_mode_;
+};
+
+#if CONFIG_VP9_DECODER
+// The test parameters control VP9D_SET_LOOP_FILTER_OPT and the number of
+// decoder threads.
+class EndToEndTestLoopFilterThreading
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<bool, int> {
+ protected:
+ EndToEndTestLoopFilterThreading()
+ : EncoderTest(GET_PARAM(0)), use_loop_filter_opt_(GET_PARAM(1)) {}
+
+ virtual ~EndToEndTestLoopFilterThreading() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ cfg_.g_threads = 2;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_target_bitrate = 500;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.kf_min_dist = 1;
+ cfg_.kf_max_dist = 1;
+ dec_cfg_.threads = GET_PARAM(2);
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, 8);
+ }
+ encoder->Control(VP9E_SET_TILE_COLUMNS, 4 - video->frame() % 5);
+ }
+
+ virtual void PreDecodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Decoder *decoder) {
+ if (video->frame() == 0) {
+ decoder->Control(VP9D_SET_LOOP_FILTER_OPT, use_loop_filter_opt_ ? 1 : 0);
+ }
+ }
+
+ private:
+ const bool use_loop_filter_opt_;
+};
+#endif // CONFIG_VP9_DECODER
+
+class EndToEndNV12 : public EndToEndTestLarge {};
+
+TEST_P(EndToEndNV12, EndtoEndNV12Test) {
+ cfg_.rc_target_bitrate = kBitrate;
+ cfg_.g_error_resilient = 0;
+ cfg_.g_profile = test_video_param_.profile;
+ cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
+ cfg_.g_bit_depth = test_video_param_.bit_depth;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+
+ video.reset(new libvpx_test::YUVVideoSource(test_video_param_.filename,
+ test_video_param_.fmt, 352, 288,
+ 30, 1, 0, 100));
+ ASSERT_NE(video.get(), nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+TEST_P(EndToEndTestLarge, EndtoEndPSNRTest) {
+ cfg_.rc_target_bitrate = kBitrate;
+ cfg_.g_error_resilient = 0;
+ cfg_.g_profile = test_video_param_.profile;
+ cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
+ cfg_.g_bit_depth = test_video_param_.bit_depth;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ if (is_extension_y4m(test_video_param_.filename)) {
+ video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
+ kFrames));
+ } else {
+ video.reset(new libvpx_test::YUVVideoSource(
+ test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
+ kFramerate, 1, 0, kFrames));
+ }
+ ASSERT_NE(video.get(), nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ const double psnr = GetAveragePsnr();
+ EXPECT_GT(psnr, GetPsnrThreshold());
+}
+
+TEST_P(EndToEndTestLarge, EndtoEndPSNRDenoiserAQTest) {
+ cfg_.rc_target_bitrate = kBitrate;
+ cfg_.g_error_resilient = 0;
+ cfg_.g_profile = test_video_param_.profile;
+ cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
+ cfg_.g_bit_depth = test_video_param_.bit_depth;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ cyclic_refresh_ = 3;
+ denoiser_on_ = 1;
+ if (cfg_.g_bit_depth > 8) init_flags_ |= VPX_CODEC_USE_HIGHBITDEPTH;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ if (is_extension_y4m(test_video_param_.filename)) {
+ video.reset(new libvpx_test::Y4mVideoSource(test_video_param_.filename, 0,
+ kFrames));
+ } else {
+ video.reset(new libvpx_test::YUVVideoSource(
+ test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
+ kFramerate, 1, 0, kFrames));
+ }
+ ASSERT_NE(video.get(), nullptr);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+ const double psnr = GetAveragePsnr();
+ EXPECT_GT(psnr, GetPsnrThreshold());
+}
+
+TEST_P(EndToEndTestAdaptiveRDThresh, EndtoEndAdaptiveRDThreshRowMT) {
+ cfg_.rc_target_bitrate = kBitrate;
+ cfg_.g_error_resilient = 0;
+ cfg_.g_threads = 2;
+ ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1,
+ 0, 400);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+#if CONFIG_VP9_DECODER
+TEST_P(EndToEndTestLoopFilterThreading, TileCountChange) {
+ ::libvpx_test::RandomVideoSource video;
+ video.SetSize(4096, 2160);
+ video.set_limit(10);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+#endif // CONFIG_VP9_DECODER
+
+VP9_INSTANTIATE_TEST_SUITE(EndToEndTestLarge,
+ ::testing::ValuesIn(kEncodingModeVectors),
+ ::testing::ValuesIn(kTestVectors),
+ ::testing::ValuesIn(kCpuUsedVectors));
+
+VP9_INSTANTIATE_TEST_SUITE(EndToEndNV12,
+ ::testing::Values(::libvpx_test::kRealTime),
+ ::testing::ValuesIn(kTestVectorsNv12),
+ ::testing::Values(6, 7, 8));
+
+VP9_INSTANTIATE_TEST_SUITE(EndToEndTestAdaptiveRDThresh,
+ ::testing::Values(5, 6, 7), ::testing::Values(8, 9));
+
+#if CONFIG_VP9_DECODER
+VP9_INSTANTIATE_TEST_SUITE(EndToEndTestLoopFilterThreading, ::testing::Bool(),
+ ::testing::Range(2, 6));
+#endif // CONFIG_VP9_DECODER
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_ethread_test.cc b/media/libvpx/libvpx/test/vp9_ethread_test.cc
new file mode 100644
index 0000000000..238366cb60
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_ethread_test.cc
@@ -0,0 +1,429 @@
+/*
+ * 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 <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vp9/encoder/vp9_firstpass.h"
+
+namespace {
+// FIRSTPASS_STATS struct:
+// {
+// 25 double members;
+// 1 int64_t member;
+// }
+// Whenever FIRSTPASS_STATS struct is modified, the following constants need to
+// be revisited.
+const int kDbl = 25;
+const int kInt = 1;
+const size_t kFirstPassStatsSz = kDbl * sizeof(double) + kInt * sizeof(int64_t);
+
+class VPxFirstPassEncoderThreadTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+ VPxFirstPassEncoderThreadTest()
+ : EncoderTest(GET_PARAM(0)), encoder_initialized_(false), tiles_(0),
+ encoding_mode_(GET_PARAM(1)), set_cpu_used_(GET_PARAM(2)) {
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ row_mt_mode_ = 1;
+ first_pass_only_ = true;
+ firstpass_stats_.buf = nullptr;
+ firstpass_stats_.sz = 0;
+ }
+ virtual ~VPxFirstPassEncoderThreadTest() { free(firstpass_stats_.buf); }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_min_quantizer = 0;
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ encoder_initialized_ = false;
+ abort_ = false;
+ }
+
+ virtual void EndPassHook() {
+ // For first pass stats test, only run first pass encoder.
+ if (first_pass_only_ && cfg_.g_pass == VPX_RC_FIRST_PASS)
+ abort_ |= first_pass_only_;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource * /*video*/,
+ ::libvpx_test::Encoder *encoder) {
+ if (!encoder_initialized_) {
+ // Encode in 2-pass mode.
+ encoder->Control(VP9E_SET_TILE_COLUMNS, tiles_);
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 0);
+
+ if (encoding_mode_ == ::libvpx_test::kTwoPassGood)
+ encoder->Control(VP9E_SET_ROW_MT, row_mt_mode_);
+
+ encoder_initialized_ = true;
+ }
+ }
+
+ virtual void StatsPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ const uint8_t *const pkt_buf =
+ reinterpret_cast<uint8_t *>(pkt->data.twopass_stats.buf);
+ const size_t pkt_size = pkt->data.twopass_stats.sz;
+
+ // First pass stats size equals sizeof(FIRSTPASS_STATS)
+ EXPECT_EQ(pkt_size, kFirstPassStatsSz)
+ << "Error: First pass stats size doesn't equal kFirstPassStatsSz";
+
+ firstpass_stats_.buf =
+ realloc(firstpass_stats_.buf, firstpass_stats_.sz + pkt_size);
+ ASSERT_NE(firstpass_stats_.buf, nullptr);
+ memcpy((uint8_t *)firstpass_stats_.buf + firstpass_stats_.sz, pkt_buf,
+ pkt_size);
+ firstpass_stats_.sz += pkt_size;
+ }
+
+ bool encoder_initialized_;
+ int tiles_;
+ ::libvpx_test::TestMode encoding_mode_;
+ int set_cpu_used_;
+ int row_mt_mode_;
+ bool first_pass_only_;
+ vpx_fixed_buf_t firstpass_stats_;
+};
+
+static void compare_fp_stats(vpx_fixed_buf_t *fp_stats, double factor) {
+ // fp_stats consists of 2 set of first pass encoding stats. These 2 set of
+ // stats are compared to check if the stats match or at least are very close.
+ FIRSTPASS_STATS *stats1 = reinterpret_cast<FIRSTPASS_STATS *>(fp_stats->buf);
+ int nframes_ = (int)(fp_stats->sz / sizeof(FIRSTPASS_STATS));
+ FIRSTPASS_STATS *stats2 = stats1 + nframes_ / 2;
+ int i, j;
+
+ // The total stats are also output and included in the first pass stats. Here
+ // ignore that in the comparison.
+ for (i = 0; i < (nframes_ / 2 - 1); ++i) {
+ const double *frame_stats1 = reinterpret_cast<double *>(stats1);
+ const double *frame_stats2 = reinterpret_cast<double *>(stats2);
+
+ for (j = 0; j < kDbl; ++j) {
+ ASSERT_LE(fabs(*frame_stats1 - *frame_stats2),
+ fabs(*frame_stats1) / factor)
+ << "First failure @ frame #" << i << " stat #" << j << " ("
+ << *frame_stats1 << " vs. " << *frame_stats2 << ")";
+ frame_stats1++;
+ frame_stats2++;
+ }
+
+ stats1++;
+ stats2++;
+ }
+
+ // Reset firstpass_stats_ to 0.
+ memset((uint8_t *)fp_stats->buf, 0, fp_stats->sz);
+ fp_stats->sz = 0;
+}
+
+static void compare_fp_stats_md5(vpx_fixed_buf_t *fp_stats) {
+ // fp_stats consists of 2 set of first pass encoding stats. These 2 set of
+ // stats are compared to check if the stats match.
+ uint8_t *stats1 = reinterpret_cast<uint8_t *>(fp_stats->buf);
+ uint8_t *stats2 = stats1 + fp_stats->sz / 2;
+ ::libvpx_test::MD5 md5_row_mt_0, md5_row_mt_1;
+
+ md5_row_mt_0.Add(stats1, fp_stats->sz / 2);
+ const char *md5_row_mt_0_str = md5_row_mt_0.Get();
+
+ md5_row_mt_1.Add(stats2, fp_stats->sz / 2);
+ const char *md5_row_mt_1_str = md5_row_mt_1.Get();
+
+ // Check md5 match.
+ ASSERT_STREQ(md5_row_mt_0_str, md5_row_mt_1_str)
+ << "MD5 checksums don't match";
+
+ // Reset firstpass_stats_ to 0.
+ memset((uint8_t *)fp_stats->buf, 0, fp_stats->sz);
+ fp_stats->sz = 0;
+}
+
+TEST_P(VPxFirstPassEncoderThreadTest, FirstPassStatsTest) {
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 0, 60);
+
+ first_pass_only_ = true;
+ cfg_.rc_target_bitrate = 1000;
+
+ // Test row_mt_mode: 0 vs 1 at single thread case(threads = 1, tiles_ = 0)
+ tiles_ = 0;
+ cfg_.g_threads = 1;
+
+ row_mt_mode_ = 0;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ row_mt_mode_ = 1;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ // Compare to check if using or not using row-mt generates close stats.
+ ASSERT_NO_FATAL_FAILURE(compare_fp_stats(&firstpass_stats_, 1000.0));
+
+ // Test single thread vs multiple threads
+ row_mt_mode_ = 1;
+ tiles_ = 0;
+
+ cfg_.g_threads = 1;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ cfg_.g_threads = 4;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ // Compare to check if single-thread and multi-thread stats are close enough.
+ ASSERT_NO_FATAL_FAILURE(compare_fp_stats(&firstpass_stats_, 1000.0));
+
+ // Bit exact test in row_mt mode.
+ // When row_mt_mode_=1 and using >1 threads, the encoder generates bit exact
+ // result.
+ row_mt_mode_ = 1;
+ tiles_ = 2;
+
+ cfg_.g_threads = 2;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ cfg_.g_threads = 8;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+ // Compare to check if stats match with row-mt=0/1.
+ compare_fp_stats_md5(&firstpass_stats_);
+}
+
+class VPxEncoderThreadTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith4Params<libvpx_test::TestMode, int,
+ int, int> {
+ protected:
+ VPxEncoderThreadTest()
+ : EncoderTest(GET_PARAM(0)), encoder_initialized_(false),
+ tiles_(GET_PARAM(3)), threads_(GET_PARAM(4)),
+ encoding_mode_(GET_PARAM(1)), set_cpu_used_(GET_PARAM(2)) {
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ md5_.clear();
+ row_mt_mode_ = 1;
+ psnr_ = 0.0;
+ nframes_ = 0;
+ }
+ virtual ~VPxEncoderThreadTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ cfg_.rc_end_usage = VPX_VBR;
+ cfg_.rc_2pass_vbr_minsection_pct = 5;
+ cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_error_resilient = 1;
+ }
+ cfg_.rc_max_quantizer = 56;
+ cfg_.rc_min_quantizer = 0;
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ encoder_initialized_ = false;
+ psnr_ = 0.0;
+ nframes_ = 0;
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource * /*video*/,
+ ::libvpx_test::Encoder *encoder) {
+ if (!encoder_initialized_) {
+ // Encode 4 column tiles.
+ encoder->Control(VP9E_SET_TILE_COLUMNS, tiles_);
+ encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 0);
+ } else {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 0);
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ }
+ encoder->Control(VP9E_SET_ROW_MT, row_mt_mode_);
+
+ encoder_initialized_ = true;
+ }
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ psnr_ += pkt->data.psnr.psnr[0];
+ nframes_++;
+ }
+
+ virtual void DecompressedFrameHook(const vpx_image_t &img,
+ vpx_codec_pts_t /*pts*/) {
+ ::libvpx_test::MD5 md5_res;
+ md5_res.Add(&img);
+ md5_.push_back(md5_res.Get());
+ }
+
+ virtual bool HandleDecodeResult(const vpx_codec_err_t res,
+ const libvpx_test::VideoSource & /*video*/,
+ libvpx_test::Decoder * /*decoder*/) {
+ if (res != VPX_CODEC_OK) {
+ EXPECT_EQ(VPX_CODEC_OK, res);
+ return false;
+ }
+
+ return true;
+ }
+
+ double GetAveragePsnr() const { return nframes_ ? (psnr_ / nframes_) : 0.0; }
+
+ bool encoder_initialized_;
+ int tiles_;
+ int threads_;
+ ::libvpx_test::TestMode encoding_mode_;
+ int set_cpu_used_;
+ int row_mt_mode_;
+ double psnr_;
+ unsigned int nframes_;
+ std::vector<std::string> md5_;
+};
+
+TEST_P(VPxEncoderThreadTest, EncoderResultTest) {
+ ::libvpx_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 15, 20);
+ cfg_.rc_target_bitrate = 1000;
+
+ // Part 1: Bit exact test for row_mt_mode_ = 0.
+ // This part keeps original unit tests done before row-mt code is checked in.
+ row_mt_mode_ = 0;
+
+ // Encode using single thread.
+ cfg_.g_threads = 1;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const std::vector<std::string> single_thr_md5 = md5_;
+ md5_.clear();
+
+ // Encode using multiple threads.
+ cfg_.g_threads = threads_;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const std::vector<std::string> multi_thr_md5 = md5_;
+ md5_.clear();
+
+ // Compare to check if two vectors are equal.
+ ASSERT_EQ(single_thr_md5, multi_thr_md5);
+
+ // Part 2: row_mt_mode_ = 0 vs row_mt_mode_ = 1 single thread bit exact test.
+ row_mt_mode_ = 1;
+
+ // Encode using single thread
+ cfg_.g_threads = 1;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ std::vector<std::string> row_mt_single_thr_md5 = md5_;
+ md5_.clear();
+
+ ASSERT_EQ(single_thr_md5, row_mt_single_thr_md5);
+
+ // Part 3: Bit exact test with row-mt on
+ // When row_mt_mode_=1 and using >1 threads, the encoder generates bit exact
+ // result.
+ row_mt_mode_ = 1;
+ row_mt_single_thr_md5.clear();
+
+ // Encode using 2 threads.
+ cfg_.g_threads = 2;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ row_mt_single_thr_md5 = md5_;
+ md5_.clear();
+
+ // Encode using multiple threads.
+ cfg_.g_threads = threads_;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const std::vector<std::string> row_mt_multi_thr_md5 = md5_;
+ md5_.clear();
+
+ // Compare to check if two vectors are equal.
+ ASSERT_EQ(row_mt_single_thr_md5, row_mt_multi_thr_md5);
+
+ // Part 4: PSNR test with bit_match_mode_ = 0
+ row_mt_mode_ = 1;
+
+ // Encode using single thread.
+ cfg_.g_threads = 1;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double single_thr_psnr = GetAveragePsnr();
+
+ // Encode using multiple threads.
+ cfg_.g_threads = threads_;
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double multi_thr_psnr = GetAveragePsnr();
+
+ EXPECT_NEAR(single_thr_psnr, multi_thr_psnr, 0.2);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9, VPxFirstPassEncoderThreadTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
+ ::testing::Values(::libvpx_test::kTwoPassGood),
+ ::testing::Range(0, 4))); // cpu_used
+
+// Split this into two instantiations so that we can distinguish
+// between very slow runs ( ie cpu_speed 0 ) vs ones that can be
+// run nightly by adding Large to the title.
+INSTANTIATE_TEST_SUITE_P(
+ VP9, VPxEncoderThreadTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
+ ::testing::Values(::libvpx_test::kTwoPassGood,
+ ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime),
+ ::testing::Range(3, 10), // cpu_used
+ ::testing::Range(0, 3), // tile_columns
+ ::testing::Range(2, 5))); // threads
+
+INSTANTIATE_TEST_SUITE_P(
+ VP9Large, VPxEncoderThreadTest,
+ ::testing::Combine(
+ ::testing::Values(
+ static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
+ ::testing::Values(::libvpx_test::kTwoPassGood,
+ ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime),
+ ::testing::Range(0, 3), // cpu_used
+ ::testing::Range(0, 3), // tile_columns
+ ::testing::Range(2, 5))); // threads
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_ext_ratectrl_test.cc b/media/libvpx/libvpx/test/vp9_ext_ratectrl_test.cc
new file mode 100644
index 0000000000..739c0b7f8e
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_ext_ratectrl_test.cc
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2020 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 <cstdint>
+#include <new>
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/yuv_video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "vp9/simple_encode.h"
+#include "vpx/vpx_ext_ratectrl.h"
+#include "vpx_dsp/vpx_dsp_common.h"
+
+namespace {
+
+constexpr int kModelMagicNumber = 51396;
+constexpr uintptr_t PrivMagicNumber = 5566;
+constexpr int kFrameNum = 5;
+constexpr int kFrameNumGOP = 30;
+constexpr int kFrameNumGOPShort = 4;
+constexpr int kLosslessCodingIndex = 2;
+constexpr int kFixedGOPSize = 9;
+// The range check in vp9_cx_iface.c shows that the max
+// lag in buffer is MAX_LAG_BUFFERS (25):
+// RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
+constexpr int kMaxLagInFrames = 25;
+constexpr int kDefaultMinGfInterval = 4;
+constexpr int kDefaultMaxGfInterval = 16;
+// The active gf interval might change for each GOP
+// See function "get_active_gf_inverval_range".
+// The numbers below are from manual inspection.
+constexpr int kReadMinGfInterval = 5;
+constexpr int kReadMaxGfInterval = 13;
+const char kTestFileName[] = "bus_352x288_420_f20_b8.yuv";
+const double kPsnrThreshold = 30.4;
+
+struct ToyRateCtrl {
+ int magic_number;
+ int coding_index;
+
+ int gop_global_index;
+ int frames_since_key;
+ int show_index;
+};
+
+vpx_rc_status_t rc_create_model(void *priv,
+ const vpx_rc_config_t *ratectrl_config,
+ vpx_rc_model_t *rate_ctrl_model_ptr) {
+ ToyRateCtrl *toy_rate_ctrl = new (std::nothrow) ToyRateCtrl;
+ if (toy_rate_ctrl == nullptr) return VPX_RC_ERROR;
+ toy_rate_ctrl->magic_number = kModelMagicNumber;
+ toy_rate_ctrl->coding_index = -1;
+ *rate_ctrl_model_ptr = toy_rate_ctrl;
+ EXPECT_EQ(priv, reinterpret_cast<void *>(PrivMagicNumber));
+ EXPECT_EQ(ratectrl_config->frame_width, 352);
+ EXPECT_EQ(ratectrl_config->frame_height, 288);
+ EXPECT_EQ(ratectrl_config->show_frame_count, kFrameNum);
+ EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 24000);
+ EXPECT_EQ(ratectrl_config->frame_rate_num, 30);
+ EXPECT_EQ(ratectrl_config->frame_rate_den, 1);
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_create_model_gop(void *priv,
+ const vpx_rc_config_t *ratectrl_config,
+ vpx_rc_model_t *rate_ctrl_model_ptr) {
+ ToyRateCtrl *toy_rate_ctrl = new (std::nothrow) ToyRateCtrl;
+ if (toy_rate_ctrl == nullptr) return VPX_RC_ERROR;
+ toy_rate_ctrl->magic_number = kModelMagicNumber;
+ toy_rate_ctrl->gop_global_index = 0;
+ toy_rate_ctrl->frames_since_key = 0;
+ toy_rate_ctrl->show_index = 0;
+ toy_rate_ctrl->coding_index = 0;
+ *rate_ctrl_model_ptr = toy_rate_ctrl;
+ EXPECT_EQ(priv, reinterpret_cast<void *>(PrivMagicNumber));
+ EXPECT_EQ(ratectrl_config->frame_width, 640);
+ EXPECT_EQ(ratectrl_config->frame_height, 360);
+ EXPECT_EQ(ratectrl_config->show_frame_count, kFrameNumGOP);
+ EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 4000);
+ EXPECT_EQ(ratectrl_config->frame_rate_num, 30);
+ EXPECT_EQ(ratectrl_config->frame_rate_den, 1);
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_create_model_gop_short(
+ void *priv, const vpx_rc_config_t *ratectrl_config,
+ vpx_rc_model_t *rate_ctrl_model_ptr) {
+ ToyRateCtrl *toy_rate_ctrl = new (std::nothrow) ToyRateCtrl;
+ if (toy_rate_ctrl == nullptr) return VPX_RC_ERROR;
+ toy_rate_ctrl->magic_number = kModelMagicNumber;
+ toy_rate_ctrl->gop_global_index = 0;
+ toy_rate_ctrl->frames_since_key = 0;
+ toy_rate_ctrl->show_index = 0;
+ toy_rate_ctrl->coding_index = 0;
+ *rate_ctrl_model_ptr = toy_rate_ctrl;
+ EXPECT_EQ(priv, reinterpret_cast<void *>(PrivMagicNumber));
+ EXPECT_EQ(ratectrl_config->frame_width, 352);
+ EXPECT_EQ(ratectrl_config->frame_height, 288);
+ EXPECT_EQ(ratectrl_config->show_frame_count, kFrameNumGOPShort);
+ EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 500);
+ EXPECT_EQ(ratectrl_config->frame_rate_num, 30);
+ EXPECT_EQ(ratectrl_config->frame_rate_den, 1);
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_send_firstpass_stats(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_firstpass_stats_t *first_pass_stats) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(first_pass_stats->num_frames, kFrameNum);
+ for (int i = 0; i < first_pass_stats->num_frames; ++i) {
+ EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i);
+ }
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_send_firstpass_stats_gop(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_firstpass_stats_t *first_pass_stats) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(first_pass_stats->num_frames, kFrameNumGOP);
+ for (int i = 0; i < first_pass_stats->num_frames; ++i) {
+ EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i);
+ }
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_send_firstpass_stats_gop_short(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_firstpass_stats_t *first_pass_stats) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(first_pass_stats->num_frames, kFrameNumGOPShort);
+ for (int i = 0; i < first_pass_stats->num_frames; ++i) {
+ EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i);
+ }
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_encodeframe_decision(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_info_t *encode_frame_info,
+ vpx_rc_encodeframe_decision_t *frame_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ toy_rate_ctrl->coding_index += 1;
+
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+
+ EXPECT_LT(encode_frame_info->show_index, kFrameNum);
+ EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
+
+ if (encode_frame_info->coding_index == 0) {
+ EXPECT_EQ(encode_frame_info->show_index, 0);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ } else if (encode_frame_info->coding_index == 1) {
+ EXPECT_EQ(encode_frame_info->show_index, 4);
+ EXPECT_EQ(encode_frame_info->gop_index, 1);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeAltRef);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 1); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
+ 0); // kRefFrameTypeLast
+ } else if (encode_frame_info->coding_index >= 2 &&
+ encode_frame_info->coding_index < 5) {
+ // In the first group of pictures, coding_index and gop_index are equal.
+ EXPECT_EQ(encode_frame_info->gop_index, encode_frame_info->coding_index);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ } else if (encode_frame_info->coding_index == 5) {
+ EXPECT_EQ(encode_frame_info->show_index, 4);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeOverlay);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 1); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 1); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 1); // kRefFrameTypeFuture
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
+ 4); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[2],
+ 1); // kRefFrameTypeFuture
+ }
+ if (encode_frame_info->coding_index == kLosslessCodingIndex) {
+ // We should get sse == 0 at rc_update_encodeframe_result()
+ frame_decision->q_index = 0;
+ } else {
+ frame_decision->q_index = 100;
+ }
+ frame_decision->max_frame_size = 0;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_encodeframe_decision_gop(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_info_t *encode_frame_info,
+ vpx_rc_encodeframe_decision_t *frame_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_LT(encode_frame_info->show_index, kFrameNumGOP);
+ EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
+
+ if (encode_frame_info->coding_index == 0) {
+ EXPECT_EQ(encode_frame_info->show_index, 0);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ } else if (encode_frame_info->coding_index == 1) {
+ EXPECT_EQ(encode_frame_info->show_index, 1);
+ EXPECT_EQ(encode_frame_info->gop_index, 1);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 1); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
+ 0); // kRefFrameTypeLast
+ } else if (encode_frame_info->coding_index == 2) {
+ EXPECT_EQ(encode_frame_info->show_index, 2);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ } else if (encode_frame_info->coding_index == 3 ||
+ encode_frame_info->coding_index == 12 ||
+ encode_frame_info->coding_index == 21) {
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeAltRef);
+ EXPECT_EQ(encode_frame_info->gop_index, 1);
+ } else if (encode_frame_info->coding_index == 11 ||
+ encode_frame_info->coding_index == 20 ||
+ encode_frame_info->coding_index == 29) {
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeOverlay);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ } else if (encode_frame_info->coding_index >= 30) {
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ }
+
+ // When the model recommends an invalid q, valid range [0, 255],
+ // the encoder will ignore it and use the default q selected
+ // by libvpx rate control strategy.
+ frame_decision->q_index = VPX_DEFAULT_Q;
+ frame_decision->max_frame_size = 0;
+
+ toy_rate_ctrl->coding_index += 1;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_encodeframe_decision_gop_short(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_info_t *encode_frame_info,
+ vpx_rc_encodeframe_decision_t *frame_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
+ EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
+
+ if (encode_frame_info->coding_index == 0) {
+ EXPECT_EQ(encode_frame_info->show_index, 0);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 1) {
+ EXPECT_EQ(encode_frame_info->show_index, 1);
+ EXPECT_EQ(encode_frame_info->gop_index, 1);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 1); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 2) {
+ EXPECT_EQ(encode_frame_info->show_index, 2);
+ EXPECT_EQ(encode_frame_info->gop_index, 2);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 3) {
+ EXPECT_EQ(encode_frame_info->show_index, 3);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeGolden);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 2);
+ }
+
+ // When the model recommends an invalid q, valid range [0, 255],
+ // the encoder will ignore it and use the default q selected
+ // by libvpx rate control strategy.
+ frame_decision->q_index = VPX_DEFAULT_Q;
+ frame_decision->max_frame_size = 0;
+
+ toy_rate_ctrl->coding_index += 1;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_encodeframe_decision_gop_short_overlay(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_info_t *encode_frame_info,
+ vpx_rc_encodeframe_decision_t *frame_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
+ EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
+
+ if (encode_frame_info->coding_index == 0) {
+ EXPECT_EQ(encode_frame_info->show_index, 0);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 1) {
+ EXPECT_EQ(encode_frame_info->show_index, 3);
+ EXPECT_EQ(encode_frame_info->gop_index, 1);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeAltRef);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 1); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 2) {
+ EXPECT_EQ(encode_frame_info->show_index, 1);
+ EXPECT_EQ(encode_frame_info->gop_index, 2);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 3) {
+ EXPECT_EQ(encode_frame_info->show_index, 2);
+ EXPECT_EQ(encode_frame_info->gop_index, 3);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 4) {
+ EXPECT_EQ(encode_frame_info->show_index, 3);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeOverlay);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 2);
+ }
+
+ // When the model recommends an invalid q, valid range [0, 255],
+ // the encoder will ignore it and use the default q selected
+ // by libvpx rate control strategy.
+ frame_decision->q_index = VPX_DEFAULT_Q;
+ frame_decision->max_frame_size = 0;
+
+ toy_rate_ctrl->coding_index += 1;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_encodeframe_decision_gop_short_no_arf(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_info_t *encode_frame_info,
+ vpx_rc_encodeframe_decision_t *frame_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
+ EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
+
+ if (encode_frame_info->coding_index == 0) {
+ EXPECT_EQ(encode_frame_info->show_index, 0);
+ EXPECT_EQ(encode_frame_info->gop_index, 0);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 1) {
+ EXPECT_EQ(encode_frame_info->show_index, 1);
+ EXPECT_EQ(encode_frame_info->gop_index, 1);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
+ 1); // kRefFrameTypeLast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
+ 0); // kRefFrameTypePast
+ EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
+ 0); // kRefFrameTypeFuture
+ EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
+ 0); // kRefFrameTypeLast
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 2) {
+ EXPECT_EQ(encode_frame_info->show_index, 2);
+ EXPECT_EQ(encode_frame_info->gop_index, 2);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ } else if (encode_frame_info->coding_index == 3) {
+ EXPECT_EQ(encode_frame_info->show_index, 3);
+ EXPECT_EQ(encode_frame_info->gop_index, 3);
+ EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
+ EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
+ }
+
+ // When the model recommends an invalid q, valid range [0, 255],
+ // the encoder will ignore it and use the default q selected
+ // by libvpx rate control strategy.
+ frame_decision->q_index = VPX_DEFAULT_Q;
+ frame_decision->max_frame_size = 0;
+
+ toy_rate_ctrl->coding_index += 1;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_gop_decision(vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_gop_info_t *gop_info,
+ vpx_rc_gop_decision_t *gop_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames);
+ EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
+ EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
+ EXPECT_EQ(gop_info->active_min_gf_interval, kReadMinGfInterval);
+ EXPECT_EQ(gop_info->active_max_gf_interval, kReadMaxGfInterval);
+ EXPECT_EQ(gop_info->allow_alt_ref, 1);
+ if (gop_info->is_key_frame) {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
+ EXPECT_EQ(gop_info->frames_since_key, 0);
+ EXPECT_EQ(gop_info->gop_global_index, 0);
+ toy_rate_ctrl->gop_global_index = 0;
+ toy_rate_ctrl->frames_since_key = 0;
+ } else {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 1);
+ }
+ EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
+ EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
+ EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
+ EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
+
+ gop_decision->gop_coding_frames =
+ VPXMIN(kFixedGOPSize, gop_info->frames_to_key);
+ gop_decision->use_alt_ref = gop_decision->gop_coding_frames == kFixedGOPSize;
+ toy_rate_ctrl->frames_since_key +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ toy_rate_ctrl->show_index +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ ++toy_rate_ctrl->gop_global_index;
+ return VPX_RC_OK;
+}
+
+// Test on a 4 frame video.
+// Test a setting of 2 GOPs.
+// The first GOP has 3 coding frames, no alt ref.
+// The second GOP has 1 coding frame, no alt ref.
+vpx_rc_status_t rc_get_gop_decision_short(vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_gop_info_t *gop_info,
+ vpx_rc_gop_decision_t *gop_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames - 1);
+ EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
+ EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
+ EXPECT_EQ(gop_info->allow_alt_ref, 1);
+ if (gop_info->is_key_frame) {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
+ EXPECT_EQ(gop_info->frames_since_key, 0);
+ EXPECT_EQ(gop_info->gop_global_index, 0);
+ toy_rate_ctrl->gop_global_index = 0;
+ toy_rate_ctrl->frames_since_key = 0;
+ } else {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
+ }
+ EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
+ EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
+ EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
+ EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
+
+ gop_decision->gop_coding_frames = gop_info->gop_global_index == 0 ? 3 : 1;
+ gop_decision->use_alt_ref = 0;
+ toy_rate_ctrl->frames_since_key +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ toy_rate_ctrl->show_index +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ ++toy_rate_ctrl->gop_global_index;
+ return VPX_RC_OK;
+}
+
+// Test on a 4 frame video.
+// Test a setting of 2 GOPs.
+// The first GOP has 4 coding frames. Use alt ref.
+// The second GOP only contains the overlay frame of the first GOP's alt ref
+// frame.
+vpx_rc_status_t rc_get_gop_decision_short_overlay(
+ vpx_rc_model_t rate_ctrl_model, const vpx_rc_gop_info_t *gop_info,
+ vpx_rc_gop_decision_t *gop_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames - 1);
+ EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
+ EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
+ EXPECT_EQ(gop_info->allow_alt_ref, 1);
+ if (gop_info->is_key_frame) {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
+ EXPECT_EQ(gop_info->frames_since_key, 0);
+ EXPECT_EQ(gop_info->gop_global_index, 0);
+ toy_rate_ctrl->gop_global_index = 0;
+ toy_rate_ctrl->frames_since_key = 0;
+ } else {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 1);
+ }
+ EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
+ EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
+ EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
+ EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
+
+ gop_decision->gop_coding_frames = gop_info->gop_global_index == 0 ? 4 : 1;
+ gop_decision->use_alt_ref = gop_info->is_key_frame ? 1 : 0;
+ toy_rate_ctrl->frames_since_key +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ toy_rate_ctrl->show_index +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ ++toy_rate_ctrl->gop_global_index;
+ return VPX_RC_OK;
+}
+
+// Test on a 4 frame video.
+// Test a setting of 1 GOP.
+// The GOP has 4 coding frames. Do not use alt ref.
+vpx_rc_status_t rc_get_gop_decision_short_no_arf(
+ vpx_rc_model_t rate_ctrl_model, const vpx_rc_gop_info_t *gop_info,
+ vpx_rc_gop_decision_t *gop_decision) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames - 1);
+ EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
+ EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
+ EXPECT_EQ(gop_info->allow_alt_ref, 1);
+ if (gop_info->is_key_frame) {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
+ EXPECT_EQ(gop_info->frames_since_key, 0);
+ EXPECT_EQ(gop_info->gop_global_index, 0);
+ toy_rate_ctrl->gop_global_index = 0;
+ toy_rate_ctrl->frames_since_key = 0;
+ } else {
+ EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
+ }
+ EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
+ EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
+ EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
+ EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
+
+ gop_decision->gop_coding_frames = gop_info->gop_global_index == 0 ? 4 : 1;
+ gop_decision->use_alt_ref = 0;
+ toy_rate_ctrl->frames_since_key +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ toy_rate_ctrl->show_index +=
+ gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
+ ++toy_rate_ctrl->gop_global_index;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_update_encodeframe_result(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_result_t *encode_frame_result) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+
+ const int64_t ref_pixel_count = 352 * 288 * 3 / 2;
+ EXPECT_EQ(encode_frame_result->pixel_count, ref_pixel_count);
+ if (toy_rate_ctrl->coding_index == kLosslessCodingIndex) {
+ EXPECT_EQ(encode_frame_result->sse, 0);
+ }
+ if (toy_rate_ctrl->coding_index == kLosslessCodingIndex) {
+ EXPECT_EQ(encode_frame_result->actual_encoding_qindex, 0);
+ } else {
+ EXPECT_EQ(encode_frame_result->actual_encoding_qindex, 100);
+ }
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_update_encodeframe_result_gop(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_result_t *encode_frame_result) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+
+ const int64_t ref_pixel_count = 640 * 360 * 3 / 2;
+ EXPECT_EQ(encode_frame_result->pixel_count, ref_pixel_count);
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_update_encodeframe_result_gop_short(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_result_t *encode_frame_result) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+
+ const int64_t ref_pixel_count = 352 * 288 * 3 / 2;
+ EXPECT_EQ(encode_frame_result->pixel_count, ref_pixel_count);
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_get_default_frame_rdmult(
+ vpx_rc_model_t rate_ctrl_model,
+ const vpx_rc_encodeframe_info_t *encode_frame_info, int *rdmult) {
+ const ToyRateCtrl *toy_rate_ctrl =
+ static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
+ EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
+
+ *rdmult = VPX_DEFAULT_RDMULT;
+ return VPX_RC_OK;
+}
+
+vpx_rc_status_t rc_delete_model(vpx_rc_model_t rate_ctrl_model) {
+ ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
+ EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
+ delete toy_rate_ctrl;
+ return VPX_RC_OK;
+}
+
+class ExtRateCtrlTest : public ::libvpx_test::EncoderTest,
+ public ::testing::Test {
+ protected:
+ ExtRateCtrlTest() : EncoderTest(&::libvpx_test::kVP9) {}
+
+ ~ExtRateCtrlTest() override = default;
+
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ vpx_rc_funcs_t rc_funcs;
+ rc_funcs.rc_type = VPX_RC_QP;
+ rc_funcs.create_model = rc_create_model;
+ rc_funcs.send_firstpass_stats = rc_send_firstpass_stats;
+ rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision;
+ rc_funcs.update_encodeframe_result = rc_update_encodeframe_result;
+ rc_funcs.delete_model = rc_delete_model;
+ rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
+ encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
+ }
+ }
+};
+
+TEST_F(ExtRateCtrlTest, EncodeTest) {
+ cfg_.rc_target_bitrate = 24000;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
+ "bus_352x288_420_f20_b8.yuv", VPX_IMG_FMT_I420, 352, 288, 30, 1, 0,
+ kFrameNum));
+
+ ASSERT_NE(video, nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+class ExtRateCtrlTestGOP : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+ ExtRateCtrlTestGOP() : EncoderTest(&::libvpx_test::kVP9) {}
+
+ ~ExtRateCtrlTestGOP() override = default;
+
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
+ encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
+
+ vpx_rc_funcs_t rc_funcs;
+ rc_funcs.rc_type = VPX_RC_GOP_QP;
+ rc_funcs.create_model = rc_create_model_gop;
+ rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop;
+ rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision_gop;
+ rc_funcs.get_gop_decision = rc_get_gop_decision;
+ rc_funcs.update_encodeframe_result = rc_update_encodeframe_result_gop;
+ rc_funcs.delete_model = rc_delete_model;
+ rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
+ encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
+ }
+ }
+};
+
+TEST_F(ExtRateCtrlTestGOP, EncodeTest) {
+ cfg_.rc_target_bitrate = 4000;
+ cfg_.g_lag_in_frames = kMaxLagInFrames;
+ cfg_.rc_end_usage = VPX_VBR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
+ "noisy_clip_640_360.y4m", VPX_IMG_FMT_I420, 640, 360, 30, 1, 0,
+ kFrameNumGOP));
+
+ ASSERT_NE(video, nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+class ExtRateCtrlTestGOPShort : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+ ExtRateCtrlTestGOPShort() : EncoderTest(&::libvpx_test::kVP9) {}
+
+ ~ExtRateCtrlTestGOPShort() override = default;
+
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
+ encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
+ encoder->Control(VP9E_SET_TARGET_LEVEL, vp9::LEVEL_AUTO);
+
+ vpx_rc_funcs_t rc_funcs;
+ rc_funcs.rc_type = VPX_RC_GOP_QP;
+ rc_funcs.create_model = rc_create_model_gop_short;
+ rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
+ rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision_gop_short;
+ rc_funcs.get_gop_decision = rc_get_gop_decision_short;
+ rc_funcs.update_encodeframe_result =
+ rc_update_encodeframe_result_gop_short;
+ rc_funcs.delete_model = rc_delete_model;
+ rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
+ encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
+ }
+ }
+};
+
+TEST_F(ExtRateCtrlTestGOPShort, EncodeTest) {
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
+ cfg_.rc_end_usage = VPX_VBR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
+ kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
+
+ ASSERT_NE(video, nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+class ExtRateCtrlTestGOPShortOverlay
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+ ExtRateCtrlTestGOPShortOverlay() : EncoderTest(&::libvpx_test::kVP9) {}
+
+ ~ExtRateCtrlTestGOPShortOverlay() override = default;
+
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
+ encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
+ encoder->Control(VP9E_SET_TARGET_LEVEL, vp9::LEVEL_AUTO);
+
+ vpx_rc_funcs_t rc_funcs;
+ rc_funcs.rc_type = VPX_RC_GOP_QP;
+ rc_funcs.create_model = rc_create_model_gop_short;
+ rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
+ rc_funcs.get_encodeframe_decision =
+ rc_get_encodeframe_decision_gop_short_overlay;
+ rc_funcs.get_gop_decision = rc_get_gop_decision_short_overlay;
+ rc_funcs.update_encodeframe_result =
+ rc_update_encodeframe_result_gop_short;
+ rc_funcs.delete_model = rc_delete_model;
+ rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
+ encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
+ }
+ }
+};
+
+TEST_F(ExtRateCtrlTestGOPShortOverlay, EncodeTest) {
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
+ cfg_.rc_end_usage = VPX_VBR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
+ kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
+
+ ASSERT_NE(video, nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+class ExtRateCtrlTestGOPShortNoARF
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+ ExtRateCtrlTestGOPShortNoARF() : EncoderTest(&::libvpx_test::kVP9) {}
+
+ ~ExtRateCtrlTestGOPShortNoARF() override = default;
+
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
+ encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
+ encoder->Control(VP9E_SET_TARGET_LEVEL, vp9::LEVEL_AUTO);
+
+ vpx_rc_funcs_t rc_funcs;
+ rc_funcs.rc_type = VPX_RC_GOP_QP;
+ rc_funcs.create_model = rc_create_model_gop_short;
+ rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
+ rc_funcs.get_encodeframe_decision =
+ rc_get_encodeframe_decision_gop_short_no_arf;
+ rc_funcs.get_gop_decision = rc_get_gop_decision_short_no_arf;
+ rc_funcs.update_encodeframe_result =
+ rc_update_encodeframe_result_gop_short;
+ rc_funcs.delete_model = rc_delete_model;
+ rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
+ encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
+ }
+ }
+};
+
+TEST_F(ExtRateCtrlTestGOPShortNoARF, EncodeTest) {
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
+ cfg_.rc_end_usage = VPX_VBR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
+ kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
+
+ ASSERT_NE(video, nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+class ExtRateCtrlTestRdmult : public ::libvpx_test::EncoderTest,
+ public ::testing::Test {
+ protected:
+ ExtRateCtrlTestRdmult() : EncoderTest(&::libvpx_test::kVP9) {}
+
+ ~ExtRateCtrlTestRdmult() override = default;
+
+ void SetUp() override {
+ InitializeConfig();
+ SetMode(::libvpx_test::kTwoPassGood);
+ }
+
+ void BeginPassHook(unsigned int) override {
+ psnr_ = 0.0;
+ nframes_ = 0;
+ }
+
+ void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) override {
+ psnr_ += pkt->data.psnr.psnr[0];
+ nframes_++;
+ }
+
+ void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) override {
+ if (video->frame() == 0) {
+ vpx_rc_funcs_t rc_funcs;
+ rc_funcs.rc_type = VPX_RC_GOP_QP_RDMULT;
+ rc_funcs.create_model = rc_create_model_gop_short;
+ rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
+ rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision_gop_short;
+ rc_funcs.get_gop_decision = rc_get_gop_decision_short;
+ rc_funcs.update_encodeframe_result =
+ rc_update_encodeframe_result_gop_short;
+ rc_funcs.get_frame_rdmult = rc_get_default_frame_rdmult;
+ rc_funcs.delete_model = rc_delete_model;
+ rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
+ encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
+ }
+ }
+
+ double GetAveragePsnr() const {
+ if (nframes_) return psnr_ / nframes_;
+ return 0.0;
+ }
+
+ private:
+ double psnr_;
+ unsigned int nframes_;
+};
+
+TEST_F(ExtRateCtrlTestRdmult, DefaultRdmult) {
+ cfg_.rc_target_bitrate = 500;
+ cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
+ cfg_.rc_end_usage = VPX_VBR;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
+ kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
+
+ ASSERT_NE(video, nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+
+ const double psnr = GetAveragePsnr();
+ EXPECT_GT(psnr, kPsnrThreshold);
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_intrapred_test.cc b/media/libvpx/libvpx/test/vp9_intrapred_test.cc
new file mode 100644
index 0000000000..6de7cf8d0f
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_intrapred_test.cc
@@ -0,0 +1,1198 @@
+/*
+ * 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 <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_blockd.h"
+#include "vp9/common/vp9_pred_common.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+using libvpx_test::ACMRandom;
+
+const int count_test_block = 100000;
+
+typedef void (*IntraPredFunc)(uint8_t *dst, ptrdiff_t stride,
+ const uint8_t *above, const uint8_t *left);
+
+struct IntraPredParam {
+ IntraPredParam(IntraPredFunc pred = nullptr, IntraPredFunc ref = nullptr,
+ int block_size_value = 0, int bit_depth_value = 0)
+ : pred_fn(pred), ref_fn(ref), block_size(block_size_value),
+ bit_depth(bit_depth_value) {}
+
+ IntraPredFunc pred_fn;
+ IntraPredFunc ref_fn;
+ int block_size;
+ int bit_depth;
+};
+
+template <typename Pixel, typename PredParam>
+class IntraPredTest : public ::testing::TestWithParam<PredParam> {
+ public:
+ void RunTest(Pixel *left_col, Pixel *above_data, Pixel *dst, Pixel *ref_dst) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ const int block_size = params_.block_size;
+ above_row_ = above_data + 16;
+ left_col_ = left_col;
+ dst_ = dst;
+ ref_dst_ = ref_dst;
+ int error_count = 0;
+ for (int i = 0; i < count_test_block; ++i) {
+ // TODO(webm:1797): Some of the optimised predictor implementations rely
+ // on the trailing half of the above_row_ being a copy of the final
+ // element, however relying on this in some cases can cause the MD5 tests
+ // to fail. We have fixed all of these cases for Neon, so fill the whole
+ // of above_row_ randomly.
+#if HAVE_NEON
+ // Fill edges with random data, try first with saturated values.
+ for (int x = -1; x < 2 * block_size; x++) {
+ if (i == 0) {
+ above_row_[x] = mask_;
+ } else {
+ above_row_[x] = rnd.Rand16() & mask_;
+ }
+ }
+#else
+ // Fill edges with random data, try first with saturated values.
+ for (int x = -1; x < block_size; x++) {
+ if (i == 0) {
+ above_row_[x] = mask_;
+ } else {
+ above_row_[x] = rnd.Rand16() & mask_;
+ }
+ }
+ for (int x = block_size; x < 2 * block_size; x++) {
+ above_row_[x] = above_row_[block_size - 1];
+ }
+#endif
+ for (int y = 0; y < block_size; y++) {
+ if (i == 0) {
+ left_col_[y] = mask_;
+ } else {
+ left_col_[y] = rnd.Rand16() & mask_;
+ }
+ }
+ Predict();
+ CheckPrediction(i, &error_count);
+ }
+ ASSERT_EQ(0, error_count);
+ }
+
+ protected:
+ virtual void SetUp() {
+ params_ = this->GetParam();
+ stride_ = params_.block_size * 3;
+ mask_ = (1 << params_.bit_depth) - 1;
+ }
+
+ void Predict();
+
+ void CheckPrediction(int test_case_number, int *error_count) const {
+ // For each pixel ensure that the calculated value is the same as reference.
+ const int block_size = params_.block_size;
+ for (int y = 0; y < block_size; y++) {
+ for (int x = 0; x < block_size; x++) {
+ *error_count += ref_dst_[x + y * stride_] != dst_[x + y * stride_];
+ if (*error_count == 1) {
+ ASSERT_EQ(ref_dst_[x + y * stride_], dst_[x + y * stride_])
+ << " Failed on Test Case Number " << test_case_number;
+ }
+ }
+ }
+ }
+
+ Pixel *above_row_;
+ Pixel *left_col_;
+ Pixel *dst_;
+ Pixel *ref_dst_;
+ ptrdiff_t stride_;
+ int mask_;
+
+ PredParam params_;
+};
+
+template <>
+void IntraPredTest<uint8_t, IntraPredParam>::Predict() {
+ params_.ref_fn(ref_dst_, stride_, above_row_, left_col_);
+ ASM_REGISTER_STATE_CHECK(
+ params_.pred_fn(dst_, stride_, above_row_, left_col_));
+}
+
+typedef IntraPredTest<uint8_t, IntraPredParam> VP9IntraPredTest;
+
+TEST_P(VP9IntraPredTest, IntraPredTests) {
+ // max block size is 32
+ DECLARE_ALIGNED(16, uint8_t, left_col[2 * 32]);
+ DECLARE_ALIGNED(16, uint8_t, above_data[2 * 32 + 32]);
+ DECLARE_ALIGNED(16, uint8_t, dst[3 * 32 * 32]);
+ DECLARE_ALIGNED(16, uint8_t, ref_dst[3 * 32 * 32]);
+ RunTest(left_col, above_data, dst, ref_dst);
+}
+
+// Instantiate a token test to avoid -Wuninitialized warnings when none of the
+// other tests are enabled.
+INSTANTIATE_TEST_SUITE_P(
+ C, VP9IntraPredTest,
+ ::testing::Values(IntraPredParam(&vpx_d45_predictor_4x4_c,
+ &vpx_d45_predictor_4x4_c, 4, 8)));
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VP9IntraPredTest,
+ ::testing::Values(
+ IntraPredParam(&vpx_d45_predictor_4x4_sse2, &vpx_d45_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_d45_predictor_8x8_sse2, &vpx_d45_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_d207_predictor_4x4_sse2, &vpx_d207_predictor_4x4_c,
+ 4, 8),
+ IntraPredParam(&vpx_dc_128_predictor_4x4_sse2,
+ &vpx_dc_128_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_128_predictor_8x8_sse2,
+ &vpx_dc_128_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_128_predictor_16x16_sse2,
+ &vpx_dc_128_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_128_predictor_32x32_sse2,
+ &vpx_dc_128_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_left_predictor_4x4_sse2,
+ &vpx_dc_left_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_left_predictor_8x8_sse2,
+ &vpx_dc_left_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_left_predictor_16x16_sse2,
+ &vpx_dc_left_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_left_predictor_32x32_sse2,
+ &vpx_dc_left_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_predictor_4x4_sse2, &vpx_dc_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_8x8_sse2, &vpx_dc_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_16x16_sse2, &vpx_dc_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_dc_predictor_32x32_sse2, &vpx_dc_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_dc_top_predictor_4x4_sse2,
+ &vpx_dc_top_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_top_predictor_8x8_sse2,
+ &vpx_dc_top_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_top_predictor_16x16_sse2,
+ &vpx_dc_top_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_top_predictor_32x32_sse2,
+ &vpx_dc_top_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_h_predictor_4x4_sse2, &vpx_h_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_h_predictor_8x8_sse2, &vpx_h_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_h_predictor_16x16_sse2, &vpx_h_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_h_predictor_32x32_sse2, &vpx_h_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_tm_predictor_4x4_sse2, &vpx_tm_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_8x8_sse2, &vpx_tm_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_16x16_sse2, &vpx_tm_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_tm_predictor_32x32_sse2, &vpx_tm_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_v_predictor_4x4_sse2, &vpx_v_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_v_predictor_8x8_sse2, &vpx_v_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_v_predictor_16x16_sse2, &vpx_v_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_v_predictor_32x32_sse2, &vpx_v_predictor_32x32_c,
+ 32, 8)));
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, VP9IntraPredTest,
+ ::testing::Values(IntraPredParam(&vpx_d45_predictor_16x16_ssse3,
+ &vpx_d45_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d45_predictor_32x32_ssse3,
+ &vpx_d45_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d63_predictor_4x4_ssse3,
+ &vpx_d63_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_d63_predictor_8x8_ssse3,
+ &vpx_d63_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_d63_predictor_16x16_ssse3,
+ &vpx_d63_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d63_predictor_32x32_ssse3,
+ &vpx_d63_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d153_predictor_4x4_ssse3,
+ &vpx_d153_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_d153_predictor_8x8_ssse3,
+ &vpx_d153_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_d153_predictor_16x16_ssse3,
+ &vpx_d153_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d153_predictor_32x32_ssse3,
+ &vpx_d153_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d207_predictor_8x8_ssse3,
+ &vpx_d207_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_d207_predictor_16x16_ssse3,
+ &vpx_d207_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d207_predictor_32x32_ssse3,
+ &vpx_d207_predictor_32x32_c, 32, 8)));
+#endif // HAVE_SSSE3
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VP9IntraPredTest,
+ ::testing::Values(
+ IntraPredParam(&vpx_d45_predictor_4x4_neon, &vpx_d45_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_d45_predictor_8x8_neon, &vpx_d45_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_d45_predictor_16x16_neon,
+ &vpx_d45_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d45_predictor_32x32_neon,
+ &vpx_d45_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d63_predictor_4x4_neon, &vpx_d63_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_d63_predictor_8x8_neon, &vpx_d63_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_d63_predictor_16x16_neon,
+ &vpx_d63_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d63_predictor_32x32_neon,
+ &vpx_d63_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d117_predictor_4x4_neon, &vpx_d117_predictor_4x4_c,
+ 4, 8),
+ IntraPredParam(&vpx_d117_predictor_8x8_neon, &vpx_d117_predictor_8x8_c,
+ 8, 8),
+ IntraPredParam(&vpx_d117_predictor_16x16_neon,
+ &vpx_d117_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d117_predictor_32x32_neon,
+ &vpx_d117_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d135_predictor_4x4_neon, &vpx_d135_predictor_4x4_c,
+ 4, 8),
+ IntraPredParam(&vpx_d135_predictor_8x8_neon, &vpx_d135_predictor_8x8_c,
+ 8, 8),
+ IntraPredParam(&vpx_d135_predictor_16x16_neon,
+ &vpx_d135_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d135_predictor_32x32_neon,
+ &vpx_d135_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d153_predictor_4x4_neon, &vpx_d153_predictor_4x4_c,
+ 4, 8),
+ IntraPredParam(&vpx_d153_predictor_8x8_neon, &vpx_d153_predictor_8x8_c,
+ 8, 8),
+ IntraPredParam(&vpx_d153_predictor_16x16_neon,
+ &vpx_d153_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d153_predictor_32x32_neon,
+ &vpx_d153_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d207_predictor_4x4_neon, &vpx_d207_predictor_4x4_c,
+ 4, 8),
+ IntraPredParam(&vpx_d207_predictor_8x8_neon, &vpx_d207_predictor_8x8_c,
+ 8, 8),
+ IntraPredParam(&vpx_d207_predictor_16x16_neon,
+ &vpx_d207_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d207_predictor_32x32_neon,
+ &vpx_d207_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_128_predictor_4x4_neon,
+ &vpx_dc_128_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_128_predictor_8x8_neon,
+ &vpx_dc_128_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_128_predictor_16x16_neon,
+ &vpx_dc_128_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_128_predictor_32x32_neon,
+ &vpx_dc_128_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_left_predictor_4x4_neon,
+ &vpx_dc_left_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_left_predictor_8x8_neon,
+ &vpx_dc_left_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_left_predictor_16x16_neon,
+ &vpx_dc_left_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_left_predictor_32x32_neon,
+ &vpx_dc_left_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_predictor_4x4_neon, &vpx_dc_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_8x8_neon, &vpx_dc_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_16x16_neon, &vpx_dc_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_dc_predictor_32x32_neon, &vpx_dc_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_dc_top_predictor_4x4_neon,
+ &vpx_dc_top_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_top_predictor_8x8_neon,
+ &vpx_dc_top_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_top_predictor_16x16_neon,
+ &vpx_dc_top_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_top_predictor_32x32_neon,
+ &vpx_dc_top_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_h_predictor_4x4_neon, &vpx_h_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_h_predictor_8x8_neon, &vpx_h_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_h_predictor_16x16_neon, &vpx_h_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_h_predictor_32x32_neon, &vpx_h_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_tm_predictor_4x4_neon, &vpx_tm_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_8x8_neon, &vpx_tm_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_16x16_neon, &vpx_tm_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_tm_predictor_32x32_neon, &vpx_tm_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_v_predictor_4x4_neon, &vpx_v_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_v_predictor_8x8_neon, &vpx_v_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_v_predictor_16x16_neon, &vpx_v_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_v_predictor_32x32_neon, &vpx_v_predictor_32x32_c,
+ 32, 8)));
+#endif // HAVE_NEON
+
+#if HAVE_DSPR2
+INSTANTIATE_TEST_SUITE_P(
+ DSPR2, VP9IntraPredTest,
+ ::testing::Values(IntraPredParam(&vpx_dc_predictor_4x4_dspr2,
+ &vpx_dc_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_predictor_8x8_dspr2,
+ &vpx_dc_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_predictor_16x16_dspr2,
+ &vpx_dc_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_h_predictor_4x4_dspr2,
+ &vpx_h_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_h_predictor_8x8_dspr2,
+ &vpx_h_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_h_predictor_16x16_dspr2,
+ &vpx_h_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_tm_predictor_4x4_dspr2,
+ &vpx_tm_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_tm_predictor_8x8_dspr2,
+ &vpx_tm_predictor_8x8_c, 8, 8)));
+#endif // HAVE_DSPR2
+
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(
+ MSA, VP9IntraPredTest,
+ ::testing::Values(
+ IntraPredParam(&vpx_dc_128_predictor_4x4_msa,
+ &vpx_dc_128_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_128_predictor_8x8_msa,
+ &vpx_dc_128_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_128_predictor_16x16_msa,
+ &vpx_dc_128_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_128_predictor_32x32_msa,
+ &vpx_dc_128_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_left_predictor_4x4_msa,
+ &vpx_dc_left_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_left_predictor_8x8_msa,
+ &vpx_dc_left_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_left_predictor_16x16_msa,
+ &vpx_dc_left_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_left_predictor_32x32_msa,
+ &vpx_dc_left_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_predictor_4x4_msa, &vpx_dc_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_8x8_msa, &vpx_dc_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_16x16_msa, &vpx_dc_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_dc_predictor_32x32_msa, &vpx_dc_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_dc_top_predictor_4x4_msa,
+ &vpx_dc_top_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_dc_top_predictor_8x8_msa,
+ &vpx_dc_top_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_dc_top_predictor_16x16_msa,
+ &vpx_dc_top_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_top_predictor_32x32_msa,
+ &vpx_dc_top_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_h_predictor_4x4_msa, &vpx_h_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_h_predictor_8x8_msa, &vpx_h_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_h_predictor_16x16_msa, &vpx_h_predictor_16x16_c, 16,
+ 8),
+ IntraPredParam(&vpx_h_predictor_32x32_msa, &vpx_h_predictor_32x32_c, 32,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_4x4_msa, &vpx_tm_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_8x8_msa, &vpx_tm_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_16x16_msa, &vpx_tm_predictor_16x16_c,
+ 16, 8),
+ IntraPredParam(&vpx_tm_predictor_32x32_msa, &vpx_tm_predictor_32x32_c,
+ 32, 8),
+ IntraPredParam(&vpx_v_predictor_4x4_msa, &vpx_v_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_v_predictor_8x8_msa, &vpx_v_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_v_predictor_16x16_msa, &vpx_v_predictor_16x16_c, 16,
+ 8),
+ IntraPredParam(&vpx_v_predictor_32x32_msa, &vpx_v_predictor_32x32_c, 32,
+ 8)));
+#endif // HAVE_MSA
+
+// TODO(crbug.com/webm/1522): Fix test failures.
+#if 0
+ IntraPredParam(&vpx_d45_predictor_8x8_vsx, &vpx_d45_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_d63_predictor_8x8_vsx, &vpx_d63_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_dc_predictor_8x8_vsx, &vpx_dc_predictor_8x8_c, 8,
+ 8),
+ IntraPredParam(&vpx_h_predictor_4x4_vsx, &vpx_h_predictor_4x4_c, 4, 8),
+ IntraPredParam(&vpx_h_predictor_8x8_vsx, &vpx_h_predictor_8x8_c, 8, 8),
+ IntraPredParam(&vpx_tm_predictor_4x4_vsx, &vpx_tm_predictor_4x4_c, 4,
+ 8),
+ IntraPredParam(&vpx_tm_predictor_8x8_vsx, &vpx_tm_predictor_8x8_c, 8,
+ 8),
+#endif
+
+#if HAVE_VSX
+INSTANTIATE_TEST_SUITE_P(
+ VSX, VP9IntraPredTest,
+ ::testing::Values(IntraPredParam(&vpx_d45_predictor_16x16_vsx,
+ &vpx_d45_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d45_predictor_32x32_vsx,
+ &vpx_d45_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_d63_predictor_16x16_vsx,
+ &vpx_d63_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_d63_predictor_32x32_vsx,
+ &vpx_d63_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_128_predictor_16x16_vsx,
+ &vpx_dc_128_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_128_predictor_32x32_vsx,
+ &vpx_dc_128_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_left_predictor_16x16_vsx,
+ &vpx_dc_left_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_left_predictor_32x32_vsx,
+ &vpx_dc_left_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_predictor_16x16_vsx,
+ &vpx_dc_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_predictor_32x32_vsx,
+ &vpx_dc_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_dc_top_predictor_16x16_vsx,
+ &vpx_dc_top_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_dc_top_predictor_32x32_vsx,
+ &vpx_dc_top_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_h_predictor_16x16_vsx,
+ &vpx_h_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_h_predictor_32x32_vsx,
+ &vpx_h_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_tm_predictor_16x16_vsx,
+ &vpx_tm_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_tm_predictor_32x32_vsx,
+ &vpx_tm_predictor_32x32_c, 32, 8),
+ IntraPredParam(&vpx_v_predictor_16x16_vsx,
+ &vpx_v_predictor_16x16_c, 16, 8),
+ IntraPredParam(&vpx_v_predictor_32x32_vsx,
+ &vpx_v_predictor_32x32_c, 32, 8)));
+#endif // HAVE_VSX
+
+#if CONFIG_VP9_HIGHBITDEPTH
+typedef void (*HighbdIntraPred)(uint16_t *dst, ptrdiff_t stride,
+ const uint16_t *above, const uint16_t *left,
+ int bps);
+struct HighbdIntraPredParam {
+ HighbdIntraPredParam(HighbdIntraPred pred = nullptr,
+ HighbdIntraPred ref = nullptr, int block_size_value = 0,
+ int bit_depth_value = 0)
+ : pred_fn(pred), ref_fn(ref), block_size(block_size_value),
+ bit_depth(bit_depth_value) {}
+
+ HighbdIntraPred pred_fn;
+ HighbdIntraPred ref_fn;
+ int block_size;
+ int bit_depth;
+};
+
+#if HAVE_SSSE3 || HAVE_NEON || HAVE_SSE2
+template <>
+void IntraPredTest<uint16_t, HighbdIntraPredParam>::Predict() {
+ const int bit_depth = params_.bit_depth;
+ params_.ref_fn(ref_dst_, stride_, above_row_, left_col_, bit_depth);
+ ASM_REGISTER_STATE_CHECK(
+ params_.pred_fn(dst_, stride_, above_row_, left_col_, bit_depth));
+}
+
+typedef IntraPredTest<uint16_t, HighbdIntraPredParam> VP9HighbdIntraPredTest;
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VP9HighbdIntraPredTest);
+
+TEST_P(VP9HighbdIntraPredTest, HighbdIntraPredTests) {
+ // max block size is 32
+ DECLARE_ALIGNED(16, uint16_t, left_col[2 * 32]);
+ DECLARE_ALIGNED(16, uint16_t, above_data[2 * 32 + 32]);
+ DECLARE_ALIGNED(16, uint16_t, dst[3 * 32 * 32]);
+ DECLARE_ALIGNED(16, uint16_t, ref_dst[3 * 32 * 32]);
+ RunTest(left_col, above_data, dst, ref_dst);
+}
+#endif
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3_TO_C_8, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_4x4_ssse3,
+ &vpx_highbd_d45_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_8x8_ssse3,
+ &vpx_highbd_d45_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_16x16_ssse3,
+ &vpx_highbd_d45_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_32x32_ssse3,
+ &vpx_highbd_d45_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_8x8_ssse3,
+ &vpx_highbd_d63_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_16x16_ssse3,
+ &vpx_highbd_d63_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_32x32_c,
+ &vpx_highbd_d63_predictor_32x32_ssse3, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_8x8_ssse3,
+ &vpx_highbd_d117_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_16x16_ssse3,
+ &vpx_highbd_d117_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_32x32_c,
+ &vpx_highbd_d117_predictor_32x32_ssse3, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_8x8_ssse3,
+ &vpx_highbd_d135_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_16x16_ssse3,
+ &vpx_highbd_d135_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_32x32_ssse3,
+ &vpx_highbd_d135_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_8x8_ssse3,
+ &vpx_highbd_d153_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_16x16_ssse3,
+ &vpx_highbd_d153_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_32x32_ssse3,
+ &vpx_highbd_d153_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_8x8_ssse3,
+ &vpx_highbd_d207_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_16x16_ssse3,
+ &vpx_highbd_d207_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_32x32_ssse3,
+ &vpx_highbd_d207_predictor_32x32_c, 32, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3_TO_C_10, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_4x4_ssse3,
+ &vpx_highbd_d45_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_8x8_ssse3,
+ &vpx_highbd_d45_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_16x16_ssse3,
+ &vpx_highbd_d45_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_32x32_ssse3,
+ &vpx_highbd_d45_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_8x8_ssse3,
+ &vpx_highbd_d63_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_16x16_ssse3,
+ &vpx_highbd_d63_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_32x32_c,
+ &vpx_highbd_d63_predictor_32x32_ssse3, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_8x8_ssse3,
+ &vpx_highbd_d117_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_16x16_ssse3,
+ &vpx_highbd_d117_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_32x32_c,
+ &vpx_highbd_d117_predictor_32x32_ssse3, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_8x8_ssse3,
+ &vpx_highbd_d135_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_16x16_ssse3,
+ &vpx_highbd_d135_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_32x32_ssse3,
+ &vpx_highbd_d135_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_8x8_ssse3,
+ &vpx_highbd_d153_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_16x16_ssse3,
+ &vpx_highbd_d153_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_32x32_ssse3,
+ &vpx_highbd_d153_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_8x8_ssse3,
+ &vpx_highbd_d207_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_16x16_ssse3,
+ &vpx_highbd_d207_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_32x32_ssse3,
+ &vpx_highbd_d207_predictor_32x32_c, 32, 10)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3_TO_C_12, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_4x4_ssse3,
+ &vpx_highbd_d45_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_8x8_ssse3,
+ &vpx_highbd_d45_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_16x16_ssse3,
+ &vpx_highbd_d45_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_32x32_ssse3,
+ &vpx_highbd_d45_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_8x8_ssse3,
+ &vpx_highbd_d63_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_16x16_ssse3,
+ &vpx_highbd_d63_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_32x32_c,
+ &vpx_highbd_d63_predictor_32x32_ssse3, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_8x8_ssse3,
+ &vpx_highbd_d117_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_16x16_ssse3,
+ &vpx_highbd_d117_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_32x32_c,
+ &vpx_highbd_d117_predictor_32x32_ssse3, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_8x8_ssse3,
+ &vpx_highbd_d135_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_16x16_ssse3,
+ &vpx_highbd_d135_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_32x32_ssse3,
+ &vpx_highbd_d135_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_8x8_ssse3,
+ &vpx_highbd_d153_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_16x16_ssse3,
+ &vpx_highbd_d153_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_32x32_ssse3,
+ &vpx_highbd_d153_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_8x8_ssse3,
+ &vpx_highbd_d207_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_16x16_ssse3,
+ &vpx_highbd_d207_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_32x32_ssse3,
+ &vpx_highbd_d207_predictor_32x32_c, 32, 12)));
+#endif // HAVE_SSSE3
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(
+ SSE2_TO_C_8, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_4x4_sse2,
+ &vpx_highbd_dc_128_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_8x8_sse2,
+ &vpx_highbd_dc_128_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_16x16_sse2,
+ &vpx_highbd_dc_128_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_32x32_sse2,
+ &vpx_highbd_dc_128_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_4x4_sse2,
+ &vpx_highbd_d63_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_4x4_sse2,
+ &vpx_highbd_d117_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_4x4_sse2,
+ &vpx_highbd_d135_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_4x4_sse2,
+ &vpx_highbd_d153_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_4x4_sse2,
+ &vpx_highbd_d207_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_4x4_sse2,
+ &vpx_highbd_dc_left_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_8x8_sse2,
+ &vpx_highbd_dc_left_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_16x16_sse2,
+ &vpx_highbd_dc_left_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_32x32_sse2,
+ &vpx_highbd_dc_left_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_4x4_sse2,
+ &vpx_highbd_dc_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_8x8_sse2,
+ &vpx_highbd_dc_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_16x16_sse2,
+ &vpx_highbd_dc_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_32x32_sse2,
+ &vpx_highbd_dc_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_4x4_sse2,
+ &vpx_highbd_dc_top_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_8x8_sse2,
+ &vpx_highbd_dc_top_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_16x16_sse2,
+ &vpx_highbd_dc_top_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_32x32_sse2,
+ &vpx_highbd_dc_top_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_4x4_sse2,
+ &vpx_highbd_tm_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_8x8_sse2,
+ &vpx_highbd_tm_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_16x16_sse2,
+ &vpx_highbd_tm_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_32x32_sse2,
+ &vpx_highbd_tm_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_4x4_sse2,
+ &vpx_highbd_h_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_8x8_sse2,
+ &vpx_highbd_h_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_16x16_sse2,
+ &vpx_highbd_h_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_32x32_sse2,
+ &vpx_highbd_h_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_4x4_sse2,
+ &vpx_highbd_v_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_8x8_sse2,
+ &vpx_highbd_v_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_16x16_sse2,
+ &vpx_highbd_v_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_32x32_sse2,
+ &vpx_highbd_v_predictor_32x32_c, 32, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2_TO_C_10, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_4x4_sse2,
+ &vpx_highbd_dc_128_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_8x8_sse2,
+ &vpx_highbd_dc_128_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_16x16_sse2,
+ &vpx_highbd_dc_128_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_32x32_sse2,
+ &vpx_highbd_dc_128_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_4x4_sse2,
+ &vpx_highbd_d63_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_4x4_sse2,
+ &vpx_highbd_d117_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_4x4_sse2,
+ &vpx_highbd_d135_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_4x4_sse2,
+ &vpx_highbd_d153_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_4x4_sse2,
+ &vpx_highbd_d207_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_4x4_sse2,
+ &vpx_highbd_dc_left_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_8x8_sse2,
+ &vpx_highbd_dc_left_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_16x16_sse2,
+ &vpx_highbd_dc_left_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_32x32_sse2,
+ &vpx_highbd_dc_left_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_4x4_sse2,
+ &vpx_highbd_dc_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_8x8_sse2,
+ &vpx_highbd_dc_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_16x16_sse2,
+ &vpx_highbd_dc_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_32x32_sse2,
+ &vpx_highbd_dc_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_4x4_sse2,
+ &vpx_highbd_dc_top_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_8x8_sse2,
+ &vpx_highbd_dc_top_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_16x16_sse2,
+ &vpx_highbd_dc_top_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_32x32_sse2,
+ &vpx_highbd_dc_top_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_4x4_sse2,
+ &vpx_highbd_tm_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_8x8_sse2,
+ &vpx_highbd_tm_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_16x16_sse2,
+ &vpx_highbd_tm_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_32x32_sse2,
+ &vpx_highbd_tm_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_4x4_sse2,
+ &vpx_highbd_h_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_8x8_sse2,
+ &vpx_highbd_h_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_16x16_sse2,
+ &vpx_highbd_h_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_32x32_sse2,
+ &vpx_highbd_h_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_4x4_sse2,
+ &vpx_highbd_v_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_8x8_sse2,
+ &vpx_highbd_v_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_16x16_sse2,
+ &vpx_highbd_v_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_32x32_sse2,
+ &vpx_highbd_v_predictor_32x32_c, 32, 10)));
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE2_TO_C_12, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_4x4_sse2,
+ &vpx_highbd_dc_128_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_8x8_sse2,
+ &vpx_highbd_dc_128_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_16x16_sse2,
+ &vpx_highbd_dc_128_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_32x32_sse2,
+ &vpx_highbd_dc_128_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_4x4_sse2,
+ &vpx_highbd_d63_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_4x4_sse2,
+ &vpx_highbd_d117_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_4x4_sse2,
+ &vpx_highbd_d135_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_4x4_sse2,
+ &vpx_highbd_d153_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_4x4_sse2,
+ &vpx_highbd_d207_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_4x4_sse2,
+ &vpx_highbd_dc_left_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_8x8_sse2,
+ &vpx_highbd_dc_left_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_16x16_sse2,
+ &vpx_highbd_dc_left_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_32x32_sse2,
+ &vpx_highbd_dc_left_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_4x4_sse2,
+ &vpx_highbd_dc_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_8x8_sse2,
+ &vpx_highbd_dc_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_16x16_sse2,
+ &vpx_highbd_dc_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_32x32_sse2,
+ &vpx_highbd_dc_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_4x4_sse2,
+ &vpx_highbd_dc_top_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_8x8_sse2,
+ &vpx_highbd_dc_top_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_16x16_sse2,
+ &vpx_highbd_dc_top_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_32x32_sse2,
+ &vpx_highbd_dc_top_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_4x4_sse2,
+ &vpx_highbd_tm_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_8x8_sse2,
+ &vpx_highbd_tm_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_16x16_sse2,
+ &vpx_highbd_tm_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_32x32_sse2,
+ &vpx_highbd_tm_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_4x4_sse2,
+ &vpx_highbd_h_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_8x8_sse2,
+ &vpx_highbd_h_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_16x16_sse2,
+ &vpx_highbd_h_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_32x32_sse2,
+ &vpx_highbd_h_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_4x4_sse2,
+ &vpx_highbd_v_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_8x8_sse2,
+ &vpx_highbd_v_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_16x16_sse2,
+ &vpx_highbd_v_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_32x32_sse2,
+ &vpx_highbd_v_predictor_32x32_c, 32, 12)));
+#endif // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(
+ NEON_TO_C_8, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_4x4_neon,
+ &vpx_highbd_d45_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_8x8_neon,
+ &vpx_highbd_d45_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_16x16_neon,
+ &vpx_highbd_d45_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_32x32_neon,
+ &vpx_highbd_d45_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_4x4_neon,
+ &vpx_highbd_d63_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_8x8_neon,
+ &vpx_highbd_d63_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_16x16_neon,
+ &vpx_highbd_d63_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_32x32_neon,
+ &vpx_highbd_d63_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_4x4_neon,
+ &vpx_highbd_d117_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_8x8_neon,
+ &vpx_highbd_d117_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_16x16_neon,
+ &vpx_highbd_d117_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_32x32_neon,
+ &vpx_highbd_d117_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_4x4_neon,
+ &vpx_highbd_d135_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_8x8_neon,
+ &vpx_highbd_d135_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_16x16_neon,
+ &vpx_highbd_d135_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_32x32_neon,
+ &vpx_highbd_d135_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_4x4_neon,
+ &vpx_highbd_d153_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_8x8_neon,
+ &vpx_highbd_d153_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_16x16_neon,
+ &vpx_highbd_d153_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_32x32_neon,
+ &vpx_highbd_d153_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_4x4_neon,
+ &vpx_highbd_d207_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_8x8_neon,
+ &vpx_highbd_d207_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_16x16_neon,
+ &vpx_highbd_d207_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_32x32_neon,
+ &vpx_highbd_d207_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_4x4_neon,
+ &vpx_highbd_dc_128_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_8x8_neon,
+ &vpx_highbd_dc_128_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_16x16_neon,
+ &vpx_highbd_dc_128_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_32x32_neon,
+ &vpx_highbd_dc_128_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_4x4_neon,
+ &vpx_highbd_dc_left_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_8x8_neon,
+ &vpx_highbd_dc_left_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_16x16_neon,
+ &vpx_highbd_dc_left_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_32x32_neon,
+ &vpx_highbd_dc_left_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_4x4_neon,
+ &vpx_highbd_dc_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_8x8_neon,
+ &vpx_highbd_dc_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_16x16_neon,
+ &vpx_highbd_dc_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_32x32_neon,
+ &vpx_highbd_dc_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_4x4_neon,
+ &vpx_highbd_dc_top_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_8x8_neon,
+ &vpx_highbd_dc_top_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_16x16_neon,
+ &vpx_highbd_dc_top_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_32x32_neon,
+ &vpx_highbd_dc_top_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_4x4_neon,
+ &vpx_highbd_h_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_8x8_neon,
+ &vpx_highbd_h_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_16x16_neon,
+ &vpx_highbd_h_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_32x32_neon,
+ &vpx_highbd_h_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_4x4_neon,
+ &vpx_highbd_tm_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_8x8_neon,
+ &vpx_highbd_tm_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_16x16_neon,
+ &vpx_highbd_tm_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_32x32_neon,
+ &vpx_highbd_tm_predictor_32x32_c, 32, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_4x4_neon,
+ &vpx_highbd_v_predictor_4x4_c, 4, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_8x8_neon,
+ &vpx_highbd_v_predictor_8x8_c, 8, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_16x16_neon,
+ &vpx_highbd_v_predictor_16x16_c, 16, 8),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_32x32_neon,
+ &vpx_highbd_v_predictor_32x32_c, 32, 8)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON_TO_C_10, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_4x4_neon,
+ &vpx_highbd_d45_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_8x8_neon,
+ &vpx_highbd_d45_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_16x16_neon,
+ &vpx_highbd_d45_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_32x32_neon,
+ &vpx_highbd_d45_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_4x4_neon,
+ &vpx_highbd_d63_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_8x8_neon,
+ &vpx_highbd_d63_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_16x16_neon,
+ &vpx_highbd_d63_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_32x32_neon,
+ &vpx_highbd_d63_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_4x4_neon,
+ &vpx_highbd_d117_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_8x8_neon,
+ &vpx_highbd_d117_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_16x16_neon,
+ &vpx_highbd_d117_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_32x32_neon,
+ &vpx_highbd_d117_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_4x4_neon,
+ &vpx_highbd_d135_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_8x8_neon,
+ &vpx_highbd_d135_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_16x16_neon,
+ &vpx_highbd_d135_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_32x32_neon,
+ &vpx_highbd_d135_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_4x4_neon,
+ &vpx_highbd_d153_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_8x8_neon,
+ &vpx_highbd_d153_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_16x16_neon,
+ &vpx_highbd_d153_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_32x32_neon,
+ &vpx_highbd_d153_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_4x4_neon,
+ &vpx_highbd_d207_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_8x8_neon,
+ &vpx_highbd_d207_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_16x16_neon,
+ &vpx_highbd_d207_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_32x32_neon,
+ &vpx_highbd_d207_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_4x4_neon,
+ &vpx_highbd_dc_128_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_8x8_neon,
+ &vpx_highbd_dc_128_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_16x16_neon,
+ &vpx_highbd_dc_128_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_32x32_neon,
+ &vpx_highbd_dc_128_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_4x4_neon,
+ &vpx_highbd_dc_left_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_8x8_neon,
+ &vpx_highbd_dc_left_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_16x16_neon,
+ &vpx_highbd_dc_left_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_32x32_neon,
+ &vpx_highbd_dc_left_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_4x4_neon,
+ &vpx_highbd_dc_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_8x8_neon,
+ &vpx_highbd_dc_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_16x16_neon,
+ &vpx_highbd_dc_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_32x32_neon,
+ &vpx_highbd_dc_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_4x4_neon,
+ &vpx_highbd_dc_top_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_8x8_neon,
+ &vpx_highbd_dc_top_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_16x16_neon,
+ &vpx_highbd_dc_top_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_32x32_neon,
+ &vpx_highbd_dc_top_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_4x4_neon,
+ &vpx_highbd_h_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_8x8_neon,
+ &vpx_highbd_h_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_16x16_neon,
+ &vpx_highbd_h_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_32x32_neon,
+ &vpx_highbd_h_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_4x4_neon,
+ &vpx_highbd_tm_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_8x8_neon,
+ &vpx_highbd_tm_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_16x16_neon,
+ &vpx_highbd_tm_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_32x32_neon,
+ &vpx_highbd_tm_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_4x4_neon,
+ &vpx_highbd_v_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_8x8_neon,
+ &vpx_highbd_v_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_16x16_neon,
+ &vpx_highbd_v_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_32x32_neon,
+ &vpx_highbd_v_predictor_32x32_c, 32, 10)));
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON_TO_C_12, VP9HighbdIntraPredTest,
+ ::testing::Values(
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_4x4_neon,
+ &vpx_highbd_d45_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_8x8_neon,
+ &vpx_highbd_d45_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_16x16_neon,
+ &vpx_highbd_d45_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d45_predictor_32x32_neon,
+ &vpx_highbd_d45_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_4x4_neon,
+ &vpx_highbd_d63_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_8x8_neon,
+ &vpx_highbd_d63_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_16x16_neon,
+ &vpx_highbd_d63_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d63_predictor_32x32_neon,
+ &vpx_highbd_d63_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_4x4_neon,
+ &vpx_highbd_d117_predictor_4x4_c, 4, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_8x8_neon,
+ &vpx_highbd_d117_predictor_8x8_c, 8, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_16x16_neon,
+ &vpx_highbd_d117_predictor_16x16_c, 16, 10),
+ HighbdIntraPredParam(&vpx_highbd_d117_predictor_32x32_neon,
+ &vpx_highbd_d117_predictor_32x32_c, 32, 10),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_4x4_neon,
+ &vpx_highbd_d135_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_8x8_neon,
+ &vpx_highbd_d135_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_16x16_neon,
+ &vpx_highbd_d135_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d135_predictor_32x32_neon,
+ &vpx_highbd_d135_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_4x4_neon,
+ &vpx_highbd_d153_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_8x8_neon,
+ &vpx_highbd_d153_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_16x16_neon,
+ &vpx_highbd_d153_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d153_predictor_32x32_neon,
+ &vpx_highbd_d153_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_4x4_neon,
+ &vpx_highbd_d207_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_8x8_neon,
+ &vpx_highbd_d207_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_16x16_neon,
+ &vpx_highbd_d207_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_d207_predictor_32x32_neon,
+ &vpx_highbd_d207_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_4x4_neon,
+ &vpx_highbd_dc_128_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_8x8_neon,
+ &vpx_highbd_dc_128_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_16x16_neon,
+ &vpx_highbd_dc_128_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_128_predictor_32x32_neon,
+ &vpx_highbd_dc_128_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_4x4_neon,
+ &vpx_highbd_dc_left_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_8x8_neon,
+ &vpx_highbd_dc_left_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_16x16_neon,
+ &vpx_highbd_dc_left_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_left_predictor_32x32_neon,
+ &vpx_highbd_dc_left_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_4x4_neon,
+ &vpx_highbd_dc_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_8x8_neon,
+ &vpx_highbd_dc_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_16x16_neon,
+ &vpx_highbd_dc_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_predictor_32x32_neon,
+ &vpx_highbd_dc_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_4x4_neon,
+ &vpx_highbd_dc_top_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_8x8_neon,
+ &vpx_highbd_dc_top_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_16x16_neon,
+ &vpx_highbd_dc_top_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_dc_top_predictor_32x32_neon,
+ &vpx_highbd_dc_top_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_4x4_neon,
+ &vpx_highbd_h_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_8x8_neon,
+ &vpx_highbd_h_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_16x16_neon,
+ &vpx_highbd_h_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_h_predictor_32x32_neon,
+ &vpx_highbd_h_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_4x4_neon,
+ &vpx_highbd_tm_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_8x8_neon,
+ &vpx_highbd_tm_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_16x16_neon,
+ &vpx_highbd_tm_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_tm_predictor_32x32_neon,
+ &vpx_highbd_tm_predictor_32x32_c, 32, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_4x4_neon,
+ &vpx_highbd_v_predictor_4x4_c, 4, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_8x8_neon,
+ &vpx_highbd_v_predictor_8x8_c, 8, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_16x16_neon,
+ &vpx_highbd_v_predictor_16x16_c, 16, 12),
+ HighbdIntraPredParam(&vpx_highbd_v_predictor_32x32_neon,
+ &vpx_highbd_v_predictor_32x32_c, 32, 12)));
+#endif // HAVE_NEON
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_lossless_test.cc b/media/libvpx/libvpx/test/vp9_lossless_test.cc
new file mode 100644
index 0000000000..931ac30a36
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_lossless_test.cc
@@ -0,0 +1,125 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+
+namespace {
+
+const int kMaxPsnr = 100;
+
+class LosslessTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+ LosslessTest()
+ : EncoderTest(GET_PARAM(0)), psnr_(kMaxPsnr), nframes_(0),
+ encoding_mode_(GET_PARAM(1)) {}
+
+ virtual ~LosslessTest() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ // Only call Control if quantizer > 0 to verify that using quantizer
+ // alone will activate lossless
+ if (cfg_.rc_max_quantizer > 0 || cfg_.rc_min_quantizer > 0) {
+ encoder->Control(VP9E_SET_LOSSLESS, 1);
+ }
+ }
+ }
+
+ virtual void BeginPassHook(unsigned int /*pass*/) {
+ psnr_ = kMaxPsnr;
+ nframes_ = 0;
+ }
+
+ virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+ if (pkt->data.psnr.psnr[0] < psnr_) psnr_ = pkt->data.psnr.psnr[0];
+ }
+
+ double GetMinPsnr() const { return psnr_; }
+
+ private:
+ double psnr_;
+ unsigned int nframes_;
+ libvpx_test::TestMode encoding_mode_;
+};
+
+TEST_P(LosslessTest, TestLossLessEncoding) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 2000;
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 0;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ // intentionally changed the dimension for better testing coverage
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 10);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double psnr_lossless = GetMinPsnr();
+ EXPECT_GE(psnr_lossless, kMaxPsnr);
+}
+
+TEST_P(LosslessTest, TestLossLessEncoding444) {
+ libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 10);
+
+ cfg_.g_profile = 1;
+ cfg_.g_timebase = video.timebase();
+ cfg_.rc_target_bitrate = 2000;
+ cfg_.g_lag_in_frames = 25;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 0;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double psnr_lossless = GetMinPsnr();
+ EXPECT_GE(psnr_lossless, kMaxPsnr);
+}
+
+TEST_P(LosslessTest, TestLossLessEncodingCtrl) {
+ const vpx_rational timebase = { 33333333, 1000000000 };
+ cfg_.g_timebase = timebase;
+ cfg_.rc_target_bitrate = 2000;
+ cfg_.g_lag_in_frames = 25;
+ // Intentionally set Q > 0, to make sure control can be used to activate
+ // lossless
+ cfg_.rc_min_quantizer = 10;
+ cfg_.rc_max_quantizer = 20;
+
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+ timebase.den, timebase.num, 0, 10);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ const double psnr_lossless = GetMinPsnr();
+ EXPECT_GE(psnr_lossless, kMaxPsnr);
+}
+
+VP9_INSTANTIATE_TEST_SUITE(LosslessTest,
+ ::testing::Values(::libvpx_test::kRealTime,
+ ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kTwoPassGood));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_motion_vector_test.cc b/media/libvpx/libvpx/test/vp9_motion_vector_test.cc
new file mode 100644
index 0000000000..6b1082a106
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_motion_vector_test.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 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 <memory>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/yuv_video_source.h"
+
+namespace {
+#define MAX_EXTREME_MV 1
+#define MIN_EXTREME_MV 2
+
+// Encoding modes
+const libvpx_test::TestMode kEncodingModeVectors[] = {
+ ::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime
+};
+
+// Encoding speeds
+const int kCpuUsedVectors[] = { 0, 1, 2, 3, 4, 5, 6 };
+
+// MV test modes: 1 - always use maximum MV; 2 - always use minimum MV.
+const int kMVTestModes[] = { MAX_EXTREME_MV, MIN_EXTREME_MV };
+
+class MotionVectorTestLarge
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith3Params<libvpx_test::TestMode, int,
+ int> {
+ protected:
+ MotionVectorTestLarge()
+ : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)),
+ cpu_used_(GET_PARAM(2)), mv_test_mode_(GET_PARAM(3)) {}
+
+ virtual ~MotionVectorTestLarge() {}
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(encoding_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ cfg_.g_lag_in_frames = 3;
+ cfg_.rc_end_usage = VPX_VBR;
+ } else {
+ cfg_.g_lag_in_frames = 0;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ }
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+ encoder->Control(VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, mv_test_mode_);
+ if (encoding_mode_ != ::libvpx_test::kRealTime) {
+ encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+ encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+ encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+ encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+ }
+ }
+ }
+
+ libvpx_test::TestMode encoding_mode_;
+ int cpu_used_;
+ int mv_test_mode_;
+};
+
+TEST_P(MotionVectorTestLarge, OverallTest) {
+ cfg_.rc_target_bitrate = 24000;
+ cfg_.g_profile = 0;
+ init_flags_ = VPX_CODEC_USE_PSNR;
+
+ std::unique_ptr<libvpx_test::VideoSource> video;
+ video.reset(new libvpx_test::YUVVideoSource(
+ "niklas_640_480_30.yuv", VPX_IMG_FMT_I420, 3840, 2160, // 2048, 1080,
+ 30, 1, 0, 5));
+
+ ASSERT_NE(video.get(), nullptr);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
+}
+
+VP9_INSTANTIATE_TEST_SUITE(MotionVectorTestLarge,
+ ::testing::ValuesIn(kEncodingModeVectors),
+ ::testing::ValuesIn(kCpuUsedVectors),
+ ::testing::ValuesIn(kMVTestModes));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_quantize_test.cc b/media/libvpx/libvpx/test/vp9_quantize_test.cc
new file mode 100644
index 0000000000..5e3a7c2701
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_quantize_test.cc
@@ -0,0 +1,758 @@
+/*
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/buffer.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_scan.h"
+#include "vp9/encoder/vp9_block.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/msvc.h"
+#include "vpx_ports/vpx_timer.h"
+
+using libvpx_test::ACMRandom;
+using libvpx_test::Buffer;
+
+namespace {
+const int number_of_iterations = 100;
+
+typedef void (*QuantizeFunc)(const tran_low_t *coeff, intptr_t count,
+ const macroblock_plane *mb_plane,
+ tran_low_t *qcoeff, tran_low_t *dqcoeff,
+ const int16_t *dequant, uint16_t *eob,
+ const struct ScanOrder *scan_order);
+typedef std::tuple<QuantizeFunc, QuantizeFunc, vpx_bit_depth_t,
+ int /*max_size*/, bool /*is_fp*/>
+ QuantizeParam;
+
+// Wrapper which takes a macroblock_plane.
+typedef void (*QuantizeBaseFunc)(const tran_low_t *coeff, intptr_t count,
+ const int16_t *zbin, const int16_t *round,
+ const int16_t *quant,
+ const int16_t *quant_shift, tran_low_t *qcoeff,
+ tran_low_t *dqcoeff, const int16_t *dequant,
+ uint16_t *eob, const int16_t *scan,
+ const int16_t *iscan);
+
+template <QuantizeBaseFunc fn>
+void QuantWrapper(const tran_low_t *coeff, intptr_t count,
+ const macroblock_plane *const mb_plane, tran_low_t *qcoeff,
+ tran_low_t *dqcoeff, const int16_t *dequant, uint16_t *eob,
+ const struct ScanOrder *const scan_order) {
+ fn(coeff, count, mb_plane->zbin, mb_plane->round, mb_plane->quant,
+ mb_plane->quant_shift, qcoeff, dqcoeff, dequant, eob, scan_order->scan,
+ scan_order->iscan);
+}
+
+// Wrapper for 32x32 version which does not use count
+typedef void (*Quantize32x32Func)(const tran_low_t *coeff,
+ const macroblock_plane *const mb_plane,
+ tran_low_t *qcoeff, tran_low_t *dqcoeff,
+ const int16_t *dequant, uint16_t *eob,
+ const struct ScanOrder *const scan_order);
+
+template <Quantize32x32Func fn>
+void Quant32x32Wrapper(const tran_low_t *coeff, intptr_t count,
+ const macroblock_plane *const mb_plane,
+ tran_low_t *qcoeff, tran_low_t *dqcoeff,
+ const int16_t *dequant, uint16_t *eob,
+ const struct ScanOrder *const scan_order) {
+ (void)count;
+ fn(coeff, mb_plane, qcoeff, dqcoeff, dequant, eob, scan_order);
+}
+
+// Wrapper for FP version which does not use zbin or quant_shift.
+typedef void (*QuantizeFPFunc)(const tran_low_t *coeff, intptr_t count,
+ const int16_t *round, const int16_t *quant,
+ tran_low_t *qcoeff, tran_low_t *dqcoeff,
+ const int16_t *dequant, uint16_t *eob,
+ const int16_t *scan, const int16_t *iscan);
+
+template <QuantizeFPFunc fn>
+void QuantFPWrapper(const tran_low_t *coeff, intptr_t count,
+ const macroblock_plane *const mb_plane, tran_low_t *qcoeff,
+ tran_low_t *dqcoeff, const int16_t *dequant, uint16_t *eob,
+ const struct ScanOrder *const scan_order) {
+ fn(coeff, count, mb_plane->round_fp, mb_plane->quant_fp, qcoeff, dqcoeff,
+ dequant, eob, scan_order->scan, scan_order->iscan);
+}
+
+void GenerateHelperArrays(ACMRandom *rnd, int16_t *zbin, int16_t *round,
+ int16_t *quant, int16_t *quant_shift,
+ int16_t *dequant, int16_t *round_fp,
+ int16_t *quant_fp) {
+ // Max when q == 0. Otherwise, it is 48 for Y and 42 for U/V.
+ constexpr int kMaxQRoundingFactorFp = 64;
+
+ for (int j = 0; j < 2; j++) {
+ // The range is 4 to 1828 in the VP9 tables.
+ const int qlookup = rnd->RandRange(1825) + 4;
+ round_fp[j] = (kMaxQRoundingFactorFp * qlookup) >> 7;
+ quant_fp[j] = (1 << 16) / qlookup;
+
+ // Values determined by deconstructing vp9_init_quantizer().
+ // zbin may be up to 1143 for 8 and 10 bit Y values, or 1200 for 12 bit Y
+ // values or U/V values of any bit depth. This is because y_delta is not
+ // factored into the vp9_ac_quant() call.
+ zbin[j] = rnd->RandRange(1200);
+
+ // round may be up to 685 for Y values or 914 for U/V.
+ round[j] = rnd->RandRange(914);
+ // quant ranges from 1 to -32703
+ quant[j] = static_cast<int>(rnd->RandRange(32704)) - 32703;
+ // quant_shift goes up to 1 << 16.
+ quant_shift[j] = rnd->RandRange(16384);
+ // dequant maxes out at 1828 for all cases.
+ dequant[j] = rnd->RandRange(1828);
+ }
+ for (int j = 2; j < 8; j++) {
+ zbin[j] = zbin[1];
+ round_fp[j] = round_fp[1];
+ quant_fp[j] = quant_fp[1];
+ round[j] = round[1];
+ quant[j] = quant[1];
+ quant_shift[j] = quant_shift[1];
+ dequant[j] = dequant[1];
+ }
+}
+
+class VP9QuantizeBase : public AbstractBench {
+ public:
+ VP9QuantizeBase(vpx_bit_depth_t bit_depth, int max_size, bool is_fp)
+ : bit_depth_(bit_depth), max_size_(max_size), is_fp_(is_fp),
+ coeff_(Buffer<tran_low_t>(max_size_, max_size_, 0, 16)),
+ qcoeff_(Buffer<tran_low_t>(max_size_, max_size_, 0, 32)),
+ dqcoeff_(Buffer<tran_low_t>(max_size_, max_size_, 0, 32)) {
+ // TODO(jianj): SSSE3 and AVX2 tests fail on extreme values.
+#if HAVE_NEON
+ max_value_ = (1 << (7 + bit_depth_)) - 1;
+#else
+ max_value_ = (1 << bit_depth_) - 1;
+#endif
+
+ mb_plane_ = reinterpret_cast<macroblock_plane *>(
+ vpx_memalign(16, sizeof(macroblock_plane)));
+
+ zbin_ptr_ = mb_plane_->zbin =
+ reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*zbin_ptr_)));
+ round_fp_ptr_ = mb_plane_->round_fp = reinterpret_cast<int16_t *>(
+ vpx_memalign(16, 8 * sizeof(*round_fp_ptr_)));
+ quant_fp_ptr_ = mb_plane_->quant_fp = reinterpret_cast<int16_t *>(
+ vpx_memalign(16, 8 * sizeof(*quant_fp_ptr_)));
+ round_ptr_ = mb_plane_->round =
+ reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*round_ptr_)));
+ quant_ptr_ = mb_plane_->quant =
+ reinterpret_cast<int16_t *>(vpx_memalign(16, 8 * sizeof(*quant_ptr_)));
+ quant_shift_ptr_ = mb_plane_->quant_shift = reinterpret_cast<int16_t *>(
+ vpx_memalign(16, 8 * sizeof(*quant_shift_ptr_)));
+ dequant_ptr_ = reinterpret_cast<int16_t *>(
+ vpx_memalign(16, 8 * sizeof(*dequant_ptr_)));
+
+ r_ptr_ = (is_fp_) ? round_fp_ptr_ : round_ptr_;
+ q_ptr_ = (is_fp_) ? quant_fp_ptr_ : quant_ptr_;
+ }
+
+ ~VP9QuantizeBase() {
+ vpx_free(mb_plane_);
+ vpx_free(zbin_ptr_);
+ vpx_free(round_fp_ptr_);
+ vpx_free(quant_fp_ptr_);
+ vpx_free(round_ptr_);
+ vpx_free(quant_ptr_);
+ vpx_free(quant_shift_ptr_);
+ vpx_free(dequant_ptr_);
+ mb_plane_ = nullptr;
+ zbin_ptr_ = nullptr;
+ round_fp_ptr_ = nullptr;
+ quant_fp_ptr_ = nullptr;
+ round_ptr_ = nullptr;
+ quant_ptr_ = nullptr;
+ quant_shift_ptr_ = nullptr;
+ dequant_ptr_ = nullptr;
+ libvpx_test::ClearSystemState();
+ }
+
+ protected:
+ macroblock_plane *mb_plane_;
+ int16_t *zbin_ptr_;
+ int16_t *quant_fp_ptr_;
+ int16_t *round_fp_ptr_;
+ int16_t *round_ptr_;
+ int16_t *quant_ptr_;
+ int16_t *quant_shift_ptr_;
+ int16_t *dequant_ptr_;
+ const vpx_bit_depth_t bit_depth_;
+ int max_value_;
+ const int max_size_;
+ const bool is_fp_;
+ Buffer<tran_low_t> coeff_;
+ Buffer<tran_low_t> qcoeff_;
+ Buffer<tran_low_t> dqcoeff_;
+ int16_t *r_ptr_;
+ int16_t *q_ptr_;
+ int count_;
+ const ScanOrder *scan_;
+ uint16_t eob_;
+};
+
+class VP9QuantizeTest : public VP9QuantizeBase,
+ public ::testing::TestWithParam<QuantizeParam> {
+ public:
+ VP9QuantizeTest()
+ : VP9QuantizeBase(GET_PARAM(2), GET_PARAM(3), GET_PARAM(4)),
+ quantize_op_(GET_PARAM(0)), ref_quantize_op_(GET_PARAM(1)) {}
+
+ protected:
+ virtual void Run();
+ void Speed(bool is_median);
+ const QuantizeFunc quantize_op_;
+ const QuantizeFunc ref_quantize_op_;
+};
+
+void VP9QuantizeTest::Run() {
+ quantize_op_(coeff_.TopLeftPixel(), count_, mb_plane_, qcoeff_.TopLeftPixel(),
+ dqcoeff_.TopLeftPixel(), dequant_ptr_, &eob_, scan_);
+}
+
+void VP9QuantizeTest::Speed(bool is_median) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ ASSERT_TRUE(coeff_.Init());
+ ASSERT_TRUE(qcoeff_.Init());
+ ASSERT_TRUE(dqcoeff_.Init());
+ TX_SIZE starting_sz, ending_sz;
+
+ if (max_size_ == 16) {
+ starting_sz = TX_4X4;
+ ending_sz = TX_16X16;
+ } else {
+ starting_sz = TX_32X32;
+ ending_sz = TX_32X32;
+ }
+
+ for (TX_SIZE sz = starting_sz; sz <= ending_sz; ++sz) {
+ // zbin > coeff, zbin < coeff.
+ for (int i = 0; i < 2; ++i) {
+ // TX_TYPE defines the scan order. That is not relevant to the speed test.
+ // Pick the first one.
+ const TX_TYPE tx_type = DCT_DCT;
+ count_ = (4 << sz) * (4 << sz);
+ scan_ = &vp9_scan_orders[sz][tx_type];
+
+ GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_,
+ quant_shift_ptr_, dequant_ptr_, round_fp_ptr_,
+ quant_fp_ptr_);
+
+ if (i == 0) {
+ // When |coeff values| are less than zbin the results are 0.
+ int threshold = 100;
+ if (max_size_ == 32) {
+ // For 32x32, the threshold is halved. Double it to keep the values
+ // from clearing it.
+ threshold = 200;
+ }
+ for (int j = 0; j < 8; ++j) zbin_ptr_[j] = threshold;
+ coeff_.Set(&rnd, -99, 99);
+ } else if (i == 1) {
+ for (int j = 0; j < 8; ++j) zbin_ptr_[j] = 50;
+ coeff_.Set(&rnd, -500, 500);
+ }
+
+ const char *type =
+ (i == 0) ? "Bypass calculations " : "Full calculations ";
+ char block_size[16];
+ snprintf(block_size, sizeof(block_size), "%dx%d", 4 << sz, 4 << sz);
+ char title[100];
+ snprintf(title, sizeof(title), "%25s %8s ", type, block_size);
+
+ if (is_median) {
+ RunNTimes(10000000 / count_);
+ PrintMedian(title);
+ } else {
+ Buffer<tran_low_t> ref_qcoeff =
+ Buffer<tran_low_t>(max_size_, max_size_, 0, 32);
+ ASSERT_TRUE(ref_qcoeff.Init());
+ Buffer<tran_low_t> ref_dqcoeff =
+ Buffer<tran_low_t>(max_size_, max_size_, 0, 32);
+ ASSERT_TRUE(ref_dqcoeff.Init());
+ uint16_t ref_eob = 0;
+
+ const int kNumTests = 5000000;
+ vpx_usec_timer timer, simd_timer;
+
+ vpx_usec_timer_start(&timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ ref_quantize_op_(coeff_.TopLeftPixel(), count_, mb_plane_,
+ ref_qcoeff.TopLeftPixel(),
+ ref_dqcoeff.TopLeftPixel(), dequant_ptr_, &ref_eob,
+ scan_);
+ }
+ vpx_usec_timer_mark(&timer);
+
+ vpx_usec_timer_start(&simd_timer);
+ for (int n = 0; n < kNumTests; ++n) {
+ quantize_op_(coeff_.TopLeftPixel(), count_, mb_plane_,
+ qcoeff_.TopLeftPixel(), dqcoeff_.TopLeftPixel(),
+ dequant_ptr_, &eob_, scan_);
+ }
+ vpx_usec_timer_mark(&simd_timer);
+
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer));
+ const int simd_elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&simd_timer));
+ printf("%s c_time = %d \t simd_time = %d \t Gain = %f \n", title,
+ elapsed_time, simd_elapsed_time,
+ ((float)elapsed_time / simd_elapsed_time));
+ }
+ }
+ }
+}
+
+// This quantizer compares the AC coefficients to the quantization step size to
+// determine if further multiplication operations are needed.
+// Based on vp9_quantize_fp_sse2().
+inline void quant_fp_nz(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
+ const int16_t *round_ptr, const int16_t *quant_ptr,
+ tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
+ const int16_t *dequant_ptr, uint16_t *eob_ptr,
+ const int16_t *scan, const int16_t *iscan,
+ int is_32x32) {
+ int i, eob = -1;
+ const int thr = dequant_ptr[1] >> (1 + is_32x32);
+ (void)iscan;
+
+ // Quantization pass: All coefficients with index >= zero_flag are
+ // skippable. Note: zero_flag can be zero.
+ for (i = 0; i < n_coeffs; i += 16) {
+ int y;
+ int nzflag_cnt = 0;
+ int abs_coeff[16];
+ int coeff_sign[16];
+
+ // count nzflag for each row (16 tran_low_t)
+ for (y = 0; y < 16; ++y) {
+ const int rc = i + y;
+ const int coeff = coeff_ptr[rc];
+ coeff_sign[y] = (coeff >> 31);
+ abs_coeff[y] = (coeff ^ coeff_sign[y]) - coeff_sign[y];
+ // The first 16 are skipped in the sse2 code. Do the same here to match.
+ if (i >= 16 && (abs_coeff[y] <= thr)) {
+ nzflag_cnt++;
+ }
+ }
+
+ for (y = 0; y < 16; ++y) {
+ const int rc = i + y;
+ // If all of the AC coeffs in a row has magnitude less than the
+ // quantization step_size/2, quantize to zero.
+ if (nzflag_cnt < 16) {
+ int tmp;
+ int _round;
+
+ if (is_32x32) {
+ _round = ROUND_POWER_OF_TWO(round_ptr[rc != 0], 1);
+ } else {
+ _round = round_ptr[rc != 0];
+ }
+ tmp = clamp(abs_coeff[y] + _round, INT16_MIN, INT16_MAX);
+ tmp = (tmp * quant_ptr[rc != 0]) >> (16 - is_32x32);
+ qcoeff_ptr[rc] = (tmp ^ coeff_sign[y]) - coeff_sign[y];
+ dqcoeff_ptr[rc] =
+ static_cast<tran_low_t>(qcoeff_ptr[rc] * dequant_ptr[rc != 0]);
+
+ if (is_32x32) {
+ dqcoeff_ptr[rc] = static_cast<tran_low_t>(qcoeff_ptr[rc] *
+ dequant_ptr[rc != 0] / 2);
+ } else {
+ dqcoeff_ptr[rc] =
+ static_cast<tran_low_t>(qcoeff_ptr[rc] * dequant_ptr[rc != 0]);
+ }
+ } else {
+ qcoeff_ptr[rc] = 0;
+ dqcoeff_ptr[rc] = 0;
+ }
+ }
+ }
+
+ // Scan for eob.
+ for (i = 0; i < n_coeffs; i++) {
+ // Use the scan order to find the correct eob.
+ const int rc = scan[i];
+ if (qcoeff_ptr[rc]) {
+ eob = i;
+ }
+ }
+ *eob_ptr = eob + 1;
+}
+
+void quantize_fp_nz_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
+ const int16_t *round_ptr, const int16_t *quant_ptr,
+ tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
+ const int16_t *dequant_ptr, uint16_t *eob_ptr,
+ const int16_t *scan, const int16_t *iscan) {
+ quant_fp_nz(coeff_ptr, n_coeffs, round_ptr, quant_ptr, qcoeff_ptr,
+ dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, 0);
+}
+
+void quantize_fp_32x32_nz_c(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
+ const int16_t *round_ptr, const int16_t *quant_ptr,
+ tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
+ const int16_t *dequant_ptr, uint16_t *eob_ptr,
+ const int16_t *scan, const int16_t *iscan) {
+ quant_fp_nz(coeff_ptr, n_coeffs, round_ptr, quant_ptr, qcoeff_ptr,
+ dqcoeff_ptr, dequant_ptr, eob_ptr, scan, iscan, 1);
+}
+
+TEST_P(VP9QuantizeTest, OperationCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ ASSERT_TRUE(coeff_.Init());
+ ASSERT_TRUE(qcoeff_.Init());
+ ASSERT_TRUE(dqcoeff_.Init());
+ Buffer<tran_low_t> ref_qcoeff =
+ Buffer<tran_low_t>(max_size_, max_size_, 0, 32);
+ ASSERT_TRUE(ref_qcoeff.Init());
+ Buffer<tran_low_t> ref_dqcoeff =
+ Buffer<tran_low_t>(max_size_, max_size_, 0, 32);
+ ASSERT_TRUE(ref_dqcoeff.Init());
+ uint16_t ref_eob = 0;
+ eob_ = 0;
+
+ for (int i = 0; i < number_of_iterations; ++i) {
+ TX_SIZE sz;
+ if (max_size_ == 16) {
+ sz = static_cast<TX_SIZE>(i % 3); // TX_4X4, TX_8X8 TX_16X16
+ } else {
+ sz = TX_32X32;
+ }
+ const TX_TYPE tx_type = static_cast<TX_TYPE>((i >> 2) % 3);
+ scan_ = &vp9_scan_orders[sz][tx_type];
+ count_ = (4 << sz) * (4 << sz);
+ coeff_.Set(&rnd, -max_value_, max_value_);
+ GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_,
+ quant_shift_ptr_, dequant_ptr_, round_fp_ptr_,
+ quant_fp_ptr_);
+ ref_quantize_op_(coeff_.TopLeftPixel(), count_, mb_plane_,
+ ref_qcoeff.TopLeftPixel(), ref_dqcoeff.TopLeftPixel(),
+ dequant_ptr_, &ref_eob, scan_);
+
+ ASM_REGISTER_STATE_CHECK(quantize_op_(
+ coeff_.TopLeftPixel(), count_, mb_plane_, qcoeff_.TopLeftPixel(),
+ dqcoeff_.TopLeftPixel(), dequant_ptr_, &eob_, scan_));
+
+ EXPECT_TRUE(qcoeff_.CheckValues(ref_qcoeff));
+ EXPECT_TRUE(dqcoeff_.CheckValues(ref_dqcoeff));
+
+ EXPECT_EQ(eob_, ref_eob);
+
+ if (HasFailure()) {
+ printf("Failure on iteration %d.\n", i);
+ qcoeff_.PrintDifference(ref_qcoeff);
+ dqcoeff_.PrintDifference(ref_dqcoeff);
+ return;
+ }
+ }
+}
+
+TEST_P(VP9QuantizeTest, EOBCheck) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+ ASSERT_TRUE(coeff_.Init());
+ ASSERT_TRUE(qcoeff_.Init());
+ ASSERT_TRUE(dqcoeff_.Init());
+ Buffer<tran_low_t> ref_qcoeff =
+ Buffer<tran_low_t>(max_size_, max_size_, 0, 32);
+ ASSERT_TRUE(ref_qcoeff.Init());
+ Buffer<tran_low_t> ref_dqcoeff =
+ Buffer<tran_low_t>(max_size_, max_size_, 0, 32);
+ ASSERT_TRUE(ref_dqcoeff.Init());
+ uint16_t ref_eob = 0;
+ eob_ = 0;
+ const uint32_t max_index = max_size_ * max_size_ - 1;
+
+ for (int i = 0; i < number_of_iterations; ++i) {
+ TX_SIZE sz;
+ if (max_size_ == 16) {
+ sz = static_cast<TX_SIZE>(i % 3); // TX_4X4, TX_8X8 TX_16X16
+ } else {
+ sz = TX_32X32;
+ }
+ const TX_TYPE tx_type = static_cast<TX_TYPE>((i >> 2) % 3);
+ scan_ = &vp9_scan_orders[sz][tx_type];
+ count_ = (4 << sz) * (4 << sz);
+ // Two random entries
+ coeff_.Set(0);
+ coeff_.TopLeftPixel()[rnd.RandRange(count_) & max_index] =
+ static_cast<int>(rnd.RandRange(max_value_ * 2)) - max_value_;
+ coeff_.TopLeftPixel()[rnd.RandRange(count_) & max_index] =
+ static_cast<int>(rnd.RandRange(max_value_ * 2)) - max_value_;
+ GenerateHelperArrays(&rnd, zbin_ptr_, round_ptr_, quant_ptr_,
+ quant_shift_ptr_, dequant_ptr_, round_fp_ptr_,
+ quant_fp_ptr_);
+ ref_quantize_op_(coeff_.TopLeftPixel(), count_, mb_plane_,
+ ref_qcoeff.TopLeftPixel(), ref_dqcoeff.TopLeftPixel(),
+ dequant_ptr_, &ref_eob, scan_);
+
+ ASM_REGISTER_STATE_CHECK(quantize_op_(
+ coeff_.TopLeftPixel(), count_, mb_plane_, qcoeff_.TopLeftPixel(),
+ dqcoeff_.TopLeftPixel(), dequant_ptr_, &eob_, scan_));
+
+ EXPECT_TRUE(qcoeff_.CheckValues(ref_qcoeff));
+ EXPECT_TRUE(dqcoeff_.CheckValues(ref_dqcoeff));
+
+ EXPECT_EQ(eob_, ref_eob);
+
+ if (HasFailure()) {
+ printf("Failure on iteration %d.\n", i);
+ qcoeff_.PrintDifference(ref_qcoeff);
+ dqcoeff_.PrintDifference(ref_dqcoeff);
+ return;
+ }
+ }
+}
+
+TEST_P(VP9QuantizeTest, DISABLED_Speed) { Speed(false); }
+
+TEST_P(VP9QuantizeTest, DISABLED_SpeedMedian) { Speed(true); }
+
+using std::make_tuple;
+
+#if HAVE_SSE2
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VP9QuantizeTest,
+ ::testing::Values(
+ make_tuple(&QuantWrapper<vpx_quantize_b_sse2>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8, 16, false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_sse2>,
+ &QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8, 16, true),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_sse2>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_8, 16,
+ false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_sse2>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_10, 16,
+ false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_sse2>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_12, 16,
+ false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_sse2>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_sse2>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_10, 32, false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_sse2>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_12, 32, false)));
+
+#else
+INSTANTIATE_TEST_SUITE_P(
+ SSE2, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&QuantWrapper<vpx_quantize_b_sse2>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8,
+ 16, false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_sse2>,
+ &QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8,
+ 16, true)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_SSE2
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(
+ SSSE3, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&QuantWrapper<vpx_quantize_b_ssse3>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8,
+ 16, false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_ssse3>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_ssse3>,
+ &QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8,
+ 16, true),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_ssse3>,
+ &QuantFPWrapper<quantize_fp_32x32_nz_c>,
+ VPX_BITS_8, 32, true)));
+#endif // HAVE_SSSE3
+
+#if HAVE_AVX
+INSTANTIATE_TEST_SUITE_P(
+ AVX, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&QuantWrapper<vpx_quantize_b_avx>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8,
+ 16, false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_avx>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false)));
+#endif // HAVE_AVX
+
+#if VPX_ARCH_X86_64 && HAVE_AVX2
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, VP9QuantizeTest,
+ ::testing::Values(
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_avx2>,
+ &QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8, 16, true),
+ make_tuple(&QuantFPWrapper<vp9_highbd_quantize_fp_avx2>,
+ &QuantFPWrapper<vp9_highbd_quantize_fp_c>, VPX_BITS_12, 16,
+ true),
+ make_tuple(&QuantFPWrapper<vp9_highbd_quantize_fp_32x32_avx2>,
+ &QuantFPWrapper<vp9_highbd_quantize_fp_32x32_c>, VPX_BITS_12,
+ 32, true),
+ make_tuple(&QuantWrapper<vpx_quantize_b_avx2>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8, 16, false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_avx2>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_8, 16,
+ false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_avx2>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_10, 16,
+ false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_avx2>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_12, 16,
+ false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_avx2>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>, VPX_BITS_8, 32,
+ false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_avx2>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_avx2>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_10, 32, false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_avx2>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_12, 32, false)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&QuantFPWrapper<vp9_quantize_fp_avx2>,
+ &QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8,
+ 16, true),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_avx2>,
+ &QuantFPWrapper<quantize_fp_32x32_nz_c>,
+ VPX_BITS_8, 32, true),
+ make_tuple(&QuantWrapper<vpx_quantize_b_avx2>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8,
+ 16, false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_avx2>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_AVX2
+
+#if HAVE_NEON
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VP9QuantizeTest,
+ ::testing::Values(
+ make_tuple(&QuantWrapper<vpx_quantize_b_neon>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8, 16, false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_neon>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_8, 16,
+ false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_neon>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_10, 16,
+ false),
+ make_tuple(&QuantWrapper<vpx_highbd_quantize_b_neon>,
+ &QuantWrapper<vpx_highbd_quantize_b_c>, VPX_BITS_12, 16,
+ false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_neon>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>, VPX_BITS_8, 32,
+ false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_neon>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_neon>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_10, 32, false),
+ make_tuple(&Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_neon>,
+ &Quant32x32Wrapper<vpx_highbd_quantize_b_32x32_c>,
+ VPX_BITS_12, 32, false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_neon>,
+ &QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8, 16, true),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_neon>,
+ &QuantFPWrapper<vp9_quantize_fp_32x32_c>, VPX_BITS_8, 32,
+ true)));
+#else
+INSTANTIATE_TEST_SUITE_P(
+ NEON, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&QuantWrapper<vpx_quantize_b_neon>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8,
+ 16, false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_neon>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>,
+ VPX_BITS_8, 32, false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_neon>,
+ &QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8,
+ 16, true),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_neon>,
+ &QuantFPWrapper<vp9_quantize_fp_32x32_c>,
+ VPX_BITS_8, 32, true)));
+#endif // CONFIG_VP9_HIGHBITDEPTH
+#endif // HAVE_NEON
+
+#if HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(
+ VSX, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&vpx_quantize_b_vsx, &vpx_quantize_b_c,
+ VPX_BITS_8, 16, false),
+ make_tuple(&vpx_quantize_b_32x32_vsx,
+ &vpx_quantize_b_32x32_c, VPX_BITS_8, 32,
+ false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_vsx>,
+ &QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8,
+ 16, true),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_vsx>,
+ &QuantFPWrapper<vp9_quantize_fp_32x32_c>,
+ VPX_BITS_8, 32, true)));
+#endif // HAVE_VSX && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_SUITE_P(LSX, VP9QuantizeTest,
+ ::testing::Values(make_tuple(&vpx_quantize_b_lsx,
+ &vpx_quantize_b_c,
+ VPX_BITS_8, 16, false),
+ make_tuple(&vpx_quantize_b_32x32_lsx,
+ &vpx_quantize_b_32x32_c,
+ VPX_BITS_8, 32, false)));
+#endif // HAVE_LSX && !CONFIG_VP9_HIGHBITDEPTH
+
+// Only useful to compare "Speed" test results.
+INSTANTIATE_TEST_SUITE_P(
+ DISABLED_C, VP9QuantizeTest,
+ ::testing::Values(
+ make_tuple(&QuantWrapper<vpx_quantize_b_c>,
+ &QuantWrapper<vpx_quantize_b_c>, VPX_BITS_8, 16, false),
+ make_tuple(&Quant32x32Wrapper<vpx_quantize_b_32x32_c>,
+ &Quant32x32Wrapper<vpx_quantize_b_32x32_c>, VPX_BITS_8, 32,
+ false),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_c>,
+ &QuantFPWrapper<vp9_quantize_fp_c>, VPX_BITS_8, 16, true),
+ make_tuple(&QuantFPWrapper<quantize_fp_nz_c>,
+ &QuantFPWrapper<quantize_fp_nz_c>, VPX_BITS_8, 16, true),
+ make_tuple(&QuantFPWrapper<quantize_fp_32x32_nz_c>,
+ &QuantFPWrapper<quantize_fp_32x32_nz_c>, VPX_BITS_8, 32,
+ true),
+ make_tuple(&QuantFPWrapper<vp9_quantize_fp_32x32_c>,
+ &QuantFPWrapper<vp9_quantize_fp_32x32_c>, VPX_BITS_8, 32,
+ true)));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_ratectrl_rtc_test.cc b/media/libvpx/libvpx/test/vp9_ratectrl_rtc_test.cc
new file mode 100644
index 0000000000..5abda1290a
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_ratectrl_rtc_test.cc
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 2020 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 "vp9/ratectrl_rtc.h"
+
+#include <fstream> // NOLINT
+#include <string>
+
+#include "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/video_source.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_ports/bitops.h"
+
+namespace {
+
+const size_t kNumFrames = 300;
+
+const int kTemporalId3Layer[4] = { 0, 2, 1, 2 };
+const int kTemporalId2Layer[2] = { 0, 1 };
+const int kTemporalRateAllocation3Layer[3] = { 50, 70, 100 };
+const int kTemporalRateAllocation2Layer[2] = { 60, 100 };
+const int kSpatialLayerBitrate[3] = { 200, 400, 1000 };
+
+class RcInterfaceTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<int, vpx_rc_mode> {
+ public:
+ RcInterfaceTest()
+ : EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)), key_interval_(3000),
+ encoder_exit_(false) {}
+
+ virtual ~RcInterfaceTest() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, 7);
+ encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
+ encoder->Control(VP9E_SET_TUNE_CONTENT, 0);
+ encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 1000);
+ encoder->Control(VP9E_SET_RTC_EXTERNAL_RATECTRL, 1);
+ }
+ frame_params_.frame_type = video->frame() % key_interval_ == 0
+ ? libvpx::RcFrameType::kKeyFrame
+ : libvpx::RcFrameType::kInterFrame;
+ if (rc_cfg_.rc_mode == VPX_CBR &&
+ frame_params_.frame_type == libvpx::RcFrameType::kInterFrame) {
+ // Disable golden frame update.
+ frame_flags_ |= VP8_EFLAG_NO_UPD_GF;
+ frame_flags_ |= VP8_EFLAG_NO_UPD_ARF;
+ }
+ encoder_exit_ = video->frame() == kNumFrames;
+ }
+
+ virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+ if (encoder_exit_) {
+ return;
+ }
+ int loopfilter_level, qp;
+ encoder->Control(VP9E_GET_LOOPFILTER_LEVEL, &loopfilter_level);
+ encoder->Control(VP8E_GET_LAST_QUANTIZER, &qp);
+ rc_api_->ComputeQP(frame_params_);
+ ASSERT_EQ(rc_api_->GetQP(), qp);
+ ASSERT_EQ(rc_api_->GetLoopfilterLevel(), loopfilter_level);
+ }
+
+ virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+ rc_api_->PostEncodeUpdate(pkt->data.frame.sz, frame_params_);
+ }
+
+ void RunOneLayer() {
+ SetConfig(GET_PARAM(2));
+ rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
+ frame_params_.spatial_layer_id = 0;
+ frame_params_.temporal_layer_id = 0;
+
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
+ 1280, 720, 30, 1, 0, kNumFrames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunOneLayerVBRPeriodicKey() {
+ if (GET_PARAM(2) != VPX_VBR) return;
+ key_interval_ = 100;
+ SetConfig(VPX_VBR);
+ rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
+ frame_params_.spatial_layer_id = 0;
+ frame_params_.temporal_layer_id = 0;
+
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
+ 1280, 720, 30, 1, 0, kNumFrames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ private:
+ void SetConfig(vpx_rc_mode rc_mode) {
+ rc_cfg_.width = 1280;
+ rc_cfg_.height = 720;
+ rc_cfg_.max_quantizer = 52;
+ rc_cfg_.min_quantizer = 2;
+ rc_cfg_.target_bandwidth = 1000;
+ rc_cfg_.buf_initial_sz = 600;
+ rc_cfg_.buf_optimal_sz = 600;
+ rc_cfg_.buf_sz = 1000;
+ rc_cfg_.undershoot_pct = 50;
+ rc_cfg_.overshoot_pct = 50;
+ rc_cfg_.max_intra_bitrate_pct = 1000;
+ rc_cfg_.framerate = 30.0;
+ rc_cfg_.ss_number_layers = 1;
+ rc_cfg_.ts_number_layers = 1;
+ rc_cfg_.scaling_factor_num[0] = 1;
+ rc_cfg_.scaling_factor_den[0] = 1;
+ rc_cfg_.layer_target_bitrate[0] = 1000;
+ rc_cfg_.max_quantizers[0] = 52;
+ rc_cfg_.min_quantizers[0] = 2;
+ rc_cfg_.rc_mode = rc_mode;
+ rc_cfg_.aq_mode = aq_mode_;
+
+ // Encoder settings for ground truth.
+ cfg_.g_w = 1280;
+ cfg_.g_h = 720;
+ cfg_.rc_undershoot_pct = 50;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_buf_initial_sz = 600;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_dropframe_thresh = 0;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 52;
+ cfg_.rc_end_usage = rc_mode;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 0;
+ cfg_.rc_target_bitrate = 1000;
+ cfg_.kf_min_dist = key_interval_;
+ cfg_.kf_max_dist = key_interval_;
+ }
+
+ std::unique_ptr<libvpx::VP9RateControlRTC> rc_api_;
+ libvpx::VP9RateControlRtcConfig rc_cfg_;
+ int aq_mode_;
+ int key_interval_;
+ libvpx::VP9FrameParamsQpRTC frame_params_;
+ bool encoder_exit_;
+};
+
+class RcInterfaceSvcTest
+ : public ::libvpx_test::EncoderTest,
+ public ::libvpx_test::CodecTestWith2Params<int, bool> {
+ public:
+ RcInterfaceSvcTest()
+ : EncoderTest(GET_PARAM(0)), aq_mode_(GET_PARAM(1)), key_interval_(3000),
+ dynamic_spatial_layers_(0), inter_layer_pred_off_(GET_PARAM(2)),
+ parallel_spatial_layers_(false) {}
+ virtual ~RcInterfaceSvcTest() {}
+
+ protected:
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ }
+
+ virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, 7);
+ encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
+ encoder->Control(VP9E_SET_TUNE_CONTENT, 0);
+ encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 900);
+ encoder->Control(VP9E_SET_RTC_EXTERNAL_RATECTRL, 1);
+ encoder->Control(VP9E_SET_SVC, 1);
+ encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
+ if (inter_layer_pred_off_) {
+ encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED,
+ INTER_LAYER_PRED_OFF_NONKEY);
+ }
+ }
+ frame_params_.frame_type = video->frame() % key_interval_ == 0
+ ? libvpx::RcFrameType::kKeyFrame
+ : libvpx::RcFrameType::kInterFrame;
+ encoder_exit_ = video->frame() == kNumFrames;
+ current_superframe_ = video->frame();
+ if (dynamic_spatial_layers_ == 1) {
+ if (video->frame() == 100) {
+ // Go down to 2 spatial layers: set top SL to 0 bitrate.
+ // Update the encoder config.
+ cfg_.rc_target_bitrate -= cfg_.layer_target_bitrate[8];
+ cfg_.layer_target_bitrate[6] = 0;
+ cfg_.layer_target_bitrate[7] = 0;
+ cfg_.layer_target_bitrate[8] = 0;
+ encoder->Config(&cfg_);
+ // Update the RC config.
+ rc_cfg_.target_bandwidth -= rc_cfg_.layer_target_bitrate[8];
+ rc_cfg_.layer_target_bitrate[6] = 0;
+ rc_cfg_.layer_target_bitrate[7] = 0;
+ rc_cfg_.layer_target_bitrate[8] = 0;
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+ } else if (video->frame() == 200) {
+ // Go down to 1 spatial layer.
+ // Update the encoder config.
+ cfg_.rc_target_bitrate -= cfg_.layer_target_bitrate[5];
+ cfg_.layer_target_bitrate[3] = 0;
+ cfg_.layer_target_bitrate[4] = 0;
+ cfg_.layer_target_bitrate[5] = 0;
+ encoder->Config(&cfg_);
+ // Update the RC config.
+ rc_cfg_.target_bandwidth -= rc_cfg_.layer_target_bitrate[5];
+ rc_cfg_.layer_target_bitrate[3] = 0;
+ rc_cfg_.layer_target_bitrate[4] = 0;
+ rc_cfg_.layer_target_bitrate[5] = 0;
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+ } else if (0 && video->frame() == 280) {
+ // TODO(marpan): Re-enable this going back up when issue is fixed.
+ // Go back up to 3 spatial layers.
+ // Update the encoder config: use the original bitrates.
+ SetEncoderConfigSvc(3, 3);
+ encoder->Config(&cfg_);
+ // Update the RC config.
+ SetRCConfigSvc(3, 3);
+ ASSERT_TRUE(rc_api_->UpdateRateControl(rc_cfg_));
+ }
+ }
+ }
+
+ virtual void SetFrameParamsSvc(int sl) {
+ frame_params_.spatial_layer_id = sl;
+ if (rc_cfg_.ts_number_layers == 3)
+ frame_params_.temporal_layer_id =
+ kTemporalId3Layer[current_superframe_ % 4];
+ else if (rc_cfg_.ts_number_layers == 2)
+ frame_params_.temporal_layer_id =
+ kTemporalId2Layer[current_superframe_ % 2];
+ else
+ frame_params_.temporal_layer_id = 0;
+ frame_params_.frame_type =
+ current_superframe_ % key_interval_ == 0 && sl == 0
+ ? libvpx::RcFrameType::kKeyFrame
+ : libvpx::RcFrameType::kInterFrame;
+ }
+
+ virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) {
+ ::libvpx_test::CxDataIterator iter = encoder->GetCxData();
+ for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) sizes_[sl] = 0;
+ std::vector<int> rc_qp;
+ while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+ ParseSuperframeSizes(static_cast<const uint8_t *>(pkt->data.frame.buf),
+ pkt->data.frame.sz);
+ if (!parallel_spatial_layers_ || current_superframe_ == 0) {
+ for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
+ if (sizes_[sl] > 0) {
+ SetFrameParamsSvc(sl);
+ rc_api_->ComputeQP(frame_params_);
+ rc_api_->PostEncodeUpdate(sizes_[sl], frame_params_);
+ rc_qp.push_back(rc_api_->GetQP());
+ }
+ }
+ } else {
+ for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
+ if (sizes_[sl] > 0) {
+ SetFrameParamsSvc(sl);
+ rc_api_->ComputeQP(frame_params_);
+ }
+ }
+ for (int sl = 0; sl < rc_cfg_.ss_number_layers; sl++) {
+ if (sizes_[sl] > 0) {
+ SetFrameParamsSvc(sl);
+ rc_api_->PostEncodeUpdate(sizes_[sl], frame_params_);
+ rc_qp.push_back(rc_api_->GetQP());
+ }
+ }
+ }
+ }
+ if (!encoder_exit_) {
+ int loopfilter_level;
+ std::vector<int> encoder_qp(VPX_SS_MAX_LAYERS, 0);
+ encoder->Control(VP9E_GET_LOOPFILTER_LEVEL, &loopfilter_level);
+ encoder->Control(VP9E_GET_LAST_QUANTIZER_SVC_LAYERS, encoder_qp.data());
+ encoder_qp.resize(rc_qp.size());
+ ASSERT_EQ(rc_qp, encoder_qp);
+ ASSERT_EQ(rc_api_->GetLoopfilterLevel(), loopfilter_level);
+ }
+ }
+ // This method needs to be overridden because non-reference frames are
+ // expected to be mismatched frames as the encoder will avoid loopfilter on
+ // these frames.
+ virtual void MismatchHook(const vpx_image_t * /*img1*/,
+ const vpx_image_t * /*img2*/) {}
+
+ void RunSvc() {
+ SetRCConfigSvc(3, 3);
+ rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
+ SetEncoderConfigSvc(3, 3);
+
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
+ 1280, 720, 30, 1, 0, kNumFrames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunSvcPeriodicKey() {
+ SetRCConfigSvc(3, 3);
+ key_interval_ = 100;
+ rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
+ SetEncoderConfigSvc(3, 3);
+
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
+ 1280, 720, 30, 1, 0, kNumFrames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunSvcDynamicSpatial() {
+ dynamic_spatial_layers_ = 1;
+ SetRCConfigSvc(3, 3);
+ rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
+ SetEncoderConfigSvc(3, 3);
+
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
+ 1280, 720, 30, 1, 0, kNumFrames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ void RunSvcParallelSpatialLayers() {
+ if (!inter_layer_pred_off_) return;
+ parallel_spatial_layers_ = true;
+ SetRCConfigSvc(3, 3);
+ rc_api_ = libvpx::VP9RateControlRTC::Create(rc_cfg_);
+ SetEncoderConfigSvc(3, 3);
+
+ ::libvpx_test::I420VideoSource video("desktop_office1.1280_720-020.yuv",
+ 1280, 720, 30, 1, 0, kNumFrames);
+
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+ }
+
+ private:
+ vpx_codec_err_t ParseSuperframeSizes(const uint8_t *data, size_t data_sz) {
+ uint8_t marker = *(data + data_sz - 1);
+ if ((marker & 0xe0) == 0xc0) {
+ const uint32_t frames = (marker & 0x7) + 1;
+ const uint32_t mag = ((marker >> 3) & 0x3) + 1;
+ const size_t index_sz = 2 + mag * frames;
+ // This chunk is marked as having a superframe index but doesn't have
+ // enough data for it, thus it's an invalid superframe index.
+ if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
+ {
+ const uint8_t marker2 = *(data + data_sz - index_sz);
+ // This chunk is marked as having a superframe index but doesn't have
+ // the matching marker byte at the front of the index therefore it's an
+ // invalid chunk.
+ if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
+ }
+ const uint8_t *x = &data[data_sz - index_sz + 1];
+ for (uint32_t i = 0; i < frames; ++i) {
+ uint32_t this_sz = 0;
+
+ for (uint32_t j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
+ sizes_[i] = this_sz;
+ }
+ }
+ return VPX_CODEC_OK;
+ }
+
+ void SetEncoderConfigSvc(int number_spatial_layers,
+ int number_temporal_layers) {
+ cfg_.g_w = 1280;
+ cfg_.g_h = 720;
+ cfg_.ss_number_layers = number_spatial_layers;
+ cfg_.ts_number_layers = number_temporal_layers;
+ cfg_.g_timebase.num = 1;
+ cfg_.g_timebase.den = 30;
+ if (number_spatial_layers == 3) {
+ svc_params_.scaling_factor_num[0] = 1;
+ svc_params_.scaling_factor_den[0] = 4;
+ svc_params_.scaling_factor_num[1] = 2;
+ svc_params_.scaling_factor_den[1] = 4;
+ svc_params_.scaling_factor_num[2] = 4;
+ svc_params_.scaling_factor_den[2] = 4;
+ } else if (number_spatial_layers == 2) {
+ svc_params_.scaling_factor_num[0] = 1;
+ svc_params_.scaling_factor_den[0] = 2;
+ svc_params_.scaling_factor_num[1] = 2;
+ svc_params_.scaling_factor_den[1] = 2;
+ } else if (number_spatial_layers == 1) {
+ svc_params_.scaling_factor_num[0] = 1;
+ svc_params_.scaling_factor_den[0] = 1;
+ }
+
+ for (int i = 0; i < VPX_MAX_LAYERS; ++i) {
+ svc_params_.max_quantizers[i] = 56;
+ svc_params_.min_quantizers[i] = 2;
+ svc_params_.speed_per_layer[i] = 7;
+ svc_params_.loopfilter_ctrl[i] = LOOPFILTER_ALL;
+ }
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.g_error_resilient = 0;
+
+ if (number_temporal_layers == 3) {
+ cfg_.ts_rate_decimator[0] = 4;
+ cfg_.ts_rate_decimator[1] = 2;
+ cfg_.ts_rate_decimator[2] = 1;
+ cfg_.temporal_layering_mode = 3;
+ } else if (number_temporal_layers == 2) {
+ cfg_.ts_rate_decimator[0] = 2;
+ cfg_.ts_rate_decimator[1] = 1;
+ cfg_.temporal_layering_mode = 2;
+ } else if (number_temporal_layers == 1) {
+ cfg_.ts_rate_decimator[0] = 1;
+ cfg_.temporal_layering_mode = 0;
+ }
+
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 600;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_min_quantizer = 2;
+ cfg_.rc_max_quantizer = 56;
+ cfg_.g_threads = 1;
+ cfg_.kf_max_dist = 9999;
+ cfg_.rc_overshoot_pct = 50;
+ cfg_.rc_undershoot_pct = 50;
+
+ cfg_.rc_target_bitrate = 0;
+ for (int sl = 0; sl < number_spatial_layers; sl++) {
+ int spatial_bitrate = 0;
+ if (number_spatial_layers <= 3)
+ spatial_bitrate = kSpatialLayerBitrate[sl];
+ for (int tl = 0; tl < number_temporal_layers; tl++) {
+ int layer = sl * number_temporal_layers + tl;
+ if (number_temporal_layers == 3)
+ cfg_.layer_target_bitrate[layer] =
+ kTemporalRateAllocation3Layer[tl] * spatial_bitrate / 100;
+ else if (number_temporal_layers == 2)
+ cfg_.layer_target_bitrate[layer] =
+ kTemporalRateAllocation2Layer[tl] * spatial_bitrate / 100;
+ else if (number_temporal_layers == 1)
+ cfg_.layer_target_bitrate[layer] = spatial_bitrate;
+ }
+ cfg_.rc_target_bitrate += spatial_bitrate;
+ }
+
+ cfg_.kf_min_dist = key_interval_;
+ cfg_.kf_max_dist = key_interval_;
+ }
+
+ void SetRCConfigSvc(int number_spatial_layers, int number_temporal_layers) {
+ rc_cfg_.width = 1280;
+ rc_cfg_.height = 720;
+ rc_cfg_.ss_number_layers = number_spatial_layers;
+ rc_cfg_.ts_number_layers = number_temporal_layers;
+ rc_cfg_.max_quantizer = 56;
+ rc_cfg_.min_quantizer = 2;
+ rc_cfg_.buf_initial_sz = 500;
+ rc_cfg_.buf_optimal_sz = 600;
+ rc_cfg_.buf_sz = 1000;
+ rc_cfg_.undershoot_pct = 50;
+ rc_cfg_.overshoot_pct = 50;
+ rc_cfg_.max_intra_bitrate_pct = 900;
+ rc_cfg_.framerate = 30.0;
+ rc_cfg_.rc_mode = VPX_CBR;
+ rc_cfg_.aq_mode = aq_mode_;
+
+ if (number_spatial_layers == 3) {
+ rc_cfg_.scaling_factor_num[0] = 1;
+ rc_cfg_.scaling_factor_den[0] = 4;
+ rc_cfg_.scaling_factor_num[1] = 2;
+ rc_cfg_.scaling_factor_den[1] = 4;
+ rc_cfg_.scaling_factor_num[2] = 4;
+ rc_cfg_.scaling_factor_den[2] = 4;
+ } else if (number_spatial_layers == 2) {
+ rc_cfg_.scaling_factor_num[0] = 1;
+ rc_cfg_.scaling_factor_den[0] = 2;
+ rc_cfg_.scaling_factor_num[1] = 2;
+ rc_cfg_.scaling_factor_den[1] = 2;
+ } else if (number_spatial_layers == 1) {
+ rc_cfg_.scaling_factor_num[0] = 1;
+ rc_cfg_.scaling_factor_den[0] = 1;
+ }
+
+ if (number_temporal_layers == 3) {
+ rc_cfg_.ts_rate_decimator[0] = 4;
+ rc_cfg_.ts_rate_decimator[1] = 2;
+ rc_cfg_.ts_rate_decimator[2] = 1;
+ } else if (number_temporal_layers == 2) {
+ rc_cfg_.ts_rate_decimator[0] = 2;
+ rc_cfg_.ts_rate_decimator[1] = 1;
+ } else if (number_temporal_layers == 1) {
+ rc_cfg_.ts_rate_decimator[0] = 1;
+ }
+
+ rc_cfg_.target_bandwidth = 0;
+ for (int sl = 0; sl < number_spatial_layers; sl++) {
+ int spatial_bitrate = 0;
+ if (number_spatial_layers <= 3)
+ spatial_bitrate = kSpatialLayerBitrate[sl];
+ for (int tl = 0; tl < number_temporal_layers; tl++) {
+ int layer = sl * number_temporal_layers + tl;
+ if (number_temporal_layers == 3)
+ rc_cfg_.layer_target_bitrate[layer] =
+ kTemporalRateAllocation3Layer[tl] * spatial_bitrate / 100;
+ else if (number_temporal_layers == 2)
+ rc_cfg_.layer_target_bitrate[layer] =
+ kTemporalRateAllocation2Layer[tl] * spatial_bitrate / 100;
+ else if (number_temporal_layers == 1)
+ rc_cfg_.layer_target_bitrate[layer] = spatial_bitrate;
+ }
+ rc_cfg_.target_bandwidth += spatial_bitrate;
+ }
+
+ for (int sl = 0; sl < rc_cfg_.ss_number_layers; ++sl) {
+ for (int tl = 0; tl < rc_cfg_.ts_number_layers; ++tl) {
+ const int i = sl * rc_cfg_.ts_number_layers + tl;
+ rc_cfg_.max_quantizers[i] = 56;
+ rc_cfg_.min_quantizers[i] = 2;
+ }
+ }
+ }
+
+ int aq_mode_;
+ std::unique_ptr<libvpx::VP9RateControlRTC> rc_api_;
+ libvpx::VP9RateControlRtcConfig rc_cfg_;
+ vpx_svc_extra_cfg_t svc_params_;
+ libvpx::VP9FrameParamsQpRTC frame_params_;
+ bool encoder_exit_;
+ int current_superframe_;
+ uint32_t sizes_[8];
+ int key_interval_;
+ int dynamic_spatial_layers_;
+ bool inter_layer_pred_off_;
+ // ComputeQP() and PostEncodeUpdate() don't need to be sequential for KSVC.
+ bool parallel_spatial_layers_;
+};
+
+TEST_P(RcInterfaceTest, OneLayer) { RunOneLayer(); }
+
+TEST_P(RcInterfaceTest, OneLayerVBRPeriodicKey) { RunOneLayerVBRPeriodicKey(); }
+
+TEST_P(RcInterfaceSvcTest, Svc) { RunSvc(); }
+
+TEST_P(RcInterfaceSvcTest, SvcParallelSpatialLayers) {
+ RunSvcParallelSpatialLayers();
+}
+
+TEST_P(RcInterfaceSvcTest, SvcPeriodicKey) { RunSvcPeriodicKey(); }
+
+TEST_P(RcInterfaceSvcTest, SvcDynamicSpatial) { RunSvcDynamicSpatial(); }
+
+VP9_INSTANTIATE_TEST_SUITE(RcInterfaceTest, ::testing::Values(0, 3),
+ ::testing::Values(VPX_CBR, VPX_VBR));
+VP9_INSTANTIATE_TEST_SUITE(RcInterfaceSvcTest, ::testing::Values(0, 3),
+ ::testing::Values(true, false));
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_roi_test.cc b/media/libvpx/libvpx/test/vp9_roi_test.cc
new file mode 100644
index 0000000000..e8373c4c0b
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_roi_test.cc
@@ -0,0 +1,148 @@
+/*
+ * 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 <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/video_source.h"
+#include "test/y4m_video_source.h"
+#include "test/yuv_video_source.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+#define MASK_WIDTH 40
+#define MASK_HEIGHT 30
+#define MASK_SIZE MASK_WIDTH *MASK_HEIGHT
+
+namespace {
+
+const int mask[MASK_SIZE] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+class RoiMaskBackgroundSkip : public ::libvpx_test::EncoderTest,
+ public ::testing::Test {
+ protected:
+ RoiMaskBackgroundSkip() : EncoderTest(&::libvpx_test::kVP9) {}
+ virtual ~RoiMaskBackgroundSkip() { free(roi_.roi_map); }
+
+ virtual void SetUp() {
+ InitializeConfig();
+ SetMode(::libvpx_test::kRealTime);
+ SetRoi();
+ }
+
+ void SetRoi() {
+ const int block_size = 8;
+ unsigned int i, j;
+ roi_.rows = (cfg_.g_h + block_size - 1) / block_size;
+ roi_.cols = (cfg_.g_w + block_size - 1) / block_size;
+ memset(&roi_.skip, 0, sizeof(roi_.skip));
+ memset(&roi_.delta_q, 0, sizeof(roi_.delta_q));
+ memset(&roi_.delta_lf, 0, sizeof(roi_.delta_lf));
+ memset(roi_.ref_frame, -1, sizeof(roi_.ref_frame));
+ roi_.ref_frame[1] = 1;
+ // Use segment 3 for skip.
+ roi_.skip[3] = 1;
+ roi_.roi_map =
+ (uint8_t *)calloc(roi_.rows * roi_.cols, sizeof(*roi_.roi_map));
+ for (i = 0; i < roi_.rows; ++i) {
+ for (j = 0; j < roi_.cols; ++j) {
+ const int idx = i * roi_.cols + j;
+ if (mask[idx] == 1) roi_.roi_map[idx] = 3;
+ }
+ }
+ }
+
+ virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+ ::libvpx_test::Encoder *encoder) {
+ if (video->frame() == 0) {
+ encoder->Control(VP8E_SET_CPUUSED, 7);
+ encoder->Control(VP9E_SET_AQ_MODE, 3);
+ }
+ encoder->Control(VP9E_SET_ROI_MAP, &roi_);
+ }
+
+ private:
+ vpx_roi_map_t roi_;
+};
+
+TEST_F(RoiMaskBackgroundSkip, RoiMaskNoMismatch) {
+ cfg_.rc_buf_initial_sz = 500;
+ cfg_.rc_buf_optimal_sz = 500;
+ cfg_.rc_buf_sz = 1000;
+ cfg_.rc_undershoot_pct = 20;
+ cfg_.rc_undershoot_pct = 20;
+ cfg_.rc_dropframe_thresh = 10;
+ cfg_.rc_min_quantizer = 0;
+ cfg_.rc_max_quantizer = 50;
+ cfg_.rc_end_usage = VPX_CBR;
+ cfg_.rc_target_bitrate = 200;
+ cfg_.g_lag_in_frames = 0;
+ cfg_.kf_max_dist = 9999;
+
+ ::libvpx_test::I420VideoSource video("desktopqvga.320_240.yuv", 320, 240, 30,
+ 1, 0, 150);
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_scale_test.cc b/media/libvpx/libvpx/test/vp9_scale_test.cc
new file mode 100644
index 0000000000..2d1203fb89
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_scale_test.cc
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2017 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_scale_rtcd.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/vpx_scale_test.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/vpx_timer.h"
+#include "vpx_scale/yv12config.h"
+
+namespace libvpx_test {
+
+typedef void (*ScaleFrameFunc)(const YV12_BUFFER_CONFIG *src,
+ YV12_BUFFER_CONFIG *dst,
+ INTERP_FILTER filter_type, int phase_scaler);
+
+class ScaleTest : public VpxScaleBase,
+ public ::testing::TestWithParam<ScaleFrameFunc> {
+ public:
+ virtual ~ScaleTest() {}
+
+ protected:
+ virtual void SetUp() { scale_fn_ = GetParam(); }
+
+ void ReferenceScaleFrame(INTERP_FILTER filter_type, int phase_scaler) {
+ vp9_scale_and_extend_frame_c(&img_, &ref_img_, filter_type, phase_scaler);
+ }
+
+ void ScaleFrame(INTERP_FILTER filter_type, int phase_scaler) {
+ ASM_REGISTER_STATE_CHECK(
+ scale_fn_(&img_, &dst_img_, filter_type, phase_scaler));
+ }
+
+ void RunTest(INTERP_FILTER filter_type) {
+ static const int kNumSizesToTest = 20;
+ static const int kNumScaleFactorsToTest = 4;
+ static const int kSizesToTest[] = {
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 68, 128, 134
+ };
+ static const int kScaleFactors[] = { 1, 2, 3, 4 };
+ for (int phase_scaler = 0; phase_scaler < 16; ++phase_scaler) {
+ for (int h = 0; h < kNumSizesToTest; ++h) {
+ const int src_height = kSizesToTest[h];
+ for (int w = 0; w < kNumSizesToTest; ++w) {
+ const int src_width = kSizesToTest[w];
+ for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest;
+ ++sf_up_idx) {
+ const int sf_up = kScaleFactors[sf_up_idx];
+ for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest;
+ ++sf_down_idx) {
+ const int sf_down = kScaleFactors[sf_down_idx];
+ const int dst_width = src_width * sf_up / sf_down;
+ const int dst_height = src_height * sf_up / sf_down;
+ if (sf_up == sf_down && sf_up != 1) {
+ continue;
+ }
+ // I420 frame width and height must be even.
+ if (!dst_width || !dst_height || dst_width & 1 ||
+ dst_height & 1) {
+ continue;
+ }
+ // vpx_convolve8_c() has restriction on the step which cannot
+ // exceed 64 (ratio 1 to 4).
+ if (src_width > 4 * dst_width || src_height > 4 * dst_height) {
+ continue;
+ }
+ ASSERT_NO_FATAL_FAILURE(ResetScaleImages(src_width, src_height,
+ dst_width, dst_height));
+ ReferenceScaleFrame(filter_type, phase_scaler);
+ ScaleFrame(filter_type, phase_scaler);
+ if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc,
+ ref_img_.frame_size)) {
+ printf(
+ "filter_type = %d, phase_scaler = %d, src_width = %4d, "
+ "src_height = %4d, dst_width = %4d, dst_height = %4d, "
+ "scale factor = %d:%d\n",
+ filter_type, phase_scaler, src_width, src_height, dst_width,
+ dst_height, sf_down, sf_up);
+ PrintDiff();
+ }
+ CompareImages(dst_img_);
+ DeallocScaleImages();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ void PrintDiffComponent(const uint8_t *const ref, const uint8_t *const opt,
+ const int stride, const int width, const int height,
+ const int plane_idx) const {
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ if (ref[y * stride + x] != opt[y * stride + x]) {
+ printf("Plane %d pixel[%d][%d] diff:%6d (ref),%6d (opt)\n", plane_idx,
+ y, x, ref[y * stride + x], opt[y * stride + x]);
+ break;
+ }
+ }
+ }
+ }
+
+ void PrintDiff() const {
+ assert(ref_img_.y_stride == dst_img_.y_stride);
+ assert(ref_img_.y_width == dst_img_.y_width);
+ assert(ref_img_.y_height == dst_img_.y_height);
+ assert(ref_img_.uv_stride == dst_img_.uv_stride);
+ assert(ref_img_.uv_width == dst_img_.uv_width);
+ assert(ref_img_.uv_height == dst_img_.uv_height);
+
+ if (memcmp(dst_img_.buffer_alloc, ref_img_.buffer_alloc,
+ ref_img_.frame_size)) {
+ PrintDiffComponent(ref_img_.y_buffer, dst_img_.y_buffer,
+ ref_img_.y_stride, ref_img_.y_width, ref_img_.y_height,
+ 0);
+ PrintDiffComponent(ref_img_.u_buffer, dst_img_.u_buffer,
+ ref_img_.uv_stride, ref_img_.uv_width,
+ ref_img_.uv_height, 1);
+ PrintDiffComponent(ref_img_.v_buffer, dst_img_.v_buffer,
+ ref_img_.uv_stride, ref_img_.uv_width,
+ ref_img_.uv_height, 2);
+ }
+ }
+
+ ScaleFrameFunc scale_fn_;
+};
+
+TEST_P(ScaleTest, ScaleFrame_EightTap) { RunTest(EIGHTTAP); }
+TEST_P(ScaleTest, ScaleFrame_EightTapSmooth) { RunTest(EIGHTTAP_SMOOTH); }
+TEST_P(ScaleTest, ScaleFrame_EightTapSharp) { RunTest(EIGHTTAP_SHARP); }
+TEST_P(ScaleTest, ScaleFrame_Bilinear) { RunTest(BILINEAR); }
+
+TEST_P(ScaleTest, DISABLED_Speed) {
+ static const int kCountSpeedTestBlock = 100;
+ static const int kNumScaleFactorsToTest = 4;
+ static const int kScaleFactors[] = { 1, 2, 3, 4 };
+ const int src_width = 1280;
+ const int src_height = 720;
+ for (INTERP_FILTER filter_type = 2; filter_type < 4; ++filter_type) {
+ for (int phase_scaler = 0; phase_scaler < 2; ++phase_scaler) {
+ for (int sf_up_idx = 0; sf_up_idx < kNumScaleFactorsToTest; ++sf_up_idx) {
+ const int sf_up = kScaleFactors[sf_up_idx];
+ for (int sf_down_idx = 0; sf_down_idx < kNumScaleFactorsToTest;
+ ++sf_down_idx) {
+ const int sf_down = kScaleFactors[sf_down_idx];
+ const int dst_width = src_width * sf_up / sf_down;
+ const int dst_height = src_height * sf_up / sf_down;
+ if (sf_up == sf_down && sf_up != 1) {
+ continue;
+ }
+ // I420 frame width and height must be even.
+ if (dst_width & 1 || dst_height & 1) {
+ continue;
+ }
+ ASSERT_NO_FATAL_FAILURE(
+ ResetScaleImages(src_width, src_height, dst_width, dst_height));
+ ASM_REGISTER_STATE_CHECK(
+ ReferenceScaleFrame(filter_type, phase_scaler));
+
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kCountSpeedTestBlock; ++i) {
+ ScaleFrame(filter_type, phase_scaler);
+ }
+ libvpx_test::ClearSystemState();
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+ CompareImages(dst_img_);
+ DeallocScaleImages();
+
+ printf(
+ "filter_type = %d, phase_scaler = %d, src_width = %4d, "
+ "src_height = %4d, dst_width = %4d, dst_height = %4d, "
+ "scale factor = %d:%d, scale time: %5d ms\n",
+ filter_type, phase_scaler, src_width, src_height, dst_width,
+ dst_height, sf_down, sf_up, elapsed_time);
+ }
+ }
+ }
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(C, ScaleTest,
+ ::testing::Values(vp9_scale_and_extend_frame_c));
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_SUITE_P(SSSE3, ScaleTest,
+ ::testing::Values(vp9_scale_and_extend_frame_ssse3));
+#endif // HAVE_SSSE3
+
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, ScaleTest,
+ ::testing::Values(vp9_scale_and_extend_frame_neon));
+#endif // HAVE_NEON
+
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/vp9_skip_loopfilter_test.cc b/media/libvpx/libvpx/test/vp9_skip_loopfilter_test.cc
new file mode 100644
index 0000000000..c080a2caae
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_skip_loopfilter_test.cc
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2015 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 <string>
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/webm_video_source.h"
+
+namespace {
+
+const char kVp9TestFile[] = "vp90-2-08-tile_1x8_frame_parallel.webm";
+const char kVp9Md5File[] = "vp90-2-08-tile_1x8_frame_parallel.webm.md5";
+
+// Class for testing shutting off the loop filter.
+class SkipLoopFilterTest {
+ public:
+ SkipLoopFilterTest()
+ : video_(nullptr), decoder_(nullptr), md5_file_(nullptr) {}
+
+ ~SkipLoopFilterTest() {
+ if (md5_file_ != nullptr) fclose(md5_file_);
+ delete decoder_;
+ delete video_;
+ }
+
+ // If |threads| > 0 then set the decoder with that number of threads.
+ bool Init(int num_threads) {
+ expected_md5_[0] = '\0';
+ junk_[0] = '\0';
+ video_ = new libvpx_test::WebMVideoSource(kVp9TestFile);
+ if (video_ == nullptr) {
+ EXPECT_NE(video_, nullptr);
+ return false;
+ }
+ video_->Init();
+ video_->Begin();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ if (num_threads > 0) cfg.threads = num_threads;
+ decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+ if (decoder_ == nullptr) {
+ EXPECT_NE(decoder_, nullptr);
+ return false;
+ }
+
+ OpenMd5File(kVp9Md5File);
+ return !::testing::Test::HasFailure();
+ }
+
+ // Set the VP9 skipLoopFilter control value.
+ void SetSkipLoopFilter(int value, vpx_codec_err_t expected_value) {
+ ASSERT_NE(decoder_, nullptr);
+ decoder_->Control(VP9_SET_SKIP_LOOP_FILTER, value, expected_value);
+ }
+
+ vpx_codec_err_t DecodeOneFrame() {
+ const vpx_codec_err_t res =
+ decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+ if (res == VPX_CODEC_OK) {
+ ReadMd5();
+ video_->Next();
+ }
+ return res;
+ }
+
+ vpx_codec_err_t DecodeRemainingFrames() {
+ for (; video_->cxdata() != nullptr; video_->Next()) {
+ const vpx_codec_err_t res =
+ decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+ if (res != VPX_CODEC_OK) return res;
+ ReadMd5();
+ }
+ return VPX_CODEC_OK;
+ }
+
+ // Checks if MD5 matches or doesn't.
+ void CheckMd5(bool matches) {
+ libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
+ const vpx_image_t *img = dec_iter.Next();
+ CheckMd5Vpx(*img, matches);
+ }
+
+ private:
+ // TODO(fgalligan): Move the MD5 testing code into another class.
+ void OpenMd5File(const std::string &md5_file_name) {
+ md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name);
+ ASSERT_NE(md5_file_, nullptr)
+ << "MD5 file open failed. Filename: " << md5_file_name;
+ }
+
+ // Reads the next line of the MD5 file.
+ void ReadMd5() {
+ ASSERT_NE(md5_file_, nullptr);
+ const int res = fscanf(md5_file_, "%s %s", expected_md5_, junk_);
+ ASSERT_NE(EOF, res) << "Read md5 data failed";
+ expected_md5_[32] = '\0';
+ }
+
+ // Checks if the last read MD5 matches |img| or doesn't.
+ void CheckMd5Vpx(const vpx_image_t &img, bool matches) {
+ ::libvpx_test::MD5 md5_res;
+ md5_res.Add(&img);
+ const char *const actual_md5 = md5_res.Get();
+
+ // Check MD5.
+ if (matches)
+ ASSERT_STREQ(expected_md5_, actual_md5) << "MD5 checksums don't match";
+ else
+ ASSERT_STRNE(expected_md5_, actual_md5) << "MD5 checksums match";
+ }
+
+ libvpx_test::WebMVideoSource *video_;
+ libvpx_test::VP9Decoder *decoder_;
+ FILE *md5_file_;
+ char expected_md5_[33];
+ char junk_[128];
+};
+
+TEST(SkipLoopFilterTest, ShutOffLoopFilter) {
+ const int non_zero_value = 1;
+ const int num_threads = 0;
+ SkipLoopFilterTest skip_loop_filter;
+ ASSERT_TRUE(skip_loop_filter.Init(num_threads));
+ skip_loop_filter.SetSkipLoopFilter(non_zero_value, VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, skip_loop_filter.DecodeRemainingFrames());
+ skip_loop_filter.CheckMd5(false);
+}
+
+TEST(SkipLoopFilterTest, ShutOffLoopFilterSingleThread) {
+ const int non_zero_value = 1;
+ const int num_threads = 1;
+ SkipLoopFilterTest skip_loop_filter;
+ ASSERT_TRUE(skip_loop_filter.Init(num_threads));
+ skip_loop_filter.SetSkipLoopFilter(non_zero_value, VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, skip_loop_filter.DecodeRemainingFrames());
+ skip_loop_filter.CheckMd5(false);
+}
+
+TEST(SkipLoopFilterTest, ShutOffLoopFilter8Threads) {
+ const int non_zero_value = 1;
+ const int num_threads = 8;
+ SkipLoopFilterTest skip_loop_filter;
+ ASSERT_TRUE(skip_loop_filter.Init(num_threads));
+ skip_loop_filter.SetSkipLoopFilter(non_zero_value, VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, skip_loop_filter.DecodeRemainingFrames());
+ skip_loop_filter.CheckMd5(false);
+}
+
+TEST(SkipLoopFilterTest, WithLoopFilter) {
+ const int non_zero_value = 1;
+ const int num_threads = 0;
+ SkipLoopFilterTest skip_loop_filter;
+ ASSERT_TRUE(skip_loop_filter.Init(num_threads));
+ skip_loop_filter.SetSkipLoopFilter(non_zero_value, VPX_CODEC_OK);
+ skip_loop_filter.SetSkipLoopFilter(0, VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, skip_loop_filter.DecodeRemainingFrames());
+ skip_loop_filter.CheckMd5(true);
+}
+
+TEST(SkipLoopFilterTest, ToggleLoopFilter) {
+ const int num_threads = 0;
+ SkipLoopFilterTest skip_loop_filter;
+ ASSERT_TRUE(skip_loop_filter.Init(num_threads));
+
+ for (int i = 0; i < 10; ++i) {
+ skip_loop_filter.SetSkipLoopFilter(i % 2, VPX_CODEC_OK);
+ ASSERT_EQ(VPX_CODEC_OK, skip_loop_filter.DecodeOneFrame());
+ }
+ ASSERT_EQ(VPX_CODEC_OK, skip_loop_filter.DecodeRemainingFrames());
+ skip_loop_filter.CheckMd5(false);
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/vp9_subtract_test.cc b/media/libvpx/libvpx/test/vp9_subtract_test.cc
new file mode 100644
index 0000000000..a57082f1eb
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_subtract_test.cc
@@ -0,0 +1,321 @@
+/*
+ * 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 <tuple>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/bench.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_blockd.h"
+#include "vpx_ports/msvc.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/vpx_timer.h"
+
+typedef void (*SubtractFunc)(int rows, int cols, int16_t *diff_ptr,
+ ptrdiff_t diff_stride, const uint8_t *src_ptr,
+ ptrdiff_t src_stride, const uint8_t *pred_ptr,
+ ptrdiff_t pred_stride);
+
+namespace vp9 {
+
+class VP9SubtractBlockTest : public AbstractBench,
+ public ::testing::TestWithParam<SubtractFunc> {
+ public:
+ virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+ virtual void Run() {
+ GetParam()(block_height_, block_width_, diff_, block_width_, src_,
+ block_width_, pred_, block_width_);
+ }
+
+ void SetupBlocks(BLOCK_SIZE bsize) {
+ block_width_ = 4 * num_4x4_blocks_wide_lookup[bsize];
+ block_height_ = 4 * num_4x4_blocks_high_lookup[bsize];
+ diff_ = reinterpret_cast<int16_t *>(
+ vpx_memalign(16, sizeof(*diff_) * block_width_ * block_height_ * 2));
+ pred_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(16, block_width_ * block_height_ * 2));
+ src_ = reinterpret_cast<uint8_t *>(
+ vpx_memalign(16, block_width_ * block_height_ * 2));
+ }
+
+ int block_width_;
+ int block_height_;
+ int16_t *diff_;
+ uint8_t *pred_;
+ uint8_t *src_;
+};
+
+using libvpx_test::ACMRandom;
+
+TEST_P(VP9SubtractBlockTest, DISABLED_Speed) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+ for (BLOCK_SIZE bsize = BLOCK_4X4; bsize < BLOCK_SIZES;
+ bsize = static_cast<BLOCK_SIZE>(static_cast<int>(bsize) + 1)) {
+ SetupBlocks(bsize);
+
+ RunNTimes(100000000 / (block_height_ * block_width_));
+ char block_size[16];
+ snprintf(block_size, sizeof(block_size), "%dx%d", block_height_,
+ block_width_);
+ char title[100];
+ snprintf(title, sizeof(title), "%8s ", block_size);
+ PrintMedian(title);
+
+ vpx_free(diff_);
+ vpx_free(pred_);
+ vpx_free(src_);
+ }
+}
+
+TEST_P(VP9SubtractBlockTest, SimpleSubtract) {
+ ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+ for (BLOCK_SIZE bsize = BLOCK_4X4; bsize < BLOCK_SIZES;
+ bsize = static_cast<BLOCK_SIZE>(static_cast<int>(bsize) + 1)) {
+ SetupBlocks(bsize);
+
+ for (int n = 0; n < 100; n++) {
+ for (int r = 0; r < block_height_; ++r) {
+ for (int c = 0; c < block_width_ * 2; ++c) {
+ src_[r * block_width_ * 2 + c] = rnd.Rand8();
+ pred_[r * block_width_ * 2 + c] = rnd.Rand8();
+ }
+ }
+
+ GetParam()(block_height_, block_width_, diff_, block_width_, src_,
+ block_width_, pred_, block_width_);
+
+ for (int r = 0; r < block_height_; ++r) {
+ for (int c = 0; c < block_width_; ++c) {
+ EXPECT_EQ(diff_[r * block_width_ + c],
+ (src_[r * block_width_ + c] - pred_[r * block_width_ + c]))
+ << "r = " << r << ", c = " << c
+ << ", bs = " << static_cast<int>(bsize);
+ }
+ }
+
+ GetParam()(block_height_, block_width_, diff_, block_width_ * 2, src_,
+ block_width_ * 2, pred_, block_width_ * 2);
+
+ for (int r = 0; r < block_height_; ++r) {
+ for (int c = 0; c < block_width_; ++c) {
+ EXPECT_EQ(diff_[r * block_width_ * 2 + c],
+ (src_[r * block_width_ * 2 + c] -
+ pred_[r * block_width_ * 2 + c]))
+ << "r = " << r << ", c = " << c
+ << ", bs = " << static_cast<int>(bsize);
+ }
+ }
+ }
+ vpx_free(diff_);
+ vpx_free(pred_);
+ vpx_free(src_);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(C, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_SUITE_P(SSE2, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_sse2));
+#endif
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(AVX2, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_avx2));
+#endif
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_neon));
+#endif
+#if HAVE_MSA
+INSTANTIATE_TEST_SUITE_P(MSA, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_msa));
+#endif
+
+#if HAVE_MMI
+INSTANTIATE_TEST_SUITE_P(MMI, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_mmi));
+#endif
+
+#if HAVE_VSX
+INSTANTIATE_TEST_SUITE_P(VSX, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_vsx));
+#endif
+
+#if HAVE_LSX
+INSTANTIATE_TEST_SUITE_P(LSX, VP9SubtractBlockTest,
+ ::testing::Values(vpx_subtract_block_lsx));
+#endif
+
+#if CONFIG_VP9_HIGHBITDEPTH
+
+typedef void (*HBDSubtractFunc)(int rows, int cols, int16_t *diff_ptr,
+ ptrdiff_t diff_stride, const uint8_t *src_ptr,
+ ptrdiff_t src_stride, const uint8_t *pred_ptr,
+ ptrdiff_t pred_stride, int bd);
+
+// <BLOCK_SIZE, bit_depth, optimized subtract func, reference subtract func>
+using Params = std::tuple<BLOCK_SIZE, int, HBDSubtractFunc, HBDSubtractFunc>;
+
+class VPXHBDSubtractBlockTest : public ::testing::TestWithParam<Params> {
+ public:
+ virtual void SetUp() {
+ block_width_ = 4 * num_4x4_blocks_wide_lookup[GET_PARAM(0)];
+ block_height_ = 4 * num_4x4_blocks_high_lookup[GET_PARAM(0)];
+ bit_depth_ = static_cast<vpx_bit_depth_t>(GET_PARAM(1));
+ func_ = GET_PARAM(2);
+ ref_func_ = GET_PARAM(3);
+
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+
+ constexpr size_t kMaxWidth = 128;
+ constexpr size_t kMaxBlockSize = kMaxWidth * kMaxWidth;
+ src_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
+ vpx_memalign(16, kMaxBlockSize * sizeof(uint16_t))));
+ ASSERT_NE(src_, nullptr);
+ pred_ = CONVERT_TO_BYTEPTR(reinterpret_cast<uint16_t *>(
+ vpx_memalign(16, kMaxBlockSize * sizeof(uint16_t))));
+ ASSERT_NE(pred_, nullptr);
+ diff_ = reinterpret_cast<int16_t *>(
+ vpx_memalign(16, kMaxBlockSize * sizeof(int16_t)));
+ ASSERT_NE(diff_, nullptr);
+ }
+
+ virtual void TearDown() {
+ vpx_free(CONVERT_TO_SHORTPTR(src_));
+ vpx_free(CONVERT_TO_SHORTPTR(pred_));
+ vpx_free(diff_);
+ }
+
+ protected:
+ void CheckResult();
+ void RunForSpeed();
+
+ private:
+ ACMRandom rnd_;
+ int block_height_;
+ int block_width_;
+ vpx_bit_depth_t bit_depth_;
+ HBDSubtractFunc func_;
+ HBDSubtractFunc ref_func_;
+ uint8_t *src_;
+ uint8_t *pred_;
+ int16_t *diff_;
+};
+
+void VPXHBDSubtractBlockTest::CheckResult() {
+ constexpr int kTestNum = 100;
+ constexpr int kMaxWidth = 128;
+ constexpr int kMaxBlockSize = kMaxWidth * kMaxWidth;
+ const int mask = (1 << bit_depth_) - 1;
+ for (int i = 0; i < kTestNum; ++i) {
+ for (int j = 0; j < kMaxBlockSize; ++j) {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask;
+ CONVERT_TO_SHORTPTR(pred_)[j] = rnd_.Rand16() & mask;
+ }
+
+ func_(block_height_, block_width_, diff_, block_width_, src_, block_width_,
+ pred_, block_width_, bit_depth_);
+
+ for (int r = 0; r < block_height_; ++r) {
+ for (int c = 0; c < block_width_; ++c) {
+ EXPECT_EQ(diff_[r * block_width_ + c],
+ (CONVERT_TO_SHORTPTR(src_)[r * block_width_ + c] -
+ CONVERT_TO_SHORTPTR(pred_)[r * block_width_ + c]))
+ << "r = " << r << ", c = " << c << ", test: " << i;
+ }
+ }
+ }
+}
+
+TEST_P(VPXHBDSubtractBlockTest, CheckResult) { CheckResult(); }
+
+void VPXHBDSubtractBlockTest::RunForSpeed() {
+ constexpr int kTestNum = 200000;
+ constexpr int kMaxWidth = 128;
+ constexpr int kMaxBlockSize = kMaxWidth * kMaxWidth;
+ const int mask = (1 << bit_depth_) - 1;
+
+ if (ref_func_ == func_) GTEST_SKIP();
+
+ for (int j = 0; j < kMaxBlockSize; ++j) {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask;
+ CONVERT_TO_SHORTPTR(pred_)[j] = rnd_.Rand16() & mask;
+ }
+
+ vpx_usec_timer ref_timer;
+ vpx_usec_timer_start(&ref_timer);
+ for (int i = 0; i < kTestNum; ++i) {
+ ref_func_(block_height_, block_width_, diff_, block_width_, src_,
+ block_width_, pred_, block_width_, bit_depth_);
+ }
+ vpx_usec_timer_mark(&ref_timer);
+ const int64_t ref_elapsed_time = vpx_usec_timer_elapsed(&ref_timer);
+
+ for (int j = 0; j < kMaxBlockSize; ++j) {
+ CONVERT_TO_SHORTPTR(src_)[j] = rnd_.Rand16() & mask;
+ CONVERT_TO_SHORTPTR(pred_)[j] = rnd_.Rand16() & mask;
+ }
+
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+ for (int i = 0; i < kTestNum; ++i) {
+ func_(block_height_, block_width_, diff_, block_width_, src_, block_width_,
+ pred_, block_width_, bit_depth_);
+ }
+ vpx_usec_timer_mark(&timer);
+ const int64_t elapsed_time = vpx_usec_timer_elapsed(&timer);
+
+ printf(
+ "[%dx%d]: "
+ "ref_time=%6" PRId64 " \t simd_time=%6" PRId64
+ " \t "
+ "gain=%f \n",
+ block_width_, block_height_, ref_elapsed_time, elapsed_time,
+ static_cast<double>(ref_elapsed_time) /
+ static_cast<double>(elapsed_time));
+}
+
+TEST_P(VPXHBDSubtractBlockTest, DISABLED_Speed) { RunForSpeed(); }
+
+const BLOCK_SIZE kValidBlockSize[] = { BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
+ BLOCK_8X8, BLOCK_8X16, BLOCK_16X8,
+ BLOCK_16X16, BLOCK_16X32, BLOCK_32X16,
+ BLOCK_32X32, BLOCK_32X64, BLOCK_64X32,
+ BLOCK_64X64 };
+
+INSTANTIATE_TEST_SUITE_P(
+ C, VPXHBDSubtractBlockTest,
+ ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
+ ::testing::Values(12),
+ ::testing::Values(&vpx_highbd_subtract_block_c),
+ ::testing::Values(&vpx_highbd_subtract_block_c)));
+
+#if HAVE_AVX2
+INSTANTIATE_TEST_SUITE_P(
+ AVX2, VPXHBDSubtractBlockTest,
+ ::testing::Combine(::testing::ValuesIn(kValidBlockSize),
+ ::testing::Values(12),
+ ::testing::Values(&vpx_highbd_subtract_block_avx2),
+ ::testing::Values(&vpx_highbd_subtract_block_c)));
+#endif // HAVE_AVX2
+
+#endif // CONFIG_VP9_HIGHBITDEPTH
+} // namespace vp9
diff --git a/media/libvpx/libvpx/test/vp9_thread_test.cc b/media/libvpx/libvpx/test/vp9_thread_test.cc
new file mode 100644
index 0000000000..1ceef8185c
--- /dev/null
+++ b/media/libvpx/libvpx/test/vp9_thread_test.cc
@@ -0,0 +1,295 @@
+/*
+ * 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 <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/md5_helper.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+#include "vpx_util/vpx_thread.h"
+
+namespace {
+
+using std::string;
+
+class VPxWorkerThreadTest : public ::testing::TestWithParam<bool> {
+ protected:
+ virtual ~VPxWorkerThreadTest() {}
+ virtual void SetUp() { vpx_get_worker_interface()->init(&worker_); }
+
+ virtual void TearDown() { vpx_get_worker_interface()->end(&worker_); }
+
+ void Run(VPxWorker *worker) {
+ const bool synchronous = GetParam();
+ if (synchronous) {
+ vpx_get_worker_interface()->execute(worker);
+ } else {
+ vpx_get_worker_interface()->launch(worker);
+ }
+ }
+
+ VPxWorker worker_;
+};
+
+int ThreadHook(void *data, void *return_value) {
+ int *const hook_data = reinterpret_cast<int *>(data);
+ *hook_data = 5;
+ return *reinterpret_cast<int *>(return_value);
+}
+
+TEST_P(VPxWorkerThreadTest, HookSuccess) {
+ // should be a no-op.
+ EXPECT_NE(vpx_get_worker_interface()->sync(&worker_), 0);
+
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_NE(vpx_get_worker_interface()->reset(&worker_), 0);
+
+ int hook_data = 0;
+ int return_value = 1; // return successfully from the hook
+ worker_.hook = ThreadHook;
+ worker_.data1 = &hook_data;
+ worker_.data2 = &return_value;
+
+ Run(&worker_);
+ EXPECT_NE(vpx_get_worker_interface()->sync(&worker_), 0);
+ EXPECT_FALSE(worker_.had_error);
+ EXPECT_EQ(5, hook_data);
+
+ // should be a no-op.
+ EXPECT_NE(vpx_get_worker_interface()->sync(&worker_), 0);
+ }
+}
+
+TEST_P(VPxWorkerThreadTest, HookFailure) {
+ EXPECT_NE(vpx_get_worker_interface()->reset(&worker_), 0);
+
+ int hook_data = 0;
+ int return_value = 0; // return failure from the hook
+ worker_.hook = ThreadHook;
+ worker_.data1 = &hook_data;
+ worker_.data2 = &return_value;
+
+ Run(&worker_);
+ EXPECT_FALSE(vpx_get_worker_interface()->sync(&worker_));
+ EXPECT_EQ(1, worker_.had_error);
+
+ // Ensure _reset() clears the error and _launch() can be called again.
+ return_value = 1;
+ EXPECT_NE(vpx_get_worker_interface()->reset(&worker_), 0);
+ EXPECT_FALSE(worker_.had_error);
+ vpx_get_worker_interface()->launch(&worker_);
+ EXPECT_NE(vpx_get_worker_interface()->sync(&worker_), 0);
+ EXPECT_FALSE(worker_.had_error);
+}
+
+TEST_P(VPxWorkerThreadTest, EndWithoutSync) {
+ // Create a large number of threads to increase the chances of detecting a
+ // race. Doing more work in the hook is no guarantee as any race would occur
+ // post hook execution in the main thread loop driver.
+ static const int kNumWorkers = 64;
+ VPxWorker workers[kNumWorkers];
+ int hook_data[kNumWorkers];
+ int return_value[kNumWorkers];
+
+ for (int n = 0; n < kNumWorkers; ++n) {
+ vpx_get_worker_interface()->init(&workers[n]);
+ return_value[n] = 1; // return successfully from the hook
+ workers[n].hook = ThreadHook;
+ workers[n].data1 = &hook_data[n];
+ workers[n].data2 = &return_value[n];
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ for (int n = 0; n < kNumWorkers; ++n) {
+ EXPECT_NE(vpx_get_worker_interface()->reset(&workers[n]), 0);
+ hook_data[n] = 0;
+ }
+
+ for (int n = 0; n < kNumWorkers; ++n) {
+ Run(&workers[n]);
+ }
+
+ for (int n = kNumWorkers - 1; n >= 0; --n) {
+ vpx_get_worker_interface()->end(&workers[n]);
+ }
+ }
+}
+
+TEST(VPxWorkerThreadTest, TestInterfaceAPI) {
+ EXPECT_EQ(0, vpx_set_worker_interface(nullptr));
+ EXPECT_NE(vpx_get_worker_interface(), nullptr);
+ for (int i = 0; i < 6; ++i) {
+ VPxWorkerInterface winterface = *vpx_get_worker_interface();
+ switch (i) {
+ default:
+ case 0: winterface.init = nullptr; break;
+ case 1: winterface.reset = nullptr; break;
+ case 2: winterface.sync = nullptr; break;
+ case 3: winterface.launch = nullptr; break;
+ case 4: winterface.execute = nullptr; break;
+ case 5: winterface.end = nullptr; break;
+ }
+ EXPECT_EQ(0, vpx_set_worker_interface(&winterface));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Multi-threaded decode tests
+#if CONFIG_WEBM_IO
+// Decodes |filename| with |num_threads|. Returns the md5 of the decoded frames.
+string DecodeFile(const string &filename, int num_threads) {
+ libvpx_test::WebMVideoSource video(filename);
+ video.Init();
+
+ vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+ cfg.threads = num_threads;
+ libvpx_test::VP9Decoder decoder(cfg, 0);
+
+ libvpx_test::MD5 md5;
+ for (video.Begin(); video.cxdata(); video.Next()) {
+ const vpx_codec_err_t res =
+ decoder.DecodeFrame(video.cxdata(), video.frame_size());
+ if (res != VPX_CODEC_OK) {
+ EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
+ break;
+ }
+
+ libvpx_test::DxDataIterator dec_iter = decoder.GetDxData();
+ const vpx_image_t *img = nullptr;
+
+ // Get decompressed data
+ while ((img = dec_iter.Next())) {
+ md5.Add(img);
+ }
+ }
+ return string(md5.Get());
+}
+
+// Trivial serialized thread worker interface implementation.
+// Note any worker that requires synchronization between other workers will
+// hang.
+namespace impl {
+namespace {
+
+void Init(VPxWorker *const worker) { memset(worker, 0, sizeof(*worker)); }
+int Reset(VPxWorker *const /*worker*/) { return 1; }
+int Sync(VPxWorker *const worker) { return !worker->had_error; }
+
+void Execute(VPxWorker *const worker) {
+ worker->had_error |= !worker->hook(worker->data1, worker->data2);
+}
+
+void Launch(VPxWorker *const worker) { Execute(worker); }
+void End(VPxWorker *const /*worker*/) {}
+
+} // namespace
+} // namespace impl
+
+TEST(VPxWorkerThreadTest, TestSerialInterface) {
+ static const VPxWorkerInterface serial_interface = {
+ impl::Init, impl::Reset, impl::Sync, impl::Launch, impl::Execute, impl::End
+ };
+ static const char expected_md5[] = "b35a1b707b28e82be025d960aba039bc";
+ static const char filename[] = "vp90-2-03-size-226x226.webm";
+ VPxWorkerInterface default_interface = *vpx_get_worker_interface();
+
+ EXPECT_NE(vpx_set_worker_interface(&serial_interface), 0);
+ EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
+
+ // Reset the interface.
+ EXPECT_NE(vpx_set_worker_interface(&default_interface), 0);
+ EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
+}
+
+struct FileParam {
+ const char *name;
+ const char *expected_md5;
+ friend std::ostream &operator<<(std::ostream &os, const FileParam &param) {
+ return os << "file name: " << param.name
+ << " digest: " << param.expected_md5;
+ }
+};
+
+class VP9DecodeMultiThreadedTest : public ::testing::TestWithParam<FileParam> {
+};
+
+TEST_P(VP9DecodeMultiThreadedTest, Decode) {
+ for (int t = 1; t <= 8; ++t) {
+ EXPECT_EQ(GetParam().expected_md5, DecodeFile(GetParam().name, t))
+ << "threads = " << t;
+ }
+}
+
+const FileParam kNoTilesNonFrameParallelFiles[] = {
+ { "vp90-2-03-size-226x226.webm", "b35a1b707b28e82be025d960aba039bc" }
+};
+
+const FileParam kFrameParallelFiles[] = {
+ { "vp90-2-08-tile_1x2_frame_parallel.webm",
+ "68ede6abd66bae0a2edf2eb9232241b6" },
+ { "vp90-2-08-tile_1x4_frame_parallel.webm",
+ "368ebc6ebf3a5e478d85b2c3149b2848" },
+ { "vp90-2-08-tile_1x8_frame_parallel.webm",
+ "17e439da2388aff3a0f69cb22579c6c1" },
+};
+
+const FileParam kFrameParallelResizeFiles[] = {
+ { "vp90-2-14-resize-fp-tiles-1-16.webm", "0cd5e632c326297e975f38949c31ea94" },
+ { "vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm",
+ "5c78a96a42e7f4a4f6b2edcdb791e44c" },
+ { "vp90-2-14-resize-fp-tiles-1-2.webm", "e030450ae85c3277be2a418769df98e2" },
+ { "vp90-2-14-resize-fp-tiles-1-4.webm", "312eed4e2b64eb7a4e7f18916606a430" },
+ { "vp90-2-14-resize-fp-tiles-16-1.webm", "1755c16d8af16a9cb3fe7338d90abe52" },
+ { "vp90-2-14-resize-fp-tiles-16-2.webm", "500300592d3fcb6f12fab25e48aaf4df" },
+ { "vp90-2-14-resize-fp-tiles-16-4.webm", "47c48379fa6331215d91c67648e1af6e" },
+ { "vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm",
+ "eecf17290739bc708506fa4827665989" },
+ { "vp90-2-14-resize-fp-tiles-16-8.webm", "29b6bb54e4c26b5ca85d5de5fed94e76" },
+ { "vp90-2-14-resize-fp-tiles-1-8.webm", "1b6f175e08cd82cf84bb800ac6d1caa3" },
+ { "vp90-2-14-resize-fp-tiles-2-16.webm", "ca3b03e4197995d8d5444ede7a6c0804" },
+ { "vp90-2-14-resize-fp-tiles-2-1.webm", "99aec065369d70bbb78ccdff65afed3f" },
+ { "vp90-2-14-resize-fp-tiles-2-4.webm", "22d0ebdb49b87d2920a85aea32e1afd5" },
+ { "vp90-2-14-resize-fp-tiles-2-8.webm", "c2115cf051c62e0f7db1d4a783831541" },
+ { "vp90-2-14-resize-fp-tiles-4-16.webm", "c690d7e1719b31367564cac0af0939cb" },
+ { "vp90-2-14-resize-fp-tiles-4-1.webm", "a926020b2cc3e15ad4cc271853a0ff26" },
+ { "vp90-2-14-resize-fp-tiles-4-2.webm", "42699063d9e581f1993d0cf890c2be78" },
+ { "vp90-2-14-resize-fp-tiles-4-8.webm", "7f76d96036382f45121e3d5aa6f8ec52" },
+ { "vp90-2-14-resize-fp-tiles-8-16.webm", "76a43fcdd7e658542913ea43216ec55d" },
+ { "vp90-2-14-resize-fp-tiles-8-1.webm", "8e3fbe89486ca60a59299dea9da91378" },
+ { "vp90-2-14-resize-fp-tiles-8-2.webm", "ae96f21f21b6370cc0125621b441fc52" },
+ { "vp90-2-14-resize-fp-tiles-8-4.webm", "3eb4f24f10640d42218f7fd7b9fd30d4" },
+};
+
+const FileParam kNonFrameParallelFiles[] = {
+ { "vp90-2-08-tile_1x2.webm", "570b4a5d5a70d58b5359671668328a16" },
+ { "vp90-2-08-tile_1x4.webm", "988d86049e884c66909d2d163a09841a" },
+ { "vp90-2-08-tile_1x8.webm", "0941902a52e9092cb010905eab16364c" },
+ { "vp90-2-08-tile-4x1.webm", "06505aade6647c583c8e00a2f582266f" },
+ { "vp90-2-08-tile-4x4.webm", "85c2299892460d76e2c600502d52bfe2" },
+};
+
+INSTANTIATE_TEST_SUITE_P(NoTilesNonFrameParallel, VP9DecodeMultiThreadedTest,
+ ::testing::ValuesIn(kNoTilesNonFrameParallelFiles));
+INSTANTIATE_TEST_SUITE_P(FrameParallel, VP9DecodeMultiThreadedTest,
+ ::testing::ValuesIn(kFrameParallelFiles));
+INSTANTIATE_TEST_SUITE_P(FrameParallelResize, VP9DecodeMultiThreadedTest,
+ ::testing::ValuesIn(kFrameParallelResizeFiles));
+INSTANTIATE_TEST_SUITE_P(NonFrameParallel, VP9DecodeMultiThreadedTest,
+ ::testing::ValuesIn(kNonFrameParallelFiles));
+#endif // CONFIG_WEBM_IO
+
+INSTANTIATE_TEST_SUITE_P(Synchronous, VPxWorkerThreadTest, ::testing::Bool());
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/vpx_scale_test.cc b/media/libvpx/libvpx/test/vpx_scale_test.cc
new file mode 100644
index 0000000000..7eea437fc8
--- /dev/null
+++ b/media/libvpx/libvpx/test/vpx_scale_test.cc
@@ -0,0 +1,101 @@
+/*
+ * 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_scale_rtcd.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/vpx_scale_test.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/vpx_timer.h"
+#include "vpx_scale/yv12config.h"
+
+namespace libvpx_test {
+namespace {
+
+#if VPX_ARCH_ARM || (VPX_ARCH_MIPS && !HAVE_MIPS64) || VPX_ARCH_X86
+// Avoid OOM failures on 32-bit platforms.
+const int kNumSizesToTest = 7;
+#else
+const int kNumSizesToTest = 8;
+#endif
+const int kSizesToTest[] = { 1, 15, 33, 145, 512, 1025, 3840, 16383 };
+
+typedef void (*ExtendFrameBorderFunc)(YV12_BUFFER_CONFIG *ybf);
+typedef void (*CopyFrameFunc)(const YV12_BUFFER_CONFIG *src_ybf,
+ YV12_BUFFER_CONFIG *dst_ybf);
+
+class ExtendBorderTest
+ : public VpxScaleBase,
+ public ::testing::TestWithParam<ExtendFrameBorderFunc> {
+ public:
+ virtual ~ExtendBorderTest() {}
+
+ protected:
+ virtual void SetUp() { extend_fn_ = GetParam(); }
+
+ void ExtendBorder() { ASM_REGISTER_STATE_CHECK(extend_fn_(&img_)); }
+
+ void RunTest() {
+ for (int h = 0; h < kNumSizesToTest; ++h) {
+ for (int w = 0; w < kNumSizesToTest; ++w) {
+ ASSERT_NO_FATAL_FAILURE(ResetImages(kSizesToTest[w], kSizesToTest[h]));
+ ReferenceCopyFrame();
+ ExtendBorder();
+ CompareImages(img_);
+ DeallocImages();
+ }
+ }
+ }
+
+ ExtendFrameBorderFunc extend_fn_;
+};
+
+TEST_P(ExtendBorderTest, ExtendBorder) { ASSERT_NO_FATAL_FAILURE(RunTest()); }
+
+INSTANTIATE_TEST_SUITE_P(C, ExtendBorderTest,
+ ::testing::Values(vp8_yv12_extend_frame_borders_c));
+
+class CopyFrameTest : public VpxScaleBase,
+ public ::testing::TestWithParam<CopyFrameFunc> {
+ public:
+ virtual ~CopyFrameTest() {}
+
+ protected:
+ virtual void SetUp() { copy_frame_fn_ = GetParam(); }
+
+ void CopyFrame() {
+ ASM_REGISTER_STATE_CHECK(copy_frame_fn_(&img_, &dst_img_));
+ }
+
+ void RunTest() {
+ for (int h = 0; h < kNumSizesToTest; ++h) {
+ for (int w = 0; w < kNumSizesToTest; ++w) {
+ ASSERT_NO_FATAL_FAILURE(ResetImages(kSizesToTest[w], kSizesToTest[h]));
+ ReferenceCopyFrame();
+ CopyFrame();
+ CompareImages(dst_img_);
+ DeallocImages();
+ }
+ }
+ }
+
+ CopyFrameFunc copy_frame_fn_;
+};
+
+TEST_P(CopyFrameTest, CopyFrame) { ASSERT_NO_FATAL_FAILURE(RunTest()); }
+
+INSTANTIATE_TEST_SUITE_P(C, CopyFrameTest,
+ ::testing::Values(vp8_yv12_copy_frame_c));
+
+} // namespace
+} // namespace libvpx_test
diff --git a/media/libvpx/libvpx/test/vpx_scale_test.h b/media/libvpx/libvpx/test/vpx_scale_test.h
new file mode 100644
index 0000000000..11c259ae80
--- /dev/null
+++ b/media/libvpx/libvpx/test/vpx_scale_test.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VPX_TEST_VPX_SCALE_TEST_H_
+#define VPX_TEST_VPX_SCALE_TEST_H_
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_scale_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_scale/yv12config.h"
+
+using libvpx_test::ACMRandom;
+
+namespace libvpx_test {
+
+class VpxScaleBase {
+ public:
+ virtual ~VpxScaleBase() { libvpx_test::ClearSystemState(); }
+
+ void ResetImage(YV12_BUFFER_CONFIG *const img, const int width,
+ const int height) {
+ memset(img, 0, sizeof(*img));
+ ASSERT_EQ(
+ 0, vp8_yv12_alloc_frame_buffer(img, width, height, VP8BORDERINPIXELS))
+ << "for width: " << width << " height: " << height;
+ memset(img->buffer_alloc, kBufFiller, img->frame_size);
+ }
+
+ void ResetImages(const int width, const int height) {
+ ResetImage(&img_, width, height);
+ ResetImage(&ref_img_, width, height);
+ ResetImage(&dst_img_, width, height);
+
+ FillPlane(img_.y_buffer, img_.y_crop_width, img_.y_crop_height,
+ img_.y_stride);
+ FillPlane(img_.u_buffer, img_.uv_crop_width, img_.uv_crop_height,
+ img_.uv_stride);
+ FillPlane(img_.v_buffer, img_.uv_crop_width, img_.uv_crop_height,
+ img_.uv_stride);
+ }
+
+ void ResetScaleImage(YV12_BUFFER_CONFIG *const img, const int width,
+ const int height) {
+ memset(img, 0, sizeof(*img));
+#if CONFIG_VP9_HIGHBITDEPTH
+ ASSERT_EQ(0, vpx_alloc_frame_buffer(img, width, height, 1, 1, 0,
+ VP9_ENC_BORDER_IN_PIXELS, 0));
+#else
+ ASSERT_EQ(0, vpx_alloc_frame_buffer(img, width, height, 1, 1,
+ VP9_ENC_BORDER_IN_PIXELS, 0));
+#endif
+ memset(img->buffer_alloc, kBufFiller, img->frame_size);
+ }
+
+ void ResetScaleImages(const int src_width, const int src_height,
+ const int dst_width, const int dst_height) {
+ ResetScaleImage(&img_, src_width, src_height);
+ ResetScaleImage(&ref_img_, dst_width, dst_height);
+ ResetScaleImage(&dst_img_, dst_width, dst_height);
+ FillPlaneExtreme(img_.y_buffer, img_.y_crop_width, img_.y_crop_height,
+ img_.y_stride);
+ FillPlaneExtreme(img_.u_buffer, img_.uv_crop_width, img_.uv_crop_height,
+ img_.uv_stride);
+ FillPlaneExtreme(img_.v_buffer, img_.uv_crop_width, img_.uv_crop_height,
+ img_.uv_stride);
+ }
+
+ void DeallocImages() {
+ vp8_yv12_de_alloc_frame_buffer(&img_);
+ vp8_yv12_de_alloc_frame_buffer(&ref_img_);
+ vp8_yv12_de_alloc_frame_buffer(&dst_img_);
+ }
+
+ void DeallocScaleImages() {
+ vpx_free_frame_buffer(&img_);
+ vpx_free_frame_buffer(&ref_img_);
+ vpx_free_frame_buffer(&dst_img_);
+ }
+
+ protected:
+ static const int kBufFiller = 123;
+ static const int kBufMax = kBufFiller - 1;
+
+ static void FillPlane(uint8_t *const buf, const int width, const int height,
+ const int stride) {
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ buf[x + (y * stride)] = (x + (width * y)) % kBufMax;
+ }
+ }
+ }
+
+ static void FillPlaneExtreme(uint8_t *const buf, const int width,
+ const int height, const int stride) {
+ ACMRandom rnd;
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ buf[x + (y * stride)] = rnd.Rand8() % 2 ? 255 : 0;
+ }
+ }
+ }
+
+ static void ExtendPlane(uint8_t *buf, int crop_width, int crop_height,
+ int width, int height, int stride, int padding) {
+ // Copy the outermost visible pixel to a distance of at least 'padding.'
+ // The buffers are allocated such that there may be excess space outside the
+ // padding. As long as the minimum amount of padding is achieved it is not
+ // necessary to fill this space as well.
+ uint8_t *left = buf - padding;
+ uint8_t *right = buf + crop_width;
+ const int right_extend = padding + (width - crop_width);
+ const int bottom_extend = padding + (height - crop_height);
+
+ // Fill the border pixels from the nearest image pixel.
+ for (int y = 0; y < crop_height; ++y) {
+ memset(left, left[padding], padding);
+ memset(right, right[-1], right_extend);
+ left += stride;
+ right += stride;
+ }
+
+ left = buf - padding;
+ uint8_t *top = left - (stride * padding);
+ // The buffer does not always extend as far as the stride.
+ // Equivalent to padding + width + padding.
+ const int extend_width = padding + crop_width + right_extend;
+
+ // The first row was already extended to the left and right. Copy it up.
+ for (int y = 0; y < padding; ++y) {
+ memcpy(top, left, extend_width);
+ top += stride;
+ }
+
+ uint8_t *bottom = left + (crop_height * stride);
+ for (int y = 0; y < bottom_extend; ++y) {
+ memcpy(bottom, left + (crop_height - 1) * stride, extend_width);
+ bottom += stride;
+ }
+ }
+
+ void ReferenceExtendBorder() {
+ ExtendPlane(ref_img_.y_buffer, ref_img_.y_crop_width,
+ ref_img_.y_crop_height, ref_img_.y_width, ref_img_.y_height,
+ ref_img_.y_stride, ref_img_.border);
+ ExtendPlane(ref_img_.u_buffer, ref_img_.uv_crop_width,
+ ref_img_.uv_crop_height, ref_img_.uv_width, ref_img_.uv_height,
+ ref_img_.uv_stride, ref_img_.border / 2);
+ ExtendPlane(ref_img_.v_buffer, ref_img_.uv_crop_width,
+ ref_img_.uv_crop_height, ref_img_.uv_width, ref_img_.uv_height,
+ ref_img_.uv_stride, ref_img_.border / 2);
+ }
+
+ void ReferenceCopyFrame() {
+ // Copy img_ to ref_img_ and extend frame borders. This will be used for
+ // verifying extend_fn_ as well as copy_frame_fn_.
+ EXPECT_EQ(ref_img_.frame_size, img_.frame_size);
+ for (int y = 0; y < img_.y_crop_height; ++y) {
+ for (int x = 0; x < img_.y_crop_width; ++x) {
+ ref_img_.y_buffer[x + y * ref_img_.y_stride] =
+ img_.y_buffer[x + y * img_.y_stride];
+ }
+ }
+
+ for (int y = 0; y < img_.uv_crop_height; ++y) {
+ for (int x = 0; x < img_.uv_crop_width; ++x) {
+ ref_img_.u_buffer[x + y * ref_img_.uv_stride] =
+ img_.u_buffer[x + y * img_.uv_stride];
+ ref_img_.v_buffer[x + y * ref_img_.uv_stride] =
+ img_.v_buffer[x + y * img_.uv_stride];
+ }
+ }
+
+ ReferenceExtendBorder();
+ }
+
+ void CompareImages(const YV12_BUFFER_CONFIG actual) {
+ EXPECT_EQ(ref_img_.frame_size, actual.frame_size);
+ EXPECT_EQ(0, memcmp(ref_img_.buffer_alloc, actual.buffer_alloc,
+ ref_img_.frame_size));
+ }
+
+ YV12_BUFFER_CONFIG img_;
+ YV12_BUFFER_CONFIG ref_img_;
+ YV12_BUFFER_CONFIG dst_img_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_VPX_SCALE_TEST_H_
diff --git a/media/libvpx/libvpx/test/vpx_temporal_svc_encoder.sh b/media/libvpx/libvpx/test/vpx_temporal_svc_encoder.sh
new file mode 100755
index 0000000000..69c734daf8
--- /dev/null
+++ b/media/libvpx/libvpx/test/vpx_temporal_svc_encoder.sh
@@ -0,0 +1,334 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests the libvpx vpx_temporal_svc_encoder example. To add new
+## tests to this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to vpx_tsvc_encoder_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+vpx_tsvc_encoder_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ if [ "$(vpx_config_option_enabled CONFIG_TEMPORAL_DENOISING)" != "yes" ]; then
+ elog "Warning: Temporal denoising is disabled! Spatial denoising will be " \
+ "used instead, which is probably not what you want for this test."
+ fi
+}
+
+# Runs vpx_temporal_svc_encoder using the codec specified by $1 and output file
+# name by $2. Additional positional parameters are passed directly to
+# vpx_temporal_svc_encoder.
+vpx_tsvc_encoder() {
+ local encoder="${LIBVPX_BIN_PATH}/vpx_temporal_svc_encoder"
+ encoder="${encoder}${VPX_TEST_EXE_SUFFIX}"
+ local codec="$1"
+ local output_file_base="$2"
+ local output_file="${VPX_TEST_OUTPUT_DIR}/${output_file_base}"
+ local timebase_num="1"
+ local timebase_den="1000"
+ local timebase_den_y4m="30"
+ local speed="6"
+ local frame_drop_thresh="30"
+ local max_threads="4"
+ local error_resilient="1"
+
+ shift 2
+
+ if [ ! -x "${encoder}" ]; then
+ elog "${encoder} does not exist or is not executable."
+ return 1
+ fi
+
+ # TODO(tomfinegan): Verify file output for all thread runs.
+ for threads in $(seq $max_threads); do
+ if [ "$(vpx_config_option_enabled CONFIG_VP9_HIGHBITDEPTH)" != "yes" ]; then
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${YUV_RAW_INPUT}" \
+ "${output_file}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" "${timebase_num}" "${timebase_den}" \
+ "${speed}" "${frame_drop_thresh}" "${error_resilient}" "${threads}" \
+ "$@" ${devnull} || return 1
+ # Test for y4m input.
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${Y4M_720P_INPUT}" \
+ "${output_file}" "${codec}" "${Y4M_720P_INPUT_WIDTH}" \
+ "${Y4M_720P_INPUT_HEIGHT}" "${timebase_num}" "${timebase_den_y4m}" \
+ "${speed}" "${frame_drop_thresh}" "${error_resilient}" "${threads}" \
+ "$@" ${devnull} || return 1
+ else
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${YUV_RAW_INPUT}" \
+ "${output_file}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+ "${YUV_RAW_INPUT_HEIGHT}" "${timebase_num}" "${timebase_den}" \
+ "${speed}" "${frame_drop_thresh}" "${error_resilient}" "${threads}" \
+ "$@" "8" ${devnull} || return 1
+ fi
+ done
+}
+
+# Confirms that all expected output files exist given the output file name
+# passed to vpx_temporal_svc_encoder.
+# The file name passed to vpx_temporal_svc_encoder is joined with the stream
+# number and the extension .ivf to produce per stream output files. Here $1 is
+# file name, and $2 is expected number of files.
+files_exist() {
+ local file_name="${VPX_TEST_OUTPUT_DIR}/$1"
+ local num_files="$(($2 - 1))"
+ for stream_num in $(seq 0 ${num_files}); do
+ [ -e "${file_name}_${stream_num}.ivf" ] || return 1
+ done
+}
+
+# Run vpx_temporal_svc_encoder in all supported modes for vp8 and vp9.
+
+vpx_tsvc_encoder_vp8_mode_0() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_0"
+ vpx_tsvc_encoder vp8 "${output_basename}" 0 200 || return 1
+ # Mode 0 produces 1 stream
+ files_exist "${output_basename}" 1 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_1() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_1"
+ vpx_tsvc_encoder vp8 "${output_basename}" 1 200 400 || return 1
+ # Mode 1 produces 2 streams
+ files_exist "${output_basename}" 2 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_2() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_2"
+ vpx_tsvc_encoder vp8 "${output_basename}" 2 200 400 || return 1
+ # Mode 2 produces 2 streams
+ files_exist "${output_basename}" 2 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_3() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_3"
+ vpx_tsvc_encoder vp8 "${output_basename}" 3 200 400 600 || return 1
+ # Mode 3 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_4() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_4"
+ vpx_tsvc_encoder vp8 "${output_basename}" 4 200 400 600 || return 1
+ # Mode 4 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_5() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_5"
+ vpx_tsvc_encoder vp8 "${output_basename}" 5 200 400 600 || return 1
+ # Mode 5 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_6() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_6"
+ vpx_tsvc_encoder vp8 "${output_basename}" 6 200 400 600 || return 1
+ # Mode 6 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_7() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_7"
+ vpx_tsvc_encoder vp8 "${output_basename}" 7 200 400 600 800 1000 || return 1
+ # Mode 7 produces 5 streams
+ files_exist "${output_basename}" 5 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_8() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_8"
+ vpx_tsvc_encoder vp8 "${output_basename}" 8 200 400 || return 1
+ # Mode 8 produces 2 streams
+ files_exist "${output_basename}" 2 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_9() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_9"
+ vpx_tsvc_encoder vp8 "${output_basename}" 9 200 400 600 || return 1
+ # Mode 9 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_10() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_10"
+ vpx_tsvc_encoder vp8 "${output_basename}" 10 200 400 600 || return 1
+ # Mode 10 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp8_mode_11() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp8_mode_11"
+ vpx_tsvc_encoder vp8 "${output_basename}" 11 200 400 600 || return 1
+ # Mode 11 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_0() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_0"
+ vpx_tsvc_encoder vp9 "${output_basename}" 0 200 || return 1
+ # Mode 0 produces 1 stream
+ files_exist "${output_basename}" 1 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_1() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_1"
+ vpx_tsvc_encoder vp9 "${output_basename}" 1 200 400 || return 1
+ # Mode 1 produces 2 streams
+ files_exist "${output_basename}" 2 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_2() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_2"
+ vpx_tsvc_encoder vp9 "${output_basename}" 2 200 400 || return 1
+ # Mode 2 produces 2 streams
+ files_exist "${output_basename}" 2 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_3() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_3"
+ vpx_tsvc_encoder vp9 "${output_basename}" 3 200 400 600 || return 1
+ # Mode 3 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_4() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_4"
+ vpx_tsvc_encoder vp9 "${output_basename}" 4 200 400 600 || return 1
+ # Mode 4 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_5() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_5"
+ vpx_tsvc_encoder vp9 "${output_basename}" 5 200 400 600 || return 1
+ # Mode 5 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_6() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_6"
+ vpx_tsvc_encoder vp9 "${output_basename}" 6 200 400 600 || return 1
+ # Mode 6 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_7() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_7"
+ vpx_tsvc_encoder vp9 "${output_basename}" 7 200 400 600 800 1000 || return 1
+ # Mode 7 produces 5 streams
+ files_exist "${output_basename}" 5 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_8() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_8"
+ vpx_tsvc_encoder vp9 "${output_basename}" 8 200 400 || return 1
+ # Mode 8 produces 2 streams
+ files_exist "${output_basename}" 2 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_9() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_9"
+ vpx_tsvc_encoder vp9 "${output_basename}" 9 200 400 600 || return 1
+ # Mode 9 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_10() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_10"
+ vpx_tsvc_encoder vp9 "${output_basename}" 10 200 400 600 || return 1
+ # Mode 10 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_vp9_mode_11() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ local output_basename="vpx_tsvc_encoder_vp9_mode_11"
+ vpx_tsvc_encoder vp9 "${output_basename}" 11 200 400 600 || return 1
+ # Mode 11 produces 3 streams
+ files_exist "${output_basename}" 3 || return 1
+ fi
+}
+
+vpx_tsvc_encoder_tests="vpx_tsvc_encoder_vp8_mode_0
+ vpx_tsvc_encoder_vp8_mode_1
+ vpx_tsvc_encoder_vp8_mode_2
+ vpx_tsvc_encoder_vp8_mode_3
+ vpx_tsvc_encoder_vp8_mode_4
+ vpx_tsvc_encoder_vp8_mode_5
+ vpx_tsvc_encoder_vp8_mode_6
+ vpx_tsvc_encoder_vp8_mode_7
+ vpx_tsvc_encoder_vp8_mode_8
+ vpx_tsvc_encoder_vp8_mode_9
+ vpx_tsvc_encoder_vp8_mode_10
+ vpx_tsvc_encoder_vp8_mode_11
+ vpx_tsvc_encoder_vp9_mode_0
+ vpx_tsvc_encoder_vp9_mode_1
+ vpx_tsvc_encoder_vp9_mode_2
+ vpx_tsvc_encoder_vp9_mode_3
+ vpx_tsvc_encoder_vp9_mode_4
+ vpx_tsvc_encoder_vp9_mode_5
+ vpx_tsvc_encoder_vp9_mode_6
+ vpx_tsvc_encoder_vp9_mode_7
+ vpx_tsvc_encoder_vp9_mode_8
+ vpx_tsvc_encoder_vp9_mode_9
+ vpx_tsvc_encoder_vp9_mode_10
+ vpx_tsvc_encoder_vp9_mode_11"
+
+run_tests vpx_tsvc_encoder_verify_environment "${vpx_tsvc_encoder_tests}"
diff --git a/media/libvpx/libvpx/test/vpxdec.sh b/media/libvpx/libvpx/test/vpxdec.sh
new file mode 100755
index 0000000000..199feae5f3
--- /dev/null
+++ b/media/libvpx/libvpx/test/vpxdec.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests vpxdec. To add new tests to this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to vpxdec_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available.
+vpxdec_verify_environment() {
+ if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_WEBM_FILE}" ] || \
+ [ ! -e "${VP9_FPM_WEBM_FILE}" ] || \
+ [ ! -e "${VP9_LT_50_FRAMES_WEBM_FILE}" ] || \
+ [ ! -e "${VP9_RAW_FILE}" ]; then
+ elog "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ if [ -z "$(vpx_tool_path vpxdec)" ]; then
+ elog "vpxdec not found. It must exist in LIBVPX_BIN_PATH or its parent."
+ return 1
+ fi
+}
+
+# Wrapper function for running vpxdec with pipe input. Requires that
+# LIBVPX_BIN_PATH points to the directory containing vpxdec. $1 is used as the
+# input file path and shifted away. All remaining parameters are passed through
+# to vpxdec.
+vpxdec_pipe() {
+ local decoder="$(vpx_tool_path vpxdec)"
+ local input="$1"
+ shift
+ cat "${input}" | eval "${VPX_TEST_PREFIX}" "${decoder}" - "$@" ${devnull}
+}
+
+# Wrapper function for running vpxdec. Requires that LIBVPX_BIN_PATH points to
+# the directory containing vpxdec. $1 one is used as the input file path and
+# shifted away. All remaining parameters are passed through to vpxdec.
+vpxdec() {
+ local decoder="$(vpx_tool_path vpxdec)"
+ local input="$1"
+ shift
+ eval "${VPX_TEST_PREFIX}" "${decoder}" "$input" "$@" ${devnull}
+}
+
+vpxdec_can_decode_vp8() {
+ if [ "$(vp8_decode_available)" = "yes" ]; then
+ echo yes
+ fi
+}
+
+vpxdec_can_decode_vp9() {
+ if [ "$(vp9_decode_available)" = "yes" ]; then
+ echo yes
+ fi
+}
+
+vpxdec_vp8_ivf() {
+ if [ "$(vpxdec_can_decode_vp8)" = "yes" ]; then
+ vpxdec "${VP8_IVF_FILE}" --summary --noblit
+ fi
+}
+
+vpxdec_vp8_ivf_pipe_input() {
+ if [ "$(vpxdec_can_decode_vp8)" = "yes" ]; then
+ vpxdec_pipe "${VP8_IVF_FILE}" --summary --noblit
+ fi
+}
+
+vpxdec_vp9_webm() {
+ if [ "$(vpxdec_can_decode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ vpxdec "${VP9_WEBM_FILE}" --summary --noblit
+ fi
+}
+
+vpxdec_vp9_webm_frame_parallel() {
+ if [ "$(vpxdec_can_decode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ for threads in 2 3 4 5 6 7 8; do
+ vpxdec "${VP9_FPM_WEBM_FILE}" --summary --noblit --threads=$threads \
+ --frame-parallel || return 1
+ done
+ fi
+}
+
+vpxdec_vp9_webm_less_than_50_frames() {
+ # ensure that reaching eof in webm_guess_framerate doesn't result in invalid
+ # frames in actual webm_read_frame calls.
+ if [ "$(vpxdec_can_decode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local decoder="$(vpx_tool_path vpxdec)"
+ local expected=10
+ local num_frames=$(${VPX_TEST_PREFIX} "${decoder}" \
+ "${VP9_LT_50_FRAMES_WEBM_FILE}" --summary --noblit 2>&1 \
+ | awk '/^[0-9]+ decoded frames/ { print $1 }')
+ if [ "$num_frames" -ne "$expected" ]; then
+ elog "Output frames ($num_frames) != expected ($expected)"
+ return 1
+ fi
+ fi
+}
+
+# Ensures VP9_RAW_FILE correctly produces 1 frame instead of causing a hang.
+vpxdec_vp9_raw_file() {
+ # Ensure a raw file properly reports eof and doesn't cause a hang.
+ if [ "$(vpxdec_can_decode_vp9)" = "yes" ]; then
+ local decoder="$(vpx_tool_path vpxdec)"
+ local expected=1
+ [ -x /usr/bin/timeout ] && local TIMEOUT="/usr/bin/timeout 30s"
+ local num_frames=$(${TIMEOUT} ${VPX_TEST_PREFIX} "${decoder}" \
+ "${VP9_RAW_FILE}" --summary --noblit 2>&1 \
+ | awk '/^[0-9]+ decoded frames/ { print $1 }')
+ if [ -z "$num_frames" ] || [ "$num_frames" -ne "$expected" ]; then
+ elog "Output frames ($num_frames) != expected ($expected)"
+ return 1
+ fi
+ fi
+}
+
+vpxdec_tests="vpxdec_vp8_ivf
+ vpxdec_vp8_ivf_pipe_input
+ vpxdec_vp9_webm
+ vpxdec_vp9_webm_frame_parallel
+ vpxdec_vp9_webm_less_than_50_frames
+ vpxdec_vp9_raw_file"
+
+run_tests vpxdec_verify_environment "${vpxdec_tests}"
diff --git a/media/libvpx/libvpx/test/vpxenc.sh b/media/libvpx/libvpx/test/vpxenc.sh
new file mode 100755
index 0000000000..172349a2b3
--- /dev/null
+++ b/media/libvpx/libvpx/test/vpxenc.sh
@@ -0,0 +1,489 @@
+#!/bin/sh
+##
+## 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.
+##
+## This file tests vpxenc using hantro_collage_w352h288.yuv as input. To add
+## new tests to this file, do the following:
+## 1. Write a shell function (this is your test).
+## 2. Add the function to vpxenc_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+readonly TEST_FRAMES=10
+
+# Environment check: Make sure input is available.
+vpxenc_verify_environment() {
+ if [ ! -e "${YUV_RAW_INPUT}" ]; then
+ elog "The file ${YUV_RAW_INPUT##*/} must exist in LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ]; then
+ if [ ! -e "${Y4M_NOSQ_PAR_INPUT}" ]; then
+ elog "The file ${Y4M_NOSQ_PAR_INPUT##*/} must exist in"
+ elog "LIBVPX_TEST_DATA_PATH."
+ return 1
+ fi
+ fi
+ if [ -z "$(vpx_tool_path vpxenc)" ]; then
+ elog "vpxenc not found. It must exist in LIBVPX_BIN_PATH or its parent."
+ return 1
+ fi
+}
+
+vpxenc_can_encode_vp8() {
+ if [ "$(vp8_encode_available)" = "yes" ]; then
+ echo yes
+ fi
+}
+
+vpxenc_can_encode_vp9() {
+ if [ "$(vp9_encode_available)" = "yes" ]; then
+ echo yes
+ fi
+}
+
+# Echo vpxenc command line parameters allowing use of
+# hantro_collage_w352h288.yuv as input.
+yuv_input_hantro_collage() {
+ echo ""${YUV_RAW_INPUT}"
+ --width="${YUV_RAW_INPUT_WIDTH}"
+ --height="${YUV_RAW_INPUT_HEIGHT}""
+}
+
+y4m_input_non_square_par() {
+ echo ""${Y4M_NOSQ_PAR_INPUT}""
+}
+
+y4m_input_720p() {
+ echo ""${Y4M_720P_INPUT}""
+}
+
+# Echo default vpxenc real time encoding params. $1 is the codec, which defaults
+# to vp8 if unspecified.
+vpxenc_rt_params() {
+ local codec="${1:-vp8}"
+ echo "--codec=${codec}
+ --buf-initial-sz=500
+ --buf-optimal-sz=600
+ --buf-sz=1000
+ --cpu-used=-6
+ --end-usage=cbr
+ --error-resilient=1
+ --kf-max-dist=90000
+ --lag-in-frames=0
+ --max-intra-rate=300
+ --max-q=56
+ --min-q=2
+ --noise-sensitivity=0
+ --overshoot-pct=50
+ --passes=1
+ --profile=0
+ --resize-allowed=0
+ --rt
+ --static-thresh=0
+ --undershoot-pct=50"
+}
+
+# Forces --passes to 1 with CONFIG_REALTIME_ONLY.
+vpxenc_passes_param() {
+ if [ "$(vpx_config_option_enabled CONFIG_REALTIME_ONLY)" = "yes" ]; then
+ echo "--passes=1"
+ else
+ echo "--passes=2"
+ fi
+}
+
+# Wrapper function for running vpxenc with pipe input. Requires that
+# LIBVPX_BIN_PATH points to the directory containing vpxenc. $1 is used as the
+# input file path and shifted away. All remaining parameters are passed through
+# to vpxenc.
+vpxenc_pipe() {
+ local encoder="$(vpx_tool_path vpxenc)"
+ local input="$1"
+ shift
+ cat "${input}" | eval "${VPX_TEST_PREFIX}" "${encoder}" - \
+ --test-decode=fatal \
+ "$@" ${devnull}
+}
+
+# Wrapper function for running vpxenc. Requires that LIBVPX_BIN_PATH points to
+# the directory containing vpxenc. $1 one is used as the input file path and
+# shifted away. All remaining parameters are passed through to vpxenc.
+vpxenc() {
+ local encoder="$(vpx_tool_path vpxenc)"
+ local input="$1"
+ shift
+ eval "${VPX_TEST_PREFIX}" "${encoder}" "${input}" \
+ --test-decode=fatal \
+ "$@" ${devnull}
+}
+
+vpxenc_vp8_ivf() {
+ if [ "$(vpxenc_can_encode_vp8)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp8.ivf"
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp8 \
+ --limit="${TEST_FRAMES}" \
+ --ivf \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp8_webm() {
+ if [ "$(vpxenc_can_encode_vp8)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp8.webm"
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp8 \
+ --limit="${TEST_FRAMES}" \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp8_webm_rt() {
+ if [ "$(vpxenc_can_encode_vp8)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp8_rt.webm"
+ vpxenc $(yuv_input_hantro_collage) \
+ $(vpxenc_rt_params vp8) \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp8_webm_2pass() {
+ if [ "$(vpxenc_can_encode_vp8)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp8.webm"
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp8 \
+ --limit="${TEST_FRAMES}" \
+ --output="${output}" \
+ --passes=2 || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp8_webm_lag10_frames20() {
+ if [ "$(vpxenc_can_encode_vp8)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local lag_total_frames=20
+ local lag_frames=10
+ local output="${VPX_TEST_OUTPUT_DIR}/vp8_lag10_frames20.webm"
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp8 \
+ --limit="${lag_total_frames}" \
+ --lag-in-frames="${lag_frames}" \
+ --output="${output}" \
+ --auto-alt-ref=1 \
+ --passes=2 || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp8_ivf_piped_input() {
+ if [ "$(vpxenc_can_encode_vp8)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp8_piped_input.ivf"
+ vpxenc_pipe $(yuv_input_hantro_collage) \
+ --codec=vp8 \
+ --limit="${TEST_FRAMES}" \
+ --ivf \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_ivf() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9.ivf"
+ local passes=$(vpxenc_passes_param)
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp9 \
+ --limit="${TEST_FRAMES}" \
+ "${passes}" \
+ --ivf \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_webm() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9.webm"
+ local passes=$(vpxenc_passes_param)
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp9 \
+ --limit="${TEST_FRAMES}" \
+ "${passes}" \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_webm_rt() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_rt.webm"
+ vpxenc $(yuv_input_hantro_collage) \
+ $(vpxenc_rt_params vp9) \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_webm_rt_multithread_tiled() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_rt_multithread_tiled.webm"
+ local tilethread_min=2
+ local tilethread_max=4
+ local num_threads="$(seq ${tilethread_min} ${tilethread_max})"
+ local num_tile_cols="$(seq ${tilethread_min} ${tilethread_max})"
+
+ for threads in ${num_threads}; do
+ for tile_cols in ${num_tile_cols}; do
+ vpxenc $(y4m_input_720p) \
+ $(vpxenc_rt_params vp9) \
+ --threads=${threads} \
+ --tile-columns=${tile_cols} \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ rm "${output}"
+ done
+ done
+ fi
+}
+
+vpxenc_vp9_webm_rt_multithread_tiled_frameparallel() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_rt_mt_t_fp.webm"
+ local tilethread_min=2
+ local tilethread_max=4
+ local num_threads="$(seq ${tilethread_min} ${tilethread_max})"
+ local num_tile_cols="$(seq ${tilethread_min} ${tilethread_max})"
+
+ for threads in ${num_threads}; do
+ for tile_cols in ${num_tile_cols}; do
+ vpxenc $(y4m_input_720p) \
+ $(vpxenc_rt_params vp9) \
+ --threads=${threads} \
+ --tile-columns=${tile_cols} \
+ --frame-parallel=1 \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ rm "${output}"
+ done
+ done
+ fi
+}
+
+vpxenc_vp9_webm_2pass() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9.webm"
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp9 \
+ --limit="${TEST_FRAMES}" \
+ --output="${output}" \
+ --passes=2 || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_ivf_lossless() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_lossless.ivf"
+ local passes=$(vpxenc_passes_param)
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp9 \
+ --limit="${TEST_FRAMES}" \
+ --ivf \
+ --output="${output}" \
+ "${passes}" \
+ --lossless=1 || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_ivf_minq0_maxq0() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_lossless_minq0_maxq0.ivf"
+ local passes=$(vpxenc_passes_param)
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp9 \
+ --limit="${TEST_FRAMES}" \
+ --ivf \
+ --output="${output}" \
+ "${passes}" \
+ --min-q=0 \
+ --max-q=0 || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_webm_lag10_frames20() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local lag_total_frames=20
+ local lag_frames=10
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_lag10_frames20.webm"
+ local passes=$(vpxenc_passes_param)
+ vpxenc $(yuv_input_hantro_collage) \
+ --codec=vp9 \
+ --limit="${lag_total_frames}" \
+ --lag-in-frames="${lag_frames}" \
+ --output="${output}" \
+ "${passes}" \
+ --auto-alt-ref=1 || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+# TODO(fgalligan): Test that DisplayWidth is different than video width.
+vpxenc_vp9_webm_non_square_par() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ] && \
+ [ "$(webm_io_available)" = "yes" ]; then
+ local output="${VPX_TEST_OUTPUT_DIR}/vp9_non_square_par.webm"
+ local passes=$(vpxenc_passes_param)
+ vpxenc $(y4m_input_non_square_par) \
+ --codec=vp9 \
+ --limit="${TEST_FRAMES}" \
+ "${passes}" \
+ --output="${output}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+ fi
+}
+
+vpxenc_vp9_webm_sharpness() {
+ if [ "$(vpxenc_can_encode_vp9)" = "yes" ]; then
+ local sharpnesses="0 1 2 3 4 5 6 7"
+ local output="${VPX_TEST_OUTPUT_DIR}/vpxenc_vp9_webm_sharpness.ivf"
+ local last_size=0
+ local this_size=0
+
+ for sharpness in ${sharpnesses}; do
+
+ vpxenc $(yuv_input_hantro_collage) \
+ --sharpness="${sharpness}" \
+ --codec=vp9 \
+ --limit=1 \
+ --cpu-used=2 \
+ --end-usage=q \
+ --cq-level=40 \
+ --output="${output}" \
+ "${passes}" || return 1
+
+ if [ ! -e "${output}" ]; then
+ elog "Output file does not exist."
+ return 1
+ fi
+
+ this_size=$(stat -c '%s' "${output}")
+ if [ "${this_size}" -lt "${last_size}" ]; then
+ elog "Higher sharpness value yielded lower file size."
+ echo "${this_size}" " < " "${last_size}"
+ return 1
+ fi
+ last_size="${this_size}"
+
+ done
+ fi
+}
+
+vpxenc_tests="vpxenc_vp8_ivf
+ vpxenc_vp8_webm
+ vpxenc_vp8_webm_rt
+ vpxenc_vp8_ivf_piped_input
+ vpxenc_vp9_ivf
+ vpxenc_vp9_webm
+ vpxenc_vp9_webm_rt
+ vpxenc_vp9_webm_rt_multithread_tiled
+ vpxenc_vp9_webm_rt_multithread_tiled_frameparallel
+ vpxenc_vp9_ivf_lossless
+ vpxenc_vp9_ivf_minq0_maxq0
+ vpxenc_vp9_webm_lag10_frames20
+ vpxenc_vp9_webm_non_square_par
+ vpxenc_vp9_webm_sharpness"
+
+if [ "$(vpx_config_option_enabled CONFIG_REALTIME_ONLY)" != "yes" ]; then
+ vpxenc_tests="$vpxenc_tests
+ vpxenc_vp8_webm_2pass
+ vpxenc_vp8_webm_lag10_frames20
+ vpxenc_vp9_webm_2pass"
+fi
+
+run_tests vpxenc_verify_environment "${vpxenc_tests}"
diff --git a/media/libvpx/libvpx/test/webm_video_source.h b/media/libvpx/libvpx/test/webm_video_source.h
new file mode 100644
index 0000000000..d245926298
--- /dev/null
+++ b/media/libvpx/libvpx/test/webm_video_source.h
@@ -0,0 +1,95 @@
+/*
+ * 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 VPX_TEST_WEBM_VIDEO_SOURCE_H_
+#define VPX_TEST_WEBM_VIDEO_SOURCE_H_
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <new>
+#include <string>
+#include "../tools_common.h"
+#include "../webmdec.h"
+#include "test/video_source.h"
+
+namespace libvpx_test {
+
+// This class extends VideoSource to allow parsing of WebM files,
+// so that we can do actual file decodes.
+class WebMVideoSource : public CompressedVideoSource {
+ public:
+ explicit WebMVideoSource(const std::string &file_name)
+ : file_name_(file_name), vpx_ctx_(new VpxInputContext()),
+ webm_ctx_(new WebmInputContext()), buf_(nullptr), buf_sz_(0), frame_(0),
+ end_of_file_(false) {}
+
+ virtual ~WebMVideoSource() {
+ if (vpx_ctx_->file != nullptr) fclose(vpx_ctx_->file);
+ webm_free(webm_ctx_);
+ delete vpx_ctx_;
+ delete webm_ctx_;
+ }
+
+ virtual void Init() {}
+
+ virtual void Begin() {
+ vpx_ctx_->file = OpenTestDataFile(file_name_);
+ ASSERT_NE(vpx_ctx_->file, nullptr)
+ << "Input file open failed. Filename: " << file_name_;
+
+ ASSERT_EQ(file_is_webm(webm_ctx_, vpx_ctx_), 1) << "file is not WebM";
+
+ FillFrame();
+ }
+
+ virtual void Next() {
+ ++frame_;
+ FillFrame();
+ }
+
+ void FillFrame() {
+ ASSERT_NE(vpx_ctx_->file, nullptr);
+ const int status = webm_read_frame(webm_ctx_, &buf_, &buf_sz_);
+ ASSERT_GE(status, 0) << "webm_read_frame failed";
+ if (status == 1) {
+ end_of_file_ = true;
+ }
+ }
+
+ void SeekToNextKeyFrame() {
+ ASSERT_NE(vpx_ctx_->file, nullptr);
+ do {
+ const int status = webm_read_frame(webm_ctx_, &buf_, &buf_sz_);
+ ASSERT_GE(status, 0) << "webm_read_frame failed";
+ ++frame_;
+ if (status == 1) {
+ end_of_file_ = true;
+ }
+ } while (!webm_ctx_->is_key_frame && !end_of_file_);
+ }
+
+ virtual const uint8_t *cxdata() const {
+ return end_of_file_ ? nullptr : buf_;
+ }
+ virtual size_t frame_size() const { return buf_sz_; }
+ virtual unsigned int frame_number() const { return frame_; }
+
+ protected:
+ std::string file_name_;
+ VpxInputContext *vpx_ctx_;
+ WebmInputContext *webm_ctx_;
+ uint8_t *buf_;
+ size_t buf_sz_;
+ unsigned int frame_;
+ bool end_of_file_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_WEBM_VIDEO_SOURCE_H_
diff --git a/media/libvpx/libvpx/test/y4m_test.cc b/media/libvpx/libvpx/test/y4m_test.cc
new file mode 100644
index 0000000000..32f2cd51d3
--- /dev/null
+++ b/media/libvpx/libvpx/test/y4m_test.cc
@@ -0,0 +1,244 @@
+/*
+ * 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 <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./y4menc.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+
+namespace {
+
+using std::string;
+
+static const unsigned int kWidth = 160;
+static const unsigned int kHeight = 90;
+static const unsigned int kFrames = 10;
+
+struct Y4mTestParam {
+ const char *filename;
+ unsigned int bit_depth;
+ vpx_img_fmt format;
+ const char *md5raw;
+};
+
+const Y4mTestParam kY4mTestVectors[] = {
+ { "park_joy_90p_8_420.y4m", 8, VPX_IMG_FMT_I420,
+ "e5406275b9fc6bb3436c31d4a05c1cab" },
+ { "park_joy_90p_8_422.y4m", 8, VPX_IMG_FMT_I422,
+ "284a47a47133b12884ec3a14e959a0b6" },
+ { "park_joy_90p_8_444.y4m", 8, VPX_IMG_FMT_I444,
+ "90517ff33843d85de712fd4fe60dbed0" },
+ { "park_joy_90p_10_420_20f.y4m", 10, VPX_IMG_FMT_I42016,
+ "2f56ab9809269f074df7e3daf1ce0be6" },
+ { "park_joy_90p_10_422_20f.y4m", 10, VPX_IMG_FMT_I42216,
+ "1b5c73d2e8e8c4e02dc4889ecac41c83" },
+ { "park_joy_90p_10_444_20f.y4m", 10, VPX_IMG_FMT_I44416,
+ "ec4ab5be53195c5b838d1d19e1bc2674" },
+ { "park_joy_90p_12_420_20f.y4m", 12, VPX_IMG_FMT_I42016,
+ "3370856c8ddebbd1f9bb2e66f97677f4" },
+ { "park_joy_90p_12_422_20f.y4m", 12, VPX_IMG_FMT_I42216,
+ "4eab364318dd8201acbb182e43bd4966" },
+ { "park_joy_90p_12_444_20f.y4m", 12, VPX_IMG_FMT_I44416,
+ "f189dfbbd92119fc8e5f211a550166be" },
+};
+
+static void write_image_file(const vpx_image_t *img, FILE *file) {
+ int plane, y;
+ for (plane = 0; plane < 3; ++plane) {
+ const unsigned char *buf = img->planes[plane];
+ const int stride = img->stride[plane];
+ const int bytes_per_sample = (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
+ const int h =
+ (plane ? (img->d_h + img->y_chroma_shift) >> img->y_chroma_shift
+ : img->d_h);
+ const int w =
+ (plane ? (img->d_w + img->x_chroma_shift) >> img->x_chroma_shift
+ : img->d_w);
+ for (y = 0; y < h; ++y) {
+ fwrite(buf, bytes_per_sample, w, file);
+ buf += stride;
+ }
+ }
+}
+
+class Y4mVideoSourceTest : public ::testing::TestWithParam<Y4mTestParam>,
+ public ::libvpx_test::Y4mVideoSource {
+ protected:
+ Y4mVideoSourceTest() : Y4mVideoSource("", 0, 0) {}
+
+ virtual ~Y4mVideoSourceTest() { CloseSource(); }
+
+ virtual void Init(const std::string &file_name, int limit) {
+ file_name_ = file_name;
+ start_ = 0;
+ limit_ = limit;
+ frame_ = 0;
+ Begin();
+ }
+
+ // Checks y4m header information
+ void HeaderChecks(unsigned int bit_depth, vpx_img_fmt_t fmt) {
+ ASSERT_NE(input_file_, nullptr);
+ ASSERT_EQ(y4m_.pic_w, (int)kWidth);
+ ASSERT_EQ(y4m_.pic_h, (int)kHeight);
+ ASSERT_EQ(img()->d_w, kWidth);
+ ASSERT_EQ(img()->d_h, kHeight);
+ ASSERT_EQ(y4m_.bit_depth, bit_depth);
+ ASSERT_EQ(y4m_.vpx_fmt, fmt);
+ if (fmt == VPX_IMG_FMT_I420 || fmt == VPX_IMG_FMT_I42016) {
+ ASSERT_EQ(y4m_.bps, (int)y4m_.bit_depth * 3 / 2);
+ ASSERT_EQ(img()->x_chroma_shift, 1U);
+ ASSERT_EQ(img()->y_chroma_shift, 1U);
+ }
+ if (fmt == VPX_IMG_FMT_I422 || fmt == VPX_IMG_FMT_I42216) {
+ ASSERT_EQ(y4m_.bps, (int)y4m_.bit_depth * 2);
+ ASSERT_EQ(img()->x_chroma_shift, 1U);
+ ASSERT_EQ(img()->y_chroma_shift, 0U);
+ }
+ if (fmt == VPX_IMG_FMT_I444 || fmt == VPX_IMG_FMT_I44416) {
+ ASSERT_EQ(y4m_.bps, (int)y4m_.bit_depth * 3);
+ ASSERT_EQ(img()->x_chroma_shift, 0U);
+ ASSERT_EQ(img()->y_chroma_shift, 0U);
+ }
+ }
+
+ // Checks MD5 of the raw frame data
+ void Md5Check(const string &expected_md5) {
+ ASSERT_NE(input_file_, nullptr);
+ libvpx_test::MD5 md5;
+ for (unsigned int i = start_; i < limit_; i++) {
+ md5.Add(img());
+ Next();
+ }
+ ASSERT_EQ(string(md5.Get()), expected_md5);
+ }
+};
+
+TEST_P(Y4mVideoSourceTest, SourceTest) {
+ const Y4mTestParam t = GetParam();
+ Init(t.filename, kFrames);
+ HeaderChecks(t.bit_depth, t.format);
+ Md5Check(t.md5raw);
+}
+
+INSTANTIATE_TEST_SUITE_P(C, Y4mVideoSourceTest,
+ ::testing::ValuesIn(kY4mTestVectors));
+
+class Y4mVideoWriteTest : public Y4mVideoSourceTest {
+ protected:
+ Y4mVideoWriteTest() : tmpfile_(nullptr) {}
+
+ virtual ~Y4mVideoWriteTest() {
+ delete tmpfile_;
+ input_file_ = nullptr;
+ }
+
+ void ReplaceInputFile(FILE *input_file) {
+ CloseSource();
+ frame_ = 0;
+ input_file_ = input_file;
+ rewind(input_file_);
+ ReadSourceToStart();
+ }
+
+ // Writes out a y4m file and then reads it back
+ void WriteY4mAndReadBack() {
+ ASSERT_NE(input_file_, nullptr);
+ char buf[Y4M_BUFFER_SIZE] = { 0 };
+ const struct VpxRational framerate = { y4m_.fps_n, y4m_.fps_d };
+ tmpfile_ = new libvpx_test::TempOutFile;
+ ASSERT_NE(tmpfile_->file(), nullptr);
+ y4m_write_file_header(buf, sizeof(buf), kWidth, kHeight, &framerate,
+ y4m_.vpx_fmt, y4m_.bit_depth);
+ fputs(buf, tmpfile_->file());
+ for (unsigned int i = start_; i < limit_; i++) {
+ y4m_write_frame_header(buf, sizeof(buf));
+ fputs(buf, tmpfile_->file());
+ write_image_file(img(), tmpfile_->file());
+ Next();
+ }
+ ReplaceInputFile(tmpfile_->file());
+ }
+
+ virtual void Init(const std::string &file_name, int limit) {
+ Y4mVideoSourceTest::Init(file_name, limit);
+ WriteY4mAndReadBack();
+ }
+ libvpx_test::TempOutFile *tmpfile_;
+};
+
+TEST_P(Y4mVideoWriteTest, WriteTest) {
+ const Y4mTestParam t = GetParam();
+ Init(t.filename, kFrames);
+ HeaderChecks(t.bit_depth, t.format);
+ Md5Check(t.md5raw);
+}
+
+INSTANTIATE_TEST_SUITE_P(C, Y4mVideoWriteTest,
+ ::testing::ValuesIn(kY4mTestVectors));
+
+static const char kY4MRegularHeader[] =
+ "YUV4MPEG2 W4 H4 F30:1 Ip A0:0 C420jpeg XYSCSS=420JPEG\n"
+ "FRAME\n"
+ "012345678912345601230123";
+
+TEST(Y4MHeaderTest, RegularHeader) {
+ libvpx_test::TempOutFile f;
+ ASSERT_NE(f.file(), nullptr);
+ fwrite(kY4MRegularHeader, 1, sizeof(kY4MRegularHeader), f.file());
+ fflush(f.file());
+ EXPECT_EQ(0, fseek(f.file(), 0, 0));
+
+ y4m_input y4m;
+ EXPECT_EQ(y4m_input_open(&y4m, f.file(), /*skip_buffer=*/nullptr,
+ /*num_skip=*/0, /*only_420=*/0),
+ 0);
+ EXPECT_EQ(y4m.pic_w, 4);
+ EXPECT_EQ(y4m.pic_h, 4);
+ EXPECT_EQ(y4m.fps_n, 30);
+ EXPECT_EQ(y4m.fps_d, 1);
+ EXPECT_EQ(y4m.interlace, 'p');
+ EXPECT_EQ(strcmp("420jpeg", y4m.chroma_type), 0);
+ y4m_input_close(&y4m);
+}
+
+// Testing that headers over 100 characters can be parsed.
+static const char kY4MLongHeader[] =
+ "YUV4MPEG2 W4 H4 F30:1 Ip A0:0 C420jpeg XYSCSS=420JPEG "
+ "XCOLORRANGE=LIMITED XSOME_UNKNOWN_METADATA XOTHER_UNKNOWN_METADATA\n"
+ "FRAME\n"
+ "012345678912345601230123";
+
+TEST(Y4MHeaderTest, LongHeader) {
+ libvpx_test::TempOutFile f;
+ ASSERT_NE(f.file(), nullptr);
+ fwrite(kY4MLongHeader, 1, sizeof(kY4MLongHeader), f.file());
+ fflush(f.file());
+ EXPECT_EQ(fseek(f.file(), 0, 0), 0);
+
+ y4m_input y4m;
+ EXPECT_EQ(y4m_input_open(&y4m, f.file(), /*skip_buffer=*/nullptr,
+ /*num_skip=*/0, /*only_420=*/0),
+ 0);
+ EXPECT_EQ(y4m.pic_w, 4);
+ EXPECT_EQ(y4m.pic_h, 4);
+ EXPECT_EQ(y4m.fps_n, 30);
+ EXPECT_EQ(y4m.fps_d, 1);
+ EXPECT_EQ(y4m.interlace, 'p');
+ EXPECT_EQ(strcmp("420jpeg", y4m.chroma_type), 0);
+ y4m_input_close(&y4m);
+}
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/y4m_video_source.h b/media/libvpx/libvpx/test/y4m_video_source.h
new file mode 100644
index 0000000000..71fbf31931
--- /dev/null
+++ b/media/libvpx/libvpx/test/y4m_video_source.h
@@ -0,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.
+ */
+#ifndef VPX_TEST_Y4M_VIDEO_SOURCE_H_
+#define VPX_TEST_Y4M_VIDEO_SOURCE_H_
+#include <algorithm>
+#include <memory>
+#include <string>
+
+#include "test/video_source.h"
+#include "./y4minput.h"
+
+namespace libvpx_test {
+
+// This class extends VideoSource to allow parsing of raw yv12
+// so that we can do actual file encodes.
+class Y4mVideoSource : public VideoSource {
+ public:
+ Y4mVideoSource(const std::string &file_name, unsigned int start, int limit)
+ : file_name_(file_name), input_file_(nullptr), img_(new vpx_image_t()),
+ start_(start), limit_(limit), frame_(0), framerate_numerator_(0),
+ framerate_denominator_(0), y4m_() {}
+
+ virtual ~Y4mVideoSource() {
+ vpx_img_free(img_.get());
+ CloseSource();
+ }
+
+ virtual void OpenSource() {
+ CloseSource();
+ input_file_ = OpenTestDataFile(file_name_);
+ ASSERT_NE(input_file_, nullptr)
+ << "Input file open failed. Filename: " << file_name_;
+ }
+
+ virtual void ReadSourceToStart() {
+ ASSERT_NE(input_file_, nullptr);
+ ASSERT_FALSE(y4m_input_open(&y4m_, input_file_, nullptr, 0, 0));
+ framerate_numerator_ = y4m_.fps_n;
+ framerate_denominator_ = y4m_.fps_d;
+ frame_ = 0;
+ for (unsigned int i = 0; i < start_; i++) {
+ Next();
+ }
+ FillFrame();
+ }
+
+ virtual void Begin() {
+ OpenSource();
+ ReadSourceToStart();
+ }
+
+ virtual void Next() {
+ ++frame_;
+ FillFrame();
+ }
+
+ virtual vpx_image_t *img() const {
+ return (frame_ < limit_) ? img_.get() : nullptr;
+ }
+
+ // 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 = { framerate_denominator_, framerate_numerator_ };
+ return t;
+ }
+
+ virtual unsigned int frame() const { return frame_; }
+
+ virtual unsigned int limit() const { return limit_; }
+
+ virtual void FillFrame() {
+ ASSERT_NE(input_file_, nullptr);
+ // Read a frame from input_file.
+ y4m_input_fetch_frame(&y4m_, input_file_, img_.get());
+ }
+
+ // Swap buffers with another y4m source. This allows reading a new frame
+ // while keeping the old frame around. A whole Y4mSource is required and
+ // not just a vpx_image_t because of how the y4m reader manipulates
+ // vpx_image_t internals,
+ void SwapBuffers(Y4mVideoSource *other) {
+ std::swap(other->y4m_.dst_buf, y4m_.dst_buf);
+ vpx_image_t *tmp;
+ tmp = other->img_.release();
+ other->img_.reset(img_.release());
+ img_.reset(tmp);
+ }
+
+ protected:
+ void CloseSource() {
+ y4m_input_close(&y4m_);
+ y4m_ = y4m_input();
+ if (input_file_ != nullptr) {
+ fclose(input_file_);
+ input_file_ = nullptr;
+ }
+ }
+
+ std::string file_name_;
+ FILE *input_file_;
+ std::unique_ptr<vpx_image_t> img_;
+ unsigned int start_;
+ unsigned int limit_;
+ unsigned int frame_;
+ int framerate_numerator_;
+ int framerate_denominator_;
+ y4m_input y4m_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_Y4M_VIDEO_SOURCE_H_
diff --git a/media/libvpx/libvpx/test/yuv_temporal_filter_test.cc b/media/libvpx/libvpx/test/yuv_temporal_filter_test.cc
new file mode 100644
index 0000000000..91b4e804b3
--- /dev/null
+++ b/media/libvpx/libvpx/test/yuv_temporal_filter_test.cc
@@ -0,0 +1,726 @@
+/*
+ * Copyright (c) 2019 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"
+
+#include "./vp9_rtcd.h"
+#include "test/acm_random.h"
+#include "test/buffer.h"
+#include "test/register_state_check.h"
+#include "vpx_ports/vpx_timer.h"
+
+namespace {
+
+using ::libvpx_test::ACMRandom;
+using ::libvpx_test::Buffer;
+
+typedef void (*YUVTemporalFilterFunc)(
+ const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre,
+ int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src,
+ int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre,
+ int uv_pre_stride, unsigned int block_width, unsigned int block_height,
+ int ss_x, int ss_y, int strength, const int *const blk_fw, int use_32x32,
+ uint32_t *y_accumulator, uint16_t *y_count, uint32_t *u_accumulator,
+ uint16_t *u_count, uint32_t *v_accumulator, uint16_t *v_count);
+
+struct TemporalFilterWithBd {
+ TemporalFilterWithBd(YUVTemporalFilterFunc func, int bitdepth)
+ : temporal_filter(func), bd(bitdepth) {}
+
+ YUVTemporalFilterFunc temporal_filter;
+ int bd;
+};
+
+std::ostream &operator<<(std::ostream &os, const TemporalFilterWithBd &tf) {
+ return os << "Bitdepth: " << tf.bd;
+}
+
+int GetFilterWeight(unsigned int row, unsigned int col,
+ unsigned int block_height, unsigned int block_width,
+ const int *const blk_fw, int use_32x32) {
+ if (use_32x32) {
+ return blk_fw[0];
+ }
+
+ return blk_fw[2 * (row >= block_height / 2) + (col >= block_width / 2)];
+}
+
+template <typename PixelType>
+int GetModIndex(int sum_dist, int index, int rounding, int strength,
+ int filter_weight) {
+ int mod = sum_dist * 3 / index;
+ mod += rounding;
+ mod >>= strength;
+
+ mod = VPXMIN(16, mod);
+
+ mod = 16 - mod;
+ mod *= filter_weight;
+
+ return mod;
+}
+
+template <>
+int GetModIndex<uint8_t>(int sum_dist, int index, int rounding, int strength,
+ int filter_weight) {
+ unsigned int index_mult[14] = { 0, 0, 0, 0, 49152,
+ 39322, 32768, 28087, 24576, 21846,
+ 19661, 17874, 0, 15124 };
+
+ assert(index >= 0 && index <= 13);
+ assert(index_mult[index] != 0);
+
+ int mod = (clamp(sum_dist, 0, UINT16_MAX) * index_mult[index]) >> 16;
+ mod += rounding;
+ mod >>= strength;
+
+ mod = VPXMIN(16, mod);
+
+ mod = 16 - mod;
+ mod *= filter_weight;
+
+ return mod;
+}
+
+template <>
+int GetModIndex<uint16_t>(int sum_dist, int index, int rounding, int strength,
+ int filter_weight) {
+ int64_t index_mult[14] = { 0U, 0U, 0U, 0U,
+ 3221225472U, 2576980378U, 2147483648U, 1840700270U,
+ 1610612736U, 1431655766U, 1288490189U, 1171354718U,
+ 0U, 991146300U };
+
+ assert(index >= 0 && index <= 13);
+ assert(index_mult[index] != 0);
+
+ int mod = static_cast<int>((sum_dist * index_mult[index]) >> 32);
+ mod += rounding;
+ mod >>= strength;
+
+ mod = VPXMIN(16, mod);
+
+ mod = 16 - mod;
+ mod *= filter_weight;
+
+ return mod;
+}
+
+template <typename PixelType>
+void ApplyReferenceFilter(
+ const Buffer<PixelType> &y_src, const Buffer<PixelType> &y_pre,
+ const Buffer<PixelType> &u_src, const Buffer<PixelType> &v_src,
+ const Buffer<PixelType> &u_pre, const Buffer<PixelType> &v_pre,
+ unsigned int block_width, unsigned int block_height, int ss_x, int ss_y,
+ int strength, const int *const blk_fw, int use_32x32,
+ Buffer<uint32_t> *y_accumulator, Buffer<uint16_t> *y_counter,
+ Buffer<uint32_t> *u_accumulator, Buffer<uint16_t> *u_counter,
+ Buffer<uint32_t> *v_accumulator, Buffer<uint16_t> *v_counter) {
+ const PixelType *y_src_ptr = y_src.TopLeftPixel();
+ const PixelType *y_pre_ptr = y_pre.TopLeftPixel();
+ const PixelType *u_src_ptr = u_src.TopLeftPixel();
+ const PixelType *u_pre_ptr = u_pre.TopLeftPixel();
+ const PixelType *v_src_ptr = v_src.TopLeftPixel();
+ const PixelType *v_pre_ptr = v_pre.TopLeftPixel();
+
+ const int uv_block_width = block_width >> ss_x,
+ uv_block_height = block_height >> ss_y;
+ const int y_src_stride = y_src.stride(), y_pre_stride = y_pre.stride();
+ const int uv_src_stride = u_src.stride(), uv_pre_stride = u_pre.stride();
+ const int y_diff_stride = block_width, uv_diff_stride = uv_block_width;
+
+ Buffer<int> y_dif = Buffer<int>(block_width, block_height, 0);
+ Buffer<int> u_dif = Buffer<int>(uv_block_width, uv_block_height, 0);
+ Buffer<int> v_dif = Buffer<int>(uv_block_width, uv_block_height, 0);
+
+ ASSERT_TRUE(y_dif.Init());
+ ASSERT_TRUE(u_dif.Init());
+ ASSERT_TRUE(v_dif.Init());
+ y_dif.Set(0);
+ u_dif.Set(0);
+ v_dif.Set(0);
+
+ int *y_diff_ptr = y_dif.TopLeftPixel();
+ int *u_diff_ptr = u_dif.TopLeftPixel();
+ int *v_diff_ptr = v_dif.TopLeftPixel();
+
+ uint32_t *y_accum = y_accumulator->TopLeftPixel();
+ uint32_t *u_accum = u_accumulator->TopLeftPixel();
+ uint32_t *v_accum = v_accumulator->TopLeftPixel();
+ uint16_t *y_count = y_counter->TopLeftPixel();
+ uint16_t *u_count = u_counter->TopLeftPixel();
+ uint16_t *v_count = v_counter->TopLeftPixel();
+
+ const int y_accum_stride = y_accumulator->stride();
+ const int u_accum_stride = u_accumulator->stride();
+ const int v_accum_stride = v_accumulator->stride();
+ const int y_count_stride = y_counter->stride();
+ const int u_count_stride = u_counter->stride();
+ const int v_count_stride = v_counter->stride();
+
+ const int rounding = (1 << strength) >> 1;
+
+ // Get the square diffs
+ for (int row = 0; row < static_cast<int>(block_height); row++) {
+ for (int col = 0; col < static_cast<int>(block_width); col++) {
+ const int diff = y_src_ptr[row * y_src_stride + col] -
+ y_pre_ptr[row * y_pre_stride + col];
+ y_diff_ptr[row * y_diff_stride + col] = diff * diff;
+ }
+ }
+
+ for (int row = 0; row < uv_block_height; row++) {
+ for (int col = 0; col < uv_block_width; col++) {
+ const int u_diff = u_src_ptr[row * uv_src_stride + col] -
+ u_pre_ptr[row * uv_pre_stride + col];
+ const int v_diff = v_src_ptr[row * uv_src_stride + col] -
+ v_pre_ptr[row * uv_pre_stride + col];
+ u_diff_ptr[row * uv_diff_stride + col] = u_diff * u_diff;
+ v_diff_ptr[row * uv_diff_stride + col] = v_diff * v_diff;
+ }
+ }
+
+ // Apply the filter to luma
+ for (int row = 0; row < static_cast<int>(block_height); row++) {
+ for (int col = 0; col < static_cast<int>(block_width); col++) {
+ const int uv_row = row >> ss_y;
+ const int uv_col = col >> ss_x;
+ const int filter_weight = GetFilterWeight(row, col, block_height,
+ block_width, blk_fw, use_32x32);
+
+ // First we get the modifier for the current y pixel
+ const int y_pixel = y_pre_ptr[row * y_pre_stride + col];
+ int y_num_used = 0;
+ int y_mod = 0;
+
+ // Sum the neighboring 3x3 y pixels
+ for (int row_step = -1; row_step <= 1; row_step++) {
+ for (int col_step = -1; col_step <= 1; col_step++) {
+ const int sub_row = row + row_step;
+ const int sub_col = col + col_step;
+
+ if (sub_row >= 0 && sub_row < static_cast<int>(block_height) &&
+ sub_col >= 0 && sub_col < static_cast<int>(block_width)) {
+ y_mod += y_diff_ptr[sub_row * y_diff_stride + sub_col];
+ y_num_used++;
+ }
+ }
+ }
+
+ // Sum the corresponding uv pixels to the current y modifier
+ // Note we are rounding down instead of rounding to the nearest pixel.
+ y_mod += u_diff_ptr[uv_row * uv_diff_stride + uv_col];
+ y_mod += v_diff_ptr[uv_row * uv_diff_stride + uv_col];
+
+ y_num_used += 2;
+
+ // Set the modifier
+ y_mod = GetModIndex<PixelType>(y_mod, y_num_used, rounding, strength,
+ filter_weight);
+
+ // Accumulate the result
+ y_count[row * y_count_stride + col] += y_mod;
+ y_accum[row * y_accum_stride + col] += y_mod * y_pixel;
+ }
+ }
+
+ // Apply the filter to chroma
+ for (int uv_row = 0; uv_row < uv_block_height; uv_row++) {
+ for (int uv_col = 0; uv_col < uv_block_width; uv_col++) {
+ const int y_row = uv_row << ss_y;
+ const int y_col = uv_col << ss_x;
+ const int filter_weight = GetFilterWeight(
+ uv_row, uv_col, uv_block_height, uv_block_width, blk_fw, use_32x32);
+
+ const int u_pixel = u_pre_ptr[uv_row * uv_pre_stride + uv_col];
+ const int v_pixel = v_pre_ptr[uv_row * uv_pre_stride + uv_col];
+
+ int uv_num_used = 0;
+ int u_mod = 0, v_mod = 0;
+
+ // Sum the neighboring 3x3 chromal pixels to the chroma modifier
+ for (int row_step = -1; row_step <= 1; row_step++) {
+ for (int col_step = -1; col_step <= 1; col_step++) {
+ const int sub_row = uv_row + row_step;
+ const int sub_col = uv_col + col_step;
+
+ if (sub_row >= 0 && sub_row < uv_block_height && sub_col >= 0 &&
+ sub_col < uv_block_width) {
+ u_mod += u_diff_ptr[sub_row * uv_diff_stride + sub_col];
+ v_mod += v_diff_ptr[sub_row * uv_diff_stride + sub_col];
+ uv_num_used++;
+ }
+ }
+ }
+
+ // Sum all the luma pixels associated with the current luma pixel
+ for (int row_step = 0; row_step < 1 + ss_y; row_step++) {
+ for (int col_step = 0; col_step < 1 + ss_x; col_step++) {
+ const int sub_row = y_row + row_step;
+ const int sub_col = y_col + col_step;
+ const int y_diff = y_diff_ptr[sub_row * y_diff_stride + sub_col];
+
+ u_mod += y_diff;
+ v_mod += y_diff;
+ uv_num_used++;
+ }
+ }
+
+ // Set the modifier
+ u_mod = GetModIndex<PixelType>(u_mod, uv_num_used, rounding, strength,
+ filter_weight);
+ v_mod = GetModIndex<PixelType>(v_mod, uv_num_used, rounding, strength,
+ filter_weight);
+
+ // Accumulate the result
+ u_count[uv_row * u_count_stride + uv_col] += u_mod;
+ u_accum[uv_row * u_accum_stride + uv_col] += u_mod * u_pixel;
+ v_count[uv_row * v_count_stride + uv_col] += v_mod;
+ v_accum[uv_row * v_accum_stride + uv_col] += v_mod * v_pixel;
+ }
+ }
+}
+
+class YUVTemporalFilterTest
+ : public ::testing::TestWithParam<TemporalFilterWithBd> {
+ public:
+ virtual void SetUp() {
+ filter_func_ = GetParam().temporal_filter;
+ bd_ = GetParam().bd;
+ use_highbd_ = (bd_ != 8);
+
+ rnd_.Reset(ACMRandom::DeterministicSeed());
+ saturate_test_ = 0;
+ num_repeats_ = 10;
+
+ ASSERT_TRUE(bd_ == 8 || bd_ == 10 || bd_ == 12);
+ }
+
+ protected:
+ template <typename PixelType>
+ void CompareTestWithParam(int width, int height, int ss_x, int ss_y,
+ int filter_strength, int use_32x32,
+ const int *filter_weight);
+ template <typename PixelType>
+ void RunTestFilterWithParam(int width, int height, int ss_x, int ss_y,
+ int filter_strength, int use_32x32,
+ const int *filter_weight);
+ YUVTemporalFilterFunc filter_func_;
+ ACMRandom rnd_;
+ int saturate_test_;
+ int num_repeats_;
+ int use_highbd_;
+ int bd_;
+};
+
+template <typename PixelType>
+void YUVTemporalFilterTest::CompareTestWithParam(int width, int height,
+ int ss_x, int ss_y,
+ int filter_strength,
+ int use_32x32,
+ const int *filter_weight) {
+ const int uv_width = width >> ss_x, uv_height = height >> ss_y;
+
+ Buffer<PixelType> y_src = Buffer<PixelType>(width, height, 0);
+ Buffer<PixelType> y_pre = Buffer<PixelType>(width, height, 0);
+ Buffer<uint16_t> y_count_ref = Buffer<uint16_t>(width, height, 0);
+ Buffer<uint32_t> y_accum_ref = Buffer<uint32_t>(width, height, 0);
+ Buffer<uint16_t> y_count_tst = Buffer<uint16_t>(width, height, 0);
+ Buffer<uint32_t> y_accum_tst = Buffer<uint32_t>(width, height, 0);
+
+ Buffer<PixelType> u_src = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<PixelType> u_pre = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<uint16_t> u_count_ref = Buffer<uint16_t>(uv_width, uv_height, 0);
+ Buffer<uint32_t> u_accum_ref = Buffer<uint32_t>(uv_width, uv_height, 0);
+ Buffer<uint16_t> u_count_tst = Buffer<uint16_t>(uv_width, uv_height, 0);
+ Buffer<uint32_t> u_accum_tst = Buffer<uint32_t>(uv_width, uv_height, 0);
+
+ Buffer<PixelType> v_src = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<PixelType> v_pre = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<uint16_t> v_count_ref = Buffer<uint16_t>(uv_width, uv_height, 0);
+ Buffer<uint32_t> v_accum_ref = Buffer<uint32_t>(uv_width, uv_height, 0);
+ Buffer<uint16_t> v_count_tst = Buffer<uint16_t>(uv_width, uv_height, 0);
+ Buffer<uint32_t> v_accum_tst = Buffer<uint32_t>(uv_width, uv_height, 0);
+
+ ASSERT_TRUE(y_src.Init());
+ ASSERT_TRUE(y_pre.Init());
+ ASSERT_TRUE(y_count_ref.Init());
+ ASSERT_TRUE(y_accum_ref.Init());
+ ASSERT_TRUE(y_count_tst.Init());
+ ASSERT_TRUE(y_accum_tst.Init());
+ ASSERT_TRUE(u_src.Init());
+ ASSERT_TRUE(u_pre.Init());
+ ASSERT_TRUE(u_count_ref.Init());
+ ASSERT_TRUE(u_accum_ref.Init());
+ ASSERT_TRUE(u_count_tst.Init());
+ ASSERT_TRUE(u_accum_tst.Init());
+
+ ASSERT_TRUE(v_src.Init());
+ ASSERT_TRUE(v_pre.Init());
+ ASSERT_TRUE(v_count_ref.Init());
+ ASSERT_TRUE(v_accum_ref.Init());
+ ASSERT_TRUE(v_count_tst.Init());
+ ASSERT_TRUE(v_accum_tst.Init());
+
+ y_accum_ref.Set(0);
+ y_accum_tst.Set(0);
+ y_count_ref.Set(0);
+ y_count_tst.Set(0);
+ u_accum_ref.Set(0);
+ u_accum_tst.Set(0);
+ u_count_ref.Set(0);
+ u_count_tst.Set(0);
+ v_accum_ref.Set(0);
+ v_accum_tst.Set(0);
+ v_count_ref.Set(0);
+ v_count_tst.Set(0);
+
+ for (int repeats = 0; repeats < num_repeats_; repeats++) {
+ if (saturate_test_) {
+ const int max_val = (1 << bd_) - 1;
+ y_src.Set(max_val);
+ y_pre.Set(0);
+ u_src.Set(max_val);
+ u_pre.Set(0);
+ v_src.Set(max_val);
+ v_pre.Set(0);
+ } else {
+ y_src.Set(&rnd_, 0, 7 << (bd_ - 8));
+ y_pre.Set(&rnd_, 0, 7 << (bd_ - 8));
+ u_src.Set(&rnd_, 0, 7 << (bd_ - 8));
+ u_pre.Set(&rnd_, 0, 7 << (bd_ - 8));
+ v_src.Set(&rnd_, 0, 7 << (bd_ - 8));
+ v_pre.Set(&rnd_, 0, 7 << (bd_ - 8));
+ }
+
+ ApplyReferenceFilter<PixelType>(
+ y_src, y_pre, u_src, v_src, u_pre, v_pre, width, height, ss_x, ss_y,
+ filter_strength, filter_weight, use_32x32, &y_accum_ref, &y_count_ref,
+ &u_accum_ref, &u_count_ref, &v_accum_ref, &v_count_ref);
+
+ ASM_REGISTER_STATE_CHECK(filter_func_(
+ reinterpret_cast<const uint8_t *>(y_src.TopLeftPixel()), y_src.stride(),
+ reinterpret_cast<const uint8_t *>(y_pre.TopLeftPixel()), y_pre.stride(),
+ reinterpret_cast<const uint8_t *>(u_src.TopLeftPixel()),
+ reinterpret_cast<const uint8_t *>(v_src.TopLeftPixel()), u_src.stride(),
+ reinterpret_cast<const uint8_t *>(u_pre.TopLeftPixel()),
+ reinterpret_cast<const uint8_t *>(v_pre.TopLeftPixel()), u_pre.stride(),
+ width, height, ss_x, ss_y, filter_strength, filter_weight, use_32x32,
+ y_accum_tst.TopLeftPixel(), y_count_tst.TopLeftPixel(),
+ u_accum_tst.TopLeftPixel(), u_count_tst.TopLeftPixel(),
+ v_accum_tst.TopLeftPixel(), v_count_tst.TopLeftPixel()));
+
+ EXPECT_TRUE(y_accum_tst.CheckValues(y_accum_ref));
+ EXPECT_TRUE(y_count_tst.CheckValues(y_count_ref));
+ EXPECT_TRUE(u_accum_tst.CheckValues(u_accum_ref));
+ EXPECT_TRUE(u_count_tst.CheckValues(u_count_ref));
+ EXPECT_TRUE(v_accum_tst.CheckValues(v_accum_ref));
+ EXPECT_TRUE(v_count_tst.CheckValues(v_count_ref));
+
+ if (HasFailure()) {
+ if (use_32x32) {
+ printf("SS_X: %d, SS_Y: %d, Strength: %d, Weight: %d\n", ss_x, ss_y,
+ filter_strength, *filter_weight);
+ } else {
+ printf("SS_X: %d, SS_Y: %d, Strength: %d, Weights: %d,%d,%d,%d\n", ss_x,
+ ss_y, filter_strength, filter_weight[0], filter_weight[1],
+ filter_weight[2], filter_weight[3]);
+ }
+ y_accum_tst.PrintDifference(y_accum_ref);
+ y_count_tst.PrintDifference(y_count_ref);
+ u_accum_tst.PrintDifference(u_accum_ref);
+ u_count_tst.PrintDifference(u_count_ref);
+ v_accum_tst.PrintDifference(v_accum_ref);
+ v_count_tst.PrintDifference(v_count_ref);
+
+ return;
+ }
+ }
+}
+
+template <typename PixelType>
+void YUVTemporalFilterTest::RunTestFilterWithParam(int width, int height,
+ int ss_x, int ss_y,
+ int filter_strength,
+ int use_32x32,
+ const int *filter_weight) {
+ const int uv_width = width >> ss_x, uv_height = height >> ss_y;
+
+ Buffer<PixelType> y_src = Buffer<PixelType>(width, height, 0);
+ Buffer<PixelType> y_pre = Buffer<PixelType>(width, height, 0);
+ Buffer<uint16_t> y_count = Buffer<uint16_t>(width, height, 0);
+ Buffer<uint32_t> y_accum = Buffer<uint32_t>(width, height, 0);
+
+ Buffer<PixelType> u_src = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<PixelType> u_pre = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<uint16_t> u_count = Buffer<uint16_t>(uv_width, uv_height, 0);
+ Buffer<uint32_t> u_accum = Buffer<uint32_t>(uv_width, uv_height, 0);
+
+ Buffer<PixelType> v_src = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<PixelType> v_pre = Buffer<PixelType>(uv_width, uv_height, 0);
+ Buffer<uint16_t> v_count = Buffer<uint16_t>(uv_width, uv_height, 0);
+ Buffer<uint32_t> v_accum = Buffer<uint32_t>(uv_width, uv_height, 0);
+
+ ASSERT_TRUE(y_src.Init());
+ ASSERT_TRUE(y_pre.Init());
+ ASSERT_TRUE(y_count.Init());
+ ASSERT_TRUE(y_accum.Init());
+
+ ASSERT_TRUE(u_src.Init());
+ ASSERT_TRUE(u_pre.Init());
+ ASSERT_TRUE(u_count.Init());
+ ASSERT_TRUE(u_accum.Init());
+
+ ASSERT_TRUE(v_src.Init());
+ ASSERT_TRUE(v_pre.Init());
+ ASSERT_TRUE(v_count.Init());
+ ASSERT_TRUE(v_accum.Init());
+
+ y_accum.Set(0);
+ y_count.Set(0);
+
+ u_accum.Set(0);
+ u_count.Set(0);
+
+ v_accum.Set(0);
+ v_count.Set(0);
+
+ y_src.Set(&rnd_, 0, 7 << (bd_ - 8));
+ y_pre.Set(&rnd_, 0, 7 << (bd_ - 8));
+ u_src.Set(&rnd_, 0, 7 << (bd_ - 8));
+ u_pre.Set(&rnd_, 0, 7 << (bd_ - 8));
+ v_src.Set(&rnd_, 0, 7 << (bd_ - 8));
+ v_pre.Set(&rnd_, 0, 7 << (bd_ - 8));
+
+ for (int repeats = 0; repeats < num_repeats_; repeats++) {
+ ASM_REGISTER_STATE_CHECK(filter_func_(
+ reinterpret_cast<const uint8_t *>(y_src.TopLeftPixel()), y_src.stride(),
+ reinterpret_cast<const uint8_t *>(y_pre.TopLeftPixel()), y_pre.stride(),
+ reinterpret_cast<const uint8_t *>(u_src.TopLeftPixel()),
+ reinterpret_cast<const uint8_t *>(v_src.TopLeftPixel()), u_src.stride(),
+ reinterpret_cast<const uint8_t *>(u_pre.TopLeftPixel()),
+ reinterpret_cast<const uint8_t *>(v_pre.TopLeftPixel()), u_pre.stride(),
+ width, height, ss_x, ss_y, filter_strength, filter_weight, use_32x32,
+ y_accum.TopLeftPixel(), y_count.TopLeftPixel(), u_accum.TopLeftPixel(),
+ u_count.TopLeftPixel(), v_accum.TopLeftPixel(),
+ v_count.TopLeftPixel()));
+ }
+}
+
+TEST_P(YUVTemporalFilterTest, Use32x32) {
+ const int width = 32, height = 32;
+ const int use_32x32 = 1;
+
+ for (int ss_x = 0; ss_x <= 1; ss_x++) {
+ for (int ss_y = 0; ss_y <= 1; ss_y++) {
+ for (int filter_strength = 0; filter_strength <= 6;
+ filter_strength += 2) {
+ for (int filter_weight = 0; filter_weight <= 2; filter_weight++) {
+ if (use_highbd_) {
+ const int adjusted_strength = filter_strength + 2 * (bd_ - 8);
+ CompareTestWithParam<uint16_t>(width, height, ss_x, ss_y,
+ adjusted_strength, use_32x32,
+ &filter_weight);
+ } else {
+ CompareTestWithParam<uint8_t>(width, height, ss_x, ss_y,
+ filter_strength, use_32x32,
+ &filter_weight);
+ }
+ ASSERT_FALSE(HasFailure());
+ }
+ }
+ }
+ }
+}
+
+TEST_P(YUVTemporalFilterTest, Use16x16) {
+ const int width = 32, height = 32;
+ const int use_32x32 = 0;
+
+ for (int ss_x = 0; ss_x <= 1; ss_x++) {
+ for (int ss_y = 0; ss_y <= 1; ss_y++) {
+ for (int filter_idx = 0; filter_idx < 3 * 3 * 3 * 3; filter_idx++) {
+ // Set up the filter
+ int filter_weight[4];
+ int filter_idx_cp = filter_idx;
+ for (int idx = 0; idx < 4; idx++) {
+ filter_weight[idx] = filter_idx_cp % 3;
+ filter_idx_cp /= 3;
+ }
+
+ // Test each parameter
+ for (int filter_strength = 0; filter_strength <= 6;
+ filter_strength += 2) {
+ if (use_highbd_) {
+ const int adjusted_strength = filter_strength + 2 * (bd_ - 8);
+ CompareTestWithParam<uint16_t>(width, height, ss_x, ss_y,
+ adjusted_strength, use_32x32,
+ filter_weight);
+ } else {
+ CompareTestWithParam<uint8_t>(width, height, ss_x, ss_y,
+ filter_strength, use_32x32,
+ filter_weight);
+ }
+
+ ASSERT_FALSE(HasFailure());
+ }
+ }
+ }
+ }
+}
+
+TEST_P(YUVTemporalFilterTest, SaturationTest) {
+ const int width = 32, height = 32;
+ const int use_32x32 = 1;
+ const int filter_weight = 1;
+ saturate_test_ = 1;
+
+ for (int ss_x = 0; ss_x <= 1; ss_x++) {
+ for (int ss_y = 0; ss_y <= 1; ss_y++) {
+ for (int filter_strength = 0; filter_strength <= 6;
+ filter_strength += 2) {
+ if (use_highbd_) {
+ const int adjusted_strength = filter_strength + 2 * (bd_ - 8);
+ CompareTestWithParam<uint16_t>(width, height, ss_x, ss_y,
+ adjusted_strength, use_32x32,
+ &filter_weight);
+ } else {
+ CompareTestWithParam<uint8_t>(width, height, ss_x, ss_y,
+ filter_strength, use_32x32,
+ &filter_weight);
+ }
+
+ ASSERT_FALSE(HasFailure());
+ }
+ }
+ }
+}
+
+TEST_P(YUVTemporalFilterTest, DISABLED_Speed) {
+ const int width = 32, height = 32;
+ num_repeats_ = 1000;
+
+ for (int use_32x32 = 0; use_32x32 <= 1; use_32x32++) {
+ const int num_filter_weights = use_32x32 ? 3 : 3 * 3 * 3 * 3;
+ for (int ss_x = 0; ss_x <= 1; ss_x++) {
+ for (int ss_y = 0; ss_y <= 1; ss_y++) {
+ for (int filter_idx = 0; filter_idx < num_filter_weights;
+ filter_idx++) {
+ // Set up the filter
+ int filter_weight[4];
+ int filter_idx_cp = filter_idx;
+ for (int idx = 0; idx < 4; idx++) {
+ filter_weight[idx] = filter_idx_cp % 3;
+ filter_idx_cp /= 3;
+ }
+
+ // Test each parameter
+ for (int filter_strength = 0; filter_strength <= 6;
+ filter_strength += 2) {
+ vpx_usec_timer timer;
+ vpx_usec_timer_start(&timer);
+
+ if (use_highbd_) {
+ RunTestFilterWithParam<uint16_t>(width, height, ss_x, ss_y,
+ filter_strength, use_32x32,
+ filter_weight);
+ } else {
+ RunTestFilterWithParam<uint8_t>(width, height, ss_x, ss_y,
+ filter_strength, use_32x32,
+ filter_weight);
+ }
+
+ vpx_usec_timer_mark(&timer);
+ const int elapsed_time =
+ static_cast<int>(vpx_usec_timer_elapsed(&timer));
+
+ printf(
+ "Bitdepth: %d, Use 32X32: %d, SS_X: %d, SS_Y: %d, Weight Idx: "
+ "%d, Strength: %d, Time: %5d\n",
+ bd_, use_32x32, ss_x, ss_y, filter_idx, filter_strength,
+ elapsed_time);
+ }
+ }
+ }
+ }
+ }
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+#define WRAP_HIGHBD_FUNC(func, bd) \
+ void wrap_##func##_##bd( \
+ const uint8_t *y_src, int y_src_stride, const uint8_t *y_pre, \
+ int y_pre_stride, const uint8_t *u_src, const uint8_t *v_src, \
+ int uv_src_stride, const uint8_t *u_pre, const uint8_t *v_pre, \
+ int uv_pre_stride, unsigned int block_width, unsigned int block_height, \
+ int ss_x, int ss_y, int strength, const int *const blk_fw, \
+ int use_32x32, uint32_t *y_accumulator, uint16_t *y_count, \
+ uint32_t *u_accumulator, uint16_t *u_count, uint32_t *v_accumulator, \
+ uint16_t *v_count) { \
+ func(reinterpret_cast<const uint16_t *>(y_src), y_src_stride, \
+ reinterpret_cast<const uint16_t *>(y_pre), y_pre_stride, \
+ reinterpret_cast<const uint16_t *>(u_src), \
+ reinterpret_cast<const uint16_t *>(v_src), uv_src_stride, \
+ reinterpret_cast<const uint16_t *>(u_pre), \
+ reinterpret_cast<const uint16_t *>(v_pre), uv_pre_stride, \
+ block_width, block_height, ss_x, ss_y, strength, blk_fw, use_32x32, \
+ y_accumulator, y_count, u_accumulator, u_count, v_accumulator, \
+ v_count); \
+ }
+
+WRAP_HIGHBD_FUNC(vp9_highbd_apply_temporal_filter_c, 10)
+WRAP_HIGHBD_FUNC(vp9_highbd_apply_temporal_filter_c, 12)
+
+INSTANTIATE_TEST_SUITE_P(
+ C, YUVTemporalFilterTest,
+ ::testing::Values(
+ TemporalFilterWithBd(&wrap_vp9_highbd_apply_temporal_filter_c_10, 10),
+ TemporalFilterWithBd(&wrap_vp9_highbd_apply_temporal_filter_c_12, 12)));
+#if HAVE_SSE4_1
+WRAP_HIGHBD_FUNC(vp9_highbd_apply_temporal_filter_sse4_1, 10)
+WRAP_HIGHBD_FUNC(vp9_highbd_apply_temporal_filter_sse4_1, 12)
+
+INSTANTIATE_TEST_SUITE_P(
+ SSE4_1, YUVTemporalFilterTest,
+ ::testing::Values(
+ TemporalFilterWithBd(&wrap_vp9_highbd_apply_temporal_filter_sse4_1_10,
+ 10),
+ TemporalFilterWithBd(&wrap_vp9_highbd_apply_temporal_filter_sse4_1_12,
+ 12)));
+#endif // HAVE_SSE4_1
+#if HAVE_NEON
+WRAP_HIGHBD_FUNC(vp9_highbd_apply_temporal_filter_neon, 10)
+WRAP_HIGHBD_FUNC(vp9_highbd_apply_temporal_filter_neon, 12)
+
+INSTANTIATE_TEST_SUITE_P(
+ NEON, YUVTemporalFilterTest,
+ ::testing::Values(
+ TemporalFilterWithBd(&wrap_vp9_highbd_apply_temporal_filter_neon_10,
+ 10),
+ TemporalFilterWithBd(&wrap_vp9_highbd_apply_temporal_filter_neon_12,
+ 12)));
+#endif // HAVE_NEON
+#else
+INSTANTIATE_TEST_SUITE_P(
+ C, YUVTemporalFilterTest,
+ ::testing::Values(TemporalFilterWithBd(&vp9_apply_temporal_filter_c, 8)));
+
+#if HAVE_SSE4_1
+INSTANTIATE_TEST_SUITE_P(SSE4_1, YUVTemporalFilterTest,
+ ::testing::Values(TemporalFilterWithBd(
+ &vp9_apply_temporal_filter_sse4_1, 8)));
+#endif // HAVE_SSE4_1
+#if HAVE_NEON
+INSTANTIATE_TEST_SUITE_P(NEON, YUVTemporalFilterTest,
+ ::testing::Values(TemporalFilterWithBd(
+ &vp9_apply_temporal_filter_neon, 8)));
+#endif // HAVE_NEON
+#endif // CONFIG_VP9_HIGHBITDEPTH
+
+} // namespace
diff --git a/media/libvpx/libvpx/test/yuv_video_source.h b/media/libvpx/libvpx/test/yuv_video_source.h
new file mode 100644
index 0000000000..51948c0efb
--- /dev/null
+++ b/media/libvpx/libvpx/test/yuv_video_source.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef VPX_TEST_YUV_VIDEO_SOURCE_H_
+#define VPX_TEST_YUV_VIDEO_SOURCE_H_
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include "test/video_source.h"
+#include "vpx/vpx_image.h"
+
+namespace libvpx_test {
+
+// This class extends VideoSource to allow parsing of raw YUV
+// formats of various color sampling and bit-depths so that we can
+// do actual file encodes.
+class YUVVideoSource : public VideoSource {
+ public:
+ YUVVideoSource(const std::string &file_name, vpx_img_fmt format,
+ unsigned int width, unsigned int height, int rate_numerator,
+ int rate_denominator, unsigned int start, int limit)
+ : file_name_(file_name), input_file_(nullptr), img_(nullptr),
+ start_(start), limit_(limit), frame_(0), width_(0), height_(0),
+ format_(VPX_IMG_FMT_NONE), framerate_numerator_(rate_numerator),
+ framerate_denominator_(rate_denominator) {
+ // This initializes format_, raw_size_, width_, height_ and allocates img.
+ SetSize(width, height, format);
+ }
+
+ virtual ~YUVVideoSource() {
+ vpx_img_free(img_);
+ if (input_file_) fclose(input_file_);
+ }
+
+ virtual void Begin() {
+ if (input_file_) fclose(input_file_);
+ input_file_ = OpenTestDataFile(file_name_);
+ ASSERT_NE(input_file_, nullptr)
+ << "Input file open failed. Filename: " << file_name_;
+ if (start_) {
+ fseek(input_file_, static_cast<unsigned>(raw_size_) * start_, SEEK_SET);
+ }
+
+ frame_ = start_;
+ FillFrame();
+ }
+
+ virtual void Next() {
+ ++frame_;
+ FillFrame();
+ }
+
+ virtual vpx_image_t *img() const {
+ return (frame_ < limit_) ? img_ : nullptr;
+ }
+
+ // 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 = { framerate_denominator_, framerate_numerator_ };
+ return t;
+ }
+
+ virtual unsigned int frame() const { return frame_; }
+
+ virtual unsigned int limit() const { return limit_; }
+
+ virtual void SetSize(unsigned int width, unsigned int height,
+ vpx_img_fmt format) {
+ if (width != width_ || height != height_ || format != format_) {
+ vpx_img_free(img_);
+ img_ = vpx_img_alloc(nullptr, format, width, height, 1);
+ ASSERT_NE(img_, nullptr);
+ width_ = width;
+ height_ = height;
+ format_ = format;
+ switch (format) {
+ case VPX_IMG_FMT_NV12:
+ case VPX_IMG_FMT_I420: raw_size_ = width * height * 3 / 2; break;
+ case VPX_IMG_FMT_I422: raw_size_ = width * height * 2; break;
+ case VPX_IMG_FMT_I440: raw_size_ = width * height * 2; break;
+ case VPX_IMG_FMT_I444: raw_size_ = width * height * 3; break;
+ case VPX_IMG_FMT_I42016: raw_size_ = width * height * 3; break;
+ case VPX_IMG_FMT_I42216: raw_size_ = width * height * 4; break;
+ case VPX_IMG_FMT_I44016: raw_size_ = width * height * 4; break;
+ case VPX_IMG_FMT_I44416: raw_size_ = width * height * 6; break;
+ default: ASSERT_TRUE(0);
+ }
+ }
+ }
+
+ virtual void FillFrame() {
+ ASSERT_NE(input_file_, nullptr);
+ // Read a frame from input_file.
+ if (fread(img_->img_data, raw_size_, 1, input_file_) == 0) {
+ limit_ = frame_;
+ }
+ }
+
+ protected:
+ std::string file_name_;
+ FILE *input_file_;
+ vpx_image_t *img_;
+ size_t raw_size_;
+ unsigned int start_;
+ unsigned int limit_;
+ unsigned int frame_;
+ unsigned int width_;
+ unsigned int height_;
+ vpx_img_fmt format_;
+ int framerate_numerator_;
+ int framerate_denominator_;
+};
+
+} // namespace libvpx_test
+
+#endif // VPX_TEST_YUV_VIDEO_SOURCE_H_