Coverage Report

Created: 2025-10-10 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/ext/aom/av1/encoder/context_tree.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2016, 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 "av1/encoder/context_tree.h"
13
#include "av1/encoder/encoder.h"
14
#include "av1/encoder/rd.h"
15
#include <assert.h>
16
17
void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
18
0
                           PICK_MODE_CONTEXT *src_ctx) {
19
0
  dst_ctx->mic = src_ctx->mic;
20
0
  dst_ctx->mbmi_ext_best = src_ctx->mbmi_ext_best;
21
22
0
  dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk;
23
0
  dst_ctx->skippable = src_ctx->skippable;
24
#if CONFIG_INTERNAL_STATS
25
  dst_ctx->best_mode_index = src_ctx->best_mode_index;
26
#endif  // CONFIG_INTERNAL_STATS
27
28
0
  memcpy(dst_ctx->blk_skip, src_ctx->blk_skip,
29
0
         sizeof(uint8_t) * src_ctx->num_4x4_blk);
30
0
  av1_copy_array(dst_ctx->tx_type_map, src_ctx->tx_type_map,
31
0
                 src_ctx->num_4x4_blk);
32
33
0
  dst_ctx->rd_stats = src_ctx->rd_stats;
34
0
  dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
35
0
}
36
37
void av1_setup_shared_coeff_buffer(const SequenceHeader *const seq_params,
38
                                   PC_TREE_SHARED_BUFFERS *shared_bufs,
39
561k
                                   struct aom_internal_error_info *error) {
40
561k
  const int num_planes = seq_params->monochrome ? 1 : MAX_MB_PLANE;
41
561k
  const int max_sb_square_y = 1 << num_pels_log2_lookup[seq_params->sb_size];
42
561k
  const int max_sb_square_uv = max_sb_square_y >> (seq_params->subsampling_x +
43
561k
                                                   seq_params->subsampling_y);
44
1.52M
  for (int i = 0; i < num_planes; i++) {
45
960k
    const int max_num_pix =
46
960k
        (i == AOM_PLANE_Y) ? max_sb_square_y : max_sb_square_uv;
47
960k
    AOM_CHECK_MEM_ERROR(error, shared_bufs->coeff_buf[i],
48
960k
                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
49
960k
    AOM_CHECK_MEM_ERROR(error, shared_bufs->qcoeff_buf[i],
50
960k
                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
51
960k
    AOM_CHECK_MEM_ERROR(error, shared_bufs->dqcoeff_buf[i],
52
960k
                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
53
960k
  }
54
561k
}
55
56
561k
void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs) {
57
2.24M
  for (int i = 0; i < 3; i++) {
58
1.68M
    aom_free(shared_bufs->coeff_buf[i]);
59
1.68M
    aom_free(shared_bufs->qcoeff_buf[i]);
60
1.68M
    aom_free(shared_bufs->dqcoeff_buf[i]);
61
1.68M
    shared_bufs->coeff_buf[i] = NULL;
62
1.68M
    shared_bufs->qcoeff_buf[i] = NULL;
63
1.68M
    shared_bufs->dqcoeff_buf[i] = NULL;
64
1.68M
  }
65
561k
}
66
67
PICK_MODE_CONTEXT *av1_alloc_pmc(const struct AV1_COMP *const cpi,
68
                                 BLOCK_SIZE bsize,
69
11.8M
                                 PC_TREE_SHARED_BUFFERS *shared_bufs) {
70
11.8M
  PICK_MODE_CONTEXT *volatile ctx = NULL;
71
11.8M
  const AV1_COMMON *const cm = &cpi->common;
72
11.8M
  struct aom_internal_error_info error;
73
74
11.8M
  if (setjmp(error.jmp)) {
75
0
    av1_free_pmc(ctx, av1_num_planes(cm));
76
0
    return NULL;
77
0
  }
78
11.8M
  error.setjmp = 1;
79
80
11.8M
  AOM_CHECK_MEM_ERROR(&error, ctx, aom_calloc(1, sizeof(*ctx)));
81
11.8M
  ctx->rd_mode_is_ready = 0;
82
83
11.8M
  const int num_planes = av1_num_planes(cm);
84
11.8M
  const int num_pix = block_size_wide[bsize] * block_size_high[bsize];
85
11.8M
  const int num_blk = num_pix / 16;
86
87
11.8M
  AOM_CHECK_MEM_ERROR(&error, ctx->blk_skip,
88
11.8M
                      aom_calloc(num_blk, sizeof(*ctx->blk_skip)));
89
11.8M
  AOM_CHECK_MEM_ERROR(&error, ctx->tx_type_map,
90
11.8M
                      aom_calloc(num_blk, sizeof(*ctx->tx_type_map)));
91
11.8M
  ctx->num_4x4_blk = num_blk;
92
93
33.1M
  for (int i = 0; i < num_planes; ++i) {
94
21.2M
    ctx->coeff[i] = shared_bufs->coeff_buf[i];
95
21.2M
    ctx->qcoeff[i] = shared_bufs->qcoeff_buf[i];
96
21.2M
    ctx->dqcoeff[i] = shared_bufs->dqcoeff_buf[i];
97
21.2M
    AOM_CHECK_MEM_ERROR(&error, ctx->eobs[i],
98
21.2M
                        aom_memalign(32, num_blk * sizeof(*ctx->eobs[i])));
99
21.2M
    AOM_CHECK_MEM_ERROR(
100
21.2M
        &error, ctx->txb_entropy_ctx[i],
101
21.2M
        aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i])));
102
21.2M
  }
