Coverage Report

Created: 2026-09-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/avm/av2/common/alloccommon.c
Line
Count
Source
1
/*
2
 *
3
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
4
 *
5
 * This source code is subject to the terms of the BSD 3-Clause Clear License
6
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
7
 * License was not distributed with this source code in the LICENSE file, you
8
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
9
 * Alliance for Open Media Patent License 1.0 was not distributed with this
10
 * source code in the PATENTS file, you can obtain it at
11
 * aomedia.org/license/patent-license/.
12
 */
13
14
#include "config/avm_config.h"
15
16
#include "avm_mem/avm_mem.h"
17
18
#include "av2/common/alloccommon.h"
19
#include "av2/common/av2_common_int.h"
20
#include "av2/common/blockd.h"
21
#include "av2/common/cdef_block.h"
22
#include "av2/common/entropymode.h"
23
#include "av2/common/entropymv.h"
24
#include "av2/common/thread_common.h"
25
26
0
int av2_get_MBs(int width, int height) {
27
0
  const int aligned_width = ALIGN_POWER_OF_TWO(width, 3);
28
0
  const int aligned_height = ALIGN_POWER_OF_TWO(height, 3);
29
0
  const int mi_cols = aligned_width >> MI_SIZE_LOG2;
30
0
  const int mi_rows = aligned_height >> MI_SIZE_LOG2;
31
32
0
  const int mb_cols = (mi_cols + 2) >> 2;
33
0
  const int mb_rows = (mi_rows + 2) >> 2;
34
0
  return mb_rows * mb_cols;
35
0
}
36
37
10.8k
void av2_free_ref_frame_buffers(BufferPool *pool) {
38
10.8k
  int i;
39
40
8.35M
  for (i = 0; i < FRAME_BUFFERS; ++i) {
41
8.34M
    if (pool->frame_bufs[i].ref_count > 0 &&
42
39
        pool->frame_bufs[i].raw_frame_buffer.data != NULL) {
43
39
      pool->release_fb_cb(pool->cb_priv, &pool->frame_bufs[i].raw_frame_buffer);
44
39
      pool->frame_bufs[i].raw_frame_buffer.data = NULL;
45
39
      pool->frame_bufs[i].raw_frame_buffer.size = 0;
46
39
      pool->frame_bufs[i].raw_frame_buffer.priv = NULL;
47
39
      pool->frame_bufs[i].ref_count = 0;
48
39
    }
49
8.34M
    avm_free(pool->frame_bufs[i].mvs);
50
8.34M
    pool->frame_bufs[i].mvs = NULL;
51
8.34M
    avm_free(pool->frame_bufs[i].seg_map);
52
8.34M
    pool->frame_bufs[i].seg_map = NULL;
53
8.34M
    avm_free_frame_buffer(&pool->frame_bufs[i].buf);
54
55
33.3M
    for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
56
25.0M
      if (pool->frame_bufs[i].ccso_info.sb_filter_control[plane] != NULL) {
57
22.8k
        avm_free(pool->frame_bufs[i].ccso_info.sb_filter_control[plane]);
58
22.8k
        pool->frame_bufs[i].ccso_info.sb_filter_control[plane] = NULL;
59
22.8k
      }
60
25.0M
    }
61
62
33.3M
    for (int p = 0; p < MAX_MB_PLANE; ++p) {
63
25.0M
      av2_free_restoration_struct(&pool->frame_bufs[i].rst_info[p]);
64
25.0M
    }
65
8.34M
  }
