OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <math.h> | 11 #include <math.h> |
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 #include <string.h> | 13 #include <string.h> |
14 | 14 |
15 #include "third_party/googletest/src/include/gtest/gtest.h" | 15 #include "third_party/googletest/src/include/gtest/gtest.h" |
16 #include "test/acm_random.h" | 16 #include "test/acm_random.h" |
17 #include "test/clear_system_state.h" | 17 #include "test/clear_system_state.h" |
18 #include "test/register_state_check.h" | 18 #include "test/register_state_check.h" |
19 #include "test/util.h" | 19 #include "test/util.h" |
20 | 20 |
21 #include "./vp9_rtcd.h" | 21 #include "./vp9_rtcd.h" |
22 #include "vp9/common/vp9_entropy.h" | 22 #include "vp9/common/vp9_entropy.h" |
| 23 #include "vpx/vpx_codec.h" |
23 #include "vpx/vpx_integer.h" | 24 #include "vpx/vpx_integer.h" |
24 | 25 |
25 extern "C" { | |
26 void vp9_idct16x16_256_add_c(const int16_t *input, uint8_t *output, int pitch); | |
27 } | |
28 | |
29 using libvpx_test::ACMRandom; | 26 using libvpx_test::ACMRandom; |
30 | 27 |
31 namespace { | 28 namespace { |
32 | 29 |
33 #ifdef _MSC_VER | 30 #ifdef _MSC_VER |
34 static int round(double x) { | 31 static int round(double x) { |
35 if (x < 0) | 32 if (x < 0) |
36 return static_cast<int>(ceil(x - 0.5)); | 33 return static_cast<int>(ceil(x - 0.5)); |
37 else | 34 else |
38 return static_cast<int>(floor(x + 0.5)); | 35 return static_cast<int>(floor(x + 0.5)); |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 double temp_in[16], temp_out[16]; | 248 double temp_in[16], temp_out[16]; |
252 for (int j = 0; j < 16; ++j) | 249 for (int j = 0; j < 16; ++j) |
253 temp_in[j] = output[j + i * 16]; | 250 temp_in[j] = output[j + i * 16]; |
254 butterfly_16x16_dct_1d(temp_in, temp_out); | 251 butterfly_16x16_dct_1d(temp_in, temp_out); |
255 // Scale by some magic number | 252 // Scale by some magic number |
256 for (int j = 0; j < 16; ++j) | 253 for (int j = 0; j < 16; ++j) |
257 output[j + i * 16] = temp_out[j]/2; | 254 output[j + i * 16] = temp_out[j]/2; |
258 } | 255 } |
259 } | 256 } |
260 | 257 |
261 typedef void (*FdctFunc)(const int16_t *in, int16_t *out, int stride); | 258 typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride); |
262 typedef void (*IdctFunc)(const int16_t *in, uint8_t *out, int stride); | 259 typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride); |
263 typedef void (*FhtFunc)(const int16_t *in, int16_t *out, int stride, | 260 typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride, |
264 int tx_type); | 261 int tx_type); |
265 typedef void (*IhtFunc)(const int16_t *in, uint8_t *out, int stride, | 262 typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, |
266 int tx_type); | 263 int tx_type); |
267 | 264 |
268 typedef std::tr1::tuple<FdctFunc, IdctFunc, int> Dct16x16Param; | 265 typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param; |
269 typedef std::tr1::tuple<FhtFunc, IhtFunc, int> Ht16x16Param; | 266 typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param; |
270 | 267 |
271 void fdct16x16_ref(const int16_t *in, int16_t *out, int stride, | 268 void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride, |
272 int /*tx_type*/) { | 269 int /*tx_type*/) { |
273 vp9_fdct16x16_c(in, out, stride); | 270 vp9_fdct16x16_c(in, out, stride); |
274 } | 271 } |
275 | 272 |
276 void idct16x16_ref(const int16_t *in, uint8_t *dest, int stride, | 273 void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride, |
277 int /*tx_type*/) { | 274 int /*tx_type*/) { |
278 vp9_idct16x16_256_add_c(in, dest, stride); | 275 vp9_idct16x16_256_add_c(in, dest, stride); |
279 } | 276 } |
280 | 277 |
281 void fht16x16_ref(const int16_t *in, int16_t *out, int stride, int tx_type) { | 278 void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride, |
| 279 int tx_type) { |
282 vp9_fht16x16_c(in, out, stride, tx_type); | 280 vp9_fht16x16_c(in, out, stride, tx_type); |
283 } | 281 } |
284 | 282 |
285 void iht16x16_ref(const int16_t *in, uint8_t *dest, int stride, int tx_type) { | 283 void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride, |
| 284 int tx_type) { |
286 vp9_iht16x16_256_add_c(in, dest, stride, tx_type); | 285 vp9_iht16x16_256_add_c(in, dest, stride, tx_type); |
287 } | 286 } |
288 | 287 |
| 288 #if CONFIG_VP9_HIGHBITDEPTH |
| 289 void idct16x16_10(const tran_low_t *in, uint8_t *out, int stride) { |
| 290 vp9_high_idct16x16_256_add_c(in, out, stride, 10); |
| 291 } |
| 292 |
| 293 void idct16x16_12(const tran_low_t *in, uint8_t *out, int stride) { |
| 294 vp9_high_idct16x16_256_add_c(in, out, stride, 12); |
| 295 } |
| 296 |
| 297 void idct16x16_10_ref(const tran_low_t *in, uint8_t *out, int stride, |
| 298 int tx_type) { |
| 299 idct16x16_10(in, out, stride); |
| 300 } |
| 301 |
| 302 void idct16x16_12_ref(const tran_low_t *in, uint8_t *out, int stride, |
| 303 int tx_type) { |
| 304 idct16x16_12(in, out, stride); |
| 305 } |
| 306 |
| 307 void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { |
| 308 vp9_high_iht16x16_256_add_c(in, out, stride, tx_type, 10); |
| 309 } |
| 310 |
| 311 void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) { |
| 312 vp9_high_iht16x16_256_add_c(in, out, stride, tx_type, 12); |
| 313 } |
| 314 #endif |
| 315 |
289 class Trans16x16TestBase { | 316 class Trans16x16TestBase { |
290 public: | 317 public: |
291 virtual ~Trans16x16TestBase() {} | 318 virtual ~Trans16x16TestBase() {} |
292 | 319 |
293 protected: | 320 protected: |
294 virtual void RunFwdTxfm(int16_t *in, int16_t *out, int stride) = 0; | 321 virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0; |
295 | 322 |
296 virtual void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) = 0; | 323 virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0; |
297 | 324 |
298 void RunAccuracyCheck() { | 325 void RunAccuracyCheck() { |
299 ACMRandom rnd(ACMRandom::DeterministicSeed()); | 326 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
300 uint32_t max_error = 0; | 327 uint32_t max_error = 0; |
301 int64_t total_error = 0; | 328 int64_t total_error = 0; |
302 const int count_test_block = 10000; | 329 const int count_test_block = 10000; |
303 for (int i = 0; i < count_test_block; ++i) { | 330 for (int i = 0; i < count_test_block; ++i) { |
304 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs); | 331 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs); |
305 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, kNumCoeffs); | 332 DECLARE_ALIGNED_ARRAY(16, tran_low_t, test_temp_block, kNumCoeffs); |
306 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); | 333 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); |
307 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); | 334 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); |
| 335 #if CONFIG_VP9_HIGHBITDEPTH |
| 336 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs); |
| 337 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs); |
| 338 #endif |
308 | 339 |
309 // Initialize a test block with input range [-255, 255]. | 340 // Initialize a test block with input range [-mask_, mask_]. |
310 for (int j = 0; j < kNumCoeffs; ++j) { | 341 for (int j = 0; j < kNumCoeffs; ++j) { |
311 src[j] = rnd.Rand8(); | 342 if (bit_depth_ == VPX_BITS_8) { |
312 dst[j] = rnd.Rand8(); | 343 src[j] = rnd.Rand8(); |
313 test_input_block[j] = src[j] - dst[j]; | 344 dst[j] = rnd.Rand8(); |
| 345 test_input_block[j] = src[j] - dst[j]; |
| 346 #if CONFIG_VP9_HIGHBITDEPTH |
| 347 } else { |
| 348 src16[j] = rnd.Rand16() & mask_; |
| 349 dst16[j] = rnd.Rand16() & mask_; |
| 350 test_input_block[j] = src16[j] - dst16[j]; |
| 351 #endif |
| 352 } |
314 } | 353 } |
315 | 354 |
316 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, | 355 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block, |
317 test_temp_block, pitch_)); | 356 test_temp_block, pitch_)); |
318 ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_)); | 357 if (bit_depth_ == VPX_BITS_8) { |
| 358 ASM_REGISTER_STATE_CHECK( |
| 359 RunInvTxfm(test_temp_block, dst, pitch_)); |
| 360 #if CONFIG_VP9_HIGHBITDEPTH |
| 361 } else { |
| 362 ASM_REGISTER_STATE_CHECK( |
| 363 RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); |
| 364 #endif |
| 365 } |
319 | 366 |
320 for (int j = 0; j < kNumCoeffs; ++j) { | 367 for (int j = 0; j < kNumCoeffs; ++j) { |
| 368 #if CONFIG_VP9_HIGHBITDEPTH |
| 369 const uint32_t diff = |
| 370 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; |
| 371 #else |
321 const uint32_t diff = dst[j] - src[j]; | 372 const uint32_t diff = dst[j] - src[j]; |
| 373 #endif |
322 const uint32_t error = diff * diff; | 374 const uint32_t error = diff * diff; |
323 if (max_error < error) | 375 if (max_error < error) |
324 max_error = error; | 376 max_error = error; |
325 total_error += error; | 377 total_error += error; |
326 } | 378 } |
327 } | 379 } |
328 | 380 |
329 EXPECT_GE(1u, max_error) | 381 EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error) |
330 << "Error: 16x16 FHT/IHT has an individual round trip error > 1"; | 382 << "Error: 16x16 FHT/IHT has an individual round trip error > 1"; |
331 | 383 |
332 EXPECT_GE(count_test_block , total_error) | 384 EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error) |
333 << "Error: 16x16 FHT/IHT has average round trip error > 1 per block"; | 385 << "Error: 16x16 FHT/IHT has average round trip error > 1 per block"; |
334 } | 386 } |
335 | 387 |
336 void RunCoeffCheck() { | 388 void RunCoeffCheck() { |
337 ACMRandom rnd(ACMRandom::DeterministicSeed()); | 389 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
338 const int count_test_block = 1000; | 390 const int count_test_block = 1000; |
339 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); | 391 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); |
340 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs); | 392 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs); |
341 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs); | 393 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_block, kNumCoeffs); |
342 | 394 |
343 for (int i = 0; i < count_test_block; ++i) { | 395 for (int i = 0; i < count_test_block; ++i) { |
344 // Initialize a test block with input range [-255, 255]. | 396 // Initialize a test block with input range [-mask_, mask_]. |
345 for (int j = 0; j < kNumCoeffs; ++j) | 397 for (int j = 0; j < kNumCoeffs; ++j) |
346 input_block[j] = rnd.Rand8() - rnd.Rand8(); | 398 input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); |
347 | 399 |
348 fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_); | 400 fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_); |
349 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_)); | 401 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_)); |
350 | 402 |
351 // The minimum quant value is 4. | 403 // The minimum quant value is 4. |
352 for (int j = 0; j < kNumCoeffs; ++j) | 404 for (int j = 0; j < kNumCoeffs; ++j) |
353 EXPECT_EQ(output_block[j], output_ref_block[j]); | 405 EXPECT_EQ(output_block[j], output_ref_block[j]); |
354 } | 406 } |
355 } | 407 } |
356 | 408 |
357 void RunMemCheck() { | 409 void RunMemCheck() { |
358 ACMRandom rnd(ACMRandom::DeterministicSeed()); | 410 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
359 const int count_test_block = 1000; | 411 const int count_test_block = 1000; |
360 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); | 412 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); |
361 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); | 413 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); |
362 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs); | 414 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs); |
363 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs); | 415 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_block, kNumCoeffs); |
364 | 416 |
365 for (int i = 0; i < count_test_block; ++i) { | 417 for (int i = 0; i < count_test_block; ++i) { |
366 // Initialize a test block with input range [-255, 255]. | 418 // Initialize a test block with input range [-mask_, mask_]. |
367 for (int j = 0; j < kNumCoeffs; ++j) { | 419 for (int j = 0; j < kNumCoeffs; ++j) { |
368 input_block[j] = rnd.Rand8() - rnd.Rand8(); | 420 input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); |
369 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255; | 421 input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; |
370 } | 422 } |
371 if (i == 0) { | 423 if (i == 0) { |
372 for (int j = 0; j < kNumCoeffs; ++j) | 424 for (int j = 0; j < kNumCoeffs; ++j) |
373 input_extreme_block[j] = 255; | 425 input_extreme_block[j] = mask_; |
374 } else if (i == 1) { | 426 } else if (i == 1) { |
375 for (int j = 0; j < kNumCoeffs; ++j) | 427 for (int j = 0; j < kNumCoeffs; ++j) |
376 input_extreme_block[j] = -255; | 428 input_extreme_block[j] = -mask_; |
377 } | 429 } |
378 | 430 |
379 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); | 431 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); |
380 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, | 432 ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block, |
381 output_block, pitch_)); | 433 output_block, pitch_)); |
382 | 434 |
383 // The minimum quant value is 4. | 435 // The minimum quant value is 4. |
384 for (int j = 0; j < kNumCoeffs; ++j) { | 436 for (int j = 0; j < kNumCoeffs; ++j) { |
385 EXPECT_EQ(output_block[j], output_ref_block[j]); | 437 EXPECT_EQ(output_block[j], output_ref_block[j]); |
386 EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j])) | 438 EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j])) |
387 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; | 439 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE"; |
388 } | 440 } |
389 } | 441 } |
390 } | 442 } |
391 | 443 |
392 void RunQuantCheck(int dc_thred, int ac_thred) { | 444 void RunQuantCheck(int dc_thred, int ac_thred) { |
393 ACMRandom rnd(ACMRandom::DeterministicSeed()); | 445 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
394 const int count_test_block = 1000; | 446 const int count_test_block = 1000; |
395 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); | 447 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs); |
396 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); | 448 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs); |
397 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs); | 449 DECLARE_ALIGNED_ARRAY(16, tran_low_t, output_ref_block, kNumCoeffs); |
398 | 450 |
399 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); | 451 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); |
400 DECLARE_ALIGNED_ARRAY(16, uint8_t, ref, kNumCoeffs); | 452 DECLARE_ALIGNED_ARRAY(16, uint8_t, ref, kNumCoeffs); |
| 453 #if CONFIG_VP9_HIGHBITDEPTH |
| 454 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs); |
| 455 DECLARE_ALIGNED_ARRAY(16, uint16_t, ref16, kNumCoeffs); |
| 456 #endif |
401 | 457 |
402 for (int i = 0; i < count_test_block; ++i) { | 458 for (int i = 0; i < count_test_block; ++i) { |
403 // Initialize a test block with input range [-255, 255]. | 459 // Initialize a test block with input range [-mask_, mask_]. |
404 for (int j = 0; j < kNumCoeffs; ++j) { | 460 for (int j = 0; j < kNumCoeffs; ++j) { |
405 input_block[j] = rnd.Rand8() - rnd.Rand8(); | 461 if (bit_depth_ == VPX_BITS_8) |
406 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255; | 462 input_block[j] = rnd.Rand8() - rnd.Rand8(); |
| 463 else |
| 464 input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); |
| 465 input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; |
407 } | 466 } |
408 if (i == 0) | 467 if (i == 0) |
409 for (int j = 0; j < kNumCoeffs; ++j) | 468 for (int j = 0; j < kNumCoeffs; ++j) |
410 input_extreme_block[j] = 255; | 469 input_extreme_block[j] = mask_; |
411 if (i == 1) | 470 if (i == 1) |
412 for (int j = 0; j < kNumCoeffs; ++j) | 471 for (int j = 0; j < kNumCoeffs; ++j) |
413 input_extreme_block[j] = -255; | 472 input_extreme_block[j] = -mask_; |
414 | 473 |
415 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); | 474 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_); |
416 | 475 |
417 // clear reconstructed pixel buffers | 476 // clear reconstructed pixel buffers |
418 vpx_memset(dst, 0, kNumCoeffs * sizeof(uint8_t)); | 477 vpx_memset(dst, 0, kNumCoeffs * sizeof(uint8_t)); |
419 vpx_memset(ref, 0, kNumCoeffs * sizeof(uint8_t)); | 478 vpx_memset(ref, 0, kNumCoeffs * sizeof(uint8_t)); |
| 479 #if CONFIG_VP9_HIGHBITDEPTH |
| 480 vpx_memset(dst16, 0, kNumCoeffs * sizeof(uint16_t)); |
| 481 vpx_memset(ref16, 0, kNumCoeffs * sizeof(uint16_t)); |
| 482 #endif |
420 | 483 |
421 // quantization with maximum allowed step sizes | 484 // quantization with maximum allowed step sizes |
422 output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred; | 485 output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred; |
423 for (int j = 1; j < kNumCoeffs; ++j) | 486 for (int j = 1; j < kNumCoeffs; ++j) |
424 output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred; | 487 output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred; |
425 inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_); | 488 if (bit_depth_ == VPX_BITS_8) { |
426 ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_)); | 489 inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_); |
427 | 490 ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_)); |
428 for (int j = 0; j < kNumCoeffs; ++j) | 491 #if CONFIG_VP9_HIGHBITDEPTH |
429 EXPECT_EQ(ref[j], dst[j]); | 492 } else { |
| 493 inv_txfm_ref(output_ref_block, CONVERT_TO_BYTEPTR(ref16), pitch_, |
| 494 tx_type_); |
| 495 ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, |
| 496 CONVERT_TO_BYTEPTR(dst16), pitch_)); |
| 497 #endif |
| 498 } |
| 499 if (bit_depth_ == VPX_BITS_8) { |
| 500 for (int j = 0; j < kNumCoeffs; ++j) |
| 501 EXPECT_EQ(ref[j], dst[j]); |
| 502 #if CONFIG_VP9_HIGHBITDEPTH |
| 503 } else { |
| 504 for (int j = 0; j < kNumCoeffs; ++j) |
| 505 EXPECT_EQ(ref16[j], dst16[j]); |
| 506 #endif |
| 507 } |
430 } | 508 } |
431 } | 509 } |
432 | 510 |
433 void RunInvAccuracyCheck() { | 511 void RunInvAccuracyCheck() { |
434 ACMRandom rnd(ACMRandom::DeterministicSeed()); | 512 ACMRandom rnd(ACMRandom::DeterministicSeed()); |
435 const int count_test_block = 1000; | 513 const int count_test_block = 1000; |
436 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs); | 514 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs); |
437 DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs); | 515 DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff, kNumCoeffs); |
438 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); | 516 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs); |
439 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); | 517 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs); |
| 518 #if CONFIG_VP9_HIGHBITDEPTH |
| 519 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs); |
| 520 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs); |
| 521 #endif |
440 | 522 |
441 for (int i = 0; i < count_test_block; ++i) { | 523 for (int i = 0; i < count_test_block; ++i) { |
442 double out_r[kNumCoeffs]; | 524 double out_r[kNumCoeffs]; |
443 | 525 |
444 // Initialize a test block with input range [-255, 255]. | 526 // Initialize a test block with input range [-255, 255]. |
445 for (int j = 0; j < kNumCoeffs; ++j) { | 527 for (int j = 0; j < kNumCoeffs; ++j) { |
446 src[j] = rnd.Rand8(); | 528 if (bit_depth_ == VPX_BITS_8) { |
447 dst[j] = rnd.Rand8(); | 529 src[j] = rnd.Rand8(); |
448 in[j] = src[j] - dst[j]; | 530 dst[j] = rnd.Rand8(); |
| 531 in[j] = src[j] - dst[j]; |
| 532 #if CONFIG_VP9_HIGHBITDEPTH |
| 533 } else { |
| 534 src16[j] = rnd.Rand16() & mask_; |
| 535 dst16[j] = rnd.Rand16() & mask_; |
| 536 in[j] = src16[j] - dst16[j]; |
| 537 #endif |
| 538 } |
449 } | 539 } |
450 | 540 |
451 reference_16x16_dct_2d(in, out_r); | 541 reference_16x16_dct_2d(in, out_r); |
452 for (int j = 0; j < kNumCoeffs; ++j) | 542 for (int j = 0; j < kNumCoeffs; ++j) |
453 coeff[j] = round(out_r[j]); | 543 coeff[j] = round(out_r[j]); |
454 | 544 |
455 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16)); | 545 if (bit_depth_ == VPX_BITS_8) { |
| 546 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16)); |
| 547 #if CONFIG_VP9_HIGHBITDEPTH |
| 548 } else { |
| 549 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), |
| 550 16)); |
| 551 #endif |
| 552 } |
456 | 553 |
457 for (int j = 0; j < kNumCoeffs; ++j) { | 554 for (int j = 0; j < kNumCoeffs; ++j) { |
| 555 #if CONFIG_VP9_HIGHBITDEPTH |
| 556 const uint32_t diff = |
| 557 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; |
| 558 #else |
458 const uint32_t diff = dst[j] - src[j]; | 559 const uint32_t diff = dst[j] - src[j]; |
| 560 #endif |
459 const uint32_t error = diff * diff; | 561 const uint32_t error = diff * diff; |
460 EXPECT_GE(1u, error) | 562 EXPECT_GE(1u, error) |
461 << "Error: 16x16 IDCT has error " << error | 563 << "Error: 16x16 IDCT has error " << error |
462 << " at index " << j; | 564 << " at index " << j; |
463 } | 565 } |
464 } | 566 } |
465 } | 567 } |
466 int pitch_; | 568 int pitch_; |
467 int tx_type_; | 569 int tx_type_; |
| 570 vpx_bit_depth_t bit_depth_; |
| 571 int mask_; |
468 FhtFunc fwd_txfm_ref; | 572 FhtFunc fwd_txfm_ref; |
469 IhtFunc inv_txfm_ref; | 573 IhtFunc inv_txfm_ref; |
470 }; | 574 }; |
471 | 575 |
472 class Trans16x16DCT | 576 class Trans16x16DCT |
473 : public Trans16x16TestBase, | 577 : public Trans16x16TestBase, |
474 public ::testing::TestWithParam<Dct16x16Param> { | 578 public ::testing::TestWithParam<Dct16x16Param> { |
475 public: | 579 public: |
476 virtual ~Trans16x16DCT() {} | 580 virtual ~Trans16x16DCT() {} |
477 | 581 |
478 virtual void SetUp() { | 582 virtual void SetUp() { |
479 fwd_txfm_ = GET_PARAM(0); | 583 fwd_txfm_ = GET_PARAM(0); |
480 inv_txfm_ = GET_PARAM(1); | 584 inv_txfm_ = GET_PARAM(1); |
481 tx_type_ = GET_PARAM(2); | 585 tx_type_ = GET_PARAM(2); |
| 586 bit_depth_ = GET_PARAM(3); |
482 pitch_ = 16; | 587 pitch_ = 16; |
483 fwd_txfm_ref = fdct16x16_ref; | 588 fwd_txfm_ref = fdct16x16_ref; |
484 inv_txfm_ref = idct16x16_ref; | 589 inv_txfm_ref = idct16x16_ref; |
| 590 mask_ = (1 << bit_depth_) - 1; |
| 591 #if CONFIG_VP9_HIGHBITDEPTH |
| 592 switch (bit_depth_) { |
| 593 case 10: |
| 594 inv_txfm_ref = idct16x16_10_ref; |
| 595 break; |
| 596 case 12: |
| 597 inv_txfm_ref = idct16x16_12_ref; |
| 598 break; |
| 599 default: |
| 600 inv_txfm_ref = idct16x16_ref; |
| 601 break; |
| 602 } |
| 603 #else |
| 604 inv_txfm_ref = idct16x16_ref; |
| 605 #endif |
485 } | 606 } |
486 virtual void TearDown() { libvpx_test::ClearSystemState(); } | 607 virtual void TearDown() { libvpx_test::ClearSystemState(); } |
487 | 608 |
488 protected: | 609 protected: |
489 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { | 610 void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { |
490 fwd_txfm_(in, out, stride); | 611 fwd_txfm_(in, out, stride); |
491 } | 612 } |
492 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { | 613 void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { |
493 inv_txfm_(out, dst, stride); | 614 inv_txfm_(out, dst, stride); |
494 } | 615 } |
495 | 616 |
496 FdctFunc fwd_txfm_; | 617 FdctFunc fwd_txfm_; |
497 IdctFunc inv_txfm_; | 618 IdctFunc inv_txfm_; |
498 }; | 619 }; |
499 | 620 |
500 TEST_P(Trans16x16DCT, AccuracyCheck) { | 621 TEST_P(Trans16x16DCT, AccuracyCheck) { |
501 RunAccuracyCheck(); | 622 RunAccuracyCheck(); |
502 } | 623 } |
(...skipping 19 matching lines...) Expand all Loading... |
522 class Trans16x16HT | 643 class Trans16x16HT |
523 : public Trans16x16TestBase, | 644 : public Trans16x16TestBase, |
524 public ::testing::TestWithParam<Ht16x16Param> { | 645 public ::testing::TestWithParam<Ht16x16Param> { |
525 public: | 646 public: |
526 virtual ~Trans16x16HT() {} | 647 virtual ~Trans16x16HT() {} |
527 | 648 |
528 virtual void SetUp() { | 649 virtual void SetUp() { |
529 fwd_txfm_ = GET_PARAM(0); | 650 fwd_txfm_ = GET_PARAM(0); |
530 inv_txfm_ = GET_PARAM(1); | 651 inv_txfm_ = GET_PARAM(1); |
531 tx_type_ = GET_PARAM(2); | 652 tx_type_ = GET_PARAM(2); |
| 653 bit_depth_ = GET_PARAM(3); |
532 pitch_ = 16; | 654 pitch_ = 16; |
533 fwd_txfm_ref = fht16x16_ref; | 655 fwd_txfm_ref = fht16x16_ref; |
534 inv_txfm_ref = iht16x16_ref; | 656 inv_txfm_ref = iht16x16_ref; |
| 657 mask_ = (1 << bit_depth_) - 1; |
| 658 #if CONFIG_VP9_HIGHBITDEPTH |
| 659 switch (bit_depth_) { |
| 660 case VPX_BITS_10: |
| 661 inv_txfm_ref = iht16x16_10; |
| 662 break; |
| 663 case VPX_BITS_12: |
| 664 inv_txfm_ref = iht16x16_12; |
| 665 break; |
| 666 default: |
| 667 inv_txfm_ref = iht16x16_ref; |
| 668 break; |
| 669 } |
| 670 #else |
| 671 inv_txfm_ref = iht16x16_ref; |
| 672 #endif |
535 } | 673 } |
536 virtual void TearDown() { libvpx_test::ClearSystemState(); } | 674 virtual void TearDown() { libvpx_test::ClearSystemState(); } |
537 | 675 |
538 protected: | 676 protected: |
539 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { | 677 void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) { |
540 fwd_txfm_(in, out, stride, tx_type_); | 678 fwd_txfm_(in, out, stride, tx_type_); |
541 } | 679 } |
542 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { | 680 void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) { |
543 inv_txfm_(out, dst, stride, tx_type_); | 681 inv_txfm_(out, dst, stride, tx_type_); |
544 } | 682 } |
545 | 683 |
546 FhtFunc fwd_txfm_; | 684 FhtFunc fwd_txfm_; |
547 IhtFunc inv_txfm_; | 685 IhtFunc inv_txfm_; |
548 }; | 686 }; |
549 | 687 |
550 TEST_P(Trans16x16HT, AccuracyCheck) { | 688 TEST_P(Trans16x16HT, AccuracyCheck) { |
551 RunAccuracyCheck(); | 689 RunAccuracyCheck(); |
552 } | 690 } |
553 | 691 |
554 TEST_P(Trans16x16HT, CoeffCheck) { | 692 TEST_P(Trans16x16HT, CoeffCheck) { |
555 RunCoeffCheck(); | 693 RunCoeffCheck(); |
556 } | 694 } |
557 | 695 |
558 TEST_P(Trans16x16HT, MemCheck) { | 696 TEST_P(Trans16x16HT, MemCheck) { |
559 RunMemCheck(); | 697 RunMemCheck(); |
560 } | 698 } |
561 | 699 |
562 TEST_P(Trans16x16HT, QuantCheck) { | 700 TEST_P(Trans16x16HT, QuantCheck) { |
563 // The encoder skips any non-DC intra prediction modes, | 701 // The encoder skips any non-DC intra prediction modes, |
564 // when the quantization step size goes beyond 988. | 702 // when the quantization step size goes beyond 988. |
565 RunQuantCheck(549, 988); | 703 RunQuantCheck(549, 988); |
566 } | 704 } |
567 | 705 |
568 using std::tr1::make_tuple; | 706 using std::tr1::make_tuple; |
569 | 707 |
| 708 #if CONFIG_VP9_HIGHBITDEPTH |
570 INSTANTIATE_TEST_CASE_P( | 709 INSTANTIATE_TEST_CASE_P( |
571 C, Trans16x16DCT, | 710 C, Trans16x16DCT, |
572 ::testing::Values( | 711 ::testing::Values( |
573 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0))); | 712 make_tuple(&vp9_high_fdct16x16_c, &idct16x16_10, 0, VPX_BITS_10), |
| 713 make_tuple(&vp9_high_fdct16x16_c, &idct16x16_12, 0, VPX_BITS_12), |
| 714 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0, VPX_BITS_8))); |
| 715 #else |
| 716 INSTANTIATE_TEST_CASE_P( |
| 717 C, Trans16x16DCT, |
| 718 ::testing::Values( |
| 719 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_c, 0, VPX_BITS_8))); |
| 720 #endif |
| 721 |
| 722 #if CONFIG_VP9_HIGHBITDEPTH |
574 INSTANTIATE_TEST_CASE_P( | 723 INSTANTIATE_TEST_CASE_P( |
575 C, Trans16x16HT, | 724 C, Trans16x16HT, |
576 ::testing::Values( | 725 ::testing::Values( |
577 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0), | 726 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 0, VPX_BITS_10), |
578 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1), | 727 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 1, VPX_BITS_10), |
579 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2), | 728 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 2, VPX_BITS_10), |
580 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3))); | 729 make_tuple(&vp9_high_fht16x16_c, &iht16x16_10, 3, VPX_BITS_10), |
| 730 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 0, VPX_BITS_12), |
| 731 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 1, VPX_BITS_12), |
| 732 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 2, VPX_BITS_12), |
| 733 make_tuple(&vp9_high_fht16x16_c, &iht16x16_12, 3, VPX_BITS_12), |
| 734 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), |
| 735 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), |
| 736 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), |
| 737 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8))); |
| 738 #else |
| 739 INSTANTIATE_TEST_CASE_P( |
| 740 C, Trans16x16HT, |
| 741 ::testing::Values( |
| 742 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8), |
| 743 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8), |
| 744 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8), |
| 745 make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8))); |
| 746 #endif |
581 | 747 |
582 #if HAVE_NEON_ASM | 748 #if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH |
583 INSTANTIATE_TEST_CASE_P( | 749 INSTANTIATE_TEST_CASE_P( |
584 NEON, Trans16x16DCT, | 750 NEON, Trans16x16DCT, |
585 ::testing::Values( | 751 ::testing::Values( |
586 make_tuple(&vp9_fdct16x16_c, | 752 make_tuple(&vp9_fdct16x16_c, |
587 &vp9_idct16x16_256_add_neon, 0))); | 753 &vp9_idct16x16_256_add_neon, 0, VPX_BITS_8))); |
588 #endif | 754 #endif |
589 | 755 |
590 #if HAVE_SSE2 | 756 #if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH |
591 INSTANTIATE_TEST_CASE_P( | 757 INSTANTIATE_TEST_CASE_P( |
592 SSE2, Trans16x16DCT, | 758 SSE2, Trans16x16DCT, |
593 ::testing::Values( | 759 ::testing::Values( |
594 make_tuple(&vp9_fdct16x16_sse2, | 760 make_tuple(&vp9_fdct16x16_sse2, |
595 &vp9_idct16x16_256_add_sse2, 0))); | 761 &vp9_idct16x16_256_add_sse2, 0, VPX_BITS_8))); |
596 INSTANTIATE_TEST_CASE_P( | 762 INSTANTIATE_TEST_CASE_P( |
597 SSE2, Trans16x16HT, | 763 SSE2, Trans16x16HT, |
598 ::testing::Values( | 764 ::testing::Values( |
599 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0), | 765 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0, |
600 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1), | 766 VPX_BITS_8), |
601 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2), | 767 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1, |
602 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3))); | 768 VPX_BITS_8), |
| 769 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2, |
| 770 VPX_BITS_8), |
| 771 make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3, |
| 772 VPX_BITS_8))); |
603 #endif | 773 #endif |
604 | 774 |
605 #if HAVE_SSSE3 | 775 #if HAVE_SSSE3 && !CONFIG_VP9_HIGHBITDEPTH |
606 INSTANTIATE_TEST_CASE_P( | 776 INSTANTIATE_TEST_CASE_P( |
607 SSSE3, Trans16x16DCT, | 777 SSSE3, Trans16x16DCT, |
608 ::testing::Values( | 778 ::testing::Values( |
609 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_ssse3, 0))); | 779 make_tuple(&vp9_fdct16x16_c, &vp9_idct16x16_256_add_ssse3, 0, |
| 780 VPX_BITS_8))); |
610 #endif | 781 #endif |
611 } // namespace | 782 } // namespace |
OLD | NEW |