1 /*****************************************************************************
2 * Copyright (C) 2013 x265 project
4 * Authors: Min Chen <chenm003@163.com>
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.
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.
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.
20 * This program is also available under a commercial proprietary license.
21 * For more information, contact us at license @ x265.com.
22 *****************************************************************************/
26 #include "intrapredharness.h"
30 IntraPredHarness::IntraPredHarness()
32 for (int i
= 0; i
< INPUT_SIZE
; i
++)
33 pixel_buff
[i
] = rand() % PIXEL_MAX
;
36 bool IntraPredHarness::check_dc_primitive(intra_pred_t ref
, intra_pred_t opt
, int width
)
38 int j
= Predict::ADI_BUF_STRIDE
;
39 intptr_t stride
= FENC_STRIDE
;
42 memset(pixel_out_vec
, 0xCD, OUTPUT_SIZE
);
43 memset(pixel_out_c
, 0xCD, OUTPUT_SIZE
);
46 for (int i
= 0; i
<= 100; i
++)
48 int rand_filter
= rand() & 1;
52 pixel left
[MAX_CU_SIZE
* 2 + 1];
53 for (int k
= 0; k
< width
* 2 + 1; k
++)
55 left
[k
] = pixel_buff
[j
- 1 + k
* Predict::ADI_BUF_STRIDE
];
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
);
61 for (int k
= 0; k
< width
; k
++)
63 if (memcmp(pixel_out_vec
+ k
* FENC_STRIDE
, pixel_out_c
+ k
* FENC_STRIDE
, width
* sizeof(pixel
)))
74 bool IntraPredHarness::check_planar_primitive(intra_pred_t ref
, intra_pred_t opt
, int width
)
76 int j
= Predict::ADI_BUF_STRIDE
;
77 intptr_t stride
= FENC_STRIDE
;
80 memset(pixel_out_vec
, 0xCD, OUTPUT_SIZE
);
81 memset(pixel_out_c
, 0xCD, OUTPUT_SIZE
);
84 for (int i
= 0; i
<= 100; i
++)
86 pixel left
[MAX_CU_SIZE
* 2 + 1];
87 for (int k
= 0; k
< width
* 2 + 1; k
++)
89 left
[k
] = pixel_buff
[j
- 1 + k
* Predict::ADI_BUF_STRIDE
];
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);
95 for (int k
= 0; k
< width
; k
++)
97 if (memcmp(pixel_out_vec
+ k
* FENC_STRIDE
, pixel_out_c
+ k
* FENC_STRIDE
, width
* sizeof(pixel
)))
108 bool IntraPredHarness::check_angular_primitive(const intra_pred_t ref
[][NUM_TR_SIZE
], const intra_pred_t opt
[][NUM_TR_SIZE
])
110 int j
= Predict::ADI_BUF_STRIDE
;
111 intptr_t stride
= FENC_STRIDE
;
114 memset(pixel_out_vec
, 0xCD, OUTPUT_SIZE
);
115 memset(pixel_out_c
, 0xCD, OUTPUT_SIZE
);
118 for (int size
= 2; size
<= 5; size
++)
120 int width
= (1 << size
);
121 for (int i
= 0; i
<= 100; i
++)
123 int bFilter
= (width
<= 16) && (rand() % 2);
124 for (int pmode
= 2; pmode
<= 34; pmode
++)
126 if (!opt
[pmode
][size
- 2])
129 pixel
* refAbove
= pixel_buff
+ j
;
130 pixel
* refLeft
= refAbove
+ 3 * width
;
131 refLeft
[0] = refAbove
[0];
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
);
136 for (int k
= 0; k
< width
; k
++)
138 if (memcmp(pixel_out_vec
+ k
* FENC_STRIDE
, pixel_out_c
+ k
* FENC_STRIDE
, width
* sizeof(pixel
)))
152 bool IntraPredHarness::check_allangs_primitive(const intra_allangs_t ref
[], const intra_allangs_t opt
[])
154 int j
= Predict::ADI_BUF_STRIDE
;
158 memset(pixel_out_33_vec
, 0xCD, OUTPUT_SIZE_33
);
159 memset(pixel_out_33_c
, 0xCD, OUTPUT_SIZE_33
);
162 for (int size
= 2; size
<= 5; size
++)
164 if (opt
[size
- 2] == NULL
) continue;
166 const int width
= (1 << size
);
168 for (int i
= 0; i
<= 100; i
++)
170 isLuma
= (width
<= 16) ? true : false; // bFilter is true for 4x4, 8x8, 16x16 and false for 32x32
172 pixel
* refAbove0
= pixel_buff
+ j
;
173 pixel
* refLeft0
= refAbove0
+ 3 * width
;
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];
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
);
182 for (int p
= 2 - 2; p
<= 34 - 2; p
++)
184 for (int k
= 0; k
< width
; k
++)
186 if (memcmp(pixel_out_33_c
+ p
* (width
* width
) + k
* width
, pixel_out_33_vec
+ p
* (width
* width
) + k
* width
, width
* sizeof(pixel
)))
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
);
203 bool IntraPredHarness::testCorrectness(const EncoderPrimitives
& ref
, const EncoderPrimitives
& opt
)
205 for (int i
= BLOCK_4x4
; i
<= BLOCK_32x32
; i
++)
207 if (opt
.intra_pred
[1][i
])
209 const int size
= (1 << (i
+ 2));
210 if (!check_dc_primitive(ref
.intra_pred
[1][i
], opt
.intra_pred
[1][i
], size
))
212 printf("intra_dc %dx%d failed\n", size
, size
);
216 if (opt
.intra_pred
[0][i
])
218 const int size
= (1 << (i
+ 2));
219 if (!check_planar_primitive(ref
.intra_pred
[0][i
], opt
.intra_pred
[0][i
], size
))
221 printf("intra_planar %dx%d failed\n", size
, size
);
227 // NOTE: always call since this function have check pointer in loop
228 if (!check_angular_primitive(ref
.intra_pred
, opt
.intra_pred
))
230 printf("intra_angular failed\n");
234 if (opt
.intra_pred_allangs
[0])
236 if (!check_allangs_primitive(ref
.intra_pred_allangs
, opt
.intra_pred_allangs
))
238 printf("intra_allangs failed\n");
246 void IntraPredHarness::measureSpeed(const EncoderPrimitives
& ref
, const EncoderPrimitives
& opt
)
249 uint16_t srcStride
= 96;
251 for (int i
= BLOCK_4x4
; i
<= BLOCK_32x32
; i
++)
253 const int size
= (1 << (i
+ 2));
254 if (opt
.intra_pred
[1][i
])
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);
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);
266 if (opt
.intra_pred
[0][i
])
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);
272 if (opt
.intra_pred_allangs
[i
])
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
);
284 for (int ii
= 2; ii
<= 5; ii
++)
286 for (int p
= 2; p
<= 34; p
+= 1)
288 int pmode
= p
; //(rand()%33)+2;
289 if (opt
.intra_pred
[pmode
][ii
- 2])
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
);