Coverage Report

Created: 2026-07-16 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/ext/aom/av1/encoder/hash_motion.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018, Alliance for Open Media. All rights reserved.
3
 *
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.
10
 */
11
12
#include <assert.h>
13
#include <stdbool.h>
14
15
#include "config/av1_rtcd.h"
16
17
#include "av1/encoder/block.h"
18
#include "av1/encoder/hash.h"
19
#include "av1/encoder/hash_motion.h"
20
21
2.38G
#define kSrcBits 16
22
// kMaxAddr is the number of hash table buckets in p_hash_table->p_lookup_table.
23
// p_hash_table->p_lookup_table consists of 6 hash tables of 1 << kSrcBits
24
// buckets each. Each of the 6 supported block sizes (4, 8, 16, 32, 64, 128) has
25
// its own hash table, indexed by the return value of
26
// hash_block_size_to_index().
27
2.38G
#define kMaxAddr (6 << kSrcBits)
28
36.8M
#define kMaxCandidatesPerHashBucket 256
29
30
static void get_pixels_in_1D_char_array_by_block_2x2(const uint8_t *y_src,
31
                                                     int stride,
32
372k
                                                     uint8_t *p_pixels_in1D) {
33
372k
  const uint8_t *p_pel = y_src;
34
372k
  int index = 0;
35
1.11M
  for (int i = 0; i < 2; i++) {
36
2.23M
    for (int j = 0; j < 2; j++) {
37
1.48M
      p_pixels_in1D[index++] = p_pel[j];
38
1.48M
    }
39
744k
    p_pel += stride;
40
744k
  }
41
372k
}
42
43
static void get_pixels_in_1D_short_array_by_block_2x2(const uint16_t *y_src,
44
                                                      int stride,
45
37.3M
                                                      uint16_t *p_pixels_in1D) {
46
37.3M
  const uint16_t *p_pel = y_src;
47
37.3M
  int index = 0;
48
112M
  for (int i = 0; i < 2; i++) {
49
224M
    for (int j = 0; j < 2; j++) {
50
149M
      p_pixels_in1D[index++] = p_pel[j];
51
149M
    }
52
74.7M
    p_pel += stride;
53
74.7M
  }
54
37.3M
}
55
56
// the hash value (hash_value1) consists of two parts, the first 3 bits relate
57
// to the block size and the remaining 16 bits are the crc values. This
58
// function is used to get the first 3 bits.
59
1.37M
static int hash_block_size_to_index(int block_size) {
60
1.37M
  switch (block_size) {
61
880k
    case 4: return 0;
62
498k
    case 8: return 1;
63
0
    case 16: return 2;
64
0
    case 32: return 3;
65
0
    case 64: return 4;
66
0
    case 128: return 5;
67
0
    default: return -1;
68
1.37M
  }
69
1.37M
}
70
71
static uint32_t get_identity_hash_value(const uint8_t a, const uint8_t b,
72
372k
                                        const uint8_t c, const uint8_t d) {
73
  // The four input values add up to 32 bits, which is the size of the output.
74
  // Just pack those values as is.
75
372k
  return ((uint32_t)a << 24) + ((uint32_t)b << 16) + ((uint32_t)c << 8) +
76
372k
         ((uint32_t)d);
77
372k
}
78
79
static uint32_t get_xor_hash_value_hbd(const uint16_t a, const uint16_t b,
80
37.3M
                                       const uint16_t c, const uint16_t d) {
81
37.3M
  uint32_t result;
82
  // Pack the lower 8 bits of each input value to the 32 bit output, then xor
83
  // with the upper 8 bits of each input value.
84
37.3M
  result = ((uint32_t)(a & 0x00ff) << 24) + ((uint32_t)(b & 0x00ff) << 16) +
85
37.3M
           ((uint32_t)(c & 0x00ff) << 8) + ((uint32_t)(d & 0x00ff));
86
37.3M
  result ^= ((uint32_t)(a & 0xff00) << 16) + ((uint32_t)(b & 0xff00) << 8) +
87
37.3M
            ((uint32_t)(c & 0xff00)) + ((uint32_t)(d & 0xff00) >> 8);
88
37.3M
  return result;
89
37.3M
}
90
91
6.06k
void av1_hash_table_init(IntraBCHashInfo *intrabc_hash_info) {
92
6.06k
  if (!intrabc_hash_info->crc_initialized) {
93
6.06k
    av1_crc32c_calculator_init(&intrabc_hash_info->crc_calculator);
94
6.06k
    intrabc_hash_info->crc_initialized = 1;
95
6.06k
  }
96
6.06k
  intrabc_hash_info->intrabc_hash_table.p_lookup_table = NULL;
97
6.06k
}
98
99
104k
static void clear_all(hash_table *p_hash_table) {
100
104k
  if (p_hash_table->p_lookup_table == NULL) {
101
98.2k
    return;
102
98.2k
  }
103
2.38G
  for (int i = 0; i < kMaxAddr; i++) {
104
2.38G
    if (p_hash_table->p_lookup_table[i] != NULL) {
105
32.2M
      aom_vector_destroy(p_hash_table->p_lookup_table[i]);
106
32.2M
      aom_free(p_hash_table->p_lookup_table[i]);
107
32.2M
      p_hash_table->p_lookup_table[i] = NULL;
108
32.2M
    }
109
2.38G
  }
110
6.06k
}
111
112
104k
void av1_hash_table_destroy(hash_table *p_hash_table) {
113
104k
  clear_all(p_hash_table);
114
104k
  aom_free(p_hash_table->p_lookup_table);
115
104k
  p_hash_table->p_lookup_table = NULL;
116
104k
}
117
118
6.06k
bool av1_hash_table_create(hash_table *p_hash_table) {
119
6.06k
  if (p_hash_table->p_lookup_table != NULL) {
120
0
    clear_all(p_hash_table);
121
0
    return true;
122
0
  }
123
6.06k
  p_hash_table->p_lookup_table =
124
6.06k
      (Vector **)aom_calloc(kMaxAddr, sizeof(p_hash_table->p_lookup_table[0]));
125
6.06k
  if (!p_hash_table->p_lookup_table) return false;
126
6.06k
  return true;
127
6.06k
}
128
129
static bool hash_table_add_to_table(hash_table *p_hash_table,
130
                                    uint32_t hash_value,
131
36.8M
                                    const block_hash *curr_block_hash) {
132
36.8M
  if (p_hash_table->p_lookup_table[hash_value] == NULL) {
133
32.2M
    p_hash_table->p_lookup_table[hash_value] =
134
32.2M
        aom_malloc(sizeof(*p_hash_table->p_lookup_table[hash_value]));
135
32.2M
    if (p_hash_table->p_lookup_table[hash_value] == NULL) {
136
0
      return false;
137
0
    }
138
32.2M
    if (aom_vector_setup(p_hash_table->p_lookup_table[hash_value], 10,
139
32.2M
                         sizeof(*curr_block_hash)) == VECTOR_ERROR)
140
0
      return false;
141
32.2M
  }
142
  // Place an upper bound each hash table bucket to up to 256 intrabc
143
  // block candidates, and ignore subsequent ones. Considering more can
144
  // unnecessarily slow down encoding for virtually no efficiency gain.
145
36.8M
  if (aom_vector_byte_size(p_hash_table->p_lookup_table[hash_value]) <
146
36.8M
      kMaxCandidatesPerHashBucket * sizeof(*curr_block_hash)) {
147
36.8M
    if (aom_vector_push_back(p_hash_table->p_lookup_table[hash_value],
148
36.8M
                             (void *)curr_block_hash) == VECTOR_ERROR)
149
0
      return false;
150
36.8M
  }
151
36.8M
  return true;
152
36.8M
}
153
154
int32_t av1_hash_table_count(const hash_table *p_hash_table,
155
1.36M
                             uint32_t hash_value) {
156
1.36M
  if (p_hash_table->p_lookup_table[hash_value] == NULL) {
157
339k
    return 0;
158
1.02M
  } else {
159
1.02M
    return (int32_t)(p_hash_table->p_lookup_table[hash_value]->size);
160
1.02M
  }
161
1.36M
}
162
163
Iterator av1_hash_get_first_iterator(hash_table *p_hash_table,
164
183k
                                     uint32_t hash_value) {
165
183k
  assert(av1_hash_table_count(p_hash_table, hash_value) > 0);
166
183k
  return aom_vector_begin(p_hash_table->p_lookup_table[hash_value]);
167
183k
}
168
169
void av1_generate_block_2x2_hash_value(const YV12_BUFFER_CONFIG *picture,
170
6.06k
                                       uint32_t *pic_block_hash) {
171
6.06k
  const int width = 2;
172
6.06k
  const int height = 2;
173
6.06k
  const int x_end = picture->y_crop_width - width + 1;
174
6.06k
  const int y_end = picture->y_crop_height - height + 1;
175
176
6.06k
  if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
177
5.83k
    uint16_t p[4];
178
5.83k
    int pos = 0;
179
499k
    for (int y_pos = 0; y_pos < y_end; y_pos++) {
180
26.6M
      for (int x_pos = 0; x_pos < x_end; x_pos++) {
181
26.1M
        get_pixels_in_1D_short_array_by_block_2x2(
182
26.1M
            CONVERT_TO_SHORTPTR(picture->y_buffer) + y_pos * picture->y_stride +
183
26.1M
                x_pos,
184
26.1M
            picture->y_stride, p);
185
        // For HBD, we either have 40 or 48 bits of input data that the xor hash
186
        // reduce to 32 bits. We intentionally don't want to "discard" bits to
187
        // avoid any kind of biasing.
188
26.1M
        pic_block_hash[pos] = get_xor_hash_value_hbd(p[0], p[1], p[2], p[3]);
189
26.1M
        pos++;
190
26.1M
      }
191
493k
      pos += width - 1;
192
493k
    }
193
5.83k
  } else {
194
227
    uint8_t p[4];
195
227
    int pos = 0;
196
24.5k
    for (int y_pos = 0; y_pos < y_end; y_pos++) {
197
242k
      for (int x_pos = 0; x_pos < x_end; x_pos++) {
198
218k
        get_pixels_in_1D_char_array_by_block_2x2(
199
218k
            picture->y_buffer + y_pos * picture->y_stride + x_pos,
200
218k
            picture->y_stride, p);
201
        // This 2x2 hash isn't used directly as a "key" for the hash table, so
202
        // we can afford to just copy the 4 8-bit pixel values as a single
203
        // 32-bit value directly. (i.e. there are no concerns of a lack of
204
        // uniform distribution)
205
218k
        pic_block_hash[pos] = get_identity_hash_value(p[0], p[1], p[2], p[3]);
206
218k
        pos++;
207
218k
      }
208
24.2k
      pos += width - 1;
209
24.2k
    }
210
227
  }
