Update aom to v1.0.0

Update aom to commit id d14c5bb4f336ef1842046089849dee4a301fbbf0.
This commit is contained in:
trav90 2018-10-19 21:52:15 -05:00 committed by Roy Tam
commit 48f6d2e034
1087 changed files with 154333 additions and 265310 deletions

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <math.h>
#include <stdlib.h>
@ -35,10 +35,7 @@ TEST(AV1, TestAccounting) {
}
aom_stop_encode(&bw);
aom_reader br;
#if CONFIG_ANS && ANS_MAX_SYMBOLS
br.window_size = 1 << 16;
#endif
aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
aom_reader_init(&br, bw_buffer, bw.pos);
Accounting accounting;
aom_accounting_init(&accounting);
@ -54,7 +51,7 @@ TEST(AV1, TestAccounting) {
GTEST_ASSERT_EQ(accounting.syms.num_syms, 0);
// Should record 2 * kSymbols accounting symbols.
aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
aom_reader_init(&br, bw_buffer, bw.pos);
br.accounting = &accounting;
for (int i = 0; i < kSymbols; i++) {
aom_read(&br, 32, "A");

View file

@ -36,6 +36,19 @@ class ACMRandom {
return (value >> 15) & 0xffff;
}
int16_t Rand15Signed(void) {
const uint32_t value =
random_.Generate(testing::internal::Random::kMaxRange);
return (value >> 17) & 0xffff;
}
uint16_t Rand12(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 >> 19) & 0xfff;
}
int16_t Rand9Signed(void) {
// Use 9 bits: values between 255 (0x0FF) and -256 (0x100).
const uint32_t value = random_.Generate(512);

View file

@ -1,129 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <algorithm>
#include "third_party/googletest/src/googletest/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 aom_image_t &current, const aom_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 aom_image_t &current,
const aom_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 ::libaom_test::CodecTestWith2Params<libaom_test::TestMode, int>,
public ::libaom_test::EncoderTest {
protected:
ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {}
virtual ~ActiveMapRefreshTest() {}
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
cpu_used_ = GET_PARAM(2);
}
virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
::libaom_test::Encoder *encoder) {
::libaom_test::Y4mVideoSource *y4m_video =
static_cast<libaom_test::Y4mVideoSource *>(video);
if (video->frame() == 1) {
encoder->Control(AOME_SET_CPUUSED, cpu_used_);
encoder->Control(AV1E_SET_AQ_MODE, kAqModeCyclicRefresh);
} else if (video->frame() >= 2 && video->img()) {
aom_image_t *current = video->img();
aom_image_t *previous = y4m_holder_->img();
ASSERT_TRUE(previous != NULL);
aom_active_map_t map = aom_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(AOME_SET_ACTIVEMAP, &map);
delete[] active_map;
}
if (video->img()) {
y4m_video->SwapBuffers(y4m_holder_);
}
}
int cpu_used_;
::libaom_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_mode = 0;
cfg_.rc_min_quantizer = 8;
cfg_.rc_max_quantizer = 30;
cfg_.g_pass = AOM_RC_ONE_PASS;
cfg_.rc_end_usage = AOM_CBR;
cfg_.kf_max_dist = 90000;
::libaom_test::Y4mVideoSource video("desktop_credits.y4m", 0, 10);
::libaom_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 10);
video_holder.Begin();
y4m_holder_ = &video_holder;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
AV1_INSTANTIATE_TEST_CASE(ActiveMapRefreshTest,
::testing::Values(::libaom_test::kRealTime),
::testing::Range(5, 6));
} // namespace

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <climits>
#include <vector>

View file

@ -1,58 +0,0 @@
#
# Copyright (c) 2016, Alliance for Open Media. All rights reserved
#
# This source code is subject to the terms of the BSD 2 Clause License and
# the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
# was not distributed with this source code in the LICENSE file, you can
# obtain it at www.aomedia.org/license/software. If the Alliance for Open
# Media Patent License 1.0 was not distributed with this source code in the
# PATENTS file, you can obtain it at www.aomedia.org/license/patent.
#
# This make file builds aom_test app for android.
# The test app itself runs on the command line through adb shell
# The paths are really messed up as the libaom 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)/libaom/third_party/libwebm/Android.mk
LOCAL_PATH := $(CUR_WD)/../../..
#libaom
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libwebm
include $(BINDINGS_DIR)/libaom/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/googletest/src
LOCAL_C_INCLUDES += $(LOCAL_PATH)/third_party/googletest/src/googletest/include
LOCAL_SRC_FILES := ./third_party/googletest/src/googletest/src/gtest-all.cc
include $(BUILD_STATIC_LIBRARY)
#libaom_test
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_MODULE := libaom_test
LOCAL_STATIC_LIBRARIES := gtest libwebm
ifeq ($(ENABLE_SHARED),1)
LOCAL_SHARED_LIBRARIES := aom
else
LOCAL_STATIC_LIBRARIES += aom
endif
include $(LOCAL_PATH)/test/test.mk
LOCAL_C_INCLUDES := $(BINDINGS_DIR)
FILTERED_SRC := $(sort $(filter %.cc %.c, $(LIBAOM_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)

View file

@ -1,32 +0,0 @@
Android.mk will build aom unittests on android.
1) Configure libaom from the parent directory:
./libaom/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 --sdk-path=$NDK
2) From the parent directory, invoke ndk-build:
NDK_PROJECT_PATH=. ndk-build APP_BUILD_SCRIPT=./libaom/test/android/Android.mk \
APP_ABI=armeabi-v7a APP_PLATFORM=android-18 APP_OPTIM=release \
APP_STL=gnustl_static
Note: Both adb and ndk-build are available prebuilt at:
https://chromium.googlesource.com/android_tools
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/libaom
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=. ./aom_test

View file

@ -1,120 +0,0 @@
#
# Copyright (c) 2016, Alliance for Open Media. All rights reserved
#
# This source code is subject to the terms of the BSD 2 Clause License and
# the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
# was not distributed with this source code in the LICENSE file, you can
# obtain it at www.aomedia.org/license/software. If the Alliance for Open
# Media Patent License 1.0 was not distributed with this source code in the
# PATENTS file, you can obtain it at www.aomedia.org/license/patent.
#
# 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

View file

@ -1,60 +0,0 @@
#
# Copyright (c) 2016, Alliance for Open Media. All rights reserved
#
# This source code is subject to the terms of the BSD 2 Clause License and
# the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
# was not distributed with this source code in the LICENSE file, you can
# obtain it at www.aomedia.org/license/software. If the Alliance for Open
# Media Patent License 1.0 was not distributed with this source code in the
# PATENTS file, you can obtain it at www.aomedia.org/license/patent.
#
"""Standalone script which parses a gtest log for json.
Json is returned returns as an array. This script is used by the libaom
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())

View file

@ -1,97 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "aom_dsp/ans.h"
#include "av1/av1_dx_iface.c"
// A note on ANS_MAX_SYMBOLS == 0:
// Fused gtest doesn't work with EXPECT_FATAL_FAILURE [1]. Just run with a
// single iteration and don't try to check the window size if we are unwindowed.
// [1] https://github.com/google/googletest/issues/356
namespace {
const char kTestVideoName[] = "niklas_1280_720_30.y4m";
const int kTestVideoFrames = 10;
class AnsCodecTest : public ::libaom_test::CodecTestWithParam<int>,
public ::libaom_test::EncoderTest {
protected:
AnsCodecTest()
: EncoderTest(GET_PARAM(0)), ans_window_size_log2_(GET_PARAM(1)) {}
virtual ~AnsCodecTest() {}
virtual void SetUp() {
InitializeConfig();
SetMode(::libaom_test::kOnePassGood);
cfg_.g_lag_in_frames = 25;
cfg_.rc_end_usage = AOM_CQ;
}
virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
::libaom_test::Encoder *encoder) {
if (video->frame() == 1) {
#if ANS_MAX_SYMBOLS
encoder->Control(AV1E_SET_ANS_WINDOW_SIZE_LOG2, ans_window_size_log2_);
#endif
// Try to push a high symbol count through the codec
encoder->Control(AOME_SET_CQ_LEVEL, 8);
encoder->Control(AOME_SET_CPUUSED, 2);
encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
encoder->Control(AOME_SET_ARNR_MAXFRAMES, 7);
encoder->Control(AOME_SET_ARNR_STRENGTH, 5);
encoder->Control(AV1E_SET_TILE_COLUMNS, 0);
encoder->Control(AV1E_SET_TILE_ROWS, 0);
}
}
virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
libaom_test::Decoder *decoder) {
aom_codec_ctx_t *const av1_decoder = decoder->GetDecoder();
#if ANS_MAX_SYMBOLS
aom_codec_alg_priv_t *const priv =
reinterpret_cast<aom_codec_alg_priv_t *>(av1_decoder->priv);
FrameWorkerData *const worker_data =
reinterpret_cast<FrameWorkerData *>(priv->frame_workers[0].data1);
AV1_COMMON *const common = &worker_data->pbi->common;
EXPECT_EQ(ans_window_size_log2_, common->ans_window_size_log2);
#endif
EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
return AOM_CODEC_OK == res_dec;
}
private:
int ans_window_size_log2_;
};
TEST_P(AnsCodecTest, BitstreamParms) {
testing::internal::scoped_ptr<libaom_test::VideoSource> video(
new libaom_test::Y4mVideoSource(kTestVideoName, 0, kTestVideoFrames));
ASSERT_TRUE(video.get() != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
}
#if ANS_MAX_SYMBOLS
AV1_INSTANTIATE_TEST_CASE(AnsCodecTest, ::testing::Range(8, 24));
#else
AV1_INSTANTIATE_TEST_CASE(AnsCodecTest, ::testing::Range(0, 1));
#endif
} // namespace

View file

@ -1,213 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <ctime>
#include <utility>
#include <vector>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "aom_dsp/ansreader.h"
#include "aom_dsp/buf_ans.h"
namespace {
typedef std::vector<std::pair<uint8_t, bool> > PvVec;
const int kPrintStats = 0;
// Use a small buffer size to exercise ANS window spills or buffer growth
const int kBufAnsSize = 1 << 8;
PvVec abs_encode_build_vals(int iters) {
PvVec ret;
libaom_test::ACMRandom gen(0x30317076);
double entropy = 0;
for (int i = 0; i < iters; ++i) {
uint8_t p;
do {
p = gen.Rand8();
} while (p == 0); // zero is not a valid coding probability
bool b = gen.Rand8() < p;
ret.push_back(std::make_pair(static_cast<uint8_t>(p), b));
if (kPrintStats) {
double d = p / 256.;
entropy += -d * log2(d) - (1 - d) * log2(1 - d);
}
}
if (kPrintStats) printf("entropy %f\n", entropy);
return ret;
}
bool check_rabs(const PvVec &pv_vec, uint8_t *buf) {
BufAnsCoder a;
a.size = kBufAnsSize;
aom_buf_ans_alloc(&a, NULL);
buf_ans_write_init(&a, buf);
std::clock_t start = std::clock();
for (PvVec::const_iterator it = pv_vec.begin(); it != pv_vec.end(); ++it) {
buf_rabs_write(&a, it->second, 256 - it->first);
}
aom_buf_ans_flush(&a);
std::clock_t enc_time = std::clock() - start;
int offset = buf_ans_write_end(&a);
aom_buf_ans_free(&a);
bool okay = true;
AnsDecoder d;
#if ANS_MAX_SYMBOLS
d.window_size = kBufAnsSize;
#endif
if (ans_read_init(&d, buf, offset)) return false;
start = std::clock();
for (PvVec::const_iterator it = pv_vec.begin(); it != pv_vec.end(); ++it) {
okay = okay && (rabs_read(&d, 256 - it->first) != 0) == it->second;
}
std::clock_t dec_time = std::clock() - start;
if (!okay) return false;
if (kPrintStats)
printf("uABS size %d enc_time %f dec_time %f\n", offset,
static_cast<float>(enc_time) / CLOCKS_PER_SEC,
static_cast<float>(dec_time) / CLOCKS_PER_SEC);
return ans_read_end(&d) != 0;
}
const aom_cdf_prob spareto65[] = { 8320, 6018, 4402, 3254, 4259,
3919, 2057, 492, 45, 2 };
const int kRansSymbols =
static_cast<int>(sizeof(spareto65) / sizeof(spareto65[0]));
struct rans_sym {
aom_cdf_prob prob;
aom_cdf_prob cum_prob; // not-inclusive
};
std::vector<int> ans_encode_build_vals(rans_sym *const tab, int iters) {
aom_cdf_prob sum = 0;
for (int i = 0; i < kRansSymbols; ++i) {
tab[i].cum_prob = sum;
tab[i].prob = spareto65[i];
sum += spareto65[i];
}
std::vector<int> p_to_sym;
for (int i = 0; i < kRansSymbols; ++i) {
p_to_sym.insert(p_to_sym.end(), tab[i].prob, i);
}
assert(p_to_sym.size() == RANS_PRECISION);
std::vector<int> ret;
libaom_test::ACMRandom gen(18543637);
for (int i = 0; i < iters; ++i) {
int sym =
p_to_sym[((gen.Rand8() << 8) + gen.Rand8()) & (RANS_PRECISION - 1)];
ret.push_back(sym);
}
return ret;
}
void rans_build_dec_tab(const struct rans_sym sym_tab[],
aom_cdf_prob *dec_tab) {
unsigned int sum = 0;
for (int i = 0; sum < RANS_PRECISION; ++i) {
dec_tab[i] = sum += sym_tab[i].prob;
}
}
bool check_rans(const std::vector<int> &sym_vec, const rans_sym *const tab,
uint8_t *buf) {
BufAnsCoder a;
a.size = kBufAnsSize;
aom_buf_ans_alloc(&a, NULL);
buf_ans_write_init(&a, buf);
aom_cdf_prob dec_tab[kRansSymbols];
rans_build_dec_tab(tab, dec_tab);
std::clock_t start = std::clock();
for (std::vector<int>::const_iterator it = sym_vec.begin();
it != sym_vec.end(); ++it) {
buf_rans_write(&a, tab[*it].cum_prob, tab[*it].prob);
}
aom_buf_ans_flush(&a);
std::clock_t enc_time = std::clock() - start;
int offset = buf_ans_write_end(&a);
aom_buf_ans_free(&a);
bool okay = true;
AnsDecoder d;
#if ANS_MAX_SYMBOLS
d.window_size = kBufAnsSize;
#endif
if (ans_read_init(&d, buf, offset)) return false;
start = std::clock();
for (std::vector<int>::const_iterator it = sym_vec.begin();
it != sym_vec.end(); ++it) {
okay &= rans_read(&d, dec_tab) == *it;
}
std::clock_t dec_time = std::clock() - start;
if (!okay) return false;
if (kPrintStats)
printf("rANS size %d enc_time %f dec_time %f\n", offset,
static_cast<float>(enc_time) / CLOCKS_PER_SEC,
static_cast<float>(dec_time) / CLOCKS_PER_SEC);
return ans_read_end(&d) != 0;
}
class AbsTestFix : public ::testing::Test {
protected:
static void SetUpTestCase() { pv_vec_ = abs_encode_build_vals(kNumBools); }
virtual void SetUp() { buf_ = new uint8_t[kNumBools / 8]; }
virtual void TearDown() { delete[] buf_; }
static const int kNumBools = 100000000;
static PvVec pv_vec_;
uint8_t *buf_;
};
PvVec AbsTestFix::pv_vec_;
class AnsTestFix : public ::testing::Test {
protected:
static void SetUpTestCase() {
sym_vec_ = ans_encode_build_vals(rans_sym_tab_, kNumSyms);
}
virtual void SetUp() { buf_ = new uint8_t[kNumSyms / 2]; }
virtual void TearDown() { delete[] buf_; }
static const int kNumSyms = 25000000;
static std::vector<int> sym_vec_;
static rans_sym rans_sym_tab_[kRansSymbols];
uint8_t *buf_;
};
std::vector<int> AnsTestFix::sym_vec_;
rans_sym AnsTestFix::rans_sym_tab_[kRansSymbols];
TEST_F(AbsTestFix, Rabs) { EXPECT_TRUE(check_rabs(pv_vec_, buf_)); }
TEST_F(AnsTestFix, Rans) {
EXPECT_TRUE(check_rans(sym_vec_, rans_sym_tab_, buf_));
}
TEST(AnsTest, FinalStateSerialization) {
for (unsigned i = L_BASE; i < L_BASE * IO_BASE; ++i) {
uint8_t buf[8];
AnsCoder c;
ans_write_init(&c, buf);
c.state = i;
const int written_size = ans_write_end(&c);
ASSERT_LT(static_cast<size_t>(written_size), sizeof(buf));
AnsDecoder d;
#if ANS_MAX_SYMBOLS
// There is no real data window here because no symbols are sent through
// ans (only synthetic states), so use a dummy value
d.window_size = 1024;
#endif
const int read_init_status = ans_read_init(&d, buf, written_size);
EXPECT_EQ(read_init_status, 0);
EXPECT_EQ(d.state, i);
}
}
} // namespace

177
third_party/aom/test/aom_integer_test.cc vendored Normal file
View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "aom/aom_integer.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace {
const uint64_t kMaximumLeb128CodedSize = 8;
const uint8_t kLeb128PadByte = 0x80; // Binary: 10000000
const uint64_t kMaximumLeb128Value = UINT32_MAX;
const uint32_t kSizeTestNumValues = 6;
const uint32_t kSizeTestExpectedSizes[kSizeTestNumValues] = {
1, 1, 2, 3, 4, 5
};
const uint64_t kSizeTestInputs[kSizeTestNumValues] = {
0, 0x7f, 0x3fff, 0x1fffff, 0xffffff, 0x10000000
};
const uint8_t kOutOfRangeLeb128Value[5] = { 0x80, 0x80, 0x80, 0x80,
0x10 }; // UINT32_MAX + 1
} // namespace
TEST(AomLeb128, DecodeTest) {
const size_t num_leb128_bytes = 3;
const uint8_t leb128_bytes[num_leb128_bytes] = { 0xE5, 0x8E, 0x26 };
const uint64_t expected_value = 0x98765; // 624485
const size_t expected_length = 3;
uint64_t value = ~0ULL; // make sure value is cleared by the function
size_t length;
ASSERT_EQ(
aom_uleb_decode(&leb128_bytes[0], num_leb128_bytes, &value, &length), 0);
ASSERT_EQ(expected_value, value);
ASSERT_EQ(expected_length, length);
// Make sure the decoder stops on the last marked LEB128 byte.
aom_uleb_decode(&leb128_bytes[0], num_leb128_bytes + 1, &value, &length);
ASSERT_EQ(expected_value, value);
ASSERT_EQ(expected_length, length);
}
TEST(AomLeb128, EncodeTest) {
const uint32_t test_value = 0x98765; // 624485
const uint8_t expected_bytes[3] = { 0xE5, 0x8E, 0x26 };
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(aom_uleb_encode(test_value, kWriteBufferSize, &write_buffer[0],
&bytes_written),
0);
ASSERT_EQ(bytes_written, 3u);
for (size_t i = 0; i < bytes_written; ++i) {
ASSERT_EQ(write_buffer[i], expected_bytes[i]);
}
}
TEST(AomLeb128, EncodeDecodeTest) {
const uint32_t value = 0x98765; // 624485
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(aom_uleb_encode(value, kWriteBufferSize, &write_buffer[0],
&bytes_written),
0);
ASSERT_EQ(bytes_written, 3u);
uint64_t decoded_value;
size_t decoded_length;
aom_uleb_decode(&write_buffer[0], bytes_written, &decoded_value,
&decoded_length);
ASSERT_EQ(value, decoded_value);
ASSERT_EQ(bytes_written, decoded_length);
}
TEST(AomLeb128, FixedSizeEncodeTest) {
const uint32_t test_value = 0x123;
const uint8_t expected_bytes[4] = { 0xa3, 0x82, 0x80, 0x00 };
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(0, aom_uleb_encode_fixed_size(test_value, kWriteBufferSize,
kWriteBufferSize, &write_buffer[0],
&bytes_written));
ASSERT_EQ(kWriteBufferSize, bytes_written);
for (size_t i = 0; i < bytes_written; ++i) {
ASSERT_EQ(write_buffer[i], expected_bytes[i]);
}
}
TEST(AomLeb128, FixedSizeEncodeDecodeTest) {
const uint32_t value = 0x1;
const size_t kWriteBufferSize = 4;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t bytes_written = 0;
ASSERT_EQ(
aom_uleb_encode_fixed_size(value, kWriteBufferSize, kWriteBufferSize,
&write_buffer[0], &bytes_written),
0);
ASSERT_EQ(bytes_written, 4u);
uint64_t decoded_value;
size_t decoded_length;
aom_uleb_decode(&write_buffer[0], bytes_written, &decoded_value,
&decoded_length);
ASSERT_EQ(value, decoded_value);
ASSERT_EQ(bytes_written, decoded_length);
}
TEST(AomLeb128, SizeTest) {
for (size_t i = 0; i < kSizeTestNumValues; ++i) {
ASSERT_EQ(kSizeTestExpectedSizes[i],
aom_uleb_size_in_bytes(kSizeTestInputs[i]));
}
}
TEST(AomLeb128, DecodeFailTest) {
// Input buffer containing what would be a valid 9 byte LEB128 encoded
// unsigned integer.
const uint8_t kAllPadBytesBuffer[kMaximumLeb128CodedSize + 1] = {
kLeb128PadByte, kLeb128PadByte, kLeb128PadByte,
kLeb128PadByte, kLeb128PadByte, kLeb128PadByte,
kLeb128PadByte, kLeb128PadByte, 0
};
uint64_t decoded_value;
// Test that decode fails when result would be valid 9 byte integer.
ASSERT_EQ(aom_uleb_decode(&kAllPadBytesBuffer[0], kMaximumLeb128CodedSize + 1,
&decoded_value, NULL),
-1);
// Test that encoded value missing terminator byte within available buffer
// range causes decode error.
ASSERT_EQ(aom_uleb_decode(&kAllPadBytesBuffer[0], kMaximumLeb128CodedSize,
&decoded_value, NULL),
-1);
// Test that LEB128 input that decodes to a value larger than 32-bits fails.
size_t value_size = 0;
ASSERT_EQ(aom_uleb_decode(&kOutOfRangeLeb128Value[0],
sizeof(kOutOfRangeLeb128Value), &decoded_value,
&value_size),
-1);
}
TEST(AomLeb128, EncodeFailTest) {
const size_t kWriteBufferSize = 4;
const uint32_t kValidTestValue = 1;
uint8_t write_buffer[kWriteBufferSize] = { 0 };
size_t coded_size = 0;
ASSERT_EQ(
aom_uleb_encode(kValidTestValue, kWriteBufferSize, NULL, &coded_size),
-1);
ASSERT_EQ(aom_uleb_encode(kValidTestValue, kWriteBufferSize, &write_buffer[0],
NULL),
-1);
const uint32_t kValueOutOfRangeForBuffer = 0xFFFFFFFF;
ASSERT_EQ(aom_uleb_encode(kValueOutOfRangeForBuffer, kWriteBufferSize,
&write_buffer[0], &coded_size),
-1);
const uint64_t kValueOutOfRange = kMaximumLeb128Value + 1;
ASSERT_EQ(aom_uleb_encode(kValueOutOfRange, kWriteBufferSize,
&write_buffer[0], &coded_size),
-1);
const size_t kPadSizeOutOfRange = 5;
ASSERT_EQ(aom_uleb_encode_fixed_size(kValidTestValue, kWriteBufferSize,
kPadSizeOutOfRange, &write_buffer[0],
&coded_size),
-1);
}

View file

@ -17,10 +17,12 @@
# Environment check: Make sure input is available.
aomdec_verify_environment() {
if [ "$(av1_encode_available)" != "yes" ] ; then
if [ ! -e "${AV1_WEBM_FILE}" ] || \
[ ! -e "${AV1_FPM_WEBM_FILE}" ] || \
[ ! -e "${AV1_LT_50_FRAMES_WEBM_FILE}" ] ; then
elog "Libaom test data must exist in LIBAOM_TEST_DATA_PATH."
if [ ! -e "${AV1_IVF_FILE}" ] || \
[ ! -e "${AV1_OBU_ANNEXB_FILE}" ] || \
[ ! -e "${AV1_OBU_SEC5_FILE}" ] || \
[ ! -e "${AV1_WEBM_FILE}" ]; then
elog "Libaom test data must exist before running this test script when " \
" encoding is disabled. "
return 1
fi
fi
@ -38,10 +40,8 @@ aomdec_pipe() {
local readonly input="$1"
shift
if [ ! -e "${input}" ]; then
local file="${AOM_TEST_OUTPUT_DIR}/test_encode.ivf"
encode_yuv_raw_input_av1 "${file}" --ivf
else
local file="${input}"
elog "Input file ($input) missing in aomdec_pipe()"
return 1
fi
cat "${file}" | aomdec - "$@" ${devnull}
}
@ -63,62 +63,85 @@ aomdec_can_decode_av1() {
fi
}
aomdec_av1_ivf() {
if [ "$(aomdec_can_decode_av1)" = "yes" ]; then
local readonly file="${AV1_IVF_FILE}"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}" --ivf
fi
aomdec "${AV1_IVF_FILE}" --summary --noblit
fi
}
aomdec_av1_ivf_error_resilient() {
if [ "$(aomdec_can_decode_av1)" = "yes" ]; then
local readonly file="av1.error-resilient.ivf"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}" --ivf --error-resilient=1
fi
aomdec "${file}" --summary --noblit
fi
}
aomdec_av1_ivf_multithread() {
if [ "$(aomdec_can_decode_av1)" = "yes" ]; then
local readonly file="${AV1_IVF_FILE}"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}" --ivf
fi
for threads in 2 3 4 5 6 7 8; do
aomdec "${file}" --summary --noblit --threads=$threads
done
fi
}
aomdec_aom_ivf_pipe_input() {
if [ "$(aomdec_can_decode_av1)" = "yes" ]; then
aomdec_pipe "${AOM_IVF_FILE}" --summary --noblit
local readonly file="${AV1_IVF_FILE}"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}" --ivf
fi
aomdec_pipe "${AV1_IVF_FILE}" --summary --noblit
fi
}
aomdec_av1_obu_annexb() {
if [ "$(aomdec_can_decode_av1)" = "yes" ]; then
local readonly file="${AV1_OBU_ANNEXB_FILE}"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}" --obu --annexb=1
fi
aomdec "${file}" --summary --noblit --annexb
fi
}
aomdec_av1_obu_section5() {
if [ "$(aomdec_can_decode_av1)" = "yes" ]; then
local readonly file="${AV1_OBU_SEC5_FILE}"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}" --obu
fi
aomdec "${file}" --summary --noblit
fi
}
aomdec_av1_webm() {
if [ "$(aomdec_can_decode_av1)" = "yes" ] && \
[ "$(webm_io_available)" = "yes" ]; then
if [ ! -e "${AV1_WEBM_FILE}" ]; then
local file="${AOM_TEST_OUTPUT_DIR}/test_encode.webm"
local readonly file="${AV1_WEBM_FILE}"
if [ ! -e "${file}" ]; then
encode_yuv_raw_input_av1 "${file}"
else
aomdec "${AV1_WEBM_FILE}" --summary --noblit
fi
aomdec "${AV1_WEBM_FILE}" --summary --noblit
fi
}
aomdec_av1_webm_frame_parallel() {
if [ "$(aomdec_can_decode_av1)" = "yes" ] && \
[ "$(webm_io_available)" = "yes" ]; then
local file
if [ ! -e "${AV1_WEBM_FILE}" ]; then
file="${AOM_TEST_OUTPUT_DIR}/test_encode.webm"
encode_yuv_raw_input_av1 "${file}" "--ivf --error-resilient=1 "
else
file="${AV1_FPM_WEBM_FILE}"
fi
for threads in 2 3 4 5 6 7 8; do
aomdec "${file}" --summary --noblit --threads=$threads \
--frame-parallel
done
fi
}
# TODO(vigneshv): Enable or remove this test and associated code.
DISABLED_aomdec_av1_webm_less_than_50_frames() {
# ensure that reaching eof in webm_guess_framerate doesn't result in invalid
# frames in actual webm_read_frame calls.
if [ "$(aomdec_can_decode_av1)" = "yes" ] && \
[ "$(webm_io_available)" = "yes" ]; then
local readonly decoder="$(aom_tool_path aomdec)"
local readonly expected=10
local readonly num_frames=$(${AOM_TEST_PREFIX} "${decoder}" \
"${AV1_LT_50_FRAMES_WEBM_FILE}" --summary --noblit 2>&1 \
| awk '/^[0-9]+ decoded frames/ { print $1 }')
if [ "$num_frames" -ne "$expected" ]; then
elog "Output frames ($num_frames) != expected ($expected)"
return 1
fi
fi
}
aomdec_tests="aomdec_av1_webm
aomdec_av1_webm_frame_parallel
aomdec_tests="aomdec_av1_ivf
aomdec_av1_ivf_error_resilient
aomdec_av1_ivf_multithread
aomdec_aom_ivf_pipe_input
DISABLED_aomdec_av1_webm_less_than_50_frames"
aomdec_av1_obu_annexb
aomdec_av1_obu_section5
aomdec_av1_webm"
run_tests aomdec_verify_environment "${aomdec_tests}"

View file

@ -15,8 +15,6 @@
##
. $(dirname $0)/tools_common.sh
readonly TEST_FRAMES=5
# Environment check: Make sure input is available.
aomenc_verify_environment() {
if [ ! -e "${YUV_RAW_INPUT}" ]; then
@ -57,32 +55,6 @@ y4m_input_720p() {
echo ""${Y4M_720P_INPUT}""
}
# Echo default aomenc real time encoding params. $1 is the codec, which defaults
# to av1 if unspecified.
aomenc_rt_params() {
local readonly codec="${1:-av1}"
echo "--codec=${codec}
--buf-initial-sz=500
--buf-optimal-sz=600
--buf-sz=1000
--cpu-used=-6
--end-usage=cbr
--error-resilient=1
--kf-max-dist=90000
--lag-in-frames=0
--max-intra-rate=300
--max-q=56
--min-q=2
--noise-sensitivity=0
--overshoot-pct=50
--passes=1
--profile=0
--resize-allowed=0
--rt
--static-thresh=0
--undershoot-pct=50"
}
# Wrapper function for running aomenc with pipe input. Requires that
# LIBAOM_BIN_PATH points to the directory containing aomenc. $1 is used as the
# input file path and shifted away. All remaining parameters are passed through
@ -110,10 +82,12 @@ aomenc() {
aomenc_av1_ivf() {
if [ "$(aomenc_can_encode_av1)" = "yes" ]; then
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1.ivf"
local output="${AV1_IVF_FILE}"
if [ -e "${AV1_IVF_FILE}" ]; then
output="${AOM_TEST_OUTPUT_DIR}/av1_test.ivf"
fi
aomenc $(yuv_raw_input) \
--codec=av1 \
--limit="${TEST_FRAMES}" \
$(aomenc_encode_test_fast_params) \
--ivf \
--output="${output}"
@ -124,13 +98,52 @@ aomenc_av1_ivf() {
fi
}
aomenc_av1_obu_annexb() {
if [ "$(aomenc_can_encode_av1)" = "yes" ]; then
local output="${AV1_OBU_ANNEXB_FILE}"
if [ -e "${AV1_OBU_ANNEXB_FILE}" ]; then
output="${AOM_TEST_OUTPUT_DIR}/av1_test.annexb.obu"
fi
aomenc $(yuv_raw_input) \
$(aomenc_encode_test_fast_params) \
--obu \
--annexb=1 \
--output="${output}"
if [ ! -e "${output}" ]; then
elog "Output file does not exist."
return 1
fi
fi
}
aomenc_av1_obu_section5() {
if [ "$(aomenc_can_encode_av1)" = "yes" ]; then
local output="${AV1_OBU_SEC5_FILE}"
if [ -e "${AV1_OBU_SEC5_FILE}" ]; then
output="${AOM_TEST_OUTPUT_DIR}/av1_test.section5.obu"
fi
aomenc $(yuv_raw_input) \
$(aomenc_encode_test_fast_params) \
--obu \
--output="${output}"
if [ ! -e "${output}" ]; then
elog "Output file does not exist."
return 1
fi
fi
}
aomenc_av1_webm() {
if [ "$(aomenc_can_encode_av1)" = "yes" ] && \
[ "$(webm_io_available)" = "yes" ]; then
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1.webm"
local output="${AV1_WEBM_FILE}"
if [ -e "${AV1_WEBM_FILE}" ]; then
output="${AOM_TEST_OUTPUT_DIR}/av1_test.webm"
fi
aomenc $(yuv_raw_input) \
--codec=av1 \
--limit="${TEST_FRAMES}" \
$(aomenc_encode_test_fast_params) \
--output="${output}"
if [ ! -e "${output}" ]; then
@ -140,15 +153,14 @@ aomenc_av1_webm() {
fi
}
aomenc_av1_webm_2pass() {
aomenc_av1_webm_1pass() {
if [ "$(aomenc_can_encode_av1)" = "yes" ] && \
[ "$(webm_io_available)" = "yes" ]; then
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1.webm"
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1_test.webm"
aomenc $(yuv_raw_input) \
--codec=av1 \
--limit="${TEST_FRAMES}" \
--output="${output}" \
--passes=2
$(aomenc_encode_test_fast_params) \
--passes=1 \
--output="${output}"
if [ ! -e "${output}" ]; then
elog "Output file does not exist."
@ -161,8 +173,7 @@ aomenc_av1_ivf_lossless() {
if [ "$(aomenc_can_encode_av1)" = "yes" ]; then
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1_lossless.ivf"
aomenc $(yuv_raw_input) \
--codec=av1 \
--limit="${TEST_FRAMES}" \
$(aomenc_encode_test_fast_params) \
--ivf \
--output="${output}" \
--lossless=1
@ -178,8 +189,7 @@ aomenc_av1_ivf_minq0_maxq0() {
if [ "$(aomenc_can_encode_av1)" = "yes" ]; then
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1_lossless_minq0_maxq0.ivf"
aomenc $(yuv_raw_input) \
--codec=av1 \
--limit="${TEST_FRAMES}" \
$(aomenc_encode_test_fast_params) \
--ivf \
--output="${output}" \
--min-q=0 \
@ -199,12 +209,10 @@ aomenc_av1_webm_lag5_frames10() {
local readonly lag_frames=5
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1_lag5_frames10.webm"
aomenc $(yuv_raw_input) \
--codec=av1 \
--limit="${lag_total_frames}" \
--lag-in-frames="${lag_frames}" \
--output="${output}" \
--passes=2 \
--auto-alt-ref=1
$(aomenc_encode_test_fast_params) \
--limit=${lag_total_frames} \
--lag-in-frames=${lag_frames} \
--output="${output}"
if [ ! -e "${output}" ]; then
elog "Output file does not exist."
@ -219,8 +227,7 @@ aomenc_av1_webm_non_square_par() {
[ "$(webm_io_available)" = "yes" ]; then
local readonly output="${AOM_TEST_OUTPUT_DIR}/av1_non_square_par.webm"
aomenc $(y4m_input_non_square_par) \
--codec=av1 \
--limit="${TEST_FRAMES}" \
$(aomenc_encode_test_fast_params) \
--output="${output}"
if [ ! -e "${output}" ]; then
@ -230,12 +237,33 @@ aomenc_av1_webm_non_square_par() {
fi
}
aomenc_av1_webm_cdf_update_mode() {
if [ "$(aomenc_can_encode_av1)" = "yes" ] && \
[ "$(webm_io_available)" = "yes" ]; then
for mode in 0 1 2; do
local readonly output="${AOM_TEST_OUTPUT_DIR}/cdf_mode_${mode}.webm"
aomenc $(yuv_raw_input) \
$(aomenc_encode_test_fast_params) \
--cdf-update-mode=${mode} \
--output="${output}"
if [ ! -e "${output}" ]; then
elog "Output file does not exist."
return 1
fi
done
fi
}
aomenc_tests="aomenc_av1_ivf
aomenc_av1_obu_annexb
aomenc_av1_obu_section5
aomenc_av1_webm
aomenc_av1_webm_2pass
aomenc_av1_webm_1pass
aomenc_av1_ivf_lossless
aomenc_av1_ivf_minq0_maxq0
aomenc_av1_webm_lag5_frames10
aomenc_av1_webm_non_square_par"
aomenc_av1_webm_non_square_par
aomenc_av1_webm_cdf_update_mode"
run_tests aomenc_verify_environment "${aomenc_tests}"

View file

@ -7,9 +7,10 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "config/aom_config.h"
#include "./aom_config.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
@ -37,18 +38,14 @@ class AqSegmentTest
if (video->frame() == 1) {
encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
encoder->Control(AV1E_SET_AQ_MODE, aq_mode_);
#if CONFIG_EXT_DELTA_Q
encoder->Control(AV1E_SET_DELTAQ_MODE, deltaq_mode_);
#endif
encoder->Control(AOME_SET_MAX_INTRA_BITRATE_PCT, 100);
}
}
void DoTest(int aq_mode) {
aq_mode_ = aq_mode;
#if CONFIG_EXT_DELTA_Q
deltaq_mode_ = 0;
#endif
cfg_.kf_max_dist = 12;
cfg_.rc_min_quantizer = 8;
cfg_.rc_max_quantizer = 56;
@ -65,9 +62,7 @@ class AqSegmentTest
int set_cpu_used_;
int aq_mode_;
#if CONFIG_EXT_DELTA_Q
int deltaq_mode_;
#endif
};
// Validate that this AQ segmentation mode (AQ=1, variance_ap)
@ -90,21 +85,6 @@ TEST_P(AqSegmentTestLarge, TestNoMisMatchAQ2) { DoTest(2); }
TEST_P(AqSegmentTestLarge, TestNoMisMatchAQ3) { DoTest(3); }
#if !CONFIG_EXT_DELTA_Q
// Validate that this AQ mode (AQ=4, delta q)
// encodes and decodes without a mismatch.
TEST_P(AqSegmentTest, TestNoMisMatchAQ4) {
cfg_.rc_end_usage = AOM_CQ;
aq_mode_ = 4;
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
30, 1, 0, 15);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
#endif
#if CONFIG_EXT_DELTA_Q
// Validate that this delta q mode
// encodes and decodes without a mismatch.
TEST_P(AqSegmentTest, TestNoMisMatchExtDeltaQ) {
@ -116,7 +96,6 @@ TEST_P(AqSegmentTest, TestNoMisMatchExtDeltaQ) {
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
#endif
AV1_INSTANTIATE_TEST_CASE(AqSegmentTest,
::testing::Values(::libaom_test::kRealTime,

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
@ -50,9 +50,7 @@ const TestVideoParam kTestVectors[] = {
{ "hantro_collage_w352h288.yuv", 352, 288, 30, 1, 8, AOM_IMG_FMT_I420,
AOM_BITS_8, 0 },
{ "rush_hour_444.y4m", 352, 288, 30, 1, 8, AOM_IMG_FMT_I444, AOM_BITS_8, 1 },
#if CONFIG_HIGHBITDEPTH
// Add list of profile 2/3 test videos here ...
#endif // CONFIG_HIGHBITDEPTH
// Add list of profile 2/3 test videos here ...
};
const TestEncodeParam kEncodeVectors[] = {
@ -208,7 +206,6 @@ TEST_P(ArfFreqTestLarge, MinArfFreqTest) {
}
}
#if CONFIG_HIGHBITDEPTH || CONFIG_EXT_REFS
#if CONFIG_AV1_ENCODER
// TODO(angiebird): 25-29 fail in high bitdepth mode.
// TODO(zoeliu): This ArfFreqTest does not work with BWDREF_FRAME, as
@ -223,9 +220,4 @@ INSTANTIATE_TEST_CASE_P(
::testing::ValuesIn(kTestVectors), ::testing::ValuesIn(kEncodeVectors),
::testing::ValuesIn(kMinArfVectors)));
#endif // CONFIG_AV1_ENCODER
#else
AV1_INSTANTIATE_TEST_CASE(ArfFreqTestLarge, ::testing::ValuesIn(kTestVectors),
::testing::ValuesIn(kEncodeVectors),
::testing::ValuesIn(kMinArfVectors));
#endif // CONFIG_HIGHBITDEPTH || CONFIG_EXT_REFS
} // namespace

View file

@ -12,29 +12,238 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/av1_convolve_2d_test_util.h"
using std::tr1::tuple;
using std::tr1::make_tuple;
using ::testing::make_tuple;
using ::testing::tuple;
using libaom_test::ACMRandom;
using libaom_test::AV1Convolve2D::AV1Convolve2DTest;
#if CONFIG_HIGHBITDEPTH
using libaom_test::AV1HighbdConvolve2D::AV1HighbdConvolve2DTest;
#endif
using libaom_test::AV1Convolve2D::AV1Convolve2DSrTest;
using libaom_test::AV1Convolve2D::AV1JntConvolve2DTest;
using libaom_test::AV1HighbdConvolve2D::AV1HighbdConvolve2DSrTest;
using libaom_test::AV1HighbdConvolve2D::AV1HighbdJntConvolve2DTest;
namespace {
TEST_P(AV1Convolve2DTest, CheckOutput) { RunCheckOutput(GET_PARAM(2)); }
TEST_P(AV1Convolve2DSrTest, DISABLED_Speed) { RunSpeedTest(GET_PARAM(0)); }
TEST_P(AV1Convolve2DSrTest, CheckOutput) { RunCheckOutput(GET_PARAM(0)); }
INSTANTIATE_TEST_CASE_P(
SSE2, AV1Convolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_2d_sse2));
C_COPY, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_2d_copy_sr_c, 0, 0));
INSTANTIATE_TEST_CASE_P(
C_X, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_x_sr_c, 1, 0));
INSTANTIATE_TEST_CASE_P(
C_Y, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_y_sr_c, 0, 1));
INSTANTIATE_TEST_CASE_P(
C, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_2d_sr_c, 1, 1));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2_COPY, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(
av1_convolve_2d_copy_sr_sse2, 0, 0));
INSTANTIATE_TEST_CASE_P(
SSE2_X, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_x_sr_sse2, 1, 0));
INSTANTIATE_TEST_CASE_P(
SSE2_Y, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_y_sr_sse2, 0, 1));
INSTANTIATE_TEST_CASE_P(
SSE2, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_2d_sr_sse2, 1, 1));
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(AVX2_COPY, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(
av1_convolve_2d_copy_sr_avx2, 0, 0));
INSTANTIATE_TEST_CASE_P(
AVX2_X, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_x_sr_avx2, 1, 0));
#if CONFIG_HIGHBITDEPTH && HAVE_SSSE3
TEST_P(AV1HighbdConvolve2DTest, CheckOutput) { RunCheckOutput(GET_PARAM(3)); }
INSTANTIATE_TEST_CASE_P(
AVX2_Y, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_y_sr_avx2, 0, 1));
INSTANTIATE_TEST_CASE_P(SSSE3, AV1HighbdConvolve2DTest,
INSTANTIATE_TEST_CASE_P(
AVX2, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_2d_sr_avx2, 1, 1));
#endif // HAVE_AVX2
#endif // HAVE_SSE2
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON_X, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_x_sr_neon, 1, 0));
INSTANTIATE_TEST_CASE_P(
NEON_Y, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_y_sr_neon, 0, 1));
INSTANTIATE_TEST_CASE_P(
NEON, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(av1_convolve_2d_sr_neon, 1, 1));
INSTANTIATE_TEST_CASE_P(NEON_COPY, AV1Convolve2DSrTest,
libaom_test::AV1Convolve2D::BuildParams(
av1_convolve_2d_copy_sr_neon, 0, 0));
#endif // HAVE_NEON
TEST_P(AV1JntConvolve2DTest, CheckOutput) { RunCheckOutput(GET_PARAM(0)); }
TEST_P(AV1JntConvolve2DTest, DISABLED_Speed) { RunSpeedTest(GET_PARAM(0)); }
INSTANTIATE_TEST_CASE_P(
C_COPY, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_2d_copy_c, 0, 0));
INSTANTIATE_TEST_CASE_P(
C_X, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_x_c, 1, 0));
INSTANTIATE_TEST_CASE_P(
C_Y, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_y_c, 0, 1));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2_COPY, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(
av1_jnt_convolve_2d_copy_sse2, 0, 0));
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE2_X, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_x_sse2, 1, 0));
INSTANTIATE_TEST_CASE_P(
SSE2_Y, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_y_sse2, 0, 1));
INSTANTIATE_TEST_CASE_P(
SSSE3, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_2d_ssse3, 1, 1));
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(AVX2_COPY, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(
av1_jnt_convolve_2d_copy_avx2, 0, 0));
INSTANTIATE_TEST_CASE_P(
AVX2_X, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_x_avx2, 1, 0));
INSTANTIATE_TEST_CASE_P(
AVX2_Y, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_y_avx2, 0, 1));
INSTANTIATE_TEST_CASE_P(
AVX2, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_2d_avx2, 1, 1));
#endif // HAVE_AVX2
#endif // HAVE_SSE4_1
#endif // HAVE_SSE2
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON_COPY, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(
av1_jnt_convolve_2d_copy_neon, 0, 0));
INSTANTIATE_TEST_CASE_P(
NEON, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_2d_neon, 1, 1));
INSTANTIATE_TEST_CASE_P(
NEON_X, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_x_neon, 1, 0));
INSTANTIATE_TEST_CASE_P(
NEON_Y, AV1JntConvolve2DTest,
libaom_test::AV1Convolve2D::BuildParams(av1_jnt_convolve_y_neon, 0, 1));
#endif // HAVE_NEON
TEST_P(AV1HighbdConvolve2DSrTest, CheckOutput) { RunCheckOutput(GET_PARAM(1)); }
TEST_P(AV1HighbdConvolve2DSrTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(1));
}
INSTANTIATE_TEST_CASE_P(C_X, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_2d_ssse3));
av1_highbd_convolve_x_sr_c, 1, 0));
#endif
INSTANTIATE_TEST_CASE_P(C_Y, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_y_sr_c, 0, 1));
INSTANTIATE_TEST_CASE_P(C_COPY, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_2d_copy_sr_c, 0, 0));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2_COPY, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_2d_copy_sr_sse2, 0, 0));
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_2d_sr_ssse3, 1, 1));
INSTANTIATE_TEST_CASE_P(SSSE3_X, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_x_sr_ssse3, 1, 0));
INSTANTIATE_TEST_CASE_P(SSSE3_Y, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_y_sr_ssse3, 0, 1));
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(AVX2, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_2d_sr_avx2, 1, 1));
INSTANTIATE_TEST_CASE_P(AVX2_X, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_x_sr_avx2, 1, 0));
INSTANTIATE_TEST_CASE_P(AVX2_Y, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_y_sr_avx2, 0, 1));
INSTANTIATE_TEST_CASE_P(AVX2_COPY, AV1HighbdConvolve2DSrTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_convolve_2d_copy_sr_avx2, 0, 0));
#endif // HAVE_AVX2
#endif // HAVE_SSSE3
#endif // HAVE_SSE2
TEST_P(AV1HighbdJntConvolve2DTest, CheckOutput) {
RunCheckOutput(GET_PARAM(1));
}
TEST_P(AV1HighbdJntConvolve2DTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(1));
}
INSTANTIATE_TEST_CASE_P(C_X, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_x_c, 1, 0));
INSTANTIATE_TEST_CASE_P(C_Y, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_y_c, 0, 1));
INSTANTIATE_TEST_CASE_P(C_COPY, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_2d_copy_c, 0, 0));
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1_COPY, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_2d_copy_sse4_1, 0, 0));
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_2d_sse4_1, 1, 1));
INSTANTIATE_TEST_CASE_P(SSE4_1_X, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_x_sse4_1, 1, 0));
INSTANTIATE_TEST_CASE_P(SSE4_1_Y, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_y_sse4_1, 0, 1));
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(AVX2_COPY, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_2d_copy_avx2, 0, 0));
INSTANTIATE_TEST_CASE_P(AVX2, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_2d_avx2, 1, 1));
INSTANTIATE_TEST_CASE_P(AVX2_X, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_x_avx2, 1, 0));
INSTANTIATE_TEST_CASE_P(AVX2_Y, AV1HighbdJntConvolve2DTest,
libaom_test::AV1HighbdConvolve2D::BuildParams(
av1_highbd_jnt_convolve_y_avx2, 0, 1));
#endif // HAVE_AVX2
#endif // HAVE_SSE4_1
} // namespace

View file

@ -11,183 +11,695 @@
#include "test/av1_convolve_2d_test_util.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/common_data.h"
#include "av1/common/convolve.h"
using std::tr1::tuple;
using std::tr1::make_tuple;
using ::testing::make_tuple;
using ::testing::tuple;
namespace libaom_test {
const int kMaxSize = 128 + 32; // padding
namespace AV1Convolve2D {
::testing::internal::ParamGenerator<Convolve2DParam> BuildParams(
convolve_2d_func filter) {
const Convolve2DParam params[] = {
make_tuple(4, 4, filter), make_tuple(8, 8, filter),
make_tuple(64, 64, filter), make_tuple(4, 16, filter),
make_tuple(32, 8, filter),
};
return ::testing::ValuesIn(params);
convolve_2d_func filter, int has_subx, int has_suby) {
return ::testing::Combine(::testing::Values(filter),
::testing::Values(has_subx),
::testing::Values(has_suby),
::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
}
AV1Convolve2DTest::~AV1Convolve2DTest() {}
void AV1Convolve2DTest::SetUp() { rnd_.Reset(ACMRandom::DeterministicSeed()); }
void AV1Convolve2DTest::TearDown() { libaom_test::ClearSystemState(); }
void AV1Convolve2DTest::RunCheckOutput(convolve_2d_func test_impl) {
const int w = 128, h = 128;
const int out_w = GET_PARAM(0), out_h = GET_PARAM(1);
int i, j, k;
uint8_t *input = new uint8_t[h * w];
int output_n = out_h * MAX_SB_SIZE;
CONV_BUF_TYPE *output = new CONV_BUF_TYPE[output_n];
CONV_BUF_TYPE *output2 = new CONV_BUF_TYPE[output_n];
for (i = 0; i < h; ++i)
for (j = 0; j < w; ++j) input[i * w + j] = rnd_.Rand8();
int hfilter, vfilter, subx, suby;
for (hfilter = EIGHTTAP_REGULAR; hfilter < INTERP_FILTERS_ALL; ++hfilter) {
for (vfilter = EIGHTTAP_REGULAR; vfilter < INTERP_FILTERS_ALL; ++vfilter) {
InterpFilterParams filter_params_x =
av1_get_interp_filter_params((InterpFilter)hfilter);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params((InterpFilter)vfilter);
const int do_average = rnd_.Rand8() & 1;
ConvolveParams conv_params1 =
get_conv_params_no_round(0, do_average, 0, output, MAX_SB_SIZE);
ConvolveParams conv_params2 =
get_conv_params_no_round(0, do_average, 0, output2, MAX_SB_SIZE);
for (subx = 0; subx < 16; ++subx)
for (suby = 0; suby < 16; ++suby) {
// av1_convolve_2d is designed for accumulate two predicted blocks for
// compound mode, so we set num_iter to two here.
// A larger number may introduce overflow
const int num_iters = 2;
memset(output, 0, output_n * sizeof(*output));
memset(output2, 0, output_n * sizeof(*output2));
for (i = 0; i < num_iters; ++i) {
// Choose random locations within the source block
int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_convolve_2d_c(input + offset_r * w + offset_c, w, output,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params1);
test_impl(input + offset_r * w + offset_c, w, output2, MAX_SB_SIZE,
out_w, out_h, &filter_params_x, &filter_params_y, subx,
suby, &conv_params2);
for (j = 0; j < out_h; ++j)
for (k = 0; k < out_w; ++k) {
int idx = j * MAX_SB_SIZE + k;
ASSERT_EQ(output[idx], output2[idx])
<< "Pixel mismatch at index " << idx << " = (" << j << ", "
<< k << "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
}
}
}
delete[] input;
delete[] output;
delete[] output2;
}
} // namespace AV1Convolve2D
#if CONFIG_HIGHBITDEPTH
namespace AV1HighbdConvolve2D {
::testing::internal::ParamGenerator<HighbdConvolve2DParam> BuildParams(
highbd_convolve_2d_func filter) {
const HighbdConvolve2DParam params[] = {
make_tuple(4, 4, 8, filter), make_tuple(8, 8, 8, filter),
make_tuple(64, 64, 8, filter), make_tuple(4, 16, 8, filter),
make_tuple(32, 8, 8, filter), make_tuple(4, 4, 10, filter),
make_tuple(8, 8, 10, filter), make_tuple(64, 64, 10, filter),
make_tuple(4, 16, 10, filter), make_tuple(32, 8, 10, filter),
make_tuple(4, 4, 12, filter), make_tuple(8, 8, 12, filter),
make_tuple(64, 64, 12, filter), make_tuple(4, 16, 12, filter),
make_tuple(32, 8, 12, filter),
};
return ::testing::ValuesIn(params);
}
AV1HighbdConvolve2DTest::~AV1HighbdConvolve2DTest() {}
void AV1HighbdConvolve2DTest::SetUp() {
AV1Convolve2DSrTest::~AV1Convolve2DSrTest() {}
void AV1Convolve2DSrTest::SetUp() {
rnd_.Reset(ACMRandom::DeterministicSeed());
}
void AV1HighbdConvolve2DTest::TearDown() { libaom_test::ClearSystemState(); }
void AV1HighbdConvolve2DTest::RunCheckOutput(
highbd_convolve_2d_func test_impl) {
const int w = 128, h = 128;
const int out_w = GET_PARAM(0), out_h = GET_PARAM(1);
const int bd = GET_PARAM(2);
int i, j, k;
uint16_t *input = new uint16_t[h * w];
int output_n = out_h * MAX_SB_SIZE;
CONV_BUF_TYPE *output = new CONV_BUF_TYPE[output_n];
CONV_BUF_TYPE *output2 = new CONV_BUF_TYPE[output_n];
for (i = 0; i < h; ++i)
for (j = 0; j < w; ++j) input[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
void AV1Convolve2DSrTest::TearDown() { libaom_test::ClearSystemState(); }
void AV1Convolve2DSrTest::RunCheckOutput(convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int has_subx = GET_PARAM(1);
const int has_suby = GET_PARAM(2);
const int block_idx = GET_PARAM(3);
int hfilter, vfilter, subx, suby;
uint8_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, uint8_t, output[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, uint8_t, output2[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) input[i * w + j] = rnd_.Rand8();
for (int i = 0; i < MAX_SB_SQUARE; ++i)
output[i] = output2[i] = rnd_.Rand31();
// Make sure that sizes 2xN and Nx2 are also tested for chroma.
const int num_sizes =
(block_size_wide[block_idx] == 4 || block_size_high[block_idx] == 4) ? 2
: 1;
for (int shift = 0; shift < num_sizes; ++shift) { // luma and chroma
const int out_w = block_size_wide[block_idx] >> shift;
const int out_h = block_size_high[block_idx] >> shift;
for (hfilter = EIGHTTAP_REGULAR; hfilter < INTERP_FILTERS_ALL; ++hfilter) {
for (vfilter = EIGHTTAP_REGULAR; vfilter < INTERP_FILTERS_ALL;
++vfilter) {
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
for (int do_average = 0; do_average < 1; ++do_average) {
ConvolveParams conv_params1 =
get_conv_params_no_round(0, do_average, 0, NULL, 0, 0, 8);
ConvolveParams conv_params2 =
get_conv_params_no_round(0, do_average, 0, NULL, 0, 0, 8);
const int subx_range = has_subx ? 16 : 1;
const int suby_range = has_suby ? 16 : 1;
for (subx = 0; subx < subx_range; ++subx) {
for (suby = 0; suby < suby_range; ++suby) {
// Choose random locations within the source block
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_convolve_2d_sr_c(input + offset_r * w + offset_c, w, output,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params1);
test_impl(input + offset_r * w + offset_c, w, output2,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2);
if (memcmp(output, output2, sizeof(output))) {
for (int i = 0; i < MAX_SB_SIZE; ++i) {
for (int j = 0; j < MAX_SB_SIZE; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output[idx], output2[idx])
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
}
}
}
}
}
}
}
}
void AV1Convolve2DSrTest::RunSpeedTest(convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int has_subx = GET_PARAM(1);
const int has_suby = GET_PARAM(2);
const int block_idx = GET_PARAM(3);
uint8_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, uint8_t, output[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) input[i * w + j] = rnd_.Rand8();
int hfilter = EIGHTTAP_REGULAR, vfilter = EIGHTTAP_REGULAR;
int subx = 0, suby = 0;
const int do_average = 0;
ConvolveParams conv_params2 =
get_conv_params_no_round(0, do_average, 0, NULL, 0, 0, 8);
// Make sure that sizes 2xN and Nx2 are also tested for chroma.
const int num_sizes =
(block_size_wide[block_idx] == 4 || block_size_high[block_idx] == 4) ? 2
: 1;
for (int shift = 0; shift < num_sizes; ++shift) { // luma and chroma
const int out_w = block_size_wide[block_idx] >> shift;
const int out_h = block_size_high[block_idx] >> shift;
const int num_loops = 1000000000 / (out_w + out_h);
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
test_impl(input, w, output, MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("%d,%d convolve %3dx%-3d: %7.2f us\n", has_subx, has_suby, out_w,
out_h, 1000.0 * elapsed_time / num_loops);
}
}
AV1JntConvolve2DTest::~AV1JntConvolve2DTest() {}
void AV1JntConvolve2DTest::SetUp() {
rnd_.Reset(ACMRandom::DeterministicSeed());
}
void AV1JntConvolve2DTest::TearDown() { libaom_test::ClearSystemState(); }
void AV1JntConvolve2DTest::RunCheckOutput(convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int has_subx = GET_PARAM(1);
const int has_suby = GET_PARAM(2);
const int block_idx = GET_PARAM(3);
int hfilter, vfilter, subx, suby;
uint8_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, CONV_BUF_TYPE, output1[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, CONV_BUF_TYPE, output2[MAX_SB_SQUARE]);
DECLARE_ALIGNED(16, uint8_t, output8_1[MAX_SB_SQUARE]);
DECLARE_ALIGNED(16, uint8_t, output8_2[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) input[i * w + j] = rnd_.Rand8();
for (int i = 0; i < MAX_SB_SQUARE; ++i) {
output1[i] = output2[i] = rnd_.Rand16();
output8_1[i] = output8_2[i] = rnd_.Rand8();
}
const int out_w = block_size_wide[block_idx];
const int out_h = block_size_high[block_idx];
for (hfilter = EIGHTTAP_REGULAR; hfilter < INTERP_FILTERS_ALL; ++hfilter) {
for (vfilter = EIGHTTAP_REGULAR; vfilter < INTERP_FILTERS_ALL; ++vfilter) {
InterpFilterParams filter_params_x =
av1_get_interp_filter_params((InterpFilter)hfilter);
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params((InterpFilter)vfilter);
ConvolveParams conv_params1 =
get_conv_params_no_round(0, 0, 0, output, MAX_SB_SIZE);
ConvolveParams conv_params2 =
get_conv_params_no_round(0, 0, 0, output2, MAX_SB_SIZE);
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
for (int do_average = 0; do_average <= 1; ++do_average) {
ConvolveParams conv_params1 = get_conv_params_no_round(
0, do_average, 0, output1, MAX_SB_SIZE, 1, 8);
ConvolveParams conv_params2 = get_conv_params_no_round(
0, do_average, 0, output2, MAX_SB_SIZE, 1, 8);
for (subx = 0; subx < 16; ++subx)
for (suby = 0; suby < 16; ++suby) {
// av1_convolve_2d is designed for accumulate two predicted blocks for
// compound mode, so we set num_iter to two here.
// A larger number may introduce overflow
const int num_iters = 2;
memset(output, 0, output_n * sizeof(*output));
memset(output2, 0, output_n * sizeof(*output2));
for (i = 0; i < num_iters; ++i) {
// Test special case where jnt_comp_avg is not used
conv_params1.use_jnt_comp_avg = 0;
conv_params2.use_jnt_comp_avg = 0;
const int subx_range = has_subx ? 16 : 1;
const int suby_range = has_suby ? 16 : 1;
for (subx = 0; subx < subx_range; ++subx) {
for (suby = 0; suby < suby_range; ++suby) {
// Choose random locations within the source block
int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_highbd_convolve_2d_c(input + offset_r * w + offset_c, w, output,
MAX_SB_SIZE, out_w, out_h,
&filter_params_x, &filter_params_y, subx,
suby, &conv_params1, bd);
test_impl(input + offset_r * w + offset_c, w, output2, MAX_SB_SIZE,
out_w, out_h, &filter_params_x, &filter_params_y, subx,
suby, &conv_params2, bd);
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_jnt_convolve_2d_c(input + offset_r * w + offset_c, w, output8_1,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params1);
test_impl(input + offset_r * w + offset_c, w, output8_2,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2);
for (j = 0; j < out_h; ++j)
for (k = 0; k < out_w; ++k) {
int idx = j * MAX_SB_SIZE + k;
ASSERT_EQ(output[idx], output2[idx])
<< "Pixel mismatch at index " << idx << " = (" << j << ", "
<< k << "), sub pixel offset = (" << suby << ", " << subx
<< ")";
for (int i = 0; i < out_h; ++i) {
for (int j = 0; j < out_w; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output1[idx], output2[idx])
<< "Mismatch at unit tests for av1_jnt_convolve_2d\n"
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx << ")";
}
}
if (memcmp(output8_1, output8_2, sizeof(output8_1))) {
for (int i = 0; i < MAX_SB_SIZE; ++i) {
for (int j = 0; j < MAX_SB_SIZE; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output8_1[idx], output8_2[idx])
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
}
}
}
// Test different combination of fwd and bck offset weights
for (int k = 0; k < 2; ++k) {
for (int l = 0; l < 4; ++l) {
conv_params1.use_jnt_comp_avg = 1;
conv_params2.use_jnt_comp_avg = 1;
conv_params1.fwd_offset = quant_dist_lookup_table[k][l][0];
conv_params1.bck_offset = quant_dist_lookup_table[k][l][1];
conv_params2.fwd_offset = quant_dist_lookup_table[k][l][0];
conv_params2.bck_offset = quant_dist_lookup_table[k][l][1];
for (subx = 0; subx < subx_range; ++subx) {
for (suby = 0; suby < suby_range; ++suby) {
// Choose random locations within the source block
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_jnt_convolve_2d_c(input + offset_r * w + offset_c, w,
output8_1, MAX_SB_SIZE, out_w, out_h,
&filter_params_x, &filter_params_y, subx,
suby, &conv_params1);
test_impl(input + offset_r * w + offset_c, w, output8_2,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2);
for (int i = 0; i < out_h; ++i) {
for (int j = 0; j < out_w; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output1[idx], output2[idx])
<< "Mismatch at unit tests for "
"av1_jnt_convolve_2d\n"
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
if (memcmp(output8_1, output8_2, sizeof(output8_1))) {
for (int i = 0; i < MAX_SB_SIZE; ++i) {
for (int j = 0; j < MAX_SB_SIZE; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output8_1[idx], output8_2[idx])
<< out_w << "x" << out_h
<< " Pixel mismatch at index " << idx << " = (" << i
<< ", " << j << "), sub pixel offset = (" << suby
<< ", " << subx << ")";
}
}
}
}
}
}
}
}
}
}
}
void AV1JntConvolve2DTest::RunSpeedTest(convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int has_subx = GET_PARAM(1);
const int has_suby = GET_PARAM(2);
const int block_idx = GET_PARAM(3);
int subx = 0, suby = 0;
uint8_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, CONV_BUF_TYPE, output[MAX_SB_SQUARE]);
DECLARE_ALIGNED(16, uint8_t, output8[MAX_SB_SQUARE]);
int hfilter = EIGHTTAP_REGULAR, vfilter = EIGHTTAP_REGULAR;
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) input[i * w + j] = rnd_.Rand8();
for (int i = 0; i < MAX_SB_SQUARE; ++i) {
output[i] = rnd_.Rand16();
output8[i] = rnd_.Rand8();
}
const int out_w = block_size_wide[block_idx];
const int out_h = block_size_high[block_idx];
const int num_loops = 1000000000 / (out_w + out_h);
const int do_average = 0;
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
ConvolveParams conv_params =
get_conv_params_no_round(0, do_average, 0, output, MAX_SB_SIZE, 1, 8);
conv_params.use_jnt_comp_avg = 0;
// Choose random locations within the source block
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
test_impl(input + offset_r * w + offset_c, w, output8, MAX_SB_SIZE, out_w,
out_h, &filter_params_x, &filter_params_y, subx, suby,
&conv_params);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("%d,%d convolve %3dx%-3d: %7.2f us\n", has_subx, has_suby, out_w,
out_h, 1000.0 * elapsed_time / num_loops);
}
} // namespace AV1Convolve2D
namespace AV1HighbdConvolve2D {
::testing::internal::ParamGenerator<HighbdConvolve2DParam> BuildParams(
highbd_convolve_2d_func filter, int has_subx, int has_suby) {
return ::testing::Combine(
::testing::Range(8, 13, 2), ::testing::Values(filter),
::testing::Values(has_subx), ::testing::Values(has_suby),
::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
}
AV1HighbdConvolve2DSrTest::~AV1HighbdConvolve2DSrTest() {}
void AV1HighbdConvolve2DSrTest::SetUp() {
rnd_.Reset(ACMRandom::DeterministicSeed());
}
void AV1HighbdConvolve2DSrTest::TearDown() { libaom_test::ClearSystemState(); }
void AV1HighbdConvolve2DSrTest::RunSpeedTest(
highbd_convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int bd = GET_PARAM(0);
const int has_subx = GET_PARAM(2);
const int has_suby = GET_PARAM(3);
const int block_idx = GET_PARAM(4);
int hfilter, vfilter, subx, suby;
uint16_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, uint16_t, output[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
input[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
hfilter = EIGHTTAP_REGULAR;
vfilter = EIGHTTAP_REGULAR;
int do_average = 0;
const int offset_r = 3;
const int offset_c = 3;
subx = 0;
suby = 0;
ConvolveParams conv_params =
get_conv_params_no_round(0, do_average, 0, NULL, 0, 0, bd);
// Make sure that sizes 2xN and Nx2 are also tested for chroma.
const int num_sizes =
(block_size_wide[block_idx] == 4 || block_size_high[block_idx] == 4) ? 2
: 1;
for (int shift = 0; shift < num_sizes; ++shift) { // luma and chroma
const int out_w = block_size_wide[block_idx] >> shift;
const int out_h = block_size_high[block_idx] >> shift;
const int num_loops = 1000000000 / (out_w + out_h);
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
test_impl(input + offset_r * w + offset_c, w, output, MAX_SB_SIZE, out_w,
out_h, &filter_params_x, &filter_params_y, subx, suby,
&conv_params, bd);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("%d,%d convolve %3dx%-3d: %7.2f us\n", has_subx, has_suby, out_w,
out_h, 1000.0 * elapsed_time / num_loops);
}
}
void AV1HighbdConvolve2DSrTest::RunCheckOutput(
highbd_convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int bd = GET_PARAM(0);
const int has_subx = GET_PARAM(2);
const int has_suby = GET_PARAM(3);
const int block_idx = GET_PARAM(4);
int hfilter, vfilter, subx, suby;
uint16_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, uint16_t, output[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, uint16_t, output2[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
input[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
for (int i = 0; i < MAX_SB_SQUARE; ++i)
output[i] = output2[i] = rnd_.Rand31();
// Make sure that sizes 2xN and Nx2 are also tested for chroma.
const int num_sizes =
(block_size_wide[block_idx] == 4 || block_size_high[block_idx] == 4) ? 2
: 1;
for (int shift = 0; shift < num_sizes; ++shift) { // luma and chroma
const int out_w = block_size_wide[block_idx] >> shift;
const int out_h = block_size_high[block_idx] >> shift;
for (hfilter = EIGHTTAP_REGULAR; hfilter < INTERP_FILTERS_ALL; ++hfilter) {
for (vfilter = EIGHTTAP_REGULAR; vfilter < INTERP_FILTERS_ALL;
++vfilter) {
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
for (int do_average = 0; do_average < 1; ++do_average) {
ConvolveParams conv_params1 =
get_conv_params_no_round(0, do_average, 0, NULL, 0, 0, bd);
ConvolveParams conv_params2 =
get_conv_params_no_round(0, do_average, 0, NULL, 0, 0, bd);
const int subx_range = has_subx ? 16 : 1;
const int suby_range = has_suby ? 16 : 1;
for (subx = 0; subx < subx_range; ++subx) {
for (suby = 0; suby < suby_range; ++suby) {
// Choose random locations within the source block
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_highbd_convolve_2d_sr_c(input + offset_r * w + offset_c, w,
output, MAX_SB_SIZE, out_w, out_h,
&filter_params_x, &filter_params_y,
subx, suby, &conv_params1, bd);
test_impl(input + offset_r * w + offset_c, w, output2,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2, bd);
if (memcmp(output, output2, sizeof(output))) {
for (int i = 0; i < MAX_SB_SIZE; ++i) {
for (int j = 0; j < MAX_SB_SIZE; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output[idx], output2[idx])
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
}
}
}
}
}
}
}
}
AV1HighbdJntConvolve2DTest::~AV1HighbdJntConvolve2DTest() {}
void AV1HighbdJntConvolve2DTest::SetUp() {
rnd_.Reset(ACMRandom::DeterministicSeed());
}
void AV1HighbdJntConvolve2DTest::TearDown() { libaom_test::ClearSystemState(); }
void AV1HighbdJntConvolve2DTest::RunSpeedTest(
highbd_convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int bd = GET_PARAM(0);
const int block_idx = GET_PARAM(4);
int hfilter, vfilter, subx, suby;
uint16_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, CONV_BUF_TYPE, output[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, uint16_t, output16[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
input[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
for (int i = 0; i < MAX_SB_SQUARE; ++i) output[i] = rnd_.Rand16();
hfilter = EIGHTTAP_REGULAR;
vfilter = EIGHTTAP_REGULAR;
int do_average = 0;
const int out_w = block_size_wide[block_idx];
const int out_h = block_size_high[block_idx];
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
ConvolveParams conv_params =
get_conv_params_no_round(0, do_average, 0, output, MAX_SB_SIZE, 1, bd);
// Test special case where jnt_comp_avg is not used
conv_params.use_jnt_comp_avg = 0;
subx = 0;
suby = 0;
// Choose random locations within the source block
const int offset_r = 3;
const int offset_c = 3;
const int num_loops = 1000000000 / (out_w + out_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
test_impl(input + offset_r * w + offset_c, w, output16, MAX_SB_SIZE, out_w,
out_h, &filter_params_x, &filter_params_y, subx, suby,
&conv_params, bd);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("convolve %3dx%-3d: %7.2f us\n", out_w, out_h,
1000.0 * elapsed_time / num_loops);
}
void AV1HighbdJntConvolve2DTest::RunCheckOutput(
highbd_convolve_2d_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int bd = GET_PARAM(0);
const int has_subx = GET_PARAM(2);
const int has_suby = GET_PARAM(3);
const int block_idx = GET_PARAM(4);
int hfilter, vfilter, subx, suby;
uint16_t input[kMaxSize * kMaxSize];
DECLARE_ALIGNED(32, CONV_BUF_TYPE, output1[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, CONV_BUF_TYPE, output2[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, uint16_t, output16_1[MAX_SB_SQUARE]);
DECLARE_ALIGNED(32, uint16_t, output16_2[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
input[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
for (int i = 0; i < MAX_SB_SQUARE; ++i) {
output1[i] = output2[i] = rnd_.Rand16();
output16_1[i] = output16_2[i] = rnd_.Rand16();
}
const int out_w = block_size_wide[block_idx];
const int out_h = block_size_high[block_idx];
for (hfilter = EIGHTTAP_REGULAR; hfilter < INTERP_FILTERS_ALL; ++hfilter) {
for (vfilter = EIGHTTAP_REGULAR; vfilter < INTERP_FILTERS_ALL; ++vfilter) {
InterpFilterParams filter_params_x =
av1_get_interp_filter_params_with_block_size((InterpFilter)hfilter,
out_w);
InterpFilterParams filter_params_y =
av1_get_interp_filter_params_with_block_size((InterpFilter)vfilter,
out_h);
for (int do_average = 0; do_average <= 1; ++do_average) {
ConvolveParams conv_params1 = get_conv_params_no_round(
0, do_average, 0, output1, MAX_SB_SIZE, 1, bd);
ConvolveParams conv_params2 = get_conv_params_no_round(
0, do_average, 0, output2, MAX_SB_SIZE, 1, bd);
// Test special case where jnt_comp_avg is not used
conv_params1.use_jnt_comp_avg = 0;
conv_params2.use_jnt_comp_avg = 0;
const int subx_range = has_subx ? 16 : 1;
const int suby_range = has_suby ? 16 : 1;
for (subx = 0; subx < subx_range; ++subx) {
for (suby = 0; suby < suby_range; ++suby) {
// Choose random locations within the source block
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_highbd_jnt_convolve_2d_c(input + offset_r * w + offset_c, w,
output16_1, MAX_SB_SIZE, out_w, out_h,
&filter_params_x, &filter_params_y,
subx, suby, &conv_params1, bd);
test_impl(input + offset_r * w + offset_c, w, output16_2,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2, bd);
for (int i = 0; i < out_h; ++i) {
for (int j = 0; j < out_w; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output1[idx], output2[idx])
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx << ")";
}
}
if (memcmp(output16_1, output16_2, sizeof(output16_1))) {
for (int i = 0; i < MAX_SB_SIZE; ++i) {
for (int j = 0; j < MAX_SB_SIZE; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output16_1[idx], output16_2[idx])
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
}
}
}
// Test different combination of fwd and bck offset weights
for (int k = 0; k < 2; ++k) {
for (int l = 0; l < 4; ++l) {
conv_params1.use_jnt_comp_avg = 1;
conv_params2.use_jnt_comp_avg = 1;
conv_params1.fwd_offset = quant_dist_lookup_table[k][l][0];
conv_params1.bck_offset = quant_dist_lookup_table[k][l][1];
conv_params2.fwd_offset = quant_dist_lookup_table[k][l][0];
conv_params2.bck_offset = quant_dist_lookup_table[k][l][1];
const int subx_range = has_subx ? 16 : 1;
const int suby_range = has_suby ? 16 : 1;
for (subx = 0; subx < subx_range; ++subx) {
for (suby = 0; suby < suby_range; ++suby) {
// Choose random locations within the source block
const int offset_r = 3 + rnd_.PseudoUniform(h - out_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - out_w - 7);
av1_highbd_jnt_convolve_2d_c(
input + offset_r * w + offset_c, w, output16_1, MAX_SB_SIZE,
out_w, out_h, &filter_params_x, &filter_params_y, subx,
suby, &conv_params1, bd);
test_impl(input + offset_r * w + offset_c, w, output16_2,
MAX_SB_SIZE, out_w, out_h, &filter_params_x,
&filter_params_y, subx, suby, &conv_params2, bd);
for (int i = 0; i < out_h; ++i) {
for (int j = 0; j < out_w; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output1[idx], output2[idx])
<< out_w << "x" << out_h << " Pixel mismatch at index "
<< idx << " = (" << i << ", " << j
<< "), sub pixel offset = (" << suby << ", " << subx
<< ")";
}
}
if (memcmp(output16_1, output16_2, sizeof(output16_1))) {
for (int i = 0; i < MAX_SB_SIZE; ++i) {
for (int j = 0; j < MAX_SB_SIZE; ++j) {
int idx = i * MAX_SB_SIZE + j;
ASSERT_EQ(output16_1[idx], output16_2[idx])
<< out_w << "x" << out_h
<< " Pixel mismatch at index " << idx << " = (" << i
<< ", " << j << "), sub pixel offset = (" << suby
<< ", " << subx << ")";
}
}
}
}
}
}
}
}
}
}
delete[] input;
delete[] output;
delete[] output2;
}
} // namespace AV1HighbdConvolve2D
#endif // CONFIG_HIGHBITDEPTH
} // namespace libaom_test

View file

@ -12,11 +12,13 @@
#ifndef TEST_HIPREC_CONVOLVE_TEST_UTIL_H_
#define TEST_HIPREC_CONVOLVE_TEST_UTIL_H_
#include "config/av1_rtcd.h"
#include "config/aom_dsp_rtcd.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
@ -25,62 +27,90 @@ namespace libaom_test {
namespace AV1Convolve2D {
typedef void (*convolve_2d_func)(const uint8_t *src, int src_stride,
CONV_BUF_TYPE *dst, int dst_stride, int w,
int h, InterpFilterParams *filter_params_x,
uint8_t *dst, int dst_stride, int w, int h,
InterpFilterParams *filter_params_x,
InterpFilterParams *filter_params_y,
const int subpel_x_q4, const int subpel_y_q4,
ConvolveParams *conv_params);
typedef std::tr1::tuple<int, int, convolve_2d_func> Convolve2DParam;
typedef ::testing::tuple<convolve_2d_func, int, int, BLOCK_SIZE>
Convolve2DParam;
::testing::internal::ParamGenerator<Convolve2DParam> BuildParams(
convolve_2d_func filter);
convolve_2d_func filter, int subx_exist, int suby_exist);
class AV1Convolve2DTest : public ::testing::TestWithParam<Convolve2DParam> {
class AV1Convolve2DSrTest : public ::testing::TestWithParam<Convolve2DParam> {
public:
virtual ~AV1Convolve2DTest();
virtual ~AV1Convolve2DSrTest();
virtual void SetUp();
virtual void TearDown();
protected:
void RunCheckOutput(convolve_2d_func test_impl);
void RunSpeedTest(convolve_2d_func test_impl);
libaom_test::ACMRandom rnd_;
};
class AV1JntConvolve2DTest : public ::testing::TestWithParam<Convolve2DParam> {
public:
virtual ~AV1JntConvolve2DTest();
virtual void SetUp();
virtual void TearDown();
protected:
void RunCheckOutput(convolve_2d_func test_impl);
void RunSpeedTest(convolve_2d_func test_impl);
libaom_test::ACMRandom rnd_;
};
} // namespace AV1Convolve2D
#if CONFIG_HIGHBITDEPTH
namespace AV1HighbdConvolve2D {
typedef void (*highbd_convolve_2d_func)(
const uint16_t *src, int src_stride, CONV_BUF_TYPE *dst, int dst_stride,
int w, int h, InterpFilterParams *filter_params_x,
const uint16_t *src, int src_stride, uint16_t *dst, int dst_stride, int w,
int h, InterpFilterParams *filter_params_x,
InterpFilterParams *filter_params_y, const int subpel_x_q4,
const int subpel_y_q4, ConvolveParams *conv_params, int bd);
typedef std::tr1::tuple<int, int, int, highbd_convolve_2d_func>
typedef ::testing::tuple<int, highbd_convolve_2d_func, int, int, BLOCK_SIZE>
HighbdConvolve2DParam;
::testing::internal::ParamGenerator<HighbdConvolve2DParam> BuildParams(
highbd_convolve_2d_func filter);
highbd_convolve_2d_func filter, int subx_exist, int suby_exist);
class AV1HighbdConvolve2DTest
class AV1HighbdConvolve2DSrTest
: public ::testing::TestWithParam<HighbdConvolve2DParam> {
public:
virtual ~AV1HighbdConvolve2DTest();
virtual ~AV1HighbdConvolve2DSrTest();
virtual void SetUp();
virtual void TearDown();
protected:
void RunCheckOutput(highbd_convolve_2d_func test_impl);
void RunSpeedTest(highbd_convolve_2d_func test_impl);
libaom_test::ACMRandom rnd_;
};
class AV1HighbdJntConvolve2DTest
: public ::testing::TestWithParam<HighbdConvolve2DParam> {
public:
virtual ~AV1HighbdJntConvolve2DTest();
virtual void SetUp();
virtual void TearDown();
protected:
void RunCheckOutput(highbd_convolve_2d_func test_impl);
void RunSpeedTest(highbd_convolve_2d_func test_impl);
libaom_test::ACMRandom rnd_;
};
} // namespace AV1HighbdConvolve2D
#endif // CONFIG_HIGHBITDEPTH
} // namespace libaom_test

View file

@ -1,405 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
namespace {
using std::tr1::tuple;
using libaom_test::ACMRandom;
typedef void (*ConvInit)();
typedef void (*conv_filter_t)(const uint8_t *, int, uint8_t *, int, int, int,
const InterpFilterParams, int, int,
ConvolveParams *);
#if CONFIG_HIGHBITDEPTH
typedef void (*hbd_conv_filter_t)(const uint16_t *, int, uint16_t *, int, int,
int, const InterpFilterParams, int, int, int,
int);
#endif
// Test parameter list:
// <convolve_horiz_func, convolve_vert_func,
// <width, height>, filter_params, subpel_x_q4, avg>
typedef tuple<int, int> BlockDimension;
typedef tuple<ConvInit, conv_filter_t, conv_filter_t, BlockDimension,
InterpFilter, int, int>
ConvParams;
#if CONFIG_HIGHBITDEPTH
// Test parameter list:
// <convolve_horiz_func, convolve_vert_func,
// <width, height>, filter_params, subpel_x_q4, avg, bit_dpeth>
typedef tuple<ConvInit, hbd_conv_filter_t, hbd_conv_filter_t, BlockDimension,
InterpFilter, int, int, int>
HbdConvParams;
#endif
// Note:
// src_ and src_ref_ have special boundary requirement
// dst_ and dst_ref_ don't
const size_t maxWidth = 256;
const size_t maxHeight = 256;
const size_t maxBlockSize = maxWidth * maxHeight;
const int horizOffset = 32;
const int vertiOffset = 32;
const int stride = 128;
const int x_step_q4 = 16;
class AV1ConvolveOptimzTest : public ::testing::TestWithParam<ConvParams> {
public:
virtual ~AV1ConvolveOptimzTest() {}
virtual void SetUp() {
ConvInit conv_init = GET_PARAM(0);
conv_init();
conv_horiz_ = GET_PARAM(1);
conv_vert_ = GET_PARAM(2);
BlockDimension block = GET_PARAM(3);
width_ = std::tr1::get<0>(block);
height_ = std::tr1::get<1>(block);
filter_ = GET_PARAM(4);
subpel_ = GET_PARAM(5);
int ref = GET_PARAM(6);
const int plane = 0;
conv_params_ = get_conv_params(ref, ref, plane);
alloc_ = new uint8_t[maxBlockSize * 4];
src_ = alloc_ + (vertiOffset * maxWidth);
src_ += horizOffset;
src_ref_ = src_ + maxBlockSize;
dst_ = alloc_ + 2 * maxBlockSize;
dst_ref_ = alloc_ + 3 * maxBlockSize;
}
virtual void TearDown() {
delete[] alloc_;
libaom_test::ClearSystemState();
}
protected:
void RunHorizFilterBitExactCheck();
void RunVertFilterBitExactCheck();
private:
void PrepFilterBuffer();
void DiffFilterBuffer();
conv_filter_t conv_horiz_;
conv_filter_t conv_vert_;
uint8_t *alloc_;
uint8_t *src_;
uint8_t *dst_;
uint8_t *src_ref_;
uint8_t *dst_ref_;
int width_;
int height_;
InterpFilter filter_;
int subpel_;
ConvolveParams conv_params_;
};
void AV1ConvolveOptimzTest::PrepFilterBuffer() {
int r, c;
ACMRandom rnd(ACMRandom::DeterministicSeed());
memset(alloc_, 0, 4 * maxBlockSize * sizeof(alloc_[0]));
uint8_t *src_ptr = src_;
uint8_t *dst_ptr = dst_;
uint8_t *src_ref_ptr = src_ref_;
uint8_t *dst_ref_ptr = dst_ref_;
for (r = 0; r < height_; ++r) {
for (c = 0; c < width_; ++c) {
src_ptr[c] = rnd.Rand8();
src_ref_ptr[c] = src_ptr[c];
dst_ptr[c] = rnd.Rand8();
dst_ref_ptr[c] = dst_ptr[c];
}
src_ptr += stride;
src_ref_ptr += stride;
dst_ptr += stride;
dst_ref_ptr += stride;
}
}
void AV1ConvolveOptimzTest::DiffFilterBuffer() {
int r, c;
const uint8_t *dst_ptr = dst_;
const uint8_t *dst_ref_ptr = dst_ref_;
for (r = 0; r < height_; ++r) {
for (c = 0; c < width_; ++c) {
EXPECT_EQ((uint8_t)dst_ref_ptr[c], (uint8_t)dst_ptr[c])
<< "Error at row: " << r << " col: " << c << " "
<< "w = " << width_ << " "
<< "h = " << height_ << " "
<< "filter group index = " << filter_ << " "
<< "filter index = " << subpel_;
}
dst_ptr += stride;
dst_ref_ptr += stride;
}
}
void AV1ConvolveOptimzTest::RunHorizFilterBitExactCheck() {
PrepFilterBuffer();
InterpFilterParams filter_params = av1_get_interp_filter_params(filter_);
av1_convolve_horiz_c(src_ref_, stride, dst_ref_, stride, width_, height_,
filter_params, subpel_, x_step_q4, &conv_params_);
conv_horiz_(src_, stride, dst_, stride, width_, height_, filter_params,
subpel_, x_step_q4, &conv_params_);
DiffFilterBuffer();
// Note:
// Here we need calculate a height which is different from the specified one
// and test again.
int intermediate_height =
(((height_ - 1) * 16 + subpel_) >> SUBPEL_BITS) + filter_params.taps;
PrepFilterBuffer();
av1_convolve_horiz_c(src_ref_, stride, dst_ref_, stride, width_,
intermediate_height, filter_params, subpel_, x_step_q4,
&conv_params_);
conv_horiz_(src_, stride, dst_, stride, width_, intermediate_height,
filter_params, subpel_, x_step_q4, &conv_params_);
DiffFilterBuffer();
}
void AV1ConvolveOptimzTest::RunVertFilterBitExactCheck() {
PrepFilterBuffer();
InterpFilterParams filter_params = av1_get_interp_filter_params(filter_);
av1_convolve_vert_c(src_ref_, stride, dst_ref_, stride, width_, height_,
filter_params, subpel_, x_step_q4, &conv_params_);
conv_vert_(src_, stride, dst_, stride, width_, height_, filter_params,
subpel_, x_step_q4, &conv_params_);
DiffFilterBuffer();
}
TEST_P(AV1ConvolveOptimzTest, HorizBitExactCheck) {
RunHorizFilterBitExactCheck();
}
TEST_P(AV1ConvolveOptimzTest, VerticalBitExactCheck) {
RunVertFilterBitExactCheck();
}
using std::tr1::make_tuple;
#if (HAVE_SSSE3 || HAVE_SSE4_1) && CONFIG_DUAL_FILTER
const BlockDimension kBlockDim[] = {
make_tuple(2, 2), make_tuple(2, 4), make_tuple(4, 4),
make_tuple(4, 8), make_tuple(8, 4), make_tuple(8, 8),
make_tuple(8, 16), make_tuple(16, 8), make_tuple(16, 16),
make_tuple(16, 32), make_tuple(32, 16), make_tuple(32, 32),
make_tuple(32, 64), make_tuple(64, 32), make_tuple(64, 64),
make_tuple(64, 128), make_tuple(128, 64), make_tuple(128, 128),
};
// 10/12-tap filters
const InterpFilter kFilter[] = { EIGHTTAP_REGULAR, BILINEAR, MULTITAP_SHARP };
const int kSubpelQ4[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
const int kAvg[] = { 0, 1 };
#endif
#if HAVE_SSSE3 && CONFIG_DUAL_FILTER
INSTANTIATE_TEST_CASE_P(
SSSE3, AV1ConvolveOptimzTest,
::testing::Combine(::testing::Values(av1_lowbd_convolve_init_ssse3),
::testing::Values(av1_convolve_horiz_ssse3),
::testing::Values(av1_convolve_vert_ssse3),
::testing::ValuesIn(kBlockDim),
::testing::ValuesIn(kFilter),
::testing::ValuesIn(kSubpelQ4),
::testing::ValuesIn(kAvg)));
#endif // HAVE_SSSE3 && CONFIG_DUAL_FILTER
#if CONFIG_HIGHBITDEPTH
typedef ::testing::TestWithParam<HbdConvParams> TestWithHbdConvParams;
class AV1HbdConvolveOptimzTest : public TestWithHbdConvParams {
public:
virtual ~AV1HbdConvolveOptimzTest() {}
virtual void SetUp() {
ConvInit conv_init = GET_PARAM(0);
conv_init();
conv_horiz_ = GET_PARAM(1);
conv_vert_ = GET_PARAM(2);
BlockDimension block = GET_PARAM(3);
width_ = std::tr1::get<0>(block);
height_ = std::tr1::get<1>(block);
filter_ = GET_PARAM(4);
subpel_ = GET_PARAM(5);
avg_ = GET_PARAM(6);
bit_depth_ = GET_PARAM(7);
alloc_ = new uint16_t[maxBlockSize * 4];
src_ = alloc_ + (vertiOffset * maxWidth);
src_ += horizOffset;
src_ref_ = src_ + maxBlockSize;
dst_ = alloc_ + 2 * maxBlockSize;
dst_ref_ = alloc_ + 3 * maxBlockSize;
}
virtual void TearDown() {
delete[] alloc_;
libaom_test::ClearSystemState();
}
protected:
void RunHorizFilterBitExactCheck();
void RunVertFilterBitExactCheck();
private:
void PrepFilterBuffer();
void DiffFilterBuffer();
hbd_conv_filter_t conv_horiz_;
hbd_conv_filter_t conv_vert_;
uint16_t *alloc_;
uint16_t *src_;
uint16_t *dst_;
uint16_t *src_ref_;
uint16_t *dst_ref_;
int width_;
int height_;
InterpFilter filter_;
int subpel_;
int avg_;
int bit_depth_;
};
void AV1HbdConvolveOptimzTest::PrepFilterBuffer() {
int r, c;
ACMRandom rnd(ACMRandom::DeterministicSeed());
memset(alloc_, 0, 4 * maxBlockSize * sizeof(alloc_[0]));
uint16_t *src_ptr = src_;
uint16_t *dst_ptr = dst_;
uint16_t *dst_ref_ptr = dst_ref_;
uint16_t hbd_mask = (1 << bit_depth_) - 1;
for (r = 0; r < height_; ++r) {
for (c = 0; c < width_; ++c) {
src_ptr[c] = rnd.Rand16() & hbd_mask;
dst_ptr[c] = rnd.Rand16() & hbd_mask;
dst_ref_ptr[c] = dst_ptr[c];
}
src_ptr += stride;
dst_ptr += stride;
dst_ref_ptr += stride;
}
}
void AV1HbdConvolveOptimzTest::DiffFilterBuffer() {
int r, c;
const uint16_t *dst_ptr = dst_;
const uint16_t *dst_ref_ptr = dst_ref_;
for (r = 0; r < height_; ++r) {
for (c = 0; c < width_; ++c) {
EXPECT_EQ((uint16_t)dst_ref_ptr[c], (uint16_t)dst_ptr[c])
<< "Error at row: " << r << " col: " << c << " "
<< "w = " << width_ << " "
<< "h = " << height_ << " "
<< "filter group index = " << filter_ << " "
<< "filter index = " << subpel_ << " "
<< "bit depth = " << bit_depth_;
}
dst_ptr += stride;
dst_ref_ptr += stride;
}
}
void AV1HbdConvolveOptimzTest::RunHorizFilterBitExactCheck() {
PrepFilterBuffer();
InterpFilterParams filter_params = av1_get_interp_filter_params(filter_);
av1_highbd_convolve_horiz_c(src_, stride, dst_ref_, stride, width_, height_,
filter_params, subpel_, x_step_q4, avg_,
bit_depth_);
conv_horiz_(src_, stride, dst_, stride, width_, height_, filter_params,
subpel_, x_step_q4, avg_, bit_depth_);
DiffFilterBuffer();
// Note:
// Here we need calculate a height which is different from the specified one
// and test again.
int intermediate_height =
(((height_ - 1) * 16 + subpel_) >> SUBPEL_BITS) + filter_params.taps;
PrepFilterBuffer();
av1_highbd_convolve_horiz_c(src_, stride, dst_ref_, stride, width_,
intermediate_height, filter_params, subpel_,
x_step_q4, avg_, bit_depth_);
conv_horiz_(src_, stride, dst_, stride, width_, intermediate_height,
filter_params, subpel_, x_step_q4, avg_, bit_depth_);
DiffFilterBuffer();
}
void AV1HbdConvolveOptimzTest::RunVertFilterBitExactCheck() {
PrepFilterBuffer();
InterpFilterParams filter_params = av1_get_interp_filter_params(filter_);
av1_highbd_convolve_vert_c(src_, stride, dst_ref_, stride, width_, height_,
filter_params, subpel_, x_step_q4, avg_,
bit_depth_);
conv_vert_(src_, stride, dst_, stride, width_, height_, filter_params,
subpel_, x_step_q4, avg_, bit_depth_);
DiffFilterBuffer();
}
TEST_P(AV1HbdConvolveOptimzTest, HorizBitExactCheck) {
RunHorizFilterBitExactCheck();
}
TEST_P(AV1HbdConvolveOptimzTest, VertBitExactCheck) {
RunVertFilterBitExactCheck();
}
#if HAVE_SSE4_1 && CONFIG_DUAL_FILTER
const int kBitdepth[] = { 10, 12 };
INSTANTIATE_TEST_CASE_P(
SSE4_1, AV1HbdConvolveOptimzTest,
::testing::Combine(::testing::Values(av1_highbd_convolve_init_sse4_1),
::testing::Values(av1_highbd_convolve_horiz_sse4_1),
::testing::Values(av1_highbd_convolve_vert_sse4_1),
::testing::ValuesIn(kBlockDim),
::testing::ValuesIn(kFilter),
::testing::ValuesIn(kSubpelQ4),
::testing::ValuesIn(kAvg),
::testing::ValuesIn(kBitdepth)));
#endif // HAVE_SSE4_1 && CONFIG_DUAL_FILTER
#endif // CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -13,13 +13,16 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "av1/common/common_data.h"
namespace {
const int kTestIters = 10;
const int kPerfIters = 1000;
@ -29,8 +32,8 @@ const int kHPad = 32;
const int kXStepQn = 16;
const int kYStepQn = 20;
using std::tr1::tuple;
using std::tr1::make_tuple;
using ::testing::make_tuple;
using ::testing::tuple;
using libaom_test::ACMRandom;
enum NTaps { EIGHT_TAP, TEN_TAP, TWELVE_TAP };
@ -120,6 +123,7 @@ class TestImage {
// Allocate image data
src_data_.resize(2 * src_block_size());
dst_data_.resize(2 * dst_block_size());
dst_16_data_.resize(2 * dst_block_size());
}
void Initialize(ACMRandom *rnd);
@ -136,8 +140,13 @@ class TestImage {
return borders ? block : block + kHPad + src_stride_ * kVPad;
}
int32_t *GetDstData(bool ref, bool borders) {
int32_t *block = &dst_data_[ref ? 0 : dst_block_size()];
SrcPixel *GetDstData(bool ref, bool borders) {
SrcPixel *block = &dst_data_[ref ? 0 : dst_block_size()];
return borders ? block : block + kHPad + dst_stride_ * kVPad;
}
CONV_BUF_TYPE *GetDst16Data(bool ref, bool borders) {
CONV_BUF_TYPE *block = &dst_16_data_[ref ? 0 : dst_block_size()];
return borders ? block : block + kHPad + dst_stride_ * kVPad;
}
@ -146,7 +155,8 @@ class TestImage {
int src_stride_, dst_stride_;
std::vector<SrcPixel> src_data_;
std::vector<int32_t> dst_data_;
std::vector<SrcPixel> dst_data_;
std::vector<CONV_BUF_TYPE> dst_16_data_;
};
template <typename Pixel>
@ -190,17 +200,23 @@ template <typename SrcPixel>
void TestImage<SrcPixel>::Initialize(ACMRandom *rnd) {
PrepBuffers(rnd, w_, h_, src_stride_, bd_, false, &src_data_[0]);
PrepBuffers(rnd, w_, h_, dst_stride_, bd_, true, &dst_data_[0]);
PrepBuffers(rnd, w_, h_, dst_stride_, bd_, true, &dst_16_data_[0]);
}
template <typename SrcPixel>
void TestImage<SrcPixel>::Check() const {
// If memcmp returns 0, there's nothing to do.
const int num_pixels = dst_block_size();
const int32_t *ref_dst = &dst_data_[0];
const int32_t *tst_dst = &dst_data_[num_pixels];
const SrcPixel *ref_dst = &dst_data_[0];
const SrcPixel *tst_dst = &dst_data_[num_pixels];
if (0 == memcmp(ref_dst, tst_dst, sizeof(*ref_dst) * num_pixels)) return;
const CONV_BUF_TYPE *ref_16_dst = &dst_16_data_[0];
const CONV_BUF_TYPE *tst_16_dst = &dst_16_data_[num_pixels];
if (0 == memcmp(ref_dst, tst_dst, sizeof(*ref_dst) * num_pixels)) {
if (0 == memcmp(ref_16_dst, tst_16_dst, sizeof(*ref_16_dst) * num_pixels))
return;
}
// Otherwise, iterate through the buffer looking for differences (including
// the edges)
const int stride = dst_stride_;
@ -213,6 +229,17 @@ void TestImage<SrcPixel>::Check() const {
<< "Error at row: " << (r - kVPad) << ", col: " << (c - kHPad);
}
}
for (int r = 0; r < h_ + 2 * kVPad; ++r) {
for (int c = 0; c < w_ + 2 * kHPad; ++c) {
const int32_t ref_value = ref_16_dst[r * stride + c];
const int32_t tst_value = tst_16_dst[r * stride + c];
EXPECT_EQ(tst_value, ref_value)
<< "Error in 16 bit buffer "
<< "Error at row: " << (r - kVPad) << ", col: " << (c - kHPad);
}
}
}
typedef tuple<int, int> BlockDimension;
@ -242,8 +269,8 @@ class ConvolveScaleTestBase : public ::testing::Test {
protected:
void SetParams(const BaseParams &params, int bd) {
width_ = std::tr1::get<0>(params.dims);
height_ = std::tr1::get<1>(params.dims);
width_ = ::testing::get<0>(params.dims);
height_ = ::testing::get<1>(params.dims);
ntaps_x_ = params.ntaps_x;
ntaps_y_ = params.ntaps_y;
bd_ = bd;
@ -251,19 +278,54 @@ class ConvolveScaleTestBase : public ::testing::Test {
filter_x_.set(ntaps_x_, false);
filter_y_.set(ntaps_y_, true);
convolve_params_ = get_conv_params_no_round(0, avg_ != false, 0, NULL, 0);
convolve_params_ =
get_conv_params_no_round(0, avg_ != false, 0, NULL, 0, 1, bd);
delete image_;
image_ = new TestImage<SrcPixel>(width_, height_, bd_);
}
void SetConvParamOffset(int i, int j, int is_compound, int do_average,
int use_jnt_comp_avg) {
if (i == -1 && j == -1) {
convolve_params_.use_jnt_comp_avg = use_jnt_comp_avg;
convolve_params_.is_compound = is_compound;
convolve_params_.do_average = do_average;
} else {
convolve_params_.use_jnt_comp_avg = use_jnt_comp_avg;
convolve_params_.fwd_offset = quant_dist_lookup_table[i][j][0];
convolve_params_.bck_offset = quant_dist_lookup_table[i][j][1];
convolve_params_.is_compound = is_compound;
convolve_params_.do_average = do_average;
}
}
void Run() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int i = 0; i < kTestIters; ++i) {
int is_compound = 0;
SetConvParamOffset(-1, -1, is_compound, 0, 0);
Prep(&rnd);
RunOne(true);
RunOne(false);
image_->Check();
is_compound = 1;
for (int do_average = 0; do_average < 2; do_average++) {
for (int use_jnt_comp_avg = 0; use_jnt_comp_avg < 2;
use_jnt_comp_avg++) {
for (int j = 0; j < 2; ++j) {
for (int k = 0; k < 4; ++k) {
SetConvParamOffset(j, k, is_compound, do_average,
use_jnt_comp_avg);
Prep(&rnd);
RunOne(true);
RunOne(false);
image_->Check();
}
}
}
}
}
}
@ -327,7 +389,7 @@ class ConvolveScaleTestBase : public ::testing::Test {
typedef tuple<int, int> BlockDimension;
typedef void (*LowbdConvolveFunc)(const uint8_t *src, int src_stride,
int32_t *dst, int dst_stride, int w, int h,
uint8_t *dst, int dst_stride, int w, int h,
InterpFilterParams *filter_params_x,
InterpFilterParams *filter_params_y,
const int subpel_x_qn, const int x_step_qn,
@ -359,10 +421,10 @@ class LowBDConvolveScaleTest
void RunOne(bool ref) {
const uint8_t *src = image_->GetSrcData(ref, false);
CONV_BUF_TYPE *dst = image_->GetDstData(ref, false);
uint8_t *dst = image_->GetDstData(ref, false);
convolve_params_.dst = image_->GetDst16Data(ref, false);
const int src_stride = image_->src_stride();
const int dst_stride = image_->dst_stride();
if (ref) {
av1_convolve_2d_scale_c(src, src_stride, dst, dst_stride, width_, height_,
&filter_x_.params_, &filter_y_.params_, subpel_x_,
@ -387,7 +449,7 @@ const BlockDimension kBlockDim[] = {
make_tuple(64, 128), make_tuple(128, 64), make_tuple(128, 128),
};
const NTaps kNTaps[] = { EIGHT_TAP, TEN_TAP, TWELVE_TAP };
const NTaps kNTaps[] = { EIGHT_TAP };
TEST_P(LowBDConvolveScaleTest, Check) { Run(); }
TEST_P(LowBDConvolveScaleTest, DISABLED_Speed) { SpeedTest(); }
@ -399,9 +461,8 @@ INSTANTIATE_TEST_CASE_P(
::testing::ValuesIn(kNTaps), ::testing::ValuesIn(kNTaps),
::testing::Bool()));
#if CONFIG_HIGHBITDEPTH
typedef void (*HighbdConvolveFunc)(const uint16_t *src, int src_stride,
int32_t *dst, int dst_stride, int w, int h,
uint16_t *dst, int dst_stride, int w, int h,
InterpFilterParams *filter_params_x,
InterpFilterParams *filter_params_y,
const int subpel_x_qn, const int x_step_qn,
@ -433,7 +494,8 @@ class HighBDConvolveScaleTest
void RunOne(bool ref) {
const uint16_t *src = image_->GetSrcData(ref, false);
CONV_BUF_TYPE *dst = image_->GetDstData(ref, false);
uint16_t *dst = image_->GetDstData(ref, false);
convolve_params_.dst = image_->GetDst16Data(ref, false);
const int src_stride = image_->src_stride();
const int dst_stride = image_->dst_stride();
@ -464,6 +526,4 @@ INSTANTIATE_TEST_CASE_P(
::testing::ValuesIn(kBlockDim),
::testing::ValuesIn(kNTaps), ::testing::ValuesIn(kNTaps),
::testing::Bool(), ::testing::ValuesIn(kBDs)));
#endif // CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -1,514 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <algorithm>
#include <vector>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "aom_dsp/aom_dsp_common.h"
#include "aom_ports/mem.h"
#include "av1/common/filter.h"
#include "av1/common/convolve.h"
#include "test/acm_random.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
using std::tr1::tuple;
static void filter_block1d_horiz_c(const uint8_t *src_ptr, int src_stride,
const int16_t *filter, int tap,
uint8_t *dst_ptr, int dst_stride, int w,
int h) {
src_ptr -= tap / 2 - 1;
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
int sum = 0;
for (int i = 0; i < tap; ++i) {
sum += src_ptr[c + i] * filter[i];
}
dst_ptr[c] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
}
src_ptr += src_stride;
dst_ptr += dst_stride;
}
}
static void filter_block1d_vert_c(const uint8_t *src_ptr, int src_stride,
const int16_t *filter, int tap,
uint8_t *dst_ptr, int dst_stride, int w,
int h) {
src_ptr -= (tap / 2 - 1) * src_stride;
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
int sum = 0;
for (int i = 0; i < tap; ++i) {
sum += src_ptr[c + i * src_stride] * filter[i];
}
dst_ptr[c] = clip_pixel(ROUND_POWER_OF_TWO(sum, FILTER_BITS));
}
src_ptr += src_stride;
dst_ptr += dst_stride;
}
}
static int match(const uint8_t *out, int out_stride, const uint8_t *ref_out,
int ref_out_stride, int w, int h) {
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
if (out[r * out_stride + c] != ref_out[r * ref_out_stride + c]) return 0;
}
}
return 1;
}
typedef void (*ConvolveFunc)(const uint8_t *src, int src_stride, uint8_t *dst,
int dst_stride, int w, int h,
const InterpFilterParams filter_params,
const int subpel_q4, int step_q4,
ConvolveParams *conv_params);
struct ConvolveFunctions {
ConvolveFunctions(ConvolveFunc hf, ConvolveFunc vf) : hf_(hf), vf_(vf) {}
ConvolveFunc hf_;
ConvolveFunc vf_;
};
typedef tuple<ConvolveFunctions *, InterpFilter /*filter_x*/,
InterpFilter /*filter_y*/>
ConvolveParam;
class Av1ConvolveTest : public ::testing::TestWithParam<ConvolveParam> {
public:
virtual void SetUp() {
rnd_(ACMRandom::DeterministicSeed());
cfs_ = GET_PARAM(0);
interp_filter_ls_[0] = GET_PARAM(2);
interp_filter_ls_[2] = interp_filter_ls_[0];
interp_filter_ls_[1] = GET_PARAM(1);
interp_filter_ls_[3] = interp_filter_ls_[1];
}
virtual void TearDown() {
while (buf_ls_.size() > 0) {
uint8_t *buf = buf_ls_.back();
aom_free(buf);
buf_ls_.pop_back();
}
}
virtual uint8_t *add_input(int w, int h, int *stride) {
uint8_t *buf =
reinterpret_cast<uint8_t *>(aom_memalign(kDataAlignment, kBufferSize));
buf_ls_.push_back(buf);
*stride = w + MAX_FILTER_TAP - 1;
int offset = MAX_FILTER_TAP / 2 - 1;
for (int r = 0; r < h + MAX_FILTER_TAP - 1; ++r) {
for (int c = 0; c < w + MAX_FILTER_TAP - 1; ++c) {
buf[r * (*stride) + c] = rnd_.Rand8();
}
}
return buf + offset * (*stride) + offset;
}
virtual uint8_t *add_output(int w, int /*h*/, int *stride) {
uint8_t *buf =
reinterpret_cast<uint8_t *>(aom_memalign(kDataAlignment, kBufferSize));
buf_ls_.push_back(buf);
*stride = w;
return buf;
}
virtual void random_init_buf(uint8_t *buf, int w, int h, int stride) {
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
buf[r * stride + c] = rnd_.Rand8();
}
}
}
protected:
static const int kDataAlignment = 16;
static const int kOuterBlockSize = MAX_SB_SIZE + MAX_FILTER_TAP - 1;
static const int kBufferSize = kOuterBlockSize * kOuterBlockSize;
std::vector<uint8_t *> buf_ls_;
InterpFilter interp_filter_ls_[4];
ConvolveFunctions *cfs_;
ACMRandom rnd_;
};
int bsize_ls[] = { 1, 2, 4, 8, 16, 32, 64, 3, 7, 15, 31, 63 };
int bsize_num = NELEMENTS(bsize_ls);
TEST_P(Av1ConvolveTest, av1_convolve_vert) {
const int y_step_q4 = 16;
ConvolveParams conv_params = get_conv_params(0, 0, 0);
int in_stride, out_stride, ref_out_stride, avg_out_stride, ref_avg_out_stride;
uint8_t *in = add_input(MAX_SB_SIZE, MAX_SB_SIZE, &in_stride);
uint8_t *out = add_output(MAX_SB_SIZE, MAX_SB_SIZE, &out_stride);
uint8_t *ref_out = add_output(MAX_SB_SIZE, MAX_SB_SIZE, &ref_out_stride);
uint8_t *avg_out = add_output(MAX_SB_SIZE, MAX_SB_SIZE, &avg_out_stride);
uint8_t *ref_avg_out =
add_output(MAX_SB_SIZE, MAX_SB_SIZE, &ref_avg_out_stride);
for (int hb_idx = 0; hb_idx < bsize_num; ++hb_idx) {
for (int vb_idx = 0; vb_idx < bsize_num; ++vb_idx) {
int w = bsize_ls[hb_idx];
int h = bsize_ls[vb_idx];
for (int subpel_y_q4 = 0; subpel_y_q4 < SUBPEL_SHIFTS; ++subpel_y_q4) {
InterpFilter filter_y = interp_filter_ls_[0];
InterpFilterParams param_vert = av1_get_interp_filter_params(filter_y);
const int16_t *filter_vert =
av1_get_interp_filter_subpel_kernel(param_vert, subpel_y_q4);
filter_block1d_vert_c(in, in_stride, filter_vert, param_vert.taps,
ref_out, ref_out_stride, w, h);
conv_params.ref = 0;
conv_params.do_average = 0;
cfs_->vf_(in, in_stride, out, out_stride, w, h, param_vert, subpel_y_q4,
y_step_q4, &conv_params);
EXPECT_EQ(match(out, out_stride, ref_out, ref_out_stride, w, h), 1)
<< " hb_idx " << hb_idx << " vb_idx " << vb_idx << " filter_y "
<< filter_y << " subpel_y_q4 " << subpel_y_q4;
random_init_buf(avg_out, w, h, avg_out_stride);
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
ref_avg_out[r * ref_avg_out_stride + c] = ROUND_POWER_OF_TWO(
avg_out[r * avg_out_stride + c] + out[r * out_stride + c], 1);
}
}
conv_params.ref = 1;
conv_params.do_average = 1;
cfs_->vf_(in, in_stride, avg_out, avg_out_stride, w, h, param_vert,
subpel_y_q4, y_step_q4, &conv_params);
EXPECT_EQ(match(avg_out, avg_out_stride, ref_avg_out,
ref_avg_out_stride, w, h),
1)
<< " hb_idx " << hb_idx << " vb_idx " << vb_idx << " filter_y "
<< filter_y << " subpel_y_q4 " << subpel_y_q4;
}
}
}
};
TEST_P(Av1ConvolveTest, av1_convolve_horiz) {
const int x_step_q4 = 16;
ConvolveParams conv_params = get_conv_params(0, 0, 0);
int in_stride, out_stride, ref_out_stride, avg_out_stride, ref_avg_out_stride;
uint8_t *in = add_input(MAX_SB_SIZE, MAX_SB_SIZE, &in_stride);
uint8_t *out = add_output(MAX_SB_SIZE, MAX_SB_SIZE, &out_stride);
uint8_t *ref_out = add_output(MAX_SB_SIZE, MAX_SB_SIZE, &ref_out_stride);
uint8_t *avg_out = add_output(MAX_SB_SIZE, MAX_SB_SIZE, &avg_out_stride);
uint8_t *ref_avg_out =
add_output(MAX_SB_SIZE, MAX_SB_SIZE, &ref_avg_out_stride);
for (int hb_idx = 0; hb_idx < bsize_num; ++hb_idx) {
for (int vb_idx = 0; vb_idx < bsize_num; ++vb_idx) {
int w = bsize_ls[hb_idx];
int h = bsize_ls[vb_idx];
for (int subpel_x_q4 = 0; subpel_x_q4 < SUBPEL_SHIFTS; ++subpel_x_q4) {
InterpFilter filter_x = interp_filter_ls_[1];
InterpFilterParams param_horiz = av1_get_interp_filter_params(filter_x);
const int16_t *filter_horiz =
av1_get_interp_filter_subpel_kernel(param_horiz, subpel_x_q4);
filter_block1d_horiz_c(in, in_stride, filter_horiz, param_horiz.taps,
ref_out, ref_out_stride, w, h);
conv_params.ref = 0;
conv_params.do_average = 0;
cfs_->hf_(in, in_stride, out, out_stride, w, h, param_horiz,
subpel_x_q4, x_step_q4, &conv_params);
EXPECT_EQ(match(out, out_stride, ref_out, ref_out_stride, w, h), 1)
<< " hb_idx " << hb_idx << " vb_idx " << vb_idx << " filter_x "
<< filter_x << " subpel_x_q4 " << subpel_x_q4;
random_init_buf(avg_out, w, h, avg_out_stride);
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
ref_avg_out[r * ref_avg_out_stride + c] = ROUND_POWER_OF_TWO(
avg_out[r * avg_out_stride + c] + out[r * out_stride + c], 1);
}
}
conv_params.ref = 1;
conv_params.do_average = 1;
cfs_->hf_(in, in_stride, avg_out, avg_out_stride, w, h, param_horiz,
subpel_x_q4, x_step_q4, &conv_params);
EXPECT_EQ(match(avg_out, avg_out_stride, ref_avg_out,
ref_avg_out_stride, w, h),
1)
<< "hb_idx " << hb_idx << "vb_idx" << vb_idx << " filter_x "
<< filter_x << "subpel_x_q4 " << subpel_x_q4;
}
}
}
};
ConvolveFunctions convolve_functions_c(av1_convolve_horiz_c,
av1_convolve_vert_c);
InterpFilter filter_ls[] = { EIGHTTAP_REGULAR, EIGHTTAP_SMOOTH,
MULTITAP_SHARP };
INSTANTIATE_TEST_CASE_P(
C, Av1ConvolveTest,
::testing::Combine(::testing::Values(&convolve_functions_c),
::testing::ValuesIn(filter_ls),
::testing::ValuesIn(filter_ls)));
#if CONFIG_HIGHBITDEPTH
#ifndef __clang_analyzer__
TEST(AV1ConvolveTest, av1_highbd_convolve) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
InterpFilters interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
InterpFilterParams filter_params =
av1_get_interp_filter_params(EIGHTTAP_REGULAR);
int filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint16_t src[12 * 12];
int src_stride = filter_size;
uint16_t dst[1] = { 0 };
int dst_stride = 1;
int x_step_q4 = 16;
int y_step_q4 = 16;
int avg = 0;
int bd = 10;
int w = 1;
int h = 1;
int subpel_x_q4;
int subpel_y_q4;
for (int i = 0; i < filter_size * filter_size; i++) {
src[i] = rnd.Rand16() % (1 << bd);
}
for (subpel_x_q4 = 0; subpel_x_q4 < SUBPEL_SHIFTS; subpel_x_q4++) {
for (subpel_y_q4 = 0; subpel_y_q4 < SUBPEL_SHIFTS; subpel_y_q4++) {
av1_highbd_convolve(
CONVERT_TO_BYTEPTR(src + src_stride * filter_center + filter_center),
src_stride, CONVERT_TO_BYTEPTR(dst), dst_stride, w, h, interp_filters,
subpel_x_q4, x_step_q4, subpel_y_q4, y_step_q4, avg, bd);
const int16_t *x_filter =
av1_get_interp_filter_subpel_kernel(filter_params, subpel_x_q4);
const int16_t *y_filter =
av1_get_interp_filter_subpel_kernel(filter_params, subpel_y_q4);
int temp[12];
int dst_ref = 0;
for (int r = 0; r < filter_size; r++) {
temp[r] = 0;
for (int c = 0; c < filter_size; c++) {
temp[r] += x_filter[c] * src[r * filter_size + c];
}
temp[r] =
clip_pixel_highbd(ROUND_POWER_OF_TWO(temp[r], FILTER_BITS), bd);
dst_ref += temp[r] * y_filter[r];
}
dst_ref = clip_pixel_highbd(ROUND_POWER_OF_TWO(dst_ref, FILTER_BITS), bd);
EXPECT_EQ(dst[0], dst_ref);
}
}
}
#endif
TEST(AV1ConvolveTest, av1_highbd_convolve_avg) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
InterpFilters interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
InterpFilterParams filter_params =
av1_get_interp_filter_params(EIGHTTAP_REGULAR);
int filter_size = filter_params.taps;
int filter_center = filter_size / 2 - 1;
uint16_t src0[12 * 12];
uint16_t src1[12 * 12];
int src_stride = filter_size;
uint16_t dst0[1] = { 0 };
uint16_t dst1[1] = { 0 };
uint16_t dst[1] = { 0 };
int dst_stride = 1;
int x_step_q4 = 16;
int y_step_q4 = 16;
int avg = 0;
int bd = 10;
int w = 1;
int h = 1;
int subpel_x_q4;
int subpel_y_q4;
for (int i = 0; i < filter_size * filter_size; i++) {
src0[i] = rnd.Rand16() % (1 << bd);
src1[i] = rnd.Rand16() % (1 << bd);
}
for (subpel_x_q4 = 0; subpel_x_q4 < SUBPEL_SHIFTS; subpel_x_q4++) {
for (subpel_y_q4 = 0; subpel_y_q4 < SUBPEL_SHIFTS; subpel_y_q4++) {
int offset = filter_size * filter_center + filter_center;
avg = 0;
av1_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
CONVERT_TO_BYTEPTR(dst0), dst_stride, w, h,
interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg, bd);
avg = 0;
av1_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
CONVERT_TO_BYTEPTR(dst1), dst_stride, w, h,
interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg, bd);
avg = 0;
av1_highbd_convolve(CONVERT_TO_BYTEPTR(src0 + offset), src_stride,
CONVERT_TO_BYTEPTR(dst), dst_stride, w, h,
interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg, bd);
avg = 1;
av1_highbd_convolve(CONVERT_TO_BYTEPTR(src1 + offset), src_stride,
CONVERT_TO_BYTEPTR(dst), dst_stride, w, h,
interp_filters, subpel_x_q4, x_step_q4, subpel_y_q4,
y_step_q4, avg, bd);
EXPECT_EQ(dst[0], ROUND_POWER_OF_TWO(dst0[0] + dst1[0], 1));
}
}
}
#endif // CONFIG_HIGHBITDEPTH
#define CONVOLVE_SPEED_TEST 0
#if CONVOLVE_SPEED_TEST
#define highbd_convolve_speed(func, block_size, frame_size) \
TEST(AV1ConvolveTest, func##_speed_##block_size##_##frame_size) { \
ACMRandom rnd(ACMRandom::DeterministicSeed()); \
InterpFilter interp_filter = EIGHTTAP; \
InterpFilterParams filter_params = \
av1_get_interp_filter_params(interp_filter); \
int filter_size = filter_params.tap; \
int filter_center = filter_size / 2 - 1; \
DECLARE_ALIGNED(16, uint16_t, \
src[(frame_size + 7) * (frame_size + 7)]) = { 0 }; \
int src_stride = frame_size + 7; \
DECLARE_ALIGNED(16, uint16_t, dst[frame_size * frame_size]) = { 0 }; \
int dst_stride = frame_size; \
int x_step_q4 = 16; \
int y_step_q4 = 16; \
int subpel_x_q4 = 8; \
int subpel_y_q4 = 6; \
int bd = 10; \
\
int w = block_size; \
int h = block_size; \
\
const int16_t *filter_x = \
av1_get_interp_filter_kernel(filter_params, subpel_x_q4); \
const int16_t *filter_y = \
av1_get_interp_filter_kernel(filter_params, subpel_y_q4); \
\
for (int i = 0; i < src_stride * src_stride; i++) { \
src[i] = rnd.Rand16() % (1 << bd); \
} \
\
int offset = filter_center * src_stride + filter_center; \
int row_offset = 0; \
int col_offset = 0; \
for (int i = 0; i < 100000; i++) { \
int src_total_offset = offset + col_offset * src_stride + row_offset; \
int dst_total_offset = col_offset * dst_stride + row_offset; \
func(CONVERT_TO_BYTEPTR(src + src_total_offset), src_stride, \
CONVERT_TO_BYTEPTR(dst + dst_total_offset), dst_stride, filter_x, \
x_step_q4, filter_y, y_step_q4, w, h, bd); \
if (offset + w + w < frame_size) { \
row_offset += w; \
} else { \
row_offset = 0; \
col_offset += h; \
} \
if (col_offset + h >= frame_size) { \
col_offset = 0; \
} \
} \
}
#define lowbd_convolve_speed(func, block_size, frame_size) \
TEST(AV1ConvolveTest, func##_speed_l_##block_size##_##frame_size) { \
ACMRandom rnd(ACMRandom::DeterministicSeed()); \
InterpFilter interp_filter = EIGHTTAP; \
InterpFilterParams filter_params = \
av1_get_interp_filter_params(interp_filter); \
int filter_size = filter_params.tap; \
int filter_center = filter_size / 2 - 1; \
DECLARE_ALIGNED(16, uint8_t, src[(frame_size + 7) * (frame_size + 7)]); \
int src_stride = frame_size + 7; \
DECLARE_ALIGNED(16, uint8_t, dst[frame_size * frame_size]); \
int dst_stride = frame_size; \
int x_step_q4 = 16; \
int y_step_q4 = 16; \
int subpel_x_q4 = 8; \
int subpel_y_q4 = 6; \
int bd = 8; \
\
int w = block_size; \
int h = block_size; \
\
const int16_t *filter_x = \
av1_get_interp_filter_kernel(filter_params, subpel_x_q4); \
const int16_t *filter_y = \
av1_get_interp_filter_kernel(filter_params, subpel_y_q4); \
\
for (int i = 0; i < src_stride * src_stride; i++) { \
src[i] = rnd.Rand16() % (1 << bd); \
} \
\
int offset = filter_center * src_stride + filter_center; \
int row_offset = 0; \
int col_offset = 0; \
for (int i = 0; i < 100000; i++) { \
func(src + offset, src_stride, dst, dst_stride, filter_x, x_step_q4, \
filter_y, y_step_q4, w, h); \
if (offset + w + w < frame_size) { \
row_offset += w; \
} else { \
row_offset = 0; \
col_offset += h; \
} \
if (col_offset + h >= frame_size) { \
col_offset = 0; \
} \
} \
}
// This experiment shows that when frame size is 64x64
// aom_highbd_convolve8_sse2 and aom_convolve8_sse2's speed are similar.
// However when frame size becomes 1024x1024
// aom_highbd_convolve8_sse2 is around 50% slower than aom_convolve8_sse2
// we think the bottleneck is from memory IO
highbd_convolve_speed(aom_highbd_convolve8_sse2, 8, 64);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 16, 64);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 32, 64);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 64, 64);
lowbd_convolve_speed(aom_convolve8_sse2, 8, 64);
lowbd_convolve_speed(aom_convolve8_sse2, 16, 64);
lowbd_convolve_speed(aom_convolve8_sse2, 32, 64);
lowbd_convolve_speed(aom_convolve8_sse2, 64, 64);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 8, 1024);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 16, 1024);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 32, 1024);
highbd_convolve_speed(aom_highbd_convolve8_sse2, 64, 1024);
lowbd_convolve_speed(aom_convolve8_sse2, 8, 1024);
lowbd_convolve_speed(aom_convolve8_sse2, 16, 1024);
lowbd_convolve_speed(aom_convolve8_sse2, 32, 1024);
lowbd_convolve_speed(aom_convolve8_sse2, 64, 1024);
#endif // CONVOLVE_SPEED_TEST
} // namespace

View file

@ -1,112 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <new>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "./aom_config.h"
#include "aom_ports/msvc.h"
#undef CONFIG_COEFFICIENT_RANGE_CHECKING
#define CONFIG_COEFFICIENT_RANGE_CHECKING 1
#define AV1_DCT_GTEST
#include "av1/encoder/dct.c"
#if CONFIG_DAALA_DCT4 || CONFIG_DAALA_DCT8 || CONFIG_DAALA_DCT16 || \
CONFIG_DAALA_DCT32
#include "av1/common/daala_tx.c"
#endif
using libaom_test::ACMRandom;
namespace {
void reference_dct_1d(const double *in, double *out, int size) {
const double kInvSqrt2 = 0.707106781186547524400844362104;
for (int k = 0; k < size; ++k) {
out[k] = 0;
for (int n = 0; n < size; ++n) {
out[k] += in[n] * cos(PI * (2 * n + 1) * k / (2 * size));
}
if (k == 0) out[k] = out[k] * kInvSqrt2;
}
}
typedef void (*FdctFuncRef)(const double *in, double *out, int size);
typedef void (*IdctFuncRef)(const double *in, double *out, int size);
typedef void (*FdctFunc)(const tran_low_t *in, tran_low_t *out);
typedef void (*IdctFunc)(const tran_low_t *in, tran_low_t *out);
class TransTestBase {
public:
virtual ~TransTestBase() {}
protected:
void RunFwdAccuracyCheck() {
tran_low_t *input = new tran_low_t[txfm_size_];
tran_low_t *output = new tran_low_t[txfm_size_];
double *ref_input = new double[txfm_size_];
double *ref_output = new double[txfm_size_];
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int count_test_block = 5000;
for (int ti = 0; ti < count_test_block; ++ti) {
for (int ni = 0; ni < txfm_size_; ++ni) {
input[ni] = rnd.Rand8() - rnd.Rand8();
ref_input[ni] = static_cast<double>(input[ni]);
}
fwd_txfm_(input, output);
fwd_txfm_ref_(ref_input, ref_output, txfm_size_);
for (int ni = 0; ni < txfm_size_; ++ni) {
EXPECT_LE(
abs(output[ni] - static_cast<tran_low_t>(round(ref_output[ni]))),
max_error_);
}
}
delete[] input;
delete[] output;
delete[] ref_input;
delete[] ref_output;
}
double max_error_;
int txfm_size_;
FdctFunc fwd_txfm_;
FdctFuncRef fwd_txfm_ref_;
};
typedef std::tr1::tuple<FdctFunc, FdctFuncRef, int, int> FdctParam;
class AV1FwdTxfm : public TransTestBase,
public ::testing::TestWithParam<FdctParam> {
public:
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = GET_PARAM(1);
txfm_size_ = GET_PARAM(2);
max_error_ = GET_PARAM(3);
}
virtual void TearDown() {}
};
TEST_P(AV1FwdTxfm, RunFwdAccuracyCheck) { RunFwdAccuracyCheck(); }
INSTANTIATE_TEST_CASE_P(
C, AV1FwdTxfm,
::testing::Values(FdctParam(&fdct4, &reference_dct_1d, 4, 1),
FdctParam(&fdct8, &reference_dct_1d, 8, 1),
FdctParam(&fdct16, &reference_dct_1d, 16, 2),
FdctParam(&fdct32, &reference_dct_1d, 32, 3)));
} // namespace

View file

@ -46,6 +46,7 @@ class AV1ExtTileTest
cfg.allow_lowbitdepth = 1;
decoder_ = codec_->CreateDecoder(cfg, 0);
decoder_->Control(AV1_SET_TILE_MODE, 1);
decoder_->Control(AV1_SET_DECODE_TILE_ROW, -1);
decoder_->Control(AV1_SET_DECODE_TILE_COL, -1);
@ -86,13 +87,8 @@ class AV1ExtTileTest
encoder->Control(AV1E_SET_TILE_ROWS, kTileSize);
// TODO(yunqingwang): test single_tile_decoding = 0.
encoder->Control(AV1E_SET_SINGLE_TILE_DECODING, 1);
#if CONFIG_EXT_PARTITION
// Always use 64x64 max partition.
encoder->Control(AV1E_SET_SUPERBLOCK_SIZE, AOM_SUPERBLOCK_SIZE_64X64);
#endif
#if CONFIG_LOOPFILTERING_ACROSS_TILES
encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
#endif
}
if (video->frame() == 1) {
@ -174,6 +170,23 @@ class AV1ExtTileTest
}
}
void TestRoundTrip() {
::libaom_test::I420VideoSource video(
"hantro_collage_w352h288.yuv", kImgWidth, kImgHeight, 30, 1, 0, kLimit);
cfg_.rc_target_bitrate = 500;
cfg_.g_error_resilient = AOM_ERROR_RESILIENT_DEFAULT;
cfg_.large_scale_tile = 1;
cfg_.g_lag_in_frames = 0;
cfg_.g_threads = 1;
// Tile encoding
init_flags_ = AOM_CODEC_USE_PSNR;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
// Compare to check if two vectors are equal.
ASSERT_EQ(md5_, tile_md5_);
}
::libaom_test::TestMode encoding_mode_;
int set_cpu_used_;
::libaom_test::Decoder *decoder_;
@ -182,25 +195,19 @@ class AV1ExtTileTest
std::vector<std::string> tile_md5_;
};
TEST_P(AV1ExtTileTest, DecoderResultTest) {
::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", kImgWidth,
kImgHeight, 30, 1, 0, kLimit);
cfg_.rc_target_bitrate = 500;
cfg_.g_error_resilient = AOM_ERROR_RESILIENT_DEFAULT;
cfg_.large_scale_tile = 1;
cfg_.g_lag_in_frames = 0;
cfg_.g_threads = 1;
// Tile encoding
init_flags_ = AOM_CODEC_USE_PSNR;
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
// Compare to check if two vectors are equal.
ASSERT_EQ(md5_, tile_md5_);
}
TEST_P(AV1ExtTileTest, DISABLED_DecoderResultTest) { TestRoundTrip(); }
AV1_INSTANTIATE_TEST_CASE(
// Now only test 2-pass mode.
AV1ExtTileTest, ::testing::Values(::libaom_test::kTwoPassGood),
::testing::Range(0, 4));
::testing::Range(1, 4));
class AV1ExtTileTestLarge : public AV1ExtTileTest {};
TEST_P(AV1ExtTileTestLarge, DISABLED_DecoderResultTest) { TestRoundTrip(); }
AV1_INSTANTIATE_TEST_CASE(
// Now only test 2-pass mode.
AV1ExtTileTestLarge, ::testing::Values(::libaom_test::kTwoPassGood),
::testing::Range(0, 1));
} // namespace

View file

@ -1,276 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#include "aom_ports/mem.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht16x16Param;
void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht16x16_c(in, out, stride, txfm_param);
}
void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
const TxfmParam *txfm_param) {
av1_iht16x16_256_add_c(in, dest, stride, txfm_param);
}
#if CONFIG_HIGHBITDEPTH
typedef void (*IHbdHtFunc)(const tran_low_t *in, uint8_t *out, int stride,
TX_TYPE tx_type, int bd);
typedef void (*HbdHtFunc)(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd);
// Target optimized function, tx_type, bit depth
typedef tuple<HbdHtFunc, TX_TYPE, int> HighbdHt16x16Param;
void highbd_fht16x16_ref(const int16_t *in, int32_t *out, int stride,
TX_TYPE tx_type, int bd) {
av1_fwd_txfm2d_16x16_c(in, out, stride, tx_type, bd);
}
#endif // CONFIG_HIGHBITDEPTH
class AV1Trans16x16HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht16x16Param> {
public:
virtual ~AV1Trans16x16HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 16;
height_ = 16;
fwd_txfm_ref = fht16x16_ref;
inv_txfm_ref = iht16x16_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans16x16HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans16x16HT, AccuracyCheck) { RunAccuracyCheck(1, 0.001); }
TEST_P(AV1Trans16x16HT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
TEST_P(AV1Trans16x16HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans16x16HT, InvCoeffCheck) { RunInvCoeffCheck(); }
#if CONFIG_HIGHBITDEPTH
class AV1HighbdTrans16x16HT
: public ::testing::TestWithParam<HighbdHt16x16Param> {
public:
virtual ~AV1HighbdTrans16x16HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = highbd_fht16x16_ref;
tx_type_ = GET_PARAM(1);
bit_depth_ = GET_PARAM(2);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = 256;
input_ = reinterpret_cast<int16_t *>(
aom_memalign(32, sizeof(int16_t) * num_coeffs_));
output_ = reinterpret_cast<int32_t *>(
aom_memalign(32, sizeof(int32_t) * num_coeffs_));
output_ref_ = reinterpret_cast<int32_t *>(
aom_memalign(32, sizeof(int32_t) * num_coeffs_));
}
virtual void TearDown() {
aom_free(input_);
aom_free(output_);
aom_free(output_ref_);
libaom_test::ClearSystemState();
}
protected:
void RunBitexactCheck();
private:
HbdHtFunc fwd_txfm_;
HbdHtFunc fwd_txfm_ref_;
TX_TYPE tx_type_;
int bit_depth_;
int mask_;
int num_coeffs_;
int16_t *input_;
int32_t *output_;
int32_t *output_ref_;
};
void AV1HighbdTrans16x16HT::RunBitexactCheck() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i, j;
const int stride = 16;
const int num_tests = 1000;
for (i = 0; i < num_tests; ++i) {
for (j = 0; j < num_coeffs_; ++j) {
input_[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
}
fwd_txfm_ref_(input_, output_ref_, stride, tx_type_, bit_depth_);
ASM_REGISTER_STATE_CHECK(
fwd_txfm_(input_, output_, stride, tx_type_, bit_depth_));
for (j = 0; j < num_coeffs_; ++j) {
EXPECT_EQ(output_ref_[j], output_[j])
<< "Not bit-exact result at index: " << j << " at test block: " << i;
}
}
}
TEST_P(AV1HighbdTrans16x16HT, HighbdCoeffCheck) { RunBitexactCheck(); }
#endif // CONFIG_HIGHBITDEPTH
using std::tr1::make_tuple;
#if HAVE_SSE2 && !CONFIG_DAALA_DCT16
const Ht16x16Param kArrayHt16x16Param_sse2[] = {
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, DCT_DCT,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, ADST_DCT,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, DCT_ADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, ADST_ADST,
AOM_BITS_8, 256),
#if CONFIG_EXT_TX
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, IDTX, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, V_DCT, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, H_DCT, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, V_ADST, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, H_ADST, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, V_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2, H_FLIPADST,
AOM_BITS_8, 256)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans16x16HT,
::testing::ValuesIn(kArrayHt16x16Param_sse2));
#endif // HAVE_SSE2
#if HAVE_AVX2 && !CONFIG_DAALA_DCT16
const Ht16x16Param kArrayHt16x16Param_avx2[] = {
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, DCT_DCT,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, ADST_DCT,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, DCT_ADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, ADST_ADST,
AOM_BITS_8, 256),
#if CONFIG_EXT_TX
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, FLIPADST_DCT,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, DCT_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, FLIPADST_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, ADST_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, FLIPADST_ADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, IDTX, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, V_DCT, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, H_DCT, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, V_ADST, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, H_ADST, AOM_BITS_8,
256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, V_FLIPADST,
AOM_BITS_8, 256),
make_tuple(&av1_fht16x16_avx2, &av1_iht16x16_256_add_avx2, H_FLIPADST,
AOM_BITS_8, 256)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(AVX2, AV1Trans16x16HT,
::testing::ValuesIn(kArrayHt16x16Param_avx2));
#endif // HAVE_AVX2
#if HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT16
const HighbdHt16x16Param kArrayHBDHt16x16Param_sse4_1[] = {
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, DCT_DCT, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, DCT_DCT, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, ADST_DCT, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, ADST_DCT, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, DCT_ADST, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, DCT_ADST, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, ADST_ADST, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, ADST_ADST, 12),
#if CONFIG_EXT_TX
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, FLIPADST_DCT, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, FLIPADST_DCT, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, DCT_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, DCT_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, FLIPADST_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, FLIPADST_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, ADST_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, ADST_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, FLIPADST_ADST, 10),
make_tuple(&av1_fwd_txfm2d_16x16_sse4_1, FLIPADST_ADST, 12),
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1HighbdTrans16x16HT,
::testing::ValuesIn(kArrayHBDHt16x16Param_sse4_1));
#endif // HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT16
} // namespace

View file

@ -1,157 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht16x32Param;
void fht16x32_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht16x32_c(in, out, stride, txfm_param);
}
void iht16x32_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht16x32_512_add_c(in, out, stride, txfm_param);
}
class AV1Trans16x32HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht16x32Param> {
public:
virtual ~AV1Trans16x32HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 16;
height_ = 32;
fwd_txfm_ref = fht16x32_ref;
inv_txfm_ref = iht16x32_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans16x32HT, AccuracyCheck) { RunAccuracyCheck(4, 0.2); }
TEST_P(AV1Trans16x32HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans16x32HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans16x32HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans16x32HT, InvAccuracyCheck) { RunInvAccuracyCheck(4); }
using std::tr1::make_tuple;
const Ht16x32Param kArrayHt16x32Param_c[] = {
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, DCT_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, ADST_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, DCT_ADST, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, ADST_ADST, AOM_BITS_8,
512),
#if CONFIG_EXT_TX
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, FLIPADST_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, DCT_FLIPADST, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, FLIPADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, ADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, FLIPADST_ADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, IDTX, AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, V_DCT, AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, H_DCT, AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, V_ADST, AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, H_ADST, AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, V_FLIPADST, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_c, &av1_iht16x32_512_add_c, H_FLIPADST, AOM_BITS_8,
512)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans16x32HT,
::testing::ValuesIn(kArrayHt16x32Param_c));
#if HAVE_SSE2
const Ht16x32Param kArrayHt16x32Param_sse2[] = {
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, DCT_DCT,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, ADST_DCT,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, DCT_ADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, ADST_ADST,
AOM_BITS_8, 512),
#if CONFIG_EXT_TX
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, IDTX, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, V_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, H_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, V_ADST, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, H_ADST, AOM_BITS_8,
512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, V_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht16x32_sse2, &av1_iht16x32_512_add_sse2, H_FLIPADST,
AOM_BITS_8, 512)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans16x32HT,
::testing::ValuesIn(kArrayHt16x32Param_sse2));
#endif // HAVE_SSE2
} // namespace

View file

@ -1,155 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht16x8Param;
void fht16x8_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht16x8_c(in, out, stride, txfm_param);
}
void iht16x8_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht16x8_128_add_c(in, out, stride, txfm_param);
}
class AV1Trans16x8HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht16x8Param> {
public:
virtual ~AV1Trans16x8HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 16;
height_ = 8;
inv_txfm_ref = iht16x8_ref;
fwd_txfm_ref = fht16x8_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans16x8HT, AccuracyCheck) { RunAccuracyCheck(1, 0.001); }
TEST_P(AV1Trans16x8HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans16x8HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans16x8HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans16x8HT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
using std::tr1::make_tuple;
const Ht16x8Param kArrayHt16x8Param_c[] = {
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, DCT_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, ADST_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, DCT_ADST, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, ADST_ADST, AOM_BITS_8,
128),
#if CONFIG_EXT_TX
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, FLIPADST_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, DCT_FLIPADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, FLIPADST_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, ADST_FLIPADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, FLIPADST_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, IDTX, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, V_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, H_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, V_ADST, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, H_ADST, AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, V_FLIPADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_c, &av1_iht16x8_128_add_c, H_FLIPADST, AOM_BITS_8,
128)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans16x8HT,
::testing::ValuesIn(kArrayHt16x8Param_c));
#if HAVE_SSE2
const Ht16x8Param kArrayHt16x8Param_sse2[] = {
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, DCT_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, ADST_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, DCT_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, ADST_ADST,
AOM_BITS_8, 128),
#if CONFIG_EXT_TX
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, IDTX, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, V_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, H_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, V_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, H_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, V_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht16x8_sse2, &av1_iht16x8_128_add_sse2, H_FLIPADST,
AOM_BITS_8, 128)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans16x8HT,
::testing::ValuesIn(kArrayHt16x8Param_sse2));
#endif // HAVE_SSE2
} // namespace

View file

@ -1,157 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht32x16Param;
void fht32x16_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht32x16_c(in, out, stride, txfm_param);
}
void iht32x16_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht32x16_512_add_c(in, out, stride, txfm_param);
}
class AV1Trans32x16HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht32x16Param> {
public:
virtual ~AV1Trans32x16HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 32;
height_ = 16;
fwd_txfm_ref = fht32x16_ref;
inv_txfm_ref = iht32x16_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans32x16HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans32x16HT, AccuracyCheck) { RunAccuracyCheck(4, 0.2); }
TEST_P(AV1Trans32x16HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans32x16HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans32x16HT, InvAccuracyCheck) { RunInvAccuracyCheck(4); }
using std::tr1::make_tuple;
const Ht32x16Param kArrayHt32x16Param_c[] = {
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, DCT_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, ADST_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, DCT_ADST, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, ADST_ADST, AOM_BITS_8,
512),
#if CONFIG_EXT_TX
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, FLIPADST_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, DCT_FLIPADST, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, FLIPADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, ADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, FLIPADST_ADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, IDTX, AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, V_DCT, AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, H_DCT, AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, V_ADST, AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, H_ADST, AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, V_FLIPADST, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_c, &av1_iht32x16_512_add_c, H_FLIPADST, AOM_BITS_8,
512)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans32x16HT,
::testing::ValuesIn(kArrayHt32x16Param_c));
#if HAVE_SSE2
const Ht32x16Param kArrayHt32x16Param_sse2[] = {
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, DCT_DCT,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, ADST_DCT,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, DCT_ADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, ADST_ADST,
AOM_BITS_8, 512),
#if CONFIG_EXT_TX
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, IDTX, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, V_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, H_DCT, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, V_ADST, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, H_ADST, AOM_BITS_8,
512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, V_FLIPADST,
AOM_BITS_8, 512),
make_tuple(&av1_fht32x16_sse2, &av1_iht32x16_512_add_sse2, H_FLIPADST,
AOM_BITS_8, 512)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans32x16HT,
::testing::ValuesIn(kArrayHt32x16Param_sse2));
#endif // HAVE_SSE2
} // namespace

View file

@ -1,227 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#include "aom_ports/mem.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht32x32Param;
void fht32x32_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht32x32_c(in, out, stride, txfm_param);
}
#if CONFIG_HIGHBITDEPTH
typedef void (*IHbdHtFunc)(const tran_low_t *in, uint8_t *out, int stride,
TX_TYPE tx_type, int bd);
typedef void (*HbdHtFunc)(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd);
// Target optimized function, tx_type, bit depth
typedef tuple<HbdHtFunc, TX_TYPE, int> HighbdHt32x32Param;
void highbd_fht32x32_ref(const int16_t *in, int32_t *out, int stride,
TX_TYPE tx_type, int bd) {
av1_fwd_txfm2d_32x32_c(in, out, stride, tx_type, bd);
}
#endif // CONFIG_HIGHBITDEPTH
#if (HAVE_SSE2 || HAVE_AVX2) && !CONFIG_DAALA_DCT32
void dummy_inv_txfm(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
(void)in;
(void)out;
(void)stride;
(void)txfm_param;
}
#endif
class AV1Trans32x32HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht32x32Param> {
public:
virtual ~AV1Trans32x32HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 32;
height_ = 32;
fwd_txfm_ref = fht32x32_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans32x32HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans32x32HT, MemCheck) { RunMemCheck(); }
#if CONFIG_HIGHBITDEPTH
class AV1HighbdTrans32x32HT
: public ::testing::TestWithParam<HighbdHt32x32Param> {
public:
virtual ~AV1HighbdTrans32x32HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = highbd_fht32x32_ref;
tx_type_ = GET_PARAM(1);
bit_depth_ = GET_PARAM(2);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = 1024;
input_ = reinterpret_cast<int16_t *>(
aom_memalign(32, sizeof(int16_t) * num_coeffs_));
output_ = reinterpret_cast<int32_t *>(
aom_memalign(32, sizeof(int32_t) * num_coeffs_));
output_ref_ = reinterpret_cast<int32_t *>(
aom_memalign(32, sizeof(int32_t) * num_coeffs_));
}
virtual void TearDown() {
aom_free(input_);
aom_free(output_);
aom_free(output_ref_);
libaom_test::ClearSystemState();
}
protected:
void RunBitexactCheck();
private:
HbdHtFunc fwd_txfm_;
HbdHtFunc fwd_txfm_ref_;
TX_TYPE tx_type_;
int bit_depth_;
int mask_;
int num_coeffs_;
int16_t *input_;
int32_t *output_;
int32_t *output_ref_;
};
void AV1HighbdTrans32x32HT::RunBitexactCheck() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i, j;
const int stride = 32;
const int num_tests = 1000;
for (i = 0; i < num_tests; ++i) {
for (j = 0; j < num_coeffs_; ++j) {
input_[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
}
fwd_txfm_ref_(input_, output_ref_, stride, tx_type_, bit_depth_);
ASM_REGISTER_STATE_CHECK(
fwd_txfm_(input_, output_, stride, tx_type_, bit_depth_));
for (j = 0; j < num_coeffs_; ++j) {
EXPECT_EQ(output_ref_[j], output_[j])
<< "Not bit-exact result at index: " << j << " at test block: " << i;
}
}
}
TEST_P(AV1HighbdTrans32x32HT, HighbdCoeffCheck) { RunBitexactCheck(); }
#endif // CONFIG_HIGHBITDEPTH
using std::tr1::make_tuple;
#if HAVE_SSE2 && !CONFIG_DAALA_DCT32
const Ht32x32Param kArrayHt32x32Param_sse2[] = {
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, DCT_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, ADST_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, DCT_ADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, ADST_ADST, AOM_BITS_8, 1024),
#if CONFIG_EXT_TX
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, FLIPADST_DCT, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, DCT_FLIPADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, FLIPADST_FLIPADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, ADST_FLIPADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, FLIPADST_ADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, IDTX, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, V_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, H_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, V_ADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, H_ADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, V_FLIPADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_sse2, &dummy_inv_txfm, H_FLIPADST, AOM_BITS_8, 1024)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans32x32HT,
::testing::ValuesIn(kArrayHt32x32Param_sse2));
#endif // HAVE_SSE2 && !CONFIG_DAALA_DCT32
#if HAVE_AVX2 && !CONFIG_DAALA_DCT32
const Ht32x32Param kArrayHt32x32Param_avx2[] = {
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, DCT_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, ADST_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, DCT_ADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, ADST_ADST, AOM_BITS_8, 1024),
#if CONFIG_EXT_TX
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, FLIPADST_DCT, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, DCT_FLIPADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, FLIPADST_FLIPADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, ADST_FLIPADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, FLIPADST_ADST, AOM_BITS_8,
1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, IDTX, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, V_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, H_DCT, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, V_ADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, H_ADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, V_FLIPADST, AOM_BITS_8, 1024),
make_tuple(&av1_fht32x32_avx2, &dummy_inv_txfm, H_FLIPADST, AOM_BITS_8, 1024)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(AVX2, AV1Trans32x32HT,
::testing::ValuesIn(kArrayHt32x32Param_avx2));
#endif // HAVE_AVX2 && !CONFIG_DAALA_DCT32
} // namespace

View file

@ -1,235 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#include "aom_ports/mem.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht4x4Param;
void fht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht4x4_c(in, out, stride, txfm_param);
}
void iht4x4_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht4x4_16_add_c(in, out, stride, txfm_param);
}
#if CONFIG_HIGHBITDEPTH
typedef void (*IhighbdHtFunc)(const tran_low_t *in, uint8_t *out, int stride,
TX_TYPE tx_type, int bd);
typedef void (*HBDFhtFunc)(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd);
// HighbdHt4x4Param argument list:
// <Target optimized function, tx_type, bit depth>
typedef tuple<HBDFhtFunc, TX_TYPE, int> HighbdHt4x4Param;
void highbe_fht4x4_ref(const int16_t *in, int32_t *out, int stride,
TX_TYPE tx_type, int bd) {
av1_fwd_txfm2d_4x4_c(in, out, stride, tx_type, bd);
}
#endif // CONFIG_HIGHBITDEPTH
class AV1Trans4x4HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht4x4Param> {
public:
virtual ~AV1Trans4x4HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 4;
height_ = 4;
fwd_txfm_ref = fht4x4_ref;
inv_txfm_ref = iht4x4_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans4x4HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans4x4HT, CoeffCheck) { RunCoeffCheck(); }
// Note:
// TODO(luoyi): Add tx_type, 9-15 for inverse transform.
// Need cleanup since same tests may be done in fdct4x4_test.cc
// TEST_P(AV1Trans4x4HT, AccuracyCheck) { RunAccuracyCheck(0); }
// TEST_P(AV1Trans4x4HT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
// TEST_P(AV1Trans4x4HT, InvCoeffCheck) { RunInvCoeffCheck(); }
#if CONFIG_HIGHBITDEPTH
class AV1HighbdTrans4x4HT : public ::testing::TestWithParam<HighbdHt4x4Param> {
public:
virtual ~AV1HighbdTrans4x4HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = highbe_fht4x4_ref;
tx_type_ = GET_PARAM(1);
bit_depth_ = GET_PARAM(2);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = 16;
input_ = reinterpret_cast<int16_t *>(
aom_memalign(16, sizeof(int16_t) * num_coeffs_));
output_ = reinterpret_cast<int32_t *>(
aom_memalign(16, sizeof(int32_t) * num_coeffs_));
output_ref_ = reinterpret_cast<int32_t *>(
aom_memalign(16, sizeof(int32_t) * num_coeffs_));
}
virtual void TearDown() {
aom_free(input_);
aom_free(output_);
aom_free(output_ref_);
libaom_test::ClearSystemState();
}
protected:
void RunBitexactCheck();
private:
HBDFhtFunc fwd_txfm_;
HBDFhtFunc fwd_txfm_ref_;
TX_TYPE tx_type_;
int bit_depth_;
int mask_;
int num_coeffs_;
int16_t *input_;
int32_t *output_;
int32_t *output_ref_;
};
void AV1HighbdTrans4x4HT::RunBitexactCheck() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i, j;
const int stride = 4;
const int num_tests = 1000;
const int num_coeffs = 16;
for (i = 0; i < num_tests; ++i) {
for (j = 0; j < num_coeffs; ++j) {
input_[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
}
fwd_txfm_ref_(input_, output_ref_, stride, tx_type_, bit_depth_);
fwd_txfm_(input_, output_, stride, tx_type_, bit_depth_);
for (j = 0; j < num_coeffs; ++j) {
EXPECT_EQ(output_[j], output_ref_[j])
<< "Not bit-exact result at index: " << j << " at test block: " << i;
}
}
}
TEST_P(AV1HighbdTrans4x4HT, HighbdCoeffCheck) { RunBitexactCheck(); }
#endif // CONFIG_HIGHBITDEPTH
using std::tr1::make_tuple;
#if HAVE_SSE2 && !CONFIG_DAALA_DCT4
const Ht4x4Param kArrayHt4x4Param_sse2[] = {
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, DCT_DCT, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, ADST_DCT, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, DCT_ADST, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, ADST_ADST, AOM_BITS_8,
16),
#if CONFIG_EXT_TX
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, IDTX, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, V_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, H_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, V_ADST, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, H_ADST, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, V_FLIPADST, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2, H_FLIPADST, AOM_BITS_8,
16)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans4x4HT,
::testing::ValuesIn(kArrayHt4x4Param_sse2));
#endif // HAVE_SSE2
#if HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT4
const HighbdHt4x4Param kArrayHighbdHt4x4Param[] = {
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, DCT_DCT, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, DCT_DCT, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, ADST_DCT, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, ADST_DCT, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, DCT_ADST, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, DCT_ADST, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, ADST_ADST, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, ADST_ADST, 12),
#if CONFIG_EXT_TX
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, FLIPADST_DCT, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, FLIPADST_DCT, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, DCT_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, DCT_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, FLIPADST_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, FLIPADST_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, ADST_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, ADST_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, FLIPADST_ADST, 10),
make_tuple(&av1_fwd_txfm2d_4x4_sse4_1, FLIPADST_ADST, 12),
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1HighbdTrans4x4HT,
::testing::ValuesIn(kArrayHighbdHt4x4Param));
#endif // HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT4
} // namespace

View file

@ -1,145 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht4x8Param;
void fht4x8_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht4x8_c(in, out, stride, txfm_param);
}
void iht4x8_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht4x8_32_add_c(in, out, stride, txfm_param);
}
class AV1Trans4x8HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht4x8Param> {
public:
virtual ~AV1Trans4x8HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 4;
height_ = 8;
fwd_txfm_ref = fht4x8_ref;
inv_txfm_ref = iht4x8_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans4x8HT, AccuracyCheck) { RunAccuracyCheck(0, 0.00001); }
TEST_P(AV1Trans4x8HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans4x8HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans4x8HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans4x8HT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
using std::tr1::make_tuple;
const Ht4x8Param kArrayHt4x8Param_c[] = {
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, DCT_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, ADST_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, DCT_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, ADST_ADST, AOM_BITS_8, 32),
#if CONFIG_EXT_TX
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, FLIPADST_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, DCT_FLIPADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, FLIPADST_FLIPADST, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, ADST_FLIPADST, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, FLIPADST_ADST, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, IDTX, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, V_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, H_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, V_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, H_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, V_FLIPADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_c, &av1_iht4x8_32_add_c, H_FLIPADST, AOM_BITS_8, 32)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans4x8HT,
::testing::ValuesIn(kArrayHt4x8Param_c));
#if HAVE_SSE2
const Ht4x8Param kArrayHt4x8Param_sse2[] = {
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, DCT_DCT, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, ADST_DCT, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, DCT_ADST, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, ADST_ADST, AOM_BITS_8,
32),
#if CONFIG_EXT_TX
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, IDTX, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, V_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, H_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, V_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, H_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, V_FLIPADST, AOM_BITS_8,
32),
make_tuple(&av1_fht4x8_sse2, &av1_iht4x8_32_add_sse2, H_FLIPADST, AOM_BITS_8,
32)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans4x8HT,
::testing::ValuesIn(kArrayHt4x8Param_sse2));
#endif // HAVE_SSE2
} // namespace

View file

@ -1,124 +0,0 @@
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#if CONFIG_TX64X64
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht64x64Param;
void fht64x64_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht64x64_c(in, out, stride, txfm_param);
}
void iht64x64_ref(const tran_low_t *in, uint8_t *dest, int stride,
const TxfmParam *txfm_param) {
av1_iht64x64_4096_add_c(in, dest, stride, txfm_param);
}
class AV1Trans64x64HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht64x64Param> {
public:
virtual ~AV1Trans64x64HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 64;
height_ = 64;
fwd_txfm_ref = fht64x64_ref;
inv_txfm_ref = iht64x64_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans64x64HT, AccuracyCheck) { RunAccuracyCheck(4, 0.2); }
TEST_P(AV1Trans64x64HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans64x64HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans64x64HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans64x64HT, InvAccuracyCheck) { RunInvAccuracyCheck(4); }
using std::tr1::make_tuple;
const Ht64x64Param kArrayHt64x64Param_c[] = {
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, DCT_DCT, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, ADST_DCT, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, DCT_ADST, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, ADST_ADST, AOM_BITS_8,
4096),
#if CONFIG_EXT_TX
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, FLIPADST_DCT,
AOM_BITS_8, 4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, DCT_FLIPADST,
AOM_BITS_8, 4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, FLIPADST_FLIPADST,
AOM_BITS_8, 4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, ADST_FLIPADST,
AOM_BITS_8, 4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, FLIPADST_ADST,
AOM_BITS_8, 4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, IDTX, AOM_BITS_8, 4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, V_DCT, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, H_DCT, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, V_ADST, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, H_ADST, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, V_FLIPADST, AOM_BITS_8,
4096),
make_tuple(&av1_fht64x64_c, &av1_iht64x64_4096_add_c, H_FLIPADST, AOM_BITS_8,
4096)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans64x64HT,
::testing::ValuesIn(kArrayHt64x64Param_c));
} // namespace
#endif // CONFIG_TX64X64

View file

@ -1,154 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht8x16Param;
void fht8x16_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht8x16_c(in, out, stride, txfm_param);
}
void iht8x16_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht8x16_128_add_c(in, out, stride, txfm_param);
}
class AV1Trans8x16HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht8x16Param> {
public:
virtual ~AV1Trans8x16HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 8;
height_ = 16;
inv_txfm_ref = iht8x16_ref;
fwd_txfm_ref = fht8x16_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans8x16HT, AccuracyCheck) { RunAccuracyCheck(1, 0.001); }
TEST_P(AV1Trans8x16HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans8x16HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans8x16HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans8x16HT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
using std::tr1::make_tuple;
const Ht8x16Param kArrayHt8x16Param_c[] = {
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, DCT_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, ADST_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, DCT_ADST, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, ADST_ADST, AOM_BITS_8,
128),
#if CONFIG_EXT_TX
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, FLIPADST_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, DCT_FLIPADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, FLIPADST_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, ADST_FLIPADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, FLIPADST_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, IDTX, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, V_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, H_DCT, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, V_ADST, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, H_ADST, AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, V_FLIPADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_c, &av1_iht8x16_128_add_c, H_FLIPADST, AOM_BITS_8,
128)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans8x16HT,
::testing::ValuesIn(kArrayHt8x16Param_c));
#if HAVE_SSE2
const Ht8x16Param kArrayHt8x16Param_sse2[] = {
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, DCT_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, ADST_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, DCT_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, ADST_ADST,
AOM_BITS_8, 128),
#if CONFIG_EXT_TX
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, IDTX, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, V_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, H_DCT, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, V_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, H_ADST, AOM_BITS_8,
128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, V_FLIPADST,
AOM_BITS_8, 128),
make_tuple(&av1_fht8x16_sse2, &av1_iht8x16_128_add_sse2, H_FLIPADST,
AOM_BITS_8, 128)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans8x16HT,
::testing::ValuesIn(kArrayHt8x16Param_sse2));
#endif // HAVE_SSE2
} // namespace

View file

@ -1,144 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using std::tr1::tuple;
using libaom_test::FhtFunc;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht8x4Param;
void fht8x4_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht8x4_c(in, out, stride, txfm_param);
}
void iht8x4_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht8x4_32_add_c(in, out, stride, txfm_param);
}
class AV1Trans8x4HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht8x4Param> {
public:
virtual ~AV1Trans8x4HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 8;
height_ = 4;
fwd_txfm_ref = fht8x4_ref;
inv_txfm_ref = iht8x4_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans8x4HT, AccuracyCheck) { RunAccuracyCheck(0, 0.00001); }
TEST_P(AV1Trans8x4HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(AV1Trans8x4HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans8x4HT, InvCoeffCheck) { RunInvCoeffCheck(); }
TEST_P(AV1Trans8x4HT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
using std::tr1::make_tuple;
const Ht8x4Param kArrayHt8x4Param_c[] = {
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, DCT_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, ADST_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, DCT_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, ADST_ADST, AOM_BITS_8, 32),
#if CONFIG_EXT_TX
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, FLIPADST_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, DCT_FLIPADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, FLIPADST_FLIPADST, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, ADST_FLIPADST, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, FLIPADST_ADST, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, IDTX, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, V_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, H_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, V_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, H_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, V_FLIPADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_c, &av1_iht8x4_32_add_c, H_FLIPADST, AOM_BITS_8, 32)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(C, AV1Trans8x4HT,
::testing::ValuesIn(kArrayHt8x4Param_c));
#if HAVE_SSE2
const Ht8x4Param kArrayHt8x4Param_sse2[] = {
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, DCT_DCT, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, ADST_DCT, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, DCT_ADST, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, ADST_ADST, AOM_BITS_8,
32),
#if CONFIG_EXT_TX
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, IDTX, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, V_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, H_DCT, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, V_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, H_ADST, AOM_BITS_8, 32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, V_FLIPADST, AOM_BITS_8,
32),
make_tuple(&av1_fht8x4_sse2, &av1_iht8x4_32_add_sse2, H_FLIPADST, AOM_BITS_8,
32)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans8x4HT,
::testing::ValuesIn(kArrayHt8x4Param_sse2));
#endif // HAVE_SSE2
} // namespace

View file

@ -1,233 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#include "aom_ports/mem.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using libaom_test::FhtFunc;
using std::tr1::tuple;
typedef tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int> Ht8x8Param;
void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht8x8_c(in, out, stride, txfm_param);
}
void iht8x8_ref(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_iht8x8_64_add_c(in, out, stride, txfm_param);
}
#if CONFIG_HIGHBITDEPTH
typedef void (*IHbdHtFunc)(const tran_low_t *in, uint8_t *out, int stride,
TX_TYPE tx_type, int bd);
typedef void (*HbdHtFunc)(const int16_t *input, int32_t *output, int stride,
TX_TYPE tx_type, int bd);
// Target optimized function, tx_type, bit depth
typedef tuple<HbdHtFunc, TX_TYPE, int> HighbdHt8x8Param;
void highbd_fht8x8_ref(const int16_t *in, int32_t *out, int stride,
TX_TYPE tx_type, int bd) {
av1_fwd_txfm2d_8x8_c(in, out, stride, tx_type, bd);
}
#endif // CONFIG_HIGHBITDEPTH
class AV1Trans8x8HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht8x8Param> {
public:
virtual ~AV1Trans8x8HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 8;
height_ = 8;
fwd_txfm_ref = fht8x8_ref;
inv_txfm_ref = iht8x8_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(AV1Trans8x8HT, MemCheck) { RunMemCheck(); }
TEST_P(AV1Trans8x8HT, CoeffCheck) { RunCoeffCheck(); }
// Note:
// TODO(luoyi): Add tx_type, 9-15 for inverse transform.
// Need cleanup since same tests may be done in fdct8x8_test.cc
// TEST_P(AV1Trans8x8HT, AccuracyCheck) { RunAccuracyCheck(0); }
// TEST_P(AV1Trans8x8HT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
// TEST_P(AV1Trans8x8HT, InvCoeffCheck) { RunInvCoeffCheck(); }
#if CONFIG_HIGHBITDEPTH
class AV1HighbdTrans8x8HT : public ::testing::TestWithParam<HighbdHt8x8Param> {
public:
virtual ~AV1HighbdTrans8x8HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
fwd_txfm_ref_ = highbd_fht8x8_ref;
tx_type_ = GET_PARAM(1);
bit_depth_ = GET_PARAM(2);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = 64;
input_ = reinterpret_cast<int16_t *>(
aom_memalign(16, sizeof(int16_t) * num_coeffs_));
output_ = reinterpret_cast<int32_t *>(
aom_memalign(16, sizeof(int32_t) * num_coeffs_));
output_ref_ = reinterpret_cast<int32_t *>(
aom_memalign(16, sizeof(int32_t) * num_coeffs_));
}
virtual void TearDown() {
aom_free(input_);
aom_free(output_);
aom_free(output_ref_);
libaom_test::ClearSystemState();
}
protected:
void RunBitexactCheck();
private:
HbdHtFunc fwd_txfm_;
HbdHtFunc fwd_txfm_ref_;
TX_TYPE tx_type_;
int bit_depth_;
int mask_;
int num_coeffs_;
int16_t *input_;
int32_t *output_;
int32_t *output_ref_;
};
void AV1HighbdTrans8x8HT::RunBitexactCheck() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i, j;
const int stride = 8;
const int num_tests = 1000;
const int num_coeffs = 64;
for (i = 0; i < num_tests; ++i) {
for (j = 0; j < num_coeffs; ++j) {
input_[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
}
fwd_txfm_ref_(input_, output_ref_, stride, tx_type_, bit_depth_);
ASM_REGISTER_STATE_CHECK(
fwd_txfm_(input_, output_, stride, tx_type_, bit_depth_));
for (j = 0; j < num_coeffs; ++j) {
EXPECT_EQ(output_ref_[j], output_[j])
<< "Not bit-exact result at index: " << j << " at test block: " << i;
}
}
}
TEST_P(AV1HighbdTrans8x8HT, HighbdCoeffCheck) { RunBitexactCheck(); }
#endif // CONFIG_HIGHBITDEPTH
using std::tr1::make_tuple;
#if HAVE_SSE2 && !CONFIG_DAALA_DCT8
const Ht8x8Param kArrayHt8x8Param_sse2[] = {
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, DCT_DCT, AOM_BITS_8,
64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, ADST_DCT, AOM_BITS_8,
64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, DCT_ADST, AOM_BITS_8,
64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, ADST_ADST, AOM_BITS_8,
64),
#if CONFIG_EXT_TX
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, FLIPADST_DCT,
AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, DCT_FLIPADST,
AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, FLIPADST_FLIPADST,
AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, ADST_FLIPADST,
AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, FLIPADST_ADST,
AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, IDTX, AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, V_DCT, AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, H_DCT, AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, V_ADST, AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, H_ADST, AOM_BITS_8, 64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, V_FLIPADST, AOM_BITS_8,
64),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2, H_FLIPADST, AOM_BITS_8,
64)
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1Trans8x8HT,
::testing::ValuesIn(kArrayHt8x8Param_sse2));
#endif // HAVE_SSE2
#if HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT8
const HighbdHt8x8Param kArrayHBDHt8x8Param_sse4_1[] = {
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, DCT_DCT, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, DCT_DCT, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, ADST_DCT, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, ADST_DCT, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, DCT_ADST, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, DCT_ADST, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, ADST_ADST, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, ADST_ADST, 12),
#if CONFIG_EXT_TX
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, FLIPADST_DCT, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, FLIPADST_DCT, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, DCT_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, DCT_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, FLIPADST_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, FLIPADST_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, ADST_FLIPADST, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, ADST_FLIPADST, 12),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, FLIPADST_ADST, 10),
make_tuple(&av1_fwd_txfm2d_8x8_sse4_1, FLIPADST_ADST, 12),
#endif // CONFIG_EXT_TX
};
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1HighbdTrans8x8HT,
::testing::ValuesIn(kArrayHBDHt8x8Param_sse4_1));
#endif // HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT8
} // namespace

View file

@ -9,36 +9,37 @@
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "av1/common/av1_fwd_txfm1d.h"
#include "av1/encoder/av1_fwd_txfm1d.h"
#include "test/av1_txfm_test.h"
using libaom_test::ACMRandom;
using libaom_test::TYPE_ADST;
using libaom_test::TYPE_DCT;
using libaom_test::TYPE_IDTX;
using libaom_test::TYPE_TXFM;
using libaom_test::input_base;
using libaom_test::reference_hybrid_1d;
using libaom_test::TYPE_TXFM;
using libaom_test::TYPE_DCT;
using libaom_test::TYPE_ADST;
namespace {
const int txfm_type_num = 2;
const TYPE_TXFM txfm_type_ls[2] = { TYPE_DCT, TYPE_ADST };
const int txfm_type_num = 3;
const TYPE_TXFM txfm_type_ls[txfm_type_num] = { TYPE_DCT, TYPE_ADST,
TYPE_IDTX };
const int txfm_size_num = 5;
const int txfm_size_ls[5] = { 4, 8, 16, 32, 64 };
const TxfmFunc fwd_txfm_func_ls[2][5] = {
#if CONFIG_TX64X64
{ av1_fdct4_new, av1_fdct8_new, av1_fdct16_new, av1_fdct32_new,
av1_fdct64_new },
#else
{ av1_fdct4_new, av1_fdct8_new, av1_fdct16_new, av1_fdct32_new, NULL },
#endif
{ av1_fadst4_new, av1_fadst8_new, av1_fadst16_new, av1_fadst32_new, NULL }
const int txfm_size_ls[] = { 4, 8, 16, 32, 64 };
const TxfmFunc fwd_txfm_func_ls[][txfm_type_num] = {
{ av1_fdct4_new, av1_fadst4_new, av1_fidentity4_c },
{ av1_fdct8_new, av1_fadst8_new, av1_fidentity8_c },
{ av1_fdct16_new, av1_fadst16_new, av1_fidentity16_c },
{ av1_fdct32_new, NULL, av1_fidentity32_c },
{ av1_fdct64_new, NULL, NULL },
};
// the maximum stage number of fwd/inv 1d dct/adst txfm is 12
const int8_t cos_bit[12] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
const int8_t range_bit[12] = { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 };
const int8_t cos_bit = 14;
const int8_t range_bit[12] = { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 };
TEST(av1_fwd_txfm1d, round_shift) {
EXPECT_EQ(round_shift(7, 1), 4);
@ -51,10 +52,10 @@ TEST(av1_fwd_txfm1d, round_shift) {
EXPECT_EQ(round_shift(-8, 2), -2);
}
TEST(av1_fwd_txfm1d, cospi_arr_data) {
TEST(av1_fwd_txfm1d, av1_cospi_arr_data) {
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 64; j++) {
EXPECT_EQ(cospi_arr_data[i][j],
EXPECT_EQ(av1_cospi_arr_data[i][j],
(int32_t)round(cos(M_PI * j / 128) * (1 << (cos_bit_min + i))));
}
}
@ -71,7 +72,7 @@ TEST(av1_fwd_txfm1d, accuracy) {
for (int ti = 0; ti < txfm_type_num; ++ti) {
TYPE_TXFM txfm_type = txfm_type_ls[ti];
TxfmFunc fwd_txfm_func = fwd_txfm_func_ls[ti][si];
TxfmFunc fwd_txfm_func = fwd_txfm_func_ls[si][ti];
int max_error = 7;
const int count_test_block = 5000;
@ -86,9 +87,10 @@ TEST(av1_fwd_txfm1d, accuracy) {
reference_hybrid_1d(ref_input, ref_output, txfm_size, txfm_type);
for (int ni = 0; ni < txfm_size; ++ni) {
EXPECT_LE(
ASSERT_LE(
abs(output[ni] - static_cast<int32_t>(round(ref_output[ni]))),
max_error);
max_error)
<< "tx size = " << txfm_size << ", tx type = " << txfm_type;
}
}
}

View file

@ -12,24 +12,26 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include "config/av1_rtcd.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "test/av1_txfm_test.h"
#include "av1/common/av1_txfm.h"
#include "./av1_rtcd.h"
using libaom_test::ACMRandom;
using libaom_test::input_base;
using libaom_test::TYPE_TXFM;
using libaom_test::bd;
using libaom_test::compute_avg_abs_error;
using libaom_test::Fwd_Txfm2d_Func;
using libaom_test::TYPE_TXFM;
using libaom_test::input_base;
using std::vector;
namespace {
#if CONFIG_HIGHBITDEPTH
// tx_type_, tx_size_, max_error_, max_avg_error_
typedef std::tr1::tuple<TX_TYPE, TX_SIZE, double, double> AV1FwdTxfm2dParam;
typedef ::testing::tuple<TX_TYPE, TX_SIZE, double, double> AV1FwdTxfm2dParam;
class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> {
public:
@ -39,22 +41,16 @@ class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> {
max_error_ = GET_PARAM(2);
max_avg_error_ = GET_PARAM(3);
count_ = 500;
TXFM_2D_FLIP_CFG fwd_txfm_flip_cfg =
av1_get_fwd_txfm_cfg(tx_type_, tx_size_);
// TODO(sarahparker) this test will need to be updated when these
// functions are extended to support rectangular transforms
int amplify_bit = fwd_txfm_flip_cfg.row_cfg->shift[0] +
fwd_txfm_flip_cfg.row_cfg->shift[1] +
fwd_txfm_flip_cfg.row_cfg->shift[2];
TXFM_2D_FLIP_CFG fwd_txfm_flip_cfg;
av1_get_fwd_txfm_cfg(tx_type_, tx_size_, &fwd_txfm_flip_cfg);
amplify_factor_ = libaom_test::get_amplification_factor(tx_type_, tx_size_);
tx_width_ = tx_size_wide[fwd_txfm_flip_cfg.tx_size];
tx_height_ = tx_size_high[fwd_txfm_flip_cfg.tx_size];
ud_flip_ = fwd_txfm_flip_cfg.ud_flip;
lr_flip_ = fwd_txfm_flip_cfg.lr_flip;
amplify_factor_ =
amplify_bit >= 0 ? (1 << amplify_bit) : (1.0 / (1 << -amplify_bit));
fwd_txfm_ = libaom_test::fwd_txfm_func_ls[tx_size_];
txfm1d_size_ = libaom_test::get_txfm1d_size(tx_size_);
txfm2d_size_ = txfm1d_size_ * txfm1d_size_;
get_txfm1d_type(tx_type_, &type0_, &type1_);
txfm2d_size_ = tx_width_ * tx_height_;
input_ = reinterpret_cast<int16_t *>(
aom_memalign(16, sizeof(input_[0]) * txfm2d_size_));
output_ = reinterpret_cast<int32_t *>(
@ -76,33 +72,40 @@ class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> {
ref_output_[ni] = 0;
}
fwd_txfm_(input_, output_, txfm1d_size_, tx_type_, bd);
fwd_txfm_(input_, output_, tx_width_, tx_type_, bd);
if (lr_flip_ && ud_flip_)
libaom_test::fliplrud(ref_input_, txfm1d_size_, txfm1d_size_);
else if (lr_flip_)
libaom_test::fliplr(ref_input_, txfm1d_size_, txfm1d_size_);
else if (ud_flip_)
libaom_test::flipud(ref_input_, txfm1d_size_, txfm1d_size_);
reference_hybrid_2d(ref_input_, ref_output_, txfm1d_size_, type0_,
type1_);
for (int ni = 0; ni < txfm2d_size_; ++ni) {
ref_output_[ni] = round(ref_output_[ni] * amplify_factor_);
EXPECT_GE(max_error_,
fabs(output_[ni] - ref_output_[ni]) / amplify_factor_);
if (lr_flip_ && ud_flip_) {
libaom_test::fliplrud(ref_input_, tx_width_, tx_height_, tx_width_);
} else if (lr_flip_) {
libaom_test::fliplr(ref_input_, tx_width_, tx_height_, tx_width_);
} else if (ud_flip_) {
libaom_test::flipud(ref_input_, tx_width_, tx_height_, tx_width_);
}
libaom_test::reference_hybrid_2d(ref_input_, ref_output_, tx_type_,
tx_size_);
double actual_max_error = 0;
for (int ni = 0; ni < txfm2d_size_; ++ni) {
ref_output_[ni] = round(ref_output_[ni]);
const double this_error =
fabs(output_[ni] - ref_output_[ni]) / amplify_factor_;
actual_max_error = AOMMAX(actual_max_error, this_error);
}
EXPECT_GE(max_error_, actual_max_error)
<< "tx_size = " << tx_size_ << ", tx_type = " << tx_type_;
if (actual_max_error > max_error_) { // exit early.
break;
}
avg_abs_error += compute_avg_abs_error<int32_t, double>(
output_, ref_output_, txfm2d_size_);
}
avg_abs_error /= amplify_factor_;
avg_abs_error /= count_;
// max_abs_avg_error comes from upper bound of avg_abs_error
// printf("type0: %d type1: %d txfm_size: %d accuracy_avg_abs_error:
// %f\n", type0_, type1_, txfm1d_size_, avg_abs_error);
EXPECT_GE(max_avg_error_, avg_abs_error);
EXPECT_GE(max_avg_error_, avg_abs_error)
<< "tx_size = " << tx_size_ << ", tx_type = " << tx_type_;
}
virtual void TearDown() {
@ -119,11 +122,10 @@ class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> {
double amplify_factor_;
TX_TYPE tx_type_;
TX_SIZE tx_size_;
int txfm1d_size_;
int tx_width_;
int tx_height_;
int txfm2d_size_;
Fwd_Txfm2d_Func fwd_txfm_;
TYPE_TXFM type0_;
TYPE_TXFM type1_;
FwdTxfm2dFunc fwd_txfm_;
int16_t *input_;
int32_t *output_;
double *ref_input_;
@ -132,76 +134,209 @@ class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> {
int lr_flip_; // flip left to right
};
TEST_P(AV1FwdTxfm2d, RunFwdAccuracyCheck) { RunFwdAccuracyCheck(); }
const AV1FwdTxfm2dParam av1_fwd_txfm2d_param_c[] = {
#if CONFIG_EXT_TX
AV1FwdTxfm2dParam(FLIPADST_DCT, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(DCT_FLIPADST, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(ADST_FLIPADST, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(FLIPADST_ADST, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(FLIPADST_DCT, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(DCT_FLIPADST, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(ADST_FLIPADST, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(FLIPADST_ADST, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(FLIPADST_DCT, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(DCT_FLIPADST, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(ADST_FLIPADST, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(FLIPADST_ADST, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(FLIPADST_DCT, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(DCT_FLIPADST, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(FLIPADST_FLIPADST, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(ADST_FLIPADST, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(FLIPADST_ADST, TX_32X32, 70, 7),
#endif
AV1FwdTxfm2dParam(DCT_DCT, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(ADST_DCT, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(DCT_ADST, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(ADST_ADST, TX_4X4, 2, 0.2),
AV1FwdTxfm2dParam(DCT_DCT, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(ADST_DCT, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(DCT_ADST, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(ADST_ADST, TX_8X8, 5, 0.6),
AV1FwdTxfm2dParam(DCT_DCT, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(ADST_DCT, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(DCT_ADST, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(ADST_ADST, TX_16X16, 11, 1.5),
AV1FwdTxfm2dParam(DCT_DCT, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(ADST_DCT, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(DCT_ADST, TX_32X32, 70, 7),
AV1FwdTxfm2dParam(ADST_ADST, TX_32X32, 70, 7)
static double avg_error_ls[TX_SIZES_ALL] = {
0.5, // 4x4 transform
0.5, // 8x8 transform
1.2, // 16x16 transform
6.1, // 32x32 transform
3.4, // 64x64 transform
0.57, // 4x8 transform
0.68, // 8x4 transform
0.92, // 8x16 transform
1.1, // 16x8 transform
4.1, // 16x32 transform
6, // 32x16 transform
3.5, // 32x64 transform
5.7, // 64x32 transform
0.6, // 4x16 transform
0.9, // 16x4 transform
1.2, // 8x32 transform
1.7, // 32x8 transform
2.0, // 16x64 transform
4.7, // 64x16 transform
};
static double max_error_ls[TX_SIZES_ALL] = {
3, // 4x4 transform
5, // 8x8 transform
11, // 16x16 transform
70, // 32x32 transform
64, // 64x64 transform
3.9, // 4x8 transform
4.3, // 8x4 transform
12, // 8x16 transform
12, // 16x8 transform
32, // 16x32 transform
46, // 32x16 transform
136, // 32x64 transform
136, // 64x32 transform
5, // 4x16 transform
6, // 16x4 transform
21, // 8x32 transform
13, // 32x8 transform
30, // 16x64 transform
36, // 64x16 transform
};
vector<AV1FwdTxfm2dParam> GetTxfm2dParamList() {
vector<AV1FwdTxfm2dParam> param_list;
for (int s = 0; s < TX_SIZES; ++s) {
const double max_error = max_error_ls[s];
const double avg_error = avg_error_ls[s];
for (int t = 0; t < TX_TYPES; ++t) {
const TX_TYPE tx_type = static_cast<TX_TYPE>(t);
const TX_SIZE tx_size = static_cast<TX_SIZE>(s);
if (libaom_test::IsTxSizeTypeValid(tx_size, tx_type)) {
param_list.push_back(
AV1FwdTxfm2dParam(tx_type, tx_size, max_error, avg_error));
}
}
}
return param_list;
}
INSTANTIATE_TEST_CASE_P(C, AV1FwdTxfm2d,
::testing::ValuesIn(av1_fwd_txfm2d_param_c));
::testing::ValuesIn(GetTxfm2dParamList()));
TEST_P(AV1FwdTxfm2d, RunFwdAccuracyCheck) { RunFwdAccuracyCheck(); }
TEST(AV1FwdTxfm2d, CfgTest) {
for (int bd_idx = 0; bd_idx < BD_NUM; ++bd_idx) {
int bd = libaom_test::bd_arr[bd_idx];
int8_t low_range = libaom_test::low_range_arr[bd_idx];
int8_t high_range = libaom_test::high_range_arr[bd_idx];
// TODO(angiebird): include rect txfm in this test
for (int tx_size = 0; tx_size < TX_SIZES; ++tx_size) {
for (int tx_size = 0; tx_size < TX_SIZES_ALL; ++tx_size) {
for (int tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
TXFM_2D_FLIP_CFG cfg = av1_get_fwd_txfm_cfg(
static_cast<TX_TYPE>(tx_type), static_cast<TX_SIZE>(tx_size));
if (libaom_test::IsTxSizeTypeValid(static_cast<TX_SIZE>(tx_size),
static_cast<TX_TYPE>(tx_type)) ==
false) {
continue;
}
TXFM_2D_FLIP_CFG cfg;
av1_get_fwd_txfm_cfg(static_cast<TX_TYPE>(tx_type),
static_cast<TX_SIZE>(tx_size), &cfg);
int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
av1_gen_fwd_stage_range(stage_range_col, stage_range_row, &cfg, bd);
const TXFM_1D_CFG *col_cfg = cfg.col_cfg;
const TXFM_1D_CFG *row_cfg = cfg.row_cfg;
libaom_test::txfm_stage_range_check(stage_range_col, col_cfg->stage_num,
col_cfg->cos_bit, low_range,
libaom_test::txfm_stage_range_check(stage_range_col, cfg.stage_num_col,
cfg.cos_bit_col, low_range,
high_range);
libaom_test::txfm_stage_range_check(stage_range_row, row_cfg->stage_num,
row_cfg->cos_bit, low_range,
libaom_test::txfm_stage_range_check(stage_range_row, cfg.stage_num_row,
cfg.cos_bit_row, low_range,
high_range);
}
}
}
}
#endif // CONFIG_HIGHBITDEPTH
typedef void (*lowbd_fwd_txfm_func)(const int16_t *src_diff, tran_low_t *coeff,
int diff_stride, TxfmParam *txfm_param);
void AV1FwdTxfm2dMatchTest(TX_SIZE tx_size, lowbd_fwd_txfm_func target_func) {
const int bd = 8;
TxfmParam param;
memset(&param, 0, sizeof(param));
const int rows = tx_size_high[tx_size];
const int cols = tx_size_wide[tx_size];
// printf("%d x %d\n", cols, rows);
for (int tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
if (libaom_test::IsTxSizeTypeValid(
tx_size, static_cast<TX_TYPE>(tx_type)) == false) {
continue;
}
FwdTxfm2dFunc ref_func = libaom_test::fwd_txfm_func_ls[tx_size];
if (ref_func != NULL) {
DECLARE_ALIGNED(16, int16_t, input[64 * 64]) = { 0 };
DECLARE_ALIGNED(16, int32_t, output[64 * 64]);
DECLARE_ALIGNED(16, int32_t, ref_output[64 * 64]);
int input_stride = 64;
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int cnt = 0; cnt < 500; ++cnt) {
if (cnt == 0) {
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
input[r * input_stride + c] = (1 << bd) - 1;
}
}
} else {
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
input[r * input_stride + c] = rnd.Rand16() % (1 << bd);
}
}
}
param.tx_type = (TX_TYPE)tx_type;
param.tx_size = (TX_SIZE)tx_size;
param.tx_set_type = EXT_TX_SET_ALL16;
param.bd = bd;
ref_func(input, ref_output, input_stride, (TX_TYPE)tx_type, bd);
target_func(input, output, input_stride, &param);
const int check_rows = AOMMIN(32, rows);
const int check_cols = AOMMIN(32, rows * cols / check_rows);
for (int r = 0; r < check_rows; ++r) {
for (int c = 0; c < check_cols; ++c) {
ASSERT_EQ(ref_output[r * check_cols + c],
output[r * check_cols + c])
<< "[" << r << "," << c << "] cnt:" << cnt
<< " tx_size: " << tx_size << " tx_type: " << tx_type;
}
}
}
}
}
}
typedef ::testing::tuple<TX_SIZE, lowbd_fwd_txfm_func> LbdFwdTxfm2dParam;
class AV1FwdTxfm2dTest : public ::testing::TestWithParam<LbdFwdTxfm2dParam> {};
TEST_P(AV1FwdTxfm2dTest, match) {
AV1FwdTxfm2dMatchTest(GET_PARAM(0), GET_PARAM(1));
}
using ::testing::Combine;
using ::testing::Values;
using ::testing::ValuesIn;
#if HAVE_SSE2
static TX_SIZE fwd_txfm_for_sse2[] = {
TX_4X4,
TX_8X8,
TX_16X16,
TX_32X32,
// TX_64X64,
TX_4X8,
TX_8X4,
TX_8X16,
TX_16X8,
TX_16X32,
TX_32X16,
// TX_32X64,
// TX_64X32,
TX_4X16,
TX_16X4,
TX_8X32,
TX_32X8,
TX_16X64,
TX_64X16,
};
INSTANTIATE_TEST_CASE_P(SSE2, AV1FwdTxfm2dTest,
Combine(ValuesIn(fwd_txfm_for_sse2),
Values(av1_lowbd_fwd_txfm_sse2)));
#endif // HAVE_SSE2
#if HAVE_SSE4_1
static TX_SIZE fwd_txfm_for_sse41[] = {
TX_4X4,
TX_64X64,
TX_32X64,
TX_64X32,
};
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1FwdTxfm2dTest,
Combine(ValuesIn(fwd_txfm_for_sse41),
Values(av1_lowbd_fwd_txfm_sse4_1)));
#endif // HAVE_SSE4_1
} // namespace

View file

@ -11,7 +11,8 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "config/av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
@ -22,7 +23,7 @@
namespace {
using std::tr1::tuple;
using ::testing::tuple;
using libaom_test::ACMRandom;
typedef void (*HbdHtFunc)(const int16_t *input, int32_t *output, int stride,
@ -88,6 +89,8 @@ class AV1HighbdInvHTNxN : public ::testing::TestWithParam<IHbdHtParam> {
return 16;
} else if (1024 == num_coeffs_) {
return 32;
} else if (4096 == num_coeffs_) {
return 64;
} else {
return 0;
}
@ -133,28 +136,24 @@ void AV1HighbdInvHTNxN::RunBitexactCheck() {
TEST_P(AV1HighbdInvHTNxN, InvTransResultCheck) { RunBitexactCheck(); }
using std::tr1::make_tuple;
using ::testing::make_tuple;
#if HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH && \
!(CONFIG_DAALA_DCT4 && CONFIG_DAALA_DCT8 && CONFIG_DAALA_DCT16)
#if !CONFIG_DAALA_DCT4
#if HAVE_SSE4_1
#define PARAM_LIST_4X4 \
&av1_fwd_txfm2d_4x4_c, &av1_inv_txfm2d_add_4x4_sse4_1, \
&av1_inv_txfm2d_add_4x4_c, 16
#endif
#if !CONFIG_DAALA_DCT8
#define PARAM_LIST_8X8 \
&av1_fwd_txfm2d_8x8_c, &av1_inv_txfm2d_add_8x8_sse4_1, \
&av1_inv_txfm2d_add_8x8_c, 64
#endif
#if !CONFIG_DAALA_DCT16
#define PARAM_LIST_16X16 \
&av1_fwd_txfm2d_16x16_c, &av1_inv_txfm2d_add_16x16_sse4_1, \
&av1_inv_txfm2d_add_16x16_c, 256
#endif
#define PARAM_LIST_64X64 \
&av1_fwd_txfm2d_64x64_c, &av1_inv_txfm2d_add_64x64_sse4_1, \
&av1_inv_txfm2d_add_64x64_c, 4096
const IHbdHtParam kArrayIhtParam[] = {
// 16x16
#if !CONFIG_DAALA_DCT16
// 16x16
make_tuple(PARAM_LIST_16X16, DCT_DCT, 10),
make_tuple(PARAM_LIST_16X16, DCT_DCT, 12),
make_tuple(PARAM_LIST_16X16, ADST_DCT, 10),
@ -163,7 +162,6 @@ const IHbdHtParam kArrayIhtParam[] = {
make_tuple(PARAM_LIST_16X16, DCT_ADST, 12),
make_tuple(PARAM_LIST_16X16, ADST_ADST, 10),
make_tuple(PARAM_LIST_16X16, ADST_ADST, 12),
#if CONFIG_EXT_TX
make_tuple(PARAM_LIST_16X16, FLIPADST_DCT, 10),
make_tuple(PARAM_LIST_16X16, FLIPADST_DCT, 12),
make_tuple(PARAM_LIST_16X16, DCT_FLIPADST, 10),
@ -174,10 +172,7 @@ const IHbdHtParam kArrayIhtParam[] = {
make_tuple(PARAM_LIST_16X16, ADST_FLIPADST, 12),
make_tuple(PARAM_LIST_16X16, FLIPADST_ADST, 10),
make_tuple(PARAM_LIST_16X16, FLIPADST_ADST, 12),
#endif
#endif
// 8x8
#if !CONFIG_DAALA_DCT8
// 8x8
make_tuple(PARAM_LIST_8X8, DCT_DCT, 10),
make_tuple(PARAM_LIST_8X8, DCT_DCT, 12),
make_tuple(PARAM_LIST_8X8, ADST_DCT, 10),
@ -186,7 +181,6 @@ const IHbdHtParam kArrayIhtParam[] = {
make_tuple(PARAM_LIST_8X8, DCT_ADST, 12),
make_tuple(PARAM_LIST_8X8, ADST_ADST, 10),
make_tuple(PARAM_LIST_8X8, ADST_ADST, 12),
#if CONFIG_EXT_TX
make_tuple(PARAM_LIST_8X8, FLIPADST_DCT, 10),
make_tuple(PARAM_LIST_8X8, FLIPADST_DCT, 12),
make_tuple(PARAM_LIST_8X8, DCT_FLIPADST, 10),
@ -197,10 +191,7 @@ const IHbdHtParam kArrayIhtParam[] = {
make_tuple(PARAM_LIST_8X8, ADST_FLIPADST, 12),
make_tuple(PARAM_LIST_8X8, FLIPADST_ADST, 10),
make_tuple(PARAM_LIST_8X8, FLIPADST_ADST, 12),
#endif
#endif
// 4x4
#if !CONFIG_DAALA_DCT4
// 4x4
make_tuple(PARAM_LIST_4X4, DCT_DCT, 10),
make_tuple(PARAM_LIST_4X4, DCT_DCT, 12),
make_tuple(PARAM_LIST_4X4, ADST_DCT, 10),
@ -209,7 +200,6 @@ const IHbdHtParam kArrayIhtParam[] = {
make_tuple(PARAM_LIST_4X4, DCT_ADST, 12),
make_tuple(PARAM_LIST_4X4, ADST_ADST, 10),
make_tuple(PARAM_LIST_4X4, ADST_ADST, 12),
#if CONFIG_EXT_TX
make_tuple(PARAM_LIST_4X4, FLIPADST_DCT, 10),
make_tuple(PARAM_LIST_4X4, FLIPADST_DCT, 12),
make_tuple(PARAM_LIST_4X4, DCT_FLIPADST, 10),
@ -220,16 +210,15 @@ const IHbdHtParam kArrayIhtParam[] = {
make_tuple(PARAM_LIST_4X4, ADST_FLIPADST, 12),
make_tuple(PARAM_LIST_4X4, FLIPADST_ADST, 10),
make_tuple(PARAM_LIST_4X4, FLIPADST_ADST, 12),
#endif
#endif
make_tuple(PARAM_LIST_64X64, DCT_DCT, 10),
make_tuple(PARAM_LIST_64X64, DCT_DCT, 12),
};
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1HighbdInvHTNxN,
::testing::ValuesIn(kArrayIhtParam));
#endif // HAVE_SSE4_1 && CONFIG_HIGHBITDEPTH &&
// !(CONFIG_DAALA_DCT4 && CONFIG_DAALA_DCT8 && CONFIG_DAALA_DCT16)
#endif // HAVE_SSE4_1
#if HAVE_AVX2 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT32
#if HAVE_AVX2
#define PARAM_LIST_32X32 \
&av1_fwd_txfm2d_32x32_c, &av1_inv_txfm2d_add_32x32_avx2, \
&av1_inv_txfm2d_add_32x32_c, 1024
@ -243,5 +232,5 @@ const IHbdHtParam kArrayIhtParam32x32[] = {
INSTANTIATE_TEST_CASE_P(AVX2, AV1HighbdInvHTNxN,
::testing::ValuesIn(kArrayIhtParam32x32));
#endif // HAVE_AVX2 && CONFIG_HIGHBITDEPTH
#endif // HAVE_AVX2
} // namespace

View file

@ -0,0 +1,362 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <vector>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "config/av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/convolve.h"
#include "av1/common/resize.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
namespace {
const int kTestIters = 10;
const int kPerfIters = 1000;
const int kVPad = 32;
const int kHPad = 32;
using ::testing::make_tuple;
using ::testing::tuple;
using libaom_test::ACMRandom;
template <typename Pixel>
class TestImage {
public:
TestImage(int w_src, int h, int superres_denom, int x0, int bd)
: w_src_(w_src), h_(h), superres_denom_(superres_denom), x0_(x0),
bd_(bd) {
assert(bd < 16);
assert(bd <= 8 * static_cast<int>(sizeof(Pixel)));
assert(9 <= superres_denom && superres_denom <= 16);
assert(SCALE_NUMERATOR == 8);
assert(0 <= x0_ && x0_ <= RS_SCALE_SUBPEL_MASK);
w_dst_ = w_src_;
av1_calculate_unscaled_superres_size(&w_dst_, NULL, superres_denom);
src_stride_ = ALIGN_POWER_OF_TWO(w_src_ + 2 * kHPad, 4);
dst_stride_ = ALIGN_POWER_OF_TWO(w_dst_ + 2 * kHPad, 4);
// Allocate image data
src_data_.resize(2 * src_block_size());
dst_data_.resize(2 * dst_block_size());
}
void Initialize(ACMRandom *rnd);
void Check() const;
int src_stride() const { return src_stride_; }
int dst_stride() const { return dst_stride_; }
int src_block_size() const { return (h_ + 2 * kVPad) * src_stride(); }
int dst_block_size() const { return (h_ + 2 * kVPad) * dst_stride(); }
int src_width() const { return w_src_; }
int dst_width() const { return w_dst_; }
int height() const { return h_; }
int x0() const { return x0_; }
const Pixel *GetSrcData(bool ref, bool borders) const {
const Pixel *block = &src_data_[ref ? 0 : src_block_size()];
return borders ? block : block + kHPad + src_stride_ * kVPad;
}
Pixel *GetDstData(bool ref, bool borders) {
Pixel *block = &dst_data_[ref ? 0 : dst_block_size()];
return borders ? block : block + kHPad + dst_stride_ * kVPad;
}
private:
int w_src_, w_dst_, h_, superres_denom_, x0_, bd_;
int src_stride_, dst_stride_;
std::vector<Pixel> src_data_;
std::vector<Pixel> dst_data_;
};
template <typename Pixel>
void FillEdge(ACMRandom *rnd, int num_pixels, int bd, bool trash, Pixel *data) {
if (!trash) {
memset(data, 0, sizeof(*data) * num_pixels);
return;
}
const Pixel mask = (1 << bd) - 1;
for (int i = 0; i < num_pixels; ++i) data[i] = rnd->Rand16() & mask;
}
template <typename Pixel>
void PrepBuffers(ACMRandom *rnd, int w, int h, int stride, int bd,
bool trash_edges, Pixel *data) {
assert(rnd);
const Pixel mask = (1 << bd) - 1;
// Fill in the first buffer with random data
// Top border
FillEdge(rnd, stride * kVPad, bd, trash_edges, data);
for (int r = 0; r < h; ++r) {
Pixel *row_data = data + (kVPad + r) * stride;
// Left border, contents, right border
FillEdge(rnd, kHPad, bd, trash_edges, row_data);
for (int c = 0; c < w; ++c) row_data[kHPad + c] = rnd->Rand16() & mask;
FillEdge(rnd, kHPad, bd, trash_edges, row_data + kHPad + w);
}
// Bottom border
FillEdge(rnd, stride * kVPad, bd, trash_edges, data + stride * (kVPad + h));
const int bpp = sizeof(*data);
const int block_elts = stride * (h + 2 * kVPad);
const int block_size = bpp * block_elts;
// Now copy that to the second buffer
memcpy(data + block_elts, data, block_size);
}
template <typename Pixel>
void TestImage<Pixel>::Initialize(ACMRandom *rnd) {
PrepBuffers(rnd, w_src_, h_, src_stride_, bd_, false, &src_data_[0]);
PrepBuffers(rnd, w_dst_, h_, dst_stride_, bd_, true, &dst_data_[0]);
}
template <typename Pixel>
void TestImage<Pixel>::Check() const {
const int num_pixels = dst_block_size();
const Pixel *ref_dst = &dst_data_[0];
const Pixel *tst_dst = &dst_data_[num_pixels];
// If memcmp returns 0, there's nothing to do.
if (0 == memcmp(ref_dst, tst_dst, sizeof(*ref_dst) * num_pixels)) return;
// Otherwise, iterate through the buffer looking for differences, *ignoring
// the edges*
const int stride = dst_stride_;
for (int r = kVPad; r < h_ + kVPad; ++r) {
for (int c = kVPad; c < w_dst_ + kHPad; ++c) {
const int32_t ref_value = ref_dst[r * stride + c];
const int32_t tst_value = tst_dst[r * stride + c];
EXPECT_EQ(tst_value, ref_value)
<< "Error at row: " << (r - kVPad) << ", col: " << (c - kHPad)
<< ", superres_denom: " << superres_denom_ << ", height: " << h_
<< ", src_width: " << w_src_ << ", dst_width: " << w_dst_
<< ", x0: " << x0_;
}
}
}
template <typename Pixel>
class ConvolveHorizRSTestBase : public ::testing::Test {
public:
ConvolveHorizRSTestBase() : image_(NULL) {}
virtual ~ConvolveHorizRSTestBase() {}
virtual void TearDown() { libaom_test::ClearSystemState(); }
// Implemented by subclasses (SetUp depends on the parameters passed
// in and RunOne depends on the function to be tested. These can't
// be templated for low/high bit depths because they have different
// numbers of parameters)
virtual void SetUp() = 0;
virtual void RunOne(bool ref) = 0;
protected:
void SetBitDepth(int bd) { bd_ = bd; }
void CorrectnessTest() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int i = 0; i < kTestIters; ++i) {
for (int superres_denom = 9; superres_denom <= 16; superres_denom++) {
// Get a random height between 512 and 767
int height = rnd.Rand8() + 512;
// Get a random src width between 128 and 383
int width_src = rnd.Rand8() + 128;
// x0 is normally calculated by get_upscale_convolve_x0 in
// av1/common/resize.c. However, this test should work for
// any value of x0 between 0 and RS_SCALE_SUBPEL_MASK
// (inclusive), so we choose one at random.
int x0 = rnd.Rand16() % (RS_SCALE_SUBPEL_MASK + 1);
image_ =
new TestImage<Pixel>(width_src, height, superres_denom, x0, bd_);
Prep(&rnd);
RunOne(true);
RunOne(false);
image_->Check();
delete image_;
}
}
}
void SpeedTest() {
// Pick some specific parameters to test
int height = 767;
int width_src = 129;
int superres_denom = 13;
int x0 = RS_SCALE_SUBPEL_MASK >> 1;
image_ = new TestImage<Pixel>(width_src, height, superres_denom, x0, bd_);
ACMRandom rnd(ACMRandom::DeterministicSeed());
Prep(&rnd);
aom_usec_timer ref_timer;
aom_usec_timer_start(&ref_timer);
for (int i = 0; i < kPerfIters; ++i) RunOne(true);
aom_usec_timer_mark(&ref_timer);
const int64_t ref_time = aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer tst_timer;
aom_usec_timer_start(&tst_timer);
for (int i = 0; i < kPerfIters; ++i) RunOne(false);
aom_usec_timer_mark(&tst_timer);
const int64_t tst_time = aom_usec_timer_elapsed(&tst_timer);
std::cout << "[ ] C time = " << ref_time / 1000
<< " ms, SIMD time = " << tst_time / 1000 << " ms\n";
EXPECT_GT(ref_time, tst_time)
<< "Error: ConvolveHorizRSTest (Speed Test), SIMD slower than C.\n"
<< "C time: " << ref_time << " us\n"
<< "SIMD time: " << tst_time << " us\n";
}
void Prep(ACMRandom *rnd) {
assert(rnd);
image_->Initialize(rnd);
}
int bd_;
TestImage<Pixel> *image_;
};
typedef void (*LowBDConvolveHorizRsFunc)(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride, int w,
int h, const int16_t *x_filters,
const int x0_qn, const int x_step_qn);
// Test parameter list:
// <tst_fun_>
typedef tuple<LowBDConvolveHorizRsFunc> LowBDParams;
class LowBDConvolveHorizRSTest
: public ConvolveHorizRSTestBase<uint8_t>,
public ::testing::WithParamInterface<LowBDParams> {
public:
virtual ~LowBDConvolveHorizRSTest() {}
void SetUp() {
tst_fun_ = GET_PARAM(0);
const int bd = 8;
SetBitDepth(bd);
}
void RunOne(bool ref) {
const uint8_t *src = image_->GetSrcData(ref, false);
uint8_t *dst = image_->GetDstData(ref, false);
const int src_stride = image_->src_stride();
const int dst_stride = image_->dst_stride();
const int width_src = image_->src_width();
const int width_dst = image_->dst_width();
const int height = image_->height();
const int x0_qn = image_->x0();
const int32_t x_step_qn =
av1_get_upscale_convolve_step(width_src, width_dst);
if (ref) {
av1_convolve_horiz_rs_c(src, src_stride, dst, dst_stride, width_dst,
height, &av1_resize_filter_normative[0][0], x0_qn,
x_step_qn);
} else {
tst_fun_(src, src_stride, dst, dst_stride, width_dst, height,
&av1_resize_filter_normative[0][0], x0_qn, x_step_qn);
}
}
private:
LowBDConvolveHorizRsFunc tst_fun_;
};
TEST_P(LowBDConvolveHorizRSTest, Correctness) { CorrectnessTest(); }
TEST_P(LowBDConvolveHorizRSTest, DISABLED_Speed) { SpeedTest(); }
INSTANTIATE_TEST_CASE_P(SSE4_1, LowBDConvolveHorizRSTest,
::testing::Values(av1_convolve_horiz_rs_sse4_1));
typedef void (*HighBDConvolveHorizRsFunc)(const uint16_t *src, int src_stride,
uint16_t *dst, int dst_stride, int w,
int h, const int16_t *x_filters,
const int x0_qn, const int x_step_qn,
int bd);
// Test parameter list:
// <tst_fun_, bd_>
typedef tuple<HighBDConvolveHorizRsFunc, int> HighBDParams;
class HighBDConvolveHorizRSTest
: public ConvolveHorizRSTestBase<uint16_t>,
public ::testing::WithParamInterface<HighBDParams> {
public:
virtual ~HighBDConvolveHorizRSTest() {}
void SetUp() {
tst_fun_ = GET_PARAM(0);
const int bd = GET_PARAM(1);
SetBitDepth(bd);
}
void RunOne(bool ref) {
const uint16_t *src = image_->GetSrcData(ref, false);
uint16_t *dst = image_->GetDstData(ref, false);
const int src_stride = image_->src_stride();
const int dst_stride = image_->dst_stride();
const int width_src = image_->src_width();
const int width_dst = image_->dst_width();
const int height = image_->height();
const int x0_qn = image_->x0();
const int32_t x_step_qn =
av1_get_upscale_convolve_step(width_src, width_dst);
if (ref) {
av1_highbd_convolve_horiz_rs_c(
src, src_stride, dst, dst_stride, width_dst, height,
&av1_resize_filter_normative[0][0], x0_qn, x_step_qn, bd_);
} else {
tst_fun_(src, src_stride, dst, dst_stride, width_dst, height,
&av1_resize_filter_normative[0][0], x0_qn, x_step_qn, bd_);
}
}
private:
HighBDConvolveHorizRsFunc tst_fun_;
};
const int kBDs[] = { 8, 10, 12 };
TEST_P(HighBDConvolveHorizRSTest, Correctness) { CorrectnessTest(); }
TEST_P(HighBDConvolveHorizRSTest, DISABLED_Speed) { SpeedTest(); }
INSTANTIATE_TEST_CASE_P(
SSE4_1, HighBDConvolveHorizRSTest,
::testing::Combine(::testing::Values(av1_highbd_convolve_horiz_rs_sse4_1),
::testing::ValuesIn(kBDs)));
} // namespace

View file

@ -13,39 +13,35 @@
#include "test/av1_txfm_test.h"
#include "test/util.h"
#include "av1/common/av1_fwd_txfm1d.h"
#include "av1/common/av1_inv_txfm1d.h"
#include "av1/encoder/av1_fwd_txfm1d.h"
using libaom_test::ACMRandom;
using libaom_test::input_base;
namespace {
const int txfm_type_num = 2;
const int txfm_size_ls[5] = { 4, 8, 16, 32, 64 };
const int txfm_size_ls[] = { 4, 8, 16, 32, 64 };
const TxfmFunc fwd_txfm_func_ls[][2] = {
const TxfmFunc fwd_txfm_func_ls[][txfm_type_num] = {
{ av1_fdct4_new, av1_fadst4_new },
{ av1_fdct8_new, av1_fadst8_new },
{ av1_fdct16_new, av1_fadst16_new },
{ av1_fdct32_new, av1_fadst32_new },
#if CONFIG_TX64X64
{ av1_fdct32_new, NULL },
{ av1_fdct64_new, NULL },
#endif
};
const TxfmFunc inv_txfm_func_ls[][2] = {
const TxfmFunc inv_txfm_func_ls[][txfm_type_num] = {
{ av1_idct4_new, av1_iadst4_new },
{ av1_idct8_new, av1_iadst8_new },
{ av1_idct16_new, av1_iadst16_new },
{ av1_idct32_new, av1_iadst32_new },
#if CONFIG_TX64X64
{ av1_idct32_new, NULL },
{ av1_idct64_new, NULL },
#endif
};
// the maximum stage number of fwd/inv 1d dct/adst txfm is 12
const int8_t cos_bit[12] = { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 };
const int8_t range_bit[12] = { 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 };
const int8_t cos_bit = 13;
const int8_t range_bit[12] = { 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 };
void reference_idct_1d_int(const int32_t *in, int32_t *out, int size) {
double input[64];
@ -54,8 +50,11 @@ void reference_idct_1d_int(const int32_t *in, int32_t *out, int size) {
double output[64];
libaom_test::reference_idct_1d(input, output, size);
for (int i = 0; i < size; ++i)
for (int i = 0; i < size; ++i) {
ASSERT_GE(output[i], INT32_MIN);
ASSERT_LE(output[i], INT32_MAX);
out[i] = static_cast<int32_t>(round(output[i]));
}
}
void random_matrix(int32_t *dst, int len, ACMRandom *rnd) {
@ -73,24 +72,32 @@ void random_matrix(int32_t *dst, int len, ACMRandom *rnd) {
TEST(av1_inv_txfm1d, InvAccuracyCheck) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int count_test_block = 20000;
const int max_error[] = { 6, 10, 19, 28 };
const int max_error[] = { 6, 10, 19, 31, 40 };
ASSERT_EQ(NELEMENTS(max_error), TX_SIZES);
ASSERT_EQ(NELEMENTS(inv_txfm_func_ls), TX_SIZES);
for (int k = 0; k < count_test_block; ++k) {
// choose a random transform to test
const int txfm_type = rnd.Rand8() % NELEMENTS(inv_txfm_func_ls);
const int txfm_size = txfm_size_ls[txfm_type];
const TxfmFunc txfm_func = inv_txfm_func_ls[txfm_type][0];
const TX_SIZE tx_size = static_cast<TX_SIZE>(rnd.Rand8() % TX_SIZES);
const int tx_size_pix = txfm_size_ls[tx_size];
const TxfmFunc inv_txfm_func = inv_txfm_func_ls[tx_size][0];
int32_t input[64];
random_matrix(input, txfm_size, &rnd);
random_matrix(input, tx_size_pix, &rnd);
// 64x64 transform assumes last 32 values are zero.
memset(input + 32, 0, 32 * sizeof(input[0]));
int32_t ref_output[64];
reference_idct_1d_int(input, ref_output, txfm_size);
reference_idct_1d_int(input, ref_output, tx_size_pix);
int32_t output[64];
txfm_func(input, output, cos_bit, range_bit);
inv_txfm_func(input, output, cos_bit, range_bit);
for (int i = 0; i < txfm_size; ++i) {
EXPECT_LE(abs(output[i] - ref_output[i]), max_error[txfm_type]);
for (int i = 0; i < tx_size_pix; ++i) {
EXPECT_LE(abs(output[i] - ref_output[i]), max_error[tx_size])
<< "tx_size = " << tx_size << ", i = " << i
<< ", output[i] = " << output[i]
<< ", ref_output[i] = " << ref_output[i];
}
}
}

View file

@ -12,26 +12,35 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include "./av1_rtcd.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "test/av1_txfm_test.h"
#include "config/av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/av1_inv_txfm1d_cfg.h"
#include "av1/common/scan.h"
#include "test/acm_random.h"
#include "test/av1_txfm_test.h"
#include "test/util.h"
using libaom_test::ACMRandom;
using libaom_test::input_base;
using libaom_test::InvTxfm2dFunc;
using libaom_test::LbdInvTxfm2dFunc;
using libaom_test::bd;
using libaom_test::compute_avg_abs_error;
using libaom_test::Fwd_Txfm2d_Func;
using libaom_test::Inv_Txfm2d_Func;
using libaom_test::input_base;
using ::testing::Combine;
using ::testing::Range;
using ::testing::Values;
using std::vector;
namespace {
#if CONFIG_HIGHBITDEPTH
// AV1InvTxfm2dParam argument list:
// tx_type_, tx_size_, max_error_, max_avg_error_
typedef std::tr1::tuple<TX_TYPE, TX_SIZE, int, double> AV1InvTxfm2dParam;
typedef ::testing::tuple<TX_TYPE, TX_SIZE, int, double> AV1InvTxfm2dParam;
class AV1InvTxfm2d : public ::testing::TestWithParam<AV1InvTxfm2dParam> {
public:
@ -46,171 +55,313 @@ class AV1InvTxfm2d : public ::testing::TestWithParam<AV1InvTxfm2dParam> {
int tx_w = tx_size_wide[tx_size_];
int tx_h = tx_size_high[tx_size_];
int txfm2d_size = tx_w * tx_h;
const Fwd_Txfm2d_Func fwd_txfm_func =
libaom_test::fwd_txfm_func_ls[tx_size_];
const Inv_Txfm2d_Func inv_txfm_func =
libaom_test::inv_txfm_func_ls[tx_size_];
const FwdTxfm2dFunc fwd_txfm_func = libaom_test::fwd_txfm_func_ls[tx_size_];
const InvTxfm2dFunc inv_txfm_func = libaom_test::inv_txfm_func_ls[tx_size_];
double avg_abs_error = 0;
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int count = 500;
for (int ci = 0; ci < count; ci++) {
int16_t expected[64 * 64] = { 0 };
ASSERT_LT(txfm2d_size, NELEMENTS(expected));
DECLARE_ALIGNED(16, int16_t, input[64 * 64]) = { 0 };
ASSERT_LE(txfm2d_size, NELEMENTS(input));
for (int ni = 0; ni < txfm2d_size; ++ni) {
if (ci == 0) {
int extreme_input = input_base - 1;
expected[ni] = extreme_input; // extreme case
input[ni] = extreme_input; // extreme case
} else {
expected[ni] = rnd.Rand16() % input_base;
input[ni] = rnd.Rand16() % input_base;
}
}
int32_t coeffs[64 * 64] = { 0 };
ASSERT_LT(txfm2d_size, NELEMENTS(coeffs));
fwd_txfm_func(expected, coeffs, tx_w, tx_type_, bd);
DECLARE_ALIGNED(16, uint16_t, expected[64 * 64]) = { 0 };
ASSERT_LE(txfm2d_size, NELEMENTS(expected));
if (TxfmUsesApproximation()) {
// Compare reference forward HT + inverse HT vs forward HT + inverse HT.
double ref_input[64 * 64];
ASSERT_LE(txfm2d_size, NELEMENTS(ref_input));
for (int ni = 0; ni < txfm2d_size; ++ni) {
ref_input[ni] = input[ni];
}
double ref_coeffs[64 * 64] = { 0 };
ASSERT_LE(txfm2d_size, NELEMENTS(ref_coeffs));
ASSERT_EQ(tx_type_, DCT_DCT);
libaom_test::reference_hybrid_2d(ref_input, ref_coeffs, tx_type_,
tx_size_);
DECLARE_ALIGNED(16, int32_t, ref_coeffs_int[64 * 64]) = { 0 };
ASSERT_LE(txfm2d_size, NELEMENTS(ref_coeffs_int));
for (int ni = 0; ni < txfm2d_size; ++ni) {
ref_coeffs_int[ni] = (int32_t)round(ref_coeffs[ni]);
}
inv_txfm_func(ref_coeffs_int, expected, tx_w, tx_type_, bd);
} else {
// Compare original input vs forward HT + inverse HT.
for (int ni = 0; ni < txfm2d_size; ++ni) {
expected[ni] = input[ni];
}
}
uint16_t actual[64 * 64] = { 0 };
ASSERT_LT(txfm2d_size, NELEMENTS(actual));
DECLARE_ALIGNED(16, int32_t, coeffs[64 * 64]) = { 0 };
ASSERT_LE(txfm2d_size, NELEMENTS(coeffs));
fwd_txfm_func(input, coeffs, tx_w, tx_type_, bd);
DECLARE_ALIGNED(16, uint16_t, actual[64 * 64]) = { 0 };
ASSERT_LE(txfm2d_size, NELEMENTS(actual));
inv_txfm_func(coeffs, actual, tx_w, tx_type_, bd);
double actual_max_error = 0;
for (int ni = 0; ni < txfm2d_size; ++ni) {
EXPECT_GE(max_error_, abs(expected[ni] - actual[ni]));
const double this_error = abs(expected[ni] - actual[ni]);
actual_max_error = AOMMAX(actual_max_error, this_error);
}
avg_abs_error += compute_avg_abs_error<int16_t, uint16_t>(
EXPECT_GE(max_error_, actual_max_error)
<< " tx_w: " << tx_w << " tx_h " << tx_h << " tx_type: " << tx_type_;
if (actual_max_error > max_error_) { // exit early.
break;
}
avg_abs_error += compute_avg_abs_error<uint16_t, uint16_t>(
expected, actual, txfm2d_size);
}
avg_abs_error /= count;
// max_abs_avg_error comes from upper bound of
// printf("txfm1d_size: %d accuracy_avg_abs_error: %f\n",
// txfm1d_size_, avg_abs_error);
EXPECT_GE(max_avg_error_, avg_abs_error)
<< " tx_w: " << tx_w << " tx_h " << tx_h << " tx_type: " << tx_type_;
}
private:
bool TxfmUsesApproximation() {
if (tx_size_wide[tx_size_] == 64 || tx_size_high[tx_size_] == 64) {
return true;
}
return false;
}
int max_error_;
double max_avg_error_;
TX_TYPE tx_type_;
TX_SIZE tx_size_;
};
TEST_P(AV1InvTxfm2d, RunRoundtripCheck) { RunRoundtripCheck(); }
const AV1InvTxfm2dParam av1_inv_txfm2d_param[] = {
#if CONFIG_EXT_TX
#if CONFIG_RECT_TX
AV1InvTxfm2dParam(DCT_DCT, TX_4X8, 2, 0.007),
AV1InvTxfm2dParam(ADST_DCT, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(DCT_ADST, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(ADST_ADST, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_4X8, 2, 0.012),
AV1InvTxfm2dParam(DCT_DCT, TX_8X4, 2, 0.007),
AV1InvTxfm2dParam(ADST_DCT, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(DCT_ADST, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(ADST_ADST, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_8X4, 2, 0.007),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_8X4, 2, 0.012),
AV1InvTxfm2dParam(DCT_DCT, TX_8X16, 2, 0.025),
AV1InvTxfm2dParam(ADST_DCT, TX_8X16, 2, 0.020),
AV1InvTxfm2dParam(DCT_ADST, TX_8X16, 2, 0.027),
AV1InvTxfm2dParam(ADST_ADST, TX_8X16, 2, 0.023),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_8X16, 2, 0.020),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_8X16, 2, 0.027),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_8X16, 2, 0.032),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_8X16, 2, 0.023),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_8X16, 2, 0.023),
AV1InvTxfm2dParam(DCT_DCT, TX_16X8, 2, 0.007),
AV1InvTxfm2dParam(ADST_DCT, TX_16X8, 2, 0.012),
AV1InvTxfm2dParam(DCT_ADST, TX_16X8, 2, 0.024),
AV1InvTxfm2dParam(ADST_ADST, TX_16X8, 2, 0.033),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_16X8, 2, 0.015),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_16X8, 2, 0.032),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_16X8, 2, 0.032),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_16X8, 2, 0.033),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_16X8, 2, 0.032),
#endif
AV1InvTxfm2dParam(FLIPADST_DCT, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_16X16, 11, 0.04),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(FLIPADST_DCT, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(DCT_FLIPADST, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(FLIPADST_FLIPADST, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(ADST_FLIPADST, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(FLIPADST_ADST, TX_32X32, 4, 0.4),
#endif
AV1InvTxfm2dParam(DCT_DCT, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(ADST_DCT, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(DCT_ADST, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(ADST_ADST, TX_4X4, 2, 0.002),
AV1InvTxfm2dParam(DCT_DCT, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(ADST_DCT, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(DCT_ADST, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(ADST_ADST, TX_8X8, 2, 0.02),
AV1InvTxfm2dParam(DCT_DCT, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(ADST_DCT, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(DCT_ADST, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(ADST_ADST, TX_16X16, 2, 0.04),
AV1InvTxfm2dParam(DCT_DCT, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(ADST_DCT, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(DCT_ADST, TX_32X32, 4, 0.4),
AV1InvTxfm2dParam(ADST_ADST, TX_32X32, 4, 0.4)
static int max_error_ls[TX_SIZES_ALL] = {
2, // 4x4 transform
2, // 8x8 transform
2, // 16x16 transform
4, // 32x32 transform
3, // 64x64 transform
2, // 4x8 transform
2, // 8x4 transform
2, // 8x16 transform
2, // 16x8 transform
3, // 16x32 transform
3, // 32x16 transform
5, // 32x64 transform
5, // 64x32 transform
2, // 4x16 transform
2, // 16x4 transform
2, // 8x32 transform
2, // 32x8 transform
3, // 16x64 transform
3, // 64x16 transform
};
static double avg_error_ls[TX_SIZES_ALL] = {
0.002, // 4x4 transform
0.05, // 8x8 transform
0.07, // 16x16 transform
0.4, // 32x32 transform
0.3, // 64x64 transform
0.02, // 4x8 transform
0.02, // 8x4 transform
0.04, // 8x16 transform
0.07, // 16x8 transform
0.4, // 16x32 transform
0.5, // 32x16 transform
0.38, // 32x64 transform
0.39, // 64x32 transform
0.2, // 4x16 transform
0.2, // 16x4 transform
0.2, // 8x32 transform
0.2, // 32x8 transform
0.38, // 16x64 transform
0.38, // 64x16 transform
};
vector<AV1InvTxfm2dParam> GetInvTxfm2dParamList() {
vector<AV1InvTxfm2dParam> param_list;
for (int s = 0; s < TX_SIZES; ++s) {
const int max_error = max_error_ls[s];
const double avg_error = avg_error_ls[s];
for (int t = 0; t < TX_TYPES; ++t) {
const TX_TYPE tx_type = static_cast<TX_TYPE>(t);
const TX_SIZE tx_size = static_cast<TX_SIZE>(s);
if (libaom_test::IsTxSizeTypeValid(tx_size, tx_type)) {
param_list.push_back(
AV1InvTxfm2dParam(tx_type, tx_size, max_error, avg_error));
}
}
}
return param_list;
}
INSTANTIATE_TEST_CASE_P(C, AV1InvTxfm2d,
::testing::ValuesIn(av1_inv_txfm2d_param));
::testing::ValuesIn(GetInvTxfm2dParamList()));
TEST_P(AV1InvTxfm2d, RunRoundtripCheck) { RunRoundtripCheck(); }
TEST(AV1InvTxfm2d, CfgTest) {
for (int bd_idx = 0; bd_idx < BD_NUM; ++bd_idx) {
int bd = libaom_test::bd_arr[bd_idx];
int8_t low_range = libaom_test::low_range_arr[bd_idx];
int8_t high_range = libaom_test::high_range_arr[bd_idx];
// TODO(angiebird): include rect txfm in this test
for (int tx_size = 0; tx_size < TX_SIZES; ++tx_size) {
for (int tx_size = 0; tx_size < TX_SIZES_ALL; ++tx_size) {
for (int tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
TXFM_2D_FLIP_CFG cfg = av1_get_inv_txfm_cfg(
static_cast<TX_TYPE>(tx_type), static_cast<TX_SIZE>(tx_size));
if (libaom_test::IsTxSizeTypeValid(static_cast<TX_SIZE>(tx_size),
static_cast<TX_TYPE>(tx_type)) ==
false) {
continue;
}
TXFM_2D_FLIP_CFG cfg;
av1_get_inv_txfm_cfg(static_cast<TX_TYPE>(tx_type),
static_cast<TX_SIZE>(tx_size), &cfg);
int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
av1_gen_inv_stage_range(stage_range_col, stage_range_row, &cfg,
fwd_shift_sum[tx_size], bd);
const TXFM_1D_CFG *col_cfg = cfg.col_cfg;
const TXFM_1D_CFG *row_cfg = cfg.row_cfg;
libaom_test::txfm_stage_range_check(stage_range_col, col_cfg->stage_num,
col_cfg->cos_bit, low_range,
(TX_SIZE)tx_size, bd);
libaom_test::txfm_stage_range_check(stage_range_col, cfg.stage_num_col,
cfg.cos_bit_col, low_range,
high_range);
libaom_test::txfm_stage_range_check(stage_range_row, row_cfg->stage_num,
row_cfg->cos_bit, low_range,
libaom_test::txfm_stage_range_check(stage_range_row, cfg.stage_num_row,
cfg.cos_bit_row, low_range,
high_range);
}
}
}
}
#endif // CONFIG_HIGHBITDEPTH
typedef ::testing::tuple<const LbdInvTxfm2dFunc> AV1LbdInvTxfm2dParam;
class AV1LbdInvTxfm2d : public ::testing::TestWithParam<AV1LbdInvTxfm2dParam> {
public:
virtual void SetUp() { target_func_ = GET_PARAM(0); }
void RunAV1InvTxfm2dTest(TX_TYPE tx_type, TX_SIZE tx_size, int run_times);
private:
LbdInvTxfm2dFunc target_func_;
};
void AV1LbdInvTxfm2d::RunAV1InvTxfm2dTest(TX_TYPE tx_type, TX_SIZE tx_size,
int run_times) {
FwdTxfm2dFunc fwd_func_ = libaom_test::fwd_txfm_func_ls[tx_size];
InvTxfm2dFunc ref_func_ = libaom_test::inv_txfm_func_ls[tx_size];
if (fwd_func_ == NULL || ref_func_ == NULL || target_func_ == NULL) {
return;
}
const int bd = 8;
const int BLK_WIDTH = 64;
const int BLK_SIZE = BLK_WIDTH * BLK_WIDTH;
DECLARE_ALIGNED(16, int16_t, input[BLK_SIZE]) = { 0 };
DECLARE_ALIGNED(32, int32_t, inv_input[BLK_SIZE]) = { 0 };
DECLARE_ALIGNED(16, uint8_t, output[BLK_SIZE]) = { 0 };
DECLARE_ALIGNED(16, uint16_t, ref_output[BLK_SIZE]) = { 0 };
int stride = BLK_WIDTH;
int rows = tx_size_high[tx_size];
int cols = tx_size_wide[tx_size];
const int rows_nonezero = AOMMIN(32, rows);
const int cols_nonezero = AOMMIN(32, cols);
run_times /= (rows * cols);
run_times = AOMMAX(1, run_times);
const SCAN_ORDER *scan_order = get_default_scan(tx_size, tx_type);
const int16_t *scan = scan_order->scan;
const int16_t eobmax = rows_nonezero * cols_nonezero;
ACMRandom rnd(ACMRandom::DeterministicSeed());
int randTimes = run_times == 1 ? (eobmax + 500) : 1;
for (int cnt = 0; cnt < randTimes; ++cnt) {
const int16_t max_in = (1 << (bd)) - 1;
for (int r = 0; r < BLK_WIDTH; ++r) {
for (int c = 0; c < BLK_WIDTH; ++c) {
input[r * cols + c] = (cnt == 0) ? max_in : rnd.Rand8Extremes();
output[r * stride + c] = (cnt == 0) ? 128 : rnd.Rand8();
ref_output[r * stride + c] = output[r * stride + c];
}
}
fwd_func_(input, inv_input, stride, tx_type, bd);
// produce eob input by setting high freq coeffs to zero
const int eob = AOMMIN(cnt + 1, eobmax);
for (int i = eob; i < eobmax; i++) {
inv_input[scan[i]] = 0;
}
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < run_times; ++i) {
ref_func_(inv_input, ref_output, stride, tx_type, bd);
}
aom_usec_timer_mark(&timer);
const double time1 = static_cast<double>(aom_usec_timer_elapsed(&timer));
aom_usec_timer_start(&timer);
for (int i = 0; i < run_times; ++i) {
target_func_(inv_input, output, stride, tx_type, tx_size, eob);
}
aom_usec_timer_mark(&timer);
const double time2 = static_cast<double>(aom_usec_timer_elapsed(&timer));
if (run_times > 10) {
printf("txfm[%d] %3dx%-3d:%7.2f/%7.2fns", tx_type, cols, rows, time1,
time2);
printf("(%3.2f)\n", time1 / time2);
}
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
uint8_t ref_value = static_cast<uint8_t>(ref_output[r * stride + c]);
ASSERT_EQ(ref_value, output[r * stride + c])
<< "[" << r << "," << c << "] " << cnt
<< " tx_size: " << static_cast<int>(tx_size)
<< " tx_type: " << tx_type << " eob " << eob;
}
}
}
}
TEST_P(AV1LbdInvTxfm2d, match) {
for (int j = 0; j < (int)(TX_SIZES_ALL); ++j) {
for (int i = 0; i < (int)TX_TYPES; ++i) {
if (libaom_test::IsTxSizeTypeValid(static_cast<TX_SIZE>(j),
static_cast<TX_TYPE>(i))) {
RunAV1InvTxfm2dTest(static_cast<TX_TYPE>(i), static_cast<TX_SIZE>(j),
1);
}
}
}
}
TEST_P(AV1LbdInvTxfm2d, DISABLED_Speed) {
for (int j = 0; j < (int)(TX_SIZES_ALL); ++j) {
for (int i = 0; i < (int)TX_TYPES; ++i) {
if (libaom_test::IsTxSizeTypeValid(static_cast<TX_SIZE>(j),
static_cast<TX_TYPE>(i))) {
RunAV1InvTxfm2dTest(static_cast<TX_TYPE>(i), static_cast<TX_SIZE>(j),
10000000);
}
}
}
}
#if HAVE_SSSE3
#if defined(_MSC_VER) || defined(__SSSE3__)
#include "av1/common/x86/av1_inv_txfm_ssse3.h"
INSTANTIATE_TEST_CASE_P(SSSE3, AV1LbdInvTxfm2d,
::testing::Values(av1_lowbd_inv_txfm2d_add_ssse3));
#endif // _MSC_VER || __SSSE3__
#endif // HAVE_SSSE3
#if HAVE_AVX2
extern "C" void av1_lowbd_inv_txfm2d_add_avx2(const int32_t *input,
uint8_t *output, int stride,
TX_TYPE tx_type, TX_SIZE tx_size,
int eob);
INSTANTIATE_TEST_CASE_P(AVX2, AV1LbdInvTxfm2d,
::testing::Values(av1_lowbd_inv_txfm2d_add_avx2));
#endif // HAVE_AVX2
} // namespace

View file

@ -1,271 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/av1_txfm_test.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "av1/common/blockd.h"
#include "av1/common/scan.h"
#include "aom/aom_integer.h"
#include "aom_dsp/inv_txfm.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*IdctFunc)(const tran_low_t *in, tran_low_t *out);
class TransTestBase {
public:
virtual ~TransTestBase() {}
protected:
void RunInvAccuracyCheck() {
tran_low_t input[64];
tran_low_t output[64];
double ref_input[64];
double ref_output[64];
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int count_test_block = 5000;
for (int ti = 0; ti < count_test_block; ++ti) {
for (int ni = 0; ni < txfm_size_; ++ni) {
input[ni] = rnd.Rand8() - rnd.Rand8();
ref_input[ni] = static_cast<double>(input[ni]);
}
inv_txfm_(input, output);
libaom_test::reference_idct_1d(ref_input, ref_output, txfm_size_);
for (int ni = 0; ni < txfm_size_; ++ni) {
EXPECT_LE(
abs(output[ni] - static_cast<tran_low_t>(round(ref_output[ni]))),
max_error_);
}
}
}
double max_error_;
int txfm_size_;
IdctFunc inv_txfm_;
};
typedef std::tr1::tuple<IdctFunc, int, int> IdctParam;
class AV1InvTxfm : public TransTestBase,
public ::testing::TestWithParam<IdctParam> {
public:
virtual void SetUp() {
inv_txfm_ = GET_PARAM(0);
txfm_size_ = GET_PARAM(1);
max_error_ = GET_PARAM(2);
}
virtual void TearDown() {}
};
TEST_P(AV1InvTxfm, RunInvAccuracyCheck) { RunInvAccuracyCheck(); }
INSTANTIATE_TEST_CASE_P(C, AV1InvTxfm,
::testing::Values(IdctParam(&aom_idct4_c, 4, 1),
IdctParam(&aom_idct8_c, 8, 2),
IdctParam(&aom_idct16_c, 16, 4),
IdctParam(&aom_idct32_c, 32, 6)));
#if CONFIG_AV1_ENCODER
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::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, InvTxfmFunc, TX_SIZE, int>
PartialInvTxfmParam;
#if !CONFIG_ADAPT_SCAN
const int kMaxNumCoeffs = 1024;
#endif
class AV1PartialIDctTest
: public ::testing::TestWithParam<PartialInvTxfmParam> {
public:
virtual ~AV1PartialIDctTest() {}
virtual void SetUp() {
ftxfm_ = GET_PARAM(0);
full_itxfm_ = GET_PARAM(1);
partial_itxfm_ = GET_PARAM(2);
tx_size_ = GET_PARAM(3);
last_nonzero_ = GET_PARAM(4);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
int last_nonzero_;
TX_SIZE tx_size_;
FwdTxfmFunc ftxfm_;
InvTxfmFunc full_itxfm_;
InvTxfmFunc partial_itxfm_;
};
#if !CONFIG_ADAPT_SCAN
static MB_MODE_INFO get_mbmi() {
MB_MODE_INFO mbmi;
mbmi.ref_frame[0] = LAST_FRAME;
assert(is_inter_block(&mbmi));
return mbmi;
}
TEST_P(AV1PartialIDctTest, RunQuantCheck) {
int size;
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;
}
DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]);
const int count_test_block = 1000;
const int block_size = size * size;
DECLARE_ALIGNED(16, int16_t, input_extreme_block[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kMaxNumCoeffs]);
int max_error = 0;
for (int m = 0; m < count_test_block; ++m) {
// clear out destination buffer
memset(dst1, 0, sizeof(*dst1) * block_size);
memset(dst2, 0, sizeof(*dst2) * block_size);
memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int n = 0; n < count_test_block; ++n) {
// Initialize a test block with input range [-255, 255].
if (n == 0) {
for (int j = 0; j < block_size; ++j) input_extreme_block[j] = 255;
} else if (n == 1) {
for (int j = 0; j < block_size; ++j) input_extreme_block[j] = -255;
} else {
for (int j = 0; j < block_size; ++j) {
input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
}
}
ftxfm_(input_extreme_block, output_ref_block, size);
// quantization with maximum allowed step sizes
test_coef_block1[0] = (output_ref_block[0] / 1336) * 1336;
MB_MODE_INFO mbmi = get_mbmi();
for (int j = 1; j < last_nonzero_; ++j)
test_coef_block1[get_scan((const AV1_COMMON *)NULL, tx_size_, DCT_DCT,
&mbmi)
->scan[j]] = (output_ref_block[j] / 1828) * 1828;
}
ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block1, dst2, size));
for (int j = 0; j < block_size; ++j) {
const int diff = dst1[j] - dst2[j];
const int error = diff * diff;
if (max_error < error) max_error = error;
}
}
EXPECT_EQ(0, max_error)
<< "Error: partial inverse transform produces different results";
}
TEST_P(AV1PartialIDctTest, ResultsMatch) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int size;
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;
}
DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]);
DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]);
const int count_test_block = 1000;
const int max_coeff = 32766 / 4;
const int block_size = size * size;
int max_error = 0;
for (int i = 0; i < count_test_block; ++i) {
// clear out destination buffer
memset(dst1, 0, sizeof(*dst1) * block_size);
memset(dst2, 0, sizeof(*dst2) * block_size);
memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
int max_energy_leftover = max_coeff * max_coeff;
for (int j = 0; j < last_nonzero_; ++j) {
int16_t coef = static_cast<int16_t>(sqrt(1.0 * max_energy_leftover) *
(rnd.Rand16() - 32768) / 65536);
max_energy_leftover -= coef * coef;
if (max_energy_leftover < 0) {
max_energy_leftover = 0;
coef = 0;
}
MB_MODE_INFO mbmi = get_mbmi();
test_coef_block1[get_scan((const AV1_COMMON *)NULL, tx_size_, DCT_DCT,
&mbmi)
->scan[j]] = coef;
}
memcpy(test_coef_block2, test_coef_block1,
sizeof(*test_coef_block2) * block_size);
ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block2, dst2, size));
for (int j = 0; j < block_size; ++j) {
const int diff = dst1[j] - dst2[j];
const int error = diff * diff;
if (max_error < error) max_error = error;
}
}
EXPECT_EQ(0, max_error)
<< "Error: partial inverse transform produces different results";
}
#endif
using std::tr1::make_tuple;
INSTANTIATE_TEST_CASE_P(
C, AV1PartialIDctTest,
::testing::Values(make_tuple(&aom_fdct32x32_c, &aom_idct32x32_1024_add_c,
&aom_idct32x32_34_add_c, TX_32X32, 34),
make_tuple(&aom_fdct32x32_c, &aom_idct32x32_1024_add_c,
&aom_idct32x32_1_add_c, TX_32X32, 1),
make_tuple(&aom_fdct16x16_c, &aom_idct16x16_256_add_c,
&aom_idct16x16_10_add_c, TX_16X16, 10),
make_tuple(&aom_fdct16x16_c, &aom_idct16x16_256_add_c,
&aom_idct16x16_1_add_c, TX_16X16, 1),
make_tuple(&aom_fdct8x8_c, &aom_idct8x8_64_add_c,
&aom_idct8x8_12_add_c, TX_8X8, 12),
make_tuple(&aom_fdct8x8_c, &aom_idct8x8_64_add_c,
&aom_idct8x8_1_add_c, TX_8X8, 1),
make_tuple(&aom_fdct4x4_c, &aom_idct4x4_16_add_c,
&aom_idct4x4_1_add_c, TX_4X4, 1)));
#endif // CONFIG_AV1_ENCODER
} // namespace

View file

@ -12,8 +12,9 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./av1_rtcd.h"
#include "config/aom_config.h"
#include "config/av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
@ -22,8 +23,8 @@
namespace {
typedef void (*QuantizeFpFunc)(
const tran_low_t *coeff_ptr, intptr_t count, int skip_block,
const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr,
const tran_low_t *coeff_ptr, intptr_t count, const int16_t *zbin_ptr,
const int16_t *round_ptr, const int16_t *quant_ptr,
const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
const int16_t *scan, const int16_t *iscan, int log_scale);
@ -50,20 +51,19 @@ class AV1QuantizeTest : public ::testing::TestWithParam<QuantizeFuncParams> {
void RunQuantizeTest() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[maxSize]);
DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
DECLARE_ALIGNED(16, int16_t, zbin_ptr[8]);
DECLARE_ALIGNED(16, int16_t, round_ptr[8]);
DECLARE_ALIGNED(16, int16_t, quant_ptr[8]);
DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[8]);
DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
DECLARE_ALIGNED(16, int16_t, dequant_ptr[8]);
uint16_t eob;
uint16_t ref_eob;
int err_count_total = 0;
int first_failure = -1;
int skip_block = 0;
int count = params_.coeffCount;
const TX_SIZE txSize = getTxSize(count);
int log_scale = (txSize == TX_32X32);
@ -86,20 +86,26 @@ class AV1QuantizeTest : public ::testing::TestWithParam<QuantizeFuncParams> {
quant_ptr[j] = (1 << 16) / dequant_ptr[j];
round_ptr[j] = (abs(rnd(roundFactorRange)) * dequant_ptr[j]) >> 7;
}
quanFuncRef(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
for (int j = 2; j < 8; ++j) {
zbin_ptr[j] = zbin_ptr[1];
quant_shift_ptr[j] = quant_shift_ptr[1];
dequant_ptr[j] = dequant_ptr[1];
quant_ptr[j] = quant_ptr[1];
round_ptr[j] = round_ptr[1];
}
quanFuncRef(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
quant_shift_ptr, ref_qcoeff_ptr, ref_dqcoeff_ptr, dequant_ptr,
&ref_eob, scanOrder.scan, scanOrder.iscan, log_scale);
ASM_REGISTER_STATE_CHECK(
quanFunc(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
quanFunc(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, &eob,
scanOrder.scan, scanOrder.iscan, log_scale));
for (int j = 0; j < count; ++j) {
err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
(ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
EXPECT_EQ(ref_qcoeff_ptr[j], qcoeff_ptr[j])
ASSERT_EQ(ref_qcoeff_ptr[j], qcoeff_ptr[j])
<< "qcoeff error: i = " << i << " j = " << j << "\n";
EXPECT_EQ(ref_dqcoeff_ptr[j], dqcoeff_ptr[j])
<< "dqcoeff error: i = " << i << " j = " << j << "\n";
@ -120,18 +126,17 @@ class AV1QuantizeTest : public ::testing::TestWithParam<QuantizeFuncParams> {
void RunEobTest() {
ACMRandom rnd(ACMRandom::DeterministicSeed());
DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[maxSize]);
DECLARE_ALIGNED(16, int16_t, zbin_ptr[2]);
DECLARE_ALIGNED(16, int16_t, round_ptr[2]);
DECLARE_ALIGNED(16, int16_t, quant_ptr[2]);
DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[2]);
DECLARE_ALIGNED(16, int16_t, zbin_ptr[8]);
DECLARE_ALIGNED(16, int16_t, round_ptr[8]);
DECLARE_ALIGNED(16, int16_t, quant_ptr[8]);
DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[8]);
DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[maxSize]);
DECLARE_ALIGNED(16, int16_t, dequant_ptr[2]);
DECLARE_ALIGNED(16, int16_t, dequant_ptr[8]);
uint16_t eob;
uint16_t ref_eob;
int skip_block = 0;
int count = params_.coeffCount;
const TX_SIZE txSize = getTxSize(count);
int log_scale = (txSize == TX_32X32);
@ -157,13 +162,20 @@ class AV1QuantizeTest : public ::testing::TestWithParam<QuantizeFuncParams> {
quant_ptr[j] = (1 << 16) / dequant_ptr[j];
round_ptr[j] = (abs(rnd(roundFactorRange)) * dequant_ptr[j]) >> 7;
}
for (int j = 2; j < 8; ++j) {
zbin_ptr[j] = zbin_ptr[1];
quant_shift_ptr[j] = quant_shift_ptr[1];
dequant_ptr[j] = dequant_ptr[1];
quant_ptr[j] = quant_ptr[1];
round_ptr[j] = round_ptr[1];
}
quanFuncRef(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
quanFuncRef(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
quant_shift_ptr, ref_qcoeff_ptr, ref_dqcoeff_ptr, dequant_ptr,
&ref_eob, scanOrder.scan, scanOrder.iscan, log_scale);
ASM_REGISTER_STATE_CHECK(
quanFunc(coeff_ptr, count, skip_block, zbin_ptr, round_ptr, quant_ptr,
quanFunc(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, &eob,
scanOrder.scan, scanOrder.iscan, log_scale));
EXPECT_EQ(ref_eob, eob) << "eob error: "
@ -196,7 +208,7 @@ TEST_P(AV1QuantizeTest, EobVerify) { RunEobTest(); }
#if HAVE_SSE4_1
const QuantizeFuncParams qfps[4] = {
QuantizeFuncParams(av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
16),
QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
64),
@ -208,4 +220,20 @@ const QuantizeFuncParams qfps[4] = {
INSTANTIATE_TEST_CASE_P(SSE4_1, AV1QuantizeTest, ::testing::ValuesIn(qfps));
#endif // HAVE_SSE4_1
#if HAVE_AVX2
const QuantizeFuncParams qfps_avx2[4] = {
QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
16),
QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
64),
QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
256),
QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
1024),
};
INSTANTIATE_TEST_CASE_P(AVX2, AV1QuantizeTest, ::testing::ValuesIn(qfps_avx2));
#endif // HAVE_AVX2
} // namespace

View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "config/aom_dsp_rtcd.h"
#include "aom_mem/aom_mem.h"
#include "aom_ports/aom_timer.h"
#include "aom_ports/mem.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/util.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace AV1CompRoundShift {
typedef void (*comp_round_shift_array_func)(int32_t *arr, int size, int bit);
const int kValidBitCheck[] = {
-4, -3, -2, -1, 0, 1, 2, 3, 4,
};
typedef ::testing::tuple<comp_round_shift_array_func, BLOCK_SIZE, int>
CompRoundShiftParam;
class AV1CompRoundShiftTest
: public ::testing::TestWithParam<CompRoundShiftParam> {
public:
~AV1CompRoundShiftTest();
void SetUp() { rnd_.Reset(libaom_test::ACMRandom::DeterministicSeed()); }
void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunCheckOutput(comp_round_shift_array_func test_impl, BLOCK_SIZE bsize,
int bit);
void RunSpeedTest(comp_round_shift_array_func test_impl, BLOCK_SIZE bsize,
int bit);
libaom_test::ACMRandom rnd_;
};
AV1CompRoundShiftTest::~AV1CompRoundShiftTest() { ; }
void AV1CompRoundShiftTest::RunCheckOutput(
comp_round_shift_array_func test_impl, BLOCK_SIZE bsize, int bit) {
const int w = block_size_wide[bsize];
const int h = block_size_high[bsize];
const int blk_wd = 64;
DECLARE_ALIGNED(32, int32_t, pred_[blk_wd]);
DECLARE_ALIGNED(32, int32_t, ref_buffer_[blk_wd]);
for (int i = 0; i < (blk_wd); ++i) {
ref_buffer_[i] = pred_[i] = rnd_.Rand31() / 16;
}
av1_round_shift_array_c(ref_buffer_, w, bit);
test_impl(pred_, w, bit);
for (int x = 0; x < w; ++x) {
ASSERT_EQ(ref_buffer_[x], pred_[x]) << w << "x" << h << "mismatch @"
<< "(" << x << ")";
}
}
void AV1CompRoundShiftTest::RunSpeedTest(comp_round_shift_array_func test_impl,
BLOCK_SIZE bsize, int bit) {
const int w = block_size_wide[bsize];
const int h = block_size_high[bsize];
const int blk_wd = 64;
DECLARE_ALIGNED(32, int32_t, ref_buffer_[blk_wd]);
for (int i = 0; i < (blk_wd); ++i) {
ref_buffer_[i] = rnd_.Rand31();
}
const int num_loops = 1000000000 / (w + h);
comp_round_shift_array_func funcs[2] = { av1_round_shift_array_c, test_impl };
double elapsed_time[2] = { 0 };
for (int i = 0; i < 2; ++i) {
aom_usec_timer timer;
aom_usec_timer_start(&timer);
comp_round_shift_array_func func = funcs[i];
for (int j = 0; j < num_loops; ++j) {
func(ref_buffer_, w, bit);
}
aom_usec_timer_mark(&timer);
double time = static_cast<double>(aom_usec_timer_elapsed(&timer));
elapsed_time[i] = 1000.0 * time / num_loops;
}
printf("av1_round_shift_array %3dx%-3d: bit : %d %7.2f/%7.2fns", w, h, bit,
elapsed_time[0], elapsed_time[1]);
printf("(%3.2f)\n", elapsed_time[0] / elapsed_time[1]);
}
TEST_P(AV1CompRoundShiftTest, CheckOutput) {
RunCheckOutput(GET_PARAM(0), GET_PARAM(1), GET_PARAM(2));
}
TEST_P(AV1CompRoundShiftTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(0), GET_PARAM(1), GET_PARAM(2));
}
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, AV1CompRoundShiftTest,
::testing::Combine(::testing::Values(&av1_round_shift_array_sse4_1),
::testing::ValuesIn(txsize_to_bsize),
::testing::ValuesIn(kValidBitCheck)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, AV1CompRoundShiftTest,
::testing::Combine(::testing::Values(&av1_round_shift_array_neon),
::testing::ValuesIn(txsize_to_bsize),
::testing::ValuesIn(kValidBitCheck)));
#endif
}; // namespace AV1CompRoundShift

View file

@ -34,7 +34,6 @@ void get_txfm1d_type(TX_TYPE txfm2d_type, TYPE_TXFM *type0, TYPE_TXFM *type1) {
*type0 = TYPE_ADST;
*type1 = TYPE_ADST;
break;
#if CONFIG_EXT_TX
case FLIPADST_DCT:
*type0 = TYPE_ADST;
*type1 = TYPE_DCT;
@ -55,7 +54,34 @@ void get_txfm1d_type(TX_TYPE txfm2d_type, TYPE_TXFM *type0, TYPE_TXFM *type1) {
*type0 = TYPE_ADST;
*type1 = TYPE_ADST;
break;
#endif // CONFIG_EXT_TX
case IDTX:
*type0 = TYPE_IDTX;
*type1 = TYPE_IDTX;
break;
case H_DCT:
*type0 = TYPE_IDTX;
*type1 = TYPE_DCT;
break;
case V_DCT:
*type0 = TYPE_DCT;
*type1 = TYPE_IDTX;
break;
case H_ADST:
*type0 = TYPE_IDTX;
*type1 = TYPE_ADST;
break;
case V_ADST:
*type0 = TYPE_ADST;
*type1 = TYPE_IDTX;
break;
case H_FLIPADST:
*type0 = TYPE_IDTX;
*type1 = TYPE_ADST;
break;
case V_FLIPADST:
*type0 = TYPE_ADST;
*type1 = TYPE_IDTX;
break;
default:
*type0 = TYPE_DCT;
*type1 = TYPE_DCT;
@ -64,6 +90,7 @@ void get_txfm1d_type(TX_TYPE txfm2d_type, TYPE_TXFM *type0, TYPE_TXFM *type1) {
}
}
double Sqrt2 = pow(2, 0.5);
double invSqrt2 = 1 / pow(2, 0.5);
double dct_matrix(double n, double k, int size) {
@ -92,7 +119,63 @@ void reference_idct_1d(const double *in, double *out, int size) {
}
}
// TODO(any): Copied from the old 'fadst4' (same as the new 'av1_fadst4_new'
// function). Should be replaced by a proper reference function that takes
// 'double' input & output.
static void fadst4_new(const tran_low_t *input, tran_low_t *output) {
tran_high_t x0, x1, x2, x3;
tran_high_t s0, s1, s2, s3, s4, s5, s6, s7;
x0 = input[0];
x1 = input[1];
x2 = input[2];
x3 = input[3];
if (!(x0 | x1 | x2 | x3)) {
output[0] = output[1] = output[2] = output[3] = 0;
return;
}
s0 = sinpi_1_9 * x0;
s1 = sinpi_4_9 * x0;
s2 = sinpi_2_9 * x1;
s3 = sinpi_1_9 * x1;
s4 = sinpi_3_9 * x2;
s5 = sinpi_4_9 * x3;
s6 = sinpi_2_9 * x3;
s7 = x0 + x1 - x3;
x0 = s0 + s2 + s5;
x1 = sinpi_3_9 * s7;
x2 = s1 - s3 + s6;
x3 = s4;
s0 = x0 + x3;
s1 = x1;
s2 = x2 - x3;
s3 = x2 - x0 + x3;
// 1-D transform scaling factor is sqrt(2).
output[0] = (tran_low_t)fdct_round_shift(s0);
output[1] = (tran_low_t)fdct_round_shift(s1);
output[2] = (tran_low_t)fdct_round_shift(s2);
output[3] = (tran_low_t)fdct_round_shift(s3);
}
void reference_adst_1d(const double *in, double *out, int size) {
if (size == 4) { // Special case.
tran_low_t int_input[4];
for (int i = 0; i < 4; ++i) {
int_input[i] = static_cast<tran_low_t>(round(in[i]));
}
tran_low_t int_output[4];
fadst4_new(int_input, int_output);
for (int i = 0; i < 4; ++i) {
out[i] = int_output[i];
}
return;
}
for (int k = 0; k < size; ++k) {
out[k] = 0;
for (int n = 0; n < size; ++n) {
@ -101,96 +184,188 @@ void reference_adst_1d(const double *in, double *out, int size) {
}
}
void reference_idtx_1d(const double *in, double *out, int size) {
double scale = 0;
if (size == 4)
scale = Sqrt2;
else if (size == 8)
scale = 2;
else if (size == 16)
scale = 2 * Sqrt2;
else if (size == 32)
scale = 4;
else if (size == 64)
scale = 4 * Sqrt2;
for (int k = 0; k < size; ++k) {
out[k] = in[k] * scale;
}
}
void reference_hybrid_1d(double *in, double *out, int size, int type) {
if (type == TYPE_DCT)
reference_dct_1d(in, out, size);
else
else if (type == TYPE_ADST)
reference_adst_1d(in, out, size);
else
reference_idtx_1d(in, out, size);
}
void reference_hybrid_2d(double *in, double *out, int size, int type0,
int type1) {
double *tempOut = new double[size * size];
double get_amplification_factor(TX_TYPE tx_type, TX_SIZE tx_size) {
TXFM_2D_FLIP_CFG fwd_txfm_flip_cfg;
av1_get_fwd_txfm_cfg(tx_type, tx_size, &fwd_txfm_flip_cfg);
const int tx_width = tx_size_wide[fwd_txfm_flip_cfg.tx_size];
const int tx_height = tx_size_high[fwd_txfm_flip_cfg.tx_size];
const int8_t *shift = fwd_txfm_flip_cfg.shift;
const int amplify_bit = shift[0] + shift[1] + shift[2];
double amplify_factor =
amplify_bit >= 0 ? (1 << amplify_bit) : (1.0 / (1 << -amplify_bit));
for (int r = 0; r < size; r++) {
// out ->tempOut
for (int c = 0; c < size; c++) {
tempOut[r * size + c] = in[c * size + r];
// For rectangular transforms, we need to multiply by an extra factor.
const int rect_type = get_rect_tx_log_ratio(tx_width, tx_height);
if (abs(rect_type) == 1) {
amplify_factor *= pow(2, 0.5);
}
return amplify_factor;
}
void reference_hybrid_2d(double *in, double *out, TX_TYPE tx_type,
TX_SIZE tx_size) {
// Get transform type and size of each dimension.
TYPE_TXFM type0;
TYPE_TXFM type1;
get_txfm1d_type(tx_type, &type0, &type1);
const int tx_width = tx_size_wide[tx_size];
const int tx_height = tx_size_high[tx_size];
double *const temp_in = new double[AOMMAX(tx_width, tx_height)];
double *const temp_out = new double[AOMMAX(tx_width, tx_height)];
double *const out_interm = new double[tx_width * tx_height];
const int stride = tx_width;
// Transform columns.
for (int c = 0; c < tx_width; ++c) {
for (int r = 0; r < tx_height; ++r) {
temp_in[r] = in[r * stride + c];
}
reference_hybrid_1d(temp_in, temp_out, tx_height, type0);
for (int r = 0; r < tx_height; ++r) {
out_interm[r * stride + c] = temp_out[r];
}
}
// dct each row: in -> out
for (int r = 0; r < size; r++) {
reference_hybrid_1d(tempOut + r * size, out + r * size, size, type0);
// Transform rows.
for (int r = 0; r < tx_height; ++r) {
reference_hybrid_1d(out_interm + r * stride, out + r * stride, tx_width,
type1);
}
for (int r = 0; r < size; r++) {
// out ->tempOut
for (int c = 0; c < size; c++) {
tempOut[r * size + c] = out[c * size + r];
delete[] temp_in;
delete[] temp_out;
delete[] out_interm;
// These transforms use an approximate 2D DCT transform, by only keeping the
// top-left quarter of the coefficients, and repacking them in the first
// quarter indices.
// TODO(urvang): Refactor this code.
if (tx_width == 64 && tx_height == 64) { // tx_size == TX_64X64
// Zero out top-right 32x32 area.
for (int row = 0; row < 32; ++row) {
memset(out + row * 64 + 32, 0, 32 * sizeof(*out));
}
// Zero out the bottom 64x32 area.
memset(out + 32 * 64, 0, 32 * 64 * sizeof(*out));
// Re-pack non-zero coeffs in the first 32x32 indices.
for (int row = 1; row < 32; ++row) {
memcpy(out + row * 32, out + row * 64, 32 * sizeof(*out));
}
} else if (tx_width == 32 && tx_height == 64) { // tx_size == TX_32X64
// Zero out the bottom 32x32 area.
memset(out + 32 * 32, 0, 32 * 32 * sizeof(*out));
// Note: no repacking needed here.
} else if (tx_width == 64 && tx_height == 32) { // tx_size == TX_64X32
// Zero out right 32x32 area.
for (int row = 0; row < 32; ++row) {
memset(out + row * 64 + 32, 0, 32 * sizeof(*out));
}
// Re-pack non-zero coeffs in the first 32x32 indices.
for (int row = 1; row < 32; ++row) {
memcpy(out + row * 32, out + row * 64, 32 * sizeof(*out));
}
} else if (tx_width == 16 && tx_height == 64) { // tx_size == TX_16X64
// Zero out the bottom 16x32 area.
memset(out + 16 * 32, 0, 16 * 32 * sizeof(*out));
// Note: no repacking needed here.
} else if (tx_width == 64 && tx_height == 16) { // tx_size == TX_64X16
// Zero out right 32x16 area.
for (int row = 0; row < 16; ++row) {
memset(out + row * 64 + 32, 0, 32 * sizeof(*out));
}
// Re-pack non-zero coeffs in the first 32x16 indices.
for (int row = 1; row < 16; ++row) {
memcpy(out + row * 32, out + row * 64, 32 * sizeof(*out));
}
}
for (int r = 0; r < size; r++) {
reference_hybrid_1d(tempOut + r * size, out + r * size, size, type1);
}
delete[] tempOut;
}
template <typename Type>
void fliplr(Type *dest, int stride, int length) {
int i, j;
for (i = 0; i < length; ++i) {
for (j = 0; j < length / 2; ++j) {
const Type tmp = dest[i * stride + j];
dest[i * stride + j] = dest[i * stride + length - 1 - j];
dest[i * stride + length - 1 - j] = tmp;
// Apply appropriate scale.
const double amplify_factor = get_amplification_factor(tx_type, tx_size);
for (int c = 0; c < tx_width; ++c) {
for (int r = 0; r < tx_height; ++r) {
out[r * stride + c] *= amplify_factor;
}
}
}
template <typename Type>
void flipud(Type *dest, int stride, int length) {
int i, j;
for (j = 0; j < length; ++j) {
for (i = 0; i < length / 2; ++i) {
const Type tmp = dest[i * stride + j];
dest[i * stride + j] = dest[(length - 1 - i) * stride + j];
dest[(length - 1 - i) * stride + j] = tmp;
void fliplr(Type *dest, int width, int height, int stride) {
for (int r = 0; r < height; ++r) {
for (int c = 0; c < width / 2; ++c) {
const Type tmp = dest[r * stride + c];
dest[r * stride + c] = dest[r * stride + width - 1 - c];
dest[r * stride + width - 1 - c] = tmp;
}
}
}
template <typename Type>
void fliplrud(Type *dest, int stride, int length) {
int i, j;
for (i = 0; i < length / 2; ++i) {
for (j = 0; j < length; ++j) {
const Type tmp = dest[i * stride + j];
dest[i * stride + j] = dest[(length - 1 - i) * stride + length - 1 - j];
dest[(length - 1 - i) * stride + length - 1 - j] = tmp;
void flipud(Type *dest, int width, int height, int stride) {
for (int c = 0; c < width; ++c) {
for (int r = 0; r < height / 2; ++r) {
const Type tmp = dest[r * stride + c];
dest[r * stride + c] = dest[(height - 1 - r) * stride + c];
dest[(height - 1 - r) * stride + c] = tmp;
}
}
}
template void fliplr<double>(double *dest, int stride, int length);
template void flipud<double>(double *dest, int stride, int length);
template void fliplrud<double>(double *dest, int stride, int length);
template <typename Type>
void fliplrud(Type *dest, int width, int height, int stride) {
for (int r = 0; r < height / 2; ++r) {
for (int c = 0; c < width; ++c) {
const Type tmp = dest[r * stride + c];
dest[r * stride + c] = dest[(height - 1 - r) * stride + width - 1 - c];
dest[(height - 1 - r) * stride + width - 1 - c] = tmp;
}
}
}
template void fliplr<double>(double *dest, int width, int height, int stride);
template void flipud<double>(double *dest, int width, int height, int stride);
template void fliplrud<double>(double *dest, int width, int height, int stride);
int bd_arr[BD_NUM] = { 8, 10, 12 };
int8_t low_range_arr[BD_NUM] = { 16, 32, 32 };
int8_t low_range_arr[BD_NUM] = { 18, 32, 32 };
int8_t high_range_arr[BD_NUM] = { 32, 32, 32 };
void txfm_stage_range_check(const int8_t *stage_range, int stage_num,
const int8_t *cos_bit, int low_range,
int high_range) {
int8_t cos_bit, int low_range, int high_range) {
for (int i = 0; i < stage_num; ++i) {
EXPECT_LE(stage_range[i], low_range);
ASSERT_LE(stage_range[i] + cos_bit, high_range) << "stage = " << i;
}
for (int i = 0; i < stage_num - 1; ++i) {
// make sure there is no overflow while doing half_btf()
EXPECT_LE(stage_range[i] + cos_bit[i], high_range);
EXPECT_LE(stage_range[i + 1] + cos_bit[i], high_range);
ASSERT_LE(stage_range[i + 1] + cos_bit, high_range) << "stage = " << i;
}
}
} // namespace libaom_test

View file

@ -19,17 +19,20 @@
#endif
#include <math.h>
#include "config/av1_rtcd.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "av1/common/enums.h"
#include "av1/common/av1_txfm.h"
#include "./av1_rtcd.h"
#include "av1/common/blockd.h"
#include "av1/common/enums.h"
namespace libaom_test {
typedef enum {
TYPE_DCT = 0,
TYPE_ADST,
TYPE_IDTX,
TYPE_IDCT,
TYPE_IADST,
TYPE_LAST
@ -46,8 +49,10 @@ void reference_adst_1d(const double *in, double *out, int size);
void reference_hybrid_1d(double *in, double *out, int size, int type);
void reference_hybrid_2d(double *in, double *out, int size, int type0,
int type1);
double get_amplification_factor(TX_TYPE tx_type, TX_SIZE tx_size);
void reference_hybrid_2d(double *in, double *out, TX_TYPE tx_type,
TX_SIZE tx_size);
template <typename Type1, typename Type2>
static double compute_avg_abs_error(const Type1 *a, const Type2 *b,
const int size) {
@ -60,81 +65,62 @@ static double compute_avg_abs_error(const Type1 *a, const Type2 *b,
}
template <typename Type>
void fliplr(Type *dest, int stride, int length);
void fliplr(Type *dest, int width, int height, int stride);
template <typename Type>
void flipud(Type *dest, int stride, int length);
void flipud(Type *dest, int width, int height, int stride);
template <typename Type>
void fliplrud(Type *dest, int stride, int length);
void fliplrud(Type *dest, int width, int height, int stride);
typedef void (*TxfmFunc)(const int32_t *in, int32_t *out, const int8_t *cos_bit,
typedef void (*TxfmFunc)(const int32_t *in, int32_t *out, const int8_t cos_bit,
const int8_t *range_bit);
typedef void (*Fwd_Txfm2d_Func)(const int16_t *, int32_t *, int, TX_TYPE, int);
typedef void (*Inv_Txfm2d_Func)(const int32_t *, uint16_t *, int, TX_TYPE, int);
typedef void (*InvTxfm2dFunc)(const int32_t *, uint16_t *, int, TX_TYPE, int);
typedef void (*LbdInvTxfm2dFunc)(const int32_t *, uint8_t *, int, TX_TYPE,
TX_SIZE, int);
static const int bd = 10;
static const int input_base = (1 << bd);
#if CONFIG_HIGHBITDEPTH
static INLINE bool IsTxSizeTypeValid(TX_SIZE tx_size, TX_TYPE tx_type) {
const TX_SIZE tx_size_sqr_up = txsize_sqr_up_map[tx_size];
TxSetType tx_set_type;
if (tx_size_sqr_up > TX_32X32) {
tx_set_type = EXT_TX_SET_DCTONLY;
} else if (tx_size_sqr_up == TX_32X32) {
tx_set_type = EXT_TX_SET_DCT_IDTX;
} else {
tx_set_type = EXT_TX_SET_ALL16;
}
return av1_ext_tx_used[tx_set_type][tx_type] != 0;
}
#if CONFIG_AV1_ENCODER
static const Fwd_Txfm2d_Func fwd_txfm_func_ls[TX_SIZES_ALL] = {
#if CONFIG_CHROMA_2X2
NULL,
#endif
av1_fwd_txfm2d_4x4_c,
av1_fwd_txfm2d_8x8_c,
av1_fwd_txfm2d_16x16_c,
av1_fwd_txfm2d_32x32_c,
#if CONFIG_TX64X64
av1_fwd_txfm2d_64x64_c,
#endif // CONFIG_TX64X64
av1_fwd_txfm2d_4x8_c,
av1_fwd_txfm2d_8x4_c,
av1_fwd_txfm2d_8x16_c,
av1_fwd_txfm2d_16x8_c,
av1_fwd_txfm2d_16x32_c,
av1_fwd_txfm2d_32x16_c,
#if CONFIG_TX64X64
av1_fwd_txfm2d_32x64_c,
av1_fwd_txfm2d_64x32_c,
#endif // CONFIG_TX64X64
NULL,
NULL,
NULL,
NULL,
static const FwdTxfm2dFunc fwd_txfm_func_ls[TX_SIZES_ALL] = {
av1_fwd_txfm2d_4x4_c, av1_fwd_txfm2d_8x8_c, av1_fwd_txfm2d_16x16_c,
av1_fwd_txfm2d_32x32_c, av1_fwd_txfm2d_64x64_c, av1_fwd_txfm2d_4x8_c,
av1_fwd_txfm2d_8x4_c, av1_fwd_txfm2d_8x16_c, av1_fwd_txfm2d_16x8_c,
av1_fwd_txfm2d_16x32_c, av1_fwd_txfm2d_32x16_c, av1_fwd_txfm2d_32x64_c,
av1_fwd_txfm2d_64x32_c, av1_fwd_txfm2d_4x16_c, av1_fwd_txfm2d_16x4_c,
av1_fwd_txfm2d_8x32_c, av1_fwd_txfm2d_32x8_c, av1_fwd_txfm2d_16x64_c,
av1_fwd_txfm2d_64x16_c,
};
#endif
static const Inv_Txfm2d_Func inv_txfm_func_ls[TX_SIZES_ALL] = {
#if CONFIG_CHROMA_2X2
NULL,
#endif
av1_inv_txfm2d_add_4x4_c,
av1_inv_txfm2d_add_8x8_c,
av1_inv_txfm2d_add_16x16_c,
av1_inv_txfm2d_add_32x32_c,
#if CONFIG_TX64X64
av1_inv_txfm2d_add_64x64_c,
#endif // CONFIG_TX64X64
av1_inv_txfm2d_add_4x8_c,
av1_inv_txfm2d_add_8x4_c,
av1_inv_txfm2d_add_8x16_c,
av1_inv_txfm2d_add_16x8_c,
av1_inv_txfm2d_add_16x32_c,
av1_inv_txfm2d_add_32x16_c,
#if CONFIG_TX64X64
av1_inv_txfm2d_add_32x64_c,
av1_inv_txfm2d_add_64x32_c,
#endif // CONFIG_TX64X64
NULL,
NULL,
NULL,
NULL,
static const InvTxfm2dFunc inv_txfm_func_ls[TX_SIZES_ALL] = {
av1_inv_txfm2d_add_4x4_c, av1_inv_txfm2d_add_8x8_c,
av1_inv_txfm2d_add_16x16_c, av1_inv_txfm2d_add_32x32_c,
av1_inv_txfm2d_add_64x64_c, av1_inv_txfm2d_add_4x8_c,
av1_inv_txfm2d_add_8x4_c, av1_inv_txfm2d_add_8x16_c,
av1_inv_txfm2d_add_16x8_c, av1_inv_txfm2d_add_16x32_c,
av1_inv_txfm2d_add_32x16_c, av1_inv_txfm2d_add_32x64_c,
av1_inv_txfm2d_add_64x32_c, av1_inv_txfm2d_add_4x16_c,
av1_inv_txfm2d_add_16x4_c, av1_inv_txfm2d_add_8x32_c,
av1_inv_txfm2d_add_32x8_c, av1_inv_txfm2d_add_16x64_c,
av1_inv_txfm2d_add_64x16_c,
};
#endif // CONFIG_HIGHBITDEPTH
#define BD_NUM 3
@ -143,7 +129,7 @@ extern int8_t low_range_arr[];
extern int8_t high_range_arr[];
void txfm_stage_range_check(const int8_t *stage_range, int stage_num,
const int8_t *cos_bit, int low_range,
const int8_t cos_bit, int low_range,
int high_range);
} // namespace libaom_test
#endif // AV1_TXFM_TEST_H_

View file

@ -11,10 +11,9 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
#include "./av1_rtcd.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom_dsp/aom_dsp_common.h"
@ -100,7 +99,7 @@ TEST_F(WedgeUtilsSSEFuncTest, ResidualBlendingEquiv) {
p1[j] = clamp(s[j] + rng_(33) - 16, 0, UINT8_MAX);
}
aom_blend_a64_mask(p, w, p0, w, p1, w, m, w, h, w, 0, 0);
aom_blend_a64_mask(p, w, p0, w, p1, w, m, w, w, h, 0, 0);
aom_subtract_block(h, w, r0, w, s, w, p0, w);
aom_subtract_block(h, w, r1, w, s, w, p1, w);

View file

@ -1,299 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./aom_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 "aom_mem/aom_mem.h"
using libaom_test::ACMRandom;
namespace {
class AverageTestBase : public ::testing::Test {
public:
AverageTestBase(int width, int height) : width_(width), height_(height) {}
static void SetUpTestCase() {
source_data_ = reinterpret_cast<uint8_t *>(
aom_memalign(kDataAlignment, kDataBlockSize));
}
static void TearDownTestCase() {
aom_free(source_data_);
source_data_ = NULL;
}
virtual void TearDown() { libaom_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_stride_ = (width_ + 31) & ~31;
rnd_.Reset(ACMRandom::DeterministicSeed());
}
void FillConstant(uint8_t 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_.Rand8();
}
}
int width_, height_;
static uint8_t *source_data_;
int source_stride_;
ACMRandom rnd_;
};
typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref,
const int ref_stride, const int height);
typedef std::tr1::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam;
class IntProRowTest : public AverageTestBase,
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() {
hbuf_asm_ = reinterpret_cast<int16_t *>(
aom_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16));
hbuf_c_ = reinterpret_cast<int16_t *>(
aom_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16));
}
virtual void TearDown() {
aom_free(hbuf_c_);
hbuf_c_ = NULL;
aom_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::tr1::tuple<int, IntProColFunc, IntProColFunc> IntProColParam;
class IntProColTest : public AverageTestBase,
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 int16_t *coeffs, int length);
typedef std::tr1::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<int16_t *>(
aom_memalign(16, sizeof(*src_) * satd_size_));
ASSERT_TRUE(src_ != NULL);
}
virtual void TearDown() {
libaom_test::ClearSystemState();
aom_free(src_);
}
void FillConstant(const int16_t val) {
for (int i = 0; i < satd_size_; ++i) src_[i] = val;
}
void FillRandom() {
for (int i = 0; i < satd_size_; ++i) src_[i] = rnd_.Rand16();
}
void Check(int expected) {
int total;
ASM_REGISTER_STATE_CHECK(total = satd_func_(src_, satd_size_));
EXPECT_EQ(expected, total);
}
int satd_size_;
private:
int16_t *src_;
SatdFunc satd_func_;
ACMRandom rnd_;
};
uint8_t *AverageTestBase::source_data_ = NULL;
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(SatdTest, MinValue) {
const int kMin = -32640;
const int expected = -kMin * satd_size_;
FillConstant(kMin);
Check(expected);
}
TEST_P(SatdTest, MaxValue) {
const int kMax = 32640;
const int expected = kMax * satd_size_;
FillConstant(kMax);
Check(expected);
}
TEST_P(SatdTest, Random) {
int expected;
switch (satd_size_) {
case 16: expected = 205298; break;
case 64: expected = 1113950; break;
case 256: expected = 4268415; break;
case 1024: expected = 16954082; break;
default:
FAIL() << "Invalid satd size (" << satd_size_
<< ") valid: 16/64/256/1024";
}
FillRandom();
Check(expected);
}
using std::tr1::make_tuple;
INSTANTIATE_TEST_CASE_P(C, SatdTest,
::testing::Values(make_tuple(16, &aom_satd_c),
make_tuple(64, &aom_satd_c),
make_tuple(256, &aom_satd_c),
make_tuple(1024, &aom_satd_c)));
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, IntProRowTest,
::testing::Values(make_tuple(16, &aom_int_pro_row_sse2, &aom_int_pro_row_c),
make_tuple(32, &aom_int_pro_row_sse2, &aom_int_pro_row_c),
make_tuple(64, &aom_int_pro_row_sse2,
&aom_int_pro_row_c)));
INSTANTIATE_TEST_CASE_P(
SSE2, IntProColTest,
::testing::Values(make_tuple(16, &aom_int_pro_col_sse2, &aom_int_pro_col_c),
make_tuple(32, &aom_int_pro_col_sse2, &aom_int_pro_col_c),
make_tuple(64, &aom_int_pro_col_sse2,
&aom_int_pro_col_c)));
INSTANTIATE_TEST_CASE_P(SSE2, SatdTest,
::testing::Values(make_tuple(16, &aom_satd_sse2),
make_tuple(64, &aom_satd_sse2),
make_tuple(256, &aom_satd_sse2),
make_tuple(1024, &aom_satd_sse2)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, IntProRowTest,
::testing::Values(make_tuple(16, &aom_int_pro_row_neon, &aom_int_pro_row_c),
make_tuple(32, &aom_int_pro_row_neon, &aom_int_pro_row_c),
make_tuple(64, &aom_int_pro_row_neon,
&aom_int_pro_row_c)));
INSTANTIATE_TEST_CASE_P(
NEON, IntProColTest,
::testing::Values(make_tuple(16, &aom_int_pro_col_neon, &aom_int_pro_col_c),
make_tuple(32, &aom_int_pro_col_neon, &aom_int_pro_col_c),
make_tuple(64, &aom_int_pro_col_neon,
&aom_int_pro_col_c)));
INSTANTIATE_TEST_CASE_P(NEON, SatdTest,
::testing::Values(make_tuple(16, &aom_satd_neon),
make_tuple(64, &aom_satd_neon),
make_tuple(256, &aom_satd_neon),
make_tuple(1024, &aom_satd_neon)));
#endif
} // namespace

103
third_party/aom/test/best_encode.sh vendored Executable file
View file

@ -0,0 +1,103 @@
#!/bin/bash
#
# Copyright (c) 2016, Alliance for Open Media. All rights reserved
#
# This source code is subject to the terms of the BSD 2 Clause License and
# the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
# was not distributed with this source code in the LICENSE file, you can
# obtain it at www.aomedia.org/license/software. If the Alliance for Open
# Media Patent License 1.0 was not distributed with this source code in the
# PATENTS file, you can obtain it at www.aomedia.org/license/patent.
#
# Author: jimbankoski@google.com (Jim Bankoski)
if [[ $# -ne 2 ]]; then
echo "Encodes a file using best known settings (slow!)"
echo " Usage: be [FILE] [BITRATE]"
echo " Example: be akiyo_cif.y4m 200"
exit
fi
f=$1 # file is first parameter
b=$2 # bitrate is second parameter
if [[ -e $f.fpf ]]; then
# First-pass file found, do second pass only
aomenc \
$f \
-o $f-$b.av1.webm \
-p 2 \
--pass=2 \
--fpf=$f.fpf \
--best \
--cpu-used=0 \
--target-bitrate=$b \
--auto-alt-ref=1 \
-v \
--minsection-pct=0 \
--maxsection-pct=800 \
--lag-in-frames=25 \
--kf-min-dist=0 \
--kf-max-dist=99999 \
--static-thresh=0 \
--min-q=0 \
--max-q=63 \
--drop-frame=0 \
--bias-pct=50 \
--minsection-pct=0 \
--maxsection-pct=800 \
--psnr \
--arnr-maxframes=7 \
--arnr-strength=3 \
--arnr-type=3
else
# No first-pass file found, do 2-pass encode
aomenc \
$f \
-o $f-$b.av1.webm \
-p 2 \
--pass=1 \
--fpf=$f.fpf \
--best \
--cpu-used=0 \
--target-bitrate=$b \
--auto-alt-ref=1 \
-v \
--minsection-pct=0 \
--maxsection-pct=800 \
--lag-in-frames=25 \
--kf-min-dist=0 \
--kf-max-dist=99999 \
--static-thresh=0 \
--min-q=0 \
--max-q=63 \
--drop-frame=0
aomenc \
$f \
-o $f-$b.av1.webm \
-p 2 \
--pass=2 \
--fpf=$f.fpf \
--best \
--cpu-used=0 \
--target-bitrate=$b \
--auto-alt-ref=1 \
-v \
--minsection-pct=0 \
--maxsection-pct=800 \
--lag-in-frames=25 \
--kf-min-dist=0 \
--kf-max-dist=99999 \
--static-thresh=0 \
--min-q=0 \
--max-q=63 \
--drop-frame=0 \
--bias-pct=50 \
--minsection-pct=0 \
--maxsection-pct=800 \
--psnr \
--arnr-maxframes=7 \
--arnr-strength=3 \
--arnr-type=3
fi

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <math.h>
#include <stdlib.h>
@ -15,7 +15,8 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "config/aom_config.h"
#include "test/acm_random.h"
#include "aom/aom_integer.h"
#include "aom_dsp/bitreader.h"
@ -29,57 +30,6 @@ using libaom_test::ACMRandom;
namespace {
// Test for Bilevel code with reference
TEST(AV1, TestPrimitiveRefbilivel) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
const int kBufferSize = 65536;
aom_writer bw;
uint8_t bw_buffer[kBufferSize];
const uint16_t kRanges = 8;
const uint16_t kNearRanges = 8;
const uint16_t kReferences = 8;
const uint16_t kValues = 16;
const uint16_t range_vals[kRanges] = { 1, 13, 64, 120, 230, 420, 1100, 8000 };
uint16_t enc_values[kRanges][kNearRanges][kReferences][kValues][4];
aom_start_encode(&bw, bw_buffer);
for (int n = 0; n < kRanges; ++n) {
const uint16_t range = range_vals[n];
for (int p = 0; p < kNearRanges; ++p) {
const uint16_t near_range = 1 + rnd(range);
for (int r = 0; r < kReferences; ++r) {
const uint16_t ref = rnd(range);
for (int v = 0; v < kValues; ++v) {
const uint16_t value = rnd(range);
enc_values[n][p][r][v][0] = range;
enc_values[n][p][r][v][1] = near_range;
enc_values[n][p][r][v][2] = ref;
enc_values[n][p][r][v][3] = value;
aom_write_primitive_refbilevel(&bw, range, near_range, ref, value);
}
}
}
}
aom_stop_encode(&bw);
aom_reader br;
aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
GTEST_ASSERT_GE(aom_reader_tell(&br), 0u);
GTEST_ASSERT_LE(aom_reader_tell(&br), 1u);
for (int n = 0; n < kRanges; ++n) {
for (int p = 0; p < kNearRanges; ++p) {
for (int r = 0; r < kReferences; ++r) {
for (int v = 0; v < kValues; ++v) {
const uint16_t range = enc_values[n][p][r][v][0];
const uint16_t near_range = enc_values[n][p][r][v][1];
const uint16_t ref = enc_values[n][p][r][v][2];
const uint16_t value = aom_read_primitive_refbilevel(
&br, range, near_range, ref, ACCT_STR);
GTEST_ASSERT_EQ(value, enc_values[n][p][r][v][3]);
}
}
}
}
}
// Test for Finite subexponential code with reference
TEST(AV1, TestPrimitiveRefsubexpfin) {
ACMRandom rnd(ACMRandom::DeterministicSeed());
@ -111,7 +61,7 @@ TEST(AV1, TestPrimitiveRefsubexpfin) {
}
aom_stop_encode(&bw);
aom_reader br;
aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
aom_reader_init(&br, bw_buffer, bw.pos);
GTEST_ASSERT_GE(aom_reader_tell(&br), 0u);
GTEST_ASSERT_LE(aom_reader_tell(&br), 1u);
for (int n = 0; n < kRanges; ++n) {

View file

@ -17,11 +17,11 @@
#include "test/register_state_check.h"
#include "test/function_equivalence_test.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
#include "aom/aom_integer.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "./av1_rtcd.h"
#include "aom/aom_integer.h"
#include "av1/common/enums.h"
@ -46,8 +46,8 @@ class BlendA64Mask1DTest : public FunctionEquivalenceTest<F> {
virtual void Execute(const T *p_src0, const T *p_src1) = 0;
void Common() {
w_ = 1 << this->rng_(MAX_SB_SIZE_LOG2 + 1);
h_ = 1 << this->rng_(MAX_SB_SIZE_LOG2 + 1);
w_ = 2 << this->rng_(MAX_SB_SIZE_LOG2);
h_ = 2 << this->rng_(MAX_SB_SIZE_LOG2);
dst_offset_ = this->rng_(33);
dst_stride_ = this->rng_(kMaxWidth + 1 - w_) + w_;
@ -116,7 +116,7 @@ class BlendA64Mask1DTest : public FunctionEquivalenceTest<F> {
typedef void (*F8B)(uint8_t *dst, uint32_t dst_stride, const uint8_t *src0,
uint32_t src0_stride, const uint8_t *src1,
uint32_t src1_stride, const uint8_t *mask, int h, int w);
uint32_t src1_stride, const uint8_t *mask, int w, int h);
typedef libaom_test::FuncParam<F8B> TestFuncs;
class BlendA64Mask1DTest8B : public BlendA64Mask1DTest<F8B, uint8_t> {
@ -124,10 +124,10 @@ class BlendA64Mask1DTest8B : public BlendA64Mask1DTest<F8B, uint8_t> {
void Execute(const uint8_t *p_src0, const uint8_t *p_src1) {
params_.ref_func(dst_ref_ + dst_offset_, dst_stride_, p_src0 + src0_offset_,
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_,
h_, w_);
w_, h_);
ASM_REGISTER_STATE_CHECK(params_.tst_func(
dst_tst_ + dst_offset_, dst_stride_, p_src0 + src0_offset_,
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_, h_, w_));
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_, w_, h_));
}
};
@ -167,7 +167,7 @@ TEST_P(BlendA64Mask1DTest8B, ExtremeValues) {
static void blend_a64_hmask_ref(uint8_t *dst, uint32_t dst_stride,
const uint8_t *src0, uint32_t src0_stride,
const uint8_t *src1, uint32_t src1_stride,
const uint8_t *mask, int h, int w) {
const uint8_t *mask, int w, int h) {
uint8_t mask2d[BlendA64Mask1DTest8B::kMaxMaskSize]
[BlendA64Mask1DTest8B::kMaxMaskSize];
@ -175,14 +175,14 @@ static void blend_a64_hmask_ref(uint8_t *dst, uint32_t dst_stride,
for (int col = 0; col < w; ++col) mask2d[row][col] = mask[col];
aom_blend_a64_mask_c(dst, dst_stride, src0, src0_stride, src1, src1_stride,
&mask2d[0][0], BlendA64Mask1DTest8B::kMaxMaskSize, h, w,
&mask2d[0][0], BlendA64Mask1DTest8B::kMaxMaskSize, w, h,
0, 0);
}
static void blend_a64_vmask_ref(uint8_t *dst, uint32_t dst_stride,
const uint8_t *src0, uint32_t src0_stride,
const uint8_t *src1, uint32_t src1_stride,
const uint8_t *mask, int h, int w) {
const uint8_t *mask, int w, int h) {
uint8_t mask2d[BlendA64Mask1DTest8B::kMaxMaskSize]
[BlendA64Mask1DTest8B::kMaxMaskSize];
@ -190,7 +190,7 @@ static void blend_a64_vmask_ref(uint8_t *dst, uint32_t dst_stride,
for (int col = 0; col < w; ++col) mask2d[row][col] = mask[row];
aom_blend_a64_mask_c(dst, dst_stride, src0, src0_stride, src1, src1_stride,
&mask2d[0][0], BlendA64Mask1DTest8B::kMaxMaskSize, h, w,
&mask2d[0][0], BlendA64Mask1DTest8B::kMaxMaskSize, w, h,
0, 0);
}
@ -207,14 +207,21 @@ INSTANTIATE_TEST_CASE_P(
TestFuncs(blend_a64_vmask_ref, aom_blend_a64_vmask_sse4_1)));
#endif // HAVE_SSE4_1
#if CONFIG_HIGHBITDEPTH
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, BlendA64Mask1DTest8B,
::testing::Values(TestFuncs(blend_a64_hmask_ref,
aom_blend_a64_hmask_neon),
TestFuncs(blend_a64_vmask_ref,
aom_blend_a64_vmask_neon)));
#endif // HAVE_NEON
//////////////////////////////////////////////////////////////////////////////
// High bit-depth version
//////////////////////////////////////////////////////////////////////////////
typedef void (*FHBD)(uint8_t *dst, uint32_t dst_stride, const uint8_t *src0,
uint32_t src0_stride, const uint8_t *src1,
uint32_t src1_stride, const uint8_t *mask, int h, int w,
uint32_t src1_stride, const uint8_t *mask, int w, int h,
int bd);
typedef libaom_test::FuncParam<FHBD> TestFuncsHBD;
@ -224,11 +231,11 @@ class BlendA64Mask1DTestHBD : public BlendA64Mask1DTest<FHBD, uint16_t> {
params_.ref_func(CONVERT_TO_BYTEPTR(dst_ref_ + dst_offset_), dst_stride_,
CONVERT_TO_BYTEPTR(p_src0 + src0_offset_), src0_stride_,
CONVERT_TO_BYTEPTR(p_src1 + src1_offset_), src1_stride_,
mask_, h_, w_, bit_depth_);
mask_, w_, h_, bit_depth_);
ASM_REGISTER_STATE_CHECK(params_.tst_func(
CONVERT_TO_BYTEPTR(dst_tst_ + dst_offset_), dst_stride_,
CONVERT_TO_BYTEPTR(p_src0 + src0_offset_), src0_stride_,
CONVERT_TO_BYTEPTR(p_src1 + src1_offset_), src1_stride_, mask_, h_, w_,
CONVERT_TO_BYTEPTR(p_src1 + src1_offset_), src1_stride_, mask_, w_, h_,
bit_depth_));
}
@ -287,7 +294,7 @@ TEST_P(BlendA64Mask1DTestHBD, ExtremeValues) {
static void highbd_blend_a64_hmask_ref(
uint8_t *dst, uint32_t dst_stride, const uint8_t *src0,
uint32_t src0_stride, const uint8_t *src1, uint32_t src1_stride,
const uint8_t *mask, int h, int w, int bd) {
const uint8_t *mask, int w, int h, int bd) {
uint8_t mask2d[BlendA64Mask1DTestHBD::kMaxMaskSize]
[BlendA64Mask1DTestHBD::kMaxMaskSize];
@ -296,13 +303,13 @@ static void highbd_blend_a64_hmask_ref(
aom_highbd_blend_a64_mask_c(
dst, dst_stride, src0, src0_stride, src1, src1_stride, &mask2d[0][0],
BlendA64Mask1DTestHBD::kMaxMaskSize, h, w, 0, 0, bd);
BlendA64Mask1DTestHBD::kMaxMaskSize, w, h, 0, 0, bd);
}
static void highbd_blend_a64_vmask_ref(
uint8_t *dst, uint32_t dst_stride, const uint8_t *src0,
uint32_t src0_stride, const uint8_t *src1, uint32_t src1_stride,
const uint8_t *mask, int h, int w, int bd) {
const uint8_t *mask, int w, int h, int bd) {
uint8_t mask2d[BlendA64Mask1DTestHBD::kMaxMaskSize]
[BlendA64Mask1DTestHBD::kMaxMaskSize];
@ -311,7 +318,7 @@ static void highbd_blend_a64_vmask_ref(
aom_highbd_blend_a64_mask_c(
dst, dst_stride, src0, src0_stride, src1, src1_stride, &mask2d[0][0],
BlendA64Mask1DTestHBD::kMaxMaskSize, h, w, 0, 0, bd);
BlendA64Mask1DTestHBD::kMaxMaskSize, w, h, 0, 0, bd);
}
INSTANTIATE_TEST_CASE_P(
@ -329,6 +336,4 @@ INSTANTIATE_TEST_CASE_P(
TestFuncsHBD(highbd_blend_a64_vmask_ref,
aom_highbd_blend_a64_vmask_sse4_1)));
#endif // HAVE_SSE4_1
#endif // CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -17,11 +17,11 @@
#include "test/register_state_check.h"
#include "test/function_equivalence_test.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
#include "aom/aom_integer.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"
#include "./av1_rtcd.h"
#include "aom/aom_integer.h"
#include "av1/common/enums.h"
@ -31,8 +31,8 @@ using libaom_test::FunctionEquivalenceTest;
namespace {
template <typename F, typename T>
class BlendA64MaskTest : public FunctionEquivalenceTest<F> {
template <typename BlendA64Func, typename SrcPixel, typename DstPixel>
class BlendA64MaskTest : public FunctionEquivalenceTest<BlendA64Func> {
protected:
static const int kIterations = 10000;
static const int kMaxWidth = MAX_SB_SIZE * 5; // * 5 to cover longer strides
@ -43,14 +43,44 @@ class BlendA64MaskTest : public FunctionEquivalenceTest<F> {
virtual ~BlendA64MaskTest() {}
virtual void Execute(const T *p_src0, const T *p_src1) = 0;
virtual void Execute(const SrcPixel *p_src0, const SrcPixel *p_src1) = 0;
void Common() {
w_ = 1 << this->rng_(MAX_SB_SIZE_LOG2 + 1);
h_ = 1 << this->rng_(MAX_SB_SIZE_LOG2 + 1);
template <typename Pixel>
void GetSources(Pixel **src0, Pixel **src1, Pixel * /*dst*/) {
switch (this->rng_(3)) {
case 0: // Separate sources
*src0 = src0_;
*src1 = src1_;
break;
case 1: // src0 == dst
*src0 = dst_tst_;
src0_stride_ = dst_stride_;
src0_offset_ = dst_offset_;
*src1 = src1_;
break;
case 2: // src1 == dst
*src0 = src0_;
*src1 = dst_tst_;
src1_stride_ = dst_stride_;
src1_offset_ = dst_offset_;
break;
default: FAIL();
}
}
subx_ = this->rng_(2);
suby_ = this->rng_(2);
void GetSources(uint16_t **src0, uint16_t **src1, uint8_t * /*dst*/) {
*src0 = src0_;
*src1 = src1_;
}
uint8_t Rand1() { return this->rng_.Rand8() & 1; }
void RunTest() {
w_ = 4 << this->rng_(MAX_SB_SIZE_LOG2 - 1);
h_ = 4 << this->rng_(MAX_SB_SIZE_LOG2 - 1);
subx_ = Rand1();
suby_ = Rand1();
dst_offset_ = this->rng_(33);
dst_stride_ = this->rng_(kMaxWidth + 1 - w_) + w_;
@ -64,49 +94,35 @@ class BlendA64MaskTest : public FunctionEquivalenceTest<F> {
mask_stride_ =
this->rng_(kMaxWidth + 1 - w_ * (subx_ ? 2 : 1)) + w_ * (subx_ ? 2 : 1);
T *p_src0;
T *p_src1;
SrcPixel *p_src0;
SrcPixel *p_src1;
switch (this->rng_(3)) {
case 0: // Separate sources
p_src0 = src0_;
p_src1 = src1_;
break;
case 1: // src0 == dst
p_src0 = dst_tst_;
src0_stride_ = dst_stride_;
src0_offset_ = dst_offset_;
p_src1 = src1_;
break;
case 2: // src1 == dst
p_src0 = src0_;
p_src1 = dst_tst_;
src1_stride_ = dst_stride_;
src1_offset_ = dst_offset_;
break;
default: FAIL();
}
p_src0 = src0_;
p_src1 = src1_;
GetSources(&p_src0, &p_src1, &dst_ref_[0]);
Execute(p_src0, p_src1);
for (int r = 0; r < h_; ++r) {
for (int c = 0; c < w_; ++c) {
ASSERT_EQ(dst_ref_[dst_offset_ + r * dst_stride_ + c],
dst_tst_[dst_offset_ + r * dst_stride_ + c]);
dst_tst_[dst_offset_ + r * dst_stride_ + c])
<< w_ << "x" << h_ << " r: " << r << " c: " << c;
}
}
}
T dst_ref_[kBufSize];
T dst_tst_[kBufSize];
DstPixel dst_ref_[kBufSize];
DstPixel dst_tst_[kBufSize];
uint32_t dst_stride_;
uint32_t dst_offset_;
T src0_[kBufSize];
SrcPixel src0_[kBufSize];
uint32_t src0_stride_;
uint32_t src0_offset_;
T src1_[kBufSize];
SrcPixel src1_[kBufSize];
uint32_t src1_stride_;
uint32_t src1_offset_;
@ -127,19 +143,19 @@ class BlendA64MaskTest : public FunctionEquivalenceTest<F> {
typedef void (*F8B)(uint8_t *dst, uint32_t dst_stride, const uint8_t *src0,
uint32_t src0_stride, const uint8_t *src1,
uint32_t src1_stride, const uint8_t *mask,
uint32_t mask_stride, int h, int w, int suby, int subx);
uint32_t mask_stride, int w, int h, int subx, int suby);
typedef libaom_test::FuncParam<F8B> TestFuncs;
class BlendA64MaskTest8B : public BlendA64MaskTest<F8B, uint8_t> {
class BlendA64MaskTest8B : public BlendA64MaskTest<F8B, uint8_t, uint8_t> {
protected:
void Execute(const uint8_t *p_src0, const uint8_t *p_src1) {
params_.ref_func(dst_ref_ + dst_offset_, dst_stride_, p_src0 + src0_offset_,
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_,
kMaxMaskWidth, h_, w_, suby_, subx_);
kMaxMaskWidth, w_, h_, subx_, suby_);
ASM_REGISTER_STATE_CHECK(params_.tst_func(
dst_tst_ + dst_offset_, dst_stride_, p_src0 + src0_offset_,
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_, kMaxMaskWidth,
h_, w_, suby_, subx_));
w_, h_, subx_, suby_));
}
};
@ -156,7 +172,7 @@ TEST_P(BlendA64MaskTest8B, RandomValues) {
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = rng_(AOM_BLEND_A64_MAX_ALPHA + 1);
Common();
RunTest();
}
}
@ -172,7 +188,7 @@ TEST_P(BlendA64MaskTest8B, ExtremeValues) {
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = rng_(2) + AOM_BLEND_A64_MAX_ALPHA - 1;
Common();
RunTest();
}
}
@ -182,7 +198,85 @@ INSTANTIATE_TEST_CASE_P(SSE4_1, BlendA64MaskTest8B,
aom_blend_a64_mask_c, aom_blend_a64_mask_sse4_1)));
#endif // HAVE_SSE4_1
#if CONFIG_HIGHBITDEPTH
//////////////////////////////////////////////////////////////////////////////
// 8 bit _d16 version
//////////////////////////////////////////////////////////////////////////////
typedef void (*F8B_D16)(uint8_t *dst, uint32_t dst_stride, const uint16_t *src0,
uint32_t src0_stride, const uint16_t *src1,
uint32_t src1_stride, const uint8_t *mask,
uint32_t mask_stride, int w, int h, int subx, int suby,
ConvolveParams *conv_params);
typedef libaom_test::FuncParam<F8B_D16> TestFuncs_d16;
class BlendA64MaskTest8B_d16
: public BlendA64MaskTest<F8B_D16, uint16_t, uint8_t> {
protected:
// max number of bits used by the source
static const int kSrcMaxBitsMask = 0x3fff;
void Execute(const uint16_t *p_src0, const uint16_t *p_src1) {
ConvolveParams conv_params;
conv_params.round_0 = ROUND0_BITS;
conv_params.round_1 = COMPOUND_ROUND1_BITS;
params_.ref_func(dst_ref_ + dst_offset_, dst_stride_, p_src0 + src0_offset_,
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_,
kMaxMaskWidth, w_, h_, subx_, suby_, &conv_params);
ASM_REGISTER_STATE_CHECK(params_.tst_func(
dst_tst_ + dst_offset_, dst_stride_, p_src0 + src0_offset_,
src0_stride_, p_src1 + src1_offset_, src1_stride_, mask_, kMaxMaskWidth,
w_, h_, subx_, suby_, &conv_params));
}
};
TEST_P(BlendA64MaskTest8B_d16, RandomValues) {
for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
for (int i = 0; i < kBufSize; ++i) {
dst_ref_[i] = rng_.Rand8();
dst_tst_[i] = rng_.Rand8();
src0_[i] = rng_.Rand16() & kSrcMaxBitsMask;
src1_[i] = rng_.Rand16() & kSrcMaxBitsMask;
}
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = rng_(AOM_BLEND_A64_MAX_ALPHA + 1);
RunTest();
}
}
TEST_P(BlendA64MaskTest8B_d16, ExtremeValues) {
for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
for (int i = 0; i < kBufSize; ++i) {
dst_ref_[i] = 255;
dst_tst_[i] = 255;
src0_[i] = kSrcMaxBitsMask;
src1_[i] = kSrcMaxBitsMask;
}
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = AOM_BLEND_A64_MAX_ALPHA - 1;
RunTest();
}
}
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, BlendA64MaskTest8B_d16,
::testing::Values(TestFuncs_d16(aom_lowbd_blend_a64_d16_mask_c,
aom_lowbd_blend_a64_d16_mask_sse4_1)));
#endif // HAVE_SSE4_1
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, BlendA64MaskTest8B_d16,
::testing::Values(TestFuncs_d16(aom_lowbd_blend_a64_d16_mask_c,
aom_lowbd_blend_a64_d16_mask_neon)));
#endif // HAVE_NEON
//////////////////////////////////////////////////////////////////////////////
// High bit-depth version
//////////////////////////////////////////////////////////////////////////////
@ -190,22 +284,22 @@ INSTANTIATE_TEST_CASE_P(SSE4_1, BlendA64MaskTest8B,
typedef void (*FHBD)(uint8_t *dst, uint32_t dst_stride, const uint8_t *src0,
uint32_t src0_stride, const uint8_t *src1,
uint32_t src1_stride, const uint8_t *mask,
uint32_t mask_stride, int h, int w, int suby, int subx,
uint32_t mask_stride, int w, int h, int subx, int suby,
int bd);
typedef libaom_test::FuncParam<FHBD> TestFuncsHBD;
class BlendA64MaskTestHBD : public BlendA64MaskTest<FHBD, uint16_t> {
class BlendA64MaskTestHBD : public BlendA64MaskTest<FHBD, uint16_t, uint16_t> {
protected:
void Execute(const uint16_t *p_src0, const uint16_t *p_src1) {
params_.ref_func(CONVERT_TO_BYTEPTR(dst_ref_ + dst_offset_), dst_stride_,
CONVERT_TO_BYTEPTR(p_src0 + src0_offset_), src0_stride_,
CONVERT_TO_BYTEPTR(p_src1 + src1_offset_), src1_stride_,
mask_, kMaxMaskWidth, h_, w_, suby_, subx_, bit_depth_);
mask_, kMaxMaskWidth, w_, h_, subx_, suby_, bit_depth_);
ASM_REGISTER_STATE_CHECK(params_.tst_func(
CONVERT_TO_BYTEPTR(dst_tst_ + dst_offset_), dst_stride_,
CONVERT_TO_BYTEPTR(p_src0 + src0_offset_), src0_stride_,
CONVERT_TO_BYTEPTR(p_src1 + src1_offset_), src1_stride_, mask_,
kMaxMaskWidth, h_, w_, suby_, subx_, bit_depth_));
kMaxMaskWidth, w_, h_, subx_, suby_, bit_depth_));
}
int bit_depth_;
@ -231,7 +325,7 @@ TEST_P(BlendA64MaskTestHBD, RandomValues) {
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = rng_(AOM_BLEND_A64_MAX_ALPHA + 1);
Common();
RunTest();
}
}
@ -256,7 +350,7 @@ TEST_P(BlendA64MaskTestHBD, ExtremeValues) {
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = rng_(2) + AOM_BLEND_A64_MAX_ALPHA - 1;
Common();
RunTest();
}
}
@ -266,5 +360,104 @@ INSTANTIATE_TEST_CASE_P(
::testing::Values(TestFuncsHBD(aom_highbd_blend_a64_mask_c,
aom_highbd_blend_a64_mask_sse4_1)));
#endif // HAVE_SSE4_1
#endif // CONFIG_HIGHBITDEPTH
//////////////////////////////////////////////////////////////////////////////
// HBD _d16 version
//////////////////////////////////////////////////////////////////////////////
typedef void (*FHBD_D16)(uint8_t *dst, uint32_t dst_stride,
const CONV_BUF_TYPE *src0, uint32_t src0_stride,
const CONV_BUF_TYPE *src1, uint32_t src1_stride,
const uint8_t *mask, uint32_t mask_stride, int w,
int h, int subx, int suby, ConvolveParams *conv_params,
const int bd);
typedef libaom_test::FuncParam<FHBD_D16> TestFuncsHBD_d16;
class BlendA64MaskTestHBD_d16
: public BlendA64MaskTest<FHBD_D16, uint16_t, uint16_t> {
protected:
// max number of bits used by the source
static const int kSrcMaxBitsMask = (1 << 14) - 1;
static const int kSrcMaxBitsMaskHBD = (1 << 16) - 1;
void Execute(const uint16_t *p_src0, const uint16_t *p_src1) {
ConvolveParams conv_params;
conv_params.round_0 = (bit_depth_ == 12) ? ROUND0_BITS + 2 : ROUND0_BITS;
conv_params.round_1 = COMPOUND_ROUND1_BITS;
params_.ref_func(CONVERT_TO_BYTEPTR(dst_ref_ + dst_offset_), dst_stride_,
p_src0 + src0_offset_, src0_stride_, p_src1 + src1_offset_,
src1_stride_, mask_, kMaxMaskWidth, w_, h_, subx_, suby_,
&conv_params, bit_depth_);
if (params_.tst_func) {
ASM_REGISTER_STATE_CHECK(params_.tst_func(
CONVERT_TO_BYTEPTR(dst_tst_ + dst_offset_), dst_stride_,
p_src0 + src0_offset_, src0_stride_, p_src1 + src1_offset_,
src1_stride_, mask_, kMaxMaskWidth, w_, h_, subx_, suby_,
&conv_params, bit_depth_));
}
}
int bit_depth_;
int src_max_bits_mask_;
};
TEST_P(BlendA64MaskTestHBD_d16, RandomValues) {
if (params_.tst_func == NULL) return;
for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
switch (rng_(3)) {
case 0: bit_depth_ = 8; break;
case 1: bit_depth_ = 10; break;
default: bit_depth_ = 12; break;
}
src_max_bits_mask_ =
(bit_depth_ == 8) ? kSrcMaxBitsMask : kSrcMaxBitsMaskHBD;
for (int i = 0; i < kBufSize; ++i) {
dst_ref_[i] = rng_.Rand8();
dst_tst_[i] = rng_.Rand8();
src0_[i] = rng_.Rand16() & src_max_bits_mask_;
src1_[i] = rng_.Rand16() & src_max_bits_mask_;
}
for (int i = 0; i < kMaxMaskSize; ++i)
mask_[i] = rng_(AOM_BLEND_A64_MAX_ALPHA + 1);
RunTest();
}
}
TEST_P(BlendA64MaskTestHBD_d16, SaturatedValues) {
for (bit_depth_ = 8; bit_depth_ <= 12; bit_depth_ += 2) {
src_max_bits_mask_ =
(bit_depth_ == 8) ? kSrcMaxBitsMask : kSrcMaxBitsMaskHBD;
for (int i = 0; i < kBufSize; ++i) {
dst_ref_[i] = 0;
dst_tst_[i] = (1 << bit_depth_) - 1;
src0_[i] = src_max_bits_mask_;
src1_[i] = src_max_bits_mask_;
}
for (int i = 0; i < kMaxMaskSize; ++i) mask_[i] = AOM_BLEND_A64_MAX_ALPHA;
RunTest();
}
}
INSTANTIATE_TEST_CASE_P(
C, BlendA64MaskTestHBD_d16,
::testing::Values(TestFuncsHBD_d16(aom_highbd_blend_a64_d16_mask_c, NULL)));
// TODO(slavarnway): Enable the following in the avx2 commit. (56501)
#if 0
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(
SSE4_1, BlendA64MaskTestHBD,
::testing::Values(TestFuncsHBD(aom_highbd_blend_a64_mask_c,
aom_highbd_blend_a64_mask_avx2)));
#endif // HAVE_AVX2
#endif
} // namespace

View file

@ -1,136 +0,0 @@
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
namespace {
using libaom_test::ACMRandom;
typedef int64_t (*BlockErrorFunc)(const tran_low_t *coeff,
const tran_low_t *dqcoeff, intptr_t size,
int64_t *ssz);
#if CONFIG_HIGHBITDEPTH
typedef int64_t (*HbdBlockErrorFunc)(const tran_low_t *coeff,
const tran_low_t *dqcoeff, intptr_t size,
int64_t *ssz, int bd);
#endif
typedef std::tr1::tuple<BlockErrorFunc, BlockErrorFunc, TX_SIZE,
aom_bit_depth_t>
BlockErrorParam;
const int kTestNum = 10000;
class BlockErrorTest : public ::testing::TestWithParam<BlockErrorParam> {
public:
BlockErrorTest()
: blk_err_ref_(GET_PARAM(0)), blk_err_(GET_PARAM(1)),
tx_size_(GET_PARAM(2)), bd_(GET_PARAM(3)) {}
virtual ~BlockErrorTest() {}
virtual void SetUp() {
const intptr_t block_size = getCoeffNum();
coeff_ = reinterpret_cast<tran_low_t *>(
aom_memalign(16, 2 * block_size * sizeof(tran_low_t)));
}
virtual void TearDown() {
aom_free(coeff_);
coeff_ = NULL;
libaom_test::ClearSystemState();
}
void BlockErrorRun(int testNum) {
int i;
int64_t error_ref, error;
int64_t sse_ref, sse;
const intptr_t block_size = getCoeffNum();
tran_low_t *dqcoeff = coeff_ + block_size;
for (i = 0; i < testNum; ++i) {
FillRandomData();
error_ref = blk_err_ref_(coeff_, dqcoeff, block_size, &sse_ref);
ASM_REGISTER_STATE_CHECK(error =
blk_err_(coeff_, dqcoeff, block_size, &sse));
EXPECT_EQ(error_ref, error) << "Error doesn't match on test: " << i;
EXPECT_EQ(sse_ref, sse) << "SSE doesn't match on test: " << i;
}
}
intptr_t getCoeffNum() { return tx_size_2d[tx_size_]; }
void FillRandomData() {
const intptr_t block_size = getCoeffNum();
tran_low_t *dqcoeff = coeff_ + block_size;
intptr_t i;
int16_t margin = 512;
for (i = 0; i < block_size; ++i) {
coeff_[i] = GetRandomNumWithRange(INT16_MIN + margin, INT16_MAX - margin);
dqcoeff[i] = coeff_[i] + GetRandomDeltaWithRange(margin);
}
}
void FillConstantData() {
const intptr_t block_size = getCoeffNum();
tran_low_t *dqcoeff = coeff_ + block_size;
intptr_t i;
for (i = 0; i < block_size; ++i) {
coeff_[i] = 5;
dqcoeff[i] = 7;
}
}
tran_low_t GetRandomNumWithRange(int16_t min, int16_t max) {
return clamp((int16_t)rnd_.Rand16(), min, max);
}
tran_low_t GetRandomDeltaWithRange(int16_t delta) {
tran_low_t value = (int16_t)rnd_.Rand16();
value %= delta;
return value;
}
BlockErrorFunc blk_err_ref_;
BlockErrorFunc blk_err_;
TX_SIZE tx_size_;
aom_bit_depth_t bd_;
ACMRandom rnd_;
tran_low_t *coeff_;
};
TEST_P(BlockErrorTest, BitExact) { BlockErrorRun(kTestNum); }
using std::tr1::make_tuple;
#if !CONFIG_HIGHBITDEPTH && HAVE_SSE2
const BlockErrorParam kBlkErrParamArraySse2[] = { make_tuple(
&av1_block_error_c, &av1_block_error_sse2, TX_32X32, AOM_BITS_8) };
INSTANTIATE_TEST_CASE_P(SSE2, BlockErrorTest,
::testing::ValuesIn(kBlkErrParamArraySse2));
#endif
#if HAVE_AVX2
const BlockErrorParam kBlkErrParamArrayAvx2[] = { make_tuple(
&av1_block_error_c, &av1_block_error_avx2, TX_32X32, AOM_BITS_8) };
INSTANTIATE_TEST_CASE_P(AVX2, BlockErrorTest,
::testing::ValuesIn(kBlkErrParamArrayAvx2));
#endif
} // namespace

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <math.h>
#include <stdlib.h>
@ -69,7 +69,7 @@ TEST(AV1, TestBitIO) {
aom_stop_encode(&bw);
aom_reader br;
aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
aom_reader_init(&br, bw_buffer, bw.pos);
bit_rnd.Reset(random_seed);
for (int i = 0; i < kBitsToTest; ++i) {
if (bit_method == 2) {
@ -86,7 +86,7 @@ TEST(AV1, TestBitIO) {
}
}
#define FRAC_DIFF_TOTAL_ERROR 0.16
#define FRAC_DIFF_TOTAL_ERROR 0.18
TEST(AV1, TestTell) {
const int kBufferSize = 10000;
@ -102,7 +102,7 @@ TEST(AV1, TestTell) {
}
aom_stop_encode(&bw);
aom_reader br;
aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
aom_reader_init(&br, bw_buffer, bw.pos);
uint32_t last_tell = aom_reader_tell(&br);
uint32_t last_tell_frac = aom_reader_tell_frac(&br);
double frac_diff_total = 0;

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <climits>
#include <vector>
@ -19,12 +19,12 @@
namespace {
class BordersTest
class BordersTestLarge
: public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
public ::libaom_test::EncoderTest {
protected:
BordersTest() : EncoderTest(GET_PARAM(0)) {}
virtual ~BordersTest() {}
BordersTestLarge() : EncoderTest(GET_PARAM(0)) {}
virtual ~BordersTestLarge() {}
virtual void SetUp() {
InitializeConfig();
@ -47,7 +47,7 @@ class BordersTest
}
};
TEST_P(BordersTest, TestEncodeHighBitrate) {
TEST_P(BordersTestLarge, 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
@ -63,7 +63,7 @@ TEST_P(BordersTest, TestEncodeHighBitrate) {
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
TEST_P(BordersTest, TestLowBitrate) {
TEST_P(BordersTestLarge, 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.
@ -80,6 +80,6 @@ TEST_P(BordersTest, TestLowBitrate) {
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
}
AV1_INSTANTIATE_TEST_CASE(BordersTest,
AV1_INSTANTIATE_TEST_CASE(BordersTestLarge,
::testing::Values(::libaom_test::kTwoPassGood));
} // namespace

View file

@ -7,15 +7,16 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <cstdlib>
#include <string>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./av1_rtcd.h"
#include "config/aom_config.h"
#include "config/av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/cdef_block.h"
#include "test/acm_random.h"
@ -27,7 +28,8 @@ using libaom_test::ACMRandom;
namespace {
typedef std::tr1::tuple<cdef_filter_block_func, cdef_filter_block_func, int>
typedef ::testing::tuple<cdef_filter_block_func, cdef_filter_block_func,
BLOCK_SIZE, int, int>
cdef_dir_param_t;
class CDEFBlockTest : public ::testing::TestWithParam<cdef_dir_param_t> {
@ -37,12 +39,16 @@ class CDEFBlockTest : public ::testing::TestWithParam<cdef_dir_param_t> {
cdef = GET_PARAM(0);
ref_cdef = GET_PARAM(1);
bsize = GET_PARAM(2);
boundary = GET_PARAM(3);
depth = GET_PARAM(4);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
int bsize;
int boundary;
int depth;
cdef_filter_block_func cdef;
cdef_filter_block_func ref_cdef;
};
@ -50,7 +56,7 @@ class CDEFBlockTest : public ::testing::TestWithParam<cdef_dir_param_t> {
typedef CDEFBlockTest CDEFSpeedTest;
void test_cdef(int bsize, int iterations, cdef_filter_block_func cdef,
cdef_filter_block_func ref_cdef) {
cdef_filter_block_func ref_cdef, int boundary, int depth) {
const int size = 8;
const int ysize = size + 2 * CDEF_VBORDER;
ACMRandom rnd(ACMRandom::DeterministicSeed());
@ -61,80 +67,73 @@ void test_cdef(int bsize, int iterations, cdef_filter_block_func cdef,
memset(d, 0, sizeof(d));
int error = 0, pristrength = 0, secstrength, dir;
int boundary, pridamping, secdamping, depth, bits, level, count,
int pridamping, secdamping, bits, level, count,
errdepth = 0, errpristrength = 0, errsecstrength = 0, errboundary = 0,
errpridamping = 0, errsecdamping = 0;
unsigned int pos = 0;
for (boundary = 0; boundary < 16; boundary++) {
for (depth = 8; depth <= 12; depth += 2) {
const unsigned int max_pos = size * size >> (depth == 8);
for (pridamping = 3 + depth - 8;
pridamping < 7 - 3 * !!boundary + depth - 8; pridamping++) {
for (secdamping = 3 + depth - 8;
secdamping < 7 - 3 * !!boundary + depth - 8; secdamping++) {
for (count = 0; count < iterations; count++) {
for (level = 0; level < (1 << depth) && !error;
level += (2 + 6 * !!boundary) << (depth - 8)) {
for (bits = 1; bits <= depth && !error;
bits += 1 + 3 * !!boundary) {
for (unsigned int i = 0; i < sizeof(s) / sizeof(*s); i++)
s[i] = clamp((rnd.Rand16() & ((1 << bits) - 1)) + level, 0,
(1 << depth) - 1);
if (boundary) {
if (boundary & 1) { // Left
for (int i = 0; i < ysize; i++)
for (int j = 0; j < CDEF_HBORDER; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 2) { // Right
for (int i = 0; i < ysize; i++)
for (int j = CDEF_HBORDER + size; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 4) { // Above
for (int i = 0; i < CDEF_VBORDER; i++)
for (int j = 0; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 8) { // Below
for (int i = CDEF_VBORDER + size; i < ysize; i++)
for (int j = 0; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
}
for (dir = 0; dir < 8; dir++) {
for (pristrength = 0;
pristrength <= 19 << (depth - 8) && !error;
pristrength += (1 + 4 * !!boundary) << (depth - 8)) {
if (pristrength == 16) pristrength = 19;
for (secstrength = 0;
secstrength <= 4 << (depth - 8) && !error;
secstrength += 1 << (depth - 8)) {
if (secstrength == 3 << (depth - 8)) continue;
ref_cdef(depth == 8 ? (uint8_t *)ref_d : 0, ref_d, size,
s + CDEF_HBORDER + CDEF_VBORDER * CDEF_BSTRIDE,
pristrength, secstrength, dir, pridamping,
secdamping, bsize, (1 << depth) - 1);
// If cdef and ref_cdef are the same, we're just testing
// speed
if (cdef != ref_cdef)
ASM_REGISTER_STATE_CHECK(
cdef(depth == 8 ? (uint8_t *)d : 0, d, size,
s + CDEF_HBORDER + CDEF_VBORDER * CDEF_BSTRIDE,
pristrength, secstrength, dir, pridamping,
secdamping, bsize, (1 << depth) - 1));
if (ref_cdef != cdef) {
for (pos = 0; pos < max_pos && !error; pos++) {
error = ref_d[pos] != d[pos];
errdepth = depth;
errpristrength = pristrength;
errsecstrength = secstrength;
errboundary = boundary;
errpridamping = pridamping;
errsecdamping = secdamping;
}
}
const unsigned int max_pos = size * size >> static_cast<int>(depth == 8);
for (pridamping = 3 + depth - 8; pridamping < 7 - 3 * !!boundary + depth - 8;
pridamping++) {
for (secdamping = 3 + depth - 8;
secdamping < 7 - 3 * !!boundary + depth - 8; secdamping++) {
for (count = 0; count < iterations; count++) {
for (level = 0; level < (1 << depth) && !error;
level += (2 + 6 * !!boundary) << (depth - 8)) {
for (bits = 1; bits <= depth && !error; bits += 1 + 3 * !!boundary) {
for (unsigned int i = 0; i < sizeof(s) / sizeof(*s); i++)
s[i] = clamp((rnd.Rand16() & ((1 << bits) - 1)) + level, 0,
(1 << depth) - 1);
if (boundary) {
if (boundary & 1) { // Left
for (int i = 0; i < ysize; i++)
for (int j = 0; j < CDEF_HBORDER; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 2) { // Right
for (int i = 0; i < ysize; i++)
for (int j = CDEF_HBORDER + size; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 4) { // Above
for (int i = 0; i < CDEF_VBORDER; i++)
for (int j = 0; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 8) { // Below
for (int i = CDEF_VBORDER + size; i < ysize; i++)
for (int j = 0; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
}
for (dir = 0; dir < 8; dir++) {
for (pristrength = 0; pristrength <= 19 << (depth - 8) && !error;
pristrength += (1 + 4 * !!boundary) << (depth - 8)) {
if (pristrength == 16) pristrength = 19;
for (secstrength = 0; secstrength <= 4 << (depth - 8) && !error;
secstrength += 1 << (depth - 8)) {
if (secstrength == 3 << (depth - 8)) continue;
ref_cdef(depth == 8 ? (uint8_t *)ref_d : 0, ref_d, size,
s + CDEF_HBORDER + CDEF_VBORDER * CDEF_BSTRIDE,
pristrength, secstrength, dir, pridamping,
secdamping, bsize, (1 << depth) - 1, depth - 8);
// If cdef and ref_cdef are the same, we're just testing
// speed
if (cdef != ref_cdef)
ASM_REGISTER_STATE_CHECK(
cdef(depth == 8 ? (uint8_t *)d : 0, d, size,
s + CDEF_HBORDER + CDEF_VBORDER * CDEF_BSTRIDE,
pristrength, secstrength, dir, pridamping,
secdamping, bsize, (1 << depth) - 1, depth - 8));
if (ref_cdef != cdef) {
for (pos = 0; pos < max_pos && !error; pos++) {
error = ref_d[pos] != d[pos];
errdepth = depth;
errpristrength = pristrength;
errsecstrength = secstrength;
errboundary = boundary;
errpridamping = pridamping;
errsecdamping = secdamping;
}
}
}
@ -145,6 +144,7 @@ void test_cdef(int bsize, int iterations, cdef_filter_block_func cdef,
}
}
}
pos--;
EXPECT_EQ(0, error) << "Error: CDEFBlockTest, SIMD and C mismatch."
<< std::endl
@ -162,25 +162,20 @@ void test_cdef(int bsize, int iterations, cdef_filter_block_func cdef,
}
void test_cdef_speed(int bsize, int iterations, cdef_filter_block_func cdef,
cdef_filter_block_func ref_cdef) {
cdef_filter_block_func ref_cdef, int boundary, int depth) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
aom_usec_timer_start(&ref_timer);
test_cdef(bsize, iterations, ref_cdef, ref_cdef);
test_cdef(bsize, iterations, ref_cdef, ref_cdef, boundary, depth);
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
test_cdef(bsize, iterations, cdef, cdef);
test_cdef(bsize, iterations, cdef, cdef, boundary, depth);
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
#if 0
std::cout << "[ ] C time = " << ref_elapsed_time / 1000
<< " ms, SIMD time = " << elapsed_time / 1000 << " ms" << std::endl;
#endif
EXPECT_GT(ref_elapsed_time, elapsed_time)
<< "Error: CDEFSpeedTest, SIMD slower than C." << std::endl
<< "C time: " << ref_elapsed_time << " us" << std::endl
@ -190,7 +185,7 @@ void test_cdef_speed(int bsize, int iterations, cdef_filter_block_func cdef,
typedef int (*find_dir_t)(const uint16_t *img, int stride, int32_t *var,
int coeff_shift);
typedef std::tr1::tuple<find_dir_t, find_dir_t> find_dir_param_t;
typedef ::testing::tuple<find_dir_t, find_dir_t> find_dir_param_t;
class CDEFFindDirTest : public ::testing::TestWithParam<find_dir_param_t> {
public:
@ -268,11 +263,6 @@ void test_finddir_speed(int (*finddir)(const uint16_t *img, int stride,
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
#if 0
std::cout << "[ ] C time = " << ref_elapsed_time / 1000
<< " ms, SIMD time = " << elapsed_time / 1000 << " ms" << std::endl;
#endif
EXPECT_GT(ref_elapsed_time, elapsed_time)
<< "Error: CDEFFindDirSpeedTest, SIMD slower than C." << std::endl
<< "C time: " << ref_elapsed_time << " us" << std::endl
@ -280,11 +270,11 @@ void test_finddir_speed(int (*finddir)(const uint16_t *img, int stride,
}
TEST_P(CDEFBlockTest, TestSIMDNoMismatch) {
test_cdef(bsize, 1, cdef, ref_cdef);
test_cdef(bsize, 1, cdef, ref_cdef, boundary, depth);
}
TEST_P(CDEFSpeedTest, DISABLED_TestSpeed) {
test_cdef_speed(bsize, 4, cdef, ref_cdef);
test_cdef_speed(bsize, 4, cdef, ref_cdef, boundary, depth);
}
TEST_P(CDEFFindDirTest, TestSIMDNoMismatch) {
@ -295,7 +285,7 @@ TEST_P(CDEFFindDirSpeedTest, DISABLED_TestSpeed) {
test_finddir_speed(finddir, ref_finddir);
}
using std::tr1::make_tuple;
using ::testing::make_tuple;
// VS compiling for 32 bit targets does not support vector types in
// structs as arguments, which makes the v256 type of the intrinsics
@ -304,9 +294,11 @@ using std::tr1::make_tuple;
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, CDEFBlockTest,
::testing::Values(
make_tuple(&cdef_filter_block_sse2, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_sse2, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_sse2),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(SSE2, CDEFFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_sse2,
&cdef_find_dir_c)));
@ -314,9 +306,11 @@ INSTANTIATE_TEST_CASE_P(SSE2, CDEFFindDirTest,
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, CDEFBlockTest,
::testing::Values(
make_tuple(&cdef_filter_block_ssse3, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_ssse3, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_ssse3),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_ssse3,
&cdef_find_dir_c)));
@ -325,10 +319,11 @@ INSTANTIATE_TEST_CASE_P(SSSE3, CDEFFindDirTest,
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, CDEFBlockTest,
::testing::Values(make_tuple(&cdef_filter_block_sse4_1,
&cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_sse4_1,
&cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_sse4_1),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_sse4_1,
&cdef_find_dir_c)));
@ -337,9 +332,11 @@ INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFFindDirTest,
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(
AVX2, CDEFBlockTest,
::testing::Values(
make_tuple(&cdef_filter_block_avx2, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_avx2, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_avx2),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(AVX2, CDEFFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_avx2,
&cdef_find_dir_c)));
@ -348,9 +345,11 @@ INSTANTIATE_TEST_CASE_P(AVX2, CDEFFindDirTest,
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, CDEFBlockTest,
::testing::Values(
make_tuple(&cdef_filter_block_neon, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_neon, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_neon),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(NEON, CDEFFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_neon,
&cdef_find_dir_c)));
@ -360,9 +359,11 @@ INSTANTIATE_TEST_CASE_P(NEON, CDEFFindDirTest,
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, CDEFSpeedTest,
::testing::Values(
make_tuple(&cdef_filter_block_sse2, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_sse2, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_sse2),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(SSE2, CDEFFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_sse2,
&cdef_find_dir_c)));
@ -371,9 +372,11 @@ INSTANTIATE_TEST_CASE_P(SSE2, CDEFFindDirSpeedTest,
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, CDEFSpeedTest,
::testing::Values(
make_tuple(&cdef_filter_block_ssse3, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_ssse3, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_ssse3),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_ssse3,
&cdef_find_dir_c)));
@ -382,10 +385,11 @@ INSTANTIATE_TEST_CASE_P(SSSE3, CDEFFindDirSpeedTest,
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, CDEFSpeedTest,
::testing::Values(make_tuple(&cdef_filter_block_sse4_1,
&cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_sse4_1,
&cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_sse4_1),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_sse4_1,
&cdef_find_dir_c)));
@ -394,9 +398,11 @@ INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFFindDirSpeedTest,
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(
AVX2, CDEFSpeedTest,
::testing::Values(
make_tuple(&cdef_filter_block_avx2, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_avx2, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_avx2),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(AVX2, CDEFFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_avx2,
&cdef_find_dir_c)));
@ -405,9 +411,11 @@ INSTANTIATE_TEST_CASE_P(AVX2, CDEFFindDirSpeedTest,
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, CDEFSpeedTest,
::testing::Values(
make_tuple(&cdef_filter_block_neon, &cdef_filter_block_c, BLOCK_4X4),
make_tuple(&cdef_filter_block_neon, &cdef_filter_block_c, BLOCK_8X8)));
::testing::Combine(::testing::Values(&cdef_filter_block_neon),
::testing::Values(&cdef_filter_block_c),
::testing::Values(BLOCK_4X4, BLOCK_4X8, BLOCK_8X4,
BLOCK_8X8),
::testing::Range(0, 16), ::testing::Range(8, 13, 2)));
INSTANTIATE_TEST_CASE_P(NEON, CDEFFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_neon,
&cdef_find_dir_c)));

567
third_party/aom/test/cfl_test.cc vendored Normal file
View file

@ -0,0 +1,567 @@
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "config/av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "test/util.h"
#include "test/acm_random.h"
using ::testing::make_tuple;
using libaom_test::ACMRandom;
#define NUM_ITERATIONS (100)
#define NUM_ITERATIONS_SPEED (INT16_MAX)
#define ALL_CFL_TX_SIZES(function) \
make_tuple(TX_4X4, &function), make_tuple(TX_4X8, &function), \
make_tuple(TX_4X16, &function), make_tuple(TX_8X4, &function), \
make_tuple(TX_8X8, &function), make_tuple(TX_8X16, &function), \
make_tuple(TX_8X32, &function), make_tuple(TX_16X4, &function), \
make_tuple(TX_16X8, &function), make_tuple(TX_16X16, &function), \
make_tuple(TX_16X32, &function), make_tuple(TX_32X8, &function), \
make_tuple(TX_32X16, &function), make_tuple(TX_32X32, &function)
#define ALL_CFL_TX_SIZES_SUBSAMPLE(fun420, fun422, fun444) \
make_tuple(TX_4X4, &fun420, &fun422, &fun444), \
make_tuple(TX_4X8, &fun420, &fun422, &fun444), \
make_tuple(TX_4X16, &fun420, &fun422, &fun444), \
make_tuple(TX_8X4, &fun420, &fun422, &fun444), \
make_tuple(TX_8X8, &fun420, &fun422, &fun444), \
make_tuple(TX_8X16, &fun420, &fun422, &fun444), \
make_tuple(TX_8X32, &fun420, &fun422, &fun444), \
make_tuple(TX_16X4, &fun420, &fun422, &fun444), \
make_tuple(TX_16X8, &fun420, &fun422, &fun444), \
make_tuple(TX_16X16, &fun420, &fun422, &fun444), \
make_tuple(TX_16X32, &fun420, &fun422, &fun444), \
make_tuple(TX_32X8, &fun420, &fun422, &fun444), \
make_tuple(TX_32X16, &fun420, &fun422, &fun444), \
make_tuple(TX_32X32, &fun420, &fun422, &fun444)
namespace {
template <typename A>
static void assert_eq(const A *a, const A *b, int width, int height) {
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
ASSERT_EQ(a[j * CFL_BUF_LINE + i], b[j * CFL_BUF_LINE + i]);
}
}
}
static void assertFaster(int ref_elapsed_time, int elapsed_time) {
EXPECT_GT(ref_elapsed_time, elapsed_time)
<< "Error: CFLSubtractSpeedTest, SIMD slower than C." << std::endl
<< "C time: " << ref_elapsed_time << " us" << std::endl
<< "SIMD time: " << elapsed_time << " us" << std::endl;
}
static void printSpeed(int ref_elapsed_time, int elapsed_time, int width,
int height) {
std::cout.precision(2);
std::cout << "[ ] " << width << "x" << height
<< ": C time = " << ref_elapsed_time
<< " us, SIMD time = " << elapsed_time << " us"
<< " (~" << ref_elapsed_time / (double)elapsed_time << "x) "
<< std::endl;
}
class CFLTest {
public:
virtual ~CFLTest() {}
void init(TX_SIZE tx) {
tx_size = tx;
width = tx_size_wide[tx_size];
height = tx_size_high[tx_size];
rnd(ACMRandom::DeterministicSeed());
}
protected:
TX_SIZE tx_size;
int width;
int height;
ACMRandom rnd;
};
template <typename I>
class CFLTestWithData : public CFLTest {
public:
virtual ~CFLTestWithData() {}
protected:
I data[CFL_BUF_SQUARE];
I data_ref[CFL_BUF_SQUARE];
void randData(I (ACMRandom::*random)()) {
for (int j = 0; j < this->height; j++) {
for (int i = 0; i < this->width; i++) {
const I d = (this->rnd.*random)();
data[j * CFL_BUF_LINE + i] = d;
data_ref[j * CFL_BUF_LINE + i] = d;
}
}
}
};
template <typename I>
class CFLTestWithAlignedData : public CFLTest {
public:
CFLTestWithAlignedData() {
chroma_pels_ref =
reinterpret_cast<I *>(aom_memalign(32, sizeof(I) * CFL_BUF_SQUARE));
chroma_pels =
reinterpret_cast<I *>(aom_memalign(32, sizeof(I) * CFL_BUF_SQUARE));
sub_luma_pels_ref = reinterpret_cast<int16_t *>(
aom_memalign(32, sizeof(int16_t) * CFL_BUF_SQUARE));
sub_luma_pels = reinterpret_cast<int16_t *>(
aom_memalign(32, sizeof(int16_t) * CFL_BUF_SQUARE));
memset(chroma_pels_ref, 0, sizeof(I) * CFL_BUF_SQUARE);
memset(chroma_pels, 0, sizeof(I) * CFL_BUF_SQUARE);
memset(sub_luma_pels_ref, 0, sizeof(int16_t) * CFL_BUF_SQUARE);
memset(sub_luma_pels, 0, sizeof(int16_t) * CFL_BUF_SQUARE);
}
~CFLTestWithAlignedData() {
aom_free(chroma_pels_ref);
aom_free(sub_luma_pels_ref);
aom_free(chroma_pels);
aom_free(sub_luma_pels);
}
protected:
I *chroma_pels_ref;
I *chroma_pels;
int16_t *sub_luma_pels_ref;
int16_t *sub_luma_pels;
int alpha_q3;
I dc;
void randData(int bd) {
alpha_q3 = this->rnd(33) - 16;
dc = this->rnd(1 << bd);
for (int j = 0; j < this->height; j++) {
for (int i = 0; i < this->width; i++) {
chroma_pels[j * CFL_BUF_LINE + i] = dc;
chroma_pels_ref[j * CFL_BUF_LINE + i] = dc;
sub_luma_pels_ref[j * CFL_BUF_LINE + i] =
sub_luma_pels[j * CFL_BUF_LINE + i] = this->rnd(1 << (bd + 3));
}
}
}
};
typedef cfl_subtract_average_fn (*sub_avg_fn)(TX_SIZE tx_size);
typedef ::testing::tuple<TX_SIZE, sub_avg_fn> sub_avg_param;
class CFLSubAvgTest : public ::testing::TestWithParam<sub_avg_param>,
public CFLTestWithData<int16_t> {
public:
virtual void SetUp() {
CFLTest::init(::testing::get<0>(this->GetParam()));
sub_avg = ::testing::get<1>(this->GetParam())(tx_size);
sub_avg_ref = get_subtract_average_fn_c(tx_size);
}
virtual ~CFLSubAvgTest() {}
protected:
cfl_subtract_average_fn sub_avg;
cfl_subtract_average_fn sub_avg_ref;
};
TEST_P(CFLSubAvgTest, SubAvgTest) {
for (int it = 0; it < NUM_ITERATIONS; it++) {
randData(&ACMRandom::Rand15Signed);
sub_avg((uint16_t *)data, data);
sub_avg_ref((uint16_t *)data_ref, data_ref);
assert_eq<int16_t>(data, data_ref, width, height);
}
}
TEST_P(CFLSubAvgTest, DISABLED_SubAvgSpeedTest) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
randData(&ACMRandom::Rand15Signed);
aom_usec_timer_start(&ref_timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
sub_avg_ref((uint16_t *)data_ref, data_ref);
}
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
sub_avg((uint16_t *)data, data);
}
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
printSpeed(ref_elapsed_time, elapsed_time, width, height);
assertFaster(ref_elapsed_time, elapsed_time);
}
template <typename S, typename T, typename I>
class CFLSubsampleTest : public ::testing::TestWithParam<S>,
public CFLTestWithData<I> {
public:
virtual void SetUp() {
CFLTest::init(::testing::get<0>(this->GetParam()));
fun_420 = ::testing::get<1>(this->GetParam())(this->tx_size);
fun_422 = ::testing::get<2>(this->GetParam())(this->tx_size);
fun_444 = ::testing::get<3>(this->GetParam())(this->tx_size);
}
protected:
T fun_420;
T fun_422;
T fun_444;
T fun_420_ref;
T fun_422_ref;
T fun_444_ref;
void subsampleTest(T fun, T fun_ref, int sub_width, int sub_height,
I (ACMRandom::*random)()) {
uint16_t sub_luma_pels[CFL_BUF_SQUARE];
uint16_t sub_luma_pels_ref[CFL_BUF_SQUARE];
for (int it = 0; it < NUM_ITERATIONS; it++) {
CFLTestWithData<I>::randData(random);
fun(this->data, CFL_BUF_LINE, sub_luma_pels);
fun_ref(this->data_ref, CFL_BUF_LINE, sub_luma_pels_ref);
assert_eq<uint16_t>(sub_luma_pels, sub_luma_pels_ref, sub_width,
sub_height);
}
}
void subsampleSpeedTest(T fun, T fun_ref, I (ACMRandom::*random)()) {
uint16_t sub_luma_pels[CFL_BUF_SQUARE];
uint16_t sub_luma_pels_ref[CFL_BUF_SQUARE];
aom_usec_timer ref_timer;
aom_usec_timer timer;
CFLTestWithData<I>::randData(random);
aom_usec_timer_start(&ref_timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
fun_ref(this->data_ref, CFL_BUF_LINE, sub_luma_pels);
}
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
fun(this->data, CFL_BUF_LINE, sub_luma_pels_ref);
}
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
printSpeed(ref_elapsed_time, elapsed_time, this->width, this->height);
assertFaster(ref_elapsed_time, elapsed_time);
}
};
typedef cfl_subsample_lbd_fn (*get_subsample_lbd_fn)(TX_SIZE tx_size);
typedef ::testing::tuple<TX_SIZE, get_subsample_lbd_fn, get_subsample_lbd_fn,
get_subsample_lbd_fn>
subsample_lbd_param;
class CFLSubsampleLBDTest
: public CFLSubsampleTest<subsample_lbd_param, cfl_subsample_lbd_fn,
uint8_t> {
public:
virtual ~CFLSubsampleLBDTest() {}
virtual void SetUp() {
CFLSubsampleTest::SetUp();
fun_420_ref = cfl_get_luma_subsampling_420_lbd_c(tx_size);
fun_422_ref = cfl_get_luma_subsampling_422_lbd_c(tx_size);
fun_444_ref = cfl_get_luma_subsampling_444_lbd_c(tx_size);
}
};
TEST_P(CFLSubsampleLBDTest, SubsampleLBD420Test) {
subsampleTest(fun_420, fun_420_ref, width >> 1, height >> 1,
&ACMRandom::Rand8);
}
TEST_P(CFLSubsampleLBDTest, DISABLED_SubsampleLBD420SpeedTest) {
subsampleSpeedTest(fun_420, fun_420_ref, &ACMRandom::Rand8);
}
TEST_P(CFLSubsampleLBDTest, SubsampleLBD422Test) {
subsampleTest(fun_422, fun_422_ref, width >> 1, height, &ACMRandom::Rand8);
}
TEST_P(CFLSubsampleLBDTest, DISABLED_SubsampleLBD422SpeedTest) {
subsampleSpeedTest(fun_422, fun_422_ref, &ACMRandom::Rand8);
}
TEST_P(CFLSubsampleLBDTest, SubsampleLBD444Test) {
subsampleTest(fun_444, fun_444_ref, width, height, &ACMRandom::Rand8);
}
TEST_P(CFLSubsampleLBDTest, DISABLED_SubsampleLBD444SpeedTest) {
subsampleSpeedTest(fun_444, fun_444_ref, &ACMRandom::Rand8);
}
typedef cfl_subsample_hbd_fn (*get_subsample_hbd_fn)(TX_SIZE tx_size);
typedef ::testing::tuple<TX_SIZE, get_subsample_hbd_fn, get_subsample_hbd_fn,
get_subsample_hbd_fn>
subsample_hbd_param;
class CFLSubsampleHBDTest
: public CFLSubsampleTest<subsample_hbd_param, cfl_subsample_hbd_fn,
uint16_t> {
public:
virtual ~CFLSubsampleHBDTest() {}
virtual void SetUp() {
CFLSubsampleTest::SetUp();
fun_420_ref = cfl_get_luma_subsampling_420_hbd_c(tx_size);
fun_422_ref = cfl_get_luma_subsampling_422_hbd_c(tx_size);
fun_444_ref = cfl_get_luma_subsampling_444_hbd_c(tx_size);
}
};
TEST_P(CFLSubsampleHBDTest, SubsampleHBD420Test) {
subsampleTest(fun_420, fun_420_ref, width >> 1, height >> 1,
&ACMRandom::Rand12);
}
TEST_P(CFLSubsampleHBDTest, DISABLED_SubsampleHBD420SpeedTest) {
subsampleSpeedTest(fun_420, fun_420_ref, &ACMRandom::Rand12);
}
TEST_P(CFLSubsampleHBDTest, SubsampleHBD422Test) {
subsampleTest(fun_422, fun_422_ref, width >> 1, height, &ACMRandom::Rand12);
}
TEST_P(CFLSubsampleHBDTest, DISABLED_SubsampleHBD422SpeedTest) {
subsampleSpeedTest(fun_422, fun_422_ref, &ACMRandom::Rand12);
}
TEST_P(CFLSubsampleHBDTest, SubsampleHBD444Test) {
subsampleTest(fun_444, fun_444_ref, width, height, &ACMRandom::Rand12);
}
TEST_P(CFLSubsampleHBDTest, DISABLED_SubsampleHBD444SpeedTest) {
subsampleSpeedTest(fun_444, fun_444_ref, &ACMRandom::Rand12);
}
typedef cfl_predict_lbd_fn (*get_predict_fn)(TX_SIZE tx_size);
typedef ::testing::tuple<TX_SIZE, get_predict_fn> predict_param;
class CFLPredictTest : public ::testing::TestWithParam<predict_param>,
public CFLTestWithAlignedData<uint8_t> {
public:
virtual void SetUp() {
CFLTest::init(::testing::get<0>(this->GetParam()));
predict = ::testing::get<1>(this->GetParam())(tx_size);
predict_ref = get_predict_lbd_fn_c(tx_size);
}
virtual ~CFLPredictTest() {}
protected:
cfl_predict_lbd_fn predict;
cfl_predict_lbd_fn predict_ref;
};
TEST_P(CFLPredictTest, PredictTest) {
for (int it = 0; it < NUM_ITERATIONS; it++) {
randData(8);
predict(sub_luma_pels, chroma_pels, CFL_BUF_LINE, alpha_q3);
predict_ref(sub_luma_pels_ref, chroma_pels_ref, CFL_BUF_LINE, alpha_q3);
assert_eq<uint8_t>(chroma_pels, chroma_pels_ref, width, height);
}
}
TEST_P(CFLPredictTest, DISABLED_PredictSpeedTest) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
randData(8);
aom_usec_timer_start(&ref_timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
predict_ref(sub_luma_pels_ref, chroma_pels_ref, CFL_BUF_LINE, alpha_q3);
}
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
predict(sub_luma_pels, chroma_pels, CFL_BUF_LINE, alpha_q3);
}
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
printSpeed(ref_elapsed_time, elapsed_time, width, height);
assertFaster(ref_elapsed_time, elapsed_time);
}
typedef cfl_predict_hbd_fn (*get_predict_fn_hbd)(TX_SIZE tx_size);
typedef ::testing::tuple<TX_SIZE, get_predict_fn_hbd> predict_param_hbd;
class CFLPredictHBDTest : public ::testing::TestWithParam<predict_param_hbd>,
public CFLTestWithAlignedData<uint16_t> {
public:
virtual void SetUp() {
CFLTest::init(::testing::get<0>(this->GetParam()));
predict = ::testing::get<1>(this->GetParam())(tx_size);
predict_ref = get_predict_hbd_fn_c(tx_size);
}
virtual ~CFLPredictHBDTest() {}
protected:
cfl_predict_hbd_fn predict;
cfl_predict_hbd_fn predict_ref;
};
TEST_P(CFLPredictHBDTest, PredictHBDTest) {
int bd = 12;
for (int it = 0; it < NUM_ITERATIONS; it++) {
randData(bd);
predict(sub_luma_pels, chroma_pels, CFL_BUF_LINE, alpha_q3, bd);
predict_ref(sub_luma_pels_ref, chroma_pels_ref, CFL_BUF_LINE, alpha_q3, bd);
assert_eq<uint16_t>(chroma_pels, chroma_pels_ref, width, height);
}
}
TEST_P(CFLPredictHBDTest, DISABLED_PredictHBDSpeedTest) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
const int bd = 12;
randData(bd);
aom_usec_timer_start(&ref_timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
predict_ref(sub_luma_pels_ref, chroma_pels_ref, CFL_BUF_LINE, alpha_q3, bd);
}
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
for (int k = 0; k < NUM_ITERATIONS_SPEED; k++) {
predict(sub_luma_pels, chroma_pels, CFL_BUF_LINE, alpha_q3, bd);
}
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
printSpeed(ref_elapsed_time, elapsed_time, width, height);
assertFaster(ref_elapsed_time, elapsed_time);
}
#if HAVE_SSE2
const sub_avg_param sub_avg_sizes_sse2[] = { ALL_CFL_TX_SIZES(
get_subtract_average_fn_sse2) };
INSTANTIATE_TEST_CASE_P(SSE2, CFLSubAvgTest,
::testing::ValuesIn(sub_avg_sizes_sse2));
#endif
#if HAVE_SSSE3
const subsample_lbd_param subsample_lbd_sizes_ssse3[] = {
ALL_CFL_TX_SIZES_SUBSAMPLE(cfl_get_luma_subsampling_420_lbd_ssse3,
cfl_get_luma_subsampling_422_lbd_ssse3,
cfl_get_luma_subsampling_444_lbd_ssse3)
};
const subsample_hbd_param subsample_hbd_sizes_ssse3[] = {
ALL_CFL_TX_SIZES_SUBSAMPLE(cfl_get_luma_subsampling_420_hbd_ssse3,
cfl_get_luma_subsampling_422_hbd_ssse3,
cfl_get_luma_subsampling_444_hbd_ssse3)
};
const predict_param predict_sizes_ssse3[] = { ALL_CFL_TX_SIZES(
get_predict_lbd_fn_ssse3) };
const predict_param_hbd predict_sizes_hbd_ssse3[] = { ALL_CFL_TX_SIZES(
get_predict_hbd_fn_ssse3) };
INSTANTIATE_TEST_CASE_P(SSSE3, CFLSubsampleLBDTest,
::testing::ValuesIn(subsample_lbd_sizes_ssse3));
INSTANTIATE_TEST_CASE_P(SSSE3, CFLSubsampleHBDTest,
::testing::ValuesIn(subsample_hbd_sizes_ssse3));
INSTANTIATE_TEST_CASE_P(SSSE3, CFLPredictTest,
::testing::ValuesIn(predict_sizes_ssse3));
INSTANTIATE_TEST_CASE_P(SSSE3, CFLPredictHBDTest,
::testing::ValuesIn(predict_sizes_hbd_ssse3));
#endif
#if HAVE_AVX2
const sub_avg_param sub_avg_sizes_avx2[] = { ALL_CFL_TX_SIZES(
get_subtract_average_fn_avx2) };
const subsample_lbd_param subsample_lbd_sizes_avx2[] = {
ALL_CFL_TX_SIZES_SUBSAMPLE(cfl_get_luma_subsampling_420_lbd_avx2,
cfl_get_luma_subsampling_422_lbd_avx2,
cfl_get_luma_subsampling_444_lbd_avx2)
};
const subsample_hbd_param subsample_hbd_sizes_avx2[] = {
ALL_CFL_TX_SIZES_SUBSAMPLE(cfl_get_luma_subsampling_420_hbd_avx2,
cfl_get_luma_subsampling_422_hbd_avx2,
cfl_get_luma_subsampling_444_hbd_avx2)
};
const predict_param predict_sizes_avx2[] = { ALL_CFL_TX_SIZES(
get_predict_lbd_fn_avx2) };
const predict_param_hbd predict_sizes_hbd_avx2[] = { ALL_CFL_TX_SIZES(
get_predict_hbd_fn_avx2) };
INSTANTIATE_TEST_CASE_P(AVX2, CFLSubAvgTest,
::testing::ValuesIn(sub_avg_sizes_avx2));
INSTANTIATE_TEST_CASE_P(AVX2, CFLSubsampleLBDTest,
::testing::ValuesIn(subsample_lbd_sizes_avx2));
INSTANTIATE_TEST_CASE_P(AVX2, CFLSubsampleHBDTest,
::testing::ValuesIn(subsample_hbd_sizes_avx2));
INSTANTIATE_TEST_CASE_P(AVX2, CFLPredictTest,
::testing::ValuesIn(predict_sizes_avx2));
INSTANTIATE_TEST_CASE_P(AVX2, CFLPredictHBDTest,
::testing::ValuesIn(predict_sizes_hbd_avx2));
#endif
#if HAVE_NEON
const sub_avg_param sub_avg_sizes_neon[] = { ALL_CFL_TX_SIZES(
get_subtract_average_fn_neon) };
const subsample_lbd_param subsample_lbd_sizes_neon[] = {
ALL_CFL_TX_SIZES_SUBSAMPLE(cfl_get_luma_subsampling_420_lbd_neon,
cfl_get_luma_subsampling_422_lbd_neon,
cfl_get_luma_subsampling_444_lbd_neon)
};
const subsample_hbd_param subsample_hbd_sizes_neon[] = {
ALL_CFL_TX_SIZES_SUBSAMPLE(cfl_get_luma_subsampling_420_hbd_neon,
cfl_get_luma_subsampling_422_hbd_neon,
cfl_get_luma_subsampling_444_hbd_neon)
};
const predict_param predict_sizes_neon[] = { ALL_CFL_TX_SIZES(
get_predict_lbd_fn_neon) };
const predict_param_hbd predict_sizes_hbd_neon[] = { ALL_CFL_TX_SIZES(
get_predict_hbd_fn_neon) };
INSTANTIATE_TEST_CASE_P(NEON, CFLSubAvgTest,
::testing::ValuesIn(sub_avg_sizes_neon));
INSTANTIATE_TEST_CASE_P(NEON, CFLSubsampleLBDTest,
::testing::ValuesIn(subsample_lbd_sizes_neon));
INSTANTIATE_TEST_CASE_P(NEON, CFLSubsampleHBDTest,
::testing::ValuesIn(subsample_hbd_sizes_neon));
INSTANTIATE_TEST_CASE_P(NEON, CFLPredictTest,
::testing::ValuesIn(predict_sizes_neon));
INSTANTIATE_TEST_CASE_P(NEON, CFLPredictHBDTest,
::testing::ValuesIn(predict_sizes_hbd_neon));
#endif
#if HAVE_VSX
const sub_avg_param sub_avg_sizes_vsx[] = { ALL_CFL_TX_SIZES(
get_subtract_average_fn_vsx) };
INSTANTIATE_TEST_CASE_P(VSX, CFLSubAvgTest,
::testing::ValuesIn(sub_avg_sizes_vsx));
#endif
} // namespace

View file

@ -11,7 +11,8 @@
#ifndef TEST_CLEAR_SYSTEM_STATE_H_
#define TEST_CLEAR_SYSTEM_STATE_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#if ARCH_X86 || ARCH_X86_64
#include "aom_ports/x86.h"
#endif

View file

@ -1,437 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <cstdlib>
#include <string>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/cdef_block.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef void (*clpf_block_t)(uint8_t *dst, const uint16_t *src, int dstride,
int sstride, int sizex, int sizey,
unsigned int strength, unsigned int bitdepth);
typedef std::tr1::tuple<clpf_block_t, clpf_block_t, int, int>
clpf_block_param_t;
class CDEFClpfBlockTest : public ::testing::TestWithParam<clpf_block_param_t> {
public:
virtual ~CDEFClpfBlockTest() {}
virtual void SetUp() {
clpf = GET_PARAM(0);
ref_clpf = GET_PARAM(1);
sizex = GET_PARAM(2);
sizey = GET_PARAM(3);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
int sizex;
int sizey;
clpf_block_t clpf;
clpf_block_t ref_clpf;
};
typedef CDEFClpfBlockTest CDEFClpfSpeedTest;
#if CONFIG_HIGHBITDEPTH
typedef void (*clpf_block_hbd_t)(uint16_t *dst, const uint16_t *src,
int dstride, int sstride, int sizex, int sizey,
unsigned int strength, unsigned int bitdepth);
typedef std::tr1::tuple<clpf_block_hbd_t, clpf_block_hbd_t, int, int>
clpf_block_hbd_param_t;
class CDEFClpfBlockHbdTest
: public ::testing::TestWithParam<clpf_block_hbd_param_t> {
public:
virtual ~CDEFClpfBlockHbdTest() {}
virtual void SetUp() {
clpf = GET_PARAM(0);
ref_clpf = GET_PARAM(1);
sizex = GET_PARAM(2);
sizey = GET_PARAM(3);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
int sizex;
int sizey;
clpf_block_hbd_t clpf;
clpf_block_hbd_t ref_clpf;
};
typedef CDEFClpfBlockHbdTest ClpfHbdSpeedTest;
#endif
template <typename pixel>
void test_clpf(int w, int h, unsigned int depth, unsigned int iterations,
void (*clpf)(pixel *dst, const uint16_t *src, int dstride,
int sstride, int sizex, int sizey,
unsigned int strength, unsigned int bitdepth),
void (*ref_clpf)(pixel *dst, const uint16_t *src, int dstride,
int sstride, int sizex, int sizey,
unsigned int strength, unsigned int bitdepth)) {
const int size = 24;
ACMRandom rnd(ACMRandom::DeterministicSeed());
DECLARE_ALIGNED(16, uint16_t, s[size * size]);
DECLARE_ALIGNED(16, pixel, d[size * size]);
DECLARE_ALIGNED(16, pixel, ref_d[size * size]);
memset(ref_d, 0, size * size * sizeof(*ref_d));
memset(d, 0, size * size * sizeof(*d));
int error = 0, pos = 0, xpos = 8, ypos = 8;
unsigned int strength = 0, bits, level, count, damp = 0, boundary = 0;
assert(size >= w + 16 && size >= h + 16);
assert(depth >= 8);
// Test every combination of:
// * Input with up to <depth> bits of noise
// * Noise level around every value from 0 to (1<<depth)-1
// * All strengths
// * All dampings
// * Boundaries
// If clpf and ref_clpf are the same, we're just testing speed
for (boundary = 0; boundary < 16; boundary++) {
for (count = 0; count < iterations; count++) {
for (level = 0; level < (1U << depth) && !error;
level += (1 + 4 * !!boundary) << (depth - 8)) {
for (bits = 1; bits <= depth && !error; bits++) {
for (damp = 4 + depth - 8; damp < depth - 1 && !error; damp++) {
for (int i = 0; i < size * size; i++)
s[i] = clamp((rnd.Rand16() & ((1 << bits) - 1)) + level, 0,
(1 << depth) - 1);
if (boundary) {
if (boundary & 1) { // Left
for (int i = 0; i < size; i++)
for (int j = 0; j < xpos; j++)
s[i * size + j] = CDEF_VERY_LARGE;
}
if (boundary & 2) { // Right
for (int i = 0; i < size; i++)
for (int j = xpos + w; j < size; j++)
s[i * size + j] = CDEF_VERY_LARGE;
}
if (boundary & 4) { // Above
for (int i = 0; i < ypos; i++)
for (int j = 0; j < size; j++)
s[i * size + j] = CDEF_VERY_LARGE;
}
if (boundary & 8) { // Below
for (int i = ypos + h; i < size; i++)
for (int j = 0; j < size; j++)
s[i * size + j] = CDEF_VERY_LARGE;
}
}
for (strength = depth - 8; strength < depth - 5 && !error;
strength += !error) {
ref_clpf(ref_d + ypos * size + xpos, s + ypos * size + xpos, size,
size, w, h, 1 << strength, damp);
if (clpf != ref_clpf)
ASM_REGISTER_STATE_CHECK(clpf(d + ypos * size + xpos,
s + ypos * size + xpos, size,
size, w, h, 1 << strength, damp));
if (ref_clpf != clpf) {
for (pos = 0; pos < size * size && !error; pos++) {
error = ref_d[pos] != d[pos];
}
}
}
}
}
}
}
}
pos--;
EXPECT_EQ(0, error)
<< "Error: CDEFClpfBlockTest, SIMD and C mismatch." << std::endl
<< "First error at " << pos % size << "," << pos / size << " ("
<< (int16_t)ref_d[pos] << " != " << (int16_t)d[pos] << ") " << std::endl
<< "strength: " << (1 << strength) << std::endl
<< "damping: " << damp << std::endl
<< "depth: " << depth << std::endl
<< "boundary: " << boundary << std::endl
<< "w: " << w << std::endl
<< "h: " << h << std::endl
<< "A=" << (pos > 2 * size ? (int16_t)s[pos - 2 * size] : -1) << std::endl
<< "B=" << (pos > size ? (int16_t)s[pos - size] : -1) << std::endl
<< "C=" << (pos % size - 2 >= 0 ? (int16_t)s[pos - 2] : -1) << std::endl
<< "D=" << (pos % size - 1 >= 0 ? (int16_t)s[pos - 1] : -1) << std::endl
<< "X=" << (int16_t)s[pos] << std::endl
<< "E=" << (pos % size + 1 < size ? (int16_t)s[pos + 1] : -1) << std::endl
<< "F=" << (pos % size + 2 < size ? (int16_t)s[pos + 2] : -1) << std::endl
<< "G=" << (pos + size < size * size ? (int16_t)s[pos + size] : -1)
<< std::endl
<< "H="
<< (pos + 2 * size < size * size ? (int16_t)s[pos + 2 * size] : -1)
<< std::endl;
}
template <typename pixel>
void test_clpf_speed(int w, int h, unsigned int depth, unsigned int iterations,
void (*clpf)(pixel *dst, const uint16_t *src, int dstride,
int sstride, int sizex, int sizey,
unsigned int strength, unsigned int bitdepth),
void (*ref_clpf)(pixel *dst, const uint16_t *src,
int dstride, int sstride, int sizex,
int sizey, unsigned int strength,
unsigned int bitdepth)) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
aom_usec_timer_start(&ref_timer);
test_clpf(w, h, depth, iterations, ref_clpf, ref_clpf);
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
test_clpf(w, h, depth, iterations, clpf, clpf);
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
#if 0
std::cout << "[ ] C time = " << ref_elapsed_time / 1000
<< " ms, SIMD time = " << elapsed_time / 1000 << " ms" << std::endl;
#endif
EXPECT_GT(ref_elapsed_time, elapsed_time)
<< "Error: CDEFClpfSpeedTest, SIMD slower than C." << std::endl
<< "C time: " << ref_elapsed_time << " us" << std::endl
<< "SIMD time: " << elapsed_time << " us" << std::endl;
}
TEST_P(CDEFClpfBlockTest, TestSIMDNoMismatch) {
test_clpf(sizex, sizey, 8, 1, clpf, ref_clpf);
}
TEST_P(CDEFClpfSpeedTest, DISABLED_TestSpeed) {
test_clpf_speed(sizex, sizey, 8, 16, clpf, ref_clpf);
}
#if CONFIG_HIGHBITDEPTH
TEST_P(CDEFClpfBlockHbdTest, TestSIMDNoMismatch) {
test_clpf(sizex, sizey, 12, 1, clpf, ref_clpf);
}
TEST_P(ClpfHbdSpeedTest, DISABLED_TestSpeed) {
test_clpf_speed(sizex, sizey, 12, 4, clpf, ref_clpf);
}
#endif
using std::tr1::make_tuple;
// VS compiling for 32 bit targets does not support vector types in
// structs as arguments, which makes the v256 type of the intrinsics
// hard to support, so optimizations for this target are disabled.
#if defined(_WIN64) || !defined(_MSC_VER) || defined(__clang__)
// Test all supported architectures and block sizes
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, CDEFClpfBlockTest,
::testing::Values(
make_tuple(&aom_clpf_block_sse2, &aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_block_sse2, &aom_clpf_block_c, 8, 4),
make_tuple(&aom_clpf_block_sse2, &aom_clpf_block_c, 4, 8),
make_tuple(&aom_clpf_block_sse2, &aom_clpf_block_c, 4, 4),
make_tuple(&aom_clpf_hblock_sse2, &aom_clpf_hblock_c, 8, 8),
make_tuple(&aom_clpf_hblock_sse2, &aom_clpf_hblock_c, 8, 4),
make_tuple(&aom_clpf_hblock_sse2, &aom_clpf_hblock_c, 4, 8),
make_tuple(&aom_clpf_hblock_sse2, &aom_clpf_hblock_c, 4, 4)));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, CDEFClpfBlockTest,
::testing::Values(
make_tuple(&aom_clpf_block_ssse3, &aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_block_ssse3, &aom_clpf_block_c, 8, 4),
make_tuple(&aom_clpf_block_ssse3, &aom_clpf_block_c, 4, 8),
make_tuple(&aom_clpf_block_ssse3, &aom_clpf_block_c, 4, 4),
make_tuple(&aom_clpf_hblock_ssse3, &aom_clpf_hblock_c, 8, 8),
make_tuple(&aom_clpf_hblock_ssse3, &aom_clpf_hblock_c, 8, 4),
make_tuple(&aom_clpf_hblock_ssse3, &aom_clpf_hblock_c, 4, 8),
make_tuple(&aom_clpf_hblock_ssse3, &aom_clpf_hblock_c, 4, 4)));
#endif
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, CDEFClpfBlockTest,
::testing::Values(
make_tuple(&aom_clpf_block_sse4_1, &aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_block_sse4_1, &aom_clpf_block_c, 8, 4),
make_tuple(&aom_clpf_block_sse4_1, &aom_clpf_block_c, 4, 8),
make_tuple(&aom_clpf_block_sse4_1, &aom_clpf_block_c, 4, 4),
make_tuple(&aom_clpf_hblock_sse4_1, &aom_clpf_hblock_c, 8, 8),
make_tuple(&aom_clpf_hblock_sse4_1, &aom_clpf_hblock_c, 8, 4),
make_tuple(&aom_clpf_hblock_sse4_1, &aom_clpf_hblock_c, 4, 8),
make_tuple(&aom_clpf_hblock_sse4_1, &aom_clpf_hblock_c, 4, 4)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, CDEFClpfBlockTest,
::testing::Values(
make_tuple(&aom_clpf_block_neon, &aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_block_neon, &aom_clpf_block_c, 8, 4),
make_tuple(&aom_clpf_block_neon, &aom_clpf_block_c, 4, 8),
make_tuple(&aom_clpf_block_neon, &aom_clpf_block_c, 4, 4),
make_tuple(&aom_clpf_hblock_neon, &aom_clpf_hblock_c, 8, 8),
make_tuple(&aom_clpf_hblock_neon, &aom_clpf_hblock_c, 8, 4),
make_tuple(&aom_clpf_hblock_neon, &aom_clpf_hblock_c, 4, 8),
make_tuple(&aom_clpf_hblock_neon, &aom_clpf_hblock_c, 4, 4)));
#endif
#if CONFIG_HIGHBITDEPTH
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, CDEFClpfBlockHbdTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_sse2, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_block_hbd_sse2, &aom_clpf_block_hbd_c, 8, 4),
make_tuple(&aom_clpf_block_hbd_sse2, &aom_clpf_block_hbd_c, 4, 8),
make_tuple(&aom_clpf_block_hbd_sse2, &aom_clpf_block_hbd_c, 4, 4),
make_tuple(&aom_clpf_hblock_hbd_sse2, &aom_clpf_hblock_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_sse2, &aom_clpf_hblock_hbd_c, 8, 4),
make_tuple(&aom_clpf_hblock_hbd_sse2, &aom_clpf_hblock_hbd_c, 4, 8),
make_tuple(&aom_clpf_hblock_hbd_sse2, &aom_clpf_hblock_hbd_c, 4, 4)));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, CDEFClpfBlockHbdTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_ssse3, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_block_hbd_ssse3, &aom_clpf_block_hbd_c, 8, 4),
make_tuple(&aom_clpf_block_hbd_ssse3, &aom_clpf_block_hbd_c, 4, 8),
make_tuple(&aom_clpf_block_hbd_ssse3, &aom_clpf_block_hbd_c, 4, 4),
make_tuple(&aom_clpf_hblock_hbd_ssse3, &aom_clpf_hblock_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_ssse3, &aom_clpf_hblock_hbd_c, 8, 4),
make_tuple(&aom_clpf_hblock_hbd_ssse3, &aom_clpf_hblock_hbd_c, 4, 8),
make_tuple(&aom_clpf_hblock_hbd_ssse3, &aom_clpf_hblock_hbd_c, 4, 4)));
#endif
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, CDEFClpfBlockHbdTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_sse4_1, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_block_hbd_sse4_1, &aom_clpf_block_hbd_c, 8, 4),
make_tuple(&aom_clpf_block_hbd_sse4_1, &aom_clpf_block_hbd_c, 4, 8),
make_tuple(&aom_clpf_block_hbd_sse4_1, &aom_clpf_block_hbd_c, 4, 4),
make_tuple(&aom_clpf_hblock_hbd_sse4_1, &aom_clpf_hblock_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_sse4_1, &aom_clpf_hblock_hbd_c, 8, 4),
make_tuple(&aom_clpf_hblock_hbd_sse4_1, &aom_clpf_hblock_hbd_c, 4, 8),
make_tuple(&aom_clpf_hblock_hbd_sse4_1, &aom_clpf_hblock_hbd_c, 4, 4)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, CDEFClpfBlockHbdTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_neon, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_block_hbd_neon, &aom_clpf_block_hbd_c, 8, 4),
make_tuple(&aom_clpf_block_hbd_neon, &aom_clpf_block_hbd_c, 4, 8),
make_tuple(&aom_clpf_block_hbd_neon, &aom_clpf_block_hbd_c, 4, 4),
make_tuple(&aom_clpf_hblock_hbd_neon, &aom_clpf_hblock_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_neon, &aom_clpf_hblock_hbd_c, 8, 4),
make_tuple(&aom_clpf_hblock_hbd_neon, &aom_clpf_hblock_hbd_c, 4, 8),
make_tuple(&aom_clpf_hblock_hbd_neon, &aom_clpf_hblock_hbd_c, 4, 4)));
#endif
#endif // CONFIG_HIGHBITDEPTH
// Test speed for all supported architectures
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, CDEFClpfSpeedTest,
::testing::Values(make_tuple(&aom_clpf_block_sse2, &aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_hblock_sse2, &aom_clpf_hblock_c, 8,
8)));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFClpfSpeedTest,
::testing::Values(make_tuple(&aom_clpf_block_ssse3,
&aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_hblock_ssse3,
&aom_clpf_hblock_c, 8,
8)));
#endif
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFClpfSpeedTest,
::testing::Values(make_tuple(&aom_clpf_block_sse4_1,
&aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_hblock_sse4_1,
&aom_clpf_hblock_c, 8,
8)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, CDEFClpfSpeedTest,
::testing::Values(make_tuple(&aom_clpf_block_neon, &aom_clpf_block_c, 8, 8),
make_tuple(&aom_clpf_hblock_neon, &aom_clpf_hblock_c, 8,
8)));
#endif
#if CONFIG_HIGHBITDEPTH
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, ClpfHbdSpeedTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_sse2, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_sse2, &aom_clpf_hblock_hbd_c, 8, 8)));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, ClpfHbdSpeedTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_ssse3, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_ssse3, &aom_clpf_hblock_hbd_c, 8, 8)));
#endif
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(
SSE4_1, ClpfHbdSpeedTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_sse4_1, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_sse4_1, &aom_clpf_hblock_hbd_c, 8, 8)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(
NEON, ClpfHbdSpeedTest,
::testing::Values(
make_tuple(&aom_clpf_block_hbd_neon, &aom_clpf_block_hbd_c, 8, 8),
make_tuple(&aom_clpf_hblock_hbd_neon, &aom_clpf_hblock_hbd_c, 8, 8)));
#endif
#endif // CONFIG_HIGHBITDEPTH
#endif // defined(_WIN64) || !defined(_MSC_VER)
} // namespace

View file

@ -11,7 +11,8 @@
#ifndef TEST_CODEC_FACTORY_H_
#define TEST_CODEC_FACTORY_H_
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom/aom_decoder.h"
#include "aom/aom_encoder.h"
#if CONFIG_AV1_ENCODER
@ -39,7 +40,6 @@ class CodecFactory {
const aom_codec_flags_t flags) const = 0;
virtual Encoder *CreateEncoder(aom_codec_enc_cfg_t cfg,
unsigned long deadline,
const unsigned long init_flags,
TwopassStatsStore *stats) const = 0;
@ -54,22 +54,26 @@ class CodecFactory {
template <class T1>
class CodecTestWithParam
: public ::testing::TestWithParam<
std::tr1::tuple<const libaom_test::CodecFactory *, T1> > {};
::testing::tuple<const libaom_test::CodecFactory *, T1> > {};
template <class T1, class T2>
class CodecTestWith2Params
: public ::testing::TestWithParam<
std::tr1::tuple<const libaom_test::CodecFactory *, T1, T2> > {};
::testing::tuple<const libaom_test::CodecFactory *, T1, T2> > {};
template <class T1, class T2, class T3>
class CodecTestWith3Params
: public ::testing::TestWithParam<
std::tr1::tuple<const libaom_test::CodecFactory *, T1, T2, T3> > {};
::testing::tuple<const libaom_test::CodecFactory *, T1, T2, T3> > {};
template <class T1, class T2, class T3, class T4>
class CodecTestWith4Params
: public ::testing::TestWithParam< ::testing::tuple<
const libaom_test::CodecFactory *, T1, T2, T3, T4> > {};
/*
* AV1 Codec Definitions
*/
#if CONFIG_AV1
class AV1Decoder : public Decoder {
public:
explicit AV1Decoder(aom_codec_dec_cfg_t cfg) : Decoder(cfg) {}
@ -89,9 +93,9 @@ class AV1Decoder : public Decoder {
class AV1Encoder : public Encoder {
public:
AV1Encoder(aom_codec_enc_cfg_t cfg, unsigned long deadline,
const unsigned long init_flags, TwopassStatsStore *stats)
: Encoder(cfg, deadline, init_flags, stats) {}
AV1Encoder(aom_codec_enc_cfg_t cfg, const uint32_t init_flags,
TwopassStatsStore *stats)
: Encoder(cfg, init_flags, stats) {}
protected:
virtual aom_codec_iface_t *CodecInterface() const {
@ -123,14 +127,12 @@ class AV1CodecFactory : public CodecFactory {
}
virtual Encoder *CreateEncoder(aom_codec_enc_cfg_t cfg,
unsigned long deadline,
const unsigned long init_flags,
TwopassStatsStore *stats) const {
#if CONFIG_AV1_ENCODER
return new AV1Encoder(cfg, deadline, init_flags, stats);
return new AV1Encoder(cfg, init_flags, stats);
#else
(void)cfg;
(void)deadline;
(void)init_flags;
(void)stats;
return NULL;
@ -158,9 +160,6 @@ const libaom_test::AV1CodecFactory kAV1;
::testing::Values(static_cast<const libaom_test::CodecFactory *>( \
&libaom_test::kAV1)), \
__VA_ARGS__))
#else
#define AV1_INSTANTIATE_TEST_CASE(test, ...)
#endif // CONFIG_AV1
} // namespace libaom_test
#endif // TEST_CODEC_FACTORY_H_

View file

@ -13,7 +13,7 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom_ports/mem.h" // ROUND_POWER_OF_TWO
#include "aom/aomcx.h"
@ -32,11 +32,17 @@ class CompressedSource {
aom_codec_enc_cfg_t cfg;
aom_codec_enc_config_default(algo, &cfg, 0);
const int max_q = cfg.rc_max_quantizer;
// force the quantizer, to reduce the sensitivity on encoding choices.
// e.g, we don't want this test to break when the rate control is modified.
{
const int max_q = cfg.rc_max_quantizer;
const int min_q = cfg.rc_min_quantizer;
const int q = rnd_.PseudoUniform(max_q - min_q + 1) + min_q;
cfg.rc_end_usage = AOM_CQ;
cfg.rc_max_quantizer = max_q;
cfg.rc_min_quantizer = max_q;
cfg.rc_end_usage = AOM_Q;
cfg.rc_max_quantizer = q;
cfg.rc_min_quantizer = q;
}
// choose the picture size
{
@ -44,9 +50,26 @@ class CompressedSource {
height_ = rnd_.PseudoUniform(kHeight - 8) + 8;
}
// choose the chroma subsampling
{
const aom_img_fmt_t fmts[] = {
AOM_IMG_FMT_I420,
AOM_IMG_FMT_I422,
AOM_IMG_FMT_I444,
};
format_ = fmts[rnd_.PseudoUniform(NELEMENTS(fmts))];
}
cfg.g_w = width_;
cfg.g_h = height_;
cfg.g_lag_in_frames = 0;
if (format_ == AOM_IMG_FMT_I420)
cfg.g_profile = 0;
else if (format_ == AOM_IMG_FMT_I444)
cfg.g_profile = 1;
else if (format_ == AOM_IMG_FMT_I422)
cfg.g_profile = 2;
aom_codec_enc_init(&enc_, algo, &cfg, 0);
}
@ -54,7 +77,7 @@ class CompressedSource {
~CompressedSource() { aom_codec_destroy(&enc_); }
const aom_codec_cx_pkt_t *ReadFrame() {
uint8_t buf[kWidth * kHeight * 3 / 2] = { 0 };
uint8_t buf[kWidth * kHeight * 3] = { 0 };
// render regular pattern
const int period = rnd_.Rand8() % 32 + 1;
@ -67,8 +90,8 @@ class CompressedSource {
buf[i] = (i + phase) % period < period / 2 ? val_a : val_b;
aom_image_t img;
aom_img_wrap(&img, AOM_IMG_FMT_I420, width_, height_, 0, buf);
aom_codec_encode(&enc_, &img, frame_count_++, 1, 0, 0);
aom_img_wrap(&img, format_, width_, height_, 0, buf);
aom_codec_encode(&enc_, &img, frame_count_++, 1, 0);
aom_codec_iter_t iter = NULL;
@ -86,6 +109,7 @@ class CompressedSource {
static const int kHeight = 128;
ACMRandom rnd_;
aom_img_fmt_t format_;
aom_codec_ctx_t enc_;
int frame_count_;
int width_, height_;
@ -128,7 +152,7 @@ class Decoder {
std::vector<int16_t> decode(const aom_codec_cx_pkt_t *pkt) {
aom_codec_decode(&dec_, static_cast<uint8_t *>(pkt->data.frame.buf),
static_cast<unsigned int>(pkt->data.frame.sz), NULL, 0);
pkt->data.frame.sz, NULL);
aom_codec_iter_t iter = NULL;
return Serialize(aom_codec_get_frame(&dec_, &iter));
@ -140,18 +164,41 @@ class Decoder {
// Try to reveal a mismatch between LBD and HBD coding paths.
TEST(CodingPathSync, SearchForHbdLbdMismatch) {
const int count_tests = 100;
const int count_tests = 10;
for (int i = 0; i < count_tests; ++i) {
Decoder dec_hbd(0);
Decoder dec_lbd(1);
CompressedSource enc(i);
const aom_codec_cx_pkt_t *frame = enc.ReadFrame();
std::vector<int16_t> lbd_yuv = dec_lbd.decode(frame);
std::vector<int16_t> hbd_yuv = dec_hbd.decode(frame);
for (int k = 0; k < 3; ++k) {
const aom_codec_cx_pkt_t *frame = enc.ReadFrame();
ASSERT_EQ(lbd_yuv, hbd_yuv);
std::vector<int16_t> lbd_yuv = dec_lbd.decode(frame);
std::vector<int16_t> hbd_yuv = dec_hbd.decode(frame);
ASSERT_EQ(lbd_yuv, hbd_yuv);
}
}
}
TEST(CodingPathSyncLarge, SearchForHbdLbdMismatchLarge) {
const int count_tests = 100;
const int seed = 1234;
for (int i = 0; i < count_tests; ++i) {
Decoder dec_hbd(0);
Decoder dec_lbd(1);
CompressedSource enc(seed + i);
for (int k = 0; k < 5; ++k) {
const aom_codec_cx_pkt_t *frame = enc.ReadFrame();
std::vector<int16_t> lbd_yuv = dec_lbd.decode(frame);
std::vector<int16_t> hbd_yuv = dec_hbd.decode(frame);
ASSERT_EQ(lbd_yuv, hbd_yuv);
}
}
}

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "test/comp_avg_pred_test.h"
using ::testing::make_tuple;
using ::testing::tuple;
using libaom_test::ACMRandom;
using libaom_test::AV1JNTCOMPAVG::AV1HighBDJNTCOMPAVGTest;
using libaom_test::AV1JNTCOMPAVG::AV1HighBDJNTCOMPAVGUPSAMPLEDTest;
using libaom_test::AV1JNTCOMPAVG::AV1JNTCOMPAVGTest;
using libaom_test::AV1JNTCOMPAVG::AV1JNTCOMPAVGUPSAMPLEDTest;
namespace {
TEST_P(AV1JNTCOMPAVGTest, DISABLED_Speed) { RunSpeedTest(GET_PARAM(0)); }
TEST_P(AV1JNTCOMPAVGTest, CheckOutput) { RunCheckOutput(GET_PARAM(0)); }
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, AV1JNTCOMPAVGTest,
libaom_test::AV1JNTCOMPAVG::BuildParams(aom_jnt_comp_avg_pred_ssse3));
#endif
TEST_P(AV1JNTCOMPAVGUPSAMPLEDTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(0));
}
TEST_P(AV1JNTCOMPAVGUPSAMPLEDTest, CheckOutput) {
RunCheckOutput(GET_PARAM(0));
}
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, AV1JNTCOMPAVGUPSAMPLEDTest,
libaom_test::AV1JNTCOMPAVG::BuildParams(
aom_jnt_comp_avg_upsampled_pred_ssse3));
#endif
TEST_P(AV1HighBDJNTCOMPAVGTest, DISABLED_Speed) { RunSpeedTest(GET_PARAM(1)); }
TEST_P(AV1HighBDJNTCOMPAVGTest, CheckOutput) { RunCheckOutput(GET_PARAM(1)); }
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(
SSE2, AV1HighBDJNTCOMPAVGTest,
libaom_test::AV1JNTCOMPAVG::BuildParams(aom_highbd_jnt_comp_avg_pred_sse2));
#endif
TEST_P(AV1HighBDJNTCOMPAVGUPSAMPLEDTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(1));
}
TEST_P(AV1HighBDJNTCOMPAVGUPSAMPLEDTest, CheckOutput) {
RunCheckOutput(GET_PARAM(1));
}
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, AV1HighBDJNTCOMPAVGUPSAMPLEDTest,
libaom_test::AV1JNTCOMPAVG::BuildParams(
aom_highbd_jnt_comp_avg_upsampled_pred_sse2));
#endif
} // namespace

View file

@ -0,0 +1,546 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#ifndef TEST_COMP_AVG_PRED_TEST_H_
#define TEST_COMP_AVG_PRED_TEST_H_
#include "config/aom_dsp_rtcd.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "av1/common/common_data.h"
#include "aom_ports/aom_timer.h"
namespace libaom_test {
const int kMaxSize = 128 + 32; // padding
namespace AV1JNTCOMPAVG {
typedef void (*jntcompavg_func)(uint8_t *comp_pred, const uint8_t *pred,
int width, int height, const uint8_t *ref,
int ref_stride,
const JNT_COMP_PARAMS *jcp_param);
typedef void (*jntcompavgupsampled_func)(
MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
const MV *const mv, uint8_t *comp_pred, const uint8_t *pred, int width,
int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref,
int ref_stride, const JNT_COMP_PARAMS *jcp_param);
typedef void (*highbdjntcompavg_func)(uint16_t *comp_pred, const uint8_t *pred8,
int width, int height,
const uint8_t *ref8, int ref_stride,
const JNT_COMP_PARAMS *jcp_param);
typedef void (*highbdjntcompavgupsampled_func)(
MACROBLOCKD *xd, const struct AV1Common *const cm, int mi_row, int mi_col,
const MV *const mv, uint16_t *comp_pred, const uint8_t *pred8, int width,
int height, int subpel_x_q3, int subpel_y_q3, const uint8_t *ref8,
int ref_stride, int bd, const JNT_COMP_PARAMS *jcp_param);
typedef ::testing::tuple<jntcompavg_func, BLOCK_SIZE> JNTCOMPAVGParam;
typedef ::testing::tuple<jntcompavgupsampled_func, BLOCK_SIZE>
JNTCOMPAVGUPSAMPLEDParam;
typedef ::testing::tuple<int, highbdjntcompavg_func, BLOCK_SIZE>
HighbdJNTCOMPAVGParam;
typedef ::testing::tuple<int, highbdjntcompavgupsampled_func, BLOCK_SIZE>
HighbdJNTCOMPAVGUPSAMPLEDParam;
::testing::internal::ParamGenerator<JNTCOMPAVGParam> BuildParams(
jntcompavg_func filter) {
return ::testing::Combine(::testing::Values(filter),
::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
}
::testing::internal::ParamGenerator<JNTCOMPAVGUPSAMPLEDParam> BuildParams(
jntcompavgupsampled_func filter) {
return ::testing::Combine(::testing::Values(filter),
::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
}
::testing::internal::ParamGenerator<HighbdJNTCOMPAVGParam> BuildParams(
highbdjntcompavg_func filter) {
return ::testing::Combine(::testing::Range(8, 13, 2),
::testing::Values(filter),
::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
}
::testing::internal::ParamGenerator<HighbdJNTCOMPAVGUPSAMPLEDParam> BuildParams(
highbdjntcompavgupsampled_func filter) {
return ::testing::Combine(::testing::Range(8, 13, 2),
::testing::Values(filter),
::testing::Range(BLOCK_4X4, BLOCK_SIZES_ALL));
}
class AV1JNTCOMPAVGTest : public ::testing::TestWithParam<JNTCOMPAVGParam> {
public:
~AV1JNTCOMPAVGTest() {}
void SetUp() { rnd_.Reset(ACMRandom::DeterministicSeed()); }
void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunCheckOutput(jntcompavg_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(1);
uint8_t pred8[kMaxSize * kMaxSize];
uint8_t ref8[kMaxSize * kMaxSize];
uint8_t output[kMaxSize * kMaxSize];
uint8_t output2[kMaxSize * kMaxSize];
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand8();
ref8[i * w + j] = rnd_.Rand8();
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
for (int ii = 0; ii < 2; ii++) {
for (int jj = 0; jj < 4; jj++) {
jnt_comp_params.fwd_offset = quant_dist_lookup_table[ii][jj][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[ii][jj][1];
const int offset_r = 3 + rnd_.PseudoUniform(h - in_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - in_w - 7);
aom_jnt_comp_avg_pred_c(output, pred8 + offset_r * w + offset_c, in_w,
in_h, ref8 + offset_r * w + offset_c, in_w,
&jnt_comp_params);
test_impl(output2, pred8 + offset_r * w + offset_c, in_w, in_h,
ref8 + offset_r * w + offset_c, in_w, &jnt_comp_params);
for (int i = 0; i < in_h; ++i) {
for (int j = 0; j < in_w; ++j) {
int idx = i * in_w + j;
ASSERT_EQ(output[idx], output2[idx])
<< "Mismatch at unit tests for AV1JNTCOMPAVGTest\n"
<< in_w << "x" << in_h << " Pixel mismatch at index " << idx
<< " = (" << i << ", " << j << ")";
}
}
}
}
}
void RunSpeedTest(jntcompavg_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(1);
uint8_t pred8[kMaxSize * kMaxSize];
uint8_t ref8[kMaxSize * kMaxSize];
uint8_t output[kMaxSize * kMaxSize];
uint8_t output2[kMaxSize * kMaxSize];
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand8();
ref8[i * w + j] = rnd_.Rand8();
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
jnt_comp_params.fwd_offset = quant_dist_lookup_table[0][0][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[0][0][1];
const int num_loops = 1000000000 / (in_w + in_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
aom_jnt_comp_avg_pred_c(output, pred8, in_w, in_h, ref8, in_w,
&jnt_comp_params);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("jntcompavg c_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time / num_loops);
aom_usec_timer timer1;
aom_usec_timer_start(&timer1);
for (int i = 0; i < num_loops; ++i)
test_impl(output2, pred8, in_w, in_h, ref8, in_w, &jnt_comp_params);
aom_usec_timer_mark(&timer1);
const int elapsed_time1 = static_cast<int>(aom_usec_timer_elapsed(&timer1));
printf("jntcompavg test_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time1 / num_loops);
}
libaom_test::ACMRandom rnd_;
}; // class AV1JNTCOMPAVGTest
class AV1JNTCOMPAVGUPSAMPLEDTest
: public ::testing::TestWithParam<JNTCOMPAVGUPSAMPLEDParam> {
public:
~AV1JNTCOMPAVGUPSAMPLEDTest() {}
void SetUp() { rnd_.Reset(ACMRandom::DeterministicSeed()); }
void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunCheckOutput(jntcompavgupsampled_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(1);
uint8_t pred8[kMaxSize * kMaxSize];
uint8_t ref8[kMaxSize * kMaxSize];
DECLARE_ALIGNED(16, uint8_t, output[MAX_SB_SQUARE]);
DECLARE_ALIGNED(16, uint8_t, output2[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand8();
ref8[i * w + j] = rnd_.Rand8();
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
int sub_x_q3, sub_y_q3;
for (sub_x_q3 = 0; sub_x_q3 < 8; ++sub_x_q3) {
for (sub_y_q3 = 0; sub_y_q3 < 8; ++sub_y_q3) {
for (int ii = 0; ii < 2; ii++) {
for (int jj = 0; jj < 4; jj++) {
jnt_comp_params.fwd_offset = quant_dist_lookup_table[ii][jj][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[ii][jj][1];
const int offset_r = 3 + rnd_.PseudoUniform(h - in_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - in_w - 7);
aom_jnt_comp_avg_upsampled_pred_c(
NULL, NULL, 0, 0, NULL, output, pred8 + offset_r * w + offset_c,
in_w, in_h, sub_x_q3, sub_y_q3, ref8 + offset_r * w + offset_c,
in_w, &jnt_comp_params);
test_impl(NULL, NULL, 0, 0, NULL, output2,
pred8 + offset_r * w + offset_c, in_w, in_h, sub_x_q3,
sub_y_q3, ref8 + offset_r * w + offset_c, in_w,
&jnt_comp_params);
for (int i = 0; i < in_h; ++i) {
for (int j = 0; j < in_w; ++j) {
int idx = i * in_w + j;
ASSERT_EQ(output[idx], output2[idx])
<< "Mismatch at unit tests for AV1JNTCOMPAVGUPSAMPLEDTest\n"
<< in_w << "x" << in_h << " Pixel mismatch at index " << idx
<< " = (" << i << ", " << j << "), sub pixel offset = ("
<< sub_y_q3 << ", " << sub_x_q3 << ")";
}
}
}
}
}
}
}
void RunSpeedTest(jntcompavgupsampled_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(1);
uint8_t pred8[kMaxSize * kMaxSize];
uint8_t ref8[kMaxSize * kMaxSize];
DECLARE_ALIGNED(16, uint8_t, output[MAX_SB_SQUARE]);
DECLARE_ALIGNED(16, uint8_t, output2[MAX_SB_SQUARE]);
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand8();
ref8[i * w + j] = rnd_.Rand8();
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
jnt_comp_params.fwd_offset = quant_dist_lookup_table[0][0][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[0][0][1];
int sub_x_q3 = 0;
int sub_y_q3 = 0;
const int num_loops = 1000000000 / (in_w + in_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
aom_jnt_comp_avg_upsampled_pred_c(NULL, NULL, 0, 0, NULL, output, pred8,
in_w, in_h, sub_x_q3, sub_y_q3, ref8,
in_w, &jnt_comp_params);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("jntcompavgupsampled c_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time / num_loops);
aom_usec_timer timer1;
aom_usec_timer_start(&timer1);
for (int i = 0; i < num_loops; ++i)
test_impl(NULL, NULL, 0, 0, NULL, output2, pred8, in_w, in_h, sub_x_q3,
sub_y_q3, ref8, in_w, &jnt_comp_params);
aom_usec_timer_mark(&timer1);
const int elapsed_time1 = static_cast<int>(aom_usec_timer_elapsed(&timer1));
printf("jntcompavgupsampled test_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time1 / num_loops);
}
libaom_test::ACMRandom rnd_;
}; // class AV1JNTCOMPAVGUPSAMPLEDTest
class AV1HighBDJNTCOMPAVGTest
: public ::testing::TestWithParam<HighbdJNTCOMPAVGParam> {
public:
~AV1HighBDJNTCOMPAVGTest() {}
void SetUp() { rnd_.Reset(ACMRandom::DeterministicSeed()); }
void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunCheckOutput(highbdjntcompavg_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(2);
const int bd = GET_PARAM(0);
uint16_t pred8[kMaxSize * kMaxSize];
uint16_t ref8[kMaxSize * kMaxSize];
uint16_t output[kMaxSize * kMaxSize];
uint16_t output2[kMaxSize * kMaxSize];
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
ref8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
for (int ii = 0; ii < 2; ii++) {
for (int jj = 0; jj < 4; jj++) {
jnt_comp_params.fwd_offset = quant_dist_lookup_table[ii][jj][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[ii][jj][1];
const int offset_r = 3 + rnd_.PseudoUniform(h - in_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - in_w - 7);
aom_highbd_jnt_comp_avg_pred_c(
output, CONVERT_TO_BYTEPTR(pred8) + offset_r * w + offset_c, in_w,
in_h, CONVERT_TO_BYTEPTR(ref8) + offset_r * w + offset_c, in_w,
&jnt_comp_params);
test_impl(output2, CONVERT_TO_BYTEPTR(pred8) + offset_r * w + offset_c,
in_w, in_h,
CONVERT_TO_BYTEPTR(ref8) + offset_r * w + offset_c, in_w,
&jnt_comp_params);
for (int i = 0; i < in_h; ++i) {
for (int j = 0; j < in_w; ++j) {
int idx = i * in_w + j;
ASSERT_EQ(output[idx], output2[idx])
<< "Mismatch at unit tests for AV1HighBDJNTCOMPAVGTest\n"
<< in_w << "x" << in_h << " Pixel mismatch at index " << idx
<< " = (" << i << ", " << j << ")";
}
}
}
}
}
void RunSpeedTest(highbdjntcompavg_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(2);
const int bd = GET_PARAM(0);
uint16_t pred8[kMaxSize * kMaxSize];
uint16_t ref8[kMaxSize * kMaxSize];
uint16_t output[kMaxSize * kMaxSize];
uint16_t output2[kMaxSize * kMaxSize];
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
ref8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
jnt_comp_params.fwd_offset = quant_dist_lookup_table[0][0][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[0][0][1];
const int num_loops = 1000000000 / (in_w + in_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
aom_highbd_jnt_comp_avg_pred_c(output, CONVERT_TO_BYTEPTR(pred8), in_w,
in_h, CONVERT_TO_BYTEPTR(ref8), in_w,
&jnt_comp_params);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("highbdjntcompavg c_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time / num_loops);
aom_usec_timer timer1;
aom_usec_timer_start(&timer1);
for (int i = 0; i < num_loops; ++i)
test_impl(output2, CONVERT_TO_BYTEPTR(pred8), in_w, in_h,
CONVERT_TO_BYTEPTR(ref8), in_w, &jnt_comp_params);
aom_usec_timer_mark(&timer1);
const int elapsed_time1 = static_cast<int>(aom_usec_timer_elapsed(&timer1));
printf("highbdjntcompavg test_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time1 / num_loops);
}
libaom_test::ACMRandom rnd_;
}; // class AV1HighBDJNTCOMPAVGTest
class AV1HighBDJNTCOMPAVGUPSAMPLEDTest
: public ::testing::TestWithParam<HighbdJNTCOMPAVGUPSAMPLEDParam> {
public:
~AV1HighBDJNTCOMPAVGUPSAMPLEDTest() {}
void SetUp() { rnd_.Reset(ACMRandom::DeterministicSeed()); }
void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunCheckOutput(highbdjntcompavgupsampled_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(2);
const int bd = GET_PARAM(0);
uint16_t pred8[kMaxSize * kMaxSize];
uint16_t ref8[kMaxSize * kMaxSize];
uint16_t output[kMaxSize * kMaxSize];
uint16_t output2[kMaxSize * kMaxSize];
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
ref8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
int sub_x_q3, sub_y_q3;
for (sub_x_q3 = 0; sub_x_q3 < 8; ++sub_x_q3) {
for (sub_y_q3 = 0; sub_y_q3 < 8; ++sub_y_q3) {
for (int ii = 0; ii < 2; ii++) {
for (int jj = 0; jj < 4; jj++) {
jnt_comp_params.fwd_offset = quant_dist_lookup_table[ii][jj][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[ii][jj][1];
const int offset_r = 3 + rnd_.PseudoUniform(h - in_h - 7);
const int offset_c = 3 + rnd_.PseudoUniform(w - in_w - 7);
aom_highbd_jnt_comp_avg_upsampled_pred_c(
NULL, NULL, 0, 0, NULL, output,
CONVERT_TO_BYTEPTR(pred8) + offset_r * w + offset_c, in_w, in_h,
sub_x_q3, sub_y_q3,
CONVERT_TO_BYTEPTR(ref8) + offset_r * w + offset_c, in_w, bd,
&jnt_comp_params);
test_impl(NULL, NULL, 0, 0, NULL, output2,
CONVERT_TO_BYTEPTR(pred8) + offset_r * w + offset_c, in_w,
in_h, sub_x_q3, sub_y_q3,
CONVERT_TO_BYTEPTR(ref8) + offset_r * w + offset_c, in_w,
bd, &jnt_comp_params);
for (int i = 0; i < in_h; ++i) {
for (int j = 0; j < in_w; ++j) {
int idx = i * in_w + j;
ASSERT_EQ(output[idx], output2[idx])
<< "Mismatch at unit tests for "
"AV1HighBDJNTCOMPAVGUPSAMPLEDTest\n"
<< in_w << "x" << in_h << " Pixel mismatch at index " << idx
<< " = (" << i << ", " << j << "), sub pixel offset = ("
<< sub_y_q3 << ", " << sub_x_q3 << ")";
}
}
}
}
}
}
}
void RunSpeedTest(highbdjntcompavgupsampled_func test_impl) {
const int w = kMaxSize, h = kMaxSize;
const int block_idx = GET_PARAM(2);
const int bd = GET_PARAM(0);
uint16_t pred8[kMaxSize * kMaxSize];
uint16_t ref8[kMaxSize * kMaxSize];
uint16_t output[kMaxSize * kMaxSize];
uint16_t output2[kMaxSize * kMaxSize];
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j) {
pred8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
ref8[i * w + j] = rnd_.Rand16() & ((1 << bd) - 1);
}
const int in_w = block_size_wide[block_idx];
const int in_h = block_size_high[block_idx];
JNT_COMP_PARAMS jnt_comp_params;
jnt_comp_params.use_jnt_comp_avg = 1;
jnt_comp_params.fwd_offset = quant_dist_lookup_table[0][0][0];
jnt_comp_params.bck_offset = quant_dist_lookup_table[0][0][1];
int sub_x_q3 = 0;
int sub_y_q3 = 0;
const int num_loops = 1000000000 / (in_w + in_h);
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < num_loops; ++i)
aom_highbd_jnt_comp_avg_upsampled_pred_c(
NULL, NULL, 0, 0, NULL, output, CONVERT_TO_BYTEPTR(pred8), in_w, in_h,
sub_x_q3, sub_y_q3, CONVERT_TO_BYTEPTR(ref8), in_w, bd,
&jnt_comp_params);
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("highbdjntcompavgupsampled c_code %3dx%-3d: %7.2f us\n", in_w, in_h,
1000.0 * elapsed_time / num_loops);
aom_usec_timer timer1;
aom_usec_timer_start(&timer1);
for (int i = 0; i < num_loops; ++i)
test_impl(NULL, NULL, 0, 0, NULL, output2, CONVERT_TO_BYTEPTR(pred8),
in_w, in_h, sub_x_q3, sub_y_q3, CONVERT_TO_BYTEPTR(ref8), in_w,
bd, &jnt_comp_params);
aom_usec_timer_mark(&timer1);
const int elapsed_time1 = static_cast<int>(aom_usec_timer_elapsed(&timer1));
printf("highbdjntcompavgupsampled test_code %3dx%-3d: %7.2f us\n", in_w,
in_h, 1000.0 * elapsed_time1 / num_loops);
}
libaom_test::ACMRandom rnd_;
}; // class AV1HighBDJNTCOMPAVGUPSAMPLEDTest
} // namespace AV1JNTCOMPAVG
} // namespace libaom_test
#endif // TEST_COMP_AVG_PRED_TEST_H_

View file

@ -0,0 +1,273 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <cstdlib>
#include <new>
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
#include "aom_dsp/variance.h"
#include "aom_mem/aom_mem.h"
#include "aom_ports/aom_timer.h"
#include "aom_ports/mem.h"
#include "av1/common/reconinter.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace AV1CompMaskVariance {
typedef void (*comp_mask_pred_func)(uint8_t *comp_pred, const uint8_t *pred,
int width, int height, const uint8_t *ref,
int ref_stride, const uint8_t *mask,
int mask_stride, int invert_mask);
#if HAVE_SSSE3 || HAVE_AV2
const BLOCK_SIZE kValidBlockSize[] = {
BLOCK_8X8, BLOCK_8X16, BLOCK_8X32, BLOCK_16X8, BLOCK_16X16,
BLOCK_16X32, BLOCK_32X8, BLOCK_32X16, BLOCK_32X32,
};
#endif
typedef ::testing::tuple<comp_mask_pred_func, BLOCK_SIZE> CompMaskPredParam;
class AV1CompMaskVarianceTest
: public ::testing::TestWithParam<CompMaskPredParam> {
public:
~AV1CompMaskVarianceTest();
void SetUp();
void TearDown();
protected:
void RunCheckOutput(comp_mask_pred_func test_impl, BLOCK_SIZE bsize, int inv);
void RunSpeedTest(comp_mask_pred_func test_impl, BLOCK_SIZE bsize);
bool CheckResult(int width, int height) {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
const int idx = y * width + x;
if (comp_pred1_[idx] != comp_pred2_[idx]) {
printf("%dx%d mismatch @%d(%d,%d) ", width, height, idx, y, x);
printf("%d != %d ", comp_pred1_[idx], comp_pred2_[idx]);
return false;
}
}
}
return true;
}
libaom_test::ACMRandom rnd_;
uint8_t *comp_pred1_;
uint8_t *comp_pred2_;
uint8_t *pred_;
uint8_t *ref_buffer_;
uint8_t *ref_;
};
AV1CompMaskVarianceTest::~AV1CompMaskVarianceTest() { ; }
void AV1CompMaskVarianceTest::SetUp() {
rnd_.Reset(libaom_test::ACMRandom::DeterministicSeed());
av1_init_wedge_masks();
comp_pred1_ = (uint8_t *)aom_memalign(16, MAX_SB_SQUARE);
comp_pred2_ = (uint8_t *)aom_memalign(16, MAX_SB_SQUARE);
pred_ = (uint8_t *)aom_memalign(16, MAX_SB_SQUARE);
ref_buffer_ = (uint8_t *)aom_memalign(16, MAX_SB_SQUARE + (8 * MAX_SB_SIZE));
ref_ = ref_buffer_ + (8 * MAX_SB_SIZE);
for (int i = 0; i < MAX_SB_SQUARE; ++i) {
pred_[i] = rnd_.Rand8();
}
for (int i = 0; i < MAX_SB_SQUARE + (8 * MAX_SB_SIZE); ++i) {
ref_buffer_[i] = rnd_.Rand8();
}
}
void AV1CompMaskVarianceTest::TearDown() {
aom_free(comp_pred1_);
aom_free(comp_pred2_);
aom_free(pred_);
aom_free(ref_buffer_);
libaom_test::ClearSystemState();
}
void AV1CompMaskVarianceTest::RunCheckOutput(comp_mask_pred_func test_impl,
BLOCK_SIZE bsize, int inv) {
const int w = block_size_wide[bsize];
const int h = block_size_high[bsize];
int wedge_types = (1 << get_wedge_bits_lookup(bsize));
for (int wedge_index = 0; wedge_index < wedge_types; ++wedge_index) {
const uint8_t *mask = av1_get_contiguous_soft_mask(wedge_index, 1, bsize);
aom_comp_mask_pred_c(comp_pred1_, pred_, w, h, ref_, MAX_SB_SIZE, mask, w,
inv);
test_impl(comp_pred2_, pred_, w, h, ref_, MAX_SB_SIZE, mask, w, inv);
ASSERT_EQ(CheckResult(w, h), true)
<< " wedge " << wedge_index << " inv " << inv;
}
}
void AV1CompMaskVarianceTest::RunSpeedTest(comp_mask_pred_func test_impl,
BLOCK_SIZE bsize) {
const int w = block_size_wide[bsize];
const int h = block_size_high[bsize];
int wedge_types = (1 << get_wedge_bits_lookup(bsize));
int wedge_index = wedge_types / 2;
const uint8_t *mask = av1_get_contiguous_soft_mask(wedge_index, 1, bsize);
const int num_loops = 1000000000 / (w + h);
comp_mask_pred_func funcs[2] = { aom_comp_mask_pred_c, test_impl };
double elapsed_time[2] = { 0 };
for (int i = 0; i < 2; ++i) {
aom_usec_timer timer;
aom_usec_timer_start(&timer);
comp_mask_pred_func func = funcs[i];
for (int j = 0; j < num_loops; ++j) {
func(comp_pred1_, pred_, w, h, ref_, MAX_SB_SIZE, mask, w, 0);
}
aom_usec_timer_mark(&timer);
double time = static_cast<double>(aom_usec_timer_elapsed(&timer));
elapsed_time[i] = 1000.0 * time / num_loops;
}
printf("compMask %3dx%-3d: %7.2f/%7.2fns", w, h, elapsed_time[0],
elapsed_time[1]);
printf("(%3.2f)\n", elapsed_time[0] / elapsed_time[1]);
}
TEST_P(AV1CompMaskVarianceTest, CheckOutput) {
// inv = 0, 1
RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 0);
RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 1);
}
TEST_P(AV1CompMaskVarianceTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(0), GET_PARAM(1));
}
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, AV1CompMaskVarianceTest,
::testing::Combine(::testing::Values(&aom_comp_mask_pred_ssse3),
::testing::ValuesIn(kValidBlockSize)));
#endif
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(
AVX2, AV1CompMaskVarianceTest,
::testing::Combine(::testing::Values(&aom_comp_mask_pred_avx2),
::testing::ValuesIn(kValidBlockSize)));
#endif
#ifndef aom_comp_mask_pred
// can't run this test if aom_comp_mask_pred is defined to aom_comp_mask_pred_c
class AV1CompMaskUpVarianceTest : public AV1CompMaskVarianceTest {
public:
~AV1CompMaskUpVarianceTest();
protected:
void RunCheckOutput(comp_mask_pred_func test_impl, BLOCK_SIZE bsize, int inv);
void RunSpeedTest(comp_mask_pred_func test_impl, BLOCK_SIZE bsize,
int havSub);
};
AV1CompMaskUpVarianceTest::~AV1CompMaskUpVarianceTest() { ; }
void AV1CompMaskUpVarianceTest::RunCheckOutput(comp_mask_pred_func test_impl,
BLOCK_SIZE bsize, int inv) {
const int w = block_size_wide[bsize];
const int h = block_size_high[bsize];
int wedge_types = (1 << get_wedge_bits_lookup(bsize));
// loop through subx and suby
for (int sub = 0; sub < 8 * 8; ++sub) {
int subx = sub & 0x7;
int suby = (sub >> 3);
for (int wedge_index = 0; wedge_index < wedge_types; ++wedge_index) {
const uint8_t *mask = av1_get_contiguous_soft_mask(wedge_index, 1, bsize);
aom_comp_mask_pred = aom_comp_mask_pred_c; // ref
aom_comp_mask_upsampled_pred(NULL, NULL, 0, 0, NULL, comp_pred1_, pred_,
w, h, subx, suby, ref_, MAX_SB_SIZE, mask, w,
inv);
aom_comp_mask_pred = test_impl; // test
aom_comp_mask_upsampled_pred(NULL, NULL, 0, 0, NULL, comp_pred2_, pred_,
w, h, subx, suby, ref_, MAX_SB_SIZE, mask, w,
inv);
ASSERT_EQ(CheckResult(w, h), true)
<< " wedge " << wedge_index << " inv " << inv << "sub (" << subx
<< "," << suby << ")";
}
}
}
void AV1CompMaskUpVarianceTest::RunSpeedTest(comp_mask_pred_func test_impl,
BLOCK_SIZE bsize, int havSub) {
const int w = block_size_wide[bsize];
const int h = block_size_high[bsize];
const int subx = havSub ? 3 : 0;
const int suby = havSub ? 4 : 0;
int wedge_types = (1 << get_wedge_bits_lookup(bsize));
int wedge_index = wedge_types / 2;
const uint8_t *mask = av1_get_contiguous_soft_mask(wedge_index, 1, bsize);
const int num_loops = 1000000000 / (w + h);
comp_mask_pred_func funcs[2] = { &aom_comp_mask_pred_c, test_impl };
double elapsed_time[2] = { 0 };
for (int i = 0; i < 2; ++i) {
aom_usec_timer timer;
aom_usec_timer_start(&timer);
aom_comp_mask_pred = funcs[i];
for (int j = 0; j < num_loops; ++j) {
aom_comp_mask_upsampled_pred(NULL, NULL, 0, 0, NULL, comp_pred1_, pred_,
w, h, subx, suby, ref_, MAX_SB_SIZE, mask, w,
0);
}
aom_usec_timer_mark(&timer);
double time = static_cast<double>(aom_usec_timer_elapsed(&timer));
elapsed_time[i] = 1000.0 * time / num_loops;
}
printf("CompMaskUp[%d] %3dx%-3d:%7.2f/%7.2fns", havSub, w, h, elapsed_time[0],
elapsed_time[1]);
printf("(%3.2f)\n", elapsed_time[0] / elapsed_time[1]);
}
TEST_P(AV1CompMaskUpVarianceTest, CheckOutput) {
// inv mask = 0, 1
RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 0);
RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 1);
}
TEST_P(AV1CompMaskUpVarianceTest, DISABLED_Speed) {
RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 1);
}
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(
SSSE3, AV1CompMaskUpVarianceTest,
::testing::Combine(::testing::Values(&aom_comp_mask_pred_ssse3),
::testing::ValuesIn(kValidBlockSize)));
#endif
#if HAVE_AVX2
INSTANTIATE_TEST_CASE_P(
AVX2, AV1CompMaskUpVarianceTest,
::testing::Combine(::testing::Values(&aom_comp_mask_pred_avx2),
::testing::ValuesIn(kValidBlockSize)));
#endif
#endif // ifndef aom_comp_mask_pred
} // namespace AV1CompMaskVariance

View file

@ -11,7 +11,8 @@
#include <assert.h>
#include "./av1_rtcd.h"
#include "config/av1_rtcd.h"
#include "aom/aom_integer.h"
#include "aom_ports/aom_timer.h"
#include "test/acm_random.h"
@ -51,7 +52,7 @@ void highbd_convolve_rounding_12(CONVOLVE_ROUNDING_PARAM) {
typedef enum { LOWBITDEPTH_TEST, HIGHBITDEPTH_TEST } DataPathType;
using std::tr1::tuple;
using ::testing::tuple;
typedef tuple<ConvolveRoundFunc, ConvolveRoundFunc, DataPathType>
ConvolveRoundParam;
@ -92,11 +93,9 @@ class ConvolveRoundTest : public ::testing::TestWithParam<ConvolveRoundParam> {
if (data_path_ == LOWBITDEPTH_TEST) {
dst = reinterpret_cast<uint8_t *>(dst_);
dst_ref = reinterpret_cast<uint8_t *>(dst_ref_);
#if CONFIG_HIGHBITDEPTH
} else if (data_path_ == HIGHBITDEPTH_TEST) {
dst = CONVERT_TO_BYTEPTR(dst_);
dst_ref = CONVERT_TO_BYTEPTR(dst_ref_);
#endif
} else {
assert(0);
}
@ -163,10 +162,8 @@ class ConvolveRoundTest : public ::testing::TestWithParam<ConvolveRoundParam> {
TEST_P(ConvolveRoundTest, BitExactCheck) { ConvolveRoundingRun(); }
using std::tr1::make_tuple;
using ::testing::make_tuple;
#if HAVE_AVX2
#if CONFIG_HIGHBITDEPTH
const ConvolveRoundParam kConvRndParamArray[] = {
make_tuple(&av1_convolve_rounding_c, &av1_convolve_rounding_avx2,
LOWBITDEPTH_TEST),
@ -180,11 +177,6 @@ const ConvolveRoundParam kConvRndParamArray[] = {
&highbd_convolve_rounding_12<av1_highbd_convolve_rounding_avx2>,
HIGHBITDEPTH_TEST)
};
#else
const ConvolveRoundParam kConvRndParamArray[] = { make_tuple(
&av1_convolve_rounding_c, &av1_convolve_rounding_avx2, LOWBITDEPTH_TEST) };
#endif
INSTANTIATE_TEST_CASE_P(AVX2, ConvolveRoundTest,
::testing::ValuesIn(kConvRndParamArray));
#endif // HAVE_AVX2

File diff suppressed because it is too large Load diff

View file

@ -8,11 +8,11 @@
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "config/av1_rtcd.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/acm_random.h"
#include "test/util.h"
#include "./av1_rtcd.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
@ -24,8 +24,8 @@ namespace AV1CornerMatch {
using libaom_test::ACMRandom;
using std::tr1::tuple;
using std::tr1::make_tuple;
using ::testing::make_tuple;
using ::testing::tuple;
typedef tuple<int> CornerMatchParam;
class AV1CornerMatchTest : public ::testing::TestWithParam<CornerMatchParam> {

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"

View file

@ -7,9 +7,10 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "config/aom_config.h"
#include "./aom_config.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
@ -215,6 +216,7 @@ TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
cfg_.rc_end_usage = AOM_CBR;
cfg_.rc_target_bitrate = 200;
cfg_.g_lag_in_frames = 0;
cfg_.g_error_resilient = 1;
// TODO(marpan): Investigate datarate target failures with a smaller keyframe
// interval (128).
cfg_.kf_max_dist = 9999;

View file

@ -1,888 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_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 "av1/common/entropy.h"
#include "av1/common/scan.h"
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
#include "aom_ports/mem.h"
#include "aom_ports/msvc.h" // for round()
using libaom_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,
TxfmParam *txfm_param);
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
typedef std::tr1::tuple<FdctFunc, IdctFunc, TX_TYPE, aom_bit_depth_t>
Dct16x16Param;
typedef std::tr1::tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t>
Ht16x16Param;
typedef std::tr1::tuple<IdctFunc, IdctFunc, TX_TYPE, aom_bit_depth_t>
Idct16x16Param;
void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam * /*txfm_param*/) {
aom_fdct16x16_c(in, out, stride);
}
void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
const TxfmParam * /*txfm_param*/) {
aom_idct16x16_256_add_c(in, dest, stride);
}
void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht16x16_c(in, out, stride, txfm_param);
}
void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
const TxfmParam *txfm_param) {
av1_iht16x16_256_add_c(in, dest, stride, txfm_param);
}
#if CONFIG_HIGHBITDEPTH
void fht16x16_10(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fwd_txfm2d_16x16_c(in, out, stride, txfm_param->tx_type, 10);
}
void fht16x16_12(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fwd_txfm2d_16x16_c(in, out, stride, txfm_param->tx_type, 12);
}
void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_inv_txfm2d_add_16x16_c(in, CONVERT_TO_SHORTPTR(out), stride,
txfm_param->tx_type, 10);
}
void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_inv_txfm2d_add_16x16_c(in, CONVERT_TO_SHORTPTR(out), stride,
txfm_param->tx_type, 12);
}
#endif // CONFIG_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_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_ == AOM_BITS_8) {
src[j] = rnd.Rand8();
dst[j] = rnd.Rand8();
test_input_block[j] = src[j] - dst[j];
#if CONFIG_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_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int32_t diff =
bit_depth_ == AOM_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_, &txfm_param_);
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_, &txfm_param_);
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_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_, &txfm_param_);
// clear reconstructed pixel buffers
memset(dst, 0, kNumCoeffs * sizeof(uint8_t));
memset(ref, 0, kNumCoeffs * sizeof(uint8_t));
#if CONFIG_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_ == AOM_BITS_8) {
inv_txfm_ref(output_ref_block, ref, pitch_, &txfm_param_);
ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_));
#if CONFIG_HIGHBITDEPTH
} else {
inv_txfm_ref(output_ref_block, CONVERT_TO_BYTEPTR(ref16), pitch_,
&txfm_param_);
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(output_ref_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
}
if (bit_depth_ == AOM_BITS_8) {
for (int j = 0; j < kNumCoeffs; ++j) EXPECT_EQ(ref[j], dst[j]);
#if CONFIG_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_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
#endif // CONFIG_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_ == AOM_BITS_8) {
src[j] = rnd.Rand8();
dst[j] = rnd.Rand8();
in[j] = src[j] - dst[j];
#if CONFIG_HIGHBITDEPTH
} else {
src16[j] = rnd.Rand16() & mask_;
dst16[j] = rnd.Rand16() & mask_;
in[j] = src16[j] - dst16[j];
#endif // CONFIG_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_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), 16));
#endif // CONFIG_HIGHBITDEPTH
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
#else
const int diff = dst[j] - src[j];
#endif // CONFIG_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 = av1_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_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
#endif // CONFIG_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_ == AOM_BITS_8) {
dst[j] = 0;
ref[j] = 0;
#if CONFIG_HIGHBITDEPTH
} else {
dst16[j] = 0;
ref16[j] = 0;
#endif // CONFIG_HIGHBITDEPTH
}
}
if (bit_depth_ == AOM_BITS_8) {
ref_txfm(coeff, ref, pitch_);
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
} else {
#if CONFIG_HIGHBITDEPTH
ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif // CONFIG_HIGHBITDEPTH
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
#else
const int diff = dst[j] - ref[j];
#endif // CONFIG_HIGHBITDEPTH
const uint32_t error = diff * diff;
EXPECT_EQ(0u, error) << "Error: 16x16 IDCT Comparison has error "
<< error << " at index " << j;
}
}
}
int pitch_;
aom_bit_depth_t bit_depth_;
int mask_;
FhtFunc fwd_txfm_ref;
IhtFunc inv_txfm_ref;
TxfmParam txfm_param_;
};
class Trans16x16DCT : public Trans16x16TestBase,
public ::testing::TestWithParam<Dct16x16Param> {
public:
virtual ~Trans16x16DCT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
bit_depth_ = GET_PARAM(3);
pitch_ = 16;
fwd_txfm_ref = fdct16x16_ref;
inv_txfm_ref = idct16x16_ref;
mask_ = (1 << bit_depth_) - 1;
inv_txfm_ref = idct16x16_ref;
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_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);
bit_depth_ = GET_PARAM(3);
pitch_ = 16;
mask_ = (1 << bit_depth_) - 1;
txfm_param_.tx_type = GET_PARAM(2);
#if CONFIG_HIGHBITDEPTH
switch (bit_depth_) {
case AOM_BITS_10:
fwd_txfm_ref = fht16x16_10;
inv_txfm_ref = iht16x16_10;
break;
case AOM_BITS_12:
fwd_txfm_ref = fht16x16_12;
inv_txfm_ref = iht16x16_12;
break;
default:
fwd_txfm_ref = fht16x16_ref;
inv_txfm_ref = iht16x16_ref;
break;
}
#else
fwd_txfm_ref = fht16x16_ref;
inv_txfm_ref = iht16x16_ref;
#endif
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
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() { libaom_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_);
}
class PartialTrans16x16Test : public ::testing::TestWithParam<
std::tr1::tuple<FdctFunc, aom_bit_depth_t> > {
public:
virtual ~PartialTrans16x16Test() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
bit_depth_ = GET_PARAM(1);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
aom_bit_depth_t bit_depth_;
FdctFunc fwd_txfm_;
};
TEST_P(PartialTrans16x16Test, Extremes) {
#if CONFIG_HIGHBITDEPTH
const int16_t maxval =
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
#else
const int16_t maxval = 255;
#endif
const int minval = -maxval;
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval;
output[0] = 0;
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
EXPECT_EQ((maxval * kNumCoeffs) >> 1, output[0]);
for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval;
output[0] = 0;
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
EXPECT_EQ((minval * kNumCoeffs) >> 1, output[0]);
}
TEST_P(PartialTrans16x16Test, Random) {
#if CONFIG_HIGHBITDEPTH
const int16_t maxval =
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
#else
const int16_t maxval = 255;
#endif
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
ACMRandom rnd(ACMRandom::DeterministicSeed());
int sum = 0;
for (int i = 0; i < kNumCoeffs; ++i) {
const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1);
input[i] = val;
sum += val;
}
output[0] = 0;
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
EXPECT_EQ(sum >> 1, output[0]);
}
using std::tr1::make_tuple;
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(C, Trans16x16DCT,
::testing::Values(make_tuple(&aom_fdct16x16_c,
&aom_idct16x16_256_add_c,
DCT_DCT, AOM_BITS_8)));
#else
INSTANTIATE_TEST_CASE_P(C, Trans16x16DCT,
::testing::Values(make_tuple(&aom_fdct16x16_c,
&aom_idct16x16_256_add_c,
DCT_DCT, AOM_BITS_8)));
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
C, Trans16x16HT,
::testing::Values(
make_tuple(&fht16x16_10, &iht16x16_10, DCT_DCT, AOM_BITS_10),
make_tuple(&fht16x16_10, &iht16x16_10, ADST_DCT, AOM_BITS_10),
make_tuple(&fht16x16_10, &iht16x16_10, DCT_ADST, AOM_BITS_10),
make_tuple(&fht16x16_10, &iht16x16_10, ADST_ADST, AOM_BITS_10),
make_tuple(&fht16x16_12, &iht16x16_12, DCT_DCT, AOM_BITS_12),
make_tuple(&fht16x16_12, &iht16x16_12, ADST_DCT, AOM_BITS_12),
make_tuple(&fht16x16_12, &iht16x16_12, DCT_ADST, AOM_BITS_12),
make_tuple(&fht16x16_12, &iht16x16_12, ADST_ADST, AOM_BITS_12),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c, DCT_DCT,
AOM_BITS_8),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c, ADST_DCT,
AOM_BITS_8),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c, DCT_ADST,
AOM_BITS_8),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c, ADST_ADST,
AOM_BITS_8)));
#else
INSTANTIATE_TEST_CASE_P(
C, Trans16x16HT,
::testing::Values(make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht16x16_c, &av1_iht16x16_256_add_c,
ADST_ADST, AOM_BITS_8)));
#endif // CONFIG_HIGHBITDEPTH
#if HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
NEON, Trans16x16DCT,
::testing::Values(make_tuple(&aom_fdct16x16_c, &aom_idct16x16_256_add_neon,
DCT_DCT, AOM_BITS_8)));
#endif
#if HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(SSE2, Trans16x16DCT,
::testing::Values(make_tuple(
&aom_fdct16x16_sse2, &aom_idct16x16_256_add_sse2,
DCT_DCT, AOM_BITS_8)));
#if !CONFIG_DAALA_DCT16
INSTANTIATE_TEST_CASE_P(
SSE2, Trans16x16HT,
::testing::Values(make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_sse2,
ADST_ADST, AOM_BITS_8)));
#endif // CONFIG_DAALA_DCT16
#endif // HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(SSE2, Trans16x16DCT,
::testing::Values(make_tuple(&aom_fdct16x16_sse2,
&aom_idct16x16_256_add_c,
DCT_DCT, AOM_BITS_8)));
#if !CONFIG_DAALA_DCT16
INSTANTIATE_TEST_CASE_P(
SSE2, Trans16x16HT,
::testing::Values(make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_c,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_c,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_c,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht16x16_sse2, &av1_iht16x16_256_add_c,
ADST_ADST, AOM_BITS_8)));
#endif
#endif // HAVE_SSE2 && CONFIG_HIGHBITDEPTH
#if HAVE_MSA && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(MSA, Trans16x16DCT,
::testing::Values(make_tuple(&aom_fdct16x16_msa,
&aom_idct16x16_256_add_msa,
DCT_DCT, AOM_BITS_8)));
#if !CONFIG_EXT_TX && !CONFIG_DAALA_DCT16
// TODO(yaowu): re-enable this after msa versions are updated to match C.
INSTANTIATE_TEST_CASE_P(
DISABLED_MSA, Trans16x16HT,
::testing::Values(make_tuple(&av1_fht16x16_msa, &av1_iht16x16_256_add_msa,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_msa, &av1_iht16x16_256_add_msa,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht16x16_msa, &av1_iht16x16_256_add_msa,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht16x16_msa, &av1_iht16x16_256_add_msa,
ADST_ADST, AOM_BITS_8)));
#endif // !CONFIG_EXT_TX && !CONFIG_DAALA_DCT16
#endif // HAVE_MSA && !CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -1,425 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_config.h"
#include "./aom_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 "av1/common/entropy.h"
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
#include "aom_ports/mem.h"
#include "aom_ports/msvc.h" // for round()
using libaom_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::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, int, aom_bit_depth_t>
Trans32x32Param;
class Trans32x32Test : 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() { libaom_test::ClearSystemState(); }
protected:
int version_;
aom_bit_depth_t bit_depth_;
int mask_;
FwdTxfmFunc fwd_txfm_;
InvTxfmFunc inv_txfm_;
};
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_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_ == AOM_BITS_8) {
src[j] = rnd.Rand8();
dst[j] = rnd.Rand8();
test_input_block[j] = src[j] - dst[j];
#if CONFIG_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_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(
inv_txfm_(test_temp_block, CONVERT_TO_BYTEPTR(dst16), 32));
#endif
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int32_t diff =
bit_depth_ == AOM_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;
aom_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;
aom_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, 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_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_ == AOM_BITS_8) {
src[j] = rnd.Rand8();
dst[j] = rnd.Rand8();
in[j] = src[j] - dst[j];
#if CONFIG_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_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CONVERT_TO_BYTEPTR(dst16), 32));
#endif
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
#else
const int diff = dst[j] - src[j];
#endif
const int error = diff * diff;
EXPECT_GE(1, error) << "Error: 32x32 IDCT has error " << error
<< " at index " << j;
}
}
}
class PartialTrans32x32Test
: public ::testing::TestWithParam<
std::tr1::tuple<FwdTxfmFunc, aom_bit_depth_t> > {
public:
virtual ~PartialTrans32x32Test() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
bit_depth_ = GET_PARAM(1);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
aom_bit_depth_t bit_depth_;
FwdTxfmFunc fwd_txfm_;
};
TEST_P(PartialTrans32x32Test, Extremes) {
#if CONFIG_HIGHBITDEPTH
const int16_t maxval =
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
#else
const int16_t maxval = 255;
#endif
const int minval = -maxval;
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval;
output[0] = 0;
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
EXPECT_EQ((maxval * kNumCoeffs) >> 3, output[0]);
for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval;
output[0] = 0;
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
EXPECT_EQ((minval * kNumCoeffs) >> 3, output[0]);
}
TEST_P(PartialTrans32x32Test, Random) {
#if CONFIG_HIGHBITDEPTH
const int16_t maxval =
static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
#else
const int16_t maxval = 255;
#endif
DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
ACMRandom rnd(ACMRandom::DeterministicSeed());
int sum = 0;
for (int i = 0; i < kNumCoeffs; ++i) {
const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1);
input[i] = val;
sum += val;
}
output[0] = 0;
ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
EXPECT_EQ(sum >> 3, output[0]);
}
using std::tr1::make_tuple;
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
C, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_c, &aom_idct32x32_1024_add_c, 0,
AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_c, &aom_idct32x32_1024_add_c,
1, AOM_BITS_8)));
#else
INSTANTIATE_TEST_CASE_P(
C, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_c, &aom_idct32x32_1024_add_c, 0,
AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_c, &aom_idct32x32_1024_add_c,
1, AOM_BITS_8)));
#endif // CONFIG_HIGHBITDEPTH
#if HAVE_NEON && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
NEON, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_c, &aom_idct32x32_1024_add_neon,
DCT_DCT, AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_c,
&aom_idct32x32_1024_add_neon, ADST_DCT,
AOM_BITS_8)));
#endif // HAVE_NEON && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
SSE2, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_sse2,
&aom_idct32x32_1024_add_sse2, DCT_DCT,
AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_sse2,
&aom_idct32x32_1024_add_sse2, ADST_DCT,
AOM_BITS_8)));
#endif // HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(SSE2, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_sse2,
&aom_idct32x32_1024_add_c,
DCT_DCT, AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_sse2,
&aom_idct32x32_1024_add_c,
ADST_DCT, AOM_BITS_8)));
#endif // HAVE_SSE2 && CONFIG_HIGHBITDEPTH
#if HAVE_AVX2 && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
AVX2, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_avx2,
&aom_idct32x32_1024_add_sse2, DCT_DCT,
AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_avx2,
&aom_idct32x32_1024_add_sse2, ADST_DCT,
AOM_BITS_8)));
#endif // HAVE_AVX2 && !CONFIG_HIGHBITDEPTH
#if HAVE_AVX2 && CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
AVX2, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_avx2,
&aom_idct32x32_1024_add_sse2, DCT_DCT,
AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_avx2,
&aom_idct32x32_1024_add_sse2, ADST_DCT,
AOM_BITS_8)));
#endif // HAVE_AVX2 && CONFIG_HIGHBITDEPTH
#if HAVE_MSA && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
MSA, Trans32x32Test,
::testing::Values(make_tuple(&aom_fdct32x32_msa,
&aom_idct32x32_1024_add_msa, DCT_DCT,
AOM_BITS_8),
make_tuple(&aom_fdct32x32_rd_msa,
&aom_idct32x32_1024_add_msa, ADST_DCT,
AOM_BITS_8)));
#endif // HAVE_MSA && !CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -7,12 +7,12 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "test/ivf_video_source.h"
#include "config/aom_config.h"
#include "test/util.h"
#include "aom/aomdx.h"
#include "aom/aom_decoder.h"
@ -30,12 +30,12 @@ TEST(DecodeAPI, InvalidParams) {
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_dec_init(NULL, NULL, NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_dec_init(&dec, NULL, NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_decode(NULL, NULL, 0, NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_decode(NULL, buf, 0, NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_decode(NULL, NULL, 0, NULL));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_decode(NULL, buf, 0, NULL));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM,
aom_codec_decode(NULL, buf, NELEMENTS(buf), NULL, 0));
aom_codec_decode(NULL, buf, NELEMENTS(buf), NULL));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM,
aom_codec_decode(NULL, NULL, NELEMENTS(buf), NULL, 0));
aom_codec_decode(NULL, NULL, NELEMENTS(buf), NULL));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_destroy(NULL));
EXPECT_TRUE(aom_codec_error(NULL) != NULL);
@ -44,14 +44,9 @@ TEST(DecodeAPI, InvalidParams) {
aom_codec_dec_init(NULL, kCodecs[i], NULL, 0));
EXPECT_EQ(AOM_CODEC_OK, aom_codec_dec_init(&dec, kCodecs[i], NULL, 0));
#if !CONFIG_OBU
// Needs to be fixed
EXPECT_EQ(AOM_CODEC_UNSUP_BITSTREAM,
aom_codec_decode(&dec, buf, NELEMENTS(buf), NULL, 0));
#endif
EXPECT_EQ(AOM_CODEC_INVALID_PARAM,
aom_codec_decode(&dec, NULL, NELEMENTS(buf), NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_decode(&dec, buf, 0, NULL, 0));
aom_codec_decode(&dec, NULL, NELEMENTS(buf), NULL));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_decode(&dec, buf, 0, NULL));
EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&dec));
}

View file

@ -0,0 +1,179 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <cstdio>
#include <cstdlib>
#include <string>
#include "aom_mem/aom_mem.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"
#include "test/md5_helper.h"
#include "test/util.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace {
static const int kNumMultiThreadDecoders = 3;
class AV1DecodeMultiThreadedTest
: public ::libaom_test::CodecTestWith4Params<int, int, int, int>,
public ::libaom_test::EncoderTest {
protected:
AV1DecodeMultiThreadedTest()
: EncoderTest(GET_PARAM(0)), md5_single_thread_(), md5_multi_thread_(),
n_tile_cols_(GET_PARAM(1)), n_tile_rows_(GET_PARAM(2)),
n_tile_groups_(GET_PARAM(3)), set_cpu_used_(GET_PARAM(4)) {
init_flags_ = AOM_CODEC_USE_PSNR;
aom_codec_dec_cfg_t cfg = aom_codec_dec_cfg_t();
cfg.w = 704;
cfg.h = 576;
cfg.threads = 1;
cfg.allow_lowbitdepth = 1;
single_thread_dec_ = codec_->CreateDecoder(cfg, 0);
// Test cfg.threads == powers of 2.
for (int i = 0; i < kNumMultiThreadDecoders; ++i) {
cfg.threads <<= 1;
multi_thread_dec_[i] = codec_->CreateDecoder(cfg, 0);
}
if (single_thread_dec_->IsAV1()) {
single_thread_dec_->Control(AV1_SET_DECODE_TILE_ROW, -1);
single_thread_dec_->Control(AV1_SET_DECODE_TILE_COL, -1);
}
for (int i = 0; i < kNumMultiThreadDecoders; ++i) {
if (multi_thread_dec_[i]->IsAV1()) {
multi_thread_dec_[i]->Control(AV1_SET_DECODE_TILE_ROW, -1);
multi_thread_dec_[i]->Control(AV1_SET_DECODE_TILE_COL, -1);
}
}
}
virtual ~AV1DecodeMultiThreadedTest() {
delete single_thread_dec_;
for (int i = 0; i < kNumMultiThreadDecoders; ++i)
delete multi_thread_dec_[i];
}
virtual void SetUp() {
InitializeConfig();
SetMode(libaom_test::kTwoPassGood);
}
virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
libaom_test::Encoder *encoder) {
if (video->frame() == 1) {
encoder->Control(AV1E_SET_TILE_COLUMNS, n_tile_cols_);
encoder->Control(AV1E_SET_TILE_ROWS, n_tile_rows_);
encoder->Control(AV1E_SET_NUM_TG, n_tile_groups_);
encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
}
}
void UpdateMD5(::libaom_test::Decoder *dec, const aom_codec_cx_pkt_t *pkt,
::libaom_test::MD5 *md5) {
const aom_codec_err_t res = dec->DecodeFrame(
reinterpret_cast<uint8_t *>(pkt->data.frame.buf), pkt->data.frame.sz);
if (res != AOM_CODEC_OK) {
abort_ = true;
ASSERT_EQ(AOM_CODEC_OK, res);
}
const aom_image_t *img = dec->GetDxData().Next();
md5->Add(img);
}
virtual void FramePktHook(const aom_codec_cx_pkt_t *pkt) {
UpdateMD5(single_thread_dec_, pkt, &md5_single_thread_);
for (int i = 0; i < kNumMultiThreadDecoders; ++i)
UpdateMD5(multi_thread_dec_[i], pkt, &md5_multi_thread_[i]);
}
void DoTest() {
const aom_rational timebase = { 33333333, 1000000000 };
cfg_.g_timebase = timebase;
cfg_.rc_target_bitrate = 500;
cfg_.g_lag_in_frames = 12;
cfg_.rc_end_usage = AOM_VBR;
libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 704, 576,
timebase.den, timebase.num, 0, 5);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
const char *md5_single_thread_str = md5_single_thread_.Get();
for (int i = 0; i < kNumMultiThreadDecoders; ++i) {
const char *md5_multi_thread_str = md5_multi_thread_[i].Get();
ASSERT_STREQ(md5_single_thread_str, md5_multi_thread_str);
}
}
::libaom_test::MD5 md5_single_thread_;
::libaom_test::MD5 md5_multi_thread_[kNumMultiThreadDecoders];
::libaom_test::Decoder *single_thread_dec_;
::libaom_test::Decoder *multi_thread_dec_[kNumMultiThreadDecoders];
private:
int n_tile_cols_;
int n_tile_rows_;
int n_tile_groups_;
int set_cpu_used_;
};
// run an encode and do the decode both in single thread
// and multi thread. Ensure that the MD5 of the output in both cases
// is identical. If so, the test passes.
TEST_P(AV1DecodeMultiThreadedTest, MD5Match) {
cfg_.large_scale_tile = 0;
single_thread_dec_->Control(AV1_SET_TILE_MODE, 0);
for (int i = 0; i < kNumMultiThreadDecoders; ++i)
multi_thread_dec_[i]->Control(AV1_SET_TILE_MODE, 0);
DoTest();
}
class AV1DecodeMultiThreadedTestLarge : public AV1DecodeMultiThreadedTest {};
TEST_P(AV1DecodeMultiThreadedTestLarge, MD5Match) {
cfg_.large_scale_tile = 0;
single_thread_dec_->Control(AV1_SET_TILE_MODE, 0);
for (int i = 0; i < kNumMultiThreadDecoders; ++i)
multi_thread_dec_[i]->Control(AV1_SET_TILE_MODE, 0);
DoTest();
}
// TODO(ranjit): More tests have to be added using pre-generated MD5.
AV1_INSTANTIATE_TEST_CASE(AV1DecodeMultiThreadedTest, ::testing::Values(1, 2),
::testing::Values(1, 2), ::testing::Values(1),
::testing::Values(3));
AV1_INSTANTIATE_TEST_CASE(AV1DecodeMultiThreadedTestLarge,
::testing::Values(0, 1, 2, 6),
::testing::Values(0, 1, 2, 6),
::testing::Values(1, 4), ::testing::Values(0));
class AV1DecodeMultiThreadedLSTestLarge
: public AV1DecodeMultiThreadedTestLarge {};
TEST_P(AV1DecodeMultiThreadedLSTestLarge, DISABLED_MD5Match) {
cfg_.large_scale_tile = 1;
single_thread_dec_->Control(AV1_SET_TILE_MODE, 1);
for (int i = 0; i < kNumMultiThreadDecoders; ++i)
multi_thread_dec_[i]->Control(AV1_SET_TILE_MODE, 1);
DoTest();
}
AV1_INSTANTIATE_TEST_CASE(AV1DecodeMultiThreadedLSTestLarge,
::testing::Values(1, 2, 32),
::testing::Values(1, 2, 32), ::testing::Values(1),
::testing::Values(0, 3));
} // namespace

View file

@ -7,9 +7,14 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <string>
#include "config/aom_version.h"
#include "aom_ports/aom_timer.h"
#include "common/ivfenc.h"
#include "test/codec_factory.h"
#include "test/decode_test_driver.h"
#include "test/encode_test_driver.h"
@ -18,25 +23,21 @@
#include "test/md5_helper.h"
#include "test/util.h"
#include "test/webm_video_source.h"
#include "aom_ports/aom_timer.h"
#include "./ivfenc.h"
#include "./aom_version.h"
using std::tr1::make_tuple;
using ::testing::make_tuple;
namespace {
#define VIDEO_NAME 0
#define THREADS 1
const int kMaxPsnr = 100;
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::tr1::tuple<const char *, unsigned> DecodePerfParam;
typedef ::testing::tuple<const char *, unsigned> DecodePerfParam;
// TODO(jimbankoski): Add actual test vectors here when available.
// const DecodePerfParam kAV1DecodePerfVectors[] = {};
@ -129,7 +130,8 @@ class AV1NewEncodeDecodePerfTest
}
virtual void BeginPassHook(unsigned int /*pass*/) {
const std::string data_path = getenv("LIBAOM_TEST_DATA_PATH");
const char *const env = getenv("LIBAOM_TEST_DATA_PATH");
const std::string data_path(env ? env : ".");
const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile;
outfile_ = fopen(path_to_source.c_str(), "wb");
ASSERT_TRUE(outfile_ != NULL);
@ -157,7 +159,7 @@ class AV1NewEncodeDecodePerfTest
pkt->data.frame.sz);
}
virtual bool DoDecode() { return false; }
virtual bool DoDecode() const { return false; }
void set_speed(unsigned int speed) { speed_ = speed; }

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
@ -18,13 +18,12 @@
namespace libaom_test {
const char kVP8Name[] = "WebM Project VP8";
const char kAV1Name[] = "AOMedia Project AV1 Decoder";
aom_codec_err_t Decoder::PeekStream(const uint8_t *cxdata, size_t size,
aom_codec_stream_info_t *stream_info) {
return aom_codec_peek_stream_info(
CodecInterface(), cxdata, static_cast<unsigned int>(size), stream_info);
return aom_codec_peek_stream_info(CodecInterface(), cxdata, size,
stream_info);
}
aom_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size) {
@ -36,39 +35,22 @@ aom_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size,
aom_codec_err_t res_dec;
InitOnce();
API_REGISTER_STATE_CHECK(
res_dec = aom_codec_decode(
&decoder_, cxdata, static_cast<unsigned int>(size), user_priv, 0));
res_dec = aom_codec_decode(&decoder_, cxdata, size, user_priv));
return res_dec;
}
bool Decoder::IsVP8() const {
const char *codec_name = GetDecoderName();
return strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0;
}
bool Decoder::IsAV1() const {
const char *codec_name = GetDecoderName();
return strncmp(kAV1Name, codec_name, sizeof(kAV1Name) - 1) == 0;
}
void DecoderTest::HandlePeekResult(Decoder *const decoder,
CompressedVideoSource *video,
void DecoderTest::HandlePeekResult(Decoder *const /*decoder*/,
CompressedVideoSource * /*video*/,
const aom_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 AOM_CODEC_OK on the first
* frame, which must be a keyframe. */
if (video->frame_number() == 0) {
ASSERT_EQ(AOM_CODEC_OK, res_peek)
<< "Peek return failed: " << aom_codec_err_to_string(res_peek);
}
} else {
/* The Av1 implementation of PeekStream returns an error only if the
* data passed to it isn't a valid Av1 chunk. */
ASSERT_EQ(AOM_CODEC_OK, res_peek)
<< "Peek return failed: " << aom_codec_err_to_string(res_peek);
}
/* The Av1 implementation of PeekStream returns an error only if the
* data passed to it isn't a valid Av1 chunk. */
ASSERT_EQ(AOM_CODEC_OK, res_peek)
<< "Peek return failed: " << aom_codec_err_to_string(res_peek);
}
void DecoderTest::RunLoop(CompressedVideoSource *video,
@ -76,6 +58,7 @@ void DecoderTest::RunLoop(CompressedVideoSource *video,
Decoder *const decoder = codec_->CreateDecoder(dec_cfg, flags_);
ASSERT_TRUE(decoder != NULL);
bool end_of_file = false;
bool peeked_stream = false;
// Decode frames.
for (video->Begin(); !::testing::Test::HasFailure() && !end_of_file;
@ -83,15 +66,23 @@ void DecoderTest::RunLoop(CompressedVideoSource *video,
PreDecodeFrameHook(*video, decoder);
aom_codec_stream_info_t stream_info;
stream_info.is_annexb = 0;
if (video->cxdata() != NULL) {
const aom_codec_err_t res_peek = decoder->PeekStream(
video->cxdata(), video->frame_size(), &stream_info);
HandlePeekResult(decoder, video, res_peek);
ASSERT_FALSE(::testing::Test::HasFailure());
if (!peeked_stream) {
// TODO(yaowu): PeekStream returns error for non-sequence_header_obu,
// therefore should only be tried once per sequence, this shall be fixed
// once PeekStream is updated to properly operate on other obus.
const aom_codec_err_t res_peek = decoder->PeekStream(
video->cxdata(), video->frame_size(), &stream_info);
HandlePeekResult(decoder, video, res_peek);
ASSERT_FALSE(::testing::Test::HasFailure());
peeked_stream = true;
}
aom_codec_err_t res_dec =
decoder->DecodeFrame(video->cxdata(), video->frame_size());
if (!HandleDecodeResult(res_dec, decoder)) break;
if (!HandleDecodeResult(res_dec, *video, decoder)) break;
} else {
// Signal end of the file to the decoder.
const aom_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);

View file

@ -13,7 +13,9 @@
#define TEST_DECODE_TEST_DRIVER_H_
#include <cstring>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom/aom_decoder.h"
namespace libaom_test {
@ -93,8 +95,6 @@ class Decoder {
return aom_codec_iface_name(CodecInterface());
}
bool IsVP8() const;
bool IsAV1() const;
aom_codec_ctx_t *GetDecoder() { return &decoder_; }
@ -134,6 +134,7 @@ class DecoderTest {
// Hook to be called to handle decode result. Return true to continue.
virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
const CompressedVideoSource & /*video*/,
Decoder *decoder) {
EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
return AOM_CODEC_OK == res_dec;

View file

@ -16,7 +16,7 @@
. $(dirname $0)/tools_common.sh
# Environment check: Make sure input is available:
# $AOM_IVF_FILE and $AV1_IVF_FILE are required.
# $AV1_IVF_FILE is required.
decode_to_md5_verify_environment() {
if [ "$(av1_encode_available)" != "yes" ] && [ ! -e "${AV1_IVF_FILE}" ]; then
return 1
@ -27,7 +27,7 @@ decode_to_md5_verify_environment() {
# 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="${LIBAOM_BIN_PATH}/decode_to_md5${AOM_TEST_EXE_SUFFIX}"
local decoder="$(aom_tool_path decode_to_md5)"
local input_file="$1"
local codec="$2"
local expected_md5="$3"
@ -45,14 +45,23 @@ decode_to_md5() {
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
if [ "${actual_md5}" = "${expected_md5}" ]; then
return 0
else
elog "MD5 mismatch:"
elog "Expected: ${expected_md5}"
elog "Actual: ${actual_md5}"
return 1
fi
}
decode_to_md5_av1() {
DISABLED_decode_to_md5_av1() {
# expected MD5 sum for the last frame.
local expected_md5="26d3ef1d60754a1f6acb603c3763efbe"
local expected_md5="567dd6d4b7a7170edddbf58bbcc3aff1"
local file="${AV1_IVF_FILE}"
# TODO(urvang): Check in the encoded file (like libvpx does) to avoid
# encoding every time.
if [ "$(av1_decode_available)" = "yes" ]; then
if [ ! -e "${AV1_IVF_FILE}" ]; then
file="${AOM_TEST_OUTPUT_DIR}/test_encode.ivf"
@ -62,6 +71,7 @@ decode_to_md5_av1() {
fi
}
decode_to_md5_tests="decode_to_md5_av1"
# TODO(tomfinegan): Enable when the bitstream stabilizes.
decode_to_md5_tests="DISABLED_decode_to_md5_av1"
run_tests decode_to_md5_verify_environment "${decode_to_md5_tests}"

View file

@ -16,7 +16,7 @@
. $(dirname $0)/tools_common.sh
# Environment check: Make sure input is available:
# $AOM_IVF_FILE and $AV1_IVF_FILE are required.
# $AV1_IVF_FILE is required.
decode_with_drops_verify_environment() {
if [ "$(av1_encode_available)" != "yes" ] && [ ! -e "${AV1_IVF_FILE}" ]; then
return 1
@ -27,7 +27,7 @@ decode_with_drops_verify_environment() {
# to name the output file. $3 is the drop mode, and is passed directly to
# decode_with_drops.
decode_with_drops() {
local decoder="${LIBAOM_BIN_PATH}/decode_with_drops${AOM_TEST_EXE_SUFFIX}"
local decoder="$(aom_tool_path decode_with_drops)"
local input_file="$1"
local codec="$2"
local output_file="${AOM_TEST_OUTPUT_DIR}/decode_with_drops_${codec}"
@ -47,21 +47,22 @@ decode_with_drops() {
# Decodes $AV1_IVF_FILE while dropping frames, twice: once in sequence mode,
# and once in pattern mode.
decode_with_drops_av1() {
DISABLED_decode_with_drops_av1() {
if [ "$(av1_decode_available)" = "yes" ]; then
local file="${AV1_IVF_FILE}"
if [ ! -e "${AV1_IVF_FILE}" ]; then
file="${AOM_TEST_OUTPUT_DIR}/test_encode.ivf"
encode_yuv_raw_input_av1 "${file}" --ivf
fi
# Drop frames 2 and 3.
decode_with_drops "${file}" "av1" "2-3"
# Drop frames 3 and 4.
decode_with_drops "${file}" "av1" "3-4"
# Test pattern mode: Drop 3 of every 4 frames.
decode_with_drops "${file}" "av1" "3/4"
fi
}
decode_with_drops_tests="decode_with_drops_av1"
# TODO(yaowu): Disable this test as trailing_bit check is expected to fail
decode_with_drops_tests="DISABLED_decode_with_drops_av1"
run_tests decode_with_drops_verify_environment "${decode_with_drops_tests}"

View file

@ -1,383 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <cstdlib>
#include <string>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/cdef_block.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
using libaom_test::ACMRandom;
namespace {
typedef std::tr1::tuple<cdef_direction_func, cdef_direction_func, int>
dering_dir_param_t;
class CDEFDeringDirTest : public ::testing::TestWithParam<dering_dir_param_t> {
public:
virtual ~CDEFDeringDirTest() {}
virtual void SetUp() {
dering = GET_PARAM(0);
ref_dering = GET_PARAM(1);
bsize = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
int bsize;
cdef_direction_func dering;
cdef_direction_func ref_dering;
};
typedef CDEFDeringDirTest CDEFDeringSpeedTest;
void test_dering(int bsize, int iterations, cdef_direction_func dering,
cdef_direction_func ref_dering) {
const int size = 8;
const int ysize = size + 2 * CDEF_VBORDER;
ACMRandom rnd(ACMRandom::DeterministicSeed());
DECLARE_ALIGNED(16, uint16_t, s[ysize * CDEF_BSTRIDE]);
DECLARE_ALIGNED(16, static uint16_t, d[size * size]);
DECLARE_ALIGNED(16, static uint16_t, ref_d[size * size]);
memset(ref_d, 0, sizeof(ref_d));
memset(d, 0, sizeof(d));
int error = 0, threshold = 0, dir;
int boundary, damping, depth, bits, level, count,
errdepth = 0, errthreshold = 0, errboundary = 0, errdamping = 0;
unsigned int pos = 0;
for (boundary = 0; boundary < 16; boundary++) {
for (depth = 8; depth <= 12; depth += 2) {
for (damping = 5 + depth - 8; damping < 7 + depth - 8; damping++) {
for (count = 0; count < iterations; count++) {
for (level = 0; level < (1 << depth) && !error;
level += (1 + 4 * !!boundary) << (depth - 8)) {
for (bits = 1; bits <= depth && !error; bits++) {
for (unsigned int i = 0; i < sizeof(s) / sizeof(*s); i++)
s[i] = clamp((rnd.Rand16() & ((1 << bits) - 1)) + level, 0,
(1 << depth) - 1);
if (boundary) {
if (boundary & 1) { // Left
for (int i = 0; i < ysize; i++)
for (int j = 0; j < CDEF_HBORDER; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 2) { // Right
for (int i = 0; i < ysize; i++)
for (int j = CDEF_HBORDER + size; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 4) { // Above
for (int i = 0; i < CDEF_VBORDER; i++)
for (int j = 0; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
if (boundary & 8) { // Below
for (int i = CDEF_VBORDER + size; i < ysize; i++)
for (int j = 0; j < CDEF_BSTRIDE; j++)
s[i * CDEF_BSTRIDE + j] = CDEF_VERY_LARGE;
}
}
for (dir = 0; dir < 8; dir++) {
for (threshold = 0; threshold < 64 << (depth - 8) && !error;
threshold += (1 + 4 * !!boundary) << (depth - 8)) {
ref_dering(ref_d, size,
s + CDEF_HBORDER + CDEF_VBORDER * CDEF_BSTRIDE,
threshold, dir, damping);
// If dering and ref_dering are the same, we're just testing
// speed
if (dering != ref_dering)
ASM_REGISTER_STATE_CHECK(dering(
d, size, s + CDEF_HBORDER + CDEF_VBORDER * CDEF_BSTRIDE,
threshold, dir, damping));
if (ref_dering != dering) {
for (pos = 0; pos < sizeof(d) / sizeof(*d) && !error;
pos++) {
error = ref_d[pos] != d[pos];
errdepth = depth;
errthreshold = threshold;
errboundary = boundary;
errdamping = damping;
}
}
}
}
}
}
}
}
}
}
pos--;
EXPECT_EQ(0, error) << "Error: CDEFDeringDirTest, SIMD and C mismatch."
<< std::endl
<< "First error at " << pos % size << "," << pos / size
<< " (" << (int16_t)ref_d[pos] << " : " << (int16_t)d[pos]
<< ") " << std::endl
<< "threshold: " << errthreshold << std::endl
<< "damping: " << errdamping << std::endl
<< "depth: " << errdepth << std::endl
<< "size: " << bsize << std::endl
<< "boundary: " << errboundary << std::endl
<< std::endl;
}
void test_dering_speed(int bsize, int iterations, cdef_direction_func dering,
cdef_direction_func ref_dering) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
aom_usec_timer_start(&ref_timer);
test_dering(bsize, iterations, ref_dering, ref_dering);
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
test_dering(bsize, iterations, dering, dering);
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
#if 0
std::cout << "[ ] C time = " << ref_elapsed_time / 1000
<< " ms, SIMD time = " << elapsed_time / 1000 << " ms" << std::endl;
#endif
EXPECT_GT(ref_elapsed_time, elapsed_time)
<< "Error: CDEFDeringSpeedTest, SIMD slower than C." << std::endl
<< "C time: " << ref_elapsed_time << " us" << std::endl
<< "SIMD time: " << elapsed_time << " us" << std::endl;
}
typedef int (*find_dir_t)(const uint16_t *img, int stride, int32_t *var,
int coeff_shift);
typedef std::tr1::tuple<find_dir_t, find_dir_t> find_dir_param_t;
class CDEFDeringFindDirTest
: public ::testing::TestWithParam<find_dir_param_t> {
public:
virtual ~CDEFDeringFindDirTest() {}
virtual void SetUp() {
finddir = GET_PARAM(0);
ref_finddir = GET_PARAM(1);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
find_dir_t finddir;
find_dir_t ref_finddir;
};
typedef CDEFDeringFindDirTest CDEFDeringFindDirSpeedTest;
void test_finddir(int (*finddir)(const uint16_t *img, int stride, int32_t *var,
int coeff_shift),
int (*ref_finddir)(const uint16_t *img, int stride,
int32_t *var, int coeff_shift)) {
const int size = 8;
ACMRandom rnd(ACMRandom::DeterministicSeed());
DECLARE_ALIGNED(16, uint16_t, s[size * size]);
int error = 0;
int depth, bits, level, count, errdepth = 0;
int ref_res = 0, res = 0;
int32_t ref_var = 0, var = 0;
for (depth = 8; depth <= 12 && !error; depth += 2) {
for (count = 0; count < 512 && !error; count++) {
for (level = 0; level < (1 << depth) && !error;
level += 1 << (depth - 8)) {
for (bits = 1; bits <= depth && !error; bits++) {
for (unsigned int i = 0; i < sizeof(s) / sizeof(*s); i++)
s[i] = clamp((rnd.Rand16() & ((1 << bits) - 1)) + level, 0,
(1 << depth) - 1);
for (int c = 0; c < 1 + 9 * (finddir == ref_finddir); c++)
ref_res = ref_finddir(s, size, &ref_var, depth - 8);
if (finddir != ref_finddir)
ASM_REGISTER_STATE_CHECK(res = finddir(s, size, &var, depth - 8));
if (ref_finddir != finddir) {
if (res != ref_res || var != ref_var) error = 1;
errdepth = depth;
}
}
}
}
}
EXPECT_EQ(0, error) << "Error: CDEFDeringFindDirTest, SIMD and C mismatch."
<< std::endl
<< "return: " << res << " : " << ref_res << std::endl
<< "var: " << var << " : " << ref_var << std::endl
<< "depth: " << errdepth << std::endl
<< std::endl;
}
void test_finddir_speed(int (*finddir)(const uint16_t *img, int stride,
int32_t *var, int coeff_shift),
int (*ref_finddir)(const uint16_t *img, int stride,
int32_t *var, int coeff_shift)) {
aom_usec_timer ref_timer;
aom_usec_timer timer;
aom_usec_timer_start(&ref_timer);
test_finddir(ref_finddir, ref_finddir);
aom_usec_timer_mark(&ref_timer);
int ref_elapsed_time = (int)aom_usec_timer_elapsed(&ref_timer);
aom_usec_timer_start(&timer);
test_finddir(finddir, finddir);
aom_usec_timer_mark(&timer);
int elapsed_time = (int)aom_usec_timer_elapsed(&timer);
#if 0
std::cout << "[ ] C time = " << ref_elapsed_time / 1000
<< " ms, SIMD time = " << elapsed_time / 1000 << " ms" << std::endl;
#endif
EXPECT_GT(ref_elapsed_time, elapsed_time)
<< "Error: CDEFDeringFindDirSpeedTest, SIMD slower than C." << std::endl
<< "C time: " << ref_elapsed_time << " us" << std::endl
<< "SIMD time: " << elapsed_time << " us" << std::endl;
}
TEST_P(CDEFDeringDirTest, TestSIMDNoMismatch) {
test_dering(bsize, 1, dering, ref_dering);
}
TEST_P(CDEFDeringSpeedTest, DISABLED_TestSpeed) {
test_dering_speed(bsize, 4, dering, ref_dering);
}
TEST_P(CDEFDeringFindDirTest, TestSIMDNoMismatch) {
test_finddir(finddir, ref_finddir);
}
TEST_P(CDEFDeringFindDirSpeedTest, DISABLED_TestSpeed) {
test_finddir_speed(finddir, ref_finddir);
}
using std::tr1::make_tuple;
// VS compiling for 32 bit targets does not support vector types in
// structs as arguments, which makes the v256 type of the intrinsics
// hard to support, so optimizations for this target are disabled.
#if defined(_WIN64) || !defined(_MSC_VER) || defined(__clang__)
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, CDEFDeringDirTest,
::testing::Values(make_tuple(&cdef_direction_4x4_sse2,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_sse2,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(SSE2, CDEFDeringFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_sse2,
&cdef_find_dir_c)));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFDeringDirTest,
::testing::Values(make_tuple(&cdef_direction_4x4_ssse3,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_ssse3,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFDeringFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_ssse3,
&cdef_find_dir_c)));
#endif
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFDeringDirTest,
::testing::Values(make_tuple(&cdef_direction_4x4_sse4_1,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_sse4_1,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFDeringFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_sse4_1,
&cdef_find_dir_c)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, CDEFDeringDirTest,
::testing::Values(make_tuple(&cdef_direction_4x4_neon,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_neon,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(NEON, CDEFDeringFindDirTest,
::testing::Values(make_tuple(&cdef_find_dir_neon,
&cdef_find_dir_c)));
#endif
// Test speed for all supported architectures
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, CDEFDeringSpeedTest,
::testing::Values(make_tuple(&cdef_direction_4x4_sse2,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_sse2,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(SSE2, CDEFDeringFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_sse2,
&cdef_find_dir_c)));
#endif
#if HAVE_SSSE3
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFDeringSpeedTest,
::testing::Values(make_tuple(&cdef_direction_4x4_ssse3,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_ssse3,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(SSSE3, CDEFDeringFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_ssse3,
&cdef_find_dir_c)));
#endif
#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFDeringSpeedTest,
::testing::Values(make_tuple(&cdef_direction_4x4_sse4_1,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_sse4_1,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(SSE4_1, CDEFDeringFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_sse4_1,
&cdef_find_dir_c)));
#endif
#if HAVE_NEON
INSTANTIATE_TEST_CASE_P(NEON, CDEFDeringSpeedTest,
::testing::Values(make_tuple(&cdef_direction_4x4_neon,
&cdef_direction_4x4_c, 4),
make_tuple(&cdef_direction_8x8_neon,
&cdef_direction_8x8_c,
8)));
INSTANTIATE_TEST_CASE_P(NEON, CDEFDeringFindDirSpeedTest,
::testing::Values(make_tuple(&cdef_find_dir_neon,
&cdef_find_dir_c)));
#endif
#endif // defined(_WIN64) || !defined(_MSC_VER)
} // namespace

View file

@ -0,0 +1,359 @@
/*
* Copyright (c) 2018, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "config/aom_config.h"
#include "config/aom_dsp_rtcd.h"
#include "aom_mem/aom_mem.h"
#include "aom_ports/aom_timer.h"
#include "av1/common/blockd.h"
#include "av1/common/pred_common.h"
#include "av1/common/reconintra.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
namespace {
const int kZ1Start = 0;
const int kZ2Start = 90;
const int kZ3Start = 180;
const TX_SIZE kTxSize[] = { TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_64X64,
TX_4X8, TX_8X4, TX_8X16, TX_16X8, TX_16X32,
TX_32X16, TX_32X64, TX_64X32, TX_4X16, TX_16X4,
TX_8X32, TX_32X8, TX_16X64, TX_64X16 };
const char *const kTxSizeStrings[] = {
"TX_4X4", "TX_8X8", "TX_16X16", "TX_32X32", "TX_64X64",
"TX_4X8", "TX_8X4", "TX_8X16", "TX_16X8", "TX_16X32",
"TX_32X16", "TX_32X64", "TX_64X32", "TX_4X16", "TX_16X4",
"TX_8X32", "TX_32X8", "TX_16X64", "TX_64X16"
};
using libaom_test::ACMRandom;
typedef void (*DrPred_Hbd)(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int upsample_above, int upsample_left, int dx,
int dy, int bd);
typedef void (*DrPred)(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left,
int upsample_above, int upsample_left, int dx, int dy,
int bd);
typedef void (*Z1_Lbd)(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left,
int upsample_above, int dx, int dy);
template <Z1_Lbd fn>
void z1_wrapper(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left, int upsample_above,
int /*upsample_left*/, int dx, int dy, int /*bd*/) {
fn(dst, stride, bw, bh, above, left, upsample_above, dx, dy);
}
typedef void (*Z2_Lbd)(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left,
int upsample_above, int upsample_left, int dx, int dy);
template <Z2_Lbd fn>
void z2_wrapper(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left, int upsample_above,
int upsample_left, int dx, int dy, int /*bd*/) {
fn(dst, stride, bw, bh, above, left, upsample_above, upsample_left, dx, dy);
}
typedef void (*Z3_Lbd)(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left,
int upsample_left, int dx, int dy);
template <Z3_Lbd fn>
void z3_wrapper(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
const uint8_t *above, const uint8_t *left,
int /*upsample_above*/, int upsample_left, int dx, int dy,
int /*bd*/) {
fn(dst, stride, bw, bh, above, left, upsample_left, dx, dy);
}
typedef void (*Z1_Hbd)(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int upsample_above, int dx, int dy, int bd);
template <Z1_Hbd fn>
void z1_wrapper_hbd(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int upsample_above, int /*upsample_left*/, int dx, int dy,
int bd) {
fn(dst, stride, bw, bh, above, left, upsample_above, dx, dy, bd);
}
typedef void (*Z2_Hbd)(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int upsample_above, int upsample_left, int dx, int dy,
int bd);
template <Z2_Hbd fn>
void z2_wrapper_hbd(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int upsample_above, int upsample_left, int dx, int dy,
int bd) {
fn(dst, stride, bw, bh, above, left, upsample_above, upsample_left, dx, dy,
bd);
}
typedef void (*Z3_Hbd)(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int upsample_left, int dx, int dy, int bd);
template <Z3_Hbd fn>
void z3_wrapper_hbd(uint16_t *dst, ptrdiff_t stride, int bw, int bh,
const uint16_t *above, const uint16_t *left,
int /*upsample_above*/, int upsample_left, int dx, int dy,
int bd) {
fn(dst, stride, bw, bh, above, left, upsample_left, dx, dy, bd);
}
template <typename FuncType>
struct DrPredFunc {
DrPredFunc(FuncType pred = NULL, FuncType tst = NULL, int bit_depth_value = 0,
int start_angle_value = 0)
: ref_fn(pred), tst_fn(tst), bit_depth(bit_depth_value),
start_angle(start_angle_value) {}
FuncType ref_fn;
FuncType tst_fn;
int bit_depth;
int start_angle;
};
template <typename Pixel, typename FuncType>
class DrPredTest : public ::testing::TestWithParam<DrPredFunc<FuncType> > {
protected:
static const int kMaxNumTests = 100000;
static const int kIterations = 10;
static const int kDstStride = 64;
static const int kDstSize = kDstStride * kDstStride;
static const int kOffset = 16;
static const int kBufSize = ((2 * MAX_TX_SIZE) << 1) + 16;
DrPredTest()
: upsample_above_(0), upsample_left_(0), bw_(0), bh_(0), dx_(1), dy_(1),
bd_(8), txsize_(TX_4X4) {
params_ = this->GetParam();
start_angle_ = params_.start_angle;
stop_angle_ = start_angle_ + 90;
dst_ref_ = &dst_ref_data_[0];
dst_tst_ = &dst_tst_data_[0];
dst_stride_ = kDstStride;
above_ = &above_data_[kOffset];
left_ = &left_data_[kOffset];
for (int i = 0; i < kBufSize; ++i) {
above_data_[i] = rng_.Rand8();
left_data_[i] = rng_.Rand8();
}
for (int i = 0; i < kDstSize; ++i) {
dst_ref_[i] = 0;
}
}
virtual ~DrPredTest() {}
void Predict(bool speedtest, int tx) {
const int kNumTests = speedtest ? kMaxNumTests : 1;
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int k = 0; k < kNumTests; ++k) {
params_.ref_fn(dst_ref_, dst_stride_, bw_, bh_, above_, left_,
upsample_above_, upsample_left_, dx_, dy_, bd_);
}
aom_usec_timer_mark(&timer);
const int ref_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
aom_usec_timer_start(&timer);
if (params_.tst_fn) {
for (int k = 0; k < kNumTests; ++k) {
ASM_REGISTER_STATE_CHECK(params_.tst_fn(dst_tst_, dst_stride_, bw_, bh_,
above_, left_, upsample_above_,
upsample_left_, dx_, dy_, bd_));
}
}
aom_usec_timer_mark(&timer);
const int tst_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
OutputTimes(kNumTests, ref_time, tst_time, tx);
}
void RunTest(bool speedtest) {
for (int i = 0; i < kBufSize; ++i) {
above_data_[i] = left_data_[i] = (1 << bd_) - 1;
}
for (int tx = 0; tx < TX_SIZES_ALL; ++tx) {
if (params_.tst_fn == NULL) {
for (int i = 0; i < kDstSize; ++i) {
dst_tst_[i] = (1 << bd_) - 1;
}
} else {
for (int i = 0; i < kDstSize; ++i) {
dst_tst_[i] = 0;
}
}
bw_ = tx_size_wide[kTxSize[tx]];
bh_ = tx_size_high[kTxSize[tx]];
Predict(speedtest, tx);
for (int r = 0; r < bh_; ++r) {
for (int c = 0; c < bw_; ++c) {
ASSERT_EQ(dst_ref_[r * dst_stride_ + c],
dst_tst_[r * dst_stride_ + c])
<< bw_ << "x" << bh_ << " r: " << r << " c: " << c
<< " dx: " << dx_ << " dy: " << dy_
<< " upsample_above: " << upsample_above_
<< " upsample_left: " << upsample_left_;
}
}
}
}
void OutputTimes(int num_tests, int ref_time, int tst_time, int tx) {
if (num_tests > 1) {
if (params_.tst_fn) {
const float x = static_cast<float>(ref_time) / tst_time;
printf("\t[%8s] :: ref time %6d, tst time %6d %3.2f\n",
kTxSizeStrings[tx], ref_time, tst_time, x);
} else {
printf("\t[%8s] :: ref time %6d\n", kTxSizeStrings[tx], ref_time);
}
}
}
Pixel dst_ref_data_[kDstSize];
Pixel dst_tst_data_[kDstSize];
Pixel left_data_[kBufSize];
Pixel dummy_data_[kBufSize];
Pixel above_data_[kBufSize];
Pixel *dst_ref_;
Pixel *dst_tst_;
Pixel *above_;
Pixel *left_;
int dst_stride_;
int upsample_above_;
int upsample_left_;
int bw_;
int bh_;
int dx_;
int dy_;
int bd_;
TX_SIZE txsize_;
int start_angle_;
int stop_angle_;
ACMRandom rng_;
DrPredFunc<FuncType> params_;
};
class LowbdDrPredTest : public DrPredTest<uint8_t, DrPred> {};
TEST_P(LowbdDrPredTest, SaturatedValues) {
for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
upsample_above_ = iter & 1;
for (int angle = start_angle_; angle < stop_angle_; ++angle) {
dx_ = av1_get_dx(angle);
dy_ = av1_get_dy(angle);
if (dx_ && dy_) RunTest(false);
}
}
}
TEST_P(LowbdDrPredTest, DISABLED_Speed) {
const int angles[] = { 3, 45, 87 };
for (upsample_above_ = 0; upsample_above_ < 2; ++upsample_above_) {
upsample_left_ = upsample_above_;
for (int i = 0; i < 3; ++i) {
dx_ = av1_get_dx(angles[i] + start_angle_);
dy_ = av1_get_dy(angles[i] + start_angle_);
printf("upsample_above: %d upsample_left: %d angle: %d ~~~~~~~~~~~~~~~\n",
upsample_above_, upsample_left_, angles[i] + start_angle_);
if (dx_ && dy_) RunTest(true);
}
}
}
using ::testing::make_tuple;
INSTANTIATE_TEST_CASE_P(
C, LowbdDrPredTest,
::testing::Values(DrPredFunc<DrPred>(&z1_wrapper<av1_dr_prediction_z1_c>,
NULL, AOM_BITS_8, kZ1Start),
DrPredFunc<DrPred>(&z2_wrapper<av1_dr_prediction_z2_c>,
NULL, AOM_BITS_8, kZ2Start),
DrPredFunc<DrPred>(&z3_wrapper<av1_dr_prediction_z3_c>,
NULL, AOM_BITS_8, kZ3Start)));
class HighbdDrPredTest : public DrPredTest<uint16_t, DrPred_Hbd> {};
TEST_P(HighbdDrPredTest, SaturatedValues) {
for (int iter = 0; iter < kIterations && !HasFatalFailure(); ++iter) {
upsample_above_ = iter & 1;
for (int angle = start_angle_; angle < stop_angle_; ++angle) {
dx_ = av1_get_dx(angle);
dy_ = av1_get_dy(angle);
if (dx_ && dy_) RunTest(false);
}
}
}
TEST_P(HighbdDrPredTest, DISABLED_Speed) {
const int angles[] = { 3, 45, 87 };
for (upsample_above_ = 0; upsample_above_ < 2; ++upsample_above_) {
upsample_left_ = upsample_above_;
for (int i = 0; i < 3; ++i) {
dx_ = av1_get_dx(angles[i] + start_angle_);
dy_ = av1_get_dy(angles[i] + start_angle_);
printf("upsample_above: %d upsample_left: %d angle: %d ~~~~~~~~~~~~~~~\n",
upsample_above_, upsample_left_, angles[i] + start_angle_);
if (dx_ && dy_) RunTest(true);
}
}
}
INSTANTIATE_TEST_CASE_P(
C, HighbdDrPredTest,
::testing::Values(
DrPredFunc<DrPred_Hbd>(&z1_wrapper_hbd<av1_highbd_dr_prediction_z1_c>,
NULL, AOM_BITS_8, kZ1Start),
DrPredFunc<DrPred_Hbd>(&z1_wrapper_hbd<av1_highbd_dr_prediction_z1_c>,
NULL, AOM_BITS_10, kZ1Start),
DrPredFunc<DrPred_Hbd>(&z1_wrapper_hbd<av1_highbd_dr_prediction_z1_c>,
NULL, AOM_BITS_12, kZ1Start),
DrPredFunc<DrPred_Hbd>(&z2_wrapper_hbd<av1_highbd_dr_prediction_z2_c>,
NULL, AOM_BITS_8, kZ2Start),
DrPredFunc<DrPred_Hbd>(&z2_wrapper_hbd<av1_highbd_dr_prediction_z2_c>,
NULL, AOM_BITS_10, kZ2Start),
DrPredFunc<DrPred_Hbd>(&z2_wrapper_hbd<av1_highbd_dr_prediction_z2_c>,
NULL, AOM_BITS_12, kZ2Start),
DrPredFunc<DrPred_Hbd>(&z3_wrapper_hbd<av1_highbd_dr_prediction_z3_c>,
NULL, AOM_BITS_8, kZ3Start),
DrPredFunc<DrPred_Hbd>(&z3_wrapper_hbd<av1_highbd_dr_prediction_z3_c>,
NULL, AOM_BITS_10, kZ3Start),
DrPredFunc<DrPred_Hbd>(&z3_wrapper_hbd<av1_highbd_dr_prediction_z3_c>,
NULL, AOM_BITS_12, kZ3Start)));
} // namespace

70
third_party/aom/test/dump_obu.sh vendored Executable file
View file

@ -0,0 +1,70 @@
#!/bin/sh
## Copyright (c) 2018, Alliance for Open Media. All rights reserved
##
## This source code is subject to the terms of the BSD 2 Clause License and
## the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
## was not distributed with this source code in the LICENSE file, you can
## obtain it at www.aomedia.org/license/software. If the Alliance for Open
## Media Patent License 1.0 was not distributed with this source code in the
## PATENTS file, you can obtain it at www.aomedia.org/license/patent.
##
## This file tests the libaom dump_obu tool. To add new tests to this
## file, do the following:
## 1. Write a shell function (this is your test).
## 2. Add the function to dump_obu_tests (on a new line).
##
. $(dirname $0)/tools_common.sh
readonly dump_obu_test_file="${AOM_TEST_OUTPUT_DIR}/av1_obu_test.ivf"
dump_obu_verify_environment() {
if [ ! -e "${YUV_RAW_INPUT}" ]; then
elog "The file ${YUV_RAW_INPUT##*/} must exist in LIBAOM_TEST_DATA_PATH."
return 1
fi
if [ "$(dump_obu_available)" = "yes" ]; then
if [ -z "$(aom_tool_path dump_obu)" ]; then
elog "dump_obu not found in LIBAOM_BIN_PATH, its parent, or child tools/."
fi
fi
}
dump_obu_available() {
if [ "$(av1_decode_available)" = "yes" ] && \
[ "$(av1_encode_available)" = "yes" ]; then
echo yes
fi
}
aomenc_available() {
if [ -x "$(aom_tool_path aomenc)" ]; then
echo yes
fi
}
encode_test_file() {
if [ "$(aomenc_available)" = "yes" ]; then
local readonly encoder="$(aom_tool_path aomenc)"
eval "${encoder}" \
$(aomenc_encode_test_fast_params) \
$(yuv_raw_input) \
--ivf \
--output=${dump_obu_test_file} \
${devnull}
if [ ! -e "${dump_obu_test_file}" ]; then
elog "dump_obu test input encode failed."
return 1
fi
fi
}
dump_obu() {
encode_test_file
eval $(aom_tool_path dump_obu) "${dump_obu_test_file}" ${devnull}
}
dump_obu_tests="dump_obu"
run_tests dump_obu_verify_environment "${dump_obu_tests}"

159
third_party/aom/test/ec_test.cc vendored Normal file
View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include <cstdlib>
#include "aom_dsp/entenc.h"
#include "aom_dsp/entdec.h"
TEST(EC_TEST, random_ec_test) {
od_ec_enc enc;
od_ec_dec dec;
int sz;
int i;
int ret;
unsigned int sym;
unsigned int seed;
unsigned char *ptr;
uint32_t ptr_sz;
char *seed_str;
ret = 0;
seed_str = getenv("EC_TEST_SEED");
if (seed_str) {
seed = atoi(seed_str);
} else {
seed = 0xdaa1a;
}
srand(seed);
od_ec_enc_init(&enc, 1);
/*Test compatibility between multiple different encode/decode routines.*/
for (i = 0; i < 409600; i++) {
unsigned *fz;
unsigned *fts;
unsigned *data;
unsigned *tell;
unsigned *enc_method;
int j;
sz = rand() / ((RAND_MAX >> (rand() % 9U)) + 1U);
fz = (unsigned *)malloc(sz * sizeof(*fz));
fts = (unsigned *)malloc(sz * sizeof(*fts));
data = (unsigned *)malloc(sz * sizeof(*data));
tell = (unsigned *)malloc((sz + 1) * sizeof(*tell));
enc_method = (unsigned *)malloc(sz * sizeof(*enc_method));
od_ec_enc_reset(&enc);
tell[0] = od_ec_enc_tell_frac(&enc);
for (j = 0; j < sz; j++) {
data[j] = rand() / ((RAND_MAX >> 1) + 1);
fts[j] = CDF_PROB_BITS;
fz[j] = (rand() % (CDF_PROB_TOP - 2)) >> (CDF_PROB_BITS - fts[j]);
fz[j] = OD_MAXI(fz[j], 1);
enc_method[j] = 3 + (rand() & 1);
switch (enc_method[j]) {
case 3: {
od_ec_encode_bool_q15(&enc, data[j],
OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
break;
}
case 4: {
uint16_t cdf[2];
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
od_ec_encode_cdf_q15(&enc, data[j], cdf, 2);
break;
}
}
tell[j + 1] = od_ec_enc_tell_frac(&enc);
}
ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_GE(((od_ec_enc_tell(&enc) + 7U) >> 3), ptr_sz)
<< "od_ec_enc_tell() lied: "
"there's "
<< ptr_sz << " bytes instead of " << ((od_ec_enc_tell(&enc) + 7) >> 3)
<< " (Random seed: " << seed << ")\n";
od_ec_dec_init(&dec, ptr, ptr_sz);
EXPECT_EQ(od_ec_dec_tell_frac(&dec), tell[0])
<< "od_ec_dec_tell() mismatch between encoder and decoder "
"at symbol 0: "
<< (unsigned)od_ec_dec_tell_frac(&dec) << " instead of " << tell[0]
<< " (Random seed: " << seed << ").\n";
for (j = 0; j < sz; j++) {
int dec_method;
if (CDF_SHIFT == 0) {
dec_method = 3 + (rand() & 1);
} else {
dec_method = enc_method[j];
}
switch (dec_method) {
case 3: {
sym = od_ec_decode_bool_q15(
&dec, OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
break;
}
case 4: {
uint16_t cdf[2];
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
sym = od_ec_decode_cdf_q15(&dec, cdf, 2);
break;
}
}
EXPECT_EQ(sym, data[j])
<< "Decoded " << sym << " instead of " << data[j]
<< " with fz=" << fz[j] << " and ftb=" << fts[j] << "at position "
<< j << " of " << sz << " (Random seed: " << seed << ").\n"
<< "Encoding method: " << enc_method[j]
<< " decoding method: " << dec_method << "\n";
EXPECT_EQ(od_ec_dec_tell_frac(&dec), tell[j + 1])
<< "od_ec_dec_tell() mismatch between encoder and "
"decoder at symbol "
<< j + 1 << ": " << (unsigned)od_ec_dec_tell_frac(&dec)
<< " instead of " << tell[j + 1] << " (Random seed: " << seed
<< ").\n";
}
free(enc_method);
free(tell);
free(data);
free(fts);
free(fz);
}
od_ec_enc_reset(&enc);
if (CDF_SHIFT == 0) {
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
od_ec_enc_patch_initial_bits(&enc, 3, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
od_ec_enc_patch_initial_bits(&enc, 0, 5);
EXPECT_TRUE(enc.error)
<< "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n";
od_ec_enc_reset(&enc);
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 1, OD_ICDF(32256));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
od_ec_enc_patch_initial_bits(&enc, 0, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_EQ(ptr_sz, 2u);
EXPECT_EQ(ptr[0], 63)
<< "Got " << ptr[0]
<< " when expecting 63 for od_ec_enc_patch_initial_bits().\n";
}
od_ec_enc_clear(&enc);
EXPECT_EQ(ret, 0);
}

View file

@ -7,11 +7,12 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "config/aom_config.h"
#include "test/util.h"
#include "aom/aomcx.h"
#include "aom/aom_encoder.h"
@ -33,8 +34,8 @@ TEST(EncodeAPI, InvalidParams) {
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_enc_init(NULL, NULL, NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_enc_init(&enc, NULL, NULL, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_encode(NULL, NULL, 0, 0, 0, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_encode(NULL, &img, 0, 0, 0, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_encode(NULL, NULL, 0, 0, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_encode(NULL, &img, 0, 0, 0));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM, aom_codec_destroy(NULL));
EXPECT_EQ(AOM_CODEC_INVALID_PARAM,
aom_codec_enc_config_default(NULL, NULL, 0));
@ -53,7 +54,7 @@ TEST(EncodeAPI, InvalidParams) {
EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(kCodecs[i], &cfg, 0));
EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, kCodecs[i], &cfg, 0));
EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, NULL, 0, 0, 0, 0));
EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, NULL, 0, 0, 0));
EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
}

View file

@ -7,12 +7,14 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <string>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./aom_version.h"
#include "config/aom_config.h"
#include "config/aom_version.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/i420_video_source.h"

View file

@ -7,13 +7,14 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <string>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "config/aom_config.h"
#include "aom_ports/mem.h"
#include "test/codec_factory.h"
#include "test/decode_test_driver.h"
@ -34,21 +35,6 @@ void Encoder::InitEncoder(VideoSource *video) {
res = aom_codec_enc_init(&encoder_, CodecInterface(), &cfg_, init_flags_);
ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
#if CONFIG_AV1_ENCODER
if (CodecInterface() == &aom_codec_av1_cx_algo) {
// Default to 1 tile column for AV1. With CONFIG_EXT_TILE, the
// default is already the largest possible tile size
#if !CONFIG_EXT_TILE
const int log2_tile_columns = 0;
res = aom_codec_control_(&encoder_, AV1E_SET_TILE_COLUMNS,
log2_tile_columns);
ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
#endif // !CONFIG_EXT_TILE
} else
#endif
{
}
}
}
@ -82,15 +68,14 @@ void Encoder::EncodeFrameInternal(const VideoSource &video,
}
// Encode the frame
API_REGISTER_STATE_CHECK(res = aom_codec_encode(&encoder_, img, video.pts(),
video.duration(), frame_flags,
deadline_));
API_REGISTER_STATE_CHECK(res =
aom_codec_encode(&encoder_, img, video.pts(),
video.duration(), frame_flags));
ASSERT_EQ(AOM_CODEC_OK, res) << EncoderError();
}
void Encoder::Flush() {
const aom_codec_err_t res =
aom_codec_encode(&encoder_, NULL, 0, 0, 0, deadline_);
const aom_codec_err_t res = aom_codec_encode(&encoder_, NULL, 0, 0, 0);
if (!encoder_.priv)
ASSERT_EQ(AOM_CODEC_ERROR, res) << EncoderError();
else
@ -105,11 +90,8 @@ void EncoderTest::InitializeConfig() {
void EncoderTest::SetMode(TestMode mode) {
switch (mode) {
case kOnePassGood:
case kTwoPassGood: deadline_ = AOM_DL_GOOD_QUALITY; break;
case kRealTime:
deadline_ = AOM_DL_GOOD_QUALITY;
cfg_.g_lag_in_frames = 0;
break;
case kTwoPassGood: break;
case kRealTime: cfg_.g_lag_in_frames = 0; break;
default: ASSERT_TRUE(false) << "Unexpected mode " << mode;
}
mode_ = mode;
@ -149,14 +131,16 @@ static bool compare_img(const aom_image_t *img1, const aom_image_t *img2,
int *const mismatch_row, int *const mismatch_col,
int *const mismatch_plane, int *const mismatch_pix1,
int *const mismatch_pix2) {
if (img1->fmt != img2->fmt || img1->cs != img2->cs ||
img1->d_w != img2->d_w || img1->d_h != img2->d_h) {
if (img1->fmt != img2->fmt || img1->cp != img2->cp || img1->tc != img2->tc ||
img1->mc != img2->mc || img1->d_w != img2->d_w ||
img1->d_h != img2->d_h || img1->monochrome != img2->monochrome) {
if (mismatch_row != NULL) *mismatch_row = -1;
if (mismatch_col != NULL) *mismatch_col = -1;
return false;
}
for (int plane = 0; plane < 3; plane++) {
const int num_planes = img1->monochrome ? 1 : 3;
for (int plane = 0; plane < num_planes; plane++) {
if (!compare_plane(img1->planes[plane], img1->stride[plane],
img2->planes[plane], img2->stride[plane],
aom_img_plane_width(img1, plane),
@ -209,7 +193,7 @@ void EncoderTest::RunLoop(VideoSource *video) {
BeginPassHook(pass);
testing::internal::scoped_ptr<Encoder> encoder(
codec_->CreateEncoder(cfg_, deadline_, init_flags_, &stats_));
codec_->CreateEncoder(cfg_, init_flags_, &stats_));
ASSERT_TRUE(encoder.get() != NULL);
ASSERT_NO_FATAL_FAILURE(video->Begin());
@ -228,10 +212,11 @@ void EncoderTest::RunLoop(VideoSource *video) {
dec_init_flags |= AOM_CODEC_USE_INPUT_FRAGMENTS;
testing::internal::scoped_ptr<Decoder> decoder(
codec_->CreateDecoder(dec_cfg, dec_init_flags));
#if CONFIG_AV1 && CONFIG_EXT_TILE
#if CONFIG_AV1_DECODER
if (decoder->IsAV1()) {
// Set dec_cfg.tile_row = -1 and dec_cfg.tile_col = -1 so that the whole
// frame is decoded.
decoder->Control(AV1_SET_TILE_MODE, cfg_.large_scale_tile);
decoder->Control(AV1_SET_DECODE_TILE_ROW, -1);
decoder->Control(AV1_SET_DECODE_TILE_COL, -1);
}
@ -256,8 +241,16 @@ void EncoderTest::RunLoop(VideoSource *video) {
case AOM_CODEC_CX_FRAME_PKT:
has_cxdata = true;
if (decoder.get() != NULL && DoDecode()) {
aom_codec_err_t res_dec = decoder->DecodeFrame(
(const uint8_t *)pkt->data.frame.buf, pkt->data.frame.sz);
aom_codec_err_t res_dec;
if (DoDecodeInvisible()) {
res_dec = decoder->DecodeFrame(
(const uint8_t *)pkt->data.frame.buf, pkt->data.frame.sz);
} else {
res_dec = decoder->DecodeFrame(
(const uint8_t *)pkt->data.frame.buf +
(pkt->data.frame.sz - pkt->data.frame.vis_frame_size),
pkt->data.frame.vis_frame_size);
}
if (!HandleDecodeResult(res_dec, decoder.get())) break;

View file

@ -16,7 +16,8 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "config/aom_config.h"
#if CONFIG_AV1_ENCODER
#include "aom/aomcx.h"
#endif
@ -37,6 +38,9 @@ enum TestMode { kRealTime, kOnePassGood, kTwoPassGood };
#define TWO_PASS_TEST_MODES ::testing::Values(::libaom_test::kTwoPassGood)
#define NONREALTIME_TEST_MODES \
::testing::Values(::libaom_test::kOnePassGood, ::libaom_test::kTwoPassGood)
// Provides an object to handle the libaom get_cx_data() iteration pattern
class CxDataIterator {
public:
@ -78,9 +82,9 @@ class TwopassStatsStore {
// level of abstraction will be fleshed out as more tests are written.
class Encoder {
public:
Encoder(aom_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) {
Encoder(aom_codec_enc_cfg_t cfg, const uint32_t init_flags,
TwopassStatsStore *stats)
: cfg_(cfg), init_flags_(init_flags), stats_(stats) {
memset(&encoder_, 0, sizeof(encoder_));
}
@ -128,8 +132,6 @@ class Encoder {
cfg_ = *cfg;
}
void set_deadline(unsigned long deadline) { deadline_ = deadline; }
protected:
virtual aom_codec_iface_t *CodecInterface() const = 0;
@ -147,7 +149,6 @@ class Encoder {
aom_codec_ctx_t encoder_;
aom_codec_enc_cfg_t cfg_;
unsigned long deadline_;
unsigned long init_flags_;
TwopassStatsStore *stats_;
};
@ -173,7 +174,7 @@ class EncoderTest {
// Initialize the cfg_ member with the default configuration.
void InitializeConfig();
// Map the TestMode enum to the deadline_ and passes_ variables.
// Map the TestMode enum to the passes_ variables.
void SetMode(TestMode mode);
// Set encoder flag.
@ -206,9 +207,11 @@ class EncoderTest {
return !(::testing::Test::HasFatalFailure() || abort_);
}
const CodecFactory *codec_;
// Hook to determine whether to decode frame after encoding
virtual bool DoDecode() const { return 1; }
virtual bool DoDecode() const { return true; }
// Hook to determine whether to decode invisible frames after encoding
virtual bool DoDecodeInvisible() const { return true; }
// Hook to handle encode/decode mismatch
virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2);
@ -230,10 +233,10 @@ class EncoderTest {
return pkt;
}
const CodecFactory *codec_;
bool abort_;
aom_codec_enc_cfg_t cfg_;
unsigned int passes_;
unsigned long deadline_;
TwopassStatsStore stats_;
unsigned long init_flags_;
unsigned long frame_flags_;

View file

@ -1,164 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"
#include "test/encode_test_driver.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "av1/av1_dx_iface.c"
namespace {
const int kCpuUsed = 2;
struct EncodePerfTestVideo {
const char *name;
uint32_t width;
uint32_t height;
uint32_t bitrate;
int frames;
};
const EncodePerfTestVideo kAV1EncodePerfTestVectors[] = {
{ "niklas_1280_720_30.y4m", 1280, 720, 600, 10 },
};
struct EncodeParameters {
int32_t tile_rows;
int32_t tile_cols;
int32_t lossless;
int32_t error_resilient;
int32_t frame_parallel;
aom_color_range_t color_range;
aom_color_space_t cs;
#if CONFIG_COLORSPACE_HEADERS
aom_transfer_function_t tf;
aom_chroma_sample_position_t csp;
#endif
int render_size[2];
// TODO(JBB): quantizers / bitrate
};
const EncodeParameters kAV1EncodeParameterSet[] = {
{ 0, 0, 0, 1, 0, AOM_CR_STUDIO_RANGE, AOM_CS_BT_601, { 0, 0 } },
{ 0, 0, 0, 0, 0, AOM_CR_FULL_RANGE, AOM_CS_BT_709, { 0, 0 } },
#if CONFIG_COLORSPACE_HEADERS
{ 0, 0, 1, 0, 0, AOM_CR_FULL_RANGE, AOM_CS_BT_2020_NCL, { 0, 0 } },
#else
{ 0, 0, 1, 0, 0, AOM_CR_FULL_RANGE, AOM_CS_BT_2020, { 0, 0 } },
#endif
{ 0, 2, 0, 0, 1, AOM_CR_STUDIO_RANGE, AOM_CS_UNKNOWN, { 640, 480 } },
// TODO(JBB): Test profiles (requires more work).
};
class AvxEncoderParmsGetToDecoder
: public ::libaom_test::CodecTestWith2Params<EncodeParameters,
EncodePerfTestVideo>,
public ::libaom_test::EncoderTest,
{
protected:
AvxEncoderParmsGetToDecoder()
: EncoderTest(GET_PARAM(0)), encode_parms(GET_PARAM(1)) {}
virtual ~AvxEncoderParmsGetToDecoder() {}
virtual void SetUp() {
InitializeConfig();
SetMode(::libaom_test::kTwoPassGood);
cfg_.g_lag_in_frames = 25;
cfg_.g_error_resilient = encode_parms.error_resilient;
dec_cfg_.threads = 4;
test_video_ = GET_PARAM(2);
cfg_.rc_target_bitrate = test_video_.bitrate;
}
virtual void PreEncodeFrameHook(::libaom_test::VideoSource *video,
::libaom_test::Encoder *encoder) {
if (video->frame() == 1) {
encoder->Control(AV1E_SET_COLOR_SPACE, encode_parms.cs);
#if CONFIG_COLORSPACE_HEADERS
encoder->Control(AV1E_SET_TRANSFER_FUNCTION, encode_parms.tf);
encoder->Control(AV1E_SET_CHROMA_SAMPLE_POSITION, encode_parms.csp);
#endif
encoder->Control(AV1E_SET_COLOR_RANGE, encode_parms.color_range);
encoder->Control(AV1E_SET_LOSSLESS, encode_parms.lossless);
encoder->Control(AV1E_SET_FRAME_PARALLEL_DECODING,
encode_parms.frame_parallel);
encoder->Control(AV1E_SET_TILE_ROWS, encode_parms.tile_rows);
encoder->Control(AV1E_SET_TILE_COLUMNS, encode_parms.tile_cols);
encoder->Control(AOME_SET_CPUUSED, kCpuUsed);
encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
encoder->Control(AOME_SET_ARNR_MAXFRAMES, 7);
encoder->Control(AOME_SET_ARNR_STRENGTH, 5);
if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0)
encoder->Control(AV1E_SET_RENDER_SIZE, encode_parms.render_size);
}
}
virtual bool HandleDecodeResult(const aom_codec_err_t res_dec,
libaom_test::Decoder *decoder) {
aom_codec_ctx_t *const av1_decoder = decoder->GetDecoder();
aom_codec_alg_priv_t *const priv =
reinterpret_cast<aom_codec_alg_priv_t *>(av1_decoder->priv);
FrameWorkerData *const worker_data =
reinterpret_cast<FrameWorkerData *>(priv->frame_workers[0].data1);
AV1_COMMON *const common = &worker_data->pbi->common;
if (encode_parms.lossless) {
EXPECT_EQ(0, common->base_qindex);
EXPECT_EQ(0, common->y_dc_delta_q);
EXPECT_EQ(0, common->uv_dc_delta_q);
EXPECT_EQ(0, common->uv_ac_delta_q);
EXPECT_EQ(ONLY_4X4, common->tx_mode);
}
EXPECT_EQ(encode_parms.error_resilient, common->error_resilient_mode);
if (encode_parms.error_resilient) {
EXPECT_EQ(0, common->use_prev_frame_mvs);
}
EXPECT_EQ(encode_parms.color_range, common->color_range);
EXPECT_EQ(encode_parms.cs, common->color_space);
#if CONFIG_COLORSPACE_HEADERS
EXPECT_EQ(encode_parms.tf, common->transfer_function);
EXPECT_EQ(encode_parms.csp, common->chroma_sample_position);
#endif
if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) {
EXPECT_EQ(encode_parms.render_size[0], common->render_width);
EXPECT_EQ(encode_parms.render_size[1], common->render_height);
}
EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols);
EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows);
EXPECT_EQ(AOM_CODEC_OK, res_dec) << decoder->DecodeError();
return AOM_CODEC_OK == res_dec;
}
EncodePerfTestVideo test_video_;
private:
EncodeParameters encode_parms;
};
TEST_P(AvxEncoderParmsGetToDecoder, BitstreamParms) {
init_flags_ = AOM_CODEC_USE_PSNR;
testing::internal::scoped_ptr<libaom_test::VideoSource> video(
new libaom_test::Y4mVideoSource(test_video_.name, 0, test_video_.frames));
ASSERT_TRUE(video.get() != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
}
AV1_INSTANTIATE_TEST_CASE(AvxEncoderParmsGetToDecoder,
::testing::ValuesIn(kAV1EncodeParameterSet),
::testing::ValuesIn(kAV1EncodePerfTestVectors));
} // namespace

242
third_party/aom/test/encodetxb_test.cc vendored Normal file
View file

@ -0,0 +1,242 @@
/*
* Copyright (c) 2017, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "config/aom_config.h"
#include "config/av1_rtcd.h"
#include "aom_ports/aom_timer.h"
#include "aom_ports/mem.h"
#include "av1/common/idct.h"
#include "av1/common/onyxc_int.h"
#include "av1/common/scan.h"
#include "av1/common/txb_common.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
namespace {
using libaom_test::ACMRandom;
typedef void (*GetNzMapContextsFunc)(const uint8_t *const levels,
const int16_t *const scan,
const uint16_t eob, const TX_SIZE tx_size,
const TX_CLASS tx_class,
int8_t *const coeff_contexts);
class EncodeTxbTest : public ::testing::TestWithParam<GetNzMapContextsFunc> {
public:
EncodeTxbTest() : get_nz_map_contexts_func_(GetParam()) {}
virtual ~EncodeTxbTest() {}
virtual void SetUp() {
coeff_contexts_ref_ = reinterpret_cast<int8_t *>(
aom_memalign(16, sizeof(*coeff_contexts_ref_) * MAX_TX_SQUARE));
ASSERT_TRUE(coeff_contexts_ref_ != NULL);
coeff_contexts_ = reinterpret_cast<int8_t *>(
aom_memalign(16, sizeof(*coeff_contexts_) * MAX_TX_SQUARE));
ASSERT_TRUE(coeff_contexts_ != NULL);
}
virtual void TearDown() {
aom_free(coeff_contexts_ref_);
aom_free(coeff_contexts_);
libaom_test::ClearSystemState();
}
void GetNzMapContextsRun() {
const int kNumTests = 10;
int result = 0;
for (int is_inter = 0; is_inter < 2; ++is_inter) {
for (int tx_type = DCT_DCT; tx_type < TX_TYPES; ++tx_type) {
const TX_CLASS tx_class = tx_type_to_class[tx_type];
for (int tx_size = TX_4X4; tx_size < TX_SIZES_ALL; ++tx_size) {
const int bwl = get_txb_bwl((TX_SIZE)tx_size);
const int width = get_txb_wide((TX_SIZE)tx_size);
const int height = get_txb_high((TX_SIZE)tx_size);
const int real_width = tx_size_wide[tx_size];
const int real_height = tx_size_high[tx_size];
const int16_t *const scan = av1_scan_orders[tx_size][tx_type].scan;
levels_ = set_levels(levels_buf_, width);
for (int i = 0; i < kNumTests && !result; ++i) {
for (int eob = 1; eob <= width * height && !result; ++eob) {
InitDataWithEob(scan, bwl, eob);
av1_get_nz_map_contexts_c(levels_, scan, eob, (TX_SIZE)tx_size,
tx_class, coeff_contexts_ref_);
get_nz_map_contexts_func_(levels_, scan, eob, (TX_SIZE)tx_size,
tx_class, coeff_contexts_);
result = Compare(scan, eob);
EXPECT_EQ(result, 0)
<< " tx_class " << tx_class << " width " << real_width
<< " height " << real_height << " eob " << eob;
}
}
}
}
}
}
void SpeedTestGetNzMapContextsRun() {
const int kNumTests = 2000000000;
aom_usec_timer timer;
printf("Note: Only test the largest possible eob case!\n");
for (int tx_size = TX_4X4; tx_size < TX_SIZES_ALL; ++tx_size) {
const int bwl = get_txb_bwl((TX_SIZE)tx_size);
const int width = get_txb_wide((TX_SIZE)tx_size);
const int height = get_txb_high((TX_SIZE)tx_size);
const int real_width = tx_size_wide[tx_size];
const int real_height = tx_size_high[tx_size];
const TX_TYPE tx_type = DCT_DCT;
const TX_CLASS tx_class = tx_type_to_class[tx_type];
const int16_t *const scan = av1_scan_orders[tx_size][tx_type].scan;
const int eob = width * height;
const int numTests = kNumTests / (width * height);
levels_ = set_levels(levels_buf_, width);
InitDataWithEob(scan, bwl, eob);
aom_usec_timer_start(&timer);
for (int i = 0; i < numTests; ++i) {
get_nz_map_contexts_func_(levels_, scan, eob, (TX_SIZE)tx_size,
tx_class, coeff_contexts_);
}
aom_usec_timer_mark(&timer);
const int elapsed_time = static_cast<int>(aom_usec_timer_elapsed(&timer));
printf("get_nz_map_contexts_%2dx%2d: %7.1f ms\n", real_width, real_height,
elapsed_time / 1000.0);
}
}
private:
void InitDataWithEob(const int16_t *const scan, const int bwl,
const int eob) {
memset(levels_buf_, 0, sizeof(levels_buf_));
memset(coeff_contexts_, 0, sizeof(*coeff_contexts_) * MAX_TX_SQUARE);
for (int c = 0; c < eob; ++c) {
levels_[get_padded_idx(scan[c], bwl)] =
static_cast<uint8_t>(clamp(rnd_.Rand8(), 0, INT8_MAX));
coeff_contexts_[scan[c]] = rnd_.Rand16() >> 1;
}
memcpy(coeff_contexts_ref_, coeff_contexts_,
sizeof(*coeff_contexts_) * MAX_TX_SQUARE);
}
bool Compare(const int16_t *const scan, const int eob) const {
bool result = false;
if (memcmp(coeff_contexts_, coeff_contexts_ref_,
sizeof(*coeff_contexts_ref_) * MAX_TX_SQUARE)) {
for (int i = 0; i < eob; i++) {
const int pos = scan[i];
if (coeff_contexts_ref_[pos] != coeff_contexts_[pos]) {
printf("coeff_contexts_[%d] diff:%6d (ref),%6d (opt)\n", pos,
coeff_contexts_ref_[pos], coeff_contexts_[pos]);
result = true;
break;
}
}
}
return result;
}
GetNzMapContextsFunc get_nz_map_contexts_func_;
ACMRandom rnd_;
uint8_t levels_buf_[TX_PAD_2D];
uint8_t *levels_;
int8_t *coeff_contexts_ref_;
int8_t *coeff_contexts_;
};
TEST_P(EncodeTxbTest, GetNzMapContexts) { GetNzMapContextsRun(); }
TEST_P(EncodeTxbTest, DISABLED_SpeedTestGetNzMapContexts) {
SpeedTestGetNzMapContextsRun();
}
#if HAVE_SSE2
INSTANTIATE_TEST_CASE_P(SSE2, EncodeTxbTest,
::testing::Values(av1_get_nz_map_contexts_sse2));
#endif
#if HAVE_SSE4_1
class EncodeTxbInitLevelTest : public ::testing::TestWithParam<int> {
public:
virtual ~EncodeTxbInitLevelTest() {}
virtual void TearDown() { libaom_test::ClearSystemState(); }
void RunTest(int tx_size, int is_speed);
};
void EncodeTxbInitLevelTest::RunTest(int tx_size, int is_speed) {
const int width = get_txb_wide((TX_SIZE)tx_size);
const int height = get_txb_high((TX_SIZE)tx_size);
tran_low_t coeff[MAX_TX_SQUARE];
uint8_t levels_buf[2][TX_PAD_2D];
uint8_t *const levels0 = set_levels(levels_buf[0], width);
uint8_t *const levels1 = set_levels(levels_buf[1], width);
ACMRandom rnd(ACMRandom::DeterministicSeed());
for (int i = 0; i < width * height; i++) {
coeff[i] = rnd.Rand15Signed() + rnd.Rand15Signed();
}
for (int i = 0; i < TX_PAD_2D; i++) {
levels_buf[0][i] = rnd.Rand8();
levels_buf[1][i] = rnd.Rand8();
}
const int run_times = is_speed ? (width * height) * 10000 : 1;
aom_usec_timer timer;
aom_usec_timer_start(&timer);
for (int i = 0; i < run_times; ++i) {
av1_txb_init_levels_c(coeff, width, height, levels0);
}
const double t1 = get_time_mark(&timer);
aom_usec_timer_start(&timer);
for (int i = 0; i < run_times; ++i) {
av1_txb_init_levels_sse4_1(coeff, width, height, levels1);
}
const double t2 = get_time_mark(&timer);
if (is_speed) {
printf("init %3dx%-3d:%7.2f/%7.2fns", width, height, t1, t2);
printf("(%3.2f)\n", t1 / t2);
}
const int stride = width + TX_PAD_HOR;
for (int r = 0; r < height + TX_PAD_VER; ++r) {
for (int c = 0; c < stride; ++c) {
ASSERT_EQ(levels_buf[0][c + r * stride], levels_buf[1][c + r * stride])
<< "[" << r << "," << c << "] " << run_times << width << "x"
<< height;
}
}
}
TEST_P(EncodeTxbInitLevelTest, match) { RunTest(GetParam(), 0); }
TEST_P(EncodeTxbInitLevelTest, DISABLED_Speed) { RunTest(GetParam(), 1); }
INSTANTIATE_TEST_CASE_P(SSE4_1, EncodeTxbInitLevelTest,
::testing::Range(0, static_cast<int>(TX_SIZES_ALL), 1));
#endif
} // namespace

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
@ -30,7 +30,7 @@ const double kPsnrThreshold[][5] = {
// AV1 HBD average PSNR is slightly lower than AV1.
// We make two cases here to enable the testing and
// guard picture quality.
#if CONFIG_AV1_ENCODER && CONFIG_HIGHBITDEPTH
#if CONFIG_AV1_ENCODER
{ 36.0, 37.0, 37.0, 37.0, 37.0 }, { 31.0, 36.0, 36.0, 36.0, 36.0 },
{ 31.0, 35.0, 35.0, 35.0, 35.0 }, { 31.0, 34.0, 34.0, 34.0, 34.0 },
{ 31.0, 33.0, 33.0, 33.0, 33.0 }, { 31.0, 32.0, 32.0, 32.0, 32.0 },
@ -40,7 +40,7 @@ const double kPsnrThreshold[][5] = {
{ 34.0, 35.0, 35.0, 35.0, 35.0 }, { 33.0, 34.0, 34.0, 34.0, 34.0 },
{ 32.0, 33.0, 33.0, 33.0, 33.0 }, { 31.0, 32.0, 32.0, 32.0, 32.0 },
{ 30.0, 31.0, 31.0, 31.0, 31.0 }, { 29.0, 30.0, 30.0, 30.0, 30.0 },
#endif // CONFIG_HIGHBITDEPTH && CONFIG_AV1_ENCODER
#endif // CONFIG_AV1_ENCODER
};
typedef struct {
@ -53,24 +53,20 @@ typedef struct {
const TestVideoParam kTestVectors[] = {
{ "park_joy_90p_8_420.y4m", 8, AOM_IMG_FMT_I420, AOM_BITS_8, 0 },
{ "park_joy_90p_8_422.y4m", 8, AOM_IMG_FMT_I422, AOM_BITS_8, 1 },
{ "park_joy_90p_8_422.y4m", 8, AOM_IMG_FMT_I422, AOM_BITS_8, 2 },
{ "park_joy_90p_8_444.y4m", 8, AOM_IMG_FMT_I444, AOM_BITS_8, 1 },
{ "park_joy_90p_8_440.yuv", 8, AOM_IMG_FMT_I440, AOM_BITS_8, 1 },
#if CONFIG_HIGHBITDEPTH
{ "park_joy_90p_10_420.y4m", 10, AOM_IMG_FMT_I42016, AOM_BITS_10, 2 },
{ "park_joy_90p_10_422.y4m", 10, AOM_IMG_FMT_I42216, AOM_BITS_10, 3 },
{ "park_joy_90p_10_444.y4m", 10, AOM_IMG_FMT_I44416, AOM_BITS_10, 3 },
{ "park_joy_90p_10_440.yuv", 10, AOM_IMG_FMT_I44016, AOM_BITS_10, 3 },
{ "park_joy_90p_10_420.y4m", 10, AOM_IMG_FMT_I42016, AOM_BITS_10, 0 },
{ "park_joy_90p_10_422.y4m", 10, AOM_IMG_FMT_I42216, AOM_BITS_10, 2 },
{ "park_joy_90p_10_444.y4m", 10, AOM_IMG_FMT_I44416, AOM_BITS_10, 1 },
{ "park_joy_90p_12_420.y4m", 12, AOM_IMG_FMT_I42016, AOM_BITS_12, 2 },
{ "park_joy_90p_12_422.y4m", 12, AOM_IMG_FMT_I42216, AOM_BITS_12, 3 },
{ "park_joy_90p_12_444.y4m", 12, AOM_IMG_FMT_I44416, AOM_BITS_12, 3 },
{ "park_joy_90p_12_440.yuv", 12, AOM_IMG_FMT_I44016, AOM_BITS_12, 3 },
#endif // CONFIG_HIGHBITDEPTH
{ "park_joy_90p_12_422.y4m", 12, AOM_IMG_FMT_I42216, AOM_BITS_12, 2 },
{ "park_joy_90p_12_444.y4m", 12, AOM_IMG_FMT_I44416, AOM_BITS_12, 2 },
};
// Encoding modes tested
const libaom_test::TestMode kEncodingModeVectors[] = {
::libaom_test::kTwoPassGood, ::libaom_test::kOnePassGood,
::libaom_test::kTwoPassGood,
::libaom_test::kOnePassGood,
::libaom_test::kRealTime,
};
@ -150,6 +146,32 @@ class EndToEndTest
return kPsnrThreshold[cpu_used_][encoding_mode_];
}
void DoTest() {
cfg_.rc_target_bitrate = kBitrate;
cfg_.g_error_resilient = 0;
cfg_.g_profile = test_video_param_.profile;
cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
cfg_.g_bit_depth = test_video_param_.bit_depth;
init_flags_ = AOM_CODEC_USE_PSNR;
if (cfg_.g_bit_depth > 8) init_flags_ |= AOM_CODEC_USE_HIGHBITDEPTH;
testing::internal::scoped_ptr<libaom_test::VideoSource> video;
if (is_extension_y4m(test_video_param_.filename)) {
video.reset(new libaom_test::Y4mVideoSource(test_video_param_.filename, 0,
kFrames));
} else {
video.reset(new libaom_test::YUVVideoSource(
test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
kFramerate, 1, 0, kFrames));
}
ASSERT_TRUE(video.get() != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
const double psnr = GetAveragePsnr();
EXPECT_GT(psnr, GetPsnrThreshold())
<< "cpu used = " << cpu_used_ << ", encoding mode = " << encoding_mode_;
}
TestVideoParam test_video_param_;
int cpu_used_;
@ -161,55 +183,9 @@ class EndToEndTest
class EndToEndTestLarge : public EndToEndTest {};
TEST_P(EndToEndTestLarge, EndtoEndPSNRTest) {
cfg_.rc_target_bitrate = kBitrate;
cfg_.g_error_resilient = 0;
cfg_.g_profile = test_video_param_.profile;
cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
cfg_.g_bit_depth = test_video_param_.bit_depth;
init_flags_ = AOM_CODEC_USE_PSNR;
if (cfg_.g_bit_depth > 8) init_flags_ |= AOM_CODEC_USE_HIGHBITDEPTH;
TEST_P(EndToEndTestLarge, EndtoEndPSNRTest) { DoTest(); }
testing::internal::scoped_ptr<libaom_test::VideoSource> video;
if (is_extension_y4m(test_video_param_.filename)) {
video.reset(new libaom_test::Y4mVideoSource(test_video_param_.filename, 0,
kFrames));
} else {
video.reset(new libaom_test::YUVVideoSource(
test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
kFramerate, 1, 0, kFrames));
}
ASSERT_TRUE(video.get() != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
const double psnr = GetAveragePsnr();
EXPECT_GT(psnr, GetPsnrThreshold());
}
TEST_P(EndToEndTest, EndtoEndPSNRTest) {
cfg_.rc_target_bitrate = kBitrate;
cfg_.g_error_resilient = 0;
cfg_.g_profile = test_video_param_.profile;
cfg_.g_input_bit_depth = test_video_param_.input_bit_depth;
cfg_.g_bit_depth = test_video_param_.bit_depth;
init_flags_ = AOM_CODEC_USE_PSNR;
if (cfg_.g_bit_depth > 8) init_flags_ |= AOM_CODEC_USE_HIGHBITDEPTH;
testing::internal::scoped_ptr<libaom_test::VideoSource> video;
if (is_extension_y4m(test_video_param_.filename)) {
video.reset(new libaom_test::Y4mVideoSource(test_video_param_.filename, 0,
kFrames));
} else {
video.reset(new libaom_test::YUVVideoSource(
test_video_param_.filename, test_video_param_.fmt, kWidth, kHeight,
kFramerate, 1, 0, kFrames));
}
ASSERT_TRUE(video.get() != NULL);
ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
const double psnr = GetAveragePsnr();
EXPECT_GT(psnr, GetPsnrThreshold());
}
TEST_P(EndToEndTest, EndtoEndPSNRTest) { DoTest(); }
AV1_INSTANTIATE_TEST_CASE(EndToEndTestLarge,
::testing::ValuesIn(kEncodingModeVectors),

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <cmath>
#include <cstdlib>
@ -15,8 +15,9 @@
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./aom_config.h"
#include "./av1_rtcd.h"
#include "config/aom_config.h"
#include "config/av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
@ -28,14 +29,13 @@
using libaom_test::ACMRandom;
namespace {
#if CONFIG_HIGHBITDEPTH
const int kNumIterations = 1000;
typedef int64_t (*ErrorBlockFunc)(const tran_low_t *coeff,
const tran_low_t *dqcoeff,
intptr_t block_size, int64_t *ssz, int bps);
typedef std::tr1::tuple<ErrorBlockFunc, ErrorBlockFunc, aom_bit_depth_t>
typedef ::testing::tuple<ErrorBlockFunc, ErrorBlockFunc, aom_bit_depth_t>
ErrorBlockParam;
class ErrorBlockTest : public ::testing::TestWithParam<ErrorBlockParam> {
@ -156,8 +156,8 @@ TEST_P(ErrorBlockTest, ExtremeValues) {
<< "First failed at test case " << first_failure;
}
#if HAVE_SSE2 || HAVE_AVX
using std::tr1::make_tuple;
#if (HAVE_SSE2 || HAVE_AVX)
using ::testing::make_tuple;
INSTANTIATE_TEST_CASE_P(
SSE2, ErrorBlockTest,
@ -168,6 +168,4 @@ INSTANTIATE_TEST_CASE_P(
make_tuple(&av1_highbd_block_error_sse2,
&av1_highbd_block_error_c, AOM_BITS_8)));
#endif // HAVE_SSE2
#endif // CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"
@ -18,7 +18,13 @@
namespace {
const int kMaxErrorFrames = 12;
const int kMaxInvisibleErrorFrames = 12;
const int kMaxDroppableFrames = 12;
const int kMaxErrorResilientFrames = 12;
const int kMaxNoMFMVFrames = 12;
const int kMaxPrimRefNoneFrames = 12;
const int kMaxSFrames = 12;
const int kCpuUsed = 1;
class ErrorResilienceTestLarge
: public ::libaom_test::CodecTestWithParam<libaom_test::TestMode>,
@ -26,7 +32,7 @@ class ErrorResilienceTestLarge
protected:
ErrorResilienceTestLarge()
: EncoderTest(GET_PARAM(0)), psnr_(0.0), nframes_(0), mismatch_psnr_(0.0),
mismatch_nframes_(0), encoding_mode_(GET_PARAM(1)) {
mismatch_nframes_(0), encoding_mode_(GET_PARAM(1)), allow_mismatch_(0) {
Reset();
}
@ -34,8 +40,21 @@ class ErrorResilienceTestLarge
void Reset() {
error_nframes_ = 0;
invisible_error_nframes_ = 0;
droppable_nframes_ = 0;
pattern_switch_ = 0;
error_resilient_nframes_ = 0;
nomfmv_nframes_ = 0;
prim_ref_none_nframes_ = 0;
s_nframes_ = 0;
}
void SetupEncoder(int bitrate, int lag) {
const aom_rational timebase = { 33333333, 1000000000 };
cfg_.g_timebase = timebase;
cfg_.rc_target_bitrate = bitrate;
cfg_.kf_mode = AOM_KF_DISABLED;
cfg_.g_lag_in_frames = lag;
init_flags_ = AOM_CODEC_USE_PSNR;
}
virtual void SetUp() {
@ -46,6 +65,7 @@ class ErrorResilienceTestLarge
virtual void BeginPassHook(unsigned int /*pass*/) {
psnr_ = 0.0;
nframes_ = 0;
decoded_nframes_ = 0;
mismatch_psnr_ = 0.0;
mismatch_nframes_ = 0;
}
@ -55,18 +75,71 @@ class ErrorResilienceTestLarge
nframes_++;
}
virtual void PreEncodeFrameHook(libaom_test::VideoSource *video) {
virtual void PreEncodeFrameHook(libaom_test::VideoSource *video,
libaom_test::Encoder *encoder) {
if (video->frame() == 0) encoder->Control(AOME_SET_CPUUSED, kCpuUsed);
frame_flags_ &=
~(AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF);
~(AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF |
AOM_EFLAG_NO_REF_FRAME_MVS | AOM_EFLAG_ERROR_RESILIENT |
AOM_EFLAG_SET_S_FRAME | AOM_EFLAG_SET_PRIMARY_REF_NONE);
if (droppable_nframes_ > 0 &&
(cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_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";
std::cout << " Encoding droppable frame: "
<< droppable_frames_[i] << "\n";
frame_flags_ |= (AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
AOM_EFLAG_NO_UPD_ARF);
return;
break;
}
}
}
if (error_resilient_nframes_ > 0 &&
(cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
for (unsigned int i = 0; i < error_resilient_nframes_; ++i) {
if (error_resilient_frames_[i] == video->frame()) {
std::cout << " Encoding error_resilient frame: "
<< error_resilient_frames_[i] << "\n";
frame_flags_ |= AOM_EFLAG_ERROR_RESILIENT;
break;
}
}
}
if (nomfmv_nframes_ > 0 &&
(cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
for (unsigned int i = 0; i < nomfmv_nframes_; ++i) {
if (nomfmv_frames_[i] == video->frame()) {
std::cout << " Encoding no mfmv frame: "
<< nomfmv_frames_[i] << "\n";
frame_flags_ |= AOM_EFLAG_NO_REF_FRAME_MVS;
break;
}
}
}
if (prim_ref_none_nframes_ > 0 &&
(cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
for (unsigned int i = 0; i < prim_ref_none_nframes_; ++i) {
if (prim_ref_none_frames_[i] == video->frame()) {
std::cout << " Encoding no PRIMARY_REF_NONE frame: "
<< prim_ref_none_frames_[i] << "\n";
frame_flags_ |= AOM_EFLAG_SET_PRIMARY_REF_NONE;
break;
}
}
}
encoder->Control(AV1E_SET_S_FRAME_MODE, 0);
if (s_nframes_ > 0 &&
(cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
for (unsigned int i = 0; i < s_nframes_; ++i) {
if (s_frames_[i] == video->frame()) {
std::cout << " Encoding S frame: " << s_frames_[i]
<< "\n";
frame_flags_ |= AOM_EFLAG_SET_S_FRAME;
break;
}
}
}
@ -96,12 +169,37 @@ class ErrorResilienceTestLarge
return 1;
}
virtual bool DoDecodeInvisible() const {
if (invisible_error_nframes_ > 0 &&
(cfg_.g_pass == AOM_RC_LAST_PASS || cfg_.g_pass == AOM_RC_ONE_PASS)) {
for (unsigned int i = 0; i < invisible_error_nframes_; ++i) {
if (invisible_error_frames_[i] == nframes_ - 1) {
std::cout << " Skipping decoding all invisible frames in "
"frame pkt: "
<< invisible_error_frames_[i] << "\n";
return 0;
}
}
}
return 1;
}
virtual void MismatchHook(const aom_image_t *img1, const aom_image_t *img2) {
double mismatch_psnr = compute_psnr(img1, img2);
mismatch_psnr_ += mismatch_psnr;
++mismatch_nframes_;
// std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
::libaom_test::EncoderTest::MismatchHook(img1, img2);
if (allow_mismatch_) {
double mismatch_psnr = compute_psnr(img1, img2);
mismatch_psnr_ += mismatch_psnr;
++mismatch_nframes_;
// std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
} else {
::libaom_test::EncoderTest::MismatchHook(img1, img2);
}
}
virtual void DecompressedFrameHook(const aom_image_t &img,
aom_codec_pts_t pts) {
(void)img;
(void)pts;
++decoded_nframes_;
}
void SetErrorFrames(int num, unsigned int *list) {
@ -114,6 +212,16 @@ class ErrorResilienceTestLarge
error_frames_[i] = list[i];
}
void SetInvisibleErrorFrames(int num, unsigned int *list) {
if (num > kMaxInvisibleErrorFrames)
num = kMaxInvisibleErrorFrames;
else if (num < 0)
num = 0;
invisible_error_nframes_ = num;
for (unsigned int i = 0; i < invisible_error_nframes_; ++i)
invisible_error_frames_[i] = list[i];
}
void SetDroppableFrames(int num, unsigned int *list) {
if (num > kMaxDroppableFrames)
num = kMaxDroppableFrames;
@ -124,42 +232,93 @@ class ErrorResilienceTestLarge
droppable_frames_[i] = list[i];
}
unsigned int GetMismatchFrames() { return mismatch_nframes_; }
void SetErrorResilientFrames(int num, unsigned int *list) {
if (num > kMaxErrorResilientFrames)
num = kMaxErrorResilientFrames;
else if (num < 0)
num = 0;
error_resilient_nframes_ = num;
for (unsigned int i = 0; i < error_resilient_nframes_; ++i)
error_resilient_frames_[i] = list[i];
}
void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
void SetNoMFMVFrames(int num, unsigned int *list) {
if (num > kMaxNoMFMVFrames)
num = kMaxNoMFMVFrames;
else if (num < 0)
num = 0;
nomfmv_nframes_ = num;
for (unsigned int i = 0; i < nomfmv_nframes_; ++i)
nomfmv_frames_[i] = list[i];
}
void SetPrimaryRefNoneFrames(int num, unsigned int *list) {
if (num > kMaxPrimRefNoneFrames)
num = kMaxPrimRefNoneFrames;
else if (num < 0)
num = 0;
prim_ref_none_nframes_ = num;
for (unsigned int i = 0; i < prim_ref_none_nframes_; ++i)
prim_ref_none_frames_[i] = list[i];
}
void SetSFrames(int num, unsigned int *list) {
if (num > kMaxSFrames)
num = kMaxSFrames;
else if (num < 0)
num = 0;
s_nframes_ = num;
for (unsigned int i = 0; i < s_nframes_; ++i) s_frames_[i] = list[i];
}
unsigned int GetMismatchFrames() { return mismatch_nframes_; }
unsigned int GetEncodedFrames() { return nframes_; }
unsigned int GetDecodedFrames() { return decoded_nframes_; }
void SetAllowMismatch(int allow) { allow_mismatch_ = allow; }
private:
double psnr_;
unsigned int nframes_;
unsigned int decoded_nframes_;
unsigned int error_nframes_;
unsigned int invisible_error_nframes_;
unsigned int droppable_nframes_;
unsigned int pattern_switch_;
unsigned int error_resilient_nframes_;
unsigned int nomfmv_nframes_;
unsigned int prim_ref_none_nframes_;
unsigned int s_nframes_;
double mismatch_psnr_;
unsigned int mismatch_nframes_;
unsigned int error_frames_[kMaxErrorFrames];
unsigned int invisible_error_frames_[kMaxInvisibleErrorFrames];
unsigned int droppable_frames_[kMaxDroppableFrames];
unsigned int error_resilient_frames_[kMaxErrorResilientFrames];
unsigned int nomfmv_frames_[kMaxNoMFMVFrames];
unsigned int prim_ref_none_frames_[kMaxPrimRefNoneFrames];
unsigned int s_frames_[kMaxSFrames];
libaom_test::TestMode encoding_mode_;
int allow_mismatch_;
};
TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
const aom_rational timebase = { 33333333, 1000000000 };
cfg_.g_timebase = timebase;
cfg_.rc_target_bitrate = 2000;
cfg_.g_lag_in_frames = 10;
init_flags_ = AOM_CODEC_USE_PSNR;
SetupEncoder(2000, 10);
libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
timebase.den, timebase.num, 0, 12);
cfg_.g_timebase.den, cfg_.g_timebase.num,
0, 12);
// Error resilient mode OFF.
// Global 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;
Reset();
// Error resilient mode ON for certain frames
unsigned int num_error_resilient_frames = 5;
unsigned int error_resilient_frame_list[] = { 3, 5, 6, 9, 11 };
SetErrorResilientFrames(num_error_resilient_frames,
error_resilient_frame_list);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
const double psnr_resilience_on = GetAveragePsnr();
EXPECT_GT(psnr_resilience_on, 25.0);
@ -175,60 +334,105 @@ TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
// 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 aom_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_ = AOM_CODEC_USE_PSNR;
SetupEncoder(500, 10);
libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
timebase.den, timebase.num, 0, 20);
// Error resilient mode ON.
cfg_.g_error_resilient = 1;
cfg_.kf_mode = AOM_KF_DISABLED;
cfg_.g_timebase.den, cfg_.g_timebase.num,
0, 20);
// 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 = 5;
unsigned int droppable_frame_list[] = { 5, 10, 13, 16, 19 };
unsigned int num_droppable_frames = 3;
unsigned int droppable_frame_list[] = { 5, 10, 13 };
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 << " Encoded frames: " << GetEncodedFrames() << "\n";
std::cout << " Decoded frames: " << GetDecodedFrames() << "\n";
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
EXPECT_EQ(GetEncodedFrames() - GetDecodedFrames(), num_droppable_frames);
}
AV1_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES);
// Check for ParseAbility property of an error-resilient frame.
// Encode a frame in error-resilient mode (E-frame), and disallow all
// subsequent frames from using MFMV. If frames are dropped before the
// E frame, all frames starting from the E frame should be parse-able.
TEST_P(ErrorResilienceTestLarge, ParseAbilityTest) {
SetupEncoder(500, 10);
libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
cfg_.g_timebase.den, cfg_.g_timebase.num,
0, 15);
SetAllowMismatch(1);
// Note that an E-frame cannot be forced on a frame that is a
// show_existing_frame, or a frame that comes directly after an invisible
// frame. Currently, this will cause an assertion failure.
// Set an arbitrary error resilient (E) frame
unsigned int num_error_resilient_frames = 1;
unsigned int error_resilient_frame_list[] = { 8 };
SetErrorResilientFrames(num_error_resilient_frames,
error_resilient_frame_list);
// Ensure that any invisible frames before the E frame are dropped
SetInvisibleErrorFrames(num_error_resilient_frames,
error_resilient_frame_list);
// Set all frames after the error resilient frame to not allow MFMV
unsigned int num_post_error_resilient_frames = 6;
unsigned int post_error_resilient_frame_list[] = { 9, 10, 11, 12, 13, 14 };
SetNoMFMVFrames(num_post_error_resilient_frames,
post_error_resilient_frame_list);
// Set a few frames before the E frame that are lost (not decoded)
unsigned int num_error_frames = 5;
unsigned int error_frame_list[] = { 3, 4, 5, 6, 7 };
SetErrorFrames(num_error_frames, error_frame_list);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
std::cout << " Encoded frames: " << GetEncodedFrames() << "\n";
std::cout << " Decoded frames: " << GetDecodedFrames() << "\n";
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
EXPECT_EQ(GetEncodedFrames() - GetDecodedFrames(), num_error_frames);
// All frames following the E-frame and the E-frame are expected to have
// mismatches, but still be parse-able.
EXPECT_LE(GetMismatchFrames(), num_post_error_resilient_frames + 1);
}
// Check for ParseAbility property of an S frame.
// Encode an S-frame. If frames are dropped before the S-frame, all frames
// starting from the S frame should be parse-able.
TEST_P(ErrorResilienceTestLarge, SFrameTest) {
SetupEncoder(500, 10);
libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
cfg_.g_timebase.den, cfg_.g_timebase.num,
0, 15);
SetAllowMismatch(1);
// Note that an S-frame cannot be forced on a frame that is a
// show_existing_frame. This issue still needs to be addressed.
// Set an arbitrary S-frame
unsigned int num_s_frames = 1;
unsigned int s_frame_list[] = { 6 };
SetSFrames(num_s_frames, s_frame_list);
// Ensure that any invisible frames before the S frame are dropped
SetInvisibleErrorFrames(num_s_frames, s_frame_list);
// Set a few frames before the S frame that are lost (not decoded)
unsigned int num_error_frames = 4;
unsigned int error_frame_list[] = { 2, 3, 4, 5 };
SetErrorFrames(num_error_frames, error_frame_list);
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
std::cout << " Encoded frames: " << GetEncodedFrames() << "\n";
std::cout << " Decoded frames: " << GetDecodedFrames() << "\n";
std::cout << " Mismatch frames: " << GetMismatchFrames() << "\n";
EXPECT_EQ(GetEncodedFrames() - GetDecodedFrames(), num_error_frames);
// All frames following the S-frame and the S-frame are expected to have
// mismatches, but still be parse-able.
EXPECT_LE(GetMismatchFrames(), GetEncodedFrames() - s_frame_list[0]);
}
AV1_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, NONREALTIME_TEST_MODES);
} // namespace

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include <string>
#include <vector>
@ -16,7 +16,7 @@
#include "test/encode_test_driver.h"
#include "test/md5_helper.h"
#include "test/util.h"
#include "test/y4m_video_source.h"
#include "test/yuv_video_source.h"
namespace {
class AVxEncoderThreadTest
@ -32,12 +32,10 @@ class AVxEncoderThreadTest
cfg.h = 720;
cfg.allow_lowbitdepth = 1;
decoder_ = codec_->CreateDecoder(cfg, 0);
#if CONFIG_AV1
if (decoder_->IsAV1()) {
decoder_->Control(AV1_SET_DECODE_TILE_ROW, -1);
decoder_->Control(AV1_SET_DECODE_TILE_COL, -1);
}
#endif
size_enc_.clear();
md5_dec_.clear();
@ -71,9 +69,6 @@ class AVxEncoderThreadTest
::libaom_test::Encoder *encoder) {
if (!encoder_initialized_) {
SetTileSize(encoder);
#if CONFIG_LOOPFILTERING_ACROSS_TILES
encoder->Control(AV1E_SET_TILE_LOOPFILTER, 0);
#endif // CONFIG_LOOPFILTERING_ACROSS_TILES
encoder->Control(AOME_SET_CPUUSED, set_cpu_used_);
if (encoding_mode_ != ::libaom_test::kRealTime) {
encoder->Control(AOME_SET_ENABLEAUTOALTREF, 1);
@ -118,7 +113,8 @@ class AVxEncoderThreadTest
}
void DoTest() {
::libaom_test::Y4mVideoSource video("niklas_1280_720_30.y4m", 15, 18);
::libaom_test::YUVVideoSource video(
"niklas_640_480_30.yuv", AOM_IMG_FMT_I420, 640, 480, 30, 1, 15, 18);
cfg_.rc_target_bitrate = 1000;
// Encode using single thread.
@ -164,18 +160,16 @@ class AVxEncoderThreadTest
};
TEST_P(AVxEncoderThreadTest, EncoderResultTest) {
#if CONFIG_AV1 && CONFIG_EXT_TILE
cfg_.large_scale_tile = 0;
#endif // CONFIG_AV1 && CONFIG_EXT_TILE
decoder_->Control(AV1_SET_TILE_MODE, 0);
DoTest();
}
class AVxEncoderThreadTestLarge : public AVxEncoderThreadTest {};
TEST_P(AVxEncoderThreadTestLarge, EncoderResultTest) {
#if CONFIG_AV1 && CONFIG_EXT_TILE
cfg_.large_scale_tile = 0;
#endif // CONFIG_AV1 && CONFIG_EXT_TILE
decoder_->Control(AV1_SET_TILE_MODE, 0);
DoTest();
}
@ -190,7 +184,6 @@ AV1_INSTANTIATE_TEST_CASE(AVxEncoderThreadTestLarge,
::libaom_test::kOnePassGood),
::testing::Range(0, 2));
#if CONFIG_AV1 && CONFIG_EXT_TILE
class AVxEncoderThreadLSTest : public AVxEncoderThreadTest {
virtual void SetTileSize(libaom_test::Encoder *encoder) {
encoder->Control(AV1E_SET_TILE_COLUMNS, 1);
@ -200,15 +193,17 @@ class AVxEncoderThreadLSTest : public AVxEncoderThreadTest {
}
};
TEST_P(AVxEncoderThreadLSTest, EncoderResultTest) {
TEST_P(AVxEncoderThreadLSTest, DISABLED_EncoderResultTest) {
cfg_.large_scale_tile = 1;
decoder_->Control(AV1_SET_TILE_MODE, 1);
DoTest();
}
class AVxEncoderThreadLSTestLarge : public AVxEncoderThreadLSTest {};
TEST_P(AVxEncoderThreadLSTestLarge, EncoderResultTest) {
TEST_P(AVxEncoderThreadLSTestLarge, DISABLED_EncoderResultTest) {
cfg_.large_scale_tile = 1;
decoder_->Control(AV1_SET_TILE_MODE, 1);
DoTest();
}
@ -220,5 +215,4 @@ AV1_INSTANTIATE_TEST_CASE(AVxEncoderThreadLSTestLarge,
::testing::Values(::libaom_test::kTwoPassGood,
::libaom_test::kOnePassGood),
::testing::Range(0, 2));
#endif // CONFIG_AV1 && CONFIG_EXT_TILE
} // namespace

View file

@ -12,10 +12,10 @@
##
. $(dirname $0)/tools_common.sh
example_tests=$(ls $(dirname $0)/*.sh)
example_tests=$(ls -r $(dirname $0)/*.sh)
# List of script names to exclude.
exclude_list="examples tools_common decode_to_md5"
exclude_list="best_encode examples run_encodes tools_common"
# Filter out the scripts in $exclude_list.
for word in ${exclude_list}; do

View file

@ -1,350 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#include "av1/common/entropy.h"
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
#include "aom_ports/mem.h"
using libaom_test::ACMRandom;
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 (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
using libaom_test::FhtFunc;
typedef std::tr1::tuple<FdctFunc, IdctFunc, TX_TYPE, aom_bit_depth_t, int>
Dct4x4Param;
typedef std::tr1::tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t, int>
Ht4x4Param;
void fdct4x4_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam * /*txfm_param*/) {
aom_fdct4x4_c(in, out, stride);
}
void fht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht4x4_c(in, out, stride, txfm_param);
}
void fwht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam * /*txfm_param*/) {
av1_fwht4x4_c(in, out, stride);
}
#if CONFIG_HIGHBITDEPTH
void fht4x4_10(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fwd_txfm2d_4x4_c(in, out, stride, txfm_param->tx_type, 10);
}
void fht4x4_12(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fwd_txfm2d_4x4_c(in, out, stride, txfm_param->tx_type, 12);
}
void iht4x4_10(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_inv_txfm2d_add_4x4_c(in, CONVERT_TO_SHORTPTR(out), stride,
txfm_param->tx_type, 10);
}
void iht4x4_12(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_inv_txfm2d_add_4x4_c(in, CONVERT_TO_SHORTPTR(out), stride,
txfm_param->tx_type, 12);
}
void iwht4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
aom_highbd_iwht4x4_16_add_c(in, out, stride, 10);
}
void iwht4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
aom_highbd_iwht4x4_16_add_c(in, out, stride, 12);
}
#endif // CONFIG_HIGHBITDEPTH
class Trans4x4DCT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Dct4x4Param> {
public:
virtual ~Trans4x4DCT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 4;
height_ = 4;
fwd_txfm_ref = fdct4x4_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride);
}
FdctFunc fwd_txfm_;
IdctFunc inv_txfm_;
};
TEST_P(Trans4x4DCT, AccuracyCheck) { RunAccuracyCheck(0, 0.00001); }
TEST_P(Trans4x4DCT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(Trans4x4DCT, MemCheck) { RunMemCheck(); }
TEST_P(Trans4x4DCT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
class Trans4x4HT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Ht4x4Param> {
public:
virtual ~Trans4x4HT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 4;
height_ = 4;
fwd_txfm_ref = fht4x4_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
txfm_param_.tx_type = GET_PARAM(2);
#if CONFIG_HIGHBITDEPTH
switch (bit_depth_) {
case AOM_BITS_10: fwd_txfm_ref = fht4x4_10; break;
case AOM_BITS_12: fwd_txfm_ref = fht4x4_12; break;
default: fwd_txfm_ref = fht4x4_ref; break;
}
#endif
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
FhtFunc fwd_txfm_;
IhtFunc inv_txfm_;
};
TEST_P(Trans4x4HT, AccuracyCheck) { RunAccuracyCheck(1, 0.005); }
TEST_P(Trans4x4HT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(Trans4x4HT, MemCheck) { RunMemCheck(); }
TEST_P(Trans4x4HT, InvAccuracyCheck) { RunInvAccuracyCheck(1); }
class Trans4x4WHT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Dct4x4Param> {
public:
virtual ~Trans4x4WHT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 4;
height_ = 4;
fwd_txfm_ref = fwht4x4_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride);
}
FdctFunc fwd_txfm_;
IdctFunc inv_txfm_;
};
TEST_P(Trans4x4WHT, AccuracyCheck) { RunAccuracyCheck(0, 0.00001); }
TEST_P(Trans4x4WHT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(Trans4x4WHT, MemCheck) { RunMemCheck(); }
TEST_P(Trans4x4WHT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
using std::tr1::make_tuple;
INSTANTIATE_TEST_CASE_P(C, Trans4x4DCT,
::testing::Values(make_tuple(&aom_fdct4x4_c,
&aom_idct4x4_16_add_c,
DCT_DCT, AOM_BITS_8, 16)));
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
DISABLED_C, Trans4x4HT,
::testing::Values(
make_tuple(&fht4x4_12, &iht4x4_12, DCT_DCT, AOM_BITS_12, 16),
make_tuple(&fht4x4_12, &iht4x4_12, ADST_DCT, AOM_BITS_12, 16),
make_tuple(&fht4x4_12, &iht4x4_12, DCT_ADST, AOM_BITS_12, 16),
make_tuple(&fht4x4_12, &iht4x4_12, ADST_ADST, AOM_BITS_12, 16)));
INSTANTIATE_TEST_CASE_P(
C, Trans4x4HT,
::testing::Values(
make_tuple(&fht4x4_10, &iht4x4_10, DCT_DCT, AOM_BITS_10, 16),
make_tuple(&fht4x4_10, &iht4x4_10, ADST_DCT, AOM_BITS_10, 16),
make_tuple(&fht4x4_10, &iht4x4_10, DCT_ADST, AOM_BITS_10, 16),
make_tuple(&fht4x4_10, &iht4x4_10, ADST_ADST, AOM_BITS_10, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, DCT_DCT, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, ADST_DCT, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, DCT_ADST, AOM_BITS_8,
16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, ADST_ADST, AOM_BITS_8,
16)));
#else
INSTANTIATE_TEST_CASE_P(
C, Trans4x4HT,
::testing::Values(make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, DCT_DCT,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, ADST_DCT,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, DCT_ADST,
AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_c, ADST_ADST,
AOM_BITS_8, 16)));
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
C, Trans4x4WHT,
::testing::Values(make_tuple(&av1_highbd_fwht4x4_c, &iwht4x4_10, DCT_DCT,
AOM_BITS_10, 16),
make_tuple(&av1_highbd_fwht4x4_c, &iwht4x4_12, DCT_DCT,
AOM_BITS_12, 16),
make_tuple(&av1_fwht4x4_c, &aom_iwht4x4_16_add_c, DCT_DCT,
AOM_BITS_8, 16)));
#else
INSTANTIATE_TEST_CASE_P(C, Trans4x4WHT,
::testing::Values(make_tuple(&av1_fwht4x4_c,
&aom_iwht4x4_16_add_c,
DCT_DCT, AOM_BITS_8, 16)));
#endif // CONFIG_HIGHBITDEPTH
#if HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(NEON, Trans4x4DCT,
::testing::Values(make_tuple(&aom_fdct4x4_c,
&aom_idct4x4_16_add_neon,
DCT_DCT, AOM_BITS_8, 16)));
#endif // HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
#if HAVE_NEON && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
NEON, Trans4x4HT,
::testing::Values(make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_neon,
DCT_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_neon,
ADST_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_neon,
DCT_ADST, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_c, &av1_iht4x4_16_add_neon,
ADST_ADST, AOM_BITS_8, 16)));
#endif // HAVE_NEON && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && !CONFIG_DAALA_DCT4
INSTANTIATE_TEST_CASE_P(
SSE2, Trans4x4WHT,
::testing::Values(make_tuple(&av1_fwht4x4_c, &aom_iwht4x4_16_add_c, DCT_DCT,
AOM_BITS_8, 16),
make_tuple(&av1_fwht4x4_c, &aom_iwht4x4_16_add_sse2,
DCT_DCT, AOM_BITS_8, 16)));
#endif
#if HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(SSE2, Trans4x4DCT,
::testing::Values(make_tuple(&aom_fdct4x4_sse2,
&aom_idct4x4_16_add_sse2,
DCT_DCT, AOM_BITS_8, 16)));
#if !CONFIG_DAALA_DCT4
INSTANTIATE_TEST_CASE_P(
SSE2, Trans4x4HT,
::testing::Values(make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2,
DCT_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2,
ADST_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2,
DCT_ADST, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_sse2,
ADST_ADST, AOM_BITS_8, 16)));
#endif // !CONFIG_DAALA_DCT4
#endif // HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT4
INSTANTIATE_TEST_CASE_P(
SSE2, Trans4x4HT,
::testing::Values(make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_c,
DCT_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_c,
ADST_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_c,
DCT_ADST, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_sse2, &av1_iht4x4_16_add_c,
ADST_ADST, AOM_BITS_8, 16)));
#endif // HAVE_SSE2 && CONFIG_HIGHBITDEPTH && !CONFIG_DAALA_DCT4
#if HAVE_MSA && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(MSA, Trans4x4DCT,
::testing::Values(make_tuple(&aom_fdct4x4_msa,
&aom_idct4x4_16_add_msa,
DCT_DCT, AOM_BITS_8, 16)));
#if !CONFIG_EXT_TX && !CONFIG_DAALA_DCT4
INSTANTIATE_TEST_CASE_P(
MSA, Trans4x4HT,
::testing::Values(make_tuple(&av1_fht4x4_msa, &av1_iht4x4_16_add_msa,
DCT_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_msa, &av1_iht4x4_16_add_msa,
ADST_DCT, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_msa, &av1_iht4x4_16_add_msa,
DCT_ADST, AOM_BITS_8, 16),
make_tuple(&av1_fht4x4_msa, &av1_iht4x4_16_add_msa,
ADST_ADST, AOM_BITS_8, 16)));
#endif // !CONFIG_EXT_TX && && !CONFIG_DAALA_DCT4
#endif // HAVE_MSA && !CONFIG_HIGHBITDEPTH
} // namespace

View file

@ -1,738 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "./aom_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 "av1/common/entropy.h"
#include "av1/common/scan.h"
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
#include "aom_ports/mem.h"
using libaom_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,
TxfmParam *txfm_param);
typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param);
typedef std::tr1::tuple<FdctFunc, IdctFunc, TX_TYPE, aom_bit_depth_t>
Dct8x8Param;
typedef std::tr1::tuple<FhtFunc, IhtFunc, TX_TYPE, aom_bit_depth_t> Ht8x8Param;
typedef std::tr1::tuple<IdctFunc, IdctFunc, int, aom_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,
TxfmParam * /*txfm_param*/) {
aom_fdct8x8_c(in, out, stride);
}
void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fht8x8_c(in, out, stride, txfm_param);
}
#if CONFIG_HIGHBITDEPTH
void fht8x8_10(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fwd_txfm2d_8x8_c(in, out, stride, txfm_param->tx_type, 10);
}
void fht8x8_12(const int16_t *in, tran_low_t *out, int stride,
TxfmParam *txfm_param) {
av1_fwd_txfm2d_8x8_c(in, out, stride, txfm_param->tx_type, 12);
}
void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_inv_txfm2d_add_8x8_c(in, CONVERT_TO_SHORTPTR(out), stride,
txfm_param->tx_type, 10);
}
void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride,
const TxfmParam *txfm_param) {
av1_inv_txfm2d_add_8x8_c(in, CONVERT_TO_SHORTPTR(out), stride,
txfm_param->tx_type, 12);
}
#endif // CONFIG_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_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_ == AOM_BITS_8) {
src[j] = rnd.Rand8();
dst[j] = rnd.Rand8();
test_input_block[j] = src[j] - dst[j];
#if CONFIG_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_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
}
for (int j = 0; j < 64; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_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_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_ == AOM_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_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_, &txfm_param_));
if (bit_depth_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
}
for (int j = 0; j < 64; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_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_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_ == AOM_BITS_8) {
src[j] = rnd.Rand8() % 2 ? 255 : 0;
dst[j] = src[j] > 0 ? 0 : 255;
in[j] = src[j] - dst[j];
#if CONFIG_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_ == AOM_BITS_8) {
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
#if CONFIG_HIGHBITDEPTH
} else {
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_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_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
#endif
const int16_t *scan = av1_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_ == AOM_BITS_8) {
dst[j] = 0;
ref[j] = 0;
#if CONFIG_HIGHBITDEPTH
} else {
dst16[j] = 0;
ref16[j] = 0;
#endif
}
}
if (bit_depth_ == AOM_BITS_8) {
ref_txfm(coeff, ref, pitch_);
ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
#if CONFIG_HIGHBITDEPTH
} else {
ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
ASM_REGISTER_STATE_CHECK(
RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_));
#endif
}
for (int j = 0; j < kNumCoeffs; ++j) {
#if CONFIG_HIGHBITDEPTH
const int diff =
bit_depth_ == AOM_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_;
FhtFunc fwd_txfm_ref;
aom_bit_depth_t bit_depth_;
int mask_;
TxfmParam txfm_param_;
};
class FwdTrans8x8DCT : public FwdTrans8x8TestBase,
public ::testing::TestWithParam<Dct8x8Param> {
public:
virtual ~FwdTrans8x8DCT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 8;
fwd_txfm_ref = fdct8x8_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
txfm_param_.tx_type = GET_PARAM(2);
}
virtual void TearDown() { libaom_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);
pitch_ = 8;
fwd_txfm_ref = fht8x8_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
txfm_param_.tx_type = GET_PARAM(2);
#if CONFIG_HIGHBITDEPTH
switch (bit_depth_) {
case AOM_BITS_10: fwd_txfm_ref = fht8x8_10; break;
case AOM_BITS_12: fwd_txfm_ref = fht8x8_12; break;
default: fwd_txfm_ref = fht8x8_ref; break;
}
#endif
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride, &txfm_param_);
}
void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride, &txfm_param_);
}
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() { libaom_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::tr1::make_tuple;
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(C, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_c,
&aom_idct8x8_64_add_c,
DCT_DCT, AOM_BITS_8)));
#else
INSTANTIATE_TEST_CASE_P(C, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_c,
&aom_idct8x8_64_add_c,
DCT_DCT, AOM_BITS_8)));
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
C, FwdTrans8x8HT,
::testing::Values(
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, DCT_DCT, AOM_BITS_8),
make_tuple(&fht8x8_10, &iht8x8_10, DCT_DCT, AOM_BITS_10),
make_tuple(&fht8x8_10, &iht8x8_10, ADST_DCT, AOM_BITS_10),
make_tuple(&fht8x8_10, &iht8x8_10, DCT_ADST, AOM_BITS_10),
make_tuple(&fht8x8_10, &iht8x8_10, ADST_ADST, AOM_BITS_10),
make_tuple(&fht8x8_12, &iht8x8_12, DCT_DCT, AOM_BITS_12),
make_tuple(&fht8x8_12, &iht8x8_12, ADST_DCT, AOM_BITS_12),
make_tuple(&fht8x8_12, &iht8x8_12, DCT_ADST, AOM_BITS_12),
make_tuple(&fht8x8_12, &iht8x8_12, ADST_ADST, AOM_BITS_12),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, ADST_ADST,
AOM_BITS_8)));
#else
INSTANTIATE_TEST_CASE_P(
C, FwdTrans8x8HT,
::testing::Values(
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_c, ADST_ADST,
AOM_BITS_8)));
#endif // CONFIG_HIGHBITDEPTH
#if HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(NEON, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_neon,
&aom_idct8x8_64_add_neon,
DCT_DCT, AOM_BITS_8)));
#endif // HAVE_NEON_ASM && !CONFIG_HIGHBITDEPTH
#if HAVE_NEON && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(
NEON, FwdTrans8x8HT,
::testing::Values(make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht8x8_c, &av1_iht8x8_64_add_neon,
ADST_ADST, AOM_BITS_8)));
#endif // HAVE_NEON && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(SSE2, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_sse2,
&aom_idct8x8_64_add_sse2,
DCT_DCT, AOM_BITS_8)));
#if !CONFIG_DAALA_DCT8
INSTANTIATE_TEST_CASE_P(
SSE2, FwdTrans8x8HT,
::testing::Values(make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_sse2,
ADST_ADST, AOM_BITS_8)));
#endif // !CONFIG_DAALA_DCT8
#endif // HAVE_SSE2 && !CONFIG_HIGHBITDEPTH
#if HAVE_SSE2 && CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(SSE2, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_sse2,
&aom_idct8x8_64_add_c,
DCT_DCT, AOM_BITS_8)));
#if !CONFIG_DAALA_DCT8
INSTANTIATE_TEST_CASE_P(
SSE2, FwdTrans8x8HT,
::testing::Values(make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht8x8_sse2, &av1_iht8x8_64_add_c,
ADST_ADST, AOM_BITS_8)));
#endif // !CONFIG_DAALA_DCT8
#endif // HAVE_SSE2 && CONFIG_HIGHBITDEPTH
#if HAVE_SSSE3 && ARCH_X86_64
INSTANTIATE_TEST_CASE_P(SSSE3, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_ssse3,
&aom_idct8x8_64_add_ssse3,
DCT_DCT, AOM_BITS_8)));
#endif
#if HAVE_MSA && !CONFIG_HIGHBITDEPTH
INSTANTIATE_TEST_CASE_P(MSA, FwdTrans8x8DCT,
::testing::Values(make_tuple(&aom_fdct8x8_msa,
&aom_idct8x8_64_add_msa,
DCT_DCT, AOM_BITS_8)));
#if !CONFIG_EXT_TX && !CONFIG_DAALA_DCT8
INSTANTIATE_TEST_CASE_P(
MSA, FwdTrans8x8HT,
::testing::Values(make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa,
DCT_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa,
ADST_DCT, AOM_BITS_8),
make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa,
DCT_ADST, AOM_BITS_8),
make_tuple(&av1_fht8x8_msa, &av1_iht8x8_64_add_msa,
ADST_ADST, AOM_BITS_8)));
#endif // !CONFIG_EXT_TX && !CONFIG_DAALA_DCT8
#endif // HAVE_MSA && !CONFIG_HIGHBITDEPTH
} // namespace

263
third_party/aom/test/fft_test.cc vendored Normal file
View file

@ -0,0 +1,263 @@
#include <math.h>
#include <algorithm>
#include <complex>
#include <vector>
#include "aom_dsp/fft_common.h"
#include "aom_mem/aom_mem.h"
#if ARCH_X86 || ARCH_X86_64
#include "aom_ports/x86.h"
#endif
#include "av1/common/common.h"
#include "config/aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
namespace {
typedef void (*tform_fun_t)(const float *input, float *temp, float *output);
// Simple 1D FFT implementation
template <typename InputType>
void fft(const InputType *data, std::complex<float> *result, int n) {
if (n == 1) {
result[0] = data[0];
return;
}
std::vector<InputType> temp(n);
for (int k = 0; k < n / 2; ++k) {
temp[k] = data[2 * k];
temp[n / 2 + k] = data[2 * k + 1];
}
fft(&temp[0], result, n / 2);
fft(&temp[n / 2], result + n / 2, n / 2);
for (int k = 0; k < n / 2; ++k) {
std::complex<float> w = std::complex<float>((float)cos(2. * PI * k / n),
(float)-sin(2. * PI * k / n));
std::complex<float> a = result[k];
std::complex<float> b = result[n / 2 + k];
result[k] = a + w * b;
result[n / 2 + k] = a - w * b;
}
}
void transpose(std::vector<std::complex<float> > *data, int n) {
for (int y = 0; y < n; ++y) {
for (int x = y + 1; x < n; ++x) {
std::swap((*data)[y * n + x], (*data)[x * n + y]);
}
}
}
// Simple 2D FFT implementation
template <class InputType>
std::vector<std::complex<float> > fft2d(const InputType *input, int n) {
std::vector<std::complex<float> > rowfft(n * n);
std::vector<std::complex<float> > result(n * n);
for (int y = 0; y < n; ++y) {
fft(input + y * n, &rowfft[y * n], n);
}
transpose(&rowfft, n);
for (int y = 0; y < n; ++y) {
fft(&rowfft[y * n], &result[y * n], n);
}
transpose(&result, n);
return result;
}
struct FFTTestArg {
int n;
void (*fft)(const float *input, float *temp, float *output);
int flag;
FFTTestArg(int n_in, tform_fun_t fft_in, int flag_in)
: n(n_in), fft(fft_in), flag(flag_in) {}
};
std::ostream &operator<<(std::ostream &os, const FFTTestArg &test_arg) {
return os << "fft_arg { n:" << test_arg.n << " fft:" << test_arg.fft
<< " flag:" << test_arg.flag << "}";
}
class FFT2DTest : public ::testing::TestWithParam<FFTTestArg> {
protected:
void SetUp() {
int n = GetParam().n;
input_ = (float *)aom_memalign(32, sizeof(*input_) * n * n);
temp_ = (float *)aom_memalign(32, sizeof(*temp_) * n * n);
output_ = (float *)aom_memalign(32, sizeof(*output_) * n * n * 2);
memset(input_, 0, sizeof(*input_) * n * n);
memset(temp_, 0, sizeof(*temp_) * n * n);
memset(output_, 0, sizeof(*output_) * n * n * 2);
#if ARCH_X86 || ARCH_X86_64
disabled_ = GetParam().flag != 0 && !(x86_simd_caps() & GetParam().flag);
#else
disabled_ = GetParam().flag != 0;
#endif
}
void TearDown() {
aom_free(input_);
aom_free(temp_);
aom_free(output_);
}
int disabled_;
float *input_;
float *temp_;
float *output_;
};
TEST_P(FFT2DTest, Correct) {
if (disabled_) return;
int n = GetParam().n;
for (int i = 0; i < n * n; ++i) {
input_[i] = 1;
std::vector<std::complex<float> > expected = fft2d<float>(&input_[0], n);
GetParam().fft(&input_[0], &temp_[0], &output_[0]);
for (int y = 0; y < n; ++y) {
for (int x = 0; x < (n / 2) + 1; ++x) {
EXPECT_NEAR(expected[y * n + x].real(), output_[2 * (y * n + x)], 1e-5);
EXPECT_NEAR(expected[y * n + x].imag(), output_[2 * (y * n + x) + 1],
1e-5);
}
}
input_[i] = 0;
}
}
TEST_P(FFT2DTest, Benchmark) {
if (disabled_) return;
int n = GetParam().n;
float sum = 0;
for (int i = 0; i < 1000 * (64 - n); ++i) {
input_[i % (n * n)] = 1;
GetParam().fft(&input_[0], &temp_[0], &output_[0]);
sum += output_[0];
input_[i % (n * n)] = 0;
}
}
INSTANTIATE_TEST_CASE_P(
FFT2DTestC, FFT2DTest,
::testing::Values(FFTTestArg(2, aom_fft2x2_float_c, 0),
FFTTestArg(4, aom_fft4x4_float_c, 0),
FFTTestArg(8, aom_fft8x8_float_c, 0),
FFTTestArg(16, aom_fft16x16_float_c, 0),
FFTTestArg(32, aom_fft32x32_float_c, 0)));
#if ARCH_X86 || ARCH_X86_64
INSTANTIATE_TEST_CASE_P(
FFT2DTestSSE2, FFT2DTest,
::testing::Values(FFTTestArg(4, aom_fft4x4_float_sse2, HAS_SSE2),
FFTTestArg(8, aom_fft8x8_float_sse2, HAS_SSE2),
FFTTestArg(16, aom_fft16x16_float_sse2, HAS_SSE2),
FFTTestArg(32, aom_fft32x32_float_sse2, HAS_SSE2)));
INSTANTIATE_TEST_CASE_P(
FFT2DTestAVX2, FFT2DTest,
::testing::Values(FFTTestArg(8, aom_fft8x8_float_avx2, HAS_AVX2),
FFTTestArg(16, aom_fft16x16_float_avx2, HAS_AVX2),
FFTTestArg(32, aom_fft32x32_float_avx2, HAS_AVX2)));
#endif
struct IFFTTestArg {
int n;
tform_fun_t ifft;
int flag;
IFFTTestArg(int n_in, tform_fun_t ifft_in, int flag_in)
: n(n_in), ifft(ifft_in), flag(flag_in) {}
};
std::ostream &operator<<(std::ostream &os, const IFFTTestArg &test_arg) {
return os << "ifft_arg { n:" << test_arg.n << " fft:" << test_arg.ifft
<< " flag:" << test_arg.flag << "}";
}
class IFFT2DTest : public ::testing::TestWithParam<IFFTTestArg> {
protected:
void SetUp() {
int n = GetParam().n;
input_ = (float *)aom_memalign(32, sizeof(*input_) * n * n * 2);
temp_ = (float *)aom_memalign(32, sizeof(*temp_) * n * n * 2);
output_ = (float *)aom_memalign(32, sizeof(*output_) * n * n);
memset(input_, 0, sizeof(*input_) * n * n * 2);
memset(temp_, 0, sizeof(*temp_) * n * n * 2);
memset(output_, 0, sizeof(*output_) * n * n);
#if ARCH_X86 || ARCH_X86_64
disabled_ = GetParam().flag != 0 && !(x86_simd_caps() & GetParam().flag);
#else
disabled_ = GetParam().flag != 0;
#endif
}
void TearDown() {
aom_free(input_);
aom_free(temp_);
aom_free(output_);
}
int disabled_;
float *input_;
float *temp_;
float *output_;
};
TEST_P(IFFT2DTest, Correctness) {
if (disabled_) return;
int n = GetParam().n;
ASSERT_GE(n, 2);
std::vector<float> expected(n * n);
std::vector<float> actual(n * n);
// Do forward transform then invert to make sure we get back expected
for (int y = 0; y < n; ++y) {
for (int x = 0; x < n; ++x) {
expected[y * n + x] = 1;
std::vector<std::complex<float> > input_c = fft2d(&expected[0], n);
for (int i = 0; i < n * n; ++i) {
input_[2 * i + 0] = input_c[i].real();
input_[2 * i + 1] = input_c[i].imag();
}
GetParam().ifft(&input_[0], &temp_[0], &output_[0]);
for (int yy = 0; yy < n; ++yy) {
for (int xx = 0; xx < n; ++xx) {
EXPECT_NEAR(expected[yy * n + xx], output_[yy * n + xx] / (n * n),
1e-5);
}
}
expected[y * n + x] = 0;
}
}
};
TEST_P(IFFT2DTest, Benchmark) {
if (disabled_) return;
int n = GetParam().n;
float sum = 0;
for (int i = 0; i < 1000 * (64 - n); ++i) {
input_[i % (n * n)] = 1;
GetParam().ifft(&input_[0], &temp_[0], &output_[0]);
sum += output_[0];
input_[i % (n * n)] = 0;
}
}
INSTANTIATE_TEST_CASE_P(
IFFT2DTestC, IFFT2DTest,
::testing::Values(IFFTTestArg(2, aom_ifft2x2_float_c, 0),
IFFTTestArg(4, aom_ifft4x4_float_c, 0),
IFFTTestArg(8, aom_ifft8x8_float_c, 0),
IFFTTestArg(16, aom_ifft16x16_float_c, 0),
IFFTTestArg(32, aom_ifft32x32_float_c, 0)));
#if ARCH_X86 || ARCH_X86_64
INSTANTIATE_TEST_CASE_P(
IFFT2DTestSSE2, IFFT2DTest,
::testing::Values(IFFTTestArg(4, aom_ifft4x4_float_sse2, HAS_SSE2),
IFFTTestArg(8, aom_ifft8x8_float_sse2, HAS_SSE2),
IFFTTestArg(16, aom_ifft16x16_float_sse2, HAS_SSE2),
IFFTTestArg(32, aom_ifft32x32_float_sse2, HAS_SSE2)));
INSTANTIATE_TEST_CASE_P(
IFFT2DTestAVX2, IFFT2DTest,
::testing::Values(IFFTTestArg(8, aom_ifft8x8_float_avx2, HAS_AVX2),
IFFTTestArg(16, aom_ifft16x16_float_avx2, HAS_AVX2),
IFFTTestArg(32, aom_ifft32x32_float_avx2, HAS_AVX2)));
#endif
} // namespace

View file

@ -0,0 +1,239 @@
#include <string>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "aom_dsp/grain_table.h"
#include "aom/internal/aom_codec_internal.h"
#include "av1/encoder/grain_test_vectors.h"
#include "test/video_source.h"
void grain_equal(const aom_film_grain_t *expected,
const aom_film_grain_t *actual) {
EXPECT_EQ(expected->apply_grain, actual->apply_grain);
EXPECT_EQ(expected->update_parameters, actual->update_parameters);
if (!expected->update_parameters) return;
EXPECT_EQ(expected->num_y_points, actual->num_y_points);
EXPECT_EQ(expected->num_cb_points, actual->num_cb_points);
EXPECT_EQ(expected->num_cr_points, actual->num_cr_points);
EXPECT_EQ(0, memcmp(expected->scaling_points_y, actual->scaling_points_y,
expected->num_y_points *
sizeof(expected->scaling_points_y[0])));
EXPECT_EQ(0, memcmp(expected->scaling_points_cb, actual->scaling_points_cb,
expected->num_cb_points *
sizeof(expected->scaling_points_cb[0])));
EXPECT_EQ(0, memcmp(expected->scaling_points_cr, actual->scaling_points_cr,
expected->num_cr_points *
sizeof(expected->scaling_points_cr[0])));
EXPECT_EQ(expected->scaling_shift, actual->scaling_shift);
EXPECT_EQ(expected->ar_coeff_lag, actual->ar_coeff_lag);
EXPECT_EQ(expected->ar_coeff_shift, actual->ar_coeff_shift);
const int num_pos_luma =
2 * expected->ar_coeff_lag * (expected->ar_coeff_lag + 1);
const int num_pos_chroma = num_pos_luma;
EXPECT_EQ(0, memcmp(expected->ar_coeffs_y, actual->ar_coeffs_y,
sizeof(expected->ar_coeffs_y[0]) * num_pos_luma));
if (actual->num_cb_points || actual->chroma_scaling_from_luma) {
EXPECT_EQ(0, memcmp(expected->ar_coeffs_cb, actual->ar_coeffs_cb,
sizeof(expected->ar_coeffs_cb[0]) * num_pos_chroma));
}
if (actual->num_cr_points || actual->chroma_scaling_from_luma) {
EXPECT_EQ(0, memcmp(expected->ar_coeffs_cr, actual->ar_coeffs_cr,
sizeof(expected->ar_coeffs_cr[0]) * num_pos_chroma));
}
EXPECT_EQ(expected->overlap_flag, actual->overlap_flag);
EXPECT_EQ(expected->chroma_scaling_from_luma,
actual->chroma_scaling_from_luma);
EXPECT_EQ(expected->grain_scale_shift, actual->grain_scale_shift);
// EXPECT_EQ(expected->random_seed, actual->random_seed);
// clip_to_restricted and bit_depth aren't written
if (expected->num_cb_points) {
EXPECT_EQ(expected->cb_mult, actual->cb_mult);
EXPECT_EQ(expected->cb_luma_mult, actual->cb_luma_mult);
EXPECT_EQ(expected->cb_offset, actual->cb_offset);
}
if (expected->num_cr_points) {
EXPECT_EQ(expected->cr_mult, actual->cr_mult);
EXPECT_EQ(expected->cr_luma_mult, actual->cr_luma_mult);
EXPECT_EQ(expected->cr_offset, actual->cr_offset);
}
}
TEST(FilmGrainTableTest, AddAndLookupSingleSegment) {
aom_film_grain_table_t table;
memset(&table, 0, sizeof(table));
aom_film_grain_t grain;
EXPECT_FALSE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
aom_film_grain_table_append(&table, 1000, 2000, film_grain_test_vectors + 0);
EXPECT_FALSE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
EXPECT_FALSE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
EXPECT_TRUE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
grain.bit_depth = film_grain_test_vectors[0].bit_depth;
EXPECT_EQ(0, memcmp(&grain, film_grain_test_vectors + 0, sizeof(table)));
// Extend the existing segment
aom_film_grain_table_append(&table, 2000, 3000, film_grain_test_vectors + 0);
EXPECT_EQ(0, table.head->next);
// Lookup and remove and check that the entry is no longer there
EXPECT_TRUE(aom_film_grain_table_lookup(&table, 1000, 2000, true, &grain));
EXPECT_FALSE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
EXPECT_TRUE(aom_film_grain_table_lookup(&table, 2000, 3000, true, &grain));
EXPECT_FALSE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
EXPECT_EQ(0, table.head);
EXPECT_EQ(0, table.tail);
aom_film_grain_table_free(&table);
}
TEST(FilmGrainTableTest, SplitSingleSegment) {
aom_film_grain_table_t table;
aom_film_grain_t grain;
memset(&table, 0, sizeof(table));
aom_film_grain_table_append(&table, 0, 1000, film_grain_test_vectors + 0);
// Test lookup and remove that adjusts start time
EXPECT_TRUE(aom_film_grain_table_lookup(&table, 0, 100, true, &grain));
EXPECT_EQ(NULL, table.head->next);
EXPECT_EQ(100, table.head->start_time);
// Test lookup and remove that adjusts end time
EXPECT_TRUE(aom_film_grain_table_lookup(&table, 900, 1000, true, &grain));
EXPECT_EQ(NULL, table.head->next);
EXPECT_EQ(100, table.head->start_time);
EXPECT_EQ(900, table.head->end_time);
// Test lookup and remove that splits the first entry
EXPECT_TRUE(aom_film_grain_table_lookup(&table, 400, 600, true, &grain));
EXPECT_EQ(100, table.head->start_time);
EXPECT_EQ(400, table.head->end_time);
ASSERT_NE((void *)NULL, table.head->next);
EXPECT_EQ(table.tail, table.head->next);
EXPECT_EQ(600, table.head->next->start_time);
EXPECT_EQ(900, table.head->next->end_time);
aom_film_grain_table_free(&table);
}
TEST(FilmGrainTableTest, AddAndLookupMultipleSegments) {
aom_film_grain_table_t table;
memset(&table, 0, sizeof(table));
aom_film_grain_t grain;
const int kNumTestVectors =
sizeof(film_grain_test_vectors) / sizeof(film_grain_test_vectors[0]);
for (int i = 0; i < kNumTestVectors; ++i) {
aom_film_grain_table_append(&table, i * 1000, (i + 1) * 1000,
film_grain_test_vectors + i);
}
for (int i = kNumTestVectors - 1; i >= 0; --i) {
EXPECT_TRUE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
true, &grain));
grain_equal(film_grain_test_vectors + i, &grain);
EXPECT_FALSE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
true, &grain));
}
// Verify that all the data has been removed
for (int i = 0; i < kNumTestVectors; ++i) {
EXPECT_FALSE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
true, &grain));
}
aom_film_grain_table_free(&table);
}
class FilmGrainTableIOTest : public ::testing::Test {
protected:
void SetUp() { memset(&error_, 0, sizeof(error_)); }
struct aom_internal_error_info error_;
};
TEST_F(FilmGrainTableIOTest, ReadMissingFile) {
aom_film_grain_table_t table;
memset(&table, 0, sizeof(table));
ASSERT_EQ(AOM_CODEC_ERROR, aom_film_grain_table_read(
&table, "/path/to/missing/file", &error_));
}
TEST_F(FilmGrainTableIOTest, ReadTruncatedFile) {
aom_film_grain_table_t table;
memset(&table, 0, sizeof(table));
std::string grain_file;
FILE *file = libaom_test::GetTempOutFile(&grain_file);
fwrite("deadbeef", 8, 1, file);
fclose(file);
ASSERT_EQ(AOM_CODEC_ERROR,
aom_film_grain_table_read(&table, grain_file.c_str(), &error_));
EXPECT_EQ(0, remove(grain_file.c_str()));
}
TEST_F(FilmGrainTableIOTest, RoundTripReadWrite) {
aom_film_grain_table_t table;
memset(&table, 0, sizeof(table));
aom_film_grain_t expected_grain[16];
const int kNumTestVectors =
sizeof(film_grain_test_vectors) / sizeof(film_grain_test_vectors[0]);
for (int i = 0; i < kNumTestVectors; ++i) {
expected_grain[i] = film_grain_test_vectors[i];
expected_grain[i].random_seed = i;
expected_grain[i].update_parameters = i % 2;
expected_grain[i].apply_grain = (i + 1) % 2;
expected_grain[i].bit_depth = 0;
aom_film_grain_table_append(&table, i * 1000, (i + 1) * 1000,
expected_grain + i);
}
std::string grain_file;
fclose(libaom_test::GetTempOutFile(&grain_file));
ASSERT_EQ(AOM_CODEC_OK,
aom_film_grain_table_write(&table, grain_file.c_str(), &error_));
aom_film_grain_table_free(&table);
memset(&table, 0, sizeof(table));
ASSERT_EQ(AOM_CODEC_OK,
aom_film_grain_table_read(&table, grain_file.c_str(), &error_));
for (int i = 0; i < kNumTestVectors; ++i) {
aom_film_grain_t grain;
EXPECT_TRUE(aom_film_grain_table_lookup(&table, i * 1000, (i + 1) * 1000,
true, &grain));
grain_equal(expected_grain + i, &grain);
}
aom_film_grain_table_free(&table);
EXPECT_EQ(0, remove(grain_file.c_str()));
}
TEST_F(FilmGrainTableIOTest, RoundTripSplit) {
std::string grain_file;
fclose(libaom_test::GetTempOutFile(&grain_file));
aom_film_grain_table_t table;
memset(&table, 0, sizeof(table));
aom_film_grain_t grain = film_grain_test_vectors[0];
aom_film_grain_table_append(&table, 0, 3000, &grain);
ASSERT_TRUE(aom_film_grain_table_lookup(&table, 1000, 2000, true, &grain));
ASSERT_TRUE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
EXPECT_FALSE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
ASSERT_TRUE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
ASSERT_EQ(AOM_CODEC_OK,
aom_film_grain_table_write(&table, grain_file.c_str(), &error_));
aom_film_grain_table_free(&table);
memset(&table, 0, sizeof(table));
ASSERT_EQ(AOM_CODEC_OK,
aom_film_grain_table_read(&table, grain_file.c_str(), &error_));
ASSERT_TRUE(aom_film_grain_table_lookup(&table, 0, 1000, false, &grain));
ASSERT_FALSE(aom_film_grain_table_lookup(&table, 1000, 2000, false, &grain));
ASSERT_TRUE(aom_film_grain_table_lookup(&table, 2000, 3000, false, &grain));
aom_film_grain_table_free(&table);
EXPECT_EQ(0, remove(grain_file.c_str()));
}

View file

@ -1,331 +0,0 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "./av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "av1/common/enums.h"
namespace {
using std::tr1::tuple;
using libaom_test::ACMRandom;
typedef void (*Predictor)(uint8_t *dst, ptrdiff_t stride, int bs,
const uint8_t *above, const uint8_t *left);
// Note:
// Test parameter list:
// Reference predictor, optimized predictor, prediction mode, block size
//
typedef tuple<Predictor, Predictor, int> PredFuncMode;
typedef tuple<PredFuncMode, int> PredParams;
#if CONFIG_HIGHBITDEPTH
typedef void (*HbdPredictor)(uint16_t *dst, ptrdiff_t stride, int bs,
const uint16_t *above, const uint16_t *left,
int bd);
// Note:
// Test parameter list:
// Reference predictor, optimized predictor, prediction mode, block size,
// bit depth
//
typedef tuple<HbdPredictor, HbdPredictor, int> HbdPredFuncMode;
typedef tuple<HbdPredFuncMode, int, int> HbdPredParams;
#endif
const int MaxBlkSize = 32;
// By default, disable speed test
#define PREDICTORS_SPEED_TEST (0)
#if PREDICTORS_SPEED_TEST
const int MaxTestNum = 100000;
#else
const int MaxTestNum = 100;
#endif
class AV1FilterIntraPredOptimzTest
: public ::testing::TestWithParam<PredParams> {
public:
virtual ~AV1FilterIntraPredOptimzTest() {}
virtual void SetUp() {
PredFuncMode funcMode = GET_PARAM(0);
predFuncRef_ = std::tr1::get<0>(funcMode);
predFunc_ = std::tr1::get<1>(funcMode);
mode_ = std::tr1::get<2>(funcMode);
blockSize_ = GET_PARAM(1);
alloc_ = new uint8_t[3 * MaxBlkSize + 2];
predRef_ = new uint8_t[MaxBlkSize * MaxBlkSize];
pred_ = new uint8_t[MaxBlkSize * MaxBlkSize];
}
virtual void TearDown() {
delete[] alloc_;
delete[] predRef_;
delete[] pred_;
libaom_test::ClearSystemState();
}
protected:
void RunTest() const {
int tstIndex = 0;
int stride = blockSize_;
uint8_t *left = alloc_;
uint8_t *above = alloc_ + MaxBlkSize + 1;
while (tstIndex < MaxTestNum) {
PrepareBuffer();
predFuncRef_(predRef_, stride, blockSize_, &above[1], left);
ASM_REGISTER_STATE_CHECK(
predFunc_(pred_, stride, blockSize_, &above[1], left));
DiffPred(tstIndex);
tstIndex += 1;
}
}
void RunSpeedTestC() const {
int tstIndex = 0;
int stride = blockSize_;
uint8_t *left = alloc_;
uint8_t *above = alloc_ + MaxBlkSize + 1;
PrepareBuffer();
while (tstIndex < MaxTestNum) {
predFuncRef_(predRef_, stride, blockSize_, &above[1], left);
tstIndex += 1;
}
}
void RunSpeedTestSSE() const {
int tstIndex = 0;
int stride = blockSize_;
uint8_t *left = alloc_;
uint8_t *above = alloc_ + MaxBlkSize + 1;
PrepareBuffer();
while (tstIndex < MaxTestNum) {
predFunc_(predRef_, stride, blockSize_, &above[1], left);
tstIndex += 1;
}
}
private:
void PrepareBuffer() const {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i = 0;
while (i < (3 * MaxBlkSize + 2)) {
alloc_[i] = rnd.Rand8();
i += 1;
}
}
void DiffPred(int testNum) const {
int i = 0;
while (i < blockSize_ * blockSize_) {
EXPECT_EQ(predRef_[i], pred_[i]) << "Error at position: " << i << " "
<< "Block size: " << blockSize_ << " "
<< "Test number: " << testNum;
i += 1;
}
}
Predictor predFunc_;
Predictor predFuncRef_;
int mode_;
int blockSize_;
uint8_t *alloc_;
uint8_t *pred_;
uint8_t *predRef_;
};
#if CONFIG_HIGHBITDEPTH
class AV1HbdFilterIntraPredOptimzTest
: public ::testing::TestWithParam<HbdPredParams> {
public:
virtual ~AV1HbdFilterIntraPredOptimzTest() {}
virtual void SetUp() {
HbdPredFuncMode funcMode = GET_PARAM(0);
predFuncRef_ = std::tr1::get<0>(funcMode);
predFunc_ = std::tr1::get<1>(funcMode);
mode_ = std::tr1::get<2>(funcMode);
blockSize_ = GET_PARAM(1);
bd_ = GET_PARAM(2);
alloc_ = new uint16_t[3 * MaxBlkSize + 2];
predRef_ = new uint16_t[MaxBlkSize * MaxBlkSize];
pred_ = new uint16_t[MaxBlkSize * MaxBlkSize];
}
virtual void TearDown() {
delete[] alloc_;
delete[] predRef_;
delete[] pred_;
libaom_test::ClearSystemState();
}
protected:
void RunTest() const {
int tstIndex = 0;
int stride = blockSize_;
uint16_t *left = alloc_;
uint16_t *above = alloc_ + MaxBlkSize + 1;
while (tstIndex < MaxTestNum) {
PrepareBuffer();
predFuncRef_(predRef_, stride, blockSize_, &above[1], left, bd_);
ASM_REGISTER_STATE_CHECK(
predFunc_(pred_, stride, blockSize_, &above[1], left, bd_));
DiffPred(tstIndex);
tstIndex += 1;
}
}
void RunSpeedTestC() const {
int tstIndex = 0;
int stride = blockSize_;
uint16_t *left = alloc_;
uint16_t *above = alloc_ + MaxBlkSize + 1;
PrepareBuffer();
while (tstIndex < MaxTestNum) {
predFuncRef_(predRef_, stride, blockSize_, &above[1], left, bd_);
tstIndex += 1;
}
}
void RunSpeedTestSSE() const {
int tstIndex = 0;
int stride = blockSize_;
uint16_t *left = alloc_;
uint16_t *above = alloc_ + MaxBlkSize + 1;
PrepareBuffer();
while (tstIndex < MaxTestNum) {
predFunc_(predRef_, stride, blockSize_, &above[1], left, bd_);
tstIndex += 1;
}
}
private:
void PrepareBuffer() const {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i = 0;
while (i < (3 * MaxBlkSize + 2)) {
alloc_[i] = rnd.Rand16() & ((1 << bd_) - 1);
i += 1;
}
}
void DiffPred(int testNum) const {
int i = 0;
while (i < blockSize_ * blockSize_) {
EXPECT_EQ(predRef_[i], pred_[i]) << "Error at position: " << i << " "
<< "Block size: " << blockSize_ << " "
<< "Bit depth: " << bd_ << " "
<< "Test number: " << testNum;
i += 1;
}
}
HbdPredictor predFunc_;
HbdPredictor predFuncRef_;
int mode_;
int blockSize_;
int bd_;
uint16_t *alloc_;
uint16_t *pred_;
uint16_t *predRef_;
};
#endif // CONFIG_HIGHBITDEPTH
TEST_P(AV1FilterIntraPredOptimzTest, BitExactCheck) { RunTest(); }
#if PREDICTORS_SPEED_TEST
TEST_P(AV1FilterIntraPredOptimzTest, SpeedCheckC) { RunSpeedTestC(); }
TEST_P(AV1FilterIntraPredOptimzTest, SpeedCheckSSE) { RunSpeedTestSSE(); }
#endif
#if CONFIG_HIGHBITDEPTH
TEST_P(AV1HbdFilterIntraPredOptimzTest, BitExactCheck) { RunTest(); }
#if PREDICTORS_SPEED_TEST
TEST_P(AV1HbdFilterIntraPredOptimzTest, SpeedCheckC) { RunSpeedTestC(); }
TEST_P(AV1HbdFilterIntraPredOptimzTest, SpeedCheckSSE) { RunSpeedTestSSE(); }
#endif // PREDICTORS_SPEED_TEST
#endif // CONFIG_HIGHBITDEPTH
using std::tr1::make_tuple;
const PredFuncMode kPredFuncMdArray[] = {
make_tuple(av1_dc_filter_predictor_c, av1_dc_filter_predictor_sse4_1,
DC_PRED),
make_tuple(av1_v_filter_predictor_c, av1_v_filter_predictor_sse4_1, V_PRED),
make_tuple(av1_h_filter_predictor_c, av1_h_filter_predictor_sse4_1, H_PRED),
make_tuple(av1_d45_filter_predictor_c, av1_d45_filter_predictor_sse4_1,
D45_PRED),
make_tuple(av1_d135_filter_predictor_c, av1_d135_filter_predictor_sse4_1,
D135_PRED),
make_tuple(av1_d117_filter_predictor_c, av1_d117_filter_predictor_sse4_1,
D117_PRED),
make_tuple(av1_d153_filter_predictor_c, av1_d153_filter_predictor_sse4_1,
D153_PRED),
make_tuple(av1_d207_filter_predictor_c, av1_d207_filter_predictor_sse4_1,
D207_PRED),
make_tuple(av1_d63_filter_predictor_c, av1_d63_filter_predictor_sse4_1,
D63_PRED),
make_tuple(av1_tm_filter_predictor_c, av1_tm_filter_predictor_sse4_1,
TM_PRED),
};
const int kBlkSize[] = { 4, 8, 16, 32 };
INSTANTIATE_TEST_CASE_P(
SSE4_1, AV1FilterIntraPredOptimzTest,
::testing::Combine(::testing::ValuesIn(kPredFuncMdArray),
::testing::ValuesIn(kBlkSize)));
#if CONFIG_HIGHBITDEPTH
const HbdPredFuncMode kHbdPredFuncMdArray[] = {
make_tuple(av1_highbd_dc_filter_predictor_c,
av1_highbd_dc_filter_predictor_sse4_1, DC_PRED),
make_tuple(av1_highbd_v_filter_predictor_c,
av1_highbd_v_filter_predictor_sse4_1, V_PRED),
make_tuple(av1_highbd_h_filter_predictor_c,
av1_highbd_h_filter_predictor_sse4_1, H_PRED),
make_tuple(av1_highbd_d45_filter_predictor_c,
av1_highbd_d45_filter_predictor_sse4_1, D45_PRED),
make_tuple(av1_highbd_d135_filter_predictor_c,
av1_highbd_d135_filter_predictor_sse4_1, D135_PRED),
make_tuple(av1_highbd_d117_filter_predictor_c,
av1_highbd_d117_filter_predictor_sse4_1, D117_PRED),
make_tuple(av1_highbd_d153_filter_predictor_c,
av1_highbd_d153_filter_predictor_sse4_1, D153_PRED),
make_tuple(av1_highbd_d207_filter_predictor_c,
av1_highbd_d207_filter_predictor_sse4_1, D207_PRED),
make_tuple(av1_highbd_d63_filter_predictor_c,
av1_highbd_d63_filter_predictor_sse4_1, D63_PRED),
make_tuple(av1_highbd_tm_filter_predictor_c,
av1_highbd_tm_filter_predictor_sse4_1, TM_PRED),
};
const int kBd[] = { 10, 12 };
INSTANTIATE_TEST_CASE_P(
SSE4_1, AV1HbdFilterIntraPredOptimzTest,
::testing::Combine(::testing::ValuesIn(kHbdPredFuncMdArray),
::testing::ValuesIn(kBlkSize),
::testing::ValuesIn(kBd)));
#endif // CONFIG_HIGHBITDEPTH
} // namespace

134
third_party/aom/test/filterintra_test.cc vendored Normal file
View file

@ -0,0 +1,134 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "config/av1_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/util.h"
#include "av1/common/enums.h"
namespace {
using ::testing::tuple;
using libaom_test::ACMRandom;
typedef void (*Predictor)(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
const uint8_t *above, const uint8_t *left, int mode);
// Note:
// Test parameter list:
// Reference predictor, optimized predictor, prediction mode, tx size
//
typedef tuple<Predictor, Predictor, int> PredFuncMode;
typedef tuple<PredFuncMode, TX_SIZE> PredParams;
const int MaxTxSize = 32;
const int MaxTestNum = 100;
class AV1FilterIntraPredTest : public ::testing::TestWithParam<PredParams> {
public:
virtual ~AV1FilterIntraPredTest() {}
virtual void SetUp() {
PredFuncMode funcMode = GET_PARAM(0);
predFuncRef_ = ::testing::get<0>(funcMode);
predFunc_ = ::testing::get<1>(funcMode);
mode_ = ::testing::get<2>(funcMode);
txSize_ = GET_PARAM(1);
alloc_ = new uint8_t[2 * MaxTxSize + 1];
predRef_ = new uint8_t[MaxTxSize * MaxTxSize];
pred_ = new uint8_t[MaxTxSize * MaxTxSize];
}
virtual void TearDown() {
delete[] alloc_;
delete[] predRef_;
delete[] pred_;
libaom_test::ClearSystemState();
}
protected:
void RunTest() const {
int tstIndex = 0;
int stride = tx_size_wide[txSize_];
uint8_t *left = alloc_;
uint8_t *above = alloc_ + MaxTxSize;
while (tstIndex < MaxTestNum) {
PrepareBuffer();
predFuncRef_(predRef_, stride, txSize_, &above[1], left, mode_);
ASM_REGISTER_STATE_CHECK(
predFunc_(pred_, stride, txSize_, &above[1], left, mode_));
DiffPred(tstIndex);
tstIndex += 1;
}
}
private:
void PrepareBuffer() const {
ACMRandom rnd(ACMRandom::DeterministicSeed());
int i = 0;
while (i < (2 * MaxTxSize + 1)) {
alloc_[i] = rnd.Rand8();
i++;
}
}
void DiffPred(int testNum) const {
int i = 0;
while (i < tx_size_wide[txSize_] * tx_size_high[txSize_]) {
EXPECT_EQ(predRef_[i], pred_[i]) << "Error at position: " << i << " "
<< "Tx size: " << tx_size_wide[txSize_]
<< "x" << tx_size_high[txSize_] << " "
<< "Test number: " << testNum;
i++;
}
}
Predictor predFunc_;
Predictor predFuncRef_;
int mode_;
TX_SIZE txSize_;
uint8_t *alloc_;
uint8_t *pred_;
uint8_t *predRef_;
};
TEST_P(AV1FilterIntraPredTest, BitExactCheck) { RunTest(); }
using ::testing::make_tuple;
const PredFuncMode kPredFuncMdArray[] = {
make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
FILTER_DC_PRED),
make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
FILTER_V_PRED),
make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
FILTER_H_PRED),
make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
FILTER_D157_PRED),
make_tuple(&av1_filter_intra_predictor_c, &av1_filter_intra_predictor_sse4_1,
FILTER_PAETH_PRED),
};
const TX_SIZE kTxSize[] = { TX_4X4, TX_8X8, TX_16X16, TX_32X32, TX_4X8,
TX_8X4, TX_8X16, TX_16X8, TX_16X32, TX_32X16,
TX_4X16, TX_16X4, TX_8X32, TX_32X8 };
INSTANTIATE_TEST_CASE_P(
SSE4_1, AV1FilterIntraPredTest,
::testing::Combine(::testing::ValuesIn(kPredFuncMdArray),
::testing::ValuesIn(kTxSize)));
} // namespace

View file

@ -7,7 +7,7 @@
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "test/codec_factory.h"

98
third_party/aom/test/fwht4x4_test.cc vendored Normal file
View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 2 Clause License and
* the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
* was not distributed with this source code in the LICENSE file, you can
* obtain it at www.aomedia.org/license/software. If the Alliance for Open
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "config/av1_rtcd.h"
#include "config/aom_dsp_rtcd.h"
#include "test/acm_random.h"
#include "test/clear_system_state.h"
#include "test/register_state_check.h"
#include "test/transform_test_base.h"
#include "test/util.h"
#include "av1/common/entropy.h"
#include "aom/aom_codec.h"
#include "aom/aom_integer.h"
#include "aom_ports/mem.h"
using libaom_test::ACMRandom;
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);
using libaom_test::FhtFunc;
typedef ::testing::tuple<FdctFunc, IdctFunc, TX_TYPE, aom_bit_depth_t, int>
Dct4x4Param;
void fwht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
TxfmParam * /*txfm_param*/) {
av1_fwht4x4_c(in, out, stride);
}
void iwht4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
av1_highbd_iwht4x4_16_add_c(in, out, stride, 10);
}
void iwht4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
av1_highbd_iwht4x4_16_add_c(in, out, stride, 12);
}
class Trans4x4WHT : public libaom_test::TransformTestBase,
public ::testing::TestWithParam<Dct4x4Param> {
public:
virtual ~Trans4x4WHT() {}
virtual void SetUp() {
fwd_txfm_ = GET_PARAM(0);
inv_txfm_ = GET_PARAM(1);
pitch_ = 4;
height_ = 4;
fwd_txfm_ref = fwht4x4_ref;
bit_depth_ = GET_PARAM(3);
mask_ = (1 << bit_depth_) - 1;
num_coeffs_ = GET_PARAM(4);
}
virtual void TearDown() { libaom_test::ClearSystemState(); }
protected:
void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
fwd_txfm_(in, out, stride);
}
void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
inv_txfm_(out, dst, stride);
}
FdctFunc fwd_txfm_;
IdctFunc inv_txfm_;
};
TEST_P(Trans4x4WHT, AccuracyCheck) { RunAccuracyCheck(0, 0.00001); }
TEST_P(Trans4x4WHT, CoeffCheck) { RunCoeffCheck(); }
TEST_P(Trans4x4WHT, MemCheck) { RunMemCheck(); }
TEST_P(Trans4x4WHT, InvAccuracyCheck) { RunInvAccuracyCheck(0); }
using ::testing::make_tuple;
INSTANTIATE_TEST_CASE_P(
C, Trans4x4WHT,
::testing::Values(make_tuple(&av1_highbd_fwht4x4_c, &iwht4x4_10, DCT_DCT,
AOM_BITS_10, 16),
make_tuple(&av1_highbd_fwht4x4_c, &iwht4x4_12, DCT_DCT,
AOM_BITS_12, 16)));
} // namespace

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