103
104
11.8M
  if (num_pix <= MAX_PALETTE_SQUARE) {
105
35.6M
    for (int i = 0; i < 2; ++i) {
106
23.7M
      if (cm->features.allow_screen_content_tools) {
107
0
        AOM_CHECK_MEM_ERROR(
108
0
            &error, ctx->color_index_map[i],
109
0
            aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
110
23.7M
      } else {
111
23.7M
        ctx->color_index_map[i] = NULL;
112
23.7M
      }
113
23.7M
    }
114
11.8M
  }
115
116
11.8M
  av1_invalid_rd_stats(&ctx->rd_stats);
117
118
11.8M
  return ctx;
119
11.8M
}
120
121
1.20M
void av1_reset_pmc(PICK_MODE_CONTEXT *ctx) {
122
1.20M
  av1_zero_array(ctx->blk_skip, ctx->num_4x4_blk);
123
1.20M
  av1_zero_array(ctx->tx_type_map, ctx->num_4x4_blk);
124
1.20M
  av1_invalid_rd_stats(&ctx->rd_stats);
125
1.20M
}
126
127
508M
void av1_free_pmc(PICK_MODE_CONTEXT *ctx, int num_planes) {
128
508M
  if (ctx == NULL) return;
129
130
11.7M
  aom_free(ctx->blk_skip);
131
11.7M
  ctx->blk_skip = NULL;
132
11.7M
  aom_free(ctx->tx_type_map);
133
33.0M
  for (int i = 0; i < num_planes; ++i) {
134
21.2M
    ctx->coeff[i] = NULL;
135
21.2M
    ctx->qcoeff[i] = NULL;
136
21.2M
    ctx->dqcoeff[i] = NULL;
137
21.2M
    aom_free(ctx->eobs[i]);
138
21.2M
    ctx->eobs[i] = NULL;
139
21.2M
    aom_free(ctx->txb_entropy_ctx[i]);
140
21.2M
    ctx->txb_entropy_ctx[i] = NULL;
141
21.2M
  }
142
143
35.5M
  for (int i = 0; i < 2; ++i) {
144
23.7M
    if (ctx->color_index_map[i]) {
145
0
      aom_free(ctx->color_index_map[i]);
146
0
      ctx->color_index_map[i] = NULL;
147
0
    }
148
23.7M
  }
149
150
11.7M
  aom_free(ctx);
151
11.7M
}
152
153
18.4M
PC_TREE *av1_alloc_pc_tree_node(BLOCK_SIZE bsize) {
154
18.4M
  PC_TREE *pc_tree = aom_calloc(1, sizeof(*pc_tree));
155
18.4M
  if (pc_tree == NULL) return NULL;
156
157
18.4M
  pc_tree->partitioning = PARTITION_NONE;
158
18.4M
  pc_tree->block_size = bsize;
159
160
18.4M
  return pc_tree;
161
18.4M
}
162
163
#define FREE_PMC_NODE(CTX)         \
164
508M
  do {                             \
165
508M
    av1_free_pmc(CTX, num_planes); \
166
508M
    CTX = NULL;                    \
167
508M
  } while (0)
