123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930 |
- /*
- * Copyright 2011 The LibYuv Project Authors. All rights reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
- #include <stdlib.h>
- #include <time.h>
- #include "../unit_test/unit_test.h"
- #include "libyuv/cpu_id.h"
- #include "libyuv/scale.h"
- #ifdef ENABLE_ROW_TESTS
- #include "libyuv/scale_row.h" // For ScaleRowDown2Box_Odd_C
- #endif
- #define STRINGIZE(line) #line
- #define FILELINESTR(file, line) file ":" STRINGIZE(line)
- namespace libyuv {
- // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
- static int I420TestFilter(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- FilterMode f,
- int benchmark_iterations,
- int disable_cpu_flags,
- int benchmark_cpu_info) {
- if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
- return 0;
- }
- int i, j;
- int src_width_uv = (Abs(src_width) + 1) >> 1;
- int src_height_uv = (Abs(src_height) + 1) >> 1;
- int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
- int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
- int src_stride_y = Abs(src_width);
- int src_stride_uv = src_width_uv;
- align_buffer_page_end(src_y, src_y_plane_size);
- align_buffer_page_end(src_u, src_uv_plane_size);
- align_buffer_page_end(src_v, src_uv_plane_size);
- if (!src_y || !src_u || !src_v) {
- printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
- return 0;
- }
- MemRandomize(src_y, src_y_plane_size);
- MemRandomize(src_u, src_uv_plane_size);
- MemRandomize(src_v, src_uv_plane_size);
- int dst_width_uv = (dst_width + 1) >> 1;
- int dst_height_uv = (dst_height + 1) >> 1;
- int64_t dst_y_plane_size = (dst_width) * (dst_height);
- int64_t dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
- int dst_stride_y = dst_width;
- int dst_stride_uv = dst_width_uv;
- align_buffer_page_end(dst_y_c, dst_y_plane_size);
- align_buffer_page_end(dst_u_c, dst_uv_plane_size);
- align_buffer_page_end(dst_v_c, dst_uv_plane_size);
- align_buffer_page_end(dst_y_opt, dst_y_plane_size);
- align_buffer_page_end(dst_u_opt, dst_uv_plane_size);
- align_buffer_page_end(dst_v_opt, dst_uv_plane_size);
- if (!dst_y_c || !dst_u_c || !dst_v_c || !dst_y_opt || !dst_u_opt ||
- !dst_v_opt) {
- printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
- return 0;
- }
- MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
- double c_time = get_time();
- I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
- src_width, src_height, dst_y_c, dst_stride_y, dst_u_c,
- dst_stride_uv, dst_v_c, dst_stride_uv, dst_width, dst_height, f);
- c_time = (get_time() - c_time);
- MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
- double opt_time = get_time();
- for (i = 0; i < benchmark_iterations; ++i) {
- I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
- src_width, src_height, dst_y_opt, dst_stride_y, dst_u_opt,
- dst_stride_uv, dst_v_opt, dst_stride_uv, dst_width, dst_height,
- f);
- }
- opt_time = (get_time() - opt_time) / benchmark_iterations;
- // Report performance of C vs OPT.
- printf("filter %d - %8d us C - %8d us OPT\n", f,
- static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
- // C version may be a little off from the optimized. Order of
- // operations may introduce rounding somewhere. So do a difference
- // of the buffers and look to see that the max difference is not
- // over 3.
- int max_diff = 0;
- for (i = 0; i < (dst_height); ++i) {
- for (j = 0; j < (dst_width); ++j) {
- int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
- dst_y_opt[(i * dst_stride_y) + j]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- }
- for (i = 0; i < (dst_height_uv); ++i) {
- for (j = 0; j < (dst_width_uv); ++j) {
- int abs_diff = Abs(dst_u_c[(i * dst_stride_uv) + j] -
- dst_u_opt[(i * dst_stride_uv) + j]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- abs_diff = Abs(dst_v_c[(i * dst_stride_uv) + j] -
- dst_v_opt[(i * dst_stride_uv) + j]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- }
- free_aligned_buffer_page_end(dst_y_c);
- free_aligned_buffer_page_end(dst_u_c);
- free_aligned_buffer_page_end(dst_v_c);
- free_aligned_buffer_page_end(dst_y_opt);
- free_aligned_buffer_page_end(dst_u_opt);
- free_aligned_buffer_page_end(dst_v_opt);
- free_aligned_buffer_page_end(src_y);
- free_aligned_buffer_page_end(src_u);
- free_aligned_buffer_page_end(src_v);
- return max_diff;
- }
- // Test scaling with 8 bit C vs 16 bit C and return maximum pixel difference.
- // 0 = exact.
- static int I420TestFilter_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- FilterMode f,
- int benchmark_iterations,
- int disable_cpu_flags,
- int benchmark_cpu_info) {
- if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
- return 0;
- }
- int i;
- int src_width_uv = (Abs(src_width) + 1) >> 1;
- int src_height_uv = (Abs(src_height) + 1) >> 1;
- int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
- int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
- int src_stride_y = Abs(src_width);
- int src_stride_uv = src_width_uv;
- align_buffer_page_end(src_y, src_y_plane_size);
- align_buffer_page_end(src_u, src_uv_plane_size);
- align_buffer_page_end(src_v, src_uv_plane_size);
- align_buffer_page_end(src_y_16, src_y_plane_size * 2);
- align_buffer_page_end(src_u_16, src_uv_plane_size * 2);
- align_buffer_page_end(src_v_16, src_uv_plane_size * 2);
- if (!src_y || !src_u || !src_v || !src_y_16 || !src_u_16 || !src_v_16) {
- printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
- return 0;
- }
- uint16_t* p_src_y_16 = reinterpret_cast<uint16_t*>(src_y_16);
- uint16_t* p_src_u_16 = reinterpret_cast<uint16_t*>(src_u_16);
- uint16_t* p_src_v_16 = reinterpret_cast<uint16_t*>(src_v_16);
- MemRandomize(src_y, src_y_plane_size);
- MemRandomize(src_u, src_uv_plane_size);
- MemRandomize(src_v, src_uv_plane_size);
- for (i = 0; i < src_y_plane_size; ++i) {
- p_src_y_16[i] = src_y[i];
- }
- for (i = 0; i < src_uv_plane_size; ++i) {
- p_src_u_16[i] = src_u[i];
- p_src_v_16[i] = src_v[i];
- }
- int dst_width_uv = (dst_width + 1) >> 1;
- int dst_height_uv = (dst_height + 1) >> 1;
- int dst_y_plane_size = (dst_width) * (dst_height);
- int dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
- int dst_stride_y = dst_width;
- int dst_stride_uv = dst_width_uv;
- align_buffer_page_end(dst_y_8, dst_y_plane_size);
- align_buffer_page_end(dst_u_8, dst_uv_plane_size);
- align_buffer_page_end(dst_v_8, dst_uv_plane_size);
- align_buffer_page_end(dst_y_16, dst_y_plane_size * 2);
- align_buffer_page_end(dst_u_16, dst_uv_plane_size * 2);
- align_buffer_page_end(dst_v_16, dst_uv_plane_size * 2);
- uint16_t* p_dst_y_16 = reinterpret_cast<uint16_t*>(dst_y_16);
- uint16_t* p_dst_u_16 = reinterpret_cast<uint16_t*>(dst_u_16);
- uint16_t* p_dst_v_16 = reinterpret_cast<uint16_t*>(dst_v_16);
- MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
- I420Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
- src_width, src_height, dst_y_8, dst_stride_y, dst_u_8,
- dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f);
- MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
- for (i = 0; i < benchmark_iterations; ++i) {
- I420Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv,
- p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16,
- dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16,
- dst_stride_uv, dst_width, dst_height, f);
- }
- // Expect an exact match.
- int max_diff = 0;
- for (i = 0; i < dst_y_plane_size; ++i) {
- int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- for (i = 0; i < dst_uv_plane_size; ++i) {
- int abs_diff = Abs(dst_u_8[i] - p_dst_u_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- abs_diff = Abs(dst_v_8[i] - p_dst_v_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- free_aligned_buffer_page_end(dst_y_8);
- free_aligned_buffer_page_end(dst_u_8);
- free_aligned_buffer_page_end(dst_v_8);
- free_aligned_buffer_page_end(dst_y_16);
- free_aligned_buffer_page_end(dst_u_16);
- free_aligned_buffer_page_end(dst_v_16);
- free_aligned_buffer_page_end(src_y);
- free_aligned_buffer_page_end(src_u);
- free_aligned_buffer_page_end(src_v);
- free_aligned_buffer_page_end(src_y_16);
- free_aligned_buffer_page_end(src_u_16);
- free_aligned_buffer_page_end(src_v_16);
- return max_diff;
- }
- // Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
- static int I444TestFilter(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- FilterMode f,
- int benchmark_iterations,
- int disable_cpu_flags,
- int benchmark_cpu_info) {
- if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
- return 0;
- }
- int i, j;
- int src_width_uv = Abs(src_width);
- int src_height_uv = Abs(src_height);
- int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
- int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
- int src_stride_y = Abs(src_width);
- int src_stride_uv = src_width_uv;
- align_buffer_page_end(src_y, src_y_plane_size);
- align_buffer_page_end(src_u, src_uv_plane_size);
- align_buffer_page_end(src_v, src_uv_plane_size);
- if (!src_y || !src_u || !src_v) {
- printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
- return 0;
- }
- MemRandomize(src_y, src_y_plane_size);
- MemRandomize(src_u, src_uv_plane_size);
- MemRandomize(src_v, src_uv_plane_size);
- int dst_width_uv = dst_width;
- int dst_height_uv = dst_height;
- int64_t dst_y_plane_size = (dst_width) * (dst_height);
- int64_t dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
- int dst_stride_y = dst_width;
- int dst_stride_uv = dst_width_uv;
- align_buffer_page_end(dst_y_c, dst_y_plane_size);
- align_buffer_page_end(dst_u_c, dst_uv_plane_size);
- align_buffer_page_end(dst_v_c, dst_uv_plane_size);
- align_buffer_page_end(dst_y_opt, dst_y_plane_size);
- align_buffer_page_end(dst_u_opt, dst_uv_plane_size);
- align_buffer_page_end(dst_v_opt, dst_uv_plane_size);
- if (!dst_y_c || !dst_u_c || !dst_v_c || !dst_y_opt || !dst_u_opt ||
- !dst_v_opt) {
- printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
- return 0;
- }
- MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
- double c_time = get_time();
- I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
- src_width, src_height, dst_y_c, dst_stride_y, dst_u_c,
- dst_stride_uv, dst_v_c, dst_stride_uv, dst_width, dst_height, f);
- c_time = (get_time() - c_time);
- MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
- double opt_time = get_time();
- for (i = 0; i < benchmark_iterations; ++i) {
- I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
- src_width, src_height, dst_y_opt, dst_stride_y, dst_u_opt,
- dst_stride_uv, dst_v_opt, dst_stride_uv, dst_width, dst_height,
- f);
- }
- opt_time = (get_time() - opt_time) / benchmark_iterations;
- // Report performance of C vs OPT.
- printf("filter %d - %8d us C - %8d us OPT\n", f,
- static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
- // C version may be a little off from the optimized. Order of
- // operations may introduce rounding somewhere. So do a difference
- // of the buffers and look to see that the max difference is not
- // over 3.
- int max_diff = 0;
- for (i = 0; i < (dst_height); ++i) {
- for (j = 0; j < (dst_width); ++j) {
- int abs_diff = Abs(dst_y_c[(i * dst_stride_y) + j] -
- dst_y_opt[(i * dst_stride_y) + j]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- }
- for (i = 0; i < (dst_height_uv); ++i) {
- for (j = 0; j < (dst_width_uv); ++j) {
- int abs_diff = Abs(dst_u_c[(i * dst_stride_uv) + j] -
- dst_u_opt[(i * dst_stride_uv) + j]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- abs_diff = Abs(dst_v_c[(i * dst_stride_uv) + j] -
- dst_v_opt[(i * dst_stride_uv) + j]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- }
- free_aligned_buffer_page_end(dst_y_c);
- free_aligned_buffer_page_end(dst_u_c);
- free_aligned_buffer_page_end(dst_v_c);
- free_aligned_buffer_page_end(dst_y_opt);
- free_aligned_buffer_page_end(dst_u_opt);
- free_aligned_buffer_page_end(dst_v_opt);
- free_aligned_buffer_page_end(src_y);
- free_aligned_buffer_page_end(src_u);
- free_aligned_buffer_page_end(src_v);
- return max_diff;
- }
- // Test scaling with 8 bit C vs 16 bit C and return maximum pixel difference.
- // 0 = exact.
- static int I444TestFilter_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- FilterMode f,
- int benchmark_iterations,
- int disable_cpu_flags,
- int benchmark_cpu_info) {
- if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
- return 0;
- }
- int i;
- int src_width_uv = Abs(src_width);
- int src_height_uv = Abs(src_height);
- int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
- int64_t src_uv_plane_size = (src_width_uv) * (src_height_uv);
- int src_stride_y = Abs(src_width);
- int src_stride_uv = src_width_uv;
- align_buffer_page_end(src_y, src_y_plane_size);
- align_buffer_page_end(src_u, src_uv_plane_size);
- align_buffer_page_end(src_v, src_uv_plane_size);
- align_buffer_page_end(src_y_16, src_y_plane_size * 2);
- align_buffer_page_end(src_u_16, src_uv_plane_size * 2);
- align_buffer_page_end(src_v_16, src_uv_plane_size * 2);
- if (!src_y || !src_u || !src_v || !src_y_16 || !src_u_16 || !src_v_16) {
- printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
- return 0;
- }
- uint16_t* p_src_y_16 = reinterpret_cast<uint16_t*>(src_y_16);
- uint16_t* p_src_u_16 = reinterpret_cast<uint16_t*>(src_u_16);
- uint16_t* p_src_v_16 = reinterpret_cast<uint16_t*>(src_v_16);
- MemRandomize(src_y, src_y_plane_size);
- MemRandomize(src_u, src_uv_plane_size);
- MemRandomize(src_v, src_uv_plane_size);
- for (i = 0; i < src_y_plane_size; ++i) {
- p_src_y_16[i] = src_y[i];
- }
- for (i = 0; i < src_uv_plane_size; ++i) {
- p_src_u_16[i] = src_u[i];
- p_src_v_16[i] = src_v[i];
- }
- int dst_width_uv = dst_width;
- int dst_height_uv = dst_height;
- int dst_y_plane_size = (dst_width) * (dst_height);
- int dst_uv_plane_size = (dst_width_uv) * (dst_height_uv);
- int dst_stride_y = dst_width;
- int dst_stride_uv = dst_width_uv;
- align_buffer_page_end(dst_y_8, dst_y_plane_size);
- align_buffer_page_end(dst_u_8, dst_uv_plane_size);
- align_buffer_page_end(dst_v_8, dst_uv_plane_size);
- align_buffer_page_end(dst_y_16, dst_y_plane_size * 2);
- align_buffer_page_end(dst_u_16, dst_uv_plane_size * 2);
- align_buffer_page_end(dst_v_16, dst_uv_plane_size * 2);
- uint16_t* p_dst_y_16 = reinterpret_cast<uint16_t*>(dst_y_16);
- uint16_t* p_dst_u_16 = reinterpret_cast<uint16_t*>(dst_u_16);
- uint16_t* p_dst_v_16 = reinterpret_cast<uint16_t*>(dst_v_16);
- MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
- I444Scale(src_y, src_stride_y, src_u, src_stride_uv, src_v, src_stride_uv,
- src_width, src_height, dst_y_8, dst_stride_y, dst_u_8,
- dst_stride_uv, dst_v_8, dst_stride_uv, dst_width, dst_height, f);
- MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
- for (i = 0; i < benchmark_iterations; ++i) {
- I444Scale_16(p_src_y_16, src_stride_y, p_src_u_16, src_stride_uv,
- p_src_v_16, src_stride_uv, src_width, src_height, p_dst_y_16,
- dst_stride_y, p_dst_u_16, dst_stride_uv, p_dst_v_16,
- dst_stride_uv, dst_width, dst_height, f);
- }
- // Expect an exact match.
- int max_diff = 0;
- for (i = 0; i < dst_y_plane_size; ++i) {
- int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- for (i = 0; i < dst_uv_plane_size; ++i) {
- int abs_diff = Abs(dst_u_8[i] - p_dst_u_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- abs_diff = Abs(dst_v_8[i] - p_dst_v_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- free_aligned_buffer_page_end(dst_y_8);
- free_aligned_buffer_page_end(dst_u_8);
- free_aligned_buffer_page_end(dst_v_8);
- free_aligned_buffer_page_end(dst_y_16);
- free_aligned_buffer_page_end(dst_u_16);
- free_aligned_buffer_page_end(dst_v_16);
- free_aligned_buffer_page_end(src_y);
- free_aligned_buffer_page_end(src_u);
- free_aligned_buffer_page_end(src_v);
- free_aligned_buffer_page_end(src_y_16);
- free_aligned_buffer_page_end(src_u_16);
- free_aligned_buffer_page_end(src_v_16);
- return max_diff;
- }
- // The following adjustments in dimensions ensure the scale factor will be
- // exactly achieved.
- // 2 is chroma subsample.
- #define DX(x, nom, denom) static_cast<int>(((Abs(x) / nom + 1) / 2) * nom * 2)
- #define SX(x, nom, denom) static_cast<int>(((x / nom + 1) / 2) * denom * 2)
- #define TEST_FACTOR1(DISABLED_, name, filter, nom, denom, max_diff) \
- TEST_F(LibYUVScaleTest, I420ScaleDownBy##name##_##filter) { \
- int diff = I420TestFilter( \
- SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
- DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
- kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, I444ScaleDownBy##name##_##filter) { \
- int diff = I444TestFilter( \
- SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
- DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
- kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, DISABLED_##I420ScaleDownBy##name##_##filter##_16) { \
- int diff = I420TestFilter_16( \
- SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
- DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
- kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, DISABLED_##I444ScaleDownBy##name##_##filter##_16) { \
- int diff = I444TestFilter_16( \
- SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
- DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
- kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- }
- // Test a scale factor with all 4 filters. Expect unfiltered to be exact, but
- // filtering is different fixed point implementations for SSSE3, Neon and C.
- #ifdef ENABLE_SLOW_TESTS
- #define TEST_FACTOR(name, nom, denom, boxdiff) \
- TEST_FACTOR1(, name, None, nom, denom, 0) \
- TEST_FACTOR1(, name, Linear, nom, denom, 3) \
- TEST_FACTOR1(, name, Bilinear, nom, denom, 3) \
- TEST_FACTOR1(, name, Box, nom, denom, boxdiff)
- #else
- #define TEST_FACTOR(name, nom, denom, boxdiff) \
- TEST_FACTOR1(DISABLED_, name, None, nom, denom, 0) \
- TEST_FACTOR1(DISABLED_, name, Linear, nom, denom, 3) \
- TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3) \
- TEST_FACTOR1(DISABLED_, name, Box, nom, denom, boxdiff)
- #endif
- TEST_FACTOR(2, 1, 2, 0)
- TEST_FACTOR(4, 1, 4, 0)
- // TEST_FACTOR(8, 1, 8, 0) Disable for benchmark performance. Takes 90 seconds.
- TEST_FACTOR(3by4, 3, 4, 1)
- TEST_FACTOR(3by8, 3, 8, 1)
- TEST_FACTOR(3, 1, 3, 0)
- #undef TEST_FACTOR1
- #undef TEST_FACTOR
- #undef SX
- #undef DX
- #define TEST_SCALETO1(DISABLED_, name, width, height, filter, max_diff) \
- TEST_F(LibYUVScaleTest, I420##name##To##width##x##height##_##filter) { \
- int diff = I420TestFilter(benchmark_width_, benchmark_height_, width, \
- height, kFilter##filter, benchmark_iterations_, \
- disable_cpu_flags_, benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, I444##name##To##width##x##height##_##filter) { \
- int diff = I444TestFilter(benchmark_width_, benchmark_height_, width, \
- height, kFilter##filter, benchmark_iterations_, \
- disable_cpu_flags_, benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, \
- DISABLED_##I420##name##To##width##x##height##_##filter##_16) { \
- int diff = I420TestFilter_16( \
- benchmark_width_, benchmark_height_, width, height, kFilter##filter, \
- benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, \
- DISABLED_##I444##name##To##width##x##height##_##filter##_16) { \
- int diff = I444TestFilter_16( \
- benchmark_width_, benchmark_height_, width, height, kFilter##filter, \
- benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, I420##name##From##width##x##height##_##filter) { \
- int diff = I420TestFilter(width, height, Abs(benchmark_width_), \
- Abs(benchmark_height_), kFilter##filter, \
- benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, I444##name##From##width##x##height##_##filter) { \
- int diff = I444TestFilter(width, height, Abs(benchmark_width_), \
- Abs(benchmark_height_), kFilter##filter, \
- benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, \
- DISABLED_##I420##name##From##width##x##height##_##filter##_16) { \
- int diff = I420TestFilter_16(width, height, Abs(benchmark_width_), \
- Abs(benchmark_height_), kFilter##filter, \
- benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- } \
- TEST_F(LibYUVScaleTest, \
- DISABLED_##I444##name##From##width##x##height##_##filter##_16) { \
- int diff = I444TestFilter_16(width, height, Abs(benchmark_width_), \
- Abs(benchmark_height_), kFilter##filter, \
- benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- }
- #ifdef ENABLE_SLOW_TESTS
- // Test scale to a specified size with all 4 filters.
- #define TEST_SCALETO(name, width, height) \
- TEST_SCALETO1(, name, width, height, None, 0) \
- TEST_SCALETO1(, name, width, height, Linear, 3) \
- TEST_SCALETO1(, name, width, height, Bilinear, 3) \
- TEST_SCALETO1(, name, width, height, Box, 3)
- #else
- // Test scale to a specified size with all 4 filters.
- #define TEST_SCALETO(name, width, height) \
- TEST_SCALETO1(DISABLED_, name, width, height, None, 0) \
- TEST_SCALETO1(DISABLED_, name, width, height, Linear, 3) \
- TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3) \
- TEST_SCALETO1(DISABLED_, name, width, height, Box, 3)
- #endif
- TEST_SCALETO(Scale, 1, 1)
- TEST_SCALETO(Scale, 320, 240)
- TEST_SCALETO(Scale, 569, 480)
- TEST_SCALETO(Scale, 640, 360)
- TEST_SCALETO(Scale, 1280, 720)
- #ifdef ENABLE_SLOW_TESTS
- TEST_SCALETO(Scale, 1920, 1080)
- #endif // ENABLE_SLOW_TESTS
- #undef TEST_SCALETO1
- #undef TEST_SCALETO
- #ifdef ENABLE_ROW_TESTS
- #ifdef HAS_SCALEROWDOWN2_SSSE3
- TEST_F(LibYUVScaleTest, TestScaleRowDown2Box_Odd_SSSE3) {
- SIMD_ALIGNED(uint8_t orig_pixels[128 * 2]);
- SIMD_ALIGNED(uint8_t dst_pixels_opt[64]);
- SIMD_ALIGNED(uint8_t dst_pixels_c[64]);
- memset(orig_pixels, 0, sizeof(orig_pixels));
- memset(dst_pixels_opt, 0, sizeof(dst_pixels_opt));
- memset(dst_pixels_c, 0, sizeof(dst_pixels_c));
- int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
- if (!has_ssse3) {
- printf("Warning SSSE3 not detected; Skipping test.\n");
- } else {
- // TL.
- orig_pixels[0] = 255u;
- orig_pixels[1] = 0u;
- orig_pixels[128 + 0] = 0u;
- orig_pixels[128 + 1] = 0u;
- // TR.
- orig_pixels[2] = 0u;
- orig_pixels[3] = 100u;
- orig_pixels[128 + 2] = 0u;
- orig_pixels[128 + 3] = 0u;
- // BL.
- orig_pixels[4] = 0u;
- orig_pixels[5] = 0u;
- orig_pixels[128 + 4] = 50u;
- orig_pixels[128 + 5] = 0u;
- // BR.
- orig_pixels[6] = 0u;
- orig_pixels[7] = 0u;
- orig_pixels[128 + 6] = 0u;
- orig_pixels[128 + 7] = 20u;
- // Odd.
- orig_pixels[126] = 4u;
- orig_pixels[127] = 255u;
- orig_pixels[128 + 126] = 16u;
- orig_pixels[128 + 127] = 255u;
- // Test regular half size.
- ScaleRowDown2Box_C(orig_pixels, 128, dst_pixels_c, 64);
- EXPECT_EQ(64u, dst_pixels_c[0]);
- EXPECT_EQ(25u, dst_pixels_c[1]);
- EXPECT_EQ(13u, dst_pixels_c[2]);
- EXPECT_EQ(5u, dst_pixels_c[3]);
- EXPECT_EQ(0u, dst_pixels_c[4]);
- EXPECT_EQ(133u, dst_pixels_c[63]);
- // Test Odd width version - Last pixel is just 1 horizontal pixel.
- ScaleRowDown2Box_Odd_C(orig_pixels, 128, dst_pixels_c, 64);
- EXPECT_EQ(64u, dst_pixels_c[0]);
- EXPECT_EQ(25u, dst_pixels_c[1]);
- EXPECT_EQ(13u, dst_pixels_c[2]);
- EXPECT_EQ(5u, dst_pixels_c[3]);
- EXPECT_EQ(0u, dst_pixels_c[4]);
- EXPECT_EQ(10u, dst_pixels_c[63]);
- // Test one pixel less, should skip the last pixel.
- memset(dst_pixels_c, 0, sizeof(dst_pixels_c));
- ScaleRowDown2Box_Odd_C(orig_pixels, 128, dst_pixels_c, 63);
- EXPECT_EQ(64u, dst_pixels_c[0]);
- EXPECT_EQ(25u, dst_pixels_c[1]);
- EXPECT_EQ(13u, dst_pixels_c[2]);
- EXPECT_EQ(5u, dst_pixels_c[3]);
- EXPECT_EQ(0u, dst_pixels_c[4]);
- EXPECT_EQ(0u, dst_pixels_c[63]);
- // Test regular half size SSSE3.
- ScaleRowDown2Box_SSSE3(orig_pixels, 128, dst_pixels_opt, 64);
- EXPECT_EQ(64u, dst_pixels_opt[0]);
- EXPECT_EQ(25u, dst_pixels_opt[1]);
- EXPECT_EQ(13u, dst_pixels_opt[2]);
- EXPECT_EQ(5u, dst_pixels_opt[3]);
- EXPECT_EQ(0u, dst_pixels_opt[4]);
- EXPECT_EQ(133u, dst_pixels_opt[63]);
- // Compare C and SSSE3 match.
- ScaleRowDown2Box_Odd_C(orig_pixels, 128, dst_pixels_c, 64);
- ScaleRowDown2Box_Odd_SSSE3(orig_pixels, 128, dst_pixels_opt, 64);
- for (int i = 0; i < 64; ++i) {
- EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
- }
- }
- }
- #endif // HAS_SCALEROWDOWN2_SSSE3
- extern "C" void ScaleRowUp2_16_NEON(const uint16_t* src_ptr,
- ptrdiff_t src_stride,
- uint16_t* dst,
- int dst_width);
- extern "C" void ScaleRowUp2_16_MMI(const uint16_t* src_ptr,
- ptrdiff_t src_stride,
- uint16_t* dst,
- int dst_width);
- extern "C" void ScaleRowUp2_16_C(const uint16_t* src_ptr,
- ptrdiff_t src_stride,
- uint16_t* dst,
- int dst_width);
- TEST_F(LibYUVScaleTest, TestScaleRowUp2_16) {
- SIMD_ALIGNED(uint16_t orig_pixels[640 * 2 + 1]); // 2 rows + 1 pixel overrun.
- SIMD_ALIGNED(uint16_t dst_pixels_opt[1280]);
- SIMD_ALIGNED(uint16_t dst_pixels_c[1280]);
- memset(orig_pixels, 0, sizeof(orig_pixels));
- memset(dst_pixels_opt, 1, sizeof(dst_pixels_opt));
- memset(dst_pixels_c, 2, sizeof(dst_pixels_c));
- for (int i = 0; i < 640 * 2 + 1; ++i) {
- orig_pixels[i] = i;
- }
- ScaleRowUp2_16_C(&orig_pixels[0], 640, &dst_pixels_c[0], 1280);
- for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
- #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
- int has_neon = TestCpuFlag(kCpuHasNEON);
- if (has_neon) {
- ScaleRowUp2_16_NEON(&orig_pixels[0], 640, &dst_pixels_opt[0], 1280);
- } else {
- ScaleRowUp2_16_C(&orig_pixels[0], 640, &dst_pixels_opt[0], 1280);
- }
- #elif !defined(LIBYUV_DISABLE_MMI) && defined(_MIPS_ARCH_LOONGSON3A)
- int has_mmi = TestCpuFlag(kCpuHasMMI);
- if (has_mmi) {
- ScaleRowUp2_16_MMI(&orig_pixels[0], 640, &dst_pixels_opt[0], 1280);
- } else {
- ScaleRowUp2_16_C(&orig_pixels[0], 640, &dst_pixels_opt[0], 1280);
- }
- #else
- ScaleRowUp2_16_C(&orig_pixels[0], 640, &dst_pixels_opt[0], 1280);
- #endif
- }
- for (int i = 0; i < 1280; ++i) {
- EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
- }
- EXPECT_EQ(dst_pixels_c[0], (0 * 9 + 1 * 3 + 640 * 3 + 641 * 1 + 8) / 16);
- EXPECT_EQ(dst_pixels_c[1279], 800);
- }
- extern "C" void ScaleRowDown2Box_16_NEON(const uint16_t* src_ptr,
- ptrdiff_t src_stride,
- uint16_t* dst,
- int dst_width);
- TEST_F(LibYUVScaleTest, TestScaleRowDown2Box_16) {
- SIMD_ALIGNED(uint16_t orig_pixels[2560 * 2]);
- SIMD_ALIGNED(uint16_t dst_pixels_c[1280]);
- SIMD_ALIGNED(uint16_t dst_pixels_opt[1280]);
- memset(orig_pixels, 0, sizeof(orig_pixels));
- memset(dst_pixels_c, 1, sizeof(dst_pixels_c));
- memset(dst_pixels_opt, 2, sizeof(dst_pixels_opt));
- for (int i = 0; i < 2560 * 2; ++i) {
- orig_pixels[i] = i;
- }
- ScaleRowDown2Box_16_C(&orig_pixels[0], 2560, &dst_pixels_c[0], 1280);
- for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
- #if !defined(LIBYUV_DISABLE_NEON) && defined(__aarch64__)
- int has_neon = TestCpuFlag(kCpuHasNEON);
- if (has_neon) {
- ScaleRowDown2Box_16_NEON(&orig_pixels[0], 2560, &dst_pixels_opt[0], 1280);
- } else {
- ScaleRowDown2Box_16_C(&orig_pixels[0], 2560, &dst_pixels_opt[0], 1280);
- }
- #else
- ScaleRowDown2Box_16_C(&orig_pixels[0], 2560, &dst_pixels_opt[0], 1280);
- #endif
- }
- for (int i = 0; i < 1280; ++i) {
- EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]);
- }
- EXPECT_EQ(dst_pixels_c[0], (0 + 1 + 2560 + 2561 + 2) / 4);
- EXPECT_EQ(dst_pixels_c[1279], 3839);
- }
- #endif // ENABLE_ROW_TESTS
- // Test scaling plane with 8 bit C vs 16 bit C and return maximum pixel
- // difference.
- // 0 = exact.
- static int TestPlaneFilter_16(int src_width,
- int src_height,
- int dst_width,
- int dst_height,
- FilterMode f,
- int benchmark_iterations,
- int disable_cpu_flags,
- int benchmark_cpu_info) {
- if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
- return 0;
- }
- int i;
- int64_t src_y_plane_size = (Abs(src_width)) * (Abs(src_height));
- int src_stride_y = Abs(src_width);
- int dst_y_plane_size = dst_width * dst_height;
- int dst_stride_y = dst_width;
- align_buffer_page_end(src_y, src_y_plane_size);
- align_buffer_page_end(src_y_16, src_y_plane_size * 2);
- align_buffer_page_end(dst_y_8, dst_y_plane_size);
- align_buffer_page_end(dst_y_16, dst_y_plane_size * 2);
- uint16_t* p_src_y_16 = reinterpret_cast<uint16_t*>(src_y_16);
- uint16_t* p_dst_y_16 = reinterpret_cast<uint16_t*>(dst_y_16);
- MemRandomize(src_y, src_y_plane_size);
- memset(dst_y_8, 0, dst_y_plane_size);
- memset(dst_y_16, 1, dst_y_plane_size * 2);
- for (i = 0; i < src_y_plane_size; ++i) {
- p_src_y_16[i] = src_y[i] & 255;
- }
- MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
- ScalePlane(src_y, src_stride_y, src_width, src_height, dst_y_8, dst_stride_y,
- dst_width, dst_height, f);
- MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
- for (i = 0; i < benchmark_iterations; ++i) {
- ScalePlane_16(p_src_y_16, src_stride_y, src_width, src_height, p_dst_y_16,
- dst_stride_y, dst_width, dst_height, f);
- }
- // Expect an exact match.
- int max_diff = 0;
- for (i = 0; i < dst_y_plane_size; ++i) {
- int abs_diff = Abs(dst_y_8[i] - p_dst_y_16[i]);
- if (abs_diff > max_diff) {
- max_diff = abs_diff;
- }
- }
- free_aligned_buffer_page_end(dst_y_8);
- free_aligned_buffer_page_end(dst_y_16);
- free_aligned_buffer_page_end(src_y);
- free_aligned_buffer_page_end(src_y_16);
- return max_diff;
- }
- // The following adjustments in dimensions ensure the scale factor will be
- // exactly achieved.
- // 2 is chroma subsample.
- #define DX(x, nom, denom) static_cast<int>(((Abs(x) / nom + 1) / 2) * nom * 2)
- #define SX(x, nom, denom) static_cast<int>(((x / nom + 1) / 2) * denom * 2)
- #define TEST_FACTOR1(name, filter, nom, denom, max_diff) \
- TEST_F(LibYUVScaleTest, DISABLED_##ScalePlaneDownBy##name##_##filter##_16) { \
- int diff = TestPlaneFilter_16( \
- SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
- DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
- kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
- benchmark_cpu_info_); \
- EXPECT_LE(diff, max_diff); \
- }
- // Test a scale factor with all 4 filters. Expect unfiltered to be exact, but
- // filtering is different fixed point implementations for SSSE3, Neon and C.
- #define TEST_FACTOR(name, nom, denom, boxdiff) \
- TEST_FACTOR1(name, None, nom, denom, 0) \
- TEST_FACTOR1(name, Linear, nom, denom, boxdiff) \
- TEST_FACTOR1(name, Bilinear, nom, denom, boxdiff) \
- TEST_FACTOR1(name, Box, nom, denom, boxdiff)
- TEST_FACTOR(2, 1, 2, 0)
- TEST_FACTOR(4, 1, 4, 0)
- // TEST_FACTOR(8, 1, 8, 0) Disable for benchmark performance. Takes 90 seconds.
- TEST_FACTOR(3by4, 3, 4, 1)
- TEST_FACTOR(3by8, 3, 8, 1)
- TEST_FACTOR(3, 1, 3, 0)
- #undef TEST_FACTOR1
- #undef TEST_FACTOR
- #undef SX
- #undef DX
- } // namespace libyuv
|