diff --git a/build/kvazaar_tests/kvazaar_tests.vcxproj b/build/kvazaar_tests/kvazaar_tests.vcxproj index b8bf7632..f7140714 100644 --- a/build/kvazaar_tests/kvazaar_tests.vcxproj +++ b/build/kvazaar_tests/kvazaar_tests.vcxproj @@ -91,6 +91,7 @@ + diff --git a/build/kvazaar_tests/kvazaar_tests.vcxproj.filters b/build/kvazaar_tests/kvazaar_tests.vcxproj.filters index d8420b8e..707f84ba 100644 --- a/build/kvazaar_tests/kvazaar_tests.vcxproj.filters +++ b/build/kvazaar_tests/kvazaar_tests.vcxproj.filters @@ -33,6 +33,9 @@ Source Files + + Source Files + diff --git a/tests/dct_tests.c b/tests/dct_tests.c new file mode 100644 index 00000000..479a5a45 --- /dev/null +++ b/tests/dct_tests.c @@ -0,0 +1,226 @@ +#include "greatest/greatest.h" + +#include "test_strategies.h" + +#include "src/image.h" + +#include +#include + + +////////////////////////////////////////////////////////////////////////// +// MACROS +#define NUM_TESTS 12 +#define NUM_SIZES 5 +#define LCU_MAX_LOG_W 5 +#define LCU_MIN_LOG_W 2 + +////////////////////////////////////////////////////////////////////////// +// GLOBALS +int16_t * dct_bufs[NUM_TESTS] = { 0 }; // SIMD aligned pointers. +int16_t * dct_actual_bufs[NUM_TESTS] = { 0 }; // pointers returned by malloc. + +static int16_t dct_result[NUM_SIZES][LCU_WIDTH*LCU_WIDTH] = { 0 }; +static int16_t idct_result[NUM_SIZES][LCU_WIDTH*LCU_WIDTH] = { 0 }; + +static struct test_env_t { + int log_width; // for selecting dim from bufs + dct_func * tested_func; + const strategy * strategy; + char msg[1024]; +} test_env; + + +////////////////////////////////////////////////////////////////////////// +// SETUP, TEARDOWN AND HELPER FUNCTIONS +static void init_gradient(int x_px, int y_px, int width, int slope, int16_t *buf) +{ + for (int y = 0; y < width; ++y) { + for (int x = 0; x < width; ++x) { + int diff_x = x_px - x; + int diff_y = y_px - y; + int val = slope * sqrt(diff_x * diff_x + diff_y * diff_y) + 0.5; + buf[y * width + x] = CLIP(0, 255, val); + } + } +} + + +static void setup_tests() +{ + for (int test = 0; test < NUM_TESTS; ++test) { + + dct_actual_bufs[test] = malloc(LCU_WIDTH*LCU_WIDTH*sizeof(int16_t) + SIMD_ALIGNMENT); + dct_bufs[test] = ALIGNED_POINTER(dct_actual_bufs[test], SIMD_ALIGNMENT); + } + + for (int test = 0; test < NUM_TESTS; ++test) { + const int width = LCU_WIDTH; + init_gradient(width, width, width, 255 / width, dct_bufs[test]); + } + + + + // Select buffer width according to function name for dct function. + int block = 0; + for (int s = 0; s < strategies.count && block < NUM_SIZES; ++s) + { + strategy *strat = &strategies.strategies[s]; + dct_func* dct_generic = 0; + if ( + ( + + strcmp(strat->type, "fast_forward_dst_4x4") == 0 || + strcmp(strat->type, "dct_4x4") == 0 || + strcmp(strat->type, "dct_8x8") == 0 || + strcmp(strat->type, "dct_16x16") == 0 || + strcmp(strat->type, "dct_32x32") == 0 + ) + && + strcmp(strat->strategy_name, "generic") == 0 + ) + { + dct_generic = strat->fptr; + dct_generic(BIT_DEPTH, dct_bufs[block], dct_result[block]); + ++block; + } + } + + block = 0; + for (int s = 0; s < strategies.count && block < NUM_SIZES; ++s) + { + strategy *strat = &strategies.strategies[s]; + dct_func* idct_generic = 0; + if ( + ( + + strcmp(strat->type, "fast_inverse_dst_4x4") == 0 || + strcmp(strat->type, "idct_4x4") == 0 || + strcmp(strat->type, "idct_8x8") == 0 || + strcmp(strat->type, "idct_16x16") == 0 || + strcmp(strat->type, "idct_32x32") == 0 + ) + && + strcmp(strat->strategy_name, "generic") == 0 + ) + { + idct_generic = strat->fptr; + idct_generic(BIT_DEPTH, idct_result[block], dct_bufs[block]); + ++block; + } + } +} + +static void tear_down_tests() +{ + for (int test = 0; test < NUM_TESTS; ++test) { + free(dct_actual_bufs[test]); + } +} + + +////////////////////////////////////////////////////////////////////////// +// TESTS +TEST dct(void) +{ + int index = test_env.log_width - 1; + if (strcmp(test_env.strategy->type, "fast_forward_dst_4x4") == 0) index = 0; + + int16_t *buf = dct_bufs[index]; + int16_t test_result[LCU_WIDTH*LCU_WIDTH] = { 0 }; + + test_env.tested_func(BIT_DEPTH, buf, test_result); + + for (int i = 0; i < LCU_WIDTH*LCU_WIDTH; ++i){ + ASSERT_EQ(test_result[i], dct_result[index][i]); + } + + PASS(); +} + +TEST idct(void) +{ + int index = test_env.log_width - 1; + if (strcmp(test_env.strategy->type, "fast_inverse_dst_4x4") == 0) index = 0; + + int16_t *buf = dct_bufs[index]; + int16_t test_result[LCU_WIDTH*LCU_WIDTH] = { 0 }; + + test_env.tested_func(BIT_DEPTH, test_result, buf); + + for (int i = 0; i < LCU_WIDTH*LCU_WIDTH; ++i){ + ASSERT_EQ(test_result[i], idct_result[index][i]); + } + + PASS(); +} + + +////////////////////////////////////////////////////////////////////////// +// TEST FIXTURES +SUITE(dct_tests) +{ + //SET_SETUP(sad_setup); + //SET_TEARDOWN(sad_teardown); + + setup_tests(); + + // Loop through all strategies picking out the intra sad ones and run + // select strategies though all tests + for (unsigned i = 0; i < strategies.count; ++i) { + const strategy * strategy = &strategies.strategies[i]; + + // Select buffer width according to function name for dct function. + if (strcmp(strategy->type, "fast_forward_dst_4x4") == 0) { + test_env.log_width = 2; + } + else if (strcmp(strategy->type, "dct_4x4") == 0) { + test_env.log_width = 2; + } + else if (strcmp(strategy->type, "dct_8x8") == 0) { + test_env.log_width = 3; + } + else if (strcmp(strategy->type, "dct_16x16") == 0) { + test_env.log_width = 4; + } + else if (strcmp(strategy->type, "dct_32x32") == 0) { + test_env.log_width = 5; + } + else if (strcmp(strategy->type, "fast_inverse_dst_4x4") == 0) { + test_env.log_width = 2; + } + else if (strcmp(strategy->type, "idct_4x4") == 0) { + test_env.log_width = 2; + } + else if (strcmp(strategy->type, "idct_8x8") == 0) { + test_env.log_width = 3; + } + else if (strcmp(strategy->type, "idct_16x16") == 0) { + test_env.log_width = 4; + } + else if (strcmp(strategy->type, "idct_32x32") == 0) { + test_env.log_width = 5; + } + else { + test_env.log_width = 0; + } + + test_env.tested_func = strategies.strategies[i].fptr; + test_env.strategy = strategy; + + // Call different tests depending on type of function. + // This allows for selecting a subset of tests with -t parameter. + if (strncmp(strategy->type, "dct_", 4) == 0 || + strcmp(strategy->type, "fast_forward_dst_4x4") == 0) + { + RUN_TEST(dct); + } + else if (strncmp(strategy->type, "idct_", 4) == 0 || + strcmp(strategy->type, "fast_inverse_dst_4x4") == 0) + { + RUN_TEST(idct); + } + } + + tear_down_tests(); +} diff --git a/tests/tests_main.c b/tests/tests_main.c index 03c80c16..e68d3813 100644 --- a/tests/tests_main.c +++ b/tests/tests_main.c @@ -7,6 +7,7 @@ extern SUITE(sad_tests); extern SUITE(intra_sad_tests); extern SUITE(satd_tests); extern SUITE(speed_tests); +extern SUITE(dct_tests); int main(int argc, char **argv) { @@ -17,6 +18,7 @@ int main(int argc, char **argv) RUN_SUITE(sad_tests); RUN_SUITE(intra_sad_tests); RUN_SUITE(satd_tests); + RUN_SUITE(dct_tests); if (greatest_info.suite_filter && greatest_name_match("speed", greatest_info.suite_filter))