168
169
void av1_free_pc_tree_recursive(PC_TREE *pc_tree, int num_planes, int keep_best,
170
                                int keep_none,
171
27.5M
                                PARTITION_SEARCH_TYPE partition_search_type) {
172
27.5M
  if (pc_tree == NULL) return;
173
174
  // Avoid freeing of extended partitions as they are not supported when
175
  // partition_search_type is VAR_BASED_PARTITION.
176
26.8M
  if (partition_search_type == VAR_BASED_PARTITION && !keep_best &&
177
7.73M
      !keep_none) {
178
7.73M
    FREE_PMC_NODE(pc_tree->none);
179
180
23.1M
    for (int i = 0; i < 2; ++i) {
181
15.4M
      FREE_PMC_NODE(pc_tree->horizontal[i]);
182
15.4M
      FREE_PMC_NODE(pc_tree->vertical[i]);
183
15.4M
    }
184
185
#if !defined(NDEBUG) && !CONFIG_REALTIME_ONLY
186
    for (int i = 0; i < 3; ++i) {
187
      assert(pc_tree->horizontala[i] == NULL);
188
      assert(pc_tree->horizontalb[i] == NULL);
189
      assert(pc_tree->verticala[i] == NULL);
190
      assert(pc_tree->verticalb[i] == NULL);
191
    }
192
    for (int i = 0; i < 4; ++i) {
193
      assert(pc_tree->horizontal4[i] == NULL);
194
      assert(pc_tree->vertical4[i] == NULL);
195
    }
196
#endif
197
198
38.6M
    for (int i = 0; i < 4; ++i) {
199
30.8M
      if (pc_tree->split[i] != NULL) {
200
7.62M
        av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0,
201
7.62M
                                   partition_search_type);
202
7.62M
        pc_tree->split[i] = NULL;
203
7.62M
      }
204
30.8M
    }
205
7.73M
    aom_free(pc_tree);
206
7.73M
    return;
207
7.73M
  }
208
209
19.1M
  const PARTITION_TYPE partition = pc_tree->partitioning;
210
211
19.1M
  if (!keep_none && (!keep_best || (partition != PARTITION_NONE)))
212
10.6M
    FREE_PMC_NODE(pc_tree->none);
213
214
57.3M
  for (int i = 0; i < 2; ++i) {
215
38.2M
    if (!keep_best || (partition != PARTITION_HORZ))
216
38.0M
      FREE_PMC_NODE(pc_tree->horizontal[i]);
217
38.2M
    if (!keep_best || (partition != PARTITION_VERT))
218
38.1M
      FREE_PMC_NODE(pc_tree->vertical[i]);
219
38.2M
  }
220
19.1M
#if !CONFIG_REALTIME_ONLY
221
76.5M
  for (int i = 0; i < 3; ++i) {
222
57.3M
    if (!keep_best || (partition != PARTITION_HORZ_A))
223
57.3M
      FREE_PMC_NODE(pc_tree->horizontala[i]);
224
57.3M
    if (!keep_best || (partition != PARTITION_HORZ_B))
225
57.3M
      FREE_PMC_NODE(pc_tree->horizontalb[i]);
226
57.3M
    if (!keep_best || (partition != PARTITION_VERT_A))
227
57.3M
      FREE_PMC_NODE(pc_tree->verticala[i]);
228
57.3M
    if (!keep_best || (partition != PARTITION_VERT_B))
229
57.3M
      FREE_PMC_NODE(pc_tree->verticalb[i]);
230
57.3M
  }
