1 /*****************************************************************************
2  * This file is part of Kvazaar HEVC encoder.
3  *
4  * Copyright (c) 2021, Tampere University, ITU/ISO/IEC, project contributors
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  *   list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice, this
14  *   list of conditions and the following disclaimer in the documentation and/or
15  *   other materials provided with the distribution.
16  *
17  * * Neither the name of the Tampere University or ITU/ISO/IEC nor the names of its
18  *   contributors may be used to endorse or promote products derived from
19  *   this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND ON
28  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  * INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
31  ****************************************************************************/
32 
33 #include "greatest/greatest.h"
34 
35 #include "test_strategies.h"
36 
37 #include "src/image.h"
38 
39 #include <math.h>
40 
41 //////////////////////////////////////////////////////////////////////////
42 // MACROS
43 #define NUM_TESTS 3
44 #define LCU_MAX_LOG_W 6
45 #define LCU_MIN_LOG_W 2
46 
47 //////////////////////////////////////////////////////////////////////////
48 // GLOBALS
49 static kvz_pixel * satd_bufs[NUM_TESTS][7][2];
50 
51 static struct {
52   int log_width; // for selecting dim from satd_bufs
53   cost_pixel_nxn_func * tested_func;
54 } satd_test_env;
55 
56 
57 //////////////////////////////////////////////////////////////////////////
58 // SETUP, TEARDOWN AND HELPER FUNCTIONS
setup_tests()59 static void setup_tests()
60 {
61   for (int test = 0; test < NUM_TESTS; ++test) {
62     for (int w = 0; w <= LCU_MIN_LOG_W; ++w) {
63       satd_bufs[test][w][0] = NULL;
64       satd_bufs[test][w][1] = NULL;
65     }
66 
67     for (int w = LCU_MIN_LOG_W; w <= LCU_MAX_LOG_W; ++w) {
68       unsigned size = 1 << (w * 2);
69       satd_bufs[test][w][0] = malloc(size * sizeof(kvz_pixel));
70       satd_bufs[test][w][1] = malloc(size * sizeof(kvz_pixel));
71     }
72   }
73 
74   //Black and white buffers
75   int test = 0;
76   for (int w = LCU_MIN_LOG_W; w <= LCU_MAX_LOG_W; ++w) {
77     unsigned size = 1 << (w * 2);
78     FILL_ARRAY(satd_bufs[test][w][0], 0, size);
79     FILL_ARRAY(satd_bufs[test][w][1], 255, size);
80   }
81 
82   //Checker patterns, buffer 1 is negative of buffer 2
83   test = 1;
84   for (int w = LCU_MIN_LOG_W; w <= LCU_MAX_LOG_W; ++w) {
85     unsigned size = 1 << (w * 2);
86     for (int i = 0; i < size; ++i){
87       satd_bufs[test][w][0][i] = 255 * ( ( ((i >> w)%2) + (i % 2) ) % 2);
88       satd_bufs[test][w][1][i] = (satd_bufs[test][w][0][i] + 1) % 2 ;
89     }
90   }
91 
92   //Gradient test pattern
93   test = 2;
94   for (int w = LCU_MIN_LOG_W; w <= LCU_MAX_LOG_W; ++w) {
95     unsigned size = 1 << (w * 2);
96     for (int i = 0; i < size; ++i){
97       int column = (i % (1 << w) );
98       int row = (i / (1 << w) );
99       int r = sqrt(row * row + column * column);
100       satd_bufs[test][w][0][i] = 255 / (r + 1);
101       satd_bufs[test][w][1][i] = 255 - 255 / (r + 1);
102     }
103   }
104 }
105 
satd_tear_down_tests()106 static void satd_tear_down_tests()
107 {
108   for (int test = 0; test < NUM_TESTS; ++test) {
109     for (int log_width = 2; log_width <= 6; ++log_width) {
110       free(satd_bufs[test][log_width][0]);
111       free(satd_bufs[test][log_width][1]);
112     }
113   }
114 }
115 
116 
117 //////////////////////////////////////////////////////////////////////////
118 // TESTS
119 
satd_test_black_and_white(void)120 TEST satd_test_black_and_white(void)
121 {
122   const int satd_results[5] = {2040, 4080, 16320, 65280, 261120};
123 
124   const int test = 0;
125 
126   kvz_pixel * buf1 = satd_bufs[test][satd_test_env.log_width][0];
127   kvz_pixel * buf2 = satd_bufs[test][satd_test_env.log_width][1];
128 
129   unsigned result1 = satd_test_env.tested_func(buf1, buf2);
130   unsigned result2 = satd_test_env.tested_func(buf2, buf1);
131 
132   ASSERT_EQ(result1, result2);
133   ASSERT_EQ(result1, satd_results[satd_test_env.log_width - 2]);
134 
135   PASS();
136 }
137 
satd_test_checkers(void)138 TEST satd_test_checkers(void)
139 {
140   const int satd_checkers_results[5] = { 2040, 4080, 16320, 65280, 261120 };
141 
142   const int test = 1;
143 
144   kvz_pixel * buf1 = satd_bufs[test][satd_test_env.log_width][0];
145   kvz_pixel * buf2 = satd_bufs[test][satd_test_env.log_width][1];
146 
147   unsigned result1 = satd_test_env.tested_func(buf1, buf2);
148   unsigned result2 = satd_test_env.tested_func(buf2, buf1);
149 
150   ASSERT_EQ(result1, result2);
151   ASSERT_EQ(result1, satd_checkers_results[satd_test_env.log_width - 2]);
152 
153   PASS();
154 }
155 
156 
satd_test_gradient(void)157 TEST satd_test_gradient(void)
158 {
159   const int satd_gradient_results[5] = {3140,9004,20481,67262,258672};
160 
161   const int test = 2;
162 
163   kvz_pixel * buf1 = satd_bufs[test][satd_test_env.log_width][0];
164   kvz_pixel * buf2 = satd_bufs[test][satd_test_env.log_width][1];
165 
166   unsigned result1 = satd_test_env.tested_func(buf1, buf2);
167   unsigned result2 = satd_test_env.tested_func(buf2, buf1);
168 
169   ASSERT_EQ(result1, result2);
170   ASSERT_EQ(result1, satd_gradient_results[satd_test_env.log_width - 2]);
171 
172   PASS();
173 }
174 
175 //////////////////////////////////////////////////////////////////////////
176 // TEST FIXTURES
SUITE(satd_tests)177 SUITE(satd_tests)
178 {
179   setup_tests();
180 
181   // Loop through all strategies picking out the intra sad ones and run
182   // selectec strategies though all tests.
183   for (volatile unsigned i = 0; i < strategies.count; ++i) {
184     const char * type = strategies.strategies[i].type;
185 
186     if (strcmp(type, "satd_4x4") == 0) {
187       satd_test_env.log_width = 2;
188     }
189     else if (strcmp(type, "satd_8x8") == 0) {
190       satd_test_env.log_width = 3;
191     }
192     else if (strcmp(type, "satd_16x16") == 0) {
193       satd_test_env.log_width = 4;
194     }
195     else if (strcmp(type, "satd_32x32") == 0) {
196       satd_test_env.log_width = 5;
197     }
198     else if (strcmp(type, "satd_64x64") == 0) {
199       satd_test_env.log_width = 6;
200     }
201     else {
202       continue;
203     }
204 
205     satd_test_env.tested_func = strategies.strategies[i].fptr;
206 
207     // Tests
208     RUN_TEST(satd_test_black_and_white);
209     RUN_TEST(satd_test_checkers);
210     RUN_TEST(satd_test_gradient);
211   }
212 
213   satd_tear_down_tests();
214 }
215