Imported Upstream version 1.4
[deb_x265.git] / source / test / intrapredharness.cpp
1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
3 *
4 * Authors: Min Chen <chenm003@163.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
19 *
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
23
24 #include "common.h"
25 #include "predict.h"
26 #include "intrapredharness.h"
27
28 using namespace x265;
29
30 IntraPredHarness::IntraPredHarness()
31 {
32 for (int i = 0; i < INPUT_SIZE; i++)
33 pixel_buff[i] = rand() % PIXEL_MAX;
34
35 initROM();
36 }
37
38 bool IntraPredHarness::check_dc_primitive(intra_pred_t ref, intra_pred_t opt, int width)
39 {
40 int j = Predict::ADI_BUF_STRIDE;
41 intptr_t stride = FENC_STRIDE;
42
43 #if _DEBUG
44 memset(pixel_out_vec, 0xCD, OUTPUT_SIZE);
45 memset(pixel_out_c, 0xCD, OUTPUT_SIZE);
46 #endif
47
48 for (int i = 0; i <= 100; i++)
49 {
50 int rand_filter = rand() & 1;
51 if (width > 16)
52 rand_filter = 0;
53
54 pixel left[MAX_CU_SIZE * 2 + 1];
55 for (int k = 0; k < width * 2 + 1; k++)
56 {
57 left[k] = pixel_buff[j - 1 + k * Predict::ADI_BUF_STRIDE];
58 }
59
60 ref(pixel_out_c, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, rand_filter);
61 checked(opt, pixel_out_vec, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, rand_filter);
62
63 for (int k = 0; k < width; k++)
64 {
65 if (memcmp(pixel_out_vec + k * FENC_STRIDE, pixel_out_c + k * FENC_STRIDE, width * sizeof(pixel)))
66 return false;
67 }
68
69 reportfail();
70 j += FENC_STRIDE;
71 }
72
73 return true;
74 }
75
76 bool IntraPredHarness::check_planar_primitive(intra_pred_t ref, intra_pred_t opt, int width)
77 {
78 int j = Predict::ADI_BUF_STRIDE;
79 intptr_t stride = FENC_STRIDE;
80
81 #if _DEBUG
82 memset(pixel_out_vec, 0xCD, OUTPUT_SIZE);
83 memset(pixel_out_c, 0xCD, OUTPUT_SIZE);
84 #endif
85
86 for (int i = 0; i <= 100; i++)
87 {
88 pixel left[MAX_CU_SIZE * 2 + 1];
89 for (int k = 0; k < width * 2 + 1; k++)
90 {
91 left[k] = pixel_buff[j - 1 + k * Predict::ADI_BUF_STRIDE];
92 }
93
94 ref(pixel_out_c, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, 0);
95 checked(opt, pixel_out_vec, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, 0);
96
97 for (int k = 0; k < width; k++)
98 {
99 if (memcmp(pixel_out_vec + k * FENC_STRIDE, pixel_out_c + k * FENC_STRIDE, width * sizeof(pixel)))
100 return false;
101 }
102
103 reportfail();
104 j += FENC_STRIDE;
105 }
106
107 return true;
108 }
109
110 bool IntraPredHarness::check_angular_primitive(const intra_pred_t ref[][NUM_TR_SIZE], const intra_pred_t opt[][NUM_TR_SIZE])
111 {
112 int j = Predict::ADI_BUF_STRIDE;
113 intptr_t stride = FENC_STRIDE;
114
115 #if _DEBUG
116 memset(pixel_out_vec, 0xCD, OUTPUT_SIZE);
117 memset(pixel_out_c, 0xCD, OUTPUT_SIZE);
118 #endif
119
120 for (int size = 2; size <= 5; size++)
121 {
122 int width = (1 << size);
123 for (int i = 0; i <= 100; i++)
124 {
125 int bFilter = (width <= 16) && (rand() % 2);
126 for (int pmode = 2; pmode <= 34; pmode++)
127 {
128 if (!opt[pmode][size - 2])
129 continue;
130
131 pixel * refAbove = pixel_buff + j;
132 pixel * refLeft = refAbove + 3 * width;
133 refLeft[0] = refAbove[0];
134
135 checked(opt[pmode][size - 2], pixel_out_vec, stride, refLeft, refAbove, pmode, bFilter);
136 ref[pmode][size - 2](pixel_out_c, stride, refLeft, refAbove, pmode, bFilter);
137
138 for (int k = 0; k < width; k++)
139 {
140 if (memcmp(pixel_out_vec + k * FENC_STRIDE, pixel_out_c + k * FENC_STRIDE, width * sizeof(pixel)))
141 return false;
142 }
143
144 reportfail();
145 }
146
147 j += FENC_STRIDE;
148 }
149 }
150
151 return true;
152 }
153
154 bool IntraPredHarness::check_allangs_primitive(const intra_allangs_t ref[], const intra_allangs_t opt[])
155 {
156 int j = Predict::ADI_BUF_STRIDE;
157 int isLuma;
158
159 #if _DEBUG
160 memset(pixel_out_33_vec, 0xCD, OUTPUT_SIZE_33);
161 memset(pixel_out_33_c, 0xCD, OUTPUT_SIZE_33);
162 #endif
163
164 for (int size = 2; size <= 5; size++)
165 {
166 if (opt[size - 2] == NULL) continue;
167
168 const int width = (1 << size);
169
170 for (int i = 0; i <= 100; i++)
171 {
172 isLuma = (width <= 16) ? true : false; // bFilter is true for 4x4, 8x8, 16x16 and false for 32x32
173
174 pixel * refAbove0 = pixel_buff + j;
175 pixel * refLeft0 = refAbove0 + 3 * width;
176
177 pixel * refAbove1 = pixel_buff + j + 3 * FENC_STRIDE; // keep this offset, since vector code may broken input buffer range [-(width-1), 0]
178 pixel * refLeft1 = refAbove1 + 3 * width + FENC_STRIDE;
179 refLeft0[0] = refAbove0[0] = refLeft1[0] = refAbove1[0];
180
181 ref[size - 2](pixel_out_33_c, refAbove0, refLeft0, refAbove1, refLeft1, isLuma);
182 checked(opt[size - 2], pixel_out_33_vec, refAbove0, refLeft0, refAbove1, refLeft1, isLuma);
183
184 for (int p = 2 - 2; p <= 34 - 2; p++)
185 {
186 for (int k = 0; k < width; k++)
187 {
188 if (memcmp(pixel_out_33_c + p * (width * width) + k * width, pixel_out_33_vec + p * (width * width) + k * width, width * sizeof(pixel)))
189 {
190 printf("\nFailed: (%dx%d) Mode(%2d), Line[%2d], bfilter=%d\n", width, width, p + 2, k, isLuma);
191 opt[size - 2](pixel_out_33_vec, refAbove0, refLeft0, refAbove1, refLeft1, isLuma);
192 return false;
193 }
194 }
195 }
196
197 reportfail();
198 j += FENC_STRIDE;
199 }
200 }
201
202 return true;
203 }
204
205 bool IntraPredHarness::testCorrectness(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
206 {
207 for (int i = BLOCK_4x4; i <= BLOCK_32x32; i++)
208 {
209 if (opt.intra_pred[1][i])
210 {
211 const int size = (1 << (i + 2));
212 if (!check_dc_primitive(ref.intra_pred[1][i], opt.intra_pred[1][i], size))
213 {
214 printf("intra_dc %dx%d failed\n", size, size);
215 return false;
216 }
217 }
218 if (opt.intra_pred[0][i])
219 {
220 const int size = (1 << (i + 2));
221 if (!check_planar_primitive(ref.intra_pred[0][i], opt.intra_pred[0][i], size))
222 {
223 printf("intra_planar %dx%d failed\n", size, size);
224 return false;
225 }
226 }
227 }
228
229 // NOTE: always call since this function have check pointer in loop
230 if (!check_angular_primitive(ref.intra_pred, opt.intra_pred))
231 {
232 printf("intra_angular failed\n");
233 return false;
234 }
235
236 if (opt.intra_pred_allangs[0])
237 {
238 if (!check_allangs_primitive(ref.intra_pred_allangs, opt.intra_pred_allangs))
239 {
240 printf("intra_allangs failed\n");
241 return false;
242 }
243 }
244
245 return true;
246 }
247
248 void IntraPredHarness::measureSpeed(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
249 {
250 int width = 64;
251 uint16_t srcStride = 96;
252
253 for (int i = BLOCK_4x4; i <= BLOCK_32x32; i++)
254 {
255 const int size = (1 << (i + 2));
256 if (opt.intra_pred[1][i])
257 {
258 printf("intra_dc_%dx%d[f=0]", size, size);
259 REPORT_SPEEDUP(opt.intra_pred[1][i], ref.intra_pred[1][i],
260 pixel_out_vec, FENC_STRIDE, pixel_buff + srcStride, pixel_buff, 0, 0);
261 if (size <= 16)
262 {
263 printf("intra_dc_%dx%d[f=1]", size, size);
264 REPORT_SPEEDUP(opt.intra_pred[1][i], ref.intra_pred[1][i],
265 pixel_out_vec, FENC_STRIDE, pixel_buff + srcStride, pixel_buff, 0, 1);
266 }
267 }
268 if (opt.intra_pred[0][i])
269 {
270 printf("intra_planar %2dx%d", size, size);
271 REPORT_SPEEDUP(opt.intra_pred[0][i], ref.intra_pred[0][i],
272 pixel_out_vec, FENC_STRIDE, pixel_buff + srcStride, pixel_buff, 0, 0);
273 }
274 if (opt.intra_pred_allangs[i])
275 {
276 bool bFilter = (size <= 16);
277 pixel * refAbove = pixel_buff + srcStride;
278 pixel * refLeft = refAbove + 3 * size;
279 refLeft[0] = refAbove[0];
280 printf("intra_allangs%dx%d", size, size);
281 REPORT_SPEEDUP(opt.intra_pred_allangs[i], ref.intra_pred_allangs[i],
282 pixel_out_33_vec, refAbove, refLeft, refAbove, refLeft, bFilter);
283 }
284 }
285
286 for (int ii = 2; ii <= 5; ii++)
287 {
288 for (int p = 2; p <= 34; p += 1)
289 {
290 int pmode = p; //(rand()%33)+2;
291 if (opt.intra_pred[pmode][ii - 2])
292 {
293 width = (1 << ii);
294 bool bFilter = (width <= 16);
295 pixel * refAbove = pixel_buff + srcStride;
296 pixel * refLeft = refAbove + 3 * width;
297 refLeft[0] = refAbove[0];
298 printf("intra_ang%dx%d[%2d]", width, width, pmode);
299 REPORT_SPEEDUP(opt.intra_pred[pmode][ii - 2], ref.intra_pred[pmode][ii - 2],
300 pixel_out_vec, FENC_STRIDE, refAbove, refLeft, pmode, bFilter);
301 }
302 }
303 }
304 }