(61d00a474) v0.9.7.1

This commit is contained in:
Regalis
2020-03-04 13:04:10 +01:00
parent 3c50efa5c9
commit 3c09ebe02f
5086 changed files with 786063 additions and 295871 deletions
@@ -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(void) {
const uint32_t value =
random_.Generate(testing::internal::Random::kMaxRange);
return (value >> 15) & 0xffff;
}
int32_t Rand20Signed(void) {
// 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(void) {
// Use 16 bits: values between 32767 and -32768.
return static_cast<int16_t>(random_.Generate(65536));
}
int16_t Rand13Signed(void) {
// 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(void) {
// 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(void) {
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(void) {
// 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(void) { return 0xbaba; }
private:
testing::internal::Random random_;
};
} // namespace libvpx_test
#endif // VPX_TEST_ACM_RANDOM_H_
@@ -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_TRUE(previous != NULL);
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_CASE(ActiveMapRefreshTest,
::testing::Values(::libvpx_test::kRealTime),
::testing::Range(5, 6));
} // namespace
@@ -0,0 +1,91 @@
/*
* 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::CodecTestWith2Params<libvpx_test::TestMode, 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_);
} 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 = NULL;
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_CASE(ActiveMapTest,
::testing::Values(::libvpx_test::kRealTime),
::testing::Range(0, 9));
} // namespace
@@ -0,0 +1,150 @@
/*
* 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;
// TODO(jimbankoski): make width and height integers not unsigned.
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_TRUE(s != NULL);
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_TRUE(s != NULL);
ASSERT_TRUE(d != NULL);
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_CASE_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_CASE_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_CASE_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
@@ -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_CASE(AltRefAqSegmentTest,
::testing::Values(::libvpx_test::kOnePassGood,
::libvpx_test::kTwoPassGood),
::testing::Range(2, 5));
} // namespace
@@ -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_CASE(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_CASE(AltRefForcedKeyTestLarge,
::testing::Values(::libvpx_test::kOnePassGood),
::testing::Range(0, 9));
VP9_INSTANTIATE_TEST_CASE(AltRefForcedKeyTestLarge,
::testing::Values(::libvpx_test::kOnePassGood),
::testing::Range(0, 9));
} // namespace
@@ -0,0 +1,57 @@
# 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.
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
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
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)
@@ -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 http://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
@@ -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
@@ -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())
@@ -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_CASE(AqSegmentTest,
::testing::Values(::libvpx_test::kRealTime,
::libvpx_test::kOnePassGood),
::testing::Range(3, 9));
} // namespace
@@ -0,0 +1,737 @@
/*
* 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_(NULL), source_stride_(0),
bit_depth_(8) {}
virtual void TearDown() {
vpx_free(source_data_);
source_data_ = NULL;
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_TRUE(source_data_ != NULL);
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
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_(NULL), hbuf_c_(NULL) {
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_TRUE(source_data_ != NULL);
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_ = NULL;
vpx_free(hbuf_c_);
hbuf_c_ = NULL;
vpx_free(hbuf_asm_);
hbuf_asm_ = NULL;
}
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_;
};
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_;
};
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_TRUE(src_ != NULL);
}
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_TRUE(coeff_ != NULL);
ASSERT_TRUE(dqcoeff_ != NULL);
}
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
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();
}
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_CASE_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_CASE_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_CASE_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
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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)));
// TODO(jianj): Remove the highbitdepth flag once the SIMD functions are
// in place.
#if !CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_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 // !CONFIG_VP9_HIGHBITDEPTH
#endif // HAVE_NEON
#if HAVE_MSA
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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
@@ -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));
}
@@ -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_
@@ -0,0 +1,221 @@
/*
* 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 SetUpTestCase() {
source_data_ = reinterpret_cast<uint8_t *>(
vpx_memalign(kDataAlignment, kDataBufferSize));
reference_data_ = reinterpret_cast<uint8_t *>(
vpx_memalign(kDataAlignment, kDataBufferSize));
}
static void TearDownTestCase() {
vpx_free(source_data_);
source_data_ = NULL;
vpx_free(reference_data_);
reference_data_ = NULL;
}
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_ = NULL;
uint8_t *BlockinessTestBase::reference_data_ = NULL;
#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_CASE_P(C, BlockinessVP9Test, ::testing::ValuesIn(c_vp9_tests));
#endif
} // namespace
@@ -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_CASE(BordersTest,
::testing::Values(::libvpx_test::kTwoPassGood));
} // namespace
@@ -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_(NULL) {}
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_(NULL) {}
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_(NULL) {}
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_(NULL) {}
~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_ != NULL) 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_TRUE(raw_buffer_ != NULL);
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 NULL;
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_
@@ -0,0 +1,184 @@
/*
* 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_(NULL), decoder_(NULL), md5_file_(NULL) {}
virtual void SetUp() {
video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
ASSERT_TRUE(video_ != NULL);
video_->Init();
video_->Begin();
const vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
ASSERT_TRUE(decoder_ != NULL);
OpenMd5File(kVP9Md5File);
}
virtual void TearDown() {
if (md5_file_ != NULL) 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() != NULL; 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()) != NULL) {
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_TRUE(md5_file_ != NULL)
<< "MD5 file open failed. Filename: " << md5_file_name_;
}
void CheckMd5(const vpx_image_t &img) {
ASSERT_TRUE(md5_file_ != NULL);
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_CASE_P(Alignments, ByteAlignmentTest,
::testing::ValuesIn(kBaTestParams));
#endif // CONFIG_WEBM_IO
} // namespace
@@ -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_
@@ -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 NULL;
#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 NULL;
#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 NULL;
#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 NULL;
#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_CASE(test, ...) \
INSTANTIATE_TEST_CASE_P( \
VP8, test, \
::testing::Combine( \
::testing::Values(static_cast<const libvpx_test::CodecFactory *>( \
&libvpx_test::kVP8)), \
__VA_ARGS__))
#else
#define VP8_INSTANTIATE_TEST_CASE(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 NULL;
#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 NULL;
#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 NULL;
#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 NULL;
#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_CASE(test, ...) \
INSTANTIATE_TEST_CASE_P( \
VP9, test, \
::testing::Combine( \
::testing::Values(static_cast<const libvpx_test::CodecFactory *>( \
&libvpx_test::kVP9)), \
__VA_ARGS__))
#else
#define VP9_INSTANTIATE_TEST_CASE(test, ...)
#endif // CONFIG_VP9
} // namespace libvpx_test
#endif // VPX_TEST_CODEC_FACTORY_H_
@@ -0,0 +1,186 @@
/*
* 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;
typedef void (*AvgPredFunc)(uint8_t *a, const uint8_t *b, int w, int h,
const uint8_t *c, int c_stride);
uint8_t avg_with_rounding(uint8_t a, uint8_t b) { return (a + b + 1) >> 1; }
void reference_pred(const Buffer<uint8_t> &pred, const Buffer<uint8_t> &ref,
int width, int height, Buffer<uint8_t> *avg) {
ASSERT_TRUE(avg->TopLeftPixel() != NULL);
ASSERT_TRUE(pred.TopLeftPixel() != NULL);
ASSERT_TRUE(ref.TopLeftPixel() != NULL);
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
avg->TopLeftPixel()[y * avg->stride() + x] =
avg_with_rounding(pred.TopLeftPixel()[y * pred.stride() + x],
ref.TopLeftPixel()[y * ref.stride() + x]);
}
}
}
class AvgPredTest : public ::testing::TestWithParam<AvgPredFunc> {
public:
virtual void SetUp() {
avg_pred_func_ = GetParam();
rnd_.Reset(ACMRandom::DeterministicSeed());
}
protected:
AvgPredFunc avg_pred_func_;
ACMRandom rnd_;
};
TEST_P(AvgPredTest, SizeCombinations) {
// 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<uint8_t> ref =
Buffer<uint8_t>(width, height, ref_padding ? 8 : 0);
ASSERT_TRUE(ref.Init());
Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(pred.Init());
Buffer<uint8_t> avg_ref = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(avg_ref.Init());
Buffer<uint8_t> avg_chk = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(avg_chk.Init());
ref.Set(&rnd_, &ACMRandom::Rand8);
pred.Set(&rnd_, &ACMRandom::Rand8);
reference_pred(pred, ref, width, height, &avg_ref);
ASM_REGISTER_STATE_CHECK(
avg_pred_func_(avg_chk.TopLeftPixel(), pred.TopLeftPixel(), width,
height, 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;
}
}
}
}
}
TEST_P(AvgPredTest, CompareReferenceRandom) {
const int width = 64;
const int height = 32;
Buffer<uint8_t> ref = Buffer<uint8_t>(width, height, 8);
ASSERT_TRUE(ref.Init());
Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(pred.Init());
Buffer<uint8_t> avg_ref = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(avg_ref.Init());
Buffer<uint8_t> avg_chk = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(avg_chk.Init());
for (int i = 0; i < 500; ++i) {
ref.Set(&rnd_, &ACMRandom::Rand8);
pred.Set(&rnd_, &ACMRandom::Rand8);
reference_pred(pred, ref, width, height, &avg_ref);
ASM_REGISTER_STATE_CHECK(avg_pred_func_(avg_chk.TopLeftPixel(),
pred.TopLeftPixel(), width, height,
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;
}
}
}
TEST_P(AvgPredTest, DISABLED_Speed) {
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<uint8_t> ref =
Buffer<uint8_t>(width, height, ref_padding ? 8 : 0);
ASSERT_TRUE(ref.Init());
Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(pred.Init());
Buffer<uint8_t> avg = Buffer<uint8_t>(width, height, 0, 16);
ASSERT_TRUE(avg.Init());
ref.Set(&rnd_, &ACMRandom::Rand8);
pred.Set(&rnd_, &ACMRandom::Rand8);
vpx_usec_timer timer;
vpx_usec_timer_start(&timer);
for (int i = 0; i < 10000000 / (width * height); ++i) {
avg_pred_func_(avg.TopLeftPixel(), pred.TopLeftPixel(), width, height,
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);
}
}
}
}
INSTANTIATE_TEST_CASE_P(C, AvgPredTest,
::testing::Values(&vpx_comp_avg_pred_c));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, AvgPredTest,
::testing::Values(&vpx_comp_avg_pred_sse2));
#endif // HAVE_SSE2
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, AvgPredTest,
::testing::Values(&vpx_comp_avg_pred_neon));
#endif // HAVE_NEON
#if HAVE_VSX
INSTANTIATE_TEST_CASE_P(VSX, AvgPredTest,
::testing::Values(&vpx_comp_avg_pred_vsx));
#endif // HAVE_VSX
} // namespace
@@ -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_CASE(ConfigTest, ONE_PASS_TEST_MODES);
} // namespace
@@ -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 SetUpTestCase() {
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 TearDownTestCase() {
vpx_free(source_data_[0]);
source_data_[0] = NULL;
vpx_free(reference_data_[0]);
reference_data_[0] = NULL;
vpx_free(source_data_[1]);
source_data_[1] = NULL;
vpx_free(reference_data_[1]);
reference_data_[1] = NULL;
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] = { NULL, NULL };
uint8_t *ConsistencyTestBase::reference_data_[2] = { NULL, NULL };
Ssimv *ConsistencyTestBase::ssim_array_ = NULL;
#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_CASE_P(C, ConsistencyVP9Test,
::testing::ValuesIn(c_vp9_tests));
#endif
} // namespace
File diff suppressed because it is too large Load Diff
@@ -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_CASE(CpuSpeedTest,
::testing::Values(::libvpx_test::kTwoPassGood,
::libvpx_test::kOnePassGood,
::libvpx_test::kRealTime),
::testing::Range(0, 10));
} // namespace
@@ -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 SetUpTestCase() { bitrates_.clear(); }
static void TearDownTestCase() {
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_CASE(CQTest, ::testing::Range(kCQLevelMin, kCQLevelMax,
kCQLevelStep));
} // namespace
@@ -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}
[ -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}"
@@ -0,0 +1,868 @@
/*
* 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()
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 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(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 // 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;
}
}
}
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(); }
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_;
};
TEST_P(InvTrans16x16DCT, CompareReference) {
CompareInvReference(ref_txfm_, thresh_);
}
using std::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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)));
#endif // CONFIG_VP9_HIGHBITDEPTH
#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
INSTANTIATE_TEST_CASE_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_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
INSTANTIATE_TEST_CASE_P(
SSE2, Trans16x16DCT,
::testing::Values(make_tuple(&vpx_fdct16x16_sse2,
&vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8)));
INSTANTIATE_TEST_CASE_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)));
#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_P(MSA, Trans16x16DCT,
::testing::Values(make_tuple(&vpx_fdct16x16_msa,
&vpx_idct16x16_256_add_msa,
0, VPX_BITS_8)));
INSTANTIATE_TEST_CASE_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_CASE_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
} // namespace
@@ -0,0 +1,399 @@
/*
* 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 "vpx/vpx_codec.h"
#include "vpx/vpx_integer.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/msvc.h" // for round()
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;
#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;
}
}
}
using std::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_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_CASE_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)));
#endif // CONFIG_VP9_HIGHBITDEPTH
#if HAVE_NEON && !CONFIG_EMULATE_HARDWARE
INSTANTIATE_TEST_CASE_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_CASE_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)));
#endif // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
INSTANTIATE_TEST_CASE_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_CASE_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)));
#endif // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
INSTANTIATE_TEST_CASE_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_CASE_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
} // namespace
@@ -0,0 +1,177 @@
/*
* 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() != NULL) {
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() != NULL) {
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_CASE_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_CASE_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_CASE_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_CASE_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_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_8)));
#else
INSTANTIATE_TEST_CASE_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_CASE_P(MSA, PartialFdctTest,
::testing::Values(make_tuple(&vpx_fdct8x8_1_msa, 8,
VPX_BITS_8)));
#else // !CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_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
@@ -0,0 +1,756 @@
/*
* 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_TRUE(src_ != NULL);
dst_ = reinterpret_cast<uint8_t *>(
vpx_memalign(16, pixel_size_ * block_size_));
ASSERT_TRUE(dst_ != NULL);
}
virtual void TearDown() {
vpx_free(src_);
src_ = NULL;
vpx_free(dst_);
dst_ = NULL;
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_TRUE(test_input_block.TopLeftPixel() != NULL);
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_TRUE(input_extreme_block.TopLeftPixel() != NULL);
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_TRUE(output_block.TopLeftPixel() != NULL);
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());
Buffer<uint8_t> dst = Buffer<uint8_t>(size_, size_, 0, 16);
ASSERT_TRUE(dst.Init());
Buffer<uint8_t> src = Buffer<uint8_t>(size_, size_, 0);
ASSERT_TRUE(src.Init());
Buffer<uint16_t> dst16 = Buffer<uint16_t>(size_, size_, 0, 16);
ASSERT_TRUE(dst16.Init());
Buffer<uint16_t> src16 = Buffer<uint16_t>(size_, size_, 0);
ASSERT_TRUE(src16.Init());
for (int i = 0; i < count_test_block; ++i) {
InitMem();
ASSERT_TRUE(in.TopLeftPixel() != NULL);
// 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_CASE_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_CASE_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_CASE_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_CASE_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
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 }
};
INSTANTIATE_TEST_CASE_P(
NEON, TransDCT,
::testing::Combine(::testing::Range(0, 4),
::testing::Values(dct_neon_func_info),
::testing::Values(0), ::testing::Values(VPX_BITS_8)));
#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_CASE_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_CASE_P(VSX, TransDCT,
::testing::Values(make_tuple(0, &dct_vsx_func_info, 0,
VPX_BITS_8)));
#endif // HAVE_VSX && !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_CASE_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_fht8x8_c, &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 },
#endif
{ &vp9_fht4x4_c, &iht_wrapper<vp9_iht4x4_16_add_neon>, 4, 1 },
{ &vp9_fht8x8_c, &iht_wrapper<vp9_iht8x8_64_add_neon>, 8, 1 },
{ &vp9_fht16x16_c, &iht_wrapper<vp9_iht16x16_256_add_neon>, 16, 1 }
};
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_P(VSX, TransWHT,
::testing::Values(make_tuple(0, &wht_vsx_func_info, 0,
VPX_BITS_8)));
#endif // HAVE_VSX && !CONFIG_EMULATE_HARDWARE
} // namespace
@@ -0,0 +1,208 @@
/*
* 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_INVALID_PARAM, vpx_codec_dec_init(NULL, NULL, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(&dec, NULL, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, NULL, 0, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, buf, 0, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_decode(NULL, buf, NELEMENTS(buf), NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_decode(NULL, NULL, NELEMENTS(buf), NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL));
EXPECT_TRUE(vpx_codec_error(NULL) != NULL);
for (int i = 0; i < NELEMENTS(kCodecs); ++i) {
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_dec_init(NULL, kCodecs[i], NULL, 0));
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, kCodecs[i], NULL, 0));
EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
vpx_codec_decode(&dec, buf, NELEMENTS(buf), NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_decode(&dec, NULL, NELEMENTS(buf), NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(&dec, buf, 0, NULL, 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, NULL,
VPX_CODEC_USE_ERROR_CONCEALMENT));
#else
EXPECT_EQ(VPX_CODEC_INCAPABLE,
vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL,
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], NULL));
}
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, NULL));
vpx_ref_frame_t ref_copy;
const int width = 352;
const int height = 288;
ASSERT_TRUE(
vpx_img_alloc(&ref_copy.img, VPX_IMG_FMT_I420, width, height, 1) != NULL);
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, NULL));
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, NULL, 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, NULL, 0));
#else
EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0));
#endif
vpx_codec_iter_t iter = NULL;
EXPECT_EQ(NULL, 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, NULL, 0));
EXPECT_EQ((data_sz < peek_size) ? VPX_CODEC_UNSUP_BITSTREAM
: VPX_CODEC_CORRUPT_FRAME,
vpx_codec_decode(&dec, data, data_sz, NULL, 0));
vpx_codec_iter_t iter = NULL;
EXPECT_EQ(NULL, 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
@@ -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_CASE_P(
VP9, DecodeCorruptedFrameTest,
::testing::Values(
static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
#endif // CONFIG_VP9
#if CONFIG_VP8
INSTANTIATE_TEST_CASE_P(
VP8, DecodeCorruptedFrameTest,
::testing::Values(
static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP8)));
#endif // CONFIG_VP8
} // namespace
@@ -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() != NULL; 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_CASE_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_TRUE(outfile_ != NULL);
}
virtual void EndPassHook() {
if (outfile_ != NULL) {
if (!fseek(outfile_, 0, SEEK_SET)) {
ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
}
fclose(outfile_);
outfile_ = NULL;
}
}
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() != NULL;
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_CASE(VP9NewEncodeDecodePerfTest,
::testing::Values(::libvpx_test::kTwoPassGood));
} // namespace
@@ -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_TRUE(video.get() != NULL);
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_TRUE(video.get() != NULL);
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_TRUE(video.get() != NULL);
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_TRUE(video.get() != NULL);
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_CASE(
DecodeSvcTest, ::testing::ValuesIn(libvpx_test::kVP9TestVectorsSvc,
libvpx_test::kVP9TestVectorsSvc +
libvpx_test::kNumVP9TestVectorsSvc));
} // namespace
@@ -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, NULL);
}
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_TRUE(decoder != NULL);
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() != NULL) {
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(NULL, 0);
ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
end_of_file = true;
}
DxDataIterator dec_iter = decoder->GetDxData();
const vpx_image_t *img = NULL;
// 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
@@ -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_(NULL) {}
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_
@@ -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}
[ -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}"
@@ -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}
[ -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"
# Test pattern mode: Drop 3 of every 4 frames.
decode_with_drops "${VP8_IVF_FILE}" "vp8" "3/4"
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"
# Test pattern mode: Drop 3 of every 4 frames.
decode_with_drops "${VP9_IVF_FILE}" "vp9" "3/4"
fi
}
decode_with_drops_tests="decode_with_drops_vp8
decode_with_drops_vp9"
run_tests decode_with_drops_verify_environment "${decode_with_drops_tests}"
@@ -0,0 +1,195 @@
/*
* 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 "./vpx_config.h"
#include "vpx/vp8cx.h"
#include "vpx/vpx_encoder.h"
namespace {
#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
TEST(EncodeAPI, InvalidParams) {
static const vpx_codec_iface_t *kCodecs[] = {
#if CONFIG_VP8_ENCODER
&vpx_codec_vp8_cx_algo,
#endif
#if CONFIG_VP9_ENCODER
&vpx_codec_vp9_cx_algo,
#endif
};
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(NULL, NULL, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(&enc, NULL, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, NULL, 0, 0, 0, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, &img, 0, 0, 0, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_enc_config_default(NULL, NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_enc_config_default(NULL, &cfg, 0));
EXPECT_TRUE(vpx_codec_error(NULL) != NULL);
for (int i = 0; i < NELEMENTS(kCodecs); ++i) {
SCOPED_TRACE(vpx_codec_iface_name(kCodecs[i]));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_enc_init(NULL, kCodecs[i], NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_enc_init(&enc, kCodecs[i], NULL, 0));
EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
vpx_codec_enc_config_default(kCodecs[i], &cfg, 1));
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(kCodecs[i], &cfg, 0));
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, kCodecs[i], &cfg, 0));
EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, NULL, 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) {
static const vpx_codec_iface_t *kCodecs[] = {
#if CONFIG_VP8_ENCODER
&vpx_codec_vp8_cx_algo,
#endif
#if CONFIG_VP9_ENCODER
&vpx_codec_vp9_cx_algo,
#endif
};
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 (int c = 0; c < NELEMENTS(kCodecs); ++c) {
const vpx_codec_iface_t *const iface = kCodecs[c];
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.
const char kVP9Name[] = "WebM Project VP9";
const bool is_vp9 = strncmp(kVP9Name, vpx_codec_iface_name(iface),
sizeof(kVP9Name) - 1) == 0;
EXPECT_EQ(is_vp9 ? 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]);
}
}
}
} // namespace
@@ -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_CASE(VP9EncodePerfTest,
::testing::Values(::libvpx_test::kRealTime));
} // namespace
@@ -0,0 +1,268 @@
/*
* 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 unsigned long 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 unsigned long 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_, NULL, 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++) {
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_TRUE(encoder.get() != NULL);
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() != NULL);
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.get() != NULL && 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(NULL, 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
@@ -0,0 +1,292 @@
/*
* 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_(NULL) {}
const vpx_codec_cx_pkt_t *Next() {
return vpx_codec_get_cx_data(encoder_, &iter_);
}
private:
vpx_codec_ctx_t *encoder_;
vpx_codec_iter_t iter_;
};
// Implements an in-memory store for libvpx twopass statistics
class TwopassStatsStore {
public:
void Append(const vpx_codec_cx_pkt_t &pkt) {
buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
pkt.data.twopass_stats.sz);
}
vpx_fixed_buf_t buf() {
const vpx_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
return buf;
}
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, const unsigned long 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_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,
const unsigned long 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),
last_pts_(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_;
unsigned long frame_flags_;
vpx_codec_pts_t last_pts_;
};
} // namespace libvpx_test
#endif // VPX_TEST_ENCODE_TEST_DRIVER_H_
@@ -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(void) {
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_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
::testing::Values(true));
VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLargeCodecControls,
ONE_PASS_TEST_MODES);
VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
::testing::Values(true));
} // namespace
@@ -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
@@ -0,0 +1,517 @@
/*
* 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_(NULL) {}
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_TRUE(ext_fb_list_ != NULL);
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_TRUE(fb != NULL);
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_TRUE(fb != NULL);
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 = NULL;
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 == NULL) {
EXPECT_TRUE(fb != NULL);
return -1;
}
ExternalFrameBuffer *const ext_fb =
reinterpret_cast<ExternalFrameBuffer *>(fb->priv);
if (ext_fb == NULL) {
EXPECT_TRUE(ext_fb != NULL);
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 != NULL) {
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_TRUE(fb != NULL);
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_(NULL), num_buffers_(0) {}
virtual ~ExternalFrameBufferMD5Test() {
if (md5_file_ != NULL) 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_TRUE(md5_file_ != NULL)
<< "Md5 file open failed. Filename: " << md5_file_name_;
}
virtual void DecompressedFrameHook(const vpx_image_t &img,
const unsigned int frame_number) {
ASSERT_TRUE(md5_file_ != NULL);
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_(NULL), decoder_(NULL), num_buffers_(0) {}
virtual void SetUp() {
video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
ASSERT_TRUE(video_ != NULL);
video_->Init();
video_->Begin();
vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
ASSERT_TRUE(decoder_ != NULL);
}
virtual void TearDown() {
delete decoder_;
decoder_ = NULL;
delete video_;
video_ = NULL;
}
// 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() != NULL; 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 = NULL;
// Get decompressed data
while ((img = dec_iter.Next()) != NULL) {
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_TRUE(video_ != NULL);
video_->Init();
video_->Begin();
vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
ASSERT_TRUE(decoder_ != NULL);
}
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_TRUE(video.get() != NULL);
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, NULL, 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, NULL));
}
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_CASE(
ExternalFrameBufferMD5Test,
::testing::ValuesIn(libvpx_test::kVP9TestVectors,
libvpx_test::kVP9TestVectors +
libvpx_test::kNumVP9TestVectors));
} // namespace
@@ -0,0 +1,768 @@
/*
* 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;
EXPECT_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;
EXPECT_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;
}
}
EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
<< "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
<< " roundtrip error > 1";
EXPECT_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);
}
EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
<< "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
<< "an individual roundtrip error > 1";
EXPECT_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";
EXPECT_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;
EXPECT_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;
EXPECT_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;
EXPECT_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(); }
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_;
};
TEST_P(InvTrans8x8DCT, CompareReference) {
CompareInvReference(ref_txfm_, thresh_);
}
using std::make_tuple;
#if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_P(SSE2, FwdTrans8x8DCT,
::testing::Values(make_tuple(&vpx_fdct8x8_sse2,
&vpx_idct8x8_64_add_sse2,
0, VPX_BITS_8)));
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_P(MSA, FwdTrans8x8DCT,
::testing::Values(make_tuple(&vpx_fdct8x8_msa,
&vpx_idct8x8_64_add_msa, 0,
VPX_BITS_8)));
INSTANTIATE_TEST_CASE_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_CASE_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
} // namespace
@@ -0,0 +1,95 @@
/*
* 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 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);
}
}
int 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_CORRUPT_FRAME;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
#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(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(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(RunLoop(&video));
}
} // namespace
@@ -0,0 +1,320 @@
/*
* 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_CASE_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_CASE_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_CASE_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_CASE_P(
SSSE3, HadamardLowbdTest,
::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_ssse3, 8)));
#endif // HAVE_SSSE3 && VPX_ARCH_X86_64
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, HadamardLowbdTest,
::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_neon, 8),
HadamardFuncWithSize(&vpx_hadamard_16x16_neon, 16)));
#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_CASE_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_CASE_P(
VSX, HadamardLowbdTest,
::testing::Values(HadamardFuncWithSize(&vpx_hadamard_8x8_vsx, 8),
HadamardFuncWithSize(&vpx_hadamard_16x16_vsx, 16)));
#endif // HAVE_VSX
#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_CASE_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_CASE_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
#endif // CONFIG_VP9_HIGHBITDEPTH
} // namespace
@@ -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_
@@ -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
@@ -0,0 +1,179 @@
/*
* 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_TRUE(input != NULL);
ASSERT_TRUE(input->Init());
predict = new Buffer<uint8_t>(4, 4, 3);
ASSERT_TRUE(predict != NULL);
ASSERT_TRUE(predict->Init());
output = new Buffer<uint8_t>(4, 4, 3);
ASSERT_TRUE(output != NULL);
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_TRUE(input->TopLeftPixel() != NULL);
// 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_TRUE(input->TopLeftPixel() != NULL);
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_CASE_P(C, IDCTTest, ::testing::Values(vp8_short_idct4x4llm_c));
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, IDCTTest,
::testing::Values(vp8_short_idct4x4llm_neon));
#endif // HAVE_NEON
#if HAVE_MMX
INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
::testing::Values(vp8_short_idct4x4llm_mmx));
#endif // HAVE_MMX
#if HAVE_MSA
INSTANTIATE_TEST_CASE_P(MSA, IDCTTest,
::testing::Values(vp8_short_idct4x4llm_msa));
#endif // HAVE_MSA
#if HAVE_MMI
INSTANTIATE_TEST_CASE_P(MMI, IDCTTest,
::testing::Values(vp8_short_idct4x4llm_mmi));
#endif // HAVE_MMI
} // namespace
@@ -0,0 +1,219 @@
/*
* 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_(NULL) {}
virtual ~InvalidFileTest() {
if (res_file_ != NULL) fclose(res_file_);
}
void OpenResFile(const std::string &res_file_name_) {
res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
ASSERT_TRUE(res_file_ != NULL)
<< "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_TRUE(res_file_ != NULL);
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_TRUE(video.get() != NULL);
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-token-partition.ivf" },
{ 1, "invalid-vp80-00-comprehensive-s17661_r01-05_b6-.ivf" },
};
VP8_INSTANTIATE_TEST_CASE(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_CASE(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_CASE(InvalidFileInvalidPeekTest,
::testing::ValuesIn(kVP8InvalidPeekTests));
#endif // CONFIG_VP8_DECODER
#if CONFIG_VP9_DECODER
const DecodeParam kVP9InvalidFileInvalidPeekTests[] = {
{ 1, "invalid-vp90-01-v3.webm" },
};
VP9_INSTANTIATE_TEST_CASE(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_CASE_P(
VP9MultiThreaded, InvalidFileTest,
::testing::Combine(
::testing::Values(
static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
::testing::ValuesIn(kMultiThreadedVP9InvalidFileTests)));
#endif // CONFIG_VP9_DECODER
} // namespace
@@ -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_(NULL), compressed_frame_buf_(NULL),
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_TRUE(compressed_frame_buf_ != NULL)
<< "Allocate frame buffer failed";
}
virtual void Begin() {
input_file_ = OpenTestDataFile(file_name_);
ASSERT_TRUE(input_file_ != NULL)
<< "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_TRUE(input_file_ != NULL);
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_ ? NULL : 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_
@@ -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_CASE(KeyframeTest, ALL_TEST_MODES);
} // namespace
@@ -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_CASE(LevelTest,
::testing::Values(::libvpx_test::kTwoPassGood,
::libvpx_test::kOnePassGood),
::testing::Range(0, 9));
} // namespace
@@ -0,0 +1,685 @@
/*
* 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_;
};
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_;
};
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;
}
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;
}
using std::make_tuple;
#if HAVE_SSE2
#if CONFIG_VP9_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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)
} // namespace
@@ -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(void) {
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_
@@ -0,0 +1,135 @@
/*
* 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 "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;
}
}
}
INSTANTIATE_TEST_CASE_P(C, MinMaxTest, ::testing::Values(&vpx_minmax_8x8_c));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, MinMaxTest,
::testing::Values(&vpx_minmax_8x8_sse2));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, MinMaxTest,
::testing::Values(&vpx_minmax_8x8_neon));
#endif
#if HAVE_MSA
INSTANTIATE_TEST_CASE_P(MSA, MinMaxTest,
::testing::Values(&vpx_minmax_8x8_msa));
#endif
} // namespace
@@ -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 = NULL;
MV *smooth_mf = NULL;
MV *estimation = NULL;
MV *ground_truth = NULL;
int(*local_var)[MF_LOCAL_STRUCTURE_SIZE] = NULL;
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] = NULL;
int(*est_local_var)[MF_LOCAL_STRUCTURE_SIZE] = NULL;
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
@@ -0,0 +1,959 @@
/*
* 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_ = NULL;
vpx_free(output_block_);
output_block_ = NULL;
vpx_free(output_block_ref_);
output_block_ref_ = NULL;
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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_P(MSA, PartialIDctTest,
::testing::ValuesIn(msa_partial_idct_tests));
#endif // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH
#endif // !CONFIG_EMULATE_HARDWARE
} // namespace
@@ -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}
[ -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}"
@@ -0,0 +1,572 @@
/*
* 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 "./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());
unsigned char *expected_output = new unsigned char[rows_ * cols_];
ASSERT_TRUE(expected_output != NULL);
SetRows(expected_output, rows_, cols_, cols_);
RunFilterLevel(src_c_.TopLeftPixel(), rows_, cols_, src_c_.stride(), q2mbl(0),
expected_output);
delete[] expected_output;
}
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_CASE_P(
C, VpxPostProcDownAndAcrossMbRowTest,
::testing::Values(vpx_post_proc_down_and_across_mb_row_c));
INSTANTIATE_TEST_CASE_P(C, VpxMbPostProcAcrossIpTest,
::testing::Values(vpx_mbpost_proc_across_ip_c));
INSTANTIATE_TEST_CASE_P(C, VpxMbPostProcDownTest,
::testing::Values(vpx_mbpost_proc_down_c));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, VpxPostProcDownAndAcrossMbRowTest,
::testing::Values(vpx_post_proc_down_and_across_mb_row_sse2));
INSTANTIATE_TEST_CASE_P(SSE2, VpxMbPostProcAcrossIpTest,
::testing::Values(vpx_mbpost_proc_across_ip_sse2));
INSTANTIATE_TEST_CASE_P(SSE2, VpxMbPostProcDownTest,
::testing::Values(vpx_mbpost_proc_down_sse2));
#endif // HAVE_SSE2
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, VpxPostProcDownAndAcrossMbRowTest,
::testing::Values(vpx_post_proc_down_and_across_mb_row_neon));
INSTANTIATE_TEST_CASE_P(NEON, VpxMbPostProcAcrossIpTest,
::testing::Values(vpx_mbpost_proc_across_ip_neon));
INSTANTIATE_TEST_CASE_P(NEON, VpxMbPostProcDownTest,
::testing::Values(vpx_mbpost_proc_down_neon));
#endif // HAVE_NEON
#if HAVE_MSA
INSTANTIATE_TEST_CASE_P(
MSA, VpxPostProcDownAndAcrossMbRowTest,
::testing::Values(vpx_post_proc_down_and_across_mb_row_msa));
INSTANTIATE_TEST_CASE_P(MSA, VpxMbPostProcAcrossIpTest,
::testing::Values(vpx_mbpost_proc_across_ip_msa));
INSTANTIATE_TEST_CASE_P(MSA, VpxMbPostProcDownTest,
::testing::Values(vpx_mbpost_proc_down_msa));
#endif // HAVE_MSA
#if HAVE_VSX
INSTANTIATE_TEST_CASE_P(
VSX, VpxPostProcDownAndAcrossMbRowTest,
::testing::Values(vpx_post_proc_down_and_across_mb_row_vsx));
INSTANTIATE_TEST_CASE_P(VSX, VpxMbPostProcAcrossIpTest,
::testing::Values(vpx_mbpost_proc_across_ip_vsx));
INSTANTIATE_TEST_CASE_P(VSX, VpxMbPostProcDownTest,
::testing::Values(vpx_mbpost_proc_down_vsx));
#endif // HAVE_VSX
} // namespace
@@ -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_(NULL), padded_dst_(NULL), dst_(NULL), dst_c_(NULL) {}
virtual void SetUp() {
src_ = new uint8_t[kSrcSize];
ASSERT_TRUE(src_ != NULL);
// 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_TRUE(padded_dst_ != NULL);
dst_ = padded_dst_ + (kBorderSize * dst_stride_) + kBorderSize;
dst_c_ = new uint8_t[16 * 16];
ASSERT_TRUE(dst_c_ != NULL);
memset(src_, 0, kSrcSize);
memset(padded_dst_, 128, padded_dst_size_);
memset(dst_c_, 0, 16 * 16);
}
virtual void TearDown() {
delete[] src_;
src_ = NULL;
vpx_free(padded_dst_);
padded_dst_ = NULL;
dst_ = NULL;
delete[] dst_c_;
dst_c_ = NULL;
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_CASE_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_CASE_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_CASE_P(
MMX, SixtapPredictTest,
::testing::Values(make_tuple(4, 4, &vp8_sixtap_predict4x4_mmx)));
#endif
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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
@@ -0,0 +1,225 @@
/*
* 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_ = NULL;
vpx_free(macroblockd_dst_);
macroblockd_dst_ = NULL;
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_;
};
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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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_CASE_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
} // namespace
@@ -0,0 +1,63 @@
/*
* 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 "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) {}
virtual ~RealtimeTest() {}
virtual void SetUp() {
InitializeConfig();
cfg_.g_lag_in_frames = 0;
SetMode(::libvpx_test::kRealTime);
}
virtual void BeginPassHook(unsigned int /*pass*/) {
// 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;
}
virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {
frame_packets_++;
}
int frame_packets_;
};
TEST_P(RealtimeTest, RealtimeFirstPassProducesFrames) {
::libvpx_test::RandomVideoSource video;
video.SetSize(kVideoSourceWidth, kVideoSourceHeight);
video.set_limit(kFramesToEncode);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
EXPECT_EQ(kFramesToEncode, frame_packets_);
}
VP8_INSTANTIATE_TEST_CASE(RealtimeTest,
::testing::Values(::libvpx_test::kRealTime));
VP9_INSTANTIATE_TEST_CASE(RealtimeTest,
::testing::Values(::libvpx_test::kRealTime));
} // namespace
@@ -0,0 +1,187 @@
/*
* 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 <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_TRUE(this_thread != NULL);
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; \
} 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];
};
#define ASM_REGISTER_STATE_CHECK(statement) \
do { \
libvpx_test::RegisterStateCheck reg_check; \
statement; \
} while (false)
} // 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; \
ASM_REGISTER_STATE_CHECK(statement); \
} 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_
@@ -0,0 +1,806 @@
/*
* 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_) {
if (smaller_width_larger_size_) {
if (frame < 30) {
*w = initial_w;
*h = initial_h;
return;
}
if (frame < 100) {
*w = initial_w * 7 / 10;
*h = initial_h * 16 / 10;
return;
}
return;
}
if (frame < 10) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_w;
*h = initial_h;
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) {
*w = initial_h;
*h = initial_w;
return;
}
}
*w = initial_w;
*h = initial_h;
}
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;
unsigned int height;
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_(NULL), 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_ = NULL;
}
#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());
}
}
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("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 299);
DefaultConfig();
cfg_.g_w = 352;
cfg_.g_h = 288;
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("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 359);
DefaultConfig();
cfg_.g_w = 352;
cfg_.g_h = 288;
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 == 1) {
// 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 2 resize events in this test.
ASSERT_EQ(resize_count, 2) << "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_(NULL), 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_ = NULL;
}
#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_CASE(ResizeTest, ONE_PASS_TEST_MODES);
VP9_INSTANTIATE_TEST_CASE(ResizeTest,
::testing::Values(::libvpx_test::kRealTime));
VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest,
::testing::Values(::libvpx_test::kOnePassBest));
VP9_INSTANTIATE_TEST_CASE(ResizeRealtimeTest,
::testing::Values(::libvpx_test::kRealTime),
::testing::Range(5, 9));
VP9_INSTANTIATE_TEST_CASE(ResizeCspTest,
::testing::Values(::libvpx_test::kRealTime));
} // namespace
@@ -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}
[ -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}"
File diff suppressed because it is too large Load Diff
@@ -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}
[ -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}"
@@ -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
@@ -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}
[ -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}"
@@ -0,0 +1,172 @@
#include <math.h>
#include <memory>
#include <vector>
#include "third_party/googletest/src/include/gtest/gtest.h"
#include "vp9/simple_encode.h"
namespace vp9 {
namespace {
// TODO(angirbid): Find a better way to construct encode info
const int w = 352;
const int h = 288;
const int frame_rate_num = 30;
const int frame_rate_den = 1;
const int target_bitrate = 1000;
const int num_frames = 17;
const char infile_path[] = "bus_352x288_420_f20_b8.yuv";
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;
}
TEST(SimpleEncode, ComputeFirstPassStats) {
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
simple_encode.ComputeFirstPassStats();
std::vector<std::vector<double>> frame_stats =
simple_encode.ObserveFirstPassStats();
EXPECT_EQ(frame_stats.size(), static_cast<size_t>(num_frames));
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(SimpleEncode, GetCodingFrameNum) {
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
simple_encode.ComputeFirstPassStats();
int num_coding_frames = simple_encode.GetCodingFrameNum();
EXPECT_EQ(num_coding_frames, 19);
}
TEST(SimpleEncode, EncodeFrame) {
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
simple_encode.ComputeFirstPassStats();
int num_coding_frames = simple_encode.GetCodingFrameNum();
EXPECT_GE(num_coding_frames, num_frames);
// The coding frames include actual show frames and alternate reference
// frames, i.e. no show frame.
int ref_num_alternate_refereces = num_coding_frames - num_frames;
int num_alternate_refereces = 0;
simple_encode.StartEncode();
size_t total_data_bit_size = 0;
for (int i = 0; i < num_coding_frames; ++i) {
EncodeFrameResult encode_frame_result;
simple_encode.EncodeFrame(&encode_frame_result);
if (i == 0) {
EXPECT_EQ(encode_frame_result.show_idx, 0);
EXPECT_EQ(encode_frame_result.frame_type, kKeyFrame)
<< "The first coding frame should be key frame";
}
if (encode_frame_result.frame_type == kAlternateReference) {
++num_alternate_refereces;
}
EXPECT_GE(encode_frame_result.show_idx, 0);
EXPECT_LT(encode_frame_result.show_idx, num_frames);
if (i == num_coding_frames - 1) {
EXPECT_EQ(encode_frame_result.show_idx, num_frames - 1)
<< "The last coding frame should be the last display order";
}
EXPECT_GE(encode_frame_result.psnr, 34)
<< "The psnr is supposed to be greater than 34 given the "
"target_bitrate 1000 kbps";
total_data_bit_size += encode_frame_result.coding_data_bit_size;
}
EXPECT_EQ(num_alternate_refereces, ref_num_alternate_refereces);
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(SimpleEncode, EncodeFrameWithQuantizeIndex) {
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
simple_encode.ComputeFirstPassStats();
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();
}
TEST(SimpleEncode, 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;
{
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
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);
}
simple_encode.EndEncode();
}
{
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
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]);
}
simple_encode.EndEncode();
}
}
TEST(SimpleEncode, GetEncodeFrameInfo) {
// Makes sure that the encode_frame_info obtained from GetEncodeFrameInfo()
// matches the counterpart in encode_frame_result obtained from EncodeFrame()
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
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();
}
} // namespace
} // namespace vp9
@@ -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}
[ -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}"
@@ -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="http://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}"
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"
@@ -0,0 +1,128 @@
/*
* 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_;
};
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_CASE_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_CASE_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_CASE_P(
MSA, SumSquaresTest,
::testing::Values(make_tuple(&vpx_sum_squares_2d_i16_c,
&vpx_sum_squares_2d_i16_msa)));
#endif // HAVE_MSA
} // namespace
@@ -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_(NULL), 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_CASE(
SuperframeTest,
::testing::Combine(::testing::Values(::libvpx_test::kTwoPassGood),
::testing::Values(0)));
} // namespace
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,481 @@
/*
* 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 "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), 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_;
}
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);
}
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)
decoder->Control(VP9_DECODE_SVC_SPATIAL_LAYER,
decode_to_layer_after_sync_);
}
}
#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_;
vpx_svc_spatial_layer_sync_t svc_layer_sync_;
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 = 1;
}
}
unsigned int mismatch_nframes_;
unsigned int num_nonref_frames_;
};
// 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;
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;
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;
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;
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;
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
// 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 4 frames. Thus set the
// layer to decode after sync frame to 3.
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;
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 4 frames. Thus set the
// layer to decode after sync frame to 3.
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;
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;
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
}
VP9_INSTANTIATE_TEST_CASE(SyncFrameOnePassCbrSvc, ::testing::Range(0, 3));
INSTANTIATE_TEST_CASE_P(
VP9, ScalePartitionOnePassCbrSvc,
::testing::Values(
static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)));
} // namespace
} // namespace svc_test
@@ -0,0 +1,134 @@
/*
* 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;
}
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
@@ -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_
@@ -0,0 +1,894 @@
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_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) += 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_RATE_CTRL) += 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-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
@@ -0,0 +1,868 @@
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
@@ -0,0 +1,208 @@
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) += aq_segment_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += alt_ref_aq_segment_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += vp8_datarate_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += vp9_datarate_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_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) += 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_RATE_CTRL) += simple_encode_test.cc
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
LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += quantize_test.cc
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
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
LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_block_error_test.cc
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
endif # VP9
## Multi-codec / unconditional whitebox tests.
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sad_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sum_squares_test.cc
TEST_INTRA_PRED_SPEED_SRCS-yes := test_intra_pred_speed.cc
TEST_INTRA_PRED_SPEED_SRCS-yes += ../md5_utils.h ../md5_utils.c
endif # CONFIG_SHARED
include $(SRC_PATH_BARE)/test/test-data.mk
@@ -0,0 +1,589 @@
/*
* 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;
// some code assumes the top row has been extended:
// d45/d63 C-code, for instance, but not the assembly.
// TODO(jzern): this style of extension isn't strictly necessary.
ASSERT_LE(block_size, kBPS);
for (int i = block_size; i < 2 * kBPS; ++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] == NULL) 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, NULL,
NULL, NULL, vpx_d207_predictor_4x4_sse2, NULL,
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, NULL,
NULL, NULL, NULL, NULL, 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, NULL, NULL, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL, NULL, NULL,
vpx_tm_predictor_32x32_sse2)
#endif // HAVE_SSE2
#if HAVE_SSSE3
INTRA_PRED_TEST(SSSE3, TestIntraPred4, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, vpx_d153_predictor_4x4_ssse3, NULL,
vpx_d63_predictor_4x4_ssse3, NULL)
INTRA_PRED_TEST(SSSE3, TestIntraPred8, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, vpx_d153_predictor_8x8_ssse3,
vpx_d207_predictor_8x8_ssse3, vpx_d63_predictor_8x8_ssse3, NULL)
INTRA_PRED_TEST(SSSE3, TestIntraPred16, NULL, NULL, NULL, NULL, NULL, NULL,
vpx_d45_predictor_16x16_ssse3, NULL, NULL,
vpx_d153_predictor_16x16_ssse3, vpx_d207_predictor_16x16_ssse3,
vpx_d63_predictor_16x16_ssse3, NULL)
INTRA_PRED_TEST(SSSE3, TestIntraPred32, NULL, NULL, NULL, NULL, NULL, NULL,
vpx_d45_predictor_32x32_ssse3, NULL, NULL,
vpx_d153_predictor_32x32_ssse3, vpx_d207_predictor_32x32_ssse3,
vpx_d63_predictor_32x32_ssse3, NULL)
#endif // HAVE_SSSE3
#if HAVE_DSPR2
INTRA_PRED_TEST(DSPR2, TestIntraPred4, vpx_dc_predictor_4x4_dspr2, NULL, NULL,
NULL, NULL, vpx_h_predictor_4x4_dspr2, NULL, NULL, NULL, NULL,
NULL, NULL, vpx_tm_predictor_4x4_dspr2)
INTRA_PRED_TEST(DSPR2, TestIntraPred8, vpx_dc_predictor_8x8_dspr2, NULL, NULL,
NULL, NULL, vpx_h_predictor_8x8_dspr2, NULL, NULL, NULL, NULL,
NULL, NULL, vpx_tm_predictor_8x8_c)
INTRA_PRED_TEST(DSPR2, TestIntraPred16, vpx_dc_predictor_16x16_dspr2, NULL,
NULL, NULL, NULL, vpx_h_predictor_16x16_dspr2, NULL, NULL, NULL,
NULL, NULL, NULL, NULL)
#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, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL, NULL,
vpx_h_predictor_4x4_vsx, NULL, NULL, NULL, NULL, NULL, NULL,
vpx_tm_predictor_4x4_vsx)
INTRA_PRED_TEST(VSX, TestIntraPred8, vpx_dc_predictor_8x8_vsx, NULL, NULL, NULL,
NULL, vpx_h_predictor_8x8_vsx, vpx_d45_predictor_8x8_vsx, NULL,
NULL, NULL, NULL, 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, NULL,
NULL, NULL, NULL, 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, NULL,
NULL, NULL, NULL, 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] == NULL) 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, NULL, 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, NULL, NULL, NULL, NULL,
NULL, NULL, 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, NULL, NULL, NULL,
NULL, NULL, NULL, 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, NULL, NULL, NULL,
NULL, NULL, NULL, vpx_highbd_tm_predictor_32x32_sse2)
#endif // HAVE_SSE2
#if HAVE_SSSE3
HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred4, NULL, NULL, NULL, NULL,
NULL, NULL, vpx_highbd_d45_predictor_4x4_ssse3, NULL,
NULL, NULL, NULL, NULL, NULL)
HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred8, NULL, NULL, NULL, NULL,
NULL, NULL, 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, NULL)
HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred16, NULL, NULL, NULL, NULL,
NULL, NULL, 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, NULL)
HIGHBD_INTRA_PRED_TEST(SSSE3, TestHighbdIntraPred32, NULL, NULL, NULL, NULL,
NULL, NULL, 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, NULL)
#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, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL, NULL,
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, NULL, NULL, NULL,
NULL, 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, NULL, NULL, NULL,
NULL, vpx_highbd_tm_predictor_32x32_neon)
#endif // HAVE_NEON
#endif // CONFIG_VP9_HIGHBITDEPTH
#include "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();
}
@@ -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_(NULL) {
#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_TRUE(md5_file_ != NULL)
<< "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_TRUE(md5_file_ != NULL);
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_TRUE(video.get() != NULL);
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_CASE(
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_CASE_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_CASE(
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_CASE_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
@@ -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
@@ -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_
@@ -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_CASE(TileIndependenceTest, ::testing::Range(0, 2, 1));
} // namespace
@@ -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_CASE(TimestampTest,
::testing::Values(::libvpx_test::kTwoPassGood));
VP9_INSTANTIATE_TEST_CASE(TimestampTest,
::testing::Values(::libvpx_test::kTwoPassGood));
} // namespace
@@ -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}" | egrep -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}" | egrep -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.
@@ -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}
[ -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
@@ -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) ? NULL : 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 = NULL;
// Get decompressed data.
while ((img = dec_iter.Next())) {
if (frame_num == 0) {
CheckUserPrivateData(img->user_priv, NULL);
} 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, NULL);
}
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
@@ -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_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,258 @@
/*
* 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 <string>
#include "test/acm_random.h"
#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 == NULL) {
#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 NULL;
#else
return tmpfile();
#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_ = NULL;
}
}
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 NULL on End-Of-Stream.
virtual vpx_image_t *img() const = 0;
// Get the presentation timestamp of the current frame.
virtual vpx_codec_pts_t pts() const = 0;
// Get the current frame's duration
virtual unsigned long duration() const = 0;
// Get the timebase for the stream
virtual vpx_rational_t timebase() const = 0;
// Get the current frame counter, starting at 0.
virtual unsigned int frame() const = 0;
// Get the current file limit.
virtual unsigned int limit() const = 0;
};
class DummyVideoSource : public VideoSource {
public:
DummyVideoSource()
: img_(NULL), 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_ : NULL; }
// Models a stream where Timebase = 1/FPS, so pts == frame.
virtual vpx_codec_pts_t pts() const { return frame_; }
virtual unsigned long duration() const { return 1; }
virtual vpx_rational_t timebase() const {
const vpx_rational_t t = { 1, 30 };
return t;
}
virtual unsigned int frame() const { return frame_; }
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(NULL, format_, width_, height_, 32);
raw_sz_ = ((img_->w + 31) & ~31) * 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_
@@ -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;
}
}
}
}
}
@@ -0,0 +1,416 @@
/*
* 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(void) {
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!";
}
VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES,
::testing::Values(0));
VP8_INSTANTIATE_TEST_CASE(DatarateTestRealTime,
::testing::Values(::libvpx_test::kRealTime),
::testing::Values(-6, -12));
} // namespace

Some files were not shown because too many files have changed in this diff Show More