211
6.06k
}
212
213
void av1_generate_block_hash_value(IntraBCHashInfo *intrabc_hash_info,
214
                                   const YV12_BUFFER_CONFIG *picture,
215
                                   int block_size,
216
                                   const uint32_t *src_pic_block_hash,
217
12.1k
                                   uint32_t *dst_pic_block_hash) {
218
12.1k
  CRC32C *calc = &intrabc_hash_info->crc_calculator;
219
220
12.1k
  const int pic_width = picture->y_crop_width;
221
12.1k
  const int x_end = picture->y_crop_width - block_size + 1;
222
12.1k
  const int y_end = picture->y_crop_height - block_size + 1;
223
12.1k
  const int src_size = block_size >> 1;
224
225
12.1k
  uint32_t p[4];
226
12.1k
  const int length = sizeof(p);
227
228
12.1k
  int pos = 0;
229
998k
  for (int y_pos = 0; y_pos < y_end; y_pos++) {
230
44.4M
    for (int x_pos = 0; x_pos < x_end; x_pos++) {
231
      // Build up a bigger block from 4 smaller, non-overlapping source block
232
      // hashes, and compute its hash. Note: source blocks at the right and
233
      // bottom borders cannot be part of larger blocks, therefore they won't be
234
      // considered into the block hash value generation process.
235
43.4M
      p[0] = src_pic_block_hash[pos];
236
43.4M
      p[1] = src_pic_block_hash[pos + src_size];
237
43.4M
      p[2] = src_pic_block_hash[pos + src_size * pic_width];
238
43.4M
      p[3] = src_pic_block_hash[pos + src_size * pic_width + src_size];
239
      // TODO: bug aomedia:433531610 - serialize input values in a way that's
240
      // independent of the computer architecture's endianness
241
43.4M
      dst_pic_block_hash[pos] =
242
43.4M
          av1_get_crc32c_value(calc, (uint8_t *)p, length);
243
43.4M
      pos++;
244
43.4M
    }
245
986k
    pos += block_size - 1;
246
986k
  }
247
12.1k
}
248
249
bool av1_add_to_hash_map_by_row_with_precal_data(hash_table *p_hash_table,
250
                                                 const uint32_t *pic_hash,
251
                                                 int pic_width, int pic_height,
252
10.6k
                                                 int block_size) {
253
10.6k
  const int x_end = pic_width - block_size + 1;
254
10.6k
  const int y_end = pic_height - block_size + 1;
255
256
10.6k
  int add_value = hash_block_size_to_index(block_size);
257
10.6k
  assert(add_value >= 0);
258
10.6k
  add_value <<= kSrcBits;
259
10.6k
  const int crc_mask = (1 << kSrcBits) - 1;
260
10.6k
  int step = block_size;
261
10.6k
  int x_offset = 0;
262
10.6k
  int y_offset = 0;
263
264
  // Explore the entire frame hierarchically to add intrabc candidate blocks to
265
  // the hash table, by starting with coarser steps (the block size), towards
266
  // finer-grained steps until every candidate block has been considered.
267
  // The nested for loop goes through the pic_hash array column by column.
268
269
  // Doing a hierarchical block exploration helps maximize spatial dispersion
270
  // of the first and foremost candidate blocks while minimizing overlap between
271
  // them. This is helpful because we only keep up to 256 entries of the
272
  // same candidate block (located in different places), so we want those
273
  // entries to cover the biggest area of the image to encode to maximize coding
274
  // efficiency.
275
276
  // This is the coordinate exploration order example for an 8x8 region, with
277
  // block_size = 4. The top-left corner (x, y) coordinates of each candidate
278
  // block are shown below. There are 5 * 5 (25) candidate blocks.
279
  //    x  0  1  2  3  4  5  6  7
280
  //  y +------------------------
281
  //  0 |  1 10  5 13  3
282
  //  1 | 16 22 18 24 20
283
  //  2 |  7 11  9 14  8
284
  //  3 | 17 23 19 25 21
285
  //  4 |  2 12  6 15  4--------+
286
  //  5 |              | 4 x 4  |
287
  //  6 |              | block  |
288
  //  7 |              +--------+
289
290
  // Please note that due to the way block exploration works, the smallest step
291
  // used is 2 (i.e. no two adjacent blocks will be explored consecutively).
292
  // Also, the exploration is designed to visit each block candidate only once.
293
103k
  while (step > 1) {
294
3.08M
    for (int x_pos = x_offset; x_pos < x_end; x_pos += step) {
295
39.8M
      for (int y_pos = y_offset; y_pos < y_end; y_pos += step) {
296
36.8M
        const int pos = y_pos * pic_width + x_pos;
297
36.8M
        block_hash curr_block_hash;
298
299
36.8M
        curr_block_hash.x = x_pos;
300
36.8M
        curr_block_hash.y = y_pos;
301
302
36.8M
        const uint32_t hash_value1 = (pic_hash[pos] & crc_mask) + add_value;
303
36.8M
        curr_block_hash.hash_value2 = pic_hash[pos];
304
305
36.8M
        if (!hash_table_add_to_table(p_hash_table, hash_value1,
306
36.8M
                                     &curr_block_hash)) {
307
0
          return false;
308
0
        }
309
36.8M
      }
310
2.98M
    }
311
312
    // Adjust offsets and step sizes with this state machine.
313
    // State 0 is needed because no blocks in pic_hash have been explored,
314
    // so exploration requires a way to account for blocks with both zero
315
    // x_offset and zero y_offset.
316
    // State 0 is always meant to be executed first, but the relative order of
317
    // states 1, 2 and 3 can be arbitrary, as long as no two adjacent blocks
318
    // are explored consecutively.
319
92.6k
    if (x_offset == 0 && y_offset == 0) {
320
      // State 0 -> State 1: special case
321
      // This state transition will only execute when step == block_size
322
10.6k
      x_offset = step / 2;
323
82.0k
    } else if (x_offset == step / 2 && y_offset == 0) {
324
      // State 1 -> State 2
325
27.3k
      x_offset = 0;
326
27.3k
      y_offset = step / 2;
327
54.6k
    } else if (x_offset == 0 && y_offset == step / 2) {
328
      // State 2 -> State 3
329
27.3k
      x_offset = step / 2;
330
27.3k
    } else {
331
27.3k
      assert(x_offset == step / 2 && y_offset == step / 2);
332
      // State 3 -> State 1: We've fully explored all the coordinates for the
333
      // current step size, continue by halving the step size
334
27.3k
      step /= 2;
335
27.3k
      x_offset = step / 2;
336
27.3k
      y_offset = 0;
337
27.3k
    }
338
92.6k
  }
339
340
10.6k
  return true;
341
10.6k
}
342
343
int av1_hash_is_horizontal_perfect(const YV12_BUFFER_CONFIG *picture,
344
0
                                   int block_size, int x_start, int y_start) {
345
0
  const int stride = picture->y_stride;
346
0
  const uint8_t *p = picture->y_buffer + y_start * stride + x_start;
347
348
0
  if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
349
0
    const uint16_t *p16 = CONVERT_TO_SHORTPTR(p);
350
0
    for (int i = 0; i < block_size; i++) {
351
0
      for (int j = 1; j < block_size; j++) {
352
0
        if (p16[j] != p16[0]) {
353
0
          return 0;
354
0
        }
355
0
      }
356
0
      p16 += stride;
357
0
    }
358
0
  } else {
359
0
    for (int i = 0; i < block_size; i++) {
360
0
      for (int j = 1; j < block_size; j++) {
361
0
        if (p[j] != p[0]) {
362
0
          return 0;
363
0
        }
364
0
      }
365
0
      p += stride;
366
0
    }
367
0
  }
