| // Copyright 2021 The libgav1 Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "src/dsp/film_grain.h" |
| |
| #include <algorithm> |
| #include <cassert> |
| #include <cstddef> |
| #include <cstdint> |
| #include <cstdio> |
| #include <cstring> |
| #include <memory> |
| #include <new> |
| #include <string> |
| #include <tuple> |
| #include <type_traits> |
| |
| #include "absl/strings/match.h" |
| #include "absl/strings/str_format.h" |
| #include "absl/time/clock.h" |
| #include "absl/time/time.h" |
| #include "gtest/gtest.h" |
| #include "src/dsp/common.h" |
| #include "src/dsp/dsp.h" |
| #include "src/dsp/film_grain_common.h" |
| #include "src/film_grain.h" |
| #include "src/utils/array_2d.h" |
| #include "src/utils/common.h" |
| #include "src/utils/constants.h" |
| #include "src/utils/cpu.h" |
| #include "src/utils/memory.h" |
| #include "src/utils/threadpool.h" |
| #include "src/utils/types.h" |
| #include "tests/block_utils.h" |
| #include "tests/third_party/libvpx/acm_random.h" |
| #include "tests/utils.h" |
| |
| namespace libgav1 { |
| namespace dsp { |
| namespace film_grain { |
| namespace { |
| |
| constexpr int kNumSpeedTests = 50; |
| constexpr int kNumFilmGrainTestParams = 10; |
| constexpr size_t kLumaBlockSize = kLumaWidth * kLumaHeight; |
| constexpr size_t kChromaBlockSize = kMaxChromaWidth * kMaxChromaHeight; |
| // Dimensions for unit tests concerning applying grain to the whole frame. |
| constexpr size_t kNumTestStripes = 64; |
| constexpr int kNoiseStripeHeight = 34; |
| constexpr size_t kFrameWidth = 1921; |
| constexpr size_t kFrameHeight = (kNumTestStripes - 1) * 32 + 1; |
| |
| /* |
| The film grain parameters for 10 frames were generated with the following |
| command line: |
| aomenc --end-usage=q --cq-level=20 --cpu-used=8 -w 1920 -h 1080 \ |
| --denoise-noise-level=50 --ivf breaking_bad_21m23s_10frames.1920_1080.yuv \ |
| -o breaking_bad_21m23s_10frames.1920_1080.noise50.ivf |
| */ |
| constexpr FilmGrainParams kFilmGrainParams[10] = { |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/8, |
| /*num_v_points=*/8, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 121, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{71, 71, 91, 99, 98, 100, 100, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 27, 40, 54, 67, 94, 255, 0, 0}, |
| /*point_u_scaling=*/{37, 37, 43, 48, 48, 50, 51, 51, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 107, 255, 0, 0}, |
| /*point_v_scaling=*/{48, 48, 43, 33, 32, 33, 34, 34, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{2, -2, -2, 10, 3, -2, 1, -4, |
| 5, -1, -25, -13, 3, -1, 0, 7, |
| -20, 103, 26, -2, 1, 14, -49, 117}, |
| /*auto_regression_coeff_u=*/{-2, 1, -3, 4, -4, 0, 3, 5, -5, |
| -17, 17, 0, -10, -5, -3, -30, 14, 70, |
| 29, 9, -2, -10, 50, 71, -11}, |
| /*auto_regression_coeff_v=*/{3, -2, -7, 6, -7, -8, 3, 1, -12, |
| -15, 28, 5, -11, -2, -7, -27, 32, 62, |
| 31, 18, -2, -6, 61, 43, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/7391, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/8, |
| /*num_u_points=*/7, |
| /*num_v_points=*/8, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 94, 134, 255, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{72, 72, 91, 99, 97, 100, 102, 102, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 67, 134, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{38, 38, 50, 49, 51, 53, 53, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 121, 255, 0, 0}, |
| /*point_v_scaling=*/{50, 50, 45, 34, 33, 35, 37, 37, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{2, -2, -2, 10, 3, -1, 1, -3, |
| 3, 1, -27, -12, 2, -1, 1, 7, |
| -17, 100, 27, 0, -1, 13, -50, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 3, -3, -1, 2, 5, -3, |
| -16, 16, -2, -10, -2, -1, -31, 14, 70, |
| 29, 9, -1, -10, 47, 70, -11}, |
| /*auto_regression_coeff_v=*/{1, 0, -5, 5, -6, -6, 2, 1, -10, |
| -14, 26, 4, -10, -3, -5, -26, 29, 63, |
| 31, 17, -1, -6, 55, 47, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/10772, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/8, |
| /*num_u_points=*/7, |
| /*num_v_points=*/8, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 94, 134, 255, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{71, 71, 91, 99, 98, 101, 103, 103, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 81, 107, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{37, 37, 49, 48, 51, 52, 52, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 121, 255, 0, 0}, |
| /*point_v_scaling=*/{49, 49, 44, 34, 32, 34, 36, 36, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{1, -2, -2, 10, 3, -1, 1, -4, |
| 4, 1, -26, -12, 2, -1, 1, 7, |
| -18, 101, 26, -1, 0, 13, -49, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -3, 4, -3, -1, 2, 5, -4, |
| -16, 17, -2, -10, -3, -2, -31, 15, 70, |
| 28, 9, -1, -10, 48, 70, -11}, |
| /*auto_regression_coeff_v=*/{1, -1, -6, 5, -6, -7, 2, 2, -11, |
| -14, 27, 5, -11, -3, -6, -26, 30, 62, |
| 30, 18, -2, -6, 58, 45, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/14153, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/5, |
| /*num_v_points=*/7, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 121, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{71, 71, 90, 99, 98, 100, 100, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 107, 255, 0, 0, 0, 0, 0}, |
| /*point_u_scaling=*/{37, 37, 48, 51, 51, 0, 0, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 94, 255, 0, 0, 0}, |
| /*point_v_scaling=*/{49, 49, 43, 33, 32, 34, 34, 0, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{2, -2, -2, 10, 3, -1, 1, -4, |
| 6, 0, -26, -13, 3, -1, 1, 6, |
| -20, 103, 26, -2, 1, 13, -48, 117}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 4, -4, -1, 2, 5, -5, |
| -16, 18, -1, -10, -3, -2, -30, 16, 69, |
| 28, 9, -2, -10, 50, 68, -11}, |
| /*auto_regression_coeff_v=*/{2, -1, -6, 5, -6, -7, 2, 2, -11, |
| -15, 29, 4, -10, -3, -6, -26, 30, 62, |
| 31, 18, -3, -6, 59, 45, 3}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/17534, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/8, |
| /*num_u_points=*/7, |
| /*num_v_points=*/7, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 94, 134, 255, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{71, 71, 91, 99, 98, 101, 103, 103, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 81, 107, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{37, 37, 49, 49, 52, 53, 53, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 94, 255, 0, 0, 0}, |
| /*point_v_scaling=*/{50, 50, 44, 34, 33, 36, 37, 0, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{2, -2, -2, 10, 3, -1, 1, -4, |
| 3, 1, -26, -12, 2, -1, 1, 7, |
| -17, 101, 26, 0, 0, 13, -50, 116}, |
| /*auto_regression_coeff_u=*/{-2, 1, -2, 3, -3, -1, 2, 5, -4, |
| -16, 16, -2, -10, -3, -1, -31, 14, 70, |
| 28, 9, -1, -10, 48, 70, -11}, |
| /*auto_regression_coeff_v=*/{1, 0, -5, 5, -6, -6, 2, 2, -10, |
| -14, 26, 4, -10, -3, -5, -26, 29, 63, |
| 30, 17, -1, -6, 56, 47, 3}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/20915, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/7, |
| /*num_v_points=*/7, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 134, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{72, 72, 91, 99, 97, 101, 101, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 67, 107, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{38, 38, 51, 50, 52, 53, 54, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 94, 255, 0, 0, 0}, |
| /*point_v_scaling=*/{51, 51, 45, 35, 33, 36, 36, 0, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{2, -2, -2, 9, 3, -1, 1, -3, |
| 2, 2, -27, -12, 2, 0, 1, 7, |
| -16, 100, 27, 0, -1, 13, -51, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 3, -3, -1, 1, 4, -2, |
| -17, 14, -3, -10, -2, 0, -31, 14, 71, |
| 29, 8, -2, -10, 45, 71, -11}, |
| /*auto_regression_coeff_v=*/{0, -1, -5, 4, -6, -5, 2, 1, -9, |
| -14, 24, 3, -10, -3, -4, -25, 29, 63, |
| 31, 16, -1, -7, 54, 48, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/24296, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/7, |
| /*num_v_points=*/8, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 134, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{72, 72, 91, 99, 97, 101, 101, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 67, 134, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{38, 38, 50, 50, 51, 53, 53, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 121, 255, 0, 0}, |
| /*point_v_scaling=*/{50, 50, 45, 34, 33, 35, 36, 36, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{2, -2, -2, 10, 3, -1, 1, -3, |
| 3, 2, -27, -12, 2, 0, 1, 7, |
| -17, 100, 27, 0, -1, 13, -51, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 3, -3, -1, 1, 5, -3, |
| -16, 15, -2, -10, -2, -1, -31, 14, 70, |
| 29, 8, -1, -10, 46, 71, -11}, |
| /*auto_regression_coeff_v=*/{1, 0, -5, 5, -6, -5, 2, 1, -9, |
| -14, 25, 4, -10, -3, -5, -25, 29, 63, |
| 31, 17, -1, -7, 55, 47, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/27677, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/7, |
| /*num_v_points=*/8, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 121, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{72, 72, 92, 99, 97, 101, 101, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 67, 174, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{38, 38, 51, 50, 52, 54, 54, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 121, 255, 0, 0}, |
| /*point_v_scaling=*/{51, 51, 46, 35, 33, 35, 37, 37, 0, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{1, -1, -2, 9, 3, -1, 1, -3, |
| 2, 2, -28, -12, 2, 0, 1, 8, |
| -16, 99, 27, 0, -1, 13, -51, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 3, -3, -1, 2, 4, -2, |
| -16, 14, -3, -10, -2, 0, -31, 13, 71, |
| 29, 8, -2, -11, 44, 72, -11}, |
| /*auto_regression_coeff_v=*/{0, -1, -5, 4, -6, -4, 2, 1, -9, |
| -13, 23, 3, -10, -3, -4, -25, 28, 63, |
| 32, 16, -1, -7, 54, 49, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/31058, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/7, |
| /*num_v_points=*/9, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 121, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{72, 72, 92, 99, 98, 100, 98, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 67, 228, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{38, 38, 51, 51, 52, 54, 54, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 121, 201, 255, 0}, |
| /*point_v_scaling=*/{51, 51, 46, 35, 34, 35, 37, 37, 37, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{1, -1, -2, 9, 3, -1, 1, -3, |
| 2, 2, -28, -12, 2, 0, 1, 8, |
| -16, 99, 27, 0, -1, 13, -52, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 3, -3, -1, 1, 4, -2, |
| -16, 13, -3, -10, -2, 0, -31, 13, 71, |
| 29, 8, -2, -11, 44, 72, -11}, |
| /*auto_regression_coeff_v=*/{0, -1, -5, 4, -6, -4, 2, 2, -8, |
| -13, 23, 3, -10, -3, -4, -25, 28, 63, |
| 32, 16, -1, -7, 54, 49, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/34439, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}, |
| {/*apply_grain=*/true, |
| /*update_grain=*/true, |
| /*chroma_scaling_from_luma=*/false, |
| /*overlap_flag=*/true, |
| /*clip_to_restricted_range=*/false, |
| /*num_y_points=*/7, |
| /*num_u_points=*/7, |
| /*num_v_points=*/9, |
| /*point_y_value=*/{0, 13, 27, 40, 54, 121, 255, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_y_scaling=*/{72, 72, 92, 99, 98, 99, 95, 0, 0, 0, 0, 0, 0, 0}, |
| /*point_u_value=*/{0, 13, 40, 54, 67, 228, 255, 0, 0, 0}, |
| /*point_u_scaling=*/{39, 39, 51, 51, 52, 54, 54, 0, 0, 0}, |
| /*point_v_value=*/{0, 13, 27, 40, 54, 67, 121, 201, 255, 0}, |
| /*point_v_scaling=*/{51, 51, 46, 35, 34, 35, 36, 35, 35, 0}, |
| /*chroma_scaling=*/11, |
| /*auto_regression_coeff_lag=*/3, |
| /*auto_regression_coeff_y=*/{1, -1, -2, 9, 3, -1, 1, -3, |
| 2, 2, -28, -11, 2, 0, 1, 8, |
| -16, 99, 27, 0, -1, 13, -52, 116}, |
| /*auto_regression_coeff_u=*/{-3, 1, -2, 3, -3, -1, 1, 4, -2, |
| -16, 13, -3, -10, -2, 0, -30, 13, 71, |
| 29, 8, -2, -10, 43, 72, -11}, |
| /*auto_regression_coeff_v=*/{0, -1, -5, 3, -6, -4, 2, 2, -8, |
| -13, 23, 3, -10, -3, -4, -25, 28, 64, |
| 32, 16, -1, -7, 53, 49, 2}, |
| /*auto_regression_shift=*/8, |
| /*grain_seed=*/37820, |
| /*reference_index=*/0, |
| /*grain_scale_shift=*/0, |
| /*u_multiplier=*/0, |
| /*u_luma_multiplier=*/64, |
| /*u_offset=*/0, |
| /*v_multiplier=*/0, |
| /*v_luma_multiplier=*/64, |
| /*v_offset=*/0}}; |
| |
| const char* GetTestDigestLuma(int bitdepth, int param_index) { |
| static const char* const kTestDigestsLuma8bpp[10] = { |
| "80da8e849110a10c0a73f9dec0d9a2fb", "54352f02aeda541e17a4c2d208897e2b", |
| "2ad9021124c82aca3e7c9517d00d1236", "f6c5f64513925b09ceba31e92511f8a1", |
| "46c6006578c68c3c8619f7a389c7de45", "fcddbd27545254dc50f1c333c8b7e313", |
| "c6d4dc181bf7f2f93ae099b836685151", "2949ef836748271195914fef9acf4e46", |
| "524e79bb87ed550e123d00a61df94381", "182222470d7b7a80017521d0261e4474", |
| }; |
| static const char* const kTestDigestsLuma10bpp[10] = { |
| "27a49a2131fb6d4dd4b8c34da1b7642e", "4ea9134f6831dd398545c85b2a68e31f", |
| "4e12232a18a2b06e958d7ab6b953faad", "0ede12864ddaced2d8062ffa4225ce24", |
| "5fee492c4a430b2417a64aa4920b69e9", "39af842a3f9370d796e8ef047c0c42a8", |
| "0efbad5f9dc07391ad243232b8df1787", "2bd41882cd82960019aa2b87d5fb1fbc", |
| "1c66629c0c4e7b6f9b0a7a6944fbad50", "2c633a50ead62f8e844a409545f46244", |
| }; |
| static const char* const kTestDigestsLuma12bpp[10] = { |
| "1dc9b38a93454a85eb924f25346ae369", "5f9d311ee5384a5a902f8e2d1297319e", |
| "cf1a35878720564c7a741f91eef66565", "47a0608fe0f6f7ccae42a5ca05783cbf", |
| "dbc28da0178e3c18a036c3f2203c300f", "04911d2074e3252119ee2d80426b8c01", |
| "df19ab8103c40b726c842ccf7772208b", "39276967eb16710d98f82068c3eeba41", |
| "b83100f18abb2062d9c9969f07182b86", "b39a69515491329698cf66f6d4fa371f", |
| }; |
| |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsLuma8bpp[param_index]; |
| case 10: |
| return kTestDigestsLuma10bpp[param_index]; |
| case 12: |
| return kTestDigestsLuma12bpp[param_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetTestDigestChromaU(int bitdepth, int param_index) { |
| static const char* const kTestDigestsChromaU8bpp[10] = { |
| "e56b7bbe9f39bf987770b18aeca59514", "d0b3fd3cf2901dae31b73f20c510d83e", |
| "800c01d58d9fb72136d21ec2bb07899a", "4cd0badba679e8edbcd60a931fce49a1", |
| "cabec236cc17f91f3f08d8cde867aa72", "380a2205cf2d40c6a27152585f61a3b0", |
| "3813526234dc7f90f80f6684772c729a", "97a43a73066d88f9cbd915d56fc9c196", |
| "5b70b27a43dd63b03e23aecd3a935071", "d5cc98685582ffd47a41a97d2e377ac8", |
| }; |
| static const char* const kTestDigestsChromaU10bpp[10] = { |
| "9a6d0369ba86317598e65913276dae6d", "2512bdc4c88f21f8185b040b7752d1db", |
| "1e86b779ce6555fcf5bd0ade2af67e73", "5ad463a354ffce522c52b616fb122024", |
| "290d53c22c2143b0882acb887da3fdf1", "54622407d865371d7e70bbf29fdda626", |
| "be306c6a94c55dbd9ef514f0ad4a0011", "904602329b0dec352b3b177b0a2554d2", |
| "58afc9497d968c67fdf2c0cf23b33aa3", "74fee7be6f62724bf901fdd04a733b46", |
| }; |
| static const char* const kTestDigestsChromaU12bpp[10] = { |
| "846d608050fe7c19d6cabe2d53cb7821", "2caf4665a26aad50f68497e4b1326417", |
| "ce40f0f8f8c207c7c985464c812fea33", "820de51d07a21da5c00833bab546f1fa", |
| "5e7bedd8933cd274af03babb4dbb94dd", "d137cf584eabea86387460a6d3f62bfe", |
| "f206e0c6ed35b3ab35c6ff37e151e963", "55d87981b7044df225b3b5935185449b", |
| "6a655c8bf4df6af0e80ae6d004a73a25", "6234ae36076cc77161af6e6e3c04449a", |
| }; |
| |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsChromaU8bpp[param_index]; |
| case 10: |
| return kTestDigestsChromaU10bpp[param_index]; |
| case 12: |
| return kTestDigestsChromaU12bpp[param_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetTestDigestChromaV(int bitdepth, int param_index) { |
| static const char* const kTestDigestsChromaV8bpp[10] = { |
| "7205ed6c07ed27b7b52d871e0559b8fa", "fad033b1482dba0ed2d450b461fa310e", |
| "6bb39798ec6a0f7bda0b0fcb0a555734", "08c19856e10123ae520ccfc63e2fbe7b", |
| "a7695a6b69fba740a50310dfa6cf1c00", "ac2eac2d13fc5b21c4f2995d5abe14b9", |
| "be35cb30062db628a9e1304fca8b75dc", "f5bfc7a910c76bcd5b32c40772170879", |
| "aca07b37d63f978d76df5cd75d0cea5e", "107c7c56d4ec21f346a1a02206301b0d", |
| }; |
| static const char* const kTestDigestsChromaV10bpp[10] = { |
| "910724a77710996c90e272f1c1e9ff8e", "d293f861580770a89f1e266931a012ad", |
| "9e4f0c85fb533e51238586f9c3e68b6e", "a5ff4478d9eeb2168262c2e955e17a4f", |
| "fba6b1e8f28e4e90c836d41f28a0c154", "50b9a93f9a1f3845e6903bff9270a3e6", |
| "7b1624c3543badf5fadaee4d1e602e6b", "3be074e4ca0eec5770748b15661aaadd", |
| "639197401032f272d6c30666a2d08f43", "28075dd34246bf9d5e6197b1944f646a", |
| }; |
| static const char* const kTestDigestsChromaV12bpp[10] = { |
| "4957ec919c20707d594fa5c2138c2550", "3f07c65bfb42c81768b1f5ad9611d1ce", |
| "665d9547171c99faba95ac81a35c9a0c", "1b5d032e0cefdb4041ad51796de8a45e", |
| "18fa974579a4f1ff8cd7df664fc339d5", "2ffaa4f143495ff73c06a580a97b6321", |
| "4fd1f562bc47a68dbfaf7c566c7c4da6", "4d37c80c9caf110c1d3d20bd1a1875b3", |
| "8ea29759640962613166dc5154837d14", "5ca4c10f42d0906c72ebee90fae6ce7d", |
| }; |
| |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsChromaV8bpp[param_index]; |
| case 10: |
| return kTestDigestsChromaV10bpp[param_index]; |
| case 12: |
| return kTestDigestsChromaV12bpp[param_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetARTestDigestLuma(int bitdepth, int coeff_lag, int param_index) { |
| static const char* const kTestDigestsLuma8bpp[3][kNumFilmGrainTestParams] = { |
| {"a835127918f93478b45f1ba4d20d81bd", "a835127918f93478b45f1ba4d20d81bd", |
| "e5db4da626e214bb17bcc7ecffa76303", "a835127918f93478b45f1ba4d20d81bd", |
| "a835127918f93478b45f1ba4d20d81bd", "e5db4da626e214bb17bcc7ecffa76303", |
| "a835127918f93478b45f1ba4d20d81bd", "1da62b7233de502123a18546b6c97da2", |
| "1da62b7233de502123a18546b6c97da2", "1da62b7233de502123a18546b6c97da2"}, |
| {"11464b880de3ecd6e6189c5c4e7f9b28", "dfe411762e283b5f49bece02ec200951", |
| "5c534d92afdf0a5b53dbe4fe7271929c", "2e1a68a18aca96c31320ba7ceab59be9", |
| "584c0323e6b276cb9acb1a294d462d58", "9571eb8f1cbaa96ea3bf64a820a8d9f0", |
| "305285ff0df87aba3c59e3fc0818697d", "0066d35c8818cf20230114dcd3765a4d", |
| "0066d35c8818cf20230114dcd3765a4d", "16d61b046084ef2636eedc5a737cb6f6"}, |
| {"0c9e2cf1b6c3cad0f7668026e8ea0516", "7d094855292d0eded9e0d1b5bab1990b", |
| "fbf28860a5f1285dcc6725a45256a86a", "dccb906904160ccabbd2c9a7797a4bf9", |
| "46f645e17f08a3260b1ae70284e5c5b8", "124fdc90bed11a7320a0cbdee8b94400", |
| "8d2978651dddeaef6282191fa146f0a0", "28b4d5aa33f05b3fb7f9323a11936bdc", |
| "6a8ea684f6736a069e3612d1af6391a8", "2781ea40a63704dbfeb3a1ac5db6f2fc"}, |
| }; |
| |
| static const char* const kTestDigestsLuma10bpp[3][kNumFilmGrainTestParams] = { |
| {"5e6bc8444ece2d38420f51d82238d812", "5e6bc8444ece2d38420f51d82238d812", |
| "2bfaec768794af33d60a9771f971f68d", "5e6bc8444ece2d38420f51d82238d812", |
| "5e6bc8444ece2d38420f51d82238d812", "c880807a368c4e82c23bea6f035ad23f", |
| "5e6bc8444ece2d38420f51d82238d812", "c576667da5286183ec3aab9a76f53a2e", |
| "c576667da5286183ec3aab9a76f53a2e", "c576667da5286183ec3aab9a76f53a2e"}, |
| {"095c2dd4d4d52aff9696df9bfdb70062", "983d14afa497060792d472a449a380c7", |
| "c5fdc0f7c594b2b36132cec6f45a79bd", "acff232ac5597c1712213150552281d1", |
| "4dd7341923b1d260092853553b6b6246", "0ca8afd71a4f564ea1ce69c4af14e9ab", |
| "9bc7565e5359d09194fcee28e4bf7b94", "6fea7805458b9d149f238a30e2dc3f13", |
| "6fea7805458b9d149f238a30e2dc3f13", "681dff5fc7a7244ba4e4a582ca7ecb14"}, |
| {"cb99352c9c6300e7e825188bb4adaee0", "7e40674de0209bd72f8e9c6e39ee6f7c", |
| "3e475572f6b4ecbb2730fd16751ad7ed", "e6e4c63abc9cb112d9d1f23886cd1415", |
| "1a1c953b175c105c604902877e2bab18", "380a53072530223d4ee622e014ee4bdb", |
| "6137394ea1172fb7ea0cbac237ff1703", "85ab0c813e46f97cb9f42542f44c01ad", |
| "68c8ac462f0e28cb35402c538bee32f1", "0038502ffa4760c8feb6f9abd4de7250"}, |
| }; |
| |
| static const char* const kTestDigestsLuma12bpp[3][kNumFilmGrainTestParams] = { |
| {"d618bbb0e337969c91b1805f39561520", "d618bbb0e337969c91b1805f39561520", |
| "678f6e911591daf9eca4e305dabdb2b3", "d618bbb0e337969c91b1805f39561520", |
| "d618bbb0e337969c91b1805f39561520", "3b26f49612fd587c7360790d40adb5de", |
| "d618bbb0e337969c91b1805f39561520", "33f77d3ff50cfc64c6bc9a896b567377", |
| "33f77d3ff50cfc64c6bc9a896b567377", "33f77d3ff50cfc64c6bc9a896b567377"}, |
| {"362fd67050fb7abaf57c43a92d993423", "e014ae0eb9e697281015c38905cc46ef", |
| "82b867e57151dc08afba31eccf5ccf69", "a94ba736cdce7bfa0b550285f59e47a9", |
| "3f1b0b7dd3b10e322254d35e4e185b7c", "7929708e5f017d58c53513cb79b35fda", |
| "6d26d31a091cbe642a7070933bd7de5a", "dc29ac40a994c0a760bfbad0bfc15b3a", |
| "dc29ac40a994c0a760bfbad0bfc15b3a", "399b919db5190a5311ce8d166580827b"}, |
| {"6116d1f569f5b568eca4dc1fbf255086", "7e9cf31ea74e8ea99ffd12094ce6cd05", |
| "bb982c4c39e82a333d744defd16f4388", "7c6e584b082dc6b97ed0d967def3993f", |
| "fb234695353058f03c8e128f2f8de130", "9218c6ca67bf6a9237f98aa1ce7acdfd", |
| "d1fb834bbb388ed066c5cbc1c79b5bdf", "d6f630daedc08216fcea12012e7408b5", |
| "dd7fe49299e6f113a98debc7411c8db8", "8b89e45a5101a28c24209ae119eafeb8"}, |
| }; |
| |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsLuma8bpp[coeff_lag - 1][param_index]; |
| case 10: |
| return kTestDigestsLuma10bpp[coeff_lag - 1][param_index]; |
| case 12: |
| return kTestDigestsLuma12bpp[coeff_lag - 1][param_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetARTestDigestChromaU(int bitdepth, int coeff_lag, |
| int subsampling_x, int subsampling_y) { |
| static const char* const kTestDigestsChromaU8bpp[12] = { |
| "11ced66de0eaf55c1ff9bad18d7b8ed7", "0c3b77345dd4ab0915ef53693ab93ce4", |
| "b0645044ba080b3ceb8f299e269377d6", "50590ad5d895f0b4bc6694d878e9cd32", |
| "85e1bf3741100135062f5b4abfe7639b", "76955b70dde61ca5c7d079c501b90906", |
| "3f0995e1397fd9efd9fc46b67f7796b3", "0a0d6c3e4e1649eb101395bc97943a07", |
| "1878855ed8db600ccae1d39abac52ec6", "13ab2b28320ed3ac2b820f08fdfd424d", |
| "f3e95544a86ead5387e3dc4e043fd0f0", "ff8f5d2d97a6689e16a7e4f482f69f0b", |
| }; |
| |
| static const char* const kTestDigestsChromaU10bpp[12] = { |
| "707f2aa5aa7e77bc6e83ab08287d748d", "0bcf40c7fead9ac3a5d71b4cc1e21549", |
| "0c1df27053e5da7cf1276a122a8f4e8b", "782962f7425eb38923a4f87e7ab319d9", |
| "b4a709ae5967afef55530b9ea8ef0062", "70a971a0b9bf06212d510b396f0f9095", |
| "d033b89d6e31f8b13c83d94c840b7d54", "40bbe804bf3f90cee667d3b275e3c964", |
| "90bb2b9d518b945adcfd1b1807f7d170", "4bc34aa157fe5ad4270c611afa75e878", |
| "e2688d7286cd43fe0a3ea734d2ad0f77", "853193c4981bd882912171061327bdf2", |
| }; |
| |
| static const char* const kTestDigestsChromaU12bpp[12] = { |
| "04c23b01d01c0e3f3247f3741581b383", "9f8ea1d66e44f6fe93d765ce56b2b0f3", |
| "5dda44b128d6c244963f1e8e17cc1d22", "9dd0a79dd2f772310a95762d445bface", |
| "0dbd40d930e4873d72ea72b9e3d62440", "d7d83c207c6b435a164206d5f457931f", |
| "e8d04f6e63ed63838adff965275a1ff1", "fc09a903e941fcff8bad67a84f705775", |
| "9cd706606a2aa40d0957547756f7abd9", "258b37e7b8f48db77dac7ea24073fe69", |
| "80149b8bb05308da09c1383d8b79d3da", "e993f3bffae53204a1942feb1af42074", |
| }; |
| |
| assert(!(subsampling_x == 0 && subsampling_y == 1)); |
| const int base_index = 3 * coeff_lag + subsampling_x + subsampling_y; |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsChromaU8bpp[base_index]; |
| case 10: |
| return kTestDigestsChromaU10bpp[base_index]; |
| case 12: |
| return kTestDigestsChromaU12bpp[base_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetARTestDigestChromaV(int bitdepth, int coeff_lag, |
| int subsampling_x, int subsampling_y) { |
| static const char* const kTestDigestsChromaV8bpp[12] = { |
| "5c2179f3d93be0a0da75d2bb90347c2f", "79b883847d7eaa7890e1d633b8e34353", |
| "90ade818e55808e8cf58c11debb5ddd1", "1d0f2a14bc4df2b2a1abaf8137029f92", |
| "ac753a57ade140dccb50c14f941ae1fc", "d24ab497558f6896f08dc17bcc3c50c1", |
| "3d74436c63920022a95c85b234db4e33", "061c2d53ed84c830f454e395c362cb16", |
| "05d24869d7fb952e332457a114c8b9b7", "fcee31b87a2ada8028c2a975e094856a", |
| "c019e2c475737abcf9c2b2a52845c646", "9cd994baa7021f8bdf1d1c468c1c8e9c", |
| }; |
| |
| static const char* const kTestDigestsChromaV10bpp[12] = { |
| "bc9e44454a05cac8571c15af5b720e79", "f0374436698d94e879c03331b1f30df4", |
| "4580dd009abd6eeed59485057c55f63e", "7d1f7aecd45302bb461f4467f2770f72", |
| "1f0d003fce6c5fedc147c6112813f43b", "4771a45c2c1a04c375400619d5536035", |
| "df9cf619a78907c0f6e58bc13d7d5546", "dd3715ce65d905f30070a36977c818e0", |
| "32de5800f76e34c128a1d89146b4010b", "db9d7c70c3f69feb68fae04398efc773", |
| "d3d0912e3fdb956fef416a010bd7b4c2", "a2fca8abd9fd38d2eef3c4495d9eff78", |
| }; |
| |
| static const char* const kTestDigestsChromaV12bpp[12] = { |
| "0d1890335f4464167de22353678ca9c6", "9e6830aba73139407196f1c811f910bc", |
| "6018f2fb76bd648bef0262471cfeba5c", "78e1ae1b790d709cdb8997621cf0fde3", |
| "5b44ae281d7f9db2f17aa3c24b4741dd", "f931d16991669cb16721de87da9b8067", |
| "5580f2aed349d9cabdafb9fc25a57b1c", "86918cd78bf95e6d4405dd050f5890b8", |
| "13c8b314eeebe35fa60b703d94e1b2c1", "13c6fb75cab3f42e0d4ca31e4d068b0e", |
| "bb9ca0bd6f8cd67e44c8ac2803abf5a5", "0da4ea711ffe557bb66577392b6f148b", |
| }; |
| |
| assert(!(subsampling_x == 0 && subsampling_y == 1)); |
| const int base_index = 3 * coeff_lag + subsampling_x + subsampling_y; |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsChromaV8bpp[base_index]; |
| case 10: |
| return kTestDigestsChromaV10bpp[base_index]; |
| case 12: |
| return kTestDigestsChromaV12bpp[base_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetGrainGenerationTestDigestLuma(int bitdepth, int param_index) { |
| static const char* const kTestDigestsLuma8bpp[kNumFilmGrainTestParams] = { |
| "c48babd99e5cfcbaa13d8b6e0c12e644", "da4b971d2de19b709e2bc98d2e50caf3", |
| "96c72faac19a79c138afeea8b8ae8c7a", "90a2b9c8304a44d14e83ca51bfd2fe8a", |
| "72bd3aa85c17850acb430afb4183bf1a", "a0acf76349b9efbc9181fc31153d9ef6", |
| "6da74dd631a4ec8b9372c0bbec22e246", "6e11fa230f0e5fbb13084255c22cabf9", |
| "be1d257b762f9880d81680e9325932a2", "37e302075af8130b371de4430e8a22cf", |
| }; |
| |
| static const char* const kTestDigestsLuma10bpp[kNumFilmGrainTestParams] = { |
| "0a40fd2f261095a6154584a531328142", "9d0c8173a94a0514c769e94b6f254030", |
| "7894e959fdd5545895412e1512c9352d", "6802cad2748cf6db7f66f53807ee46ab", |
| "ea24e962b98351c3d929a8ae41e320e2", "b333dc944274a3a094073889ca6e11d6", |
| "7211d7ac0ff7d11b5ef1538c0d98f43d", "ef9f9cbc101a07da7bfa62637130e331", |
| "85a122e32648fde84b883a1f98947c60", "dee656e3791138285bc5b71e3491a177", |
| }; |
| |
| static const char* const kTestDigestsLuma12bpp[kNumFilmGrainTestParams] = { |
| "ae359794b5340d073d597117046886ac", "4d4ad3908b4fb0f248a0086537dd6b1e", |
| "672a97e15180cbeeaf76d763992c9f23", "739124d10d16e00a158e833ea92107bc", |
| "4c38c738ff7ffc50adaa4474584d3aae", "ca05ba7e51000a7d10e5cbb2101bbd86", |
| "e207022b916bf03a76ac8742af29853d", "7454bf1859149237ff74f1161156c857", |
| "10fc2a16e663bbc305255b0883cfcd45", "4228abff6899bb33839b579288ab29fe", |
| }; |
| |
| switch (bitdepth) { |
| case 8: |
| return kTestDigestsLuma8bpp[param_index]; |
| case 10: |
| return kTestDigestsLuma10bpp[param_index]; |
| case 12: |
| return kTestDigestsLuma12bpp[param_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetConstructStripesTestDigest(int bitdepth, int overlap_flag, |
| int subsampling_x, |
| int subsampling_y) { |
| static const char* const kTestDigests8bpp[6] = { |
| "cd14aaa6fc1728290fa75772730a2155", "13ad4551feadccc3a3a9bd5e25878d2a", |
| "ed6ad9532c96ef0d79ff3228c89a429f", "82f307a7f5fc3308c3ebe268b5169e70", |
| "aed793d525b85349a8c2eb6d40e93969", "311c3deb727621a7d4f18e8defb65de7", |
| }; |
| |
| static const char* const kTestDigests10bpp[6] = { |
| "4fe2fa1e428737de3595be3a097d0203", "80568c3c3b53bdbbd03b820179092dcd", |
| "bc7b73099961a0739c36e027d6d09ea1", "e5331364e5146a6327fd94e1467f59a3", |
| "125bf18b7787e8f0792ea12f9210de0d", "21cf98cbce17eca77dc150cc9be0e0a0", |
| }; |
| |
| static const char* const kTestDigests12bpp[6] = { |
| "57f8e17078b6e8935252e918a2562636", "556a7b294a99bf1163b7166b4f68357e", |
| "249bee5572cd7d1cc07182c97adc4ba7", "9bf43ae1998c2a5b2e5f4d8236b58747", |
| "477c08fa26499936e5bb03bde097633e", "fe64b7166ff87ea0711ae4f519cadd59", |
| }; |
| |
| const int base_index = 3 * overlap_flag + subsampling_x + subsampling_y; |
| switch (bitdepth) { |
| case 8: |
| return kTestDigests8bpp[base_index]; |
| case 10: |
| return kTestDigests10bpp[base_index]; |
| case 12: |
| return kTestDigests12bpp[base_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetConstructImageTestDigest(int bitdepth, int overlap_flag, |
| int subsampling_x, int subsampling_y) { |
| static const char* const kTestDigests8bpp[6] = { |
| "17030fc692e685557a3717f9334af7e8", "d16ea46147183cd7bc36bcfc2f936a5b", |
| "68152958540dbec885f71e3bcd7aa088", "bb43b420f05a122eb4780aca06055ab1", |
| "87567b04fbdf64f391258c0742de266b", "ce87d556048b3de32570faf6729f4010", |
| }; |
| |
| static const char* const kTestDigests10bpp[6] = { |
| "5b31b29a5e22126a9bf8cd6a01645777", "2bb94a25164117f2ab18dae18e2c6577", |
| "27e57a4ed6f0c9fe0a763a03f44805e8", "481642ab0b07437b76b169aa4eb82123", |
| "656a9ef056b04565bec9ca7e0873c408", "a70fff81ab28d02d99dd4f142699ba39", |
| }; |
| |
| static const char* const kTestDigests12bpp[6] = { |
| "146f7ceadaf77e7a3c41e191a58c1d3c", "de18526db39630936733e687cdca189e", |
| "165c96ff63bf3136505ab1d239f7ceae", "a102636662547f84e5f6fb6c3e4ef959", |
| "4cb073fcc783c158a95c0b1ce0d27e9f", "3a734c71d4325a7da53e2a6e00f81647", |
| }; |
| |
| const int base_index = 3 * overlap_flag + subsampling_x + subsampling_y; |
| switch (bitdepth) { |
| case 8: |
| return kTestDigests8bpp[base_index]; |
| case 10: |
| return kTestDigests10bpp[base_index]; |
| case 12: |
| return kTestDigests12bpp[base_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetScalingInitTestDigest(int param_index, int bitdepth) { |
| static const char* const kTestDigests8bpp[kNumFilmGrainTestParams] = { |
| "315202ca3bf9c46eac8605e89baffd2a", "640f6408702b07ab7e832e7326cce56f", |
| "f75ee83e3912a3f25949e852d67326cf", "211223f5d6a4b42a8e3c662f921b71c0", |
| "f75ee83e3912a3f25949e852d67326cf", "e7a1de8c5a2cac2145c586ecf1f9051c", |
| "e7a1de8c5a2cac2145c586ecf1f9051c", "276fe5e3b30b2db2a9ff798eb6cb8e00", |
| "ac67f1c3aff2f50ed4b1975bde67ffe3", "8db6145a60d506cc94f07cef8b27c681", |
| }; |
| |
| static const char* const kTestDigests10bpp[kNumFilmGrainTestParams] = { |
| "c50be59c62b634ff45ddfbe5b978adfc", "7626286109a2a1eaf0a26f6b2bbab9aa", |
| "f2302988140c47a0724fc55ff523b6ec", "5318e33d8a59a526347ffa6a72ba6ebd", |
| "f2302988140c47a0724fc55ff523b6ec", "f435b5fe98e9d8b6c61fa6f457601c2c", |
| "f435b5fe98e9d8b6c61fa6f457601c2c", "ff07a2944dbe094d01e199098764941c", |
| "11b3e256c74cee2b5679f7457793869a", "89fab5c1db09e242d0494d1c696a774a", |
| }; |
| |
| static const char* const kTestDigests12bpp[kNumFilmGrainTestParams] = { |
| "1554df49a863a851d146213e09d311a4", "84808c3ed3b5495a62c9d2dd9a08cb26", |
| "bb31f083a3bd9ef26587478b8752f280", "34fdfe61d6871e4882e38062a0725c5c", |
| "bb31f083a3bd9ef26587478b8752f280", "e7b8c3e4508ceabe89b78f10a9e160b8", |
| "e7b8c3e4508ceabe89b78f10a9e160b8", "a0ccc9e3d0f0c9d1f08f1249264d92f5", |
| "7992a96883c8a9a35d6ca8961bc4515b", "de906ce2c0fceed6f168215447b21b16", |
| }; |
| |
| switch (bitdepth) { |
| case 8: |
| return kTestDigests8bpp[param_index]; |
| case 10: |
| return kTestDigests10bpp[param_index]; |
| case 12: |
| return kTestDigests12bpp[param_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetBlendLumaTestDigest(int bitdepth) { |
| static const char* const kTestDigests[] = { |
| "de35b16c702690b1d311cdd0973835d7", |
| "60e9f24dcaaa0207a8db5ab5f3c66608", |
| "8e7d44b620bb7768459074be6bfbca7b", |
| }; |
| |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return kTestDigests[(bitdepth - 8) / 2]; |
| } |
| |
| const char* GetBlendChromaUTestDigest(int bitdepth, |
| int chroma_scaling_from_luma, |
| int subsampling_x, int subsampling_y) { |
| static const char* const kTestDigests8bpp[6] = { |
| "36ca194734d45e75079baba1f3ec9e9e", "182b388061f59fd3e24ef4581c536e67", |
| "2e7843b4c624f03316c3cbe1cc835859", "39e6d9606915da6a41168fbb006b55e4", |
| "3f44a4e252d4823544ac66a900dc7983", "1860f0831841f262d66b23f6a6b5833b", |
| }; |
| |
| static const char* const kTestDigests10bpp[6] = { |
| "2054665564f55750c9588b505eb01ac0", "4d8b0e248f8a6bfc72516aa164e76b0b", |
| "7e549800a4f9fff6833bb7738e272baf", "8de6f30dcda99a37b359fd815e62d2f7", |
| "9b7958a2278a16bce2b7bc31fdd811f5", "c5c3c8cccf6a2b4e40b4a412a5bf4f08", |
| }; |
| |
| static const char* const kTestDigests12bpp[6] = { |
| "8fad0cc641da35e0d2d8f178c7ce8394", "793eb9d2e6b4ea2e3bb08e7068236155", |
| "9156bd85ab9493d8867a174f920bb1e6", "6834319b4c88e3e0c96b6f8d7efd08dd", |
| "c40e492790d3803a734efbc6feca46e2", "d884c3b1e2c21d98844ca7639e0599a5", |
| }; |
| |
| const int base_index = |
| 3 * chroma_scaling_from_luma + subsampling_x + subsampling_y; |
| switch (bitdepth) { |
| case 8: |
| return kTestDigests8bpp[base_index]; |
| case 10: |
| return kTestDigests10bpp[base_index]; |
| case 12: |
| return kTestDigests12bpp[base_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| const char* GetBlendChromaVTestDigest(int bitdepth, |
| int chroma_scaling_from_luma, |
| int subsampling_x, int subsampling_y) { |
| static const char* const kTestDigests8bpp[6] = { |
| "9a353e4f86d7ebaa980f7f6cfc0995ad", "17589b4039ed49ba16f32db9fae724b7", |
| "76ae8bed48a173b548993b6e1824ff67", "c1458ac9bdfbf0b4d6a175343b17b27b", |
| "fa76d1c8e48957537f26af6a5b54ec14", "313fe3c34568b7f9c5ecb09d419d4ba4", |
| }; |
| |
| static const char* const kTestDigests10bpp[6] = { |
| "8ab5a8e03f07547260033d6a0b689e3c", "275ede58d311e2f5fd76f222f45a64fc", |
| "ce13916e0f7b02087fd0356534d32770", "165bfc8cda0266936a67fa4ec9b215cb", |
| "ed4382caa936acf1158ff8049d18ffac", "942bdd1344c9182dd7572099fb9372db", |
| }; |
| |
| static const char* const kTestDigests12bpp[6] = { |
| "70704a1e171a3a70d40b7d0037a75fbc", "62549e2afbf36a1ed405a6574d39c542", |
| "e93889927ab77c6e0767ff071d980c02", "a0c1f6ed78874137710fee7418d80959", |
| "f6283e36a25cb867e30bdf0bfdb2124b", "741c2d48898835b9d9e3bd0b6ac6269a", |
| }; |
| |
| const int base_index = |
| 3 * chroma_scaling_from_luma + subsampling_x + subsampling_y; |
| switch (bitdepth) { |
| case 8: |
| return kTestDigests8bpp[base_index]; |
| case 10: |
| return kTestDigests10bpp[base_index]; |
| case 12: |
| return kTestDigests12bpp[base_index]; |
| default: |
| assert(bitdepth == 8 || bitdepth == 10 || bitdepth == 12); |
| return nullptr; |
| } |
| } |
| |
| // GetFilmGrainRandomNumber() is only invoked with |bits| equal to 11 or 8. Test |
| // both values of |bits|. |
| TEST(FilmGrainTest, GetFilmGrainRandomNumber) { |
| uint16_t seed = 51968; |
| const struct { |
| int rand; |
| uint16_t seed; |
| } kExpected11[5] = { |
| {812, 25984}, {406, 12992}, {1227, 39264}, {1637, 52400}, {818, 26200}, |
| }; |
| for (int i = 0; i < 5; ++i) { |
| int rand = GetFilmGrainRandomNumber(11, &seed); |
| EXPECT_EQ(rand, kExpected11[i].rand) << "i = " << i; |
| EXPECT_EQ(seed, kExpected11[i].seed) << "i = " << i; |
| } |
| const struct { |
| int rand; |
| uint16_t seed; |
| } kExpected8[5] = { |
| {179, 45868}, {89, 22934}, {44, 11467}, {150, 38501}, {75, 19250}, |
| }; |
| for (int i = 0; i < 5; ++i) { |
| int rand = GetFilmGrainRandomNumber(8, &seed); |
| EXPECT_EQ(rand, kExpected8[i].rand) << "i = " << i; |
| EXPECT_EQ(seed, kExpected8[i].seed) << "i = " << i; |
| } |
| } |
| |
| // In FilmGrainParams, if num_u_points and num_v_points are both 0 and |
| // chroma_scaling_from_luma is false, GenerateChromaGrains() should set both |
| // the u_grain and v_grain arrays to all zeros. |
| TEST(FilmGrainTest, GenerateZeroChromaGrains) { |
| FilmGrainParams film_grain_params = {}; |
| film_grain_params.apply_grain = true; |
| film_grain_params.update_grain = true; |
| film_grain_params.chroma_scaling = 8; |
| film_grain_params.auto_regression_shift = 6; |
| film_grain_params.grain_seed = 51968; |
| |
| int8_t u_grain[73 * 82]; |
| int8_t v_grain[73 * 82]; |
| const int chroma_width = 44; |
| const int chroma_height = 38; |
| |
| // Initialize u_grain and v_grain with arbitrary nonzero values. |
| memset(u_grain, 1, sizeof(u_grain)); |
| memset(v_grain, 2, sizeof(v_grain)); |
| for (int y = 0; y < chroma_height; ++y) { |
| for (int x = 0; x < chroma_width; ++x) { |
| EXPECT_NE(u_grain[y * chroma_width + x], 0); |
| EXPECT_NE(v_grain[y * chroma_width + x], 0); |
| } |
| } |
| |
| FilmGrain<8>::GenerateChromaGrains(film_grain_params, chroma_width, |
| chroma_height, u_grain, v_grain); |
| |
| for (int y = 0; y < chroma_height; ++y) { |
| for (int x = 0; x < chroma_width; ++x) { |
| EXPECT_EQ(u_grain[y * chroma_width + x], 0); |
| EXPECT_EQ(v_grain[y * chroma_width + x], 0); |
| } |
| } |
| } |
| |
| // First parameter is coefficient lag. Second parameter is the index into |
| // |kFilmGrainParams|. |
| template <int bitdepth> |
| class AutoRegressionTestLuma |
| : public testing::TestWithParam<std::tuple<int, int>> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| using GrainType = |
| typename std::conditional<bitdepth == 8, int8_t, int16_t>::type; |
| |
| AutoRegressionTestLuma() { |
| FilmGrainInit_C(); |
| const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth); |
| const int index = std::get<0>(GetParam()) - 1; |
| base_luma_auto_regression_func_ = |
| dsp->film_grain.luma_auto_regression[index]; |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "C/")) { |
| base_luma_auto_regression_func_ = nullptr; |
| } else if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } |
| luma_auto_regression_func_ = dsp->film_grain.luma_auto_regression[index]; |
| } |
| |
| protected: |
| // |compare| determines whether to compare the output blocks from the SIMD |
| // implementation, if used, and the C implementation. |
| // |saturate| determines whether to set the inputs to maximum values. This is |
| // intended primarily as a way to simplify differences in output when |
| // debugging. |
| void TestAutoRegressiveFilterLuma(int coeff_lag, int param_index, |
| int num_runs, bool saturate, bool compare); |
| LumaAutoRegressionFunc luma_auto_regression_func_; |
| LumaAutoRegressionFunc base_luma_auto_regression_func_; |
| GrainType luma_block_buffer_[kLumaBlockSize]; |
| GrainType base_luma_block_buffer_[kLumaBlockSize]; |
| }; |
| |
| // First parameter is coefficient lag. Second parameter is the index into |
| // |kFilmGrainParams|. |
| template <int bitdepth> |
| void AutoRegressionTestLuma<bitdepth>::TestAutoRegressiveFilterLuma( |
| int coeff_lag, int param_index, int num_runs, bool saturate, bool compare) { |
| if (luma_auto_regression_func_ == nullptr) return; |
| // Compare is only needed for NEON tests to compare with C output. |
| if (base_luma_auto_regression_func_ == nullptr && compare) return; |
| FilmGrainParams params = kFilmGrainParams[param_index]; |
| params.auto_regression_coeff_lag = coeff_lag; |
| const int grain_max = GetGrainMax<bitdepth>(); |
| for (int y = 0; y < kLumaHeight; ++y) { |
| for (int x = 0; x < kLumaWidth; ++x) { |
| if (saturate) { |
| luma_block_buffer_[y * kLumaWidth + x] = grain_max; |
| } else { |
| luma_block_buffer_[y * kLumaWidth + x] = |
| std::min(x - (kLumaWidth >> 1), y - (kLumaHeight >> 1)) * |
| (1 << (bitdepth - 8)); |
| } |
| } |
| } |
| |
| if (saturate) { |
| memset(params.auto_regression_coeff_y, 127, |
| sizeof(params.auto_regression_coeff_y)); |
| } |
| if (compare) { |
| memcpy(base_luma_block_buffer_, luma_block_buffer_, |
| sizeof(luma_block_buffer_)); |
| } |
| |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| luma_auto_regression_func_(params, luma_block_buffer_); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| if (num_runs > 1) { |
| printf("AutoRegressionLuma lag=%d, param_index=%d: %d us\n", coeff_lag, |
| param_index, |
| static_cast<int>(absl::ToInt64Microseconds(elapsed_time))); |
| return; |
| } |
| if (compare) { |
| base_luma_auto_regression_func_(params, base_luma_block_buffer_); |
| EXPECT_TRUE(test_utils::CompareBlocks( |
| luma_block_buffer_, base_luma_block_buffer_, kLumaWidth, kLumaHeight, |
| kLumaWidth, kLumaWidth, false)); |
| } else { |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("AutoRegressionLuma lag=%d, param_index=%d", coeff_lag, |
| param_index) |
| .c_str(), |
| GetARTestDigestLuma(bitdepth, coeff_lag, param_index), |
| luma_block_buffer_, sizeof(luma_block_buffer_), elapsed_time); |
| } |
| } |
| |
| using AutoRegressionTestLuma8bpp = AutoRegressionTestLuma<8>; |
| |
| TEST_P(AutoRegressionTestLuma8bpp, AutoRegressiveFilterLuma) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1, /*saturate=*/false, |
| /*compare=*/false); |
| } |
| |
| TEST_P(AutoRegressionTestLuma8bpp, AutoRegressiveFilterLumaSaturated) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1, /*saturate=*/true, |
| /*compare=*/true); |
| } |
| |
| TEST_P(AutoRegressionTestLuma8bpp, DISABLED_Speed) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1e5, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using AutoRegressionTestLuma10bpp = AutoRegressionTestLuma<10>; |
| |
| TEST_P(AutoRegressionTestLuma10bpp, AutoRegressiveFilterLuma) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1, /*saturate=*/false, |
| /*compare=*/false); |
| } |
| |
| TEST_P(AutoRegressionTestLuma10bpp, AutoRegressiveFilterLumaSaturated) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1, /*saturate=*/true, |
| /*compare=*/true); |
| } |
| |
| TEST_P(AutoRegressionTestLuma10bpp, DISABLED_Speed) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1e5, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using AutoRegressionTestLuma12bpp = AutoRegressionTestLuma<12>; |
| |
| TEST_P(AutoRegressionTestLuma12bpp, AutoRegressiveFilterLuma) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1, /*saturate=*/false, |
| /*compare=*/false); |
| } |
| |
| TEST_P(AutoRegressionTestLuma12bpp, AutoRegressiveFilterLumaSaturated) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1, /*saturate=*/true, |
| /*compare=*/true); |
| } |
| |
| TEST_P(AutoRegressionTestLuma12bpp, DISABLED_Speed) { |
| TestAutoRegressiveFilterLuma(std::get<0>(GetParam()), std::get<1>(GetParam()), |
| 1e5, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| INSTANTIATE_TEST_SUITE_P( |
| C, AutoRegressionTestLuma8bpp, |
| testing::Combine(testing::Range(1, 4) /* coeff_lag */, |
| testing::Range(0, 10) /* param_index */)); |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P( |
| NEON, AutoRegressionTestLuma8bpp, |
| testing::Combine(testing::Range(1, 4) /* coeff_lag */, |
| testing::Range(0, 10) /* param_index */)); |
| #endif |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P( |
| C, AutoRegressionTestLuma10bpp, |
| testing::Combine(testing::Range(1, 4) /* coeff_lag */, |
| testing::Range(0, 10) /* param_index */)); |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P( |
| NEON, AutoRegressionTestLuma10bpp, |
| testing::Combine(testing::Range(1, 4) /* coeff_lag */, |
| testing::Range(0, 10) /* param_index */)); |
| #endif |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| INSTANTIATE_TEST_SUITE_P( |
| C, AutoRegressionTestLuma12bpp, |
| testing::Combine(testing::Range(1, 4) /* coeff_lag */, |
| testing::Range(0, 10) /* param_index */)); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| struct AutoRegressionChromaTestParam { |
| explicit AutoRegressionChromaTestParam(const std::tuple<int, int>& in) |
| : coeff_lag(std::get<0>(in)) { |
| switch (std::get<1>(in)) { |
| case 0: |
| subsampling_x = 0; |
| subsampling_y = 0; |
| break; |
| case 1: |
| subsampling_x = 1; |
| subsampling_y = 0; |
| break; |
| default: |
| assert(std::get<1>(in) == 2); |
| subsampling_x = 1; |
| subsampling_y = 1; |
| } |
| } |
| const int coeff_lag; |
| int subsampling_x; |
| int subsampling_y; |
| }; |
| |
| template <int bitdepth> |
| class AutoRegressionTestChroma |
| : public testing::TestWithParam<std::tuple<int, int>> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| using GrainType = |
| typename std::conditional<bitdepth == 8, int8_t, int16_t>::type; |
| |
| AutoRegressionTestChroma() { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| FilmGrainInit_C(); |
| const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth); |
| // This test suite does not cover num_y_points == 0. This should be covered |
| // in the test of the full synthesis process. |
| base_chroma_auto_regression_func_ = |
| dsp->film_grain.chroma_auto_regression[1][test_param.coeff_lag]; |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "C/")) { |
| base_chroma_auto_regression_func_ = nullptr; |
| } else if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } |
| chroma_auto_regression_func_ = |
| dsp->film_grain.chroma_auto_regression[1][test_param.coeff_lag]; |
| } |
| |
| ~AutoRegressionTestChroma() override = default; |
| |
| protected: |
| // |compare| determines whether to compare the output blocks from the SIMD |
| // implementation, if used, and the C implementation. |
| // |saturate| determines whether to set the inputs to maximum values. This is |
| // intended primarily as a way to simplify differences in output when |
| // debugging. |
| void TestAutoRegressiveFilterChroma(int coeff_lag, int subsampling_x, |
| int subsampling_y, int num_runs, |
| bool saturate, bool compare); |
| ChromaAutoRegressionFunc chroma_auto_regression_func_; |
| ChromaAutoRegressionFunc base_chroma_auto_regression_func_; |
| GrainType luma_block_buffer_[kLumaBlockSize]; |
| GrainType u_block_buffer_[kChromaBlockSize]; |
| GrainType v_block_buffer_[kChromaBlockSize]; |
| GrainType base_u_block_buffer_[kChromaBlockSize]; |
| GrainType base_v_block_buffer_[kChromaBlockSize]; |
| }; |
| |
| template <int bitdepth> |
| void AutoRegressionTestChroma<bitdepth>::TestAutoRegressiveFilterChroma( |
| int coeff_lag, int subsampling_x, int subsampling_y, int num_runs, |
| bool saturate, bool compare) { |
| if (chroma_auto_regression_func_ == nullptr) return; |
| // Compare is only needed for NEON tests to compare with C output. |
| if (base_chroma_auto_regression_func_ == nullptr && compare) return; |
| |
| // This function relies on the first set of sampled params for basics. The |
| // test param generators are used for coverage. |
| FilmGrainParams params = kFilmGrainParams[0]; |
| params.auto_regression_coeff_lag = coeff_lag; |
| const int grain_max = GetGrainMax<bitdepth>(); |
| const int grain_min = GetGrainMin<bitdepth>(); |
| const int chroma_width = |
| (subsampling_x != 0) ? kMinChromaWidth : kMaxChromaWidth; |
| const int chroma_height = |
| (subsampling_y != 0) ? kMinChromaHeight : kMaxChromaHeight; |
| if (saturate) { |
| memset(params.auto_regression_coeff_u, 127, |
| sizeof(params.auto_regression_coeff_u)); |
| memset(params.auto_regression_coeff_v, 127, |
| sizeof(params.auto_regression_coeff_v)); |
| for (int y = 0; y < kLumaHeight; ++y) { |
| for (int x = 0; x < kLumaWidth; ++x) { |
| // This loop relies on the fact that kMaxChromaWidth == kLumaWidth. |
| luma_block_buffer_[y * kLumaWidth + x] = grain_max; |
| u_block_buffer_[y * kLumaWidth + x] = grain_max; |
| v_block_buffer_[y * kLumaWidth + x] = grain_max; |
| } |
| } |
| } else { |
| libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed()); |
| // Allow any valid grain values. |
| const int random_range = grain_max - grain_min + 1; |
| for (int y = 0; y < kLumaHeight; ++y) { |
| for (int x = 0; x < kLumaWidth; ++x) { |
| // This loop relies on the fact that kMaxChromaWidth == kLumaWidth. |
| const int random_y = rnd(random_range); |
| luma_block_buffer_[y * kLumaWidth + x] = random_y + grain_min; |
| const int random_u = rnd(random_range); |
| u_block_buffer_[y * kLumaWidth + x] = random_u + grain_min; |
| const int random_v = rnd(random_range); |
| v_block_buffer_[y * kLumaWidth + x] = random_v + grain_min; |
| } |
| } |
| } |
| if (compare) { |
| memcpy(base_u_block_buffer_, u_block_buffer_, sizeof(u_block_buffer_)); |
| memcpy(base_v_block_buffer_, v_block_buffer_, sizeof(v_block_buffer_)); |
| } |
| |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| chroma_auto_regression_func_(params, luma_block_buffer_, subsampling_x, |
| subsampling_y, u_block_buffer_, |
| v_block_buffer_); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| if (num_runs > 1) { |
| printf("AutoRegressionChroma lag=%d, sub_x=%d, sub_y=%d: %d us\n", |
| coeff_lag, subsampling_x, subsampling_y, |
| static_cast<int>(absl::ToInt64Microseconds(elapsed_time))); |
| return; |
| } |
| if (compare) { |
| base_chroma_auto_regression_func_(params, luma_block_buffer_, subsampling_x, |
| subsampling_y, base_u_block_buffer_, |
| base_v_block_buffer_); |
| EXPECT_TRUE(test_utils::CompareBlocks(u_block_buffer_, base_u_block_buffer_, |
| chroma_width, chroma_height, |
| chroma_width, chroma_width, false)); |
| EXPECT_TRUE(test_utils::CompareBlocks(v_block_buffer_, base_v_block_buffer_, |
| chroma_width, chroma_height, |
| chroma_width, chroma_width, false)); |
| } else { |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("AutoRegressionChromaU lag=%d, sub_x=%d, sub_y=%d", |
| coeff_lag, subsampling_x, subsampling_y) |
| .c_str(), |
| GetARTestDigestChromaU(bitdepth, coeff_lag, subsampling_x, |
| subsampling_y), |
| u_block_buffer_, sizeof(u_block_buffer_), elapsed_time); |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("AutoRegressionChromaV lag=%d, sub_x=%d, sub_y=%d", |
| coeff_lag, subsampling_x, subsampling_y) |
| .c_str(), |
| GetARTestDigestChromaV(bitdepth, coeff_lag, subsampling_x, |
| subsampling_y), |
| v_block_buffer_, sizeof(v_block_buffer_), elapsed_time); |
| } |
| } |
| |
| using AutoRegressionTestChroma8bpp = AutoRegressionTestChroma<8>; |
| |
| TEST_P(AutoRegressionTestChroma8bpp, AutoRegressiveFilterChroma) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma(test_param.coeff_lag, test_param.subsampling_x, |
| test_param.subsampling_y, 1, |
| /*saturate=*/false, |
| /*compare=*/false); |
| } |
| |
| TEST_P(AutoRegressionTestChroma8bpp, AutoRegressiveFilterChromaSaturated) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma(test_param.coeff_lag, test_param.subsampling_x, |
| test_param.subsampling_y, 1, /*saturate=*/true, |
| /*compare=*/true); |
| } |
| |
| TEST_P(AutoRegressionTestChroma8bpp, DISABLED_Speed) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma( |
| test_param.coeff_lag, test_param.subsampling_x, test_param.subsampling_y, |
| // Subsampling cuts each dimension of the chroma blocks in half, so run |
| // twice as many times to compensate. |
| 1e5 * (1 << (test_param.subsampling_y + test_param.subsampling_x)), |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using AutoRegressionTestChroma10bpp = AutoRegressionTestChroma<10>; |
| |
| TEST_P(AutoRegressionTestChroma10bpp, AutoRegressiveFilterChroma) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma(test_param.coeff_lag, test_param.subsampling_x, |
| test_param.subsampling_y, 1, |
| /*saturate=*/false, |
| /*compare=*/false); |
| } |
| |
| TEST_P(AutoRegressionTestChroma10bpp, AutoRegressiveFilterChromaSaturated) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma(test_param.coeff_lag, test_param.subsampling_x, |
| test_param.subsampling_y, 1, /*saturate=*/true, |
| /*compare=*/true); |
| } |
| |
| TEST_P(AutoRegressionTestChroma10bpp, DISABLED_Speed) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma( |
| test_param.coeff_lag, test_param.subsampling_x, test_param.subsampling_y, |
| // Subsampling cuts each dimension of the chroma blocks in half, so run |
| // twice as many times to compensate. |
| 1e5 * (1 << (test_param.subsampling_y + test_param.subsampling_x)), |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using AutoRegressionTestChroma12bpp = AutoRegressionTestChroma<12>; |
| |
| TEST_P(AutoRegressionTestChroma12bpp, AutoRegressiveFilterChroma) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma(test_param.coeff_lag, test_param.subsampling_x, |
| test_param.subsampling_y, 1, |
| /*saturate=*/false, |
| /*compare=*/false); |
| } |
| |
| TEST_P(AutoRegressionTestChroma12bpp, AutoRegressiveFilterChromaSaturated) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma(test_param.coeff_lag, test_param.subsampling_x, |
| test_param.subsampling_y, 1, /*saturate=*/true, |
| /*compare=*/true); |
| } |
| |
| TEST_P(AutoRegressionTestChroma12bpp, DISABLED_Speed) { |
| AutoRegressionChromaTestParam test_param(GetParam()); |
| TestAutoRegressiveFilterChroma( |
| test_param.coeff_lag, test_param.subsampling_x, test_param.subsampling_y, |
| // Subsampling cuts each dimension of the chroma blocks in half, so run |
| // twice as many times to compensate. |
| 1e5 * (1 << (test_param.subsampling_y + test_param.subsampling_x)), |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| INSTANTIATE_TEST_SUITE_P(C, AutoRegressionTestChroma8bpp, |
| testing::Combine(testing::Range(0, 4) /* coeff_lag */, |
| testing::Range(0, |
| 3) /* subsampling */)); |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P(C, AutoRegressionTestChroma10bpp, |
| testing::Combine(testing::Range(0, 4) /* coeff_lag */, |
| testing::Range(0, |
| 3) /* subsampling */)); |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| INSTANTIATE_TEST_SUITE_P(C, AutoRegressionTestChroma12bpp, |
| testing::Combine(testing::Range(0, 4) /* coeff_lag */, |
| testing::Range(0, |
| 3) /* subsampling */)); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, AutoRegressionTestChroma8bpp, |
| testing::Combine(testing::Range(0, 4) /* coeff_lag */, |
| testing::Range(0, |
| 3) /* subsampling */)); |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P(NEON, AutoRegressionTestChroma10bpp, |
| testing::Combine(testing::Range(0, 4) /* coeff_lag */, |
| testing::Range(0, |
| 3) /* subsampling */)); |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| #endif // LIBGAV1_ENABLE_NEON |
| |
| template <int bitdepth> |
| class GrainGenerationTest : public testing::TestWithParam<int> { |
| protected: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| using GrainType = |
| typename std::conditional<bitdepth == 8, int8_t, int16_t>::type; |
| |
| void TestGenerateGrainLuma(int param_index, int num_runs); |
| |
| GrainType luma_block_buffer_[kLumaBlockSize]; |
| }; |
| |
| template <int bitdepth> |
| void GrainGenerationTest<bitdepth>::TestGenerateGrainLuma(int param_index, |
| int num_runs) { |
| FilmGrainParams params = kFilmGrainParams[param_index]; |
| |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| FilmGrain<bitdepth>::GenerateLumaGrain(params, luma_block_buffer_); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| if (num_runs == 1) { |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("GenerateGrainLuma param_index=%d", param_index) |
| .c_str(), |
| GetGrainGenerationTestDigestLuma(bitdepth, param_index), |
| luma_block_buffer_, sizeof(luma_block_buffer_), elapsed_time); |
| } else { |
| printf("GenerateGrainLuma param_index=%d: %d us\n", param_index, |
| static_cast<int>(absl::ToInt64Microseconds(elapsed_time))); |
| } |
| } |
| |
| using GrainGenerationTest8bpp = GrainGenerationTest<8>; |
| |
| TEST_P(GrainGenerationTest8bpp, GenerateGrainLuma) { |
| TestGenerateGrainLuma(GetParam(), 1); |
| } |
| |
| TEST_P(GrainGenerationTest8bpp, DISABLED_LumaSpeed) { |
| TestGenerateGrainLuma(GetParam(), 1e5); |
| } |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using GrainGenerationTest10bpp = GrainGenerationTest<10>; |
| |
| TEST_P(GrainGenerationTest10bpp, GenerateGrainLuma) { |
| TestGenerateGrainLuma(GetParam(), 1); |
| } |
| |
| TEST_P(GrainGenerationTest10bpp, DISABLED_LumaSpeed) { |
| TestGenerateGrainLuma(GetParam(), 1e5); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using GrainGenerationTest12bpp = GrainGenerationTest<12>; |
| |
| TEST_P(GrainGenerationTest12bpp, GenerateGrainLuma) { |
| TestGenerateGrainLuma(GetParam(), 1); |
| } |
| |
| TEST_P(GrainGenerationTest12bpp, DISABLED_LumaSpeed) { |
| TestGenerateGrainLuma(GetParam(), 1e5); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| INSTANTIATE_TEST_SUITE_P(C, GrainGenerationTest8bpp, |
| testing::Range(0, 10) /* param_index */); |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P(C, GrainGenerationTest10bpp, |
| testing::Range(0, 10) /* param_index */); |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| INSTANTIATE_TEST_SUITE_P(C, GrainGenerationTest12bpp, |
| testing::Range(0, 10) /* param_index */); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| // This param type is used for both ConstructStripesTest and |
| // ConstructImageTest. |
| struct ConstructNoiseTestParam { |
| explicit ConstructNoiseTestParam(const std::tuple<int, int>& in) |
| : overlap_flag(std::get<0>(in)) { |
| switch (std::get<1>(in)) { |
| case 0: |
| subsampling_x = 0; |
| subsampling_y = 0; |
| break; |
| case 1: |
| subsampling_x = 1; |
| subsampling_y = 0; |
| break; |
| default: |
| assert(std::get<1>(in) == 2); |
| subsampling_x = 1; |
| subsampling_y = 1; |
| } |
| } |
| const int overlap_flag; |
| int subsampling_x; |
| int subsampling_y; |
| }; |
| |
| template <int bitdepth> |
| class ConstructStripesTest |
| : public testing::TestWithParam<std::tuple<int, int>> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| using GrainType = |
| typename std::conditional<bitdepth == 8, int8_t, int16_t>::type; |
| |
| ConstructStripesTest() { |
| FilmGrainInit_C(); |
| const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth); |
| base_construct_noise_stripes_func_ = |
| dsp->film_grain.construct_noise_stripes[std::get<0>(GetParam())]; |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "C/")) { |
| base_construct_noise_stripes_func_ = nullptr; |
| } else if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } |
| construct_noise_stripes_func_ = |
| dsp->film_grain.construct_noise_stripes[std::get<0>(GetParam())]; |
| } |
| |
| ~ConstructStripesTest() override = default; |
| |
| protected: |
| // |compare| determines whether to compare the output blocks from the SIMD |
| // implementation, if used, and the C implementation. |
| // |saturate| determines whether to set the inputs to maximum values. This is |
| // intended primarily as a way to simplify differences in output when |
| // debugging. |
| void TestConstructNoiseStripes(int overlap_flag, int subsampling_x, |
| int subsampling_y, int num_runs, bool saturate, |
| bool compare); |
| ConstructNoiseStripesFunc construct_noise_stripes_func_; |
| ConstructNoiseStripesFunc base_construct_noise_stripes_func_; |
| GrainType grain_buffer_[kLumaBlockSize]; |
| Array2DView<GrainType> noise_stripes_; |
| // Owns the memory that noise_stripes_ points to. |
| std::unique_ptr<GrainType[]> stripe_buffer_; |
| Array2DView<GrainType> base_noise_stripes_; |
| // Owns the memory that base_stripe_buffer_ points to. |
| std::unique_ptr<GrainType[]> base_stripe_buffer_; |
| }; |
| |
| template <int bitdepth> |
| void ConstructStripesTest<bitdepth>::TestConstructNoiseStripes( |
| int overlap_flag, int subsampling_x, int subsampling_y, int num_runs, |
| bool saturate, bool compare) { |
| if (construct_noise_stripes_func_ == nullptr) return; |
| // Compare is only needed for NEON tests to compare with C output. |
| if (base_construct_noise_stripes_func_ == nullptr && compare) return; |
| |
| const int stripe_width = ((kFrameWidth + subsampling_x) >> subsampling_x); |
| const int stripe_height = kNoiseStripeHeight; |
| const int stripe_size = stripe_height * stripe_width; |
| const int stripe_buffer_size = stripe_size * kNumTestStripes; |
| if (compare) { |
| base_stripe_buffer_.reset(new ( |
| std::nothrow) GrainType[stripe_buffer_size + kNoiseStripePadding]()); |
| ASSERT_NE(base_stripe_buffer_, nullptr); |
| base_noise_stripes_.Reset(kNumTestStripes, stripe_size, |
| base_stripe_buffer_.get()); |
| } |
| stripe_buffer_.reset( |
| new (std::nothrow) GrainType[stripe_buffer_size + kNoiseStripePadding]()); |
| ASSERT_NE(stripe_buffer_, nullptr); |
| noise_stripes_.Reset(kNumTestStripes, stripe_size, stripe_buffer_.get()); |
| |
| const int grain_max = GetGrainMax<bitdepth>(); |
| const int grain_min = GetGrainMin<bitdepth>(); |
| if (saturate) { |
| for (int y = 0; y < kLumaHeight; ++y) { |
| for (int x = 0; x < kLumaWidth; ++x) { |
| grain_buffer_[y * kLumaWidth + x] = grain_max; |
| } |
| } |
| } else { |
| libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed()); |
| // Allow any valid grain values. |
| const int random_range = grain_max - grain_min + 1; |
| for (int y = 0; y < kLumaHeight; ++y) { |
| for (int x = 0; x < kLumaWidth; ++x) { |
| grain_buffer_[y * kLumaWidth + x] = grain_min + rnd(random_range); |
| } |
| } |
| } |
| |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| construct_noise_stripes_func_(grain_buffer_, 68, kFrameWidth, kFrameHeight, |
| subsampling_x, subsampling_y, |
| &noise_stripes_); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| if (num_runs > 1) { |
| printf( |
| "ConstructNoiseStripes Speed Test for overlap=%d, sub_x=%d, " |
| "sub_y=%d: %d us\n", |
| overlap_flag, subsampling_x, subsampling_y, |
| static_cast<int>(absl::ToInt64Microseconds(elapsed_time))); |
| return; |
| } |
| if (compare) { |
| base_construct_noise_stripes_func_(grain_buffer_, 68, kFrameWidth, |
| kFrameHeight, subsampling_x, |
| subsampling_y, &base_noise_stripes_); |
| |
| constexpr int kCompareWidth = 64; |
| for (int stripe = 0; stripe < kNumTestStripes;) { |
| EXPECT_TRUE(test_utils::CompareBlocks( |
| noise_stripes_[stripe], base_noise_stripes_[stripe], kCompareWidth, |
| stripe_height, stripe_width, stripe_width, /*check_padding=*/false, |
| /*print_diff=*/false)); |
| } |
| } else { |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("ConstructNoiseStripes overlap=%d, sub_x=%d, sub_y=%d", |
| overlap_flag, subsampling_x, subsampling_y) |
| .c_str(), |
| GetConstructStripesTestDigest(bitdepth, overlap_flag, subsampling_x, |
| subsampling_y), |
| noise_stripes_[0], stripe_buffer_size, elapsed_time); |
| } |
| } |
| |
| using ConstructStripesTest8bpp = ConstructStripesTest<8>; |
| |
| TEST_P(ConstructStripesTest8bpp, RandomValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| TEST_P(ConstructStripesTest8bpp, SaturatedValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/true, /*compare=*/true); |
| } |
| TEST_P(ConstructStripesTest8bpp, DISABLED_Speed) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/500, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using ConstructStripesTest10bpp = ConstructStripesTest<10>; |
| |
| TEST_P(ConstructStripesTest10bpp, RandomValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| TEST_P(ConstructStripesTest10bpp, SaturatedValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/true, /*compare=*/true); |
| } |
| |
| TEST_P(ConstructStripesTest10bpp, DISABLED_Speed) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/500, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using ConstructStripesTest12bpp = ConstructStripesTest<12>; |
| |
| TEST_P(ConstructStripesTest12bpp, RandomValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| TEST_P(ConstructStripesTest12bpp, SaturatedValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/true, /*compare=*/true); |
| } |
| |
| TEST_P(ConstructStripesTest12bpp, DISABLED_Speed) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseStripes(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/500, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| INSTANTIATE_TEST_SUITE_P(C, ConstructStripesTest8bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P(C, ConstructStripesTest10bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| INSTANTIATE_TEST_SUITE_P(C, ConstructStripesTest12bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| template <int bitdepth> |
| class ConstructImageTest : public testing::TestWithParam<std::tuple<int, int>> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| using GrainType = |
| typename std::conditional<bitdepth == 8, int8_t, int16_t>::type; |
| |
| ConstructImageTest() { |
| FilmGrainInit_C(); |
| const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth); |
| base_construct_noise_image_overlap_func_ = |
| dsp->film_grain.construct_noise_image_overlap; |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "C/")) { |
| base_construct_noise_image_overlap_func_ = nullptr; |
| } else if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } |
| construct_noise_image_overlap_func_ = |
| dsp->film_grain.construct_noise_image_overlap; |
| } |
| |
| ~ConstructImageTest() override = default; |
| |
| protected: |
| // |compare| determines whether to compare the output blocks from the SIMD |
| // implementation, if used, and the C implementation. |
| // |saturate| determines whether to set the inputs to maximum values. This is |
| // intended primarily as a way to simplify differences in output when |
| // debugging. |
| void TestConstructNoiseImage(int overlap_flag, int subsampling_x, |
| int subsampling_y, int num_runs, bool saturate, |
| bool compare); |
| ConstructNoiseImageOverlapFunc construct_noise_image_overlap_func_; |
| ConstructNoiseImageOverlapFunc base_construct_noise_image_overlap_func_; |
| Array2DView<GrainType> noise_stripes_; |
| // Owns the memory that noise_stripes_ points to. |
| std::unique_ptr<GrainType[]> stripe_buffer_; |
| Array2D<GrainType> noise_image_; |
| Array2D<GrainType> base_noise_image_; |
| }; |
| |
| template <int bitdepth> |
| void ConstructImageTest<bitdepth>::TestConstructNoiseImage( |
| int overlap_flag, int subsampling_x, int subsampling_y, int num_runs, |
| bool saturate, bool compare) { |
| if (construct_noise_image_overlap_func_ == nullptr) return; |
| // Compare is only needed for NEON tests to compare with C output. |
| if (base_construct_noise_image_overlap_func_ == nullptr && compare) return; |
| |
| const int image_width = ((kFrameWidth + subsampling_x) >> subsampling_x); |
| const int image_height = ((kFrameHeight + subsampling_y) >> subsampling_y); |
| const int stripe_height = |
| ((kNoiseStripeHeight + subsampling_y) >> subsampling_y); |
| const int image_stride = image_width + kNoiseImagePadding; |
| const int stripe_size = stripe_height * image_width; |
| if (compare) { |
| ASSERT_TRUE(base_noise_image_.Reset(image_height, image_stride, |
| /*zero_initialize=*/false)); |
| } |
| ASSERT_TRUE(noise_image_.Reset(image_height, image_stride, |
| /*zero_initialize=*/false)); |
| // Stride between stripe rows is |image_width|. Padding is only at the |
| // end of the final row of the final stripe to protect from overreads. |
| stripe_buffer_.reset( |
| new (std::nothrow) |
| GrainType[kNumTestStripes * stripe_size + kNoiseStripePadding]); |
| ASSERT_NE(stripe_buffer_, nullptr); |
| noise_stripes_.Reset(kNumTestStripes, stripe_size, stripe_buffer_.get()); |
| |
| const int grain_max = GetGrainMax<bitdepth>(); |
| const int grain_min = GetGrainMin<bitdepth>(); |
| if (saturate) { |
| for (int i = 0; i < stripe_size; ++i) { |
| noise_stripes_[0][i] = grain_max; |
| } |
| for (int stripe = 1; stripe < kNumTestStripes; ++stripe) { |
| memcpy(noise_stripes_[stripe], noise_stripes_[0], |
| stripe_size * sizeof(noise_stripes_[0][0])); |
| } |
| } else { |
| libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed()); |
| // Allow any valid grain values. |
| const int random_range = grain_max - grain_min + 1; |
| for (int stripe = 0; stripe < kNumTestStripes; ++stripe) { |
| // Assign all allocated memory for this stripe. |
| for (int i = 0; i < stripe_height; ++i) { |
| for (int x = 0; x < image_width; ++x) { |
| noise_stripes_[stripe][i * image_width + x] = |
| grain_min + rnd(random_range); |
| } |
| } |
| } |
| } |
| |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| FilmGrain<bitdepth>::ConstructNoiseImage( |
| &noise_stripes_, kFrameWidth, kFrameHeight, subsampling_x, |
| subsampling_y, overlap_flag << (1 - subsampling_y), &noise_image_); |
| if (overlap_flag == 1) { |
| construct_noise_image_overlap_func_(&noise_stripes_, kFrameWidth, |
| kFrameHeight, subsampling_x, |
| subsampling_y, &noise_image_); |
| } |
| } |
| |
| const absl::Duration elapsed_time = absl::Now() - start; |
| if (num_runs > 1) { |
| printf( |
| "ConstructNoiseImage Speed Test for overlap=%d, sub_x=%d, " |
| "sub_y=%d: %d us\n", |
| overlap_flag, subsampling_x, subsampling_y, |
| static_cast<int>(absl::ToInt64Microseconds(elapsed_time))); |
| return; |
| } |
| if (compare) { |
| FilmGrain<bitdepth>::ConstructNoiseImage( |
| &noise_stripes_, kFrameWidth, kFrameHeight, subsampling_x, |
| subsampling_y, overlap_flag << (1 - subsampling_y), &base_noise_image_); |
| if (overlap_flag == 1) { |
| base_construct_noise_image_overlap_func_( |
| &noise_stripes_, kFrameWidth, kFrameHeight, subsampling_x, |
| subsampling_y, &base_noise_image_); |
| } |
| constexpr int kCompareWidth = 72; |
| constexpr int kCompareHeight = 72; |
| EXPECT_TRUE(test_utils::CompareBlocks( |
| noise_image_[0], base_noise_image_[0], kCompareWidth, kCompareHeight, |
| image_stride, image_stride, /*check_padding=*/false, |
| /*print_diff=*/false)); |
| } else { |
| printf("BD%d \"%s\",\n", bitdepth, |
| test_utils::GetMd5Sum(noise_image_[0], image_width, image_height, |
| image_stride) |
| .c_str()); |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("ConstructNoiseImage overlap=%d, sub_x=%d, sub_y=%d", |
| overlap_flag, subsampling_x, subsampling_y) |
| .c_str(), |
| GetConstructImageTestDigest(bitdepth, overlap_flag, subsampling_x, |
| subsampling_y), |
| noise_image_[0], image_width, image_height, image_stride, elapsed_time); |
| } |
| } |
| |
| using ConstructImageTest8bpp = ConstructImageTest<8>; |
| |
| TEST_P(ConstructImageTest8bpp, RandomValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| TEST_P(ConstructImageTest8bpp, SaturatedValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/true, /*compare=*/true); |
| } |
| |
| TEST_P(ConstructImageTest8bpp, DISABLED_Speed) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/500, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using ConstructImageTest10bpp = ConstructImageTest<10>; |
| |
| TEST_P(ConstructImageTest10bpp, RandomValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| TEST_P(ConstructImageTest10bpp, SaturatedValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/true, /*compare=*/true); |
| } |
| |
| TEST_P(ConstructImageTest10bpp, DISABLED_Speed) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/500, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using ConstructImageTest12bpp = ConstructImageTest<12>; |
| |
| TEST_P(ConstructImageTest12bpp, RandomValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| |
| TEST_P(ConstructImageTest12bpp, SaturatedValues) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/1, |
| /*saturate=*/true, /*compare=*/true); |
| } |
| |
| TEST_P(ConstructImageTest12bpp, DISABLED_Speed) { |
| ConstructNoiseTestParam test_params(GetParam()); |
| TestConstructNoiseImage(test_params.overlap_flag, test_params.subsampling_x, |
| test_params.subsampling_y, /*num_runs=*/500, |
| /*saturate=*/false, /*compare=*/false); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| INSTANTIATE_TEST_SUITE_P(C, ConstructImageTest8bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, ConstructImageTest8bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif // LIBGAV1_ENABLE_NEON |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P(C, ConstructImageTest10bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| INSTANTIATE_TEST_SUITE_P(C, ConstructImageTest12bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| template <int bitdepth> |
| class ScalingLookupTableTest : public testing::TestWithParam<int> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| ScalingLookupTableTest() { |
| test_utils::ResetDspTable(bitdepth); |
| FilmGrainInit_C(); |
| const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth); |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } |
| initialize_func_ = dsp->film_grain.initialize_scaling_lut; |
| } |
| ~ScalingLookupTableTest() override = default; |
| |
| protected: |
| void TestSpeed(int num_runs); |
| void ZeroPoints(); |
| |
| private: |
| static constexpr int kScalingLutBufferLength = |
| (kScalingLookupTableSize + kScalingLookupTablePadding) << (bitdepth - 8); |
| dsp::InitializeScalingLutFunc initialize_func_; |
| int16_t scaling_lut_[kScalingLutBufferLength]; |
| }; |
| |
| template <int bitdepth> |
| void ScalingLookupTableTest<bitdepth>::TestSpeed(int num_runs) { |
| if (initialize_func_ == nullptr) return; |
| const int param_index = GetParam(); |
| const FilmGrainParams& params = kFilmGrainParams[param_index]; |
| const absl::Time start = absl::Now(); |
| Memset(scaling_lut_, 0, kScalingLutBufferLength); |
| for (int i = 0; i < num_runs; ++i) { |
| initialize_func_(params.num_y_points, params.point_y_value, |
| params.point_y_scaling, scaling_lut_, |
| kScalingLutBufferLength); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| if (num_runs > 1) { |
| printf("InitializeScalingLut: %d us\n", |
| static_cast<int>(absl::ToInt64Microseconds(elapsed_time))); |
| return; |
| } |
| test_utils::CheckMd5Digest( |
| "FilmGrain", |
| absl::StrFormat("InitializeScalingLut for param set: %d", param_index) |
| .c_str(), |
| GetScalingInitTestDigest(param_index, bitdepth), scaling_lut_, |
| (sizeof(scaling_lut_[0]) * kScalingLookupTableSize) << (bitdepth - 8), |
| elapsed_time); |
| } |
| |
| template <int bitdepth> |
| void ScalingLookupTableTest<bitdepth>::ZeroPoints() { |
| if (initialize_func_ == nullptr) return; |
| const int param_index = GetParam(); |
| const FilmGrainParams& params = kFilmGrainParams[param_index]; |
| initialize_func_(0, params.point_y_value, params.point_y_scaling, |
| scaling_lut_, kScalingLookupTableSize); |
| for (int i = 0; i < kScalingLookupTableSize; ++i) { |
| ASSERT_EQ(scaling_lut_[i], 0); |
| } |
| } |
| |
| using ScalingLookupTableTest8bpp = ScalingLookupTableTest<8>; |
| |
| TEST_P(ScalingLookupTableTest8bpp, ZeroPoints) { ZeroPoints(); } |
| |
| TEST_P(ScalingLookupTableTest8bpp, Correctness) { TestSpeed(/*num_runs=*/1); } |
| |
| TEST_P(ScalingLookupTableTest8bpp, DISABLED_Speed) { |
| TestSpeed(/*num_runs=*/1e5); |
| } |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using ScalingLookupTableTest10bpp = ScalingLookupTableTest<10>; |
| |
| TEST_P(ScalingLookupTableTest10bpp, ZeroPoints) { ZeroPoints(); } |
| |
| TEST_P(ScalingLookupTableTest10bpp, Correctness) { TestSpeed(/*num_runs=*/1); } |
| |
| TEST_P(ScalingLookupTableTest10bpp, DISABLED_Speed) { |
| TestSpeed(/*num_runs=*/1e5); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using ScalingLookupTableTest12bpp = ScalingLookupTableTest<12>; |
| |
| TEST_P(ScalingLookupTableTest12bpp, ZeroPoints) { ZeroPoints(); } |
| |
| TEST_P(ScalingLookupTableTest12bpp, Correctness) { TestSpeed(/*num_runs=*/1); } |
| |
| TEST_P(ScalingLookupTableTest12bpp, DISABLED_Speed) { |
| TestSpeed(/*num_runs=*/1e5); |
| } |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| INSTANTIATE_TEST_SUITE_P(C, ScalingLookupTableTest8bpp, |
| testing::Range(0, kNumFilmGrainTestParams)); |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, ScalingLookupTableTest8bpp, |
| testing::Range(0, kNumFilmGrainTestParams)); |
| #endif |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| INSTANTIATE_TEST_SUITE_P(C, ScalingLookupTableTest10bpp, |
| testing::Range(0, kNumFilmGrainTestParams)); |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, ScalingLookupTableTest10bpp, |
| testing::Range(0, kNumFilmGrainTestParams)); |
| #endif |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| INSTANTIATE_TEST_SUITE_P(C, ScalingLookupTableTest12bpp, |
| testing::Range(0, kNumFilmGrainTestParams)); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| struct BlendNoiseTestParam { |
| explicit BlendNoiseTestParam(const std::tuple<int, int>& in) |
| : chroma_scaling_from_luma(std::get<0>(in)) { |
| switch (std::get<1>(in)) { |
| case 0: |
| subsampling_x = 0; |
| subsampling_y = 0; |
| break; |
| case 1: |
| subsampling_x = 1; |
| subsampling_y = 0; |
| break; |
| default: |
| assert(std::get<1>(in) == 2); |
| subsampling_x = 1; |
| subsampling_y = 1; |
| } |
| } |
| const int chroma_scaling_from_luma; |
| int subsampling_x; |
| int subsampling_y; |
| }; |
| |
| template <int bitdepth, typename Pixel> |
| class BlendNoiseTest : public testing::TestWithParam<std::tuple<int, int>> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| using GrainType = |
| typename std::conditional<bitdepth == 8, int8_t, int16_t>::type; |
| |
| BlendNoiseTest() { |
| test_utils::ResetDspTable(bitdepth); |
| FilmGrainInit_C(); |
| const dsp::Dsp* const dsp = dsp::GetDspTable(bitdepth); |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } else if (absl::StartsWith(test_case, "SSE41/")) { |
| FilmGrainInit_SSE4_1(); |
| } |
| const BlendNoiseTestParam test_param(GetParam()); |
| chroma_scaling_from_luma_ = test_param.chroma_scaling_from_luma; |
| blend_luma_func_ = dsp->film_grain.blend_noise_luma; |
| blend_chroma_func_ = |
| dsp->film_grain.blend_noise_chroma[chroma_scaling_from_luma_]; |
| subsampling_x_ = test_param.subsampling_x; |
| subsampling_y_ = test_param.subsampling_y; |
| |
| uv_width_ = (width_ + subsampling_x_) >> subsampling_x_; |
| uv_height_ = (height_ + subsampling_y_) >> subsampling_y_; |
| uv_stride_ = uv_width_ * sizeof(Pixel); |
| y_stride_ = width_ * sizeof(Pixel); |
| const size_t buffer_size = |
| sizeof(Pixel) * (width_ * height_ + 2 * uv_width_ * uv_height_ + |
| 3 * kBorderPixelsFilmGrain); |
| source_buffer_.reset(new (std::nothrow) uint8_t[buffer_size]); |
| memset(source_buffer_.get(), 0, sizeof(source_buffer_[0]) * buffer_size); |
| dest_buffer_.reset(new (std::nothrow) uint8_t[buffer_size]); |
| memset(dest_buffer_.get(), 0, sizeof(dest_buffer_[0]) * buffer_size); |
| source_plane_y_ = source_buffer_.get(); |
| source_plane_u_ = |
| source_plane_y_ + y_stride_ * height_ + kBorderPixelsFilmGrain; |
| source_plane_v_ = |
| source_plane_u_ + uv_stride_ * uv_height_ + kBorderPixelsFilmGrain; |
| dest_plane_y_ = dest_buffer_.get(); |
| dest_plane_u_ = |
| dest_plane_y_ + y_stride_ * height_ + kBorderPixelsFilmGrain; |
| dest_plane_v_ = |
| dest_plane_u_ + uv_stride_ * uv_height_ + kBorderPixelsFilmGrain; |
| } |
| ~BlendNoiseTest() override = default; |
| |
| protected: |
| void TestSpeed(int num_runs); |
| |
| private: |
| static constexpr int kScalingLutBufferLength = |
| (kScalingLookupTableSize + kScalingLookupTablePadding) << 2; |
| |
| void ConvertScalingLut10bpp(int16_t* scaling_lut_10bpp, |
| const int16_t* src_scaling_lut); |
| dsp::BlendNoiseWithImageLumaFunc blend_luma_func_; |
| dsp::BlendNoiseWithImageChromaFunc blend_chroma_func_; |
| |
| const int width_ = 1921; |
| const int height_ = 1081; |
| int chroma_scaling_from_luma_ = 0; |
| int subsampling_x_ = 0; |
| int subsampling_y_ = 0; |
| int uv_width_ = 0; |
| int uv_height_ = 0; |
| int uv_stride_ = 0; |
| int y_stride_ = 0; |
| // This holds the data that |source_plane_y_|, |source_plane_u_|, and |
| // |source_plane_v_| point to. |
| std::unique_ptr<uint8_t[]> source_buffer_; |
| // This holds the data that |dest_plane_y_|, |dest_plane_u_|, and |
| // |dest_plane_v_| point to. |
| std::unique_ptr<uint8_t[]> dest_buffer_; |
| uint8_t* source_plane_y_ = nullptr; |
| uint8_t* source_plane_u_ = nullptr; |
| uint8_t* source_plane_v_ = nullptr; |
| uint8_t* dest_plane_y_ = nullptr; |
| uint8_t* dest_plane_u_ = nullptr; |
| uint8_t* dest_plane_v_ = nullptr; |
| Array2D<GrainType> noise_image_[kMaxPlanes]; |
| int16_t scaling_lut_10bpp_y_[kScalingLutBufferLength]; |
| int16_t scaling_lut_10bpp_u_[kScalingLutBufferLength]; |
| int16_t scaling_lut_10bpp_v_[kScalingLutBufferLength]; |
| }; |
| |
| template <int bitdepth, typename Pixel> |
| void BlendNoiseTest<bitdepth, Pixel>::ConvertScalingLut10bpp( |
| int16_t* scaling_lut_10bpp, const int16_t* src_scaling_lut) { |
| for (int i = 0; i < kScalingLookupTableSize - 1; ++i) { |
| const int x_base = i << 2; |
| const int start = src_scaling_lut[i]; |
| const int end_index = std::min(i + 1, kScalingLookupTableSize - 1); |
| const int end = src_scaling_lut[end_index]; |
| const int delta = end - start; |
| scaling_lut_10bpp[x_base] = start; |
| scaling_lut_10bpp[x_base + 1] = start + RightShiftWithRounding(delta, 2); |
| scaling_lut_10bpp[x_base + 2] = |
| start + RightShiftWithRounding(2 * delta, 2); |
| scaling_lut_10bpp[x_base + 3] = |
| start + RightShiftWithRounding(3 * delta, 2); |
| } |
| } |
| |
| template <int bitdepth, typename Pixel> |
| void BlendNoiseTest<bitdepth, Pixel>::TestSpeed(const int num_runs) { |
| if (blend_chroma_func_ == nullptr || blend_luma_func_ == nullptr) return; |
| ASSERT_TRUE(noise_image_[kPlaneY].Reset(height_, |
| width_ + kBorderPixelsFilmGrain, |
| /*zero_initialize=*/false)); |
| ASSERT_TRUE(noise_image_[kPlaneU].Reset(uv_height_, |
| uv_width_ + kBorderPixelsFilmGrain, |
| /*zero_initialize=*/false)); |
| ASSERT_TRUE(noise_image_[kPlaneV].Reset(uv_height_, |
| uv_width_ + kBorderPixelsFilmGrain, |
| /*zero_initialize=*/false)); |
| libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed()); |
| // Allow any valid grain values. |
| const int grain_max = GetGrainMax<bitdepth>(); |
| const int grain_min = GetGrainMin<bitdepth>(); |
| const int random_range = grain_max - grain_min + 1; |
| auto* src_y = reinterpret_cast<Pixel*>(source_plane_y_); |
| auto* src_u = reinterpret_cast<Pixel*>(source_plane_u_); |
| auto* src_v = reinterpret_cast<Pixel*>(source_plane_v_); |
| for (int y = 0; y < height_; ++y) { |
| for (int x = 0; x < width_; ++x) { |
| const int random_source_y = rnd(random_range); |
| // Populating the luma source ensures the lookup table is tested. Chroma |
| // planes are given identical values. Giving them different values would |
| // artificially differentiate the outputs. It's important that the test |
| // expect that different outputs are caused by the different scaling |
| // lookup tables, rather than by different inputs. |
| const int uv_y_pos = y >> subsampling_y_; |
| const int uv_x_pos = x >> subsampling_x_; |
| src_y[y * width_ + x] = random_source_y; |
| src_u[uv_y_pos * uv_width_ + uv_x_pos] = random_source_y; |
| src_v[uv_y_pos * uv_width_ + uv_x_pos] = random_source_y; |
| const int random_y = rnd(random_range); |
| noise_image_[kPlaneY][y][x] = random_y + grain_min; |
| const int random_u = rnd(random_range); |
| noise_image_[kPlaneU][uv_y_pos][uv_x_pos] = random_u + grain_min; |
| const int random_v = rnd(random_range); |
| noise_image_[kPlaneV][uv_y_pos][uv_x_pos] = random_v + grain_min; |
| } |
| } |
| static constexpr int16_t kTestScalingLutY[kScalingLookupTableSize] = { |
| 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, |
| 75, 76, 77, 79, 80, 81, 83, 84, 86, 87, 88, 90, 91, 92, 92, |
| 93, 93, 94, 95, 95, 96, 97, 97, 98, 98, 99, 99, 99, 99, 98, |
| 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, |
| 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, |
| 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, |
| 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, |
| 102, 102, |
| }; |
| static constexpr int16_t kTestScalingLutU[kScalingLookupTableSize] = { |
| 30, 42, 53, 65, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, |
| 75, 76, 78, 79, 81, 82, 83, 85, 86, 88, 89, 91, 92, 93, 93, |
| 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 99, 99, 99, |
| 99, 99, 99, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, |
| 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, |
| 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, |
| 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, |
| 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, |
| 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, |
| 100, 100, 100, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, |
| 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, |
| 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, |
| 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, |
| 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 96, 96, 96, 96, 96, |
| 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, |
| 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 95, |
| 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, |
| 95, 95, |
| }; |
| static constexpr int16_t kTestScalingLutV[kScalingLookupTableSize] = { |
| 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, |
| 75, 75, 78, 79, 81, 82, 83, 85, 86, 88, 89, 91, 92, 93, 93, |
| 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, 99, 99, 99, 99, 98, |
| 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, |
| 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, |
| 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, |
| 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, |
| 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, |
| 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, |
| 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, |
| 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, |
| 255, 255, |
| }; |
| |
| if (bitdepth == 10) { |
| for (int i = 0; i < kScalingLutBufferLength; ++i) { |
| ConvertScalingLut10bpp(scaling_lut_10bpp_y_, kTestScalingLutY); |
| ConvertScalingLut10bpp(scaling_lut_10bpp_u_, kTestScalingLutU); |
| ConvertScalingLut10bpp(scaling_lut_10bpp_v_, kTestScalingLutV); |
| } |
| } |
| const FilmGrainParams& params = kFilmGrainParams[0]; |
| const int min_value = 16 << (bitdepth - 8); |
| const int max_value = 235 << (bitdepth - 8); |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| if (chroma_scaling_from_luma_) { |
| blend_chroma_func_( |
| kPlaneU, params, noise_image_, min_value, max_value, width_, height_, |
| /*start_height=*/0, subsampling_x_, subsampling_y_, |
| (bitdepth == 10) ? scaling_lut_10bpp_y_ : kTestScalingLutY, |
| source_plane_y_, y_stride_, source_plane_u_, uv_stride_, |
| dest_plane_u_, uv_stride_); |
| blend_chroma_func_( |
| kPlaneV, params, noise_image_, min_value, max_value, width_, height_, |
| /*start_height=*/0, subsampling_x_, subsampling_y_, |
| (bitdepth == 10) ? scaling_lut_10bpp_y_ : kTestScalingLutY, |
| source_plane_y_, y_stride_, source_plane_v_, uv_stride_, |
| dest_plane_v_, uv_stride_); |
| } else { |
| blend_chroma_func_( |
| kPlaneU, params, noise_image_, min_value, max_value, width_, height_, |
| /*start_height=*/0, subsampling_x_, subsampling_y_, |
| (bitdepth == 10) ? scaling_lut_10bpp_u_ : kTestScalingLutU, |
| source_plane_y_, y_stride_, source_plane_u_, uv_stride_, |
| dest_plane_u_, uv_stride_); |
| blend_chroma_func_( |
| kPlaneV, params, noise_image_, min_value, max_value, width_, height_, |
| /*start_height=*/0, subsampling_x_, subsampling_y_, |
| (bitdepth == 10) ? scaling_lut_10bpp_v_ : kTestScalingLutV, |
| source_plane_y_, y_stride_, source_plane_v_, uv_stride_, |
| dest_plane_v_, uv_stride_); |
| } |
| blend_luma_func_(noise_image_, min_value, max_value, params.chroma_scaling, |
| width_, height_, /*start_height=*/0, |
| (bitdepth == 10) ? scaling_lut_10bpp_y_ : kTestScalingLutY, |
| source_plane_y_, y_stride_, dest_plane_y_, y_stride_); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| const char* digest_luma = GetBlendLumaTestDigest(bitdepth); |
| printf("YBD%d \"%s\",\n", bitdepth, |
| test_utils::GetMd5Sum(dest_plane_y_, y_stride_ * height_).c_str()); |
| printf("UBD%d \"%s\",\n", bitdepth, |
| test_utils::GetMd5Sum(dest_plane_u_, uv_stride_ * uv_height_).c_str()); |
| printf("VBD%d \"%s\",\n", bitdepth, |
| test_utils::GetMd5Sum(dest_plane_v_, uv_stride_ * uv_height_).c_str()); |
| test_utils::CheckMd5Digest( |
| "BlendNoiseWithImage", |
| absl::StrFormat("Luma cfl=%d, sub_x=%d, sub_y=%d", |
| chroma_scaling_from_luma_, subsampling_x_, subsampling_y_) |
| .c_str(), |
| digest_luma, dest_plane_y_, y_stride_ * height_, elapsed_time); |
| const char* digest_chroma_u = GetBlendChromaUTestDigest( |
| bitdepth, chroma_scaling_from_luma_, subsampling_x_, subsampling_y_); |
| test_utils::CheckMd5Digest( |
| "BlendNoiseWithImage", |
| absl::StrFormat("ChromaU cfl=%d, sub_x=%d, sub_y=%d", |
| chroma_scaling_from_luma_, subsampling_x_, subsampling_y_) |
| .c_str(), |
| digest_chroma_u, dest_plane_u_, uv_stride_ * uv_height_, elapsed_time); |
| const char* digest_chroma_v = GetBlendChromaVTestDigest( |
| bitdepth, chroma_scaling_from_luma_, subsampling_x_, subsampling_y_); |
| test_utils::CheckMd5Digest( |
| "BlendNoiseWithImage", |
| absl::StrFormat("ChromaV cfl=%d, sub_x=%d, sub_y=%d", |
| chroma_scaling_from_luma_, subsampling_x_, subsampling_y_) |
| .c_str(), |
| digest_chroma_v, dest_plane_v_, uv_stride_ * uv_height_, elapsed_time); |
| } |
| |
| using BlendNoiseTest8bpp = BlendNoiseTest<8, uint8_t>; |
| |
| TEST_P(BlendNoiseTest8bpp, MatchesOriginalOutput) { TestSpeed(1); } |
| |
| TEST_P(BlendNoiseTest8bpp, DISABLED_Speed) { TestSpeed(kNumSpeedTests); } |
| |
| INSTANTIATE_TEST_SUITE_P(C, BlendNoiseTest8bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #if LIBGAV1_ENABLE_SSE4_1 |
| INSTANTIATE_TEST_SUITE_P(SSE41, BlendNoiseTest8bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, BlendNoiseTest8bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using BlendNoiseTest10bpp = BlendNoiseTest<10, uint16_t>; |
| |
| TEST_P(BlendNoiseTest10bpp, MatchesOriginalOutput) { TestSpeed(1); } |
| |
| TEST_P(BlendNoiseTest10bpp, DISABLED_Speed) { TestSpeed(kNumSpeedTests); } |
| |
| INSTANTIATE_TEST_SUITE_P(C, BlendNoiseTest10bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #if LIBGAV1_ENABLE_SSE4_1 |
| INSTANTIATE_TEST_SUITE_P(SSE41, BlendNoiseTest10bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, BlendNoiseTest10bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using BlendNoiseTest12bpp = BlendNoiseTest<12, uint16_t>; |
| |
| TEST_P(BlendNoiseTest12bpp, MatchesOriginalOutput) { TestSpeed(1); } |
| |
| TEST_P(BlendNoiseTest12bpp, DISABLED_Speed) { TestSpeed(kNumSpeedTests); } |
| |
| INSTANTIATE_TEST_SUITE_P(C, BlendNoiseTest12bpp, |
| testing::Combine(testing::Range(0, 2), |
| testing::Range(0, 3))); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| template <int bitdepth, typename Pixel> |
| class FilmGrainSpeedTest : public testing::TestWithParam<int> { |
| public: |
| static_assert(bitdepth >= kBitdepth8 && bitdepth <= LIBGAV1_MAX_BITDEPTH, ""); |
| FilmGrainSpeedTest() { |
| test_utils::ResetDspTable(bitdepth); |
| FilmGrainInit_C(); |
| |
| const testing::TestInfo* const test_info = |
| testing::UnitTest::GetInstance()->current_test_info(); |
| const char* const test_case = test_info->test_suite_name(); |
| if (absl::StartsWith(test_case, "NEON/")) { |
| #if LIBGAV1_ENABLE_NEON |
| FilmGrainInit_NEON(); |
| #endif |
| } else if (absl::StartsWith(test_case, "SSE41/")) { |
| FilmGrainInit_SSE4_1(); |
| } |
| uv_width_ = (width_ + subsampling_x_) >> subsampling_x_; |
| uv_height_ = (height_ + subsampling_y_) >> subsampling_y_; |
| uv_stride_ = uv_width_ * sizeof(Pixel); |
| y_stride_ = width_ * sizeof(Pixel); |
| const size_t buffer_size = |
| sizeof(Pixel) * (width_ * height_ + 2 * uv_width_ * uv_height_); |
| source_buffer_.reset(new (std::nothrow) uint8_t[buffer_size]); |
| memset(source_buffer_.get(), 0, sizeof(source_buffer_[0]) * buffer_size); |
| dest_buffer_.reset(new (std::nothrow) uint8_t[buffer_size]); |
| memset(dest_buffer_.get(), 0, sizeof(dest_buffer_[0]) * buffer_size); |
| source_plane_y_ = source_buffer_.get(); |
| source_plane_u_ = source_plane_y_ + y_stride_ * height_; |
| source_plane_v_ = source_plane_u_ + uv_stride_ * uv_height_; |
| dest_plane_y_ = dest_buffer_.get(); |
| dest_plane_u_ = dest_plane_y_ + y_stride_ * height_; |
| dest_plane_v_ = dest_plane_u_ + uv_stride_ * uv_height_; |
| const int num_threads = GetParam(); |
| thread_pool_ = ThreadPool::Create(num_threads); |
| } |
| ~FilmGrainSpeedTest() override = default; |
| |
| protected: |
| void TestSpeed(int num_runs); |
| |
| private: |
| const int width_ = 1920; |
| const int height_ = 1080; |
| const int subsampling_x_ = 1; |
| const int subsampling_y_ = 1; |
| int uv_width_ = 0; |
| int uv_height_ = 0; |
| int uv_stride_ = 0; |
| int y_stride_ = 0; |
| std::unique_ptr<uint8_t[]> source_buffer_; |
| std::unique_ptr<uint8_t[]> dest_buffer_; |
| const uint8_t* source_plane_y_ = nullptr; |
| const uint8_t* source_plane_u_ = nullptr; |
| const uint8_t* source_plane_v_ = nullptr; |
| uint8_t* dest_plane_y_ = nullptr; |
| uint8_t* dest_plane_u_ = nullptr; |
| uint8_t* dest_plane_v_ = nullptr; |
| std::unique_ptr<ThreadPool> thread_pool_; |
| }; |
| |
| // Each run of the speed test adds film grain noise to 10 dummy frames. The |
| // film grain parameters for the 10 frames were generated with aomenc. |
| template <int bitdepth, typename Pixel> |
| void FilmGrainSpeedTest<bitdepth, Pixel>::TestSpeed(const int num_runs) { |
| const dsp::Dsp* dsp = GetDspTable(bitdepth); |
| if (dsp->film_grain.blend_noise_chroma[0] == nullptr || |
| dsp->film_grain.blend_noise_luma == nullptr) { |
| return; |
| } |
| for (int k = 0; k < kNumFilmGrainTestParams; ++k) { |
| const FilmGrainParams& params = kFilmGrainParams[k]; |
| const absl::Time start = absl::Now(); |
| for (int i = 0; i < num_runs; ++i) { |
| FilmGrain<bitdepth> film_grain(params, /*is_monochrome=*/false, |
| /*color_matrix_is_identity=*/false, |
| subsampling_x_, subsampling_y_, width_, |
| height_, thread_pool_.get()); |
| EXPECT_TRUE(film_grain.AddNoise( |
| source_plane_y_, y_stride_, source_plane_u_, source_plane_v_, |
| uv_stride_, dest_plane_y_, y_stride_, dest_plane_u_, dest_plane_v_, |
| uv_stride_)); |
| } |
| const absl::Duration elapsed_time = absl::Now() - start; |
| const char* digest_luma = GetTestDigestLuma(bitdepth, k); |
| test_utils::CheckMd5Digest( |
| "FilmGrainSynthesisLuma", |
| absl::StrFormat("kFilmGrainParams[%d]", k).c_str(), digest_luma, |
| dest_plane_y_, y_stride_ * height_, elapsed_time); |
| const char* digest_chroma_u = GetTestDigestChromaU(bitdepth, k); |
| test_utils::CheckMd5Digest( |
| "FilmGrainSynthesisChromaU", |
| absl::StrFormat("kFilmGrainParams[%d]", k).c_str(), digest_chroma_u, |
| dest_plane_u_, uv_stride_ * uv_height_, elapsed_time); |
| const char* digest_chroma_v = GetTestDigestChromaV(bitdepth, k); |
| test_utils::CheckMd5Digest( |
| "FilmGrainSynthesisChromaV", |
| absl::StrFormat("kFilmGrainParams[%d]", k).c_str(), digest_chroma_v, |
| dest_plane_v_, uv_stride_ * uv_height_, elapsed_time); |
| } |
| } |
| |
| using FilmGrainSpeedTest8bpp = FilmGrainSpeedTest<8, uint8_t>; |
| |
| TEST_P(FilmGrainSpeedTest8bpp, MatchesOriginalOutput) { TestSpeed(1); } |
| |
| TEST_P(FilmGrainSpeedTest8bpp, DISABLED_Speed) { TestSpeed(kNumSpeedTests); } |
| |
| INSTANTIATE_TEST_SUITE_P(C, FilmGrainSpeedTest8bpp, testing::Values(0, 3, 8)); |
| |
| #if LIBGAV1_ENABLE_SSE4_1 |
| INSTANTIATE_TEST_SUITE_P(SSE41, FilmGrainSpeedTest8bpp, |
| testing::Values(0, 3, 8)); |
| #endif |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, FilmGrainSpeedTest8bpp, |
| testing::Values(0, 3, 8)); |
| #endif |
| |
| #if LIBGAV1_MAX_BITDEPTH >= 10 |
| using FilmGrainSpeedTest10bpp = FilmGrainSpeedTest<10, uint16_t>; |
| |
| TEST_P(FilmGrainSpeedTest10bpp, MatchesOriginalOutput) { TestSpeed(1); } |
| |
| TEST_P(FilmGrainSpeedTest10bpp, DISABLED_Speed) { TestSpeed(kNumSpeedTests); } |
| |
| INSTANTIATE_TEST_SUITE_P(C, FilmGrainSpeedTest10bpp, testing::Values(0, 3, 8)); |
| |
| #if LIBGAV1_ENABLE_SSE4_1 |
| INSTANTIATE_TEST_SUITE_P(SSE41, FilmGrainSpeedTest10bpp, |
| testing::Values(0, 3, 8)); |
| #endif |
| |
| #if LIBGAV1_ENABLE_NEON |
| INSTANTIATE_TEST_SUITE_P(NEON, FilmGrainSpeedTest10bpp, |
| testing::Values(0, 3, 8)); |
| #endif |
| |
| #endif // LIBGAV1_MAX_BITDEPTH >= 10 |
| |
| #if LIBGAV1_MAX_BITDEPTH == 12 |
| using FilmGrainSpeedTest12bpp = FilmGrainSpeedTest<12, uint16_t>; |
| |
| TEST_P(FilmGrainSpeedTest12bpp, MatchesOriginalOutput) { TestSpeed(1); } |
| |
| TEST_P(FilmGrainSpeedTest12bpp, DISABLED_Speed) { TestSpeed(kNumSpeedTests); } |
| |
| INSTANTIATE_TEST_SUITE_P(C, FilmGrainSpeedTest12bpp, testing::Values(0, 3, 8)); |
| #endif // LIBGAV1_MAX_BITDEPTH == 12 |
| |
| } // namespace |
| } // namespace film_grain |
| } // namespace dsp |
| } // namespace libgav1 |