Coverage Report

Created: 2026-09-14 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/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
16
void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
17
0
                           PICK_MODE_CONTEXT *src_ctx) {
18
0
  dst_ctx->mic = src_ctx->mic;
19
0
  dst_ctx->mbmi_ext_best = src_ctx->mbmi_ext_best;
20
21
0
  dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk;
22
0
  dst_ctx->skippable = src_ctx->skippable;
23
#if CONFIG_INTERNAL_STATS
24
  dst_ctx->best_mode_index = src_ctx->best_mode_index;
25
#endif  // CONFIG_INTERNAL_STATS
26
27
0
  memcpy(dst_ctx->blk_skip, src_ctx->blk_skip,
28
0
         sizeof(uint8_t) * src_ctx->num_4x4_blk);
29
0
  av1_copy_array(dst_ctx->tx_type_map, src_ctx->tx_type_map,
30
0
                 src_ctx->num_4x4_blk);
31
32
0
  dst_ctx->rd_stats = src_ctx->rd_stats;
33
0
  dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
34
0
}
35
36
void av1_setup_shared_coeff_buffer(const SequenceHeader *const seq_params,
37
                                   PC_TREE_SHARED_BUFFERS *shared_bufs,
38
2.40k
                                   struct aom_internal_error_info *error) {
39
2.40k
  const int num_planes = seq_params->monochrome ? 1 : MAX_MB_PLANE;
40
2.40k
  const int max_sb_square_y = 1 << num_pels_log2_lookup[seq_params->sb_size];
41
2.40k
  const int max_sb_square_uv = max_sb_square_y >> (seq_params->subsampling_x +
42
2.40k
                                                   seq_params->subsampling_y);
43
9.60k
  for (int i = 0; i < num_planes; i++) {
44
7.20k
    const int max_num_pix =
45
7.20k
        (i == AOM_PLANE_Y) ? max_sb_square_y : max_sb_square_uv;
46
7.20k
    AOM_CHECK_MEM_ERROR(error, shared_bufs->coeff_buf[i],
47
7.20k
                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
48
7.20k
    AOM_CHECK_MEM_ERROR(error, shared_bufs->qcoeff_buf[i],
49
7.20k
                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
50
7.20k
    AOM_CHECK_MEM_ERROR(error, shared_bufs->dqcoeff_buf[i],
51
7.20k
                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
52
7.20k
  }
53
2.40k
}
54
55
2.40k
void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs) {
56
9.60k
  for (int i = 0; i < 3; i++) {
57
7.20k
    aom_free(shared_bufs->coeff_buf[i]);
58
7.20k
    aom_free(shared_bufs->qcoeff_buf[i]);
59
7.20k
    aom_free(shared_bufs->dqcoeff_buf[i]);
60
7.20k
    shared_bufs->coeff_buf[i] = NULL;
61
7.20k
    shared_bufs->qcoeff_buf[i] = NULL;
62
7.20k
    shared_bufs->dqcoeff_buf[i] = NULL;
63
7.20k
  }
64
2.40k
}
65
66
PICK_MODE_CONTEXT *av1_alloc_pmc(const struct AV1_COMP *const cpi,
67
                                 BLOCK_SIZE bsize,
68
83.7k
                                 PC_TREE_SHARED_BUFFERS *shared_bufs) {
69
83.7k
  PICK_MODE_CONTEXT *ctx = NULL;
70
83.7k
  const AV1_COMMON *const cm = &cpi->common;
71
83.7k
  struct aom_internal_error_info error;
72
73
83.7k
  AOM_CHECK_MEM_ERROR(&error, ctx, aom_calloc(1, sizeof(*ctx)));
74
83.7k
  ctx->rd_mode_is_ready = 0;
75
76
83.7k
  const int num_planes = av1_num_planes(cm);
77
83.7k
  const int num_pix = block_size_wide[bsize] * block_size_high[bsize];
78
83.7k
  const int num_blk = num_pix / 16;
79
80
83.7k
  AOM_CHECK_MEM_ERROR(&error, ctx->blk_skip,
81
83.7k
                      aom_calloc(num_blk, sizeof(*ctx->blk_skip)));
82
83.7k
  AOM_CHECK_MEM_ERROR(&error, ctx->tx_type_map,
83
83.7k
                      aom_calloc(num_blk, sizeof(*ctx->tx_type_map)));
84
83.7k
  ctx->num_4x4_blk = num_blk;
85
86
334k
  for (int i = 0; i < num_planes; ++i) {
87
251k
    ctx->coeff[i] = shared_bufs->coeff_buf[i];
88
251k
    ctx->qcoeff[i] = shared_bufs->qcoeff_buf[i];
89
251k
    ctx->dqcoeff[i] = shared_bufs->dqcoeff_buf[i];
90
251k
    AOM_CHECK_MEM_ERROR(&error, ctx->eobs[i],
91
251k
                        aom_memalign(32, num_blk * sizeof(*ctx->eobs[i])));
92
251k
    AOM_CHECK_MEM_ERROR(
93
251k
        &error, ctx->txb_entropy_ctx[i],
94
251k
        aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i])));
95
251k
  }
96
97
83.7k
  if (num_pix <= MAX_PALETTE_SQUARE) {
98
251k
    for (int i = 0; i < 2; ++i) {
99
167k
      if (!cpi->sf.rt_sf.use_nonrd_pick_mode || frame_is_intra_only(cm)) {
100
167k
        AOM_CHECK_MEM_ERROR(
101
167k
            &error, ctx->color_index_map[i],
102
167k
            aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
103
167k
      } else {
104
0
        ctx->color_index_map[i] = NULL;
105
0
      }
106
167k
    }
107
83.7k
  }
108
109
83.7k
  av1_invalid_rd_stats(&ctx->rd_stats);
110
111
83.7k
  return ctx;
112
83.7k
}
113
114
6.20M
void av1_free_pmc(PICK_MODE_CONTEXT *ctx, int num_planes) {
115
6.20M
  if (ctx == NULL) return;
116
117
84.0k
  aom_free(ctx->blk_skip);
118
84.0k
  ctx->blk_skip = NULL;
119
84.0k
  aom_free(ctx->tx_type_map);
120
335k
  for (int i = 0; i < num_planes; ++i) {
121
251k
    ctx->coeff[i] = NULL;
122
251k
    ctx->qcoeff[i] = NULL;
123
251k
    ctx->dqcoeff[i] = NULL;
124
251k
    aom_free(ctx->eobs[i]);
125
251k
    ctx->eobs[i] = NULL;
126
251k
    aom_free(ctx->txb_entropy_ctx[i]);
127
251k
    ctx->txb_entropy_ctx[i] = NULL;
128
251k
  }
129
130
251k
  for (int i = 0; i < 2; ++i) {
131
167k
    if (ctx->color_index_map[i]) {
132
167k
      aom_free(ctx->color_index_map[i]);
133
167k
      ctx->color_index_map[i] = NULL;
134
167k
    }
135
167k
  }
136
137
84.0k
  aom_free(ctx);
138
84.0k
}
139
140
183k
PC_TREE *av1_alloc_pc_tree_node(BLOCK_SIZE bsize) {
141
183k
  PC_TREE *pc_tree = NULL;
142
183k
  struct aom_internal_error_info error;
143
144
183k
  AOM_CHECK_MEM_ERROR(&error, pc_tree, aom_calloc(1, sizeof(*pc_tree)));
145
146
183k
  pc_tree->partitioning = PARTITION_NONE;
147
183k
  pc_tree->block_size = bsize;
148
183k
  pc_tree->index = 0;
149
150
183k
  pc_tree->none = NULL;
151
549k
  for (int i = 0; i < 2; ++i) {
152
366k
    pc_tree->horizontal[i] = NULL;
153
366k
    pc_tree->vertical[i] = NULL;
154
366k
  }
155
732k
  for (int i = 0; i < 3; ++i) {
156
549k
    pc_tree->horizontala[i] = NULL;
157
549k
    pc_tree->horizontalb[i] = NULL;
158
549k
    pc_tree->verticala[i] = NULL;
159
549k
    pc_tree->verticalb[i] = NULL;
160
549k
  }
161
915k
  for (int i = 0; i < 4; ++i) {
162
732k
    pc_tree->horizontal4[i] = NULL;
163
732k
    pc_tree->vertical4[i] = NULL;
164
732k
    pc_tree->split[i] = NULL;
165
732k
  }
166
167
183k
  return pc_tree;
168
183k
}
169
170
#define FREE_PMC_NODE(CTX)         \
171
6.20M
  do {                             \
172
6.20M
    av1_free_pmc(CTX, num_planes); \
173
6.20M
    CTX = NULL;                    \
174
6.20M
  } while (0)
175
176
void av1_free_pc_tree_recursive(PC_TREE *pc_tree, int num_planes, int keep_best,
177
251k
                                int keep_none) {
178
251k
  if (pc_tree == NULL) return;
179
180
251k
  const PARTITION_TYPE partition = pc_tree->partitioning;
181
182
251k
  if (!keep_none && (!keep_best || (partition != PARTITION_NONE)))
183
183k
    FREE_PMC_NODE(pc_tree->none);
184
185
755k
  for (int i = 0; i < 2; ++i) {
186
503k
    if (!keep_best || (partition != PARTITION_HORZ))
187
494k
      FREE_PMC_NODE(pc_tree->horizontal[i]);
188
503k
    if (!keep_best || (partition != PARTITION_VERT))
189
495k
      FREE_PMC_NODE(pc_tree->vertical[i]);
190
503k
  }
191
1.00M
  for (int i = 0; i < 3; ++i) {
192
755k
    if (!keep_best || (partition != PARTITION_HORZ_A))
193
755k
      FREE_PMC_NODE(pc_tree->horizontala[i]);
194
755k
    if (!keep_best || (partition != PARTITION_HORZ_B))
195
755k
      FREE_PMC_NODE(pc_tree->horizontalb[i]);
196
755k
    if (!keep_best || (partition != PARTITION_VERT_A))
197
755k
      FREE_PMC_NODE(pc_tree->verticala[i]);
198
755k
    if (!keep_best || (partition != PARTITION_VERT_B))
199
755k
      FREE_PMC_NODE(pc_tree->verticalb[i]);
200
755k
  }
201
1.25M
  for (int i = 0; i < 4; ++i) {
202
1.00M
    if (!keep_best || (partition != PARTITION_HORZ_4))
203
1.00M
      FREE_PMC_NODE(pc_tree->horizontal4[i]);
204
1.00M
    if (!keep_best || (partition != PARTITION_VERT_4))
205
1.00M
      FREE_PMC_NODE(pc_tree->vertical4[i]);
206
1.00M
  }
207
208
251k
  if (!keep_best || (partition != PARTITION_SPLIT)) {
209
1.23M
    for (int i = 0; i < 4; ++i) {
210
990k
      if (pc_tree->split[i] != NULL) {
211
174k
        av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0);
212
174k
        pc_tree->split[i] = NULL;
213
174k
      }
214
990k
    }
215
247k
  }
216
217
251k
  if (!keep_best && !keep_none) aom_free(pc_tree);
218
251k
}
219
220
2.40k
void av1_setup_sms_tree(AV1_COMP *const cpi, ThreadData *td) {
221
2.40k
  AV1_COMMON *const cm = &cpi->common;
222
2.40k
  const int stat_generation_stage = is_stat_generation_stage(cpi);
223
2.40k
  const int is_sb_size_128 = cm->seq_params->sb_size == BLOCK_128X128;
224
2.40k
  const int tree_nodes =
225
2.40k
      av1_get_pc_tree_nodes(is_sb_size_128, stat_generation_stage);
226
2.40k
  int sms_tree_index = 0;
227
2.40k
  SIMPLE_MOTION_DATA_TREE *this_sms;
228
2.40k
  int square_index = 1;
229
2.40k
  int nodes;
230
231
2.40k
  aom_free(td->sms_tree);
232
2.40k
  CHECK_MEM_ERROR(cm, td->sms_tree,
233
2.40k
                  aom_calloc(tree_nodes, sizeof(*td->sms_tree)));
234
2.40k
  this_sms = &td->sms_tree[0];
235
236
2.40k
  if (!stat_generation_stage) {
237
2.40k
    const int leaf_factor = is_sb_size_128 ? 4 : 1;
238
2.40k
    const int leaf_nodes = 256 * leaf_factor;
239
240
    // Sets up all the leaf nodes in the tree.
241
1.30M
    for (sms_tree_index = 0; sms_tree_index < leaf_nodes; ++sms_tree_index) {
242
1.30M
      SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
243
1.30M
      tree->block_size = square[0];
244
1.30M
    }
245
246
    // Each node has 4 leaf nodes, fill each block_size level of the tree
247
    // from leafs to the root.
248
12.9k
    for (nodes = leaf_nodes >> 2; nodes > 0; nodes >>= 2) {
249
444k
      for (int i = 0; i < nodes; ++i) {
250
433k
        SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
251
433k
        tree->block_size = square[square_index];
252
2.16M
        for (int j = 0; j < 4; j++) tree->split[j] = this_sms++;
253
433k
        ++sms_tree_index;
254
433k
      }
255
10.5k
      ++square_index;
256
10.5k
    }
257
2.40k
  } else {
258
    // Allocation for firstpass/LAP stage
259
    // TODO(Mufaddal): refactor square_index to use a common block_size macro
260
    // from firstpass.c
261
0
    SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
262
0
    square_index = 2;
263
0
    tree->block_size = square[square_index];
264
0
  }
265
266
  // Set up the root node for the largest superblock size
267
2.40k
  td->sms_root = &td->sms_tree[tree_nodes - 1];
268
2.40k
}
269
270
2.40k
void av1_free_sms_tree(ThreadData *td) {
271
2.40k
  if (td->sms_tree != NULL) {
272
2.40k
    aom_free(td->sms_tree);
273
    td->sms_tree = NULL;
274
2.40k
  }
275
2.40k
}