368
369
0
  return 1;
370
0
}
371
372
int av1_hash_is_vertical_perfect(const YV12_BUFFER_CONFIG *picture,
373
0
                                 int block_size, int x_start, int y_start) {
374
0
  const int stride = picture->y_stride;
375
0
  const uint8_t *p = picture->y_buffer + y_start * stride + x_start;
376
377
0
  if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
378
0
    const uint16_t *p16 = CONVERT_TO_SHORTPTR(p);
379
0
    for (int i = 0; i < block_size; i++) {
380
0
      for (int j = 1; j < block_size; j++) {
381
0
        if (p16[j * stride + i] != p16[i]) {
382
0
          return 0;
383
0
        }
384
0
      }
385
0
    }
386
0
  } else {
387
0
    for (int i = 0; i < block_size; i++) {
388
0
      for (int j = 1; j < block_size; j++) {
389
0
        if (p[j * stride + i] != p[i]) {
390
0
          return 0;
391
0
        }
392
0
      }
393
0
    }
394
0
  }
395
0
  return 1;
396
0
}
397
398
void av1_get_block_hash_value(IntraBCHashInfo *intra_bc_hash_info,
399
                              const uint8_t *y_src, int stride, int block_size,
400
                              uint32_t *hash_value1, uint32_t *hash_value2,
401
1.36M
                              int use_highbitdepth) {
402
1.36M
  int add_value = hash_block_size_to_index(block_size);
403
1.36M
  assert(add_value >= 0);
404
1.36M
  add_value <<= kSrcBits;
405
1.36M
  const int crc_mask = (1 << kSrcBits) - 1;
406
407
1.36M
  CRC32C *calc = &intra_bc_hash_info->crc_calculator;
408
1.36M
  uint32_t **buf = intra_bc_hash_info->hash_value_buffer;
409
410
  // 2x2 subblock hash values in current CU
411
1.36M
  int sub_block_in_width = (block_size >> 1);
412
1.36M
  if (use_highbitdepth) {
413
1.34M
    uint16_t pixel_to_hash[4];
414
1.34M
    uint16_t *y16_src = CONVERT_TO_SHORTPTR(y_src);
415
5.01M
    for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
416
14.8M
      for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
417
11.2M
        int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
418
11.2M
        get_pixels_in_1D_short_array_by_block_2x2(
419
11.2M
            y16_src + y_pos * stride + x_pos, stride, pixel_to_hash);
420
11.2M
        assert(pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
421
        // For HBD, we either have 40 or 48 bits of input data that the xor hash
422
        // reduce to 32 bits. We intentionally don't want to "discard" bits to
423
        // avoid any kind of biasing.
424
11.2M
        buf[0][pos] =
425
11.2M
            get_xor_hash_value_hbd(pixel_to_hash[0], pixel_to_hash[1],
426
11.2M
                                   pixel_to_hash[2], pixel_to_hash[3]);
427
11.2M
      }
428
3.66M
    }
429
1.34M
  } else {
430
20.0k
    uint8_t pixel_to_hash[4];
431
72.2k
    for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
432
205k
      for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
433
153k
        int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
434
153k
        get_pixels_in_1D_char_array_by_block_2x2(y_src + y_pos * stride + x_pos,
435
153k
                                                 stride, pixel_to_hash);
436
153k
        assert(pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
437
        // This 2x2 hash isn't used directly as a "key" for the hash table, so
438
        // we can afford to just copy the 4 8-bit pixel values as a single
439
        // 32-bit value directly. (i.e. there are no concerns of a lack of
440
        // uniform distribution)
441
153k
        buf[0][pos] =
442
153k
            get_identity_hash_value(pixel_to_hash[0], pixel_to_hash[1],
443
153k
                                    pixel_to_hash[2], pixel_to_hash[3]);
444
153k
      }
445
52.2k
    }
