Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 1 | /* |
Yaowu Xu | bde4ac8 | 2016-11-28 15:26:06 -0800 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 3 | * |
Yaowu Xu | bde4ac8 | 2016-11-28 15:26:06 -0800 | [diff] [blame] | 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
| 12 | #include <stdio.h> |
| 13 | #include <stdlib.h> |
James Zern | 723bbf9 | 2022-04-28 12:54:06 -0700 | [diff] [blame] | 14 | #include <stdbool.h> |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 15 | #include <memory.h> |
| 16 | #include <math.h> |
| 17 | #include <assert.h> |
| 18 | |
Sarah Parker | 29267d3 | 2018-11-13 16:01:41 -0800 | [diff] [blame] | 19 | #include "config/aom_dsp_rtcd.h" |
| 20 | |
emilkeyder@google.com | 30ba4b4 | 2017-02-22 21:07:55 -0500 | [diff] [blame] | 21 | #include "av1/encoder/global_motion.h" |
| 22 | |
Sarah Parker | 0115e93 | 2018-10-22 14:14:22 -0700 | [diff] [blame] | 23 | #include "av1/common/convolve.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 24 | #include "av1/common/warped_motion.h" |
| 25 | |
| 26 | #include "av1/encoder/segmentation.h" |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 27 | |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 28 | #define MIN_TRANS_THRESH (1 * GM_TRANS_DECODE_FACTOR) |
| 29 | |
| 30 | // Border over which to compute the global motion |
| 31 | #define ERRORADV_BORDER 0 |
| 32 | |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 33 | /* clang-format off */ |
Rachel Barker | 80477f4 | 2023-08-07 19:50:19 +0000 | [diff] [blame] | 34 | // Error metric used for global motion evaluation. |
| 35 | // For 8-bit input, the pixel error used to index this table will always |
| 36 | // be between -255 and +255. But for 10- and 12-bit input, we use interpolation |
| 37 | // which means that we need to support indices of -256 and +256 as well. |
| 38 | // Therefore, the table is offset so that logical index 0 corresponds to |
| 39 | // error_measure_lut[256]. |
| 40 | const int error_measure_lut[513] = { |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 41 | // pow 0.7 |
Rachel Barker | 80477f4 | 2023-08-07 19:50:19 +0000 | [diff] [blame] | 42 | 16384, 16384, 16339, 16294, 16249, 16204, 16158, 16113, |
| 43 | 16068, 16022, 15977, 15932, 15886, 15840, 15795, 15749, |
| 44 | 15703, 15657, 15612, 15566, 15520, 15474, 15427, 15381, |
| 45 | 15335, 15289, 15242, 15196, 15149, 15103, 15056, 15010, |
| 46 | 14963, 14916, 14869, 14822, 14775, 14728, 14681, 14634, |
| 47 | 14587, 14539, 14492, 14445, 14397, 14350, 14302, 14254, |
| 48 | 14206, 14159, 14111, 14063, 14015, 13967, 13918, 13870, |
| 49 | 13822, 13773, 13725, 13676, 13628, 13579, 13530, 13481, |
| 50 | 13432, 13383, 13334, 13285, 13236, 13187, 13137, 13088, |
| 51 | 13038, 12988, 12939, 12889, 12839, 12789, 12739, 12689, |
| 52 | 12639, 12588, 12538, 12487, 12437, 12386, 12335, 12285, |
| 53 | 12234, 12183, 12132, 12080, 12029, 11978, 11926, 11875, |
| 54 | 11823, 11771, 11719, 11667, 11615, 11563, 11511, 11458, |
| 55 | 11406, 11353, 11301, 11248, 11195, 11142, 11089, 11036, |
| 56 | 10982, 10929, 10875, 10822, 10768, 10714, 10660, 10606, |
| 57 | 10552, 10497, 10443, 10388, 10333, 10279, 10224, 10168, |
| 58 | 10113, 10058, 10002, 9947, 9891, 9835, 9779, 9723, |
| 59 | 9666, 9610, 9553, 9497, 9440, 9383, 9326, 9268, |
| 60 | 9211, 9153, 9095, 9037, 8979, 8921, 8862, 8804, |
| 61 | 8745, 8686, 8627, 8568, 8508, 8449, 8389, 8329, |
| 62 | 8269, 8208, 8148, 8087, 8026, 7965, 7903, 7842, |
| 63 | 7780, 7718, 7656, 7593, 7531, 7468, 7405, 7341, |
| 64 | 7278, 7214, 7150, 7086, 7021, 6956, 6891, 6826, |
| 65 | 6760, 6695, 6628, 6562, 6495, 6428, 6361, 6293, |
| 66 | 6225, 6157, 6089, 6020, 5950, 5881, 5811, 5741, |
| 67 | 5670, 5599, 5527, 5456, 5383, 5311, 5237, 5164, |
| 68 | 5090, 5015, 4941, 4865, 4789, 4713, 4636, 4558, |
| 69 | 4480, 4401, 4322, 4242, 4162, 4080, 3998, 3916, |
| 70 | 3832, 3748, 3663, 3577, 3490, 3402, 3314, 3224, |
| 71 | 3133, 3041, 2948, 2854, 2758, 2661, 2562, 2461, |
| 72 | 2359, 2255, 2148, 2040, 1929, 1815, 1698, 1577, |
| 73 | 1452, 1323, 1187, 1045, 894, 731, 550, 339, |
| 74 | 0, 339, 550, 731, 894, 1045, 1187, 1323, |
| 75 | 1452, 1577, 1698, 1815, 1929, 2040, 2148, 2255, |
| 76 | 2359, 2461, 2562, 2661, 2758, 2854, 2948, 3041, |
| 77 | 3133, 3224, 3314, 3402, 3490, 3577, 3663, 3748, |
| 78 | 3832, 3916, 3998, 4080, 4162, 4242, 4322, 4401, |
| 79 | 4480, 4558, 4636, 4713, 4789, 4865, 4941, 5015, |
| 80 | 5090, 5164, 5237, 5311, 5383, 5456, 5527, 5599, |
| 81 | 5670, 5741, 5811, 5881, 5950, 6020, 6089, 6157, |
| 82 | 6225, 6293, 6361, 6428, 6495, 6562, 6628, 6695, |
| 83 | 6760, 6826, 6891, 6956, 7021, 7086, 7150, 7214, |
| 84 | 7278, 7341, 7405, 7468, 7531, 7593, 7656, 7718, |
| 85 | 7780, 7842, 7903, 7965, 8026, 8087, 8148, 8208, |
| 86 | 8269, 8329, 8389, 8449, 8508, 8568, 8627, 8686, |
| 87 | 8745, 8804, 8862, 8921, 8979, 9037, 9095, 9153, |
| 88 | 9211, 9268, 9326, 9383, 9440, 9497, 9553, 9610, |
| 89 | 9666, 9723, 9779, 9835, 9891, 9947, 10002, 10058, |
| 90 | 10113, 10168, 10224, 10279, 10333, 10388, 10443, 10497, |
| 91 | 10552, 10606, 10660, 10714, 10768, 10822, 10875, 10929, |
| 92 | 10982, 11036, 11089, 11142, 11195, 11248, 11301, 11353, |
| 93 | 11406, 11458, 11511, 11563, 11615, 11667, 11719, 11771, |
| 94 | 11823, 11875, 11926, 11978, 12029, 12080, 12132, 12183, |
| 95 | 12234, 12285, 12335, 12386, 12437, 12487, 12538, 12588, |
| 96 | 12639, 12689, 12739, 12789, 12839, 12889, 12939, 12988, |
| 97 | 13038, 13088, 13137, 13187, 13236, 13285, 13334, 13383, |
| 98 | 13432, 13481, 13530, 13579, 13628, 13676, 13725, 13773, |
| 99 | 13822, 13870, 13918, 13967, 14015, 14063, 14111, 14159, |
| 100 | 14206, 14254, 14302, 14350, 14397, 14445, 14492, 14539, |
| 101 | 14587, 14634, 14681, 14728, 14775, 14822, 14869, 14916, |
| 102 | 14963, 15010, 15056, 15103, 15149, 15196, 15242, 15289, |
| 103 | 15335, 15381, 15427, 15474, 15520, 15566, 15612, 15657, |
| 104 | 15703, 15749, 15795, 15840, 15886, 15932, 15977, 16022, |
| 105 | 16068, 16113, 16158, 16204, 16249, 16294, 16339, 16384, |
| 106 | 16384, |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 107 | }; |
| 108 | /* clang-format on */ |
| 109 | |
chiyotsai | a6545dd | 2020-07-06 14:20:50 -0700 | [diff] [blame] | 110 | int av1_is_enough_erroradvantage(double best_erroradvantage, int params_cost) { |
| 111 | return best_erroradvantage < erroradv_tr && |
| 112 | best_erroradvantage * params_cost < erroradv_prod_tr; |
Debargha Mukherjee | e832d57 | 2017-04-07 14:40:43 -0700 | [diff] [blame] | 113 | } |
emilkeyder@google.com | 30ba4b4 | 2017-02-22 21:07:55 -0500 | [diff] [blame] | 114 | |
Alex Converse | 88b4e7d | 2017-04-20 12:33:28 -0700 | [diff] [blame] | 115 | static void convert_to_params(const double *params, int32_t *model) { |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 116 | int i; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 117 | model[0] = (int32_t)floor(params[0] * (1 << GM_TRANS_PREC_BITS) + 0.5); |
| 118 | model[1] = (int32_t)floor(params[1] * (1 << GM_TRANS_PREC_BITS) + 0.5); |
| 119 | model[0] = (int32_t)clamp(model[0], GM_TRANS_MIN, GM_TRANS_MAX) * |
| 120 | GM_TRANS_DECODE_FACTOR; |
| 121 | model[1] = (int32_t)clamp(model[1], GM_TRANS_MIN, GM_TRANS_MAX) * |
| 122 | GM_TRANS_DECODE_FACTOR; |
| 123 | |
| 124 | for (i = 2; i < 6; ++i) { |
| 125 | const int diag_value = ((i == 2 || i == 5) ? (1 << GM_ALPHA_PREC_BITS) : 0); |
| 126 | model[i] = (int32_t)floor(params[i] * (1 << GM_ALPHA_PREC_BITS) + 0.5); |
| 127 | model[i] = |
| 128 | (int32_t)clamp(model[i] - diag_value, GM_ALPHA_MIN, GM_ALPHA_MAX); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 129 | model[i] = (model[i] + diag_value) * GM_ALPHA_DECODE_FACTOR; |
| 130 | } |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 131 | } |
| 132 | |
sarahparker | c957b00 | 2018-11-02 16:15:22 -0700 | [diff] [blame] | 133 | void av1_convert_model_to_params(const double *params, |
| 134 | WarpedMotionParams *model) { |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 135 | convert_to_params(params, model->wmmat); |
Venkat | b18cdfc | 2018-12-17 12:36:17 +0530 | [diff] [blame] | 136 | model->wmtype = get_wmtype(model); |
Sebastien Alaiwan | 742f646 | 2018-01-10 15:12:30 +0100 | [diff] [blame] | 137 | model->invalid = 0; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | // Adds some offset to a global motion parameter and handles |
| 141 | // all of the necessary precision shifts, clamping, and |
| 142 | // zero-centering. |
Alex Converse | 88b4e7d | 2017-04-20 12:33:28 -0700 | [diff] [blame] | 143 | static int32_t add_param_offset(int param_index, int32_t param_value, |
| 144 | int32_t offset) { |
Rachel Barker | 0d9df42 | 2023-03-07 20:51:55 +0000 | [diff] [blame] | 145 | const int scale_vals[2] = { GM_TRANS_PREC_DIFF, GM_ALPHA_PREC_DIFF }; |
| 146 | const int clamp_vals[2] = { GM_TRANS_MAX, GM_ALPHA_MAX }; |
| 147 | // type of param: 0 - translation, 1 - affine |
| 148 | const int param_type = (param_index < 2 ? 0 : 1); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 149 | const int is_one_centered = (param_index == 2 || param_index == 5); |
| 150 | |
| 151 | // Make parameter zero-centered and offset the shift that was done to make |
| 152 | // it compatible with the warped model |
| 153 | param_value = (param_value - (is_one_centered << WARPEDMODEL_PREC_BITS)) >> |
| 154 | scale_vals[param_type]; |
| 155 | // Add desired offset to the rescaled/zero-centered parameter |
| 156 | param_value += offset; |
| 157 | // Clamp the parameter so it does not overflow the number of bits allotted |
| 158 | // to it in the bitstream |
| 159 | param_value = (int32_t)clamp(param_value, -clamp_vals[param_type], |
| 160 | clamp_vals[param_type]); |
| 161 | // Rescale the parameter to WARPEDMODEL_PRECISION_BITS so it is compatible |
| 162 | // with the warped motion library |
| 163 | param_value *= (1 << scale_vals[param_type]); |
| 164 | |
| 165 | // Undo the zero-centering step if necessary |
| 166 | return param_value + (is_one_centered << WARPEDMODEL_PREC_BITS); |
| 167 | } |
| 168 | |
Alex Converse | 88b4e7d | 2017-04-20 12:33:28 -0700 | [diff] [blame] | 169 | static void force_wmtype(WarpedMotionParams *wm, TransformationType wmtype) { |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 170 | switch (wmtype) { |
Sebastien Alaiwan | 5c99f4e | 2017-11-02 14:31:33 +0100 | [diff] [blame] | 171 | case IDENTITY: |
| 172 | wm->wmmat[0] = 0; |
| 173 | wm->wmmat[1] = 0; |
| 174 | AOM_FALLTHROUGH_INTENDED; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 175 | case TRANSLATION: |
| 176 | wm->wmmat[2] = 1 << WARPEDMODEL_PREC_BITS; |
| 177 | wm->wmmat[3] = 0; |
Sebastien Alaiwan | 5c99f4e | 2017-11-02 14:31:33 +0100 | [diff] [blame] | 178 | AOM_FALLTHROUGH_INTENDED; |
| 179 | case ROTZOOM: |
| 180 | wm->wmmat[4] = -wm->wmmat[3]; |
| 181 | wm->wmmat[5] = wm->wmmat[2]; |
| 182 | AOM_FALLTHROUGH_INTENDED; |
James Zern | 88879fa | 2021-12-02 12:25:37 -0800 | [diff] [blame] | 183 | case AFFINE: break; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 184 | default: assert(0); |
| 185 | } |
| 186 | wm->wmtype = wmtype; |
| 187 | } |
| 188 | |
Jerome Jiang | 7683ed5 | 2019-09-17 15:10:25 -0700 | [diff] [blame] | 189 | #if CONFIG_AV1_HIGHBITDEPTH |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 190 | static INLINE int generic_sad_highbd(const uint16_t *const ref, int ref_stride, |
| 191 | const uint16_t *const dst, int dst_stride, |
| 192 | int p_width, int p_height) { |
| 193 | // This function should only be called for patches smaller than |
| 194 | // WARP_ERROR_BLOCK x WARP_ERROR_BLOCK. This keeps the number of pixels |
| 195 | // small enough that we don't need a 64-bit accumulator |
| 196 | assert(p_width <= WARP_ERROR_BLOCK && p_height <= WARP_ERROR_BLOCK); |
| 197 | |
| 198 | int sad = 0; |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 199 | for (int i = 0; i < p_height; ++i) { |
| 200 | for (int j = 0; j < p_width; ++j) { |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 201 | sad += abs(dst[j + i * dst_stride] - ref[j + i * ref_stride]); |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 202 | } |
| 203 | } |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 204 | return sad; |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 205 | } |
| 206 | |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 207 | #if WARP_ERROR_BLOCK != 32 |
| 208 | #error "Need to change SAD call size in highbd_segmented_frame_error" |
| 209 | #endif // WARP_ERROR_BLOCK != 32 |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 210 | static int64_t highbd_segmented_frame_error( |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 211 | const uint16_t *const ref, int ref_stride, const uint16_t *const dst, |
| 212 | int dst_stride, int p_width, int p_height, int bd, uint8_t *segment_map, |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 213 | int segment_map_stride) { |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 214 | (void)bd; |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 215 | int patch_w, patch_h; |
| 216 | const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); |
| 217 | const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); |
| 218 | int64_t sum_error = 0; |
| 219 | for (int i = 0; i < p_height; i += WARP_ERROR_BLOCK) { |
| 220 | for (int j = 0; j < p_width; j += WARP_ERROR_BLOCK) { |
| 221 | int seg_x = j >> WARP_ERROR_BLOCK_LOG; |
| 222 | int seg_y = i >> WARP_ERROR_BLOCK_LOG; |
| 223 | // Only compute the error if this block contains inliers from the motion |
| 224 | // model |
| 225 | if (!segment_map[seg_y * segment_map_stride + seg_x]) continue; |
| 226 | |
| 227 | // avoid computing error into the frame padding |
| 228 | patch_w = AOMMIN(error_bsize_w, p_width - j); |
| 229 | patch_h = AOMMIN(error_bsize_h, p_height - i); |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 230 | |
| 231 | if (patch_w == WARP_ERROR_BLOCK && patch_h == WARP_ERROR_BLOCK) { |
| 232 | sum_error += aom_highbd_sad32x32( |
| 233 | CONVERT_TO_BYTEPTR(ref + j + i * ref_stride), ref_stride, |
| 234 | CONVERT_TO_BYTEPTR(dst + j + i * dst_stride), dst_stride); |
| 235 | } else { |
| 236 | sum_error += generic_sad_highbd(ref + j + i * ref_stride, ref_stride, |
| 237 | dst + j + i * dst_stride, dst_stride, |
| 238 | patch_w, patch_h); |
| 239 | } |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 240 | } |
| 241 | } |
| 242 | return sum_error; |
| 243 | } |
| 244 | |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 245 | #if WARP_ERROR_BLOCK != 32 |
| 246 | #error "Need to change SAD call size in highbd_warp_error" |
| 247 | #endif // WARP_ERROR_BLOCK != 32 |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 248 | static int64_t highbd_warp_error(WarpedMotionParams *wm, |
| 249 | const uint16_t *const ref, int ref_width, |
| 250 | int ref_height, int ref_stride, |
| 251 | const uint16_t *const dst, int dst_stride, |
| 252 | int p_col, int p_row, int p_width, |
| 253 | int p_height, int subsampling_x, |
| 254 | int subsampling_y, int bd, int64_t best_error, |
| 255 | uint8_t *segment_map, int segment_map_stride) { |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 256 | int64_t gm_sumerr = 0; |
| 257 | const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); |
| 258 | const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); |
Rachel Barker | ed77cff | 2023-08-31 21:27:29 +0000 | [diff] [blame] | 259 | DECLARE_ALIGNED(32, uint16_t, tmp[WARP_ERROR_BLOCK * WARP_ERROR_BLOCK]); |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 260 | |
| 261 | ConvolveParams conv_params = get_conv_params(0, 0, bd); |
| 262 | conv_params.use_dist_wtd_comp_avg = 0; |
| 263 | for (int i = p_row; i < p_row + p_height; i += WARP_ERROR_BLOCK) { |
| 264 | for (int j = p_col; j < p_col + p_width; j += WARP_ERROR_BLOCK) { |
| 265 | int seg_x = j >> WARP_ERROR_BLOCK_LOG; |
| 266 | int seg_y = i >> WARP_ERROR_BLOCK_LOG; |
| 267 | // Only compute the error if this block contains inliers from the motion |
| 268 | // model |
| 269 | if (!segment_map[seg_y * segment_map_stride + seg_x]) continue; |
| 270 | // avoid warping extra 8x8 blocks in the padded region of the frame |
| 271 | // when p_width and p_height are not multiples of WARP_ERROR_BLOCK |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 272 | const int warp_w = AOMMIN(error_bsize_w, p_col + ref_width - j); |
| 273 | const int warp_h = AOMMIN(error_bsize_h, p_row + ref_height - i); |
| 274 | highbd_warp_plane(wm, ref, ref_width, ref_height, ref_stride, tmp, j, i, |
| 275 | warp_w, warp_h, WARP_ERROR_BLOCK, subsampling_x, |
| 276 | subsampling_y, bd, &conv_params); |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 277 | |
| 278 | if (warp_w == WARP_ERROR_BLOCK && warp_h == WARP_ERROR_BLOCK) { |
| 279 | gm_sumerr += aom_highbd_sad32x32( |
| 280 | CONVERT_TO_BYTEPTR(tmp), WARP_ERROR_BLOCK, |
| 281 | CONVERT_TO_BYTEPTR(dst + j + i * dst_stride), dst_stride); |
| 282 | } else { |
| 283 | gm_sumerr += |
| 284 | generic_sad_highbd(tmp, WARP_ERROR_BLOCK, dst + j + i * dst_stride, |
| 285 | dst_stride, warp_w, warp_h); |
| 286 | } |
| 287 | |
Remya | 4871f42 | 2019-09-04 14:45:50 +0530 | [diff] [blame] | 288 | if (gm_sumerr > best_error) return INT64_MAX; |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 289 | } |
| 290 | } |
| 291 | return gm_sumerr; |
| 292 | } |
Jerome Jiang | 7683ed5 | 2019-09-17 15:10:25 -0700 | [diff] [blame] | 293 | #endif |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 294 | |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 295 | static INLINE int generic_sad(const uint8_t *const ref, int ref_stride, |
| 296 | const uint8_t *const dst, int dst_stride, |
| 297 | int p_width, int p_height) { |
| 298 | // This function should only be called for patches smaller than |
| 299 | // WARP_ERROR_BLOCK x WARP_ERROR_BLOCK. This keeps the number of pixels |
| 300 | // small enough that we don't need a 64-bit accumulator |
| 301 | assert(p_width <= WARP_ERROR_BLOCK && p_height <= WARP_ERROR_BLOCK); |
| 302 | |
| 303 | int sad = 0; |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 304 | for (int i = 0; i < p_height; ++i) { |
| 305 | for (int j = 0; j < p_width; ++j) { |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 306 | sad += abs(dst[j + i * dst_stride] - ref[j + i * ref_stride]); |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 307 | } |
| 308 | } |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 309 | return sad; |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 310 | } |
| 311 | |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 312 | #if WARP_ERROR_BLOCK != 32 |
| 313 | #error "Need to change SAD call size in segmented_warp_error" |
| 314 | #endif // WARP_ERROR_BLOCK != 32 |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 315 | static int64_t segmented_frame_error(const uint8_t *const ref, int ref_stride, |
| 316 | const uint8_t *const dst, int dst_stride, |
| 317 | int p_width, int p_height, |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 318 | uint8_t *segment_map, |
| 319 | int segment_map_stride) { |
| 320 | int patch_w, patch_h; |
| 321 | const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); |
| 322 | const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); |
| 323 | int64_t sum_error = 0; |
| 324 | for (int i = 0; i < p_height; i += WARP_ERROR_BLOCK) { |
| 325 | for (int j = 0; j < p_width; j += WARP_ERROR_BLOCK) { |
| 326 | int seg_x = j >> WARP_ERROR_BLOCK_LOG; |
| 327 | int seg_y = i >> WARP_ERROR_BLOCK_LOG; |
| 328 | // Only compute the error if this block contains inliers from the motion |
| 329 | // model |
| 330 | if (!segment_map[seg_y * segment_map_stride + seg_x]) continue; |
| 331 | |
| 332 | // avoid computing error into the frame padding |
| 333 | patch_w = AOMMIN(error_bsize_w, p_width - j); |
| 334 | patch_h = AOMMIN(error_bsize_h, p_height - i); |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 335 | |
| 336 | if (patch_w == WARP_ERROR_BLOCK && patch_h == WARP_ERROR_BLOCK) { |
| 337 | sum_error += aom_sad32x32(ref + j + i * ref_stride, ref_stride, |
| 338 | dst + j + i * dst_stride, dst_stride); |
| 339 | } else { |
| 340 | sum_error += |
| 341 | generic_sad(ref + j + i * ref_stride, ref_stride, |
| 342 | dst + j + i * dst_stride, dst_stride, patch_w, patch_h); |
| 343 | } |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 344 | } |
| 345 | } |
| 346 | return sum_error; |
| 347 | } |
| 348 | |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 349 | #if WARP_ERROR_BLOCK != 32 |
| 350 | #error "Need to change SAD call size in warp_error" |
| 351 | #endif // WARP_ERROR_BLOCK != 32 |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 352 | static int64_t warp_error(WarpedMotionParams *wm, const uint8_t *const ref, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 353 | int ref_width, int ref_height, int ref_stride, |
| 354 | const uint8_t *const dst, int dst_stride, int p_col, |
| 355 | int p_row, int p_width, int p_height, |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 356 | int subsampling_x, int subsampling_y, |
| 357 | int64_t best_error, uint8_t *segment_map, |
| 358 | int segment_map_stride) { |
| 359 | int64_t gm_sumerr = 0; |
| 360 | int warp_w, warp_h; |
| 361 | const int error_bsize_w = AOMMIN(p_width, WARP_ERROR_BLOCK); |
| 362 | const int error_bsize_h = AOMMIN(p_height, WARP_ERROR_BLOCK); |
| 363 | DECLARE_ALIGNED(16, uint8_t, tmp[WARP_ERROR_BLOCK * WARP_ERROR_BLOCK]); |
| 364 | ConvolveParams conv_params = get_conv_params(0, 0, 8); |
| 365 | conv_params.use_dist_wtd_comp_avg = 0; |
| 366 | |
| 367 | for (int i = p_row; i < p_row + p_height; i += WARP_ERROR_BLOCK) { |
| 368 | for (int j = p_col; j < p_col + p_width; j += WARP_ERROR_BLOCK) { |
| 369 | int seg_x = j >> WARP_ERROR_BLOCK_LOG; |
| 370 | int seg_y = i >> WARP_ERROR_BLOCK_LOG; |
| 371 | // Only compute the error if this block contains inliers from the motion |
| 372 | // model |
| 373 | if (!segment_map[seg_y * segment_map_stride + seg_x]) continue; |
| 374 | // avoid warping extra 8x8 blocks in the padded region of the frame |
| 375 | // when p_width and p_height are not multiples of WARP_ERROR_BLOCK |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 376 | warp_w = AOMMIN(error_bsize_w, p_col + ref_width - j); |
| 377 | warp_h = AOMMIN(error_bsize_h, p_row + ref_height - i); |
| 378 | warp_plane(wm, ref, ref_width, ref_height, ref_stride, tmp, j, i, warp_w, |
| 379 | warp_h, WARP_ERROR_BLOCK, subsampling_x, subsampling_y, |
| 380 | &conv_params); |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 381 | |
Rachel Barker | 33b6de7 | 2023-11-03 04:09:59 +0000 | [diff] [blame] | 382 | if (warp_w == WARP_ERROR_BLOCK && warp_h == WARP_ERROR_BLOCK) { |
| 383 | gm_sumerr += aom_sad32x32(tmp, WARP_ERROR_BLOCK, |
| 384 | dst + j + i * dst_stride, dst_stride); |
| 385 | } else { |
| 386 | gm_sumerr += |
| 387 | generic_sad(tmp, WARP_ERROR_BLOCK, dst + j + i * dst_stride, |
| 388 | dst_stride, warp_w, warp_h); |
| 389 | } |
| 390 | |
Remya | 4871f42 | 2019-09-04 14:45:50 +0530 | [diff] [blame] | 391 | if (gm_sumerr > best_error) return INT64_MAX; |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 392 | } |
| 393 | } |
| 394 | return gm_sumerr; |
| 395 | } |
| 396 | |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 397 | int64_t av1_segmented_frame_error(int use_hbd, int bd, const uint8_t *ref, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 398 | int ref_stride, uint8_t *dst, int dst_stride, |
| 399 | int p_width, int p_height, |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 400 | uint8_t *segment_map, |
| 401 | int segment_map_stride) { |
| 402 | #if CONFIG_AV1_HIGHBITDEPTH |
| 403 | if (use_hbd) { |
| 404 | return highbd_segmented_frame_error( |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 405 | CONVERT_TO_SHORTPTR(ref), ref_stride, CONVERT_TO_SHORTPTR(dst), |
| 406 | dst_stride, p_width, p_height, bd, segment_map, segment_map_stride); |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 407 | } |
| 408 | #endif |
| 409 | (void)use_hbd; |
| 410 | (void)bd; |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 411 | return segmented_frame_error(ref, ref_stride, dst, dst_stride, p_width, |
| 412 | p_height, segment_map, segment_map_stride); |
Rachel Barker | e59f411 | 2023-06-19 22:43:28 +0000 | [diff] [blame] | 413 | } |
| 414 | |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 415 | int64_t av1_warp_error(WarpedMotionParams *wm, int use_hbd, int bd, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 416 | const uint8_t *ref, int ref_width, int ref_height, |
| 417 | int ref_stride, uint8_t *dst, int dst_stride, int p_col, |
| 418 | int p_row, int p_width, int p_height, int subsampling_x, |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 419 | int subsampling_y, int64_t best_error, |
| 420 | uint8_t *segment_map, int segment_map_stride) { |
Rachel Barker | 0d9df42 | 2023-03-07 20:51:55 +0000 | [diff] [blame] | 421 | if (!av1_get_shear_params(wm)) return INT64_MAX; |
Jerome Jiang | 7683ed5 | 2019-09-17 15:10:25 -0700 | [diff] [blame] | 422 | #if CONFIG_AV1_HIGHBITDEPTH |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 423 | if (use_hbd) |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 424 | return highbd_warp_error(wm, CONVERT_TO_SHORTPTR(ref), ref_width, |
| 425 | ref_height, ref_stride, CONVERT_TO_SHORTPTR(dst), |
| 426 | dst_stride, p_col, p_row, p_width, p_height, |
| 427 | subsampling_x, subsampling_y, bd, best_error, |
| 428 | segment_map, segment_map_stride); |
Jerome Jiang | 7683ed5 | 2019-09-17 15:10:25 -0700 | [diff] [blame] | 429 | #endif |
| 430 | (void)use_hbd; |
| 431 | (void)bd; |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 432 | return warp_error(wm, ref, ref_width, ref_height, ref_stride, dst, dst_stride, |
| 433 | p_col, p_row, p_width, p_height, subsampling_x, |
| 434 | subsampling_y, best_error, segment_map, segment_map_stride); |
Remya | 3eb3fe7 | 2019-08-30 11:35:04 +0530 | [diff] [blame] | 435 | } |
| 436 | |
Sarah Parker | 36b997b | 2019-05-09 16:06:53 -0700 | [diff] [blame] | 437 | int64_t av1_refine_integerized_param( |
| 438 | WarpedMotionParams *wm, TransformationType wmtype, int use_hbd, int bd, |
| 439 | uint8_t *ref, int r_width, int r_height, int r_stride, uint8_t *dst, |
| 440 | int d_width, int d_height, int d_stride, int n_refinements, |
Rachel Barker | e4e784e | 2023-08-04 19:58:27 +0000 | [diff] [blame] | 441 | int64_t ref_frame_error, uint8_t *segment_map, int segment_map_stride) { |
Johann | b0ef6ff | 2018-02-08 14:32:21 -0800 | [diff] [blame] | 442 | static const int max_trans_model_params[TRANS_TYPES] = { 0, 2, 4, 6 }; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 443 | const int border = ERRORADV_BORDER; |
| 444 | int i = 0, p; |
Debargha Mukherjee | 5dfa930 | 2017-02-10 05:00:08 -0800 | [diff] [blame] | 445 | int n_params = max_trans_model_params[wmtype]; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 446 | int32_t *param_mat = wm->wmmat; |
emilkeyder@google.com | 6e3557c | 2017-03-27 10:52:53 -0400 | [diff] [blame] | 447 | int64_t step_error, best_error; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 448 | int32_t step; |
| 449 | int32_t *param; |
| 450 | int32_t curr_param; |
| 451 | int32_t best_param; |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 452 | |
| 453 | force_wmtype(wm, wmtype); |
Rachel Barker | e4e784e | 2023-08-04 19:58:27 +0000 | [diff] [blame] | 454 | wm->wmtype = get_wmtype(wm); |
| 455 | |
| 456 | if (n_refinements == 0) { |
| 457 | // Compute the maximum error value that will be accepted, so that |
| 458 | // av1_warp_error can terminate early if it proves the model will not |
| 459 | // be accepted. |
| 460 | int64_t selection_threshold = (int64_t)lrint(ref_frame_error * erroradv_tr); |
| 461 | return av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 462 | dst + border * d_stride + border, d_stride, border, |
| 463 | border, d_width - 2 * border, d_height - 2 * border, |
Rachel Barker | e4e784e | 2023-08-04 19:58:27 +0000 | [diff] [blame] | 464 | 0, 0, selection_threshold, segment_map, |
| 465 | segment_map_stride); |
| 466 | } |
| 467 | |
| 468 | // When refining, use a slightly higher threshold for the initial error |
| 469 | // calculation - see comment above erroradv_early_tr for why. |
| 470 | int64_t selection_threshold = |
| 471 | (int64_t)lrint(ref_frame_error * erroradv_early_tr); |
Sarah Parker | 36b997b | 2019-05-09 16:06:53 -0700 | [diff] [blame] | 472 | best_error = |
| 473 | av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 474 | dst + border * d_stride + border, d_stride, border, border, |
| 475 | d_width - 2 * border, d_height - 2 * border, 0, 0, |
| 476 | selection_threshold, segment_map, segment_map_stride); |
Rachel Barker | a5b228f | 2023-01-16 20:09:45 +0000 | [diff] [blame] | 477 | |
Rachel Barker | e4e784e | 2023-08-04 19:58:27 +0000 | [diff] [blame] | 478 | if (best_error > selection_threshold) { |
| 479 | return INT64_MAX; |
Rachel Barker | a5b228f | 2023-01-16 20:09:45 +0000 | [diff] [blame] | 480 | } |
| 481 | |
Sarah Parker | 3e85f67 | 2017-06-15 09:04:32 -0700 | [diff] [blame] | 482 | step = 1 << (n_refinements - 1); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 483 | for (i = 0; i < n_refinements; i++, step >>= 1) { |
| 484 | for (p = 0; p < n_params; ++p) { |
| 485 | int step_dir = 0; |
| 486 | param = param_mat + p; |
| 487 | curr_param = *param; |
| 488 | best_param = curr_param; |
| 489 | // look to the left |
Rachel Barker | ea38c7d | 2023-06-19 22:03:09 +0000 | [diff] [blame] | 490 | // Note: We have to use force_wmtype() to keep the proper symmetry for |
| 491 | // ROTZOOM type models |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 492 | *param = add_param_offset(p, curr_param, -step); |
Rachel Barker | ea38c7d | 2023-06-19 22:03:09 +0000 | [diff] [blame] | 493 | force_wmtype(wm, wmtype); |
Yaowu Xu | d3e7c68 | 2017-12-21 14:08:25 -0800 | [diff] [blame] | 494 | step_error = |
| 495 | av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 496 | dst + border * d_stride + border, d_stride, border, |
| 497 | border, d_width - 2 * border, d_height - 2 * border, 0, |
| 498 | 0, best_error, segment_map, segment_map_stride); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 499 | if (step_error < best_error) { |
| 500 | best_error = step_error; |
| 501 | best_param = *param; |
| 502 | step_dir = -1; |
| 503 | } |
| 504 | |
| 505 | // look to the right |
| 506 | *param = add_param_offset(p, curr_param, step); |
Rachel Barker | ea38c7d | 2023-06-19 22:03:09 +0000 | [diff] [blame] | 507 | force_wmtype(wm, wmtype); |
Yaowu Xu | d3e7c68 | 2017-12-21 14:08:25 -0800 | [diff] [blame] | 508 | step_error = |
| 509 | av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride, |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 510 | dst + border * d_stride + border, d_stride, border, |
| 511 | border, d_width - 2 * border, d_height - 2 * border, 0, |
| 512 | 0, best_error, segment_map, segment_map_stride); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 513 | if (step_error < best_error) { |
| 514 | best_error = step_error; |
| 515 | best_param = *param; |
| 516 | step_dir = 1; |
| 517 | } |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 518 | |
| 519 | // look to the direction chosen above repeatedly until error increases |
| 520 | // for the biggest step size |
| 521 | while (step_dir) { |
| 522 | *param = add_param_offset(p, best_param, step * step_dir); |
Rachel Barker | ea38c7d | 2023-06-19 22:03:09 +0000 | [diff] [blame] | 523 | force_wmtype(wm, wmtype); |
Rachel Barker | 867fb6a | 2023-08-07 19:04:22 +0000 | [diff] [blame] | 524 | step_error = |
| 525 | av1_warp_error(wm, use_hbd, bd, ref, r_width, r_height, r_stride, |
| 526 | dst + border * d_stride + border, d_stride, border, |
| 527 | border, d_width - 2 * border, d_height - 2 * border, |
| 528 | 0, 0, best_error, segment_map, segment_map_stride); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 529 | if (step_error < best_error) { |
| 530 | best_error = step_error; |
| 531 | best_param = *param; |
| 532 | } else { |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 533 | step_dir = 0; |
| 534 | } |
| 535 | } |
Rachel Barker | ea38c7d | 2023-06-19 22:03:09 +0000 | [diff] [blame] | 536 | |
| 537 | // Restore best parameter value so far |
| 538 | *param = best_param; |
| 539 | force_wmtype(wm, wmtype); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 540 | } |
| 541 | } |
Rachel Barker | ea38c7d | 2023-06-19 22:03:09 +0000 | [diff] [blame] | 542 | |
Venkat | b18cdfc | 2018-12-17 12:36:17 +0530 | [diff] [blame] | 543 | wm->wmtype = get_wmtype(wm); |
Sarah Parker | 6847860 | 2016-12-09 13:08:40 -0800 | [diff] [blame] | 544 | return best_error; |
| 545 | } |
| 546 | |
Sarah Parker | 36b997b | 2019-05-09 16:06:53 -0700 | [diff] [blame] | 547 | #define FEAT_COUNT_TR 3 |
Rachel Barker | b49c591 | 2023-02-22 16:46:45 +0000 | [diff] [blame] | 548 | #define SEG_COUNT_TR 48 |
Sarah Parker | 36b997b | 2019-05-09 16:06:53 -0700 | [diff] [blame] | 549 | void av1_compute_feature_segmentation_map(uint8_t *segment_map, int width, |
| 550 | int height, int *inliers, |
| 551 | int num_inliers) { |
| 552 | int seg_count = 0; |
| 553 | memset(segment_map, 0, sizeof(*segment_map) * width * height); |
| 554 | |
| 555 | for (int i = 0; i < num_inliers; i++) { |
| 556 | int x = inliers[i * 2]; |
| 557 | int y = inliers[i * 2 + 1]; |
| 558 | int seg_x = x >> WARP_ERROR_BLOCK_LOG; |
| 559 | int seg_y = y >> WARP_ERROR_BLOCK_LOG; |
| 560 | segment_map[seg_y * width + seg_x] += 1; |
| 561 | } |
| 562 | |
| 563 | for (int i = 0; i < height; i++) { |
| 564 | for (int j = 0; j < width; j++) { |
| 565 | uint8_t feat_count = segment_map[i * width + j]; |
| 566 | segment_map[i * width + j] = (feat_count >= FEAT_COUNT_TR); |
| 567 | seg_count += (segment_map[i * width + j]); |
| 568 | } |
| 569 | } |
| 570 | |
| 571 | // If this motion does not make up a large enough portion of the frame, |
| 572 | // use the unsegmented version of the error metric |
Rachel Barker | b49c591 | 2023-02-22 16:46:45 +0000 | [diff] [blame] | 573 | if (seg_count < SEG_COUNT_TR) |
Sarah Parker | 36b997b | 2019-05-09 16:06:53 -0700 | [diff] [blame] | 574 | memset(segment_map, 1, width * height * sizeof(*segment_map)); |
| 575 | } |