231
95.6M
  for (int i = 0; i < 4; ++i) {
232
76.5M
    if (!keep_best || (partition != PARTITION_HORZ_4))
233
76.5M
      FREE_PMC_NODE(pc_tree->horizontal4[i]);
234
76.5M
    if (!keep_best || (partition != PARTITION_VERT_4))
235
76.5M
      FREE_PMC_NODE(pc_tree->vertical4[i]);
236
76.5M
  }
237
19.1M
#endif
238
19.1M
  if (!keep_best || (partition != PARTITION_SPLIT)) {
239
89.4M
    for (int i = 0; i < 4; ++i) {
240
71.5M
      if (pc_tree->split[i] != NULL) {
241
10.4M
        av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0,
242
10.4M
                                   partition_search_type);
243
10.4M
        pc_tree->split[i] = NULL;
244
10.4M
      }
245
71.5M
    }
246
17.8M
  }
247
248
19.1M
  if (!keep_best && !keep_none) aom_free(pc_tree);
249
19.1M
}
250
251
233k
int av1_setup_sms_tree(AV1_COMP *const cpi, ThreadData *td) {
252
  // The structure 'sms_tree' is used to store the simple motion search data for
253
  // partition pruning in inter frames. Hence, the memory allocations and
254
  // initializations related to it are avoided for allintra encoding mode.
255
233k
  if (cpi->oxcf.kf_cfg.key_freq_max == 0) return 0;
256
257
67.7k
  AV1_COMMON *const cm = &cpi->common;
258
67.7k
  const int stat_generation_stage = is_stat_generation_stage(cpi);
259
67.7k
  const int is_sb_size_128 = cm->seq_params->sb_size == BLOCK_128X128;
260
67.7k
  const int tree_nodes =
261
67.7k
      av1_get_pc_tree_nodes(is_sb_size_128, stat_generation_stage);
262
67.7k
  int sms_tree_index = 0;
263
67.7k
  SIMPLE_MOTION_DATA_TREE *this_sms;
264
67.7k
  int square_index = 1;
265
67.7k
  int nodes;
266
267
67.7k
  aom_free(td->sms_tree);
268
67.7k
  td->sms_tree =
269
67.7k
      (SIMPLE_MOTION_DATA_TREE *)aom_calloc(tree_nodes, sizeof(*td->sms_tree));
270
67.7k
  if (!td->sms_tree) return -1;
271
67.7k
  this_sms = &td->sms_tree[0];
272
273
67.7k
  if (!stat_generation_stage) {
274
53.7k
    const int leaf_factor = is_sb_size_128 ? 4 : 1;
275
53.7k
    const int leaf_nodes = 256 * leaf_factor;
276
277
    // Sets up all the leaf nodes in the tree.
278
25.5M
    for (sms_tree_index = 0; sms_tree_index < leaf_nodes; ++sms_tree_index) {
279
25.5M
      SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
280
25.5M
      tree->block_size = square[0];
281
25.5M
    }
282
283
    // Each node has 4 leaf nodes, fill each block_size level of the tree
284
    // from leafs to the root.
285
284k
    for (nodes = leaf_nodes >> 2; nodes > 0; nodes >>= 2) {
286
8.72M
      for (int i = 0; i < nodes; ++i) {
287
8.49M
        SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
288
8.49M
        tree->block_size = square[square_index];
289
42.4M
        for (int j = 0; j < 4; j++) tree->split[j] = this_sms++;
290
8.49M
        ++sms_tree_index;
291
8.49M
      }
292
230k
      ++square_index;
293
230k
    }
294
53.7k
  } else {
295
    // Allocation for firstpass/LAP stage
296
    // TODO(Mufaddal): refactor square_index to use a common block_size macro
297
    // from firstpass.c
298
13.9k
    SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
299
13.9k
    square_index = 2;
300
13.9k
    tree->block_size = square[square_index];
301
13.9k
  }
302
303
  // Set up the root node for the largest superblock size
304
67.7k
  td->sms_root = &td->sms_tree[tree_nodes - 1];
305
67.7k
  return 0;
306
67.7k
}
307
308
561k
void av1_free_sms_tree(ThreadData *td) {
309
561k
  aom_free(td->sms_tree);
310
  td->sms_tree = NULL;
311
561k
}