446
20.0k
  }
447
448
1.36M
  int src_sub_block_in_width = sub_block_in_width;
449
1.36M
  sub_block_in_width >>= 1;
450
451
1.36M
  int src_idx = 0;
452
1.36M
  int dst_idx = !src_idx;
453
454
  // 4x4 subblock hash values to current block hash values
455
1.36M
  uint32_t to_hash[4];
456
3.22M
  for (int sub_width = 4; sub_width <= block_size;
457
1.86M
       sub_width *= 2, src_idx = !src_idx) {
458
1.86M
    dst_idx = !src_idx;
459
460
1.86M
    int dst_pos = 0;
461
4.21M
    for (int y_pos = 0; y_pos < sub_block_in_width; y_pos++) {
462
5.69M
      for (int x_pos = 0; x_pos < sub_block_in_width; x_pos++) {
463
3.33M
        int srcPos = (y_pos << 1) * src_sub_block_in_width + (x_pos << 1);
464
465
3.33M
        assert(srcPos + 1 < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
466
3.33M
        assert(srcPos + src_sub_block_in_width + 1 <
467
3.33M
               AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
468
3.33M
        assert(dst_pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
469
470
3.33M
        to_hash[0] = buf[src_idx][srcPos];
471
3.33M
        to_hash[1] = buf[src_idx][srcPos + 1];
472
3.33M
        to_hash[2] = buf[src_idx][srcPos + src_sub_block_in_width];
473
3.33M
        to_hash[3] = buf[src_idx][srcPos + src_sub_block_in_width + 1];
474
475
        // TODO: bug aomedia:433531610 - serialize input values in a way that's
476
        // independent of the computer architecture's endianness
477
3.33M
        buf[dst_idx][dst_pos] =
478
3.33M
            av1_get_crc32c_value(calc, (uint8_t *)to_hash, sizeof(to_hash));
479
3.33M
        dst_pos++;
480
3.33M
      }
481
2.35M
    }
482
483
1.86M
    src_sub_block_in_width = sub_block_in_width;
484
1.86M
    sub_block_in_width >>= 1;
485
1.86M
  }
486
487
1.36M
  *hash_value1 = (buf[dst_idx][0] & crc_mask) + add_value;
488
1.36M
  *hash_value2 = buf[dst_idx][0];
489
1.36M
}