Update patch for ARM processors.
[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
36 bool IntraPredHarness::check_dc_primitive(intra_pred_t ref, intra_pred_t opt, int width)
37 {
38 int j = Predict::ADI_BUF_STRIDE;
39 intptr_t stride = FENC_STRIDE;
40
41 #if _DEBUG
42 memset(pixel_out_vec, 0xCD, OUTPUT_SIZE);
43 memset(pixel_out_c, 0xCD, OUTPUT_SIZE);
44 #endif
45
46 for (int i = 0; i <= 100; i++)
47 {
48 int rand_filter = rand() & 1;
49 if (width > 16)
50 rand_filter = 0;
51
52 pixel left[MAX_CU_SIZE * 2 + 1];
53 for (int k = 0; k < width * 2 + 1; k++)
54 {
55 left[k] = pixel_buff[j - 1 + k * Predict::ADI_BUF_STRIDE];
56 }
57
58 ref(pixel_out_c, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, rand_filter);
59 checked(opt, pixel_out_vec, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, rand_filter);
60
61 for (int k = 0; k < width; k++)
62 {
63 if (memcmp(pixel_out_vec + k * FENC_STRIDE, pixel_out_c + k * FENC_STRIDE, width * sizeof(pixel)))
64 return false;
65 }
66
67 reportfail();
68 j += FENC_STRIDE;
69 }
70
71 return true;
72 }
73
74 bool IntraPredHarness::check_planar_primitive(intra_pred_t ref, intra_pred_t opt, int width)
75 {
76 int j = Predict::ADI_BUF_STRIDE;
77 intptr_t stride = FENC_STRIDE;
78
79 #if _DEBUG
80 memset(pixel_out_vec, 0xCD, OUTPUT_SIZE);
81 memset(pixel_out_c, 0xCD, OUTPUT_SIZE);
82 #endif
83
84 for (int i = 0; i <= 100; i++)
85 {
86 pixel left[MAX_CU_SIZE * 2 + 1];
87 for (int k = 0; k < width * 2 + 1; k++)
88 {
89 left[k] = pixel_buff[j - 1 + k * Predict::ADI_BUF_STRIDE];
90 }
91
92 ref(pixel_out_c, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, 0);
93 checked(opt, pixel_out_vec, stride, pixel_buff + j - Predict::ADI_BUF_STRIDE, left + 1, 0, 0);
94
95 for (int k = 0; k < width; k++)
96 {
97 if (memcmp(pixel_out_vec + k * FENC_STRIDE, pixel_out_c + k * FENC_STRIDE, width * sizeof(pixel)))
98 return false;
99 }
100
101 reportfail();
102 j += FENC_STRIDE;
103 }
104
105 return true;
106 }
107
108 bool IntraPredHarness::check_angular_primitive(const intra_pred_t ref[][NUM_TR_SIZE], const intra_pred_t opt[][NUM_TR_SIZE])
109 {
110 int j = Predict::ADI_BUF_STRIDE;
111 intptr_t stride = FENC_STRIDE;
112
113 #if _DEBUG
114 memset(pixel_out_vec, 0xCD, OUTPUT_SIZE);
115 memset(pixel_out_c, 0xCD, OUTPUT_SIZE);
116 #endif
117
118 for (int size = 2; size <= 5; size++)
119 {
120 int width = (1 << size);
121 for (int i = 0; i <= 100; i++)
122 {
123 int bFilter = (width <= 16) && (rand() % 2);
124 for (int pmode = 2; pmode <= 34; pmode++)
125 {
126 if (!opt[pmode][size - 2])
127 continue;
128
129 pixel * refAbove = pixel_buff + j;
130 pixel * refLeft = refAbove + 3 * width;
131 refLeft[0] = refAbove[0];
132
133 checked(opt[pmode][size - 2], pixel_out_vec, stride, refLeft, refAbove, pmode, bFilter);
134 ref[pmode][size - 2](pixel_out_c, stride, refLeft, refAbove, pmode, bFilter);
135
136 for (int k = 0; k < width; k++)
137 {
138 if (memcmp(pixel_out_vec + k * FENC_STRIDE, pixel_out_c + k * FENC_STRIDE, width * sizeof(pixel)))
139 return false;
140 }
141
142 reportfail();
143 }
144
145 j += FENC_STRIDE;
146 }
147 }
148
149 return true;
150 }
151
152 bool IntraPredHarness::check_allangs_primitive(const intra_allangs_t ref[], const intra_allangs_t opt[])
153 {
154 int j = Predict::ADI_BUF_STRIDE;
155 int isLuma;
156
157 #if _DEBUG
158 memset(pixel_out_33_vec, 0xCD, OUTPUT_SIZE_33);
159 memset(pixel_out_33_c, 0xCD, OUTPUT_SIZE_33);
160 #endif
161
162 for (int size = 2; size <= 5; size++)
163 {
164 if (opt[size - 2] == NULL) continue;
165
166 const int width = (1 << size);
167
168 for (int i = 0; i <= 100; i++)
169 {
170 isLuma = (width <= 16) ? true : false; // bFilter is true for 4x4, 8x8, 16x16 and false for 32x32
171
172 pixel * refAbove0 = pixel_buff + j;
173 pixel * refLeft0 = refAbove0 + 3 * width;
174
175 pixel * refAbove1 = pixel_buff + j + 3 * FENC_STRIDE; // keep this offset, since vector code may broken input buffer range [-(width-1), 0]
176 pixel * refLeft1 = refAbove1 + 3 * width + FENC_STRIDE;
177 refLeft0[0] = refAbove0[0] = refLeft1[0] = refAbove1[0];
178
179 ref[size - 2](pixel_out_33_c, refAbove0, refLeft0, refAbove1, refLeft1, isLuma);
180 checked(opt[size - 2], pixel_out_33_vec, refAbove0, refLeft0, refAbove1, refLeft1, isLuma);
181
182 for (int p = 2 - 2; p <= 34 - 2; p++)
183 {
184 for (int k = 0; k < width; k++)
185 {
186 if (memcmp(pixel_out_33_c + p * (width * width) + k * width, pixel_out_33_vec + p * (width * width) + k * width, width * sizeof(pixel)))
187 {
188 printf("\nFailed: (%dx%d) Mode(%2d), Line[%2d], bfilter=%d\n", width, width, p + 2, k, isLuma);
189 opt[size - 2](pixel_out_33_vec, refAbove0, refLeft0, refAbove1, refLeft1, isLuma);
190 return false;
191 }
192 }
193 }
194
195 reportfail();
196 j += FENC_STRIDE;
197 }
198 }
199
200 return true;
201 }
202
203 bool IntraPredHarness::testCorrectness(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
204 {
205 for (int i = BLOCK_4x4; i <= BLOCK_32x32; i++)
206 {
207 if (opt.intra_pred[1][i])
208 {
209 const int size = (1 << (i + 2));
210 if (!check_dc_primitive(ref.intra_pred[1][i], opt.intra_pred[1][i], size))
211 {
212 printf("intra_dc %dx%d failed\n", size, size);
213 return false;
214 }
215 }
216 if (opt.intra_pred[0][i])
217 {
218 const int size = (1 << (i + 2));
219 if (!check_planar_primitive(ref.intra_pred[0][i], opt.intra_pred[0][i], size))
220 {
221 printf("intra_planar %dx%d failed\n", size, size);
222 return false;
223 }
224 }
225 }
226
227 // NOTE: always call since this function have check pointer in loop
228 if (!check_angular_primitive(ref.intra_pred, opt.intra_pred))
229 {
230 printf("intra_angular failed\n");
231 return false;
232 }
233
234 if (opt.intra_pred_allangs[0])
235 {
236 if (!check_allangs_primitive(ref.intra_pred_allangs, opt.intra_pred_allangs))
237 {
238 printf("intra_allangs failed\n");
239 return false;
240 }
241 }
242
243 return true;
244 }
245
246 void IntraPredHarness::measureSpeed(const EncoderPrimitives& ref, const EncoderPrimitives& opt)
247 {
248 int width = 64;
249 uint16_t srcStride = 96;
250
251 for (int i = BLOCK_4x4; i <= BLOCK_32x32; i++)
252 {
253 const int size = (1 << (i + 2));
254 if (opt.intra_pred[1][i])
255 {
256 printf("intra_dc_%dx%d[f=0]", size, size);
257 REPORT_SPEEDUP(opt.intra_pred[1][i], ref.intra_pred[1][i],
258 pixel_out_vec, FENC_STRIDE, pixel_buff + srcStride, pixel_buff, 0, 0);
259 if (size <= 16)
260 {
261 printf("intra_dc_%dx%d[f=1]", size, size);
262 REPORT_SPEEDUP(opt.intra_pred[1][i], ref.intra_pred[1][i],
263 pixel_out_vec, FENC_STRIDE, pixel_buff + srcStride, pixel_buff, 0, 1);
264 }
265 }
266 if (opt.intra_pred[0][i])
267 {
268 printf("intra_planar %2dx%d", size, size);
269 REPORT_SPEEDUP(opt.intra_pred[0][i], ref.intra_pred[0][i],
270 pixel_out_vec, FENC_STRIDE, pixel_buff + srcStride, pixel_buff, 0, 0);
271 }
272 if (opt.intra_pred_allangs[i])
273 {
274 bool bFilter = (size <= 16);
275 pixel * refAbove = pixel_buff + srcStride;
276 pixel * refLeft = refAbove + 3 * size;
277 refLeft[0] = refAbove[0];
278 printf("intra_allangs%dx%d", size, size);
279 REPORT_SPEEDUP(opt.intra_pred_allangs[i], ref.intra_pred_allangs[i],
280 pixel_out_33_vec, refAbove, refLeft, refAbove, refLeft, bFilter);
281 }
282 }
283
284 for (int ii = 2; ii <= 5; ii++)
285 {
286 for (int p = 2; p <= 34; p += 1)
287 {
288 int pmode = p; //(rand()%33)+2;
289 if (opt.intra_pred[pmode][ii - 2])
290 {
291 width = (1 << ii);
292 bool bFilter = (width <= 16);
293 pixel * refAbove = pixel_buff + srcStride;
294 pixel * refLeft = refAbove + 3 * width;
295 refLeft[0] = refAbove[0];
296 printf("intra_ang%dx%d[%2d]", width, width, pmode);
297 REPORT_SPEEDUP(opt.intra_pred[pmode][ii - 2], ref.intra_pred[pmode][ii - 2],
298 pixel_out_vec, FENC_STRIDE, refAbove, refLeft, pmode, bFilter);
299 }
300 }
301 }
302 }