66
10.8k
}
67
68
// Frees CDEF line buffers when their allocated and new size is not matching.
69
static INLINE void free_cdef_linebuf_conditional(
70
40
    AV2_COMMON *const cm, const size_t *new_linebuf_size) {
71
40
  CdefInfo *cdef_info = &cm->cdef_info;
72
160
  for (int plane = 0; plane < MAX_MB_PLANE; plane++) {
73
120
    if (new_linebuf_size[plane] != cdef_info->allocated_linebuf_size[plane]) {
74
87
      avm_free(cdef_info->linebuf[plane]);
75
87
      cdef_info->linebuf[plane] = NULL;
76
87
    }
77
120
  }
78
40
}
79
80
// Frees CDEF source/column buffers if their allocated and new size is not
81
// matching.
82
static INLINE void free_cdef_bufs_conditional(AV2_COMMON *const cm,
83
                                              uint16_t **const colbuf,
84
                                              uint16_t **const srcbuf,
85
                                              const size_t *new_colbuf_size,
86
40
                                              const size_t new_srcbuf_size) {
87
40
  CdefInfo *cdef_info = &cm->cdef_info;
88
40
  if (new_srcbuf_size != cdef_info->allocated_srcbuf_size) {
89
29
    avm_free(*srcbuf);
90
29
    *srcbuf = NULL;
91
29
  }
92
160
  for (int plane = 0; plane < MAX_MB_PLANE; plane++) {
93
120
    if (new_colbuf_size[plane] != cdef_info->allocated_colbuf_size[plane]) {
94
87
      avm_free(colbuf[plane]);
95
87
      colbuf[plane] = NULL;
96
87
    }
97
120
  }
98
40
}
99
100
// Free and reset CDEF source and column buffers.
101
static INLINE void free_cdef_bufs(uint16_t **const colbuf,
102
10.8k
                                  uint16_t **const srcbuf) {
103
10.8k
  avm_free(*srcbuf);
104
10.8k
  *srcbuf = NULL;
105
43.4k
  for (int plane = 0; plane < MAX_MB_PLANE; plane++) {
106
32.6k
    avm_free(colbuf[plane]);
107
32.6k
    colbuf[plane] = NULL;
108
32.6k
  }
109
10.8k
}
110
111
// Frees the memory and synchronization primitives allocated for CDEF row sync.
112
static INLINE void free_cdef_row_sync(AV2CdefRowSync **cdef_row_mt,
113
3.76k
                                      const int num_mi_rows) {
114
3.76k
  if (*cdef_row_mt == NULL) return;
115
0
#if CONFIG_MULTITHREAD
116
0
  for (int row_idx = 0; row_idx < num_mi_rows; row_idx++) {
117
0
    if ((*cdef_row_mt)[row_idx].row_mutex_ != NULL) {
118
0
      pthread_mutex_destroy((*cdef_row_mt)[row_idx].row_mutex_);
119
0
      avm_free((*cdef_row_mt)[row_idx].row_mutex_);
120
0
    }
121
0
    if ((*cdef_row_mt)[row_idx].row_cond_ != NULL) {
122
0
      pthread_cond_destroy((*cdef_row_mt)[row_idx].row_cond_);
123
0
      avm_free((*cdef_row_mt)[row_idx].row_cond_);
124
0
    }
125
0
  }
126
#else
127
  (void)num_mi_rows;
128
#endif  // CONFIG_MULTITHREAD
129
0
  avm_free(*cdef_row_mt);
130
0
  *cdef_row_mt = NULL;
131
0
}
132
133
void av2_free_cdef_buffers(AV2_COMMON *const cm,
134
                           AV2CdefWorkerData **cdef_worker,
135
10.8k
                           AV2CdefSync *cdef_sync, int num_workers) {
136
10.8k
  CdefInfo *cdef_info = &cm->cdef_info;
137
10.8k
  const int num_mi_rows = cdef_info->allocated_mi_rows;
138
139
43.4k
  for (int plane = 0; plane < MAX_MB_PLANE; plane++) {
140
32.6k
    avm_free(cdef_info->linebuf[plane]);
141
32.6k
    cdef_info->linebuf[plane] = NULL;
142
32.6k
  }
143
  // De-allocation of column buffer & source buffer (worker 0).
144
10.8k
  free_cdef_bufs(cdef_info->colbuf, &cdef_info->srcbuf);
145
146
10.8k
  if (num_workers < 2) return;
147
3.73k
  if (*cdef_worker != NULL) {
148
0
    for (int idx = 1; idx < num_workers; idx++) {
149
      // De-allocation of column buffer & source buffer for remaining workers.
150
0
      free_cdef_bufs((*cdef_worker)[idx].colbuf, &(*cdef_worker)[idx].srcbuf);
151
0
    }
152
0
    avm_free(*cdef_worker);
153
0
    *cdef_worker = NULL;
154
0
  }
155
3.73k
  free_cdef_row_sync(&cdef_sync->cdef_row_mt, num_mi_rows);
156
3.73k
}
157
158
// Allocate CDEF line buffers for each plane if not already allocated.
159
static INLINE void alloc_cdef_linebuf(AV2_COMMON *const cm,
160
                                      uint16_t **const linebuf,
161
30
                                      int num_planes) {
162
30
  CdefInfo *cdef_info = &cm->cdef_info;
163
120
  for (int plane = 0; plane < num_planes; plane++) {
164
90
    if (linebuf[plane] == NULL)
165
90
      CHECK_MEM_ERROR(cm, linebuf[plane],
166
90
                      avm_malloc(cdef_info->allocated_linebuf_size[plane]));
167
90
  }
168
30
}
169
170
// Allocate CDEF source and column buffers.
171
static INLINE void alloc_cdef_bufs(AV2_COMMON *const cm, uint16_t **colbuf,
172
30
                                   uint16_t **srcbuf, const int num_planes) {
173
30
  CdefInfo *cdef_info = &cm->cdef_info;
174
30
  if (*srcbuf == NULL)
175
30
    CHECK_MEM_ERROR(cm, *srcbuf,
176
30
                    avm_memalign(16, cdef_info->allocated_srcbuf_size));
177
178
120
  for (int plane = 0; plane < num_planes; plane++) {
179
90
    if (colbuf[plane] == NULL)
180
90
      CHECK_MEM_ERROR(cm, colbuf[plane],
181
90
                      avm_malloc(cdef_info->allocated_colbuf_size[plane]));
182
90
  }
183
30
}
184
185
// Allocate and initialize row-level synchronization structure for CDEF.
186
static INLINE void alloc_cdef_row_sync(AV2_COMMON *const cm,
187
                                       AV2CdefRowSync **cdef_row_mt,
188
0
                                       const int num_mi_rows) {
189
0
  if (*cdef_row_mt != NULL) return;
190
191
0
  CHECK_MEM_ERROR(cm, *cdef_row_mt,
192
0
                  avm_calloc(num_mi_rows, sizeof(**cdef_row_mt)));
193
0
#if CONFIG_MULTITHREAD
194
0
  for (int row_idx = 0; row_idx < num_mi_rows; row_idx++) {
195
0
    CHECK_MEM_ERROR(cm, (*cdef_row_mt)[row_idx].row_mutex_,
196
0
                    avm_malloc(sizeof(*(*cdef_row_mt)[row_idx].row_mutex_)));
197
0
    pthread_mutex_init((*cdef_row_mt)[row_idx].row_mutex_, NULL);
198
199
0
    CHECK_MEM_ERROR(cm, (*cdef_row_mt)[row_idx].row_cond_,
200
0
                    avm_malloc(sizeof(*(*cdef_row_mt)[row_idx].row_cond_)));
201
0
    pthread_cond_init((*cdef_row_mt)[row_idx].row_cond_, NULL);
202
0
  }
203
0
#endif  // CONFIG_MULTITHREAD
204
0
}
205
206
void av2_alloc_cdef_buffers(AV2_COMMON *const cm,
207
                            AV2CdefWorkerData **cdef_worker,
208
40
                            AV2CdefSync *cdef_sync, int num_workers) {
209
40
  CdefInfo *cdef_info = &cm->cdef_info;
210
40
  size_t new_linebuf_size[MAX_MB_PLANE] = { 0 };
211
40
  size_t new_colbuf_size[MAX_MB_PLANE] = { 0 };
212
40
  size_t new_srcbuf_size = 0;
213
40
  const int num_planes = av2_num_planes(cm);
214
40
  const int luma_stride =
215
40
      ALIGN_POWER_OF_TWO(cm->mi_params.mi_cols << MI_SIZE_LOG2, 4);
216
  // Check for configuration change
217
40
  const int num_mi_rows =
218
40
      (cm->mi_params.mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
219
40
  const int is_num_workers_changed =
220
40
      cdef_info->allocated_num_workers != num_workers;
221
40
  const int is_cdef_enabled = cm->seq_params.enable_cdef;
222
  // num-bufs=3 represents ping-pong buffers for top linebuf,
223
  // followed by bottom linebuf.
224
  // ping-pong is to avoid top linebuf over-write by consecutive row.
225
40
  int num_bufs = 3;
226
40
  if (num_workers > 1)
227
0
    num_bufs = (cm->mi_params.mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
228
229
40
  if (is_cdef_enabled) {
230
    // Calculate src buffer size
231
30
    new_srcbuf_size = sizeof(*cdef_info->srcbuf) * CDEF_INBUF_SIZE;
232
120
    for (int plane = 0; plane < num_planes; plane++) {
233
90
      const int shift = plane == AVM_PLANE_Y ? 0 : cm->seq_params.subsampling_x;
234
      // Calculate top and bottom line buffer size
235
90
      new_linebuf_size[plane] = sizeof(*cdef_info->linebuf) * num_bufs *
236
90
                                (CDEF_VBORDER << 1) * (luma_stride >> shift);
237
      // Calculate column buffer size
238
90
      const int block_height =
239
90
          (CDEF_BLOCKSIZE << (MI_SIZE_LOG2 - shift)) * 2 * CDEF_VBORDER;
240
90
      new_colbuf_size[plane] =
241
90
          sizeof(*cdef_info->colbuf[plane]) * block_height * CDEF_HBORDER;
242
90
    }
243
30
  }
244
245
  // Free src, line and column buffers for worker 0 in case of reallocation
246
40
  free_cdef_linebuf_conditional(cm, new_linebuf_size);
247
40
  free_cdef_bufs_conditional(cm, cdef_info->colbuf, &cdef_info->srcbuf,
248
40
                             new_colbuf_size, new_srcbuf_size);
249
250
40
  if (*cdef_worker != NULL) {
251
0
    if (is_num_workers_changed) {
252
      // Free src and column buffers for remaining workers in case of change in
253
      // num_workers
254
0
      for (int idx = 1; idx < cdef_info->allocated_num_workers; idx++)
255
0
        free_cdef_bufs((*cdef_worker)[idx].colbuf, &(*cdef_worker)[idx].srcbuf);
256
0
    } else if (num_workers > 1) {
257
      // Free src and column buffers for remaining workers in case of
258
      // reallocation
259
0
      for (int idx = 1; idx < num_workers; idx++)
260
0
        free_cdef_bufs_conditional(cm, (*cdef_worker)[idx].colbuf,
261
0
                                   &(*cdef_worker)[idx].srcbuf, new_colbuf_size,
262
0
                                   new_srcbuf_size);
263
0
    }
264
0
  }
265
266
40
  if (cdef_info->allocated_mi_rows != num_mi_rows)
267
39
    free_cdef_row_sync(&cdef_sync->cdef_row_mt, cdef_info->allocated_mi_rows);
268
269
  // Store allocated sizes for reallocation
270
40
  cdef_info->allocated_srcbuf_size = new_srcbuf_size;
271
40
  av2_copy(cdef_info->allocated_colbuf_size, new_colbuf_size);
272
40
  av2_copy(cdef_info->allocated_linebuf_size, new_linebuf_size);
273
  // Store configuration to check change in configuration
274
40
  cdef_info->allocated_mi_rows = num_mi_rows;
275
40
  cdef_info->allocated_num_workers = num_workers;
276
277
40
  if (!is_cdef_enabled) return;
278
279
  // Memory allocation of column buffer & source buffer (worker 0).
280
30
  alloc_cdef_bufs(cm, cdef_info->colbuf, &cdef_info->srcbuf, num_planes);
281
30
  alloc_cdef_linebuf(cm, cdef_info->linebuf, num_planes);
282
283
30
  if (num_workers < 2) return;
284
285
0
  if (*cdef_worker == NULL)
286
0
    CHECK_MEM_ERROR(cm, *cdef_worker,
287
0
                    avm_calloc(num_workers, sizeof(**cdef_worker)));
288
289
0
  for (int idx = 1; idx < num_workers; idx++) {
290
    // Memory allocation of column buffer & source buffer for remaining workers.
291
0
    alloc_cdef_bufs(cm, (*cdef_worker)[idx].colbuf, &(*cdef_worker)[idx].srcbuf,
292
0
                    num_planes);
293
0
  }
294
295
0
  alloc_cdef_row_sync(cm, &cdef_sync->cdef_row_mt,
296
0
                      cdef_info->allocated_mi_rows);
297
0
}
298
299
// Assumes cm->rst_info[p].restoration_unit_size is already initialized
300
471
void av2_alloc_restoration_buffers(AV2_COMMON *cm) {
301
471
  const int num_planes = av2_num_planes(cm);
302
1.88k
  for (int p = 0; p < num_planes; ++p)
303
1.41k
    av2_alloc_restoration_struct(cm, &cm->rst_info[p], p > 0);
304
305
471
  if (cm->frame_filter_dictionary == NULL) {
306
284
    allocate_frame_filter_dictionary(cm);
307
284
    translate_pcwiener_filters_to_wienerns(cm);
308
284
  }
309
310
471
  if (cm->rlbs == NULL) {
311
471
    CHECK_MEM_ERROR(cm, cm->rlbs, avm_malloc(sizeof(RestorationLineBuffers)));
312
471
  }
313
471
  if (cm->lru_stripe_buf == NULL) {
314
471
    CHECK_MEM_ERROR(
315
471
        cm, cm->lru_stripe_buf,
316
471
        avm_malloc(MAX_LRU_STRIPE_BUF_SIZE * sizeof(*cm->lru_stripe_buf)));
317
471
  }
318
319
471
  av2_alloc_restoration_boundary_buffers(cm, num_planes);
320
471
}
321
322
void av2_alloc_restoration_boundary_buffers(struct AV2Common *cm,
323
5.49k
                                            int num_planes) {
324
  // For striped loop restoration, we divide each row of tiles into "stripes",
325
  // of height 64 luma pixels but with an offset by RESTORATION_UNIT_OFFSET
326
  // luma pixels to match the output from CDEF. We will need to store 2 *
327
  // RESTORATION_CTX_VERT lines of data for each stripe, and also need to be
328
  // able to quickly answer the question "Where is the <n>'th stripe for tile
329
  // row <m>?" To make that efficient, we generate the rst_last_stripe array.
330
331
5.49k
  AV2PixelRect tile_rect;
332
5.49k
  int num_stripes = 0;
333
5.49k
  TileInfo tile_info;
334
18.7k
  for (int tr = 0; tr < cm->tiles.rows; ++tr) {
335
13.2k
    av2_tile_init(&tile_info, cm, tr, 0);
336
13.2k
    tile_rect = av2_get_tile_rect(&tile_info, cm, 0);
337
13.2k
    const int tile_h = tile_rect.bottom - tile_rect.top;
338
13.2k
    num_stripes += av2_lr_count_stripes_in_tile(tile_h, 0);
339
13.2k
  }
340
  // int num_stripes = cm->rst_info[0].vert_stripes_per_frame;
341
342
  // Now we need to allocate enough space to store the line buffers for the
343
  // stripes
344
5.49k
  const int frame_w = cm->mi_params.mi_cols << MI_SIZE_LOG2;
345
346
11.9k
  for (int p = 0; p < num_planes; ++p) {
347
6.43k
    const int is_uv = p > 0;
348
6.43k
    const int ss_x = is_uv && cm->seq_params.subsampling_x;
349
6.43k
    const int plane_w =
350
6.43k
        ((frame_w + ss_x) >> ss_x) + 2 * RESTORATION_BORDER_HORZ;
351
6.43k
    const int stride = ALIGN_POWER_OF_TWO(plane_w, 5);
352
6.43k
    const int buf_size = num_stripes * stride * RESTORATION_CTX_VERT << 1;
353
6.43k
    RestorationStripeBoundaries *boundaries = &cm->rst_info[p].boundaries;
354
6.43k
    boundaries->num_stripes = num_stripes;
355
356
6.43k
    if (buf_size != boundaries->stripe_boundary_size ||
357
11
        boundaries->stripe_boundary_above == NULL ||
358
6.42k
        boundaries->stripe_boundary_below == NULL) {
359
6.42k
      avm_free(boundaries->stripe_boundary_above);
360
6.42k
      avm_free(boundaries->stripe_boundary_below);
361
6.42k
      CHECK_MEM_ERROR(cm, boundaries->stripe_boundary_above,
362
6.42k
                      avm_memalign(32, buf_size));
363
6.42k
      CHECK_MEM_ERROR(cm, boundaries->stripe_boundary_below,
364
6.42k
                      avm_memalign(32, buf_size));
365
366
6.42k
      boundaries->stripe_boundary_size = buf_size;
367
6.42k
    }
368
6.43k
    boundaries->stripe_boundary_stride = stride;
369
6.43k
  }
370
5.49k
}
371
372
10.8k
void av2_free_restoration_buffers(AV2_COMMON *cm) {
373
10.8k
  int p;
374
43.4k
  for (p = 0; p < MAX_MB_PLANE; ++p)
375
32.6k
    av2_free_restoration_struct(&cm->rst_info[p]);
376
10.8k
  avm_free(cm->rlbs);
377
10.8k
  cm->rlbs = NULL;
378
10.8k
  avm_free(cm->lru_stripe_buf);
379
10.8k
  cm->lru_stripe_buf = NULL;
380
43.4k
  for (p = 0; p < MAX_MB_PLANE; ++p) {
381
32.6k
    RestorationStripeBoundaries *boundaries = &cm->rst_info[p].boundaries;
382
32.6k
    avm_free(boundaries->stripe_boundary_above);
383
32.6k
    avm_free(boundaries->stripe_boundary_below);
384
32.6k
    boundaries->stripe_boundary_above = NULL;
385
32.6k
    boundaries->stripe_boundary_below = NULL;
386
32.6k
  }
387
10.8k
  free_frame_filter_dictionary(cm);
388
10.8k
  avm_free_frame_buffer(&cm->rst_frame);
389
10.8k
}
390
391
18.4k
void av2_free_above_context_buffers(CommonContexts *above_contexts) {
392
18.4k
  int i;
393
18.4k
  const int num_planes = above_contexts->num_planes;
394
395
36.7k
  for (int tile_row = 0; tile_row < above_contexts->num_tile_rows; tile_row++) {
396
72.8k
    for (i = 0; i < num_planes; i++) {
397
54.5k
      avm_free(above_contexts->entropy[i][tile_row]);
398
54.5k
      above_contexts->entropy[i][tile_row] = NULL;
399
54.5k
      avm_free(above_contexts->partition[i][tile_row]);
400
54.5k
      above_contexts->partition[i][tile_row] = NULL;
401
54.5k
    }
402
18.3k
  }
403
41.2k
  for (i = 0; i < num_planes; i++) {
404
22.7k
    avm_free(above_contexts->entropy[i]);
405
22.7k
    above_contexts->entropy[i] = NULL;
406
22.7k
    avm_free(above_contexts->partition[i]);
407
22.7k
    above_contexts->partition[i] = NULL;
408
22.7k
  }
409
410
18.4k
  above_contexts->num_tile_rows = 0;
411
18.4k
  above_contexts->num_mi_cols = 0;
412
18.4k
  above_contexts->num_planes = 0;
413
18.4k
}
414
415
18.4k
static void free_sbi(CommonSBInfoParams *sbi_params) {
416
1.09M
  for (int i = 0; i < sbi_params->sbi_alloc_size; ++i) {
417
1.08M
    av2_free_ptree_recursive(sbi_params->sbi_grid_base[i].ptree_root[0]);
418
1.08M
    av2_free_ptree_recursive(sbi_params->sbi_grid_base[i].ptree_root[1]);
419
1.08M
  }
420
421
18.4k
  avm_free(sbi_params->sbi_grid_base);
422
18.4k
  sbi_params->sbi_grid_base = NULL;
423
18.4k
  sbi_params->sbi_alloc_size = 0;
424
18.4k
}
425
426
10.8k
void av2_free_context_buffers(AV2_COMMON *cm) {
427
10.8k
  cm->mi_params.free_mi(&cm->mi_params);
428
10.8k
  free_sbi(&cm->sbi_params);
429
430
10.8k
  av2_free_above_context_buffers(&cm->above_contexts);
431
10.8k
}
432
433
int av2_alloc_above_context_buffers(CommonContexts *above_contexts,
434
                                    int num_tile_rows, int num_mi_cols,
435
7.59k
                                    int num_planes) {
436
7.59k
  const int aligned_mi_cols =
437
7.59k
      ALIGN_POWER_OF_TWO(num_mi_cols, MAX_MIB_SIZE_LOG2);
438
439
  // Allocate above context buffers
440
7.59k
  above_contexts->num_tile_rows = num_tile_rows;
441
7.59k
  above_contexts->num_mi_cols = aligned_mi_cols;
442
7.59k
  above_contexts->num_planes = num_planes;
443
30.3k
  for (int plane_idx = 0; plane_idx < num_planes; plane_idx++) {
444
22.7k
    above_contexts->entropy[plane_idx] = (ENTROPY_CONTEXT **)avm_calloc(
445
22.7k
        num_tile_rows, sizeof(above_contexts->entropy[0]));
446
22.7k
    if (!above_contexts->entropy[plane_idx]) return 1;
447
22.7k
    above_contexts->partition[plane_idx] = (PARTITION_CONTEXT **)avm_calloc(
448
22.7k
        num_tile_rows, sizeof(above_contexts->partition[plane_idx]));
449
22.7k
    if (!above_contexts->partition[plane_idx]) return 1;
450
22.7k
  }
451
452
25.9k
  for (int tile_row = 0; tile_row < num_tile_rows; tile_row++) {
453
72.8k
    for (int plane_idx = 0; plane_idx < num_planes; plane_idx++) {
454
54.5k
      above_contexts->entropy[plane_idx][tile_row] =
455
54.5k
          (ENTROPY_CONTEXT *)avm_calloc(
456
54.5k
              aligned_mi_cols, sizeof(*above_contexts->entropy[0][tile_row]));
457
54.5k
      if (!above_contexts->entropy[plane_idx][tile_row]) return 1;
458
54.5k
      above_contexts->partition[plane_idx][tile_row] =
459
54.5k
          (PARTITION_CONTEXT *)avm_calloc(
460
54.5k
              aligned_mi_cols,
461
54.5k
              sizeof(*above_contexts->partition[plane_idx][tile_row]));
462
54.5k
      if (!above_contexts->partition[plane_idx][tile_row]) return 1;
463
54.5k
    }
464
18.3k
  }
465
466
7.59k
  return 0;
467
7.59k
}
468
469
// Allocate the dynamically allocated arrays in 'mi_params' assuming
470
// 'mi_params->set_mb_mi()' was already called earlier to initialize the rest of
471
// the struct members.
472
static int alloc_mi(CommonModeInfoParams *mi_params, AV2_COMMON *cm,
473
7.62k
                    int height) {
474
7.62k
  const int aligned_mi_rows = calc_mi_size(mi_params->mi_rows);
475
7.62k
  const int mi_grid_size = mi_params->mi_stride * aligned_mi_rows;
476
7.62k
  const int alloc_size_1d = mi_size_wide[mi_params->mi_alloc_bsize];
477
7.62k
  const int alloc_mi_size =
478
7.62k
      mi_params->mi_alloc_stride * (aligned_mi_rows / alloc_size_1d);
479
480
7.62k
  if (mi_params->mi_alloc_size < alloc_mi_size ||
481
7.61k
      mi_params->mi_grid_size < mi_grid_size) {
482
7.61k
    mi_params->free_mi(mi_params);
483
484
7.61k
    mi_params->mi_alloc =
485
7.61k
        avm_calloc(alloc_mi_size, sizeof(*mi_params->mi_alloc));
486
7.61k
    if (!mi_params->mi_alloc) return 1;
487
7.61k
    mi_params->mi_alloc_size = alloc_mi_size;
488
489
7.61k
    mi_params->mi_grid_base = (MB_MODE_INFO **)avm_calloc(
490
7.61k
        mi_grid_size, sizeof(*mi_params->mi_grid_base));
491
7.61k
    if (!mi_params->mi_grid_base) return 1;
492
7.61k
    mi_params->mi_grid_size = mi_grid_size;
493
7.61k
    av2_alloc_txk_skip_array(mi_params, cm);
494
7.61k
    av2_alloc_class_id_array(mi_params, cm, height);
495
7.61k
    mi_params->mi_alloc_sub =
496
7.61k
        avm_calloc(alloc_mi_size, sizeof(*mi_params->mi_alloc_sub));
497
7.61k
    if (!mi_params->mi_alloc_sub) return 1;
498
7.61k
    mi_params->submi_grid_base = (SUBMB_INFO **)avm_calloc(
499
7.61k
        mi_grid_size, sizeof(*mi_params->submi_grid_base));
500
7.61k
    if (!mi_params->submi_grid_base) return 1;
501
502
7.61k
    mi_params->tx_type_map =
503
7.61k
        avm_calloc(mi_grid_size, sizeof(*mi_params->tx_type_map));
504
7.61k
    if (!mi_params->tx_type_map) return 1;
505
7.61k
    mi_params->cctx_type_map =
506
7.61k
        avm_calloc(mi_grid_size, sizeof(*mi_params->cctx_type_map));
507
7.61k
    if (!mi_params->cctx_type_map) return 1;
508
7.61k
  } else {
509
    // Set only the strides corresponding to the current frame dims
510
5
    av2_set_txk_skip_array_stride(mi_params, cm);
511
5
    av2_set_class_id_array_stride(mi_params, cm, height);
512
5
  }
513
514
7.61k
  return 0;
515
7.62k
}
516
517
15.2k
static void set_sb_si(AV2_COMMON *cm) {
518
15.2k
  CommonSBInfoParams *const sbi_params = &cm->sbi_params;
519
15.2k
  const int mib_size_log2 = cm->mib_size_log2;
520
15.2k
  sbi_params->sb_cols =
521
15.2k
      ALIGN_POWER_OF_TWO(cm->mi_params.mi_cols, mib_size_log2) >> mib_size_log2;
522
15.2k
  sbi_params->sb_rows =
523
15.2k
      ALIGN_POWER_OF_TWO(cm->mi_params.mi_rows, mib_size_log2) >> mib_size_log2;
524
15.2k
  sbi_params->sbi_stride = cm->mi_params.mi_stride >> mib_size_log2;
525
15.2k
}
526
527
15.2k
static int alloc_sbi(CommonSBInfoParams *sbi_params) {
528
15.2k
  const int sbi_size = sbi_params->sbi_stride * sbi_params->sb_rows;
529
530
15.2k
  if (sbi_params->sbi_alloc_size < sbi_size) {
531
7.61k
    free_sbi(sbi_params);
532
7.61k
    sbi_params->sbi_grid_base =
533
7.61k
        avm_calloc(sbi_size, sizeof(*sbi_params->sbi_grid_base));
534
535
7.61k
    if (!sbi_params->sbi_grid_base) return 1;
536
537
7.61k
    sbi_params->sbi_alloc_size = sbi_size;
538
1.08M
    for (int i = 0; i < sbi_size; ++i) {
539
1.08M
      sbi_params->sbi_grid_base[i].ptree_root[0] = NULL;
540
1.08M
      sbi_params->sbi_grid_base[i].ptree_root[1] = NULL;
541
1.08M
      sbi_params->sbi_grid_base[i].sb_active_mode = BRU_ACTIVE_SB;
542
1.08M
    }
543
7.61k
  }
544
545
15.2k
  return 0;
546
15.2k
}
547
548
15.2k
int av2_alloc_superblock_info_buffers(AV2_COMMON *cm) {
549
15.2k
  CommonSBInfoParams *const sbi_params = &cm->sbi_params;
550
15.2k
  set_sb_si(cm);
551
15.2k
  return alloc_sbi(sbi_params);
552
15.2k
}
553
554
7.62k
int av2_alloc_context_buffers(AV2_COMMON *cm, int width, int height) {
555
7.62k
  CommonModeInfoParams *const mi_params = &cm->mi_params;
556
7.62k
  mi_params->set_mb_mi(mi_params, width, height);
557
7.62k
  if (alloc_mi(mi_params, cm, height)) goto fail;
558
559
7.61k
  if (av2_alloc_superblock_info_buffers(cm)) goto fail;
560
561
7.61k
  return 0;
562
563
3
fail:
564
  // clear the mi_* values to force a realloc on resync
565
3
  mi_params->set_mb_mi(mi_params, 0, 0);
566
3
  av2_free_context_buffers(cm);
567
3
  return 1;
568
7.61k
}
569
570
10.8k
void av2_remove_common(AV2_COMMON *cm) {
571
10.8k
  av2_free_context_buffers(cm);
572
573
10.8k
  avm_free(cm->fc);
574
10.8k
  cm->fc = NULL;
575
10.8k
  avm_free(cm->default_frame_context);
576
10.8k
  cm->default_frame_context = NULL;
577
10.8k
}
578
579
7.62k
void av2_init_mi_buffers(CommonModeInfoParams *mi_params) {
580
7.62k
  mi_params->setup_mi(mi_params);
581
7.62k
}