1 /*
2 *
3 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
4 *
5 * This source code is subject to the terms of the BSD 2 Clause License and
6 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
7 * was not distributed with this source code in the LICENSE file, you can
8 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
9 * Media Patent License 1.0 was not distributed with this source code in the
10 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
11 */
12
13 #include "config/aom_config.h"
14
15 #include "aom_mem/aom_mem.h"
16
17 #include "av1/common/alloccommon.h"
18 #include "av1/common/blockd.h"
19 #include "av1/common/entropymode.h"
20 #include "av1/common/entropymv.h"
21 #include "av1/common/onyxc_int.h"
22
av1_get_MBs(int width,int height)23 int av1_get_MBs(int width, int height) {
24 const int aligned_width = ALIGN_POWER_OF_TWO(width, 3);
25 const int aligned_height = ALIGN_POWER_OF_TWO(height, 3);
26 const int mi_cols = aligned_width >> MI_SIZE_LOG2;
27 const int mi_rows = aligned_height >> MI_SIZE_LOG2;
28
29 const int mb_cols = (mi_cols + 2) >> 2;
30 const int mb_rows = (mi_rows + 2) >> 2;
31 return mb_rows * mb_cols;
32 }
33
34 #if LOOP_FILTER_BITMASK
alloc_loop_filter_mask(AV1_COMMON * cm)35 static int alloc_loop_filter_mask(AV1_COMMON *cm) {
36 aom_free(cm->lf.lfm);
37 cm->lf.lfm = NULL;
38
39 // Each lfm holds bit masks for all the 4x4 blocks in a max
40 // 64x64 (128x128 for ext_partitions) region. The stride
41 // and rows are rounded up / truncated to a multiple of 16
42 // (32 for ext_partition).
43 cm->lf.lfm_stride = (cm->mi_cols + (MI_SIZE_64X64 - 1)) >> MIN_MIB_SIZE_LOG2;
44 cm->lf.lfm_num = ((cm->mi_rows + (MI_SIZE_64X64 - 1)) >> MIN_MIB_SIZE_LOG2) *
45 cm->lf.lfm_stride;
46 cm->lf.lfm =
47 (LoopFilterMask *)aom_calloc(cm->lf.lfm_num, sizeof(*cm->lf.lfm));
48 if (!cm->lf.lfm) return 1;
49
50 unsigned int i;
51 for (i = 0; i < cm->lf.lfm_num; ++i) av1_zero(cm->lf.lfm[i]);
52
53 return 0;
54 }
55
free_loop_filter_mask(AV1_COMMON * cm)56 static void free_loop_filter_mask(AV1_COMMON *cm) {
57 if (cm->lf.lfm == NULL) return;
58
59 aom_free(cm->lf.lfm);
60 cm->lf.lfm = NULL;
61 cm->lf.lfm_num = 0;
62 cm->lf.lfm_stride = 0;
63 }
64 #endif
65
av1_set_mb_mi(AV1_COMMON * cm,int width,int height)66 void av1_set_mb_mi(AV1_COMMON *cm, int width, int height) {
67 // Ensure that the decoded width and height are both multiples of
68 // 8 luma pixels (note: this may only be a multiple of 4 chroma pixels if
69 // subsampling is used).
70 // This simplifies the implementation of various experiments,
71 // eg. cdef, which operates on units of 8x8 luma pixels.
72 const int aligned_width = ALIGN_POWER_OF_TWO(width, 3);
73 const int aligned_height = ALIGN_POWER_OF_TWO(height, 3);
74
75 cm->mi_cols = aligned_width >> MI_SIZE_LOG2;
76 cm->mi_rows = aligned_height >> MI_SIZE_LOG2;
77 cm->mi_stride = calc_mi_size(cm->mi_cols);
78
79 cm->mb_cols = (cm->mi_cols + 2) >> 2;
80 cm->mb_rows = (cm->mi_rows + 2) >> 2;
81 cm->MBs = cm->mb_rows * cm->mb_cols;
82
83 #if LOOP_FILTER_BITMASK
84 alloc_loop_filter_mask(cm);
85 #endif
86 }
87
av1_free_ref_frame_buffers(BufferPool * pool)88 void av1_free_ref_frame_buffers(BufferPool *pool) {
89 int i;
90
91 for (i = 0; i < FRAME_BUFFERS; ++i) {
92 if (pool->frame_bufs[i].ref_count > 0 &&
93 pool->frame_bufs[i].raw_frame_buffer.data != NULL) {
94 pool->release_fb_cb(pool->cb_priv, &pool->frame_bufs[i].raw_frame_buffer);
95 pool->frame_bufs[i].raw_frame_buffer.data = NULL;
96 pool->frame_bufs[i].raw_frame_buffer.size = 0;
97 pool->frame_bufs[i].raw_frame_buffer.priv = NULL;
98 pool->frame_bufs[i].ref_count = 0;
99 }
100 aom_free(pool->frame_bufs[i].mvs);
101 pool->frame_bufs[i].mvs = NULL;
102 aom_free(pool->frame_bufs[i].seg_map);
103 pool->frame_bufs[i].seg_map = NULL;
104 aom_free_frame_buffer(&pool->frame_bufs[i].buf);
105 }
106 }
107
108 // Assumes cm->rst_info[p].restoration_unit_size is already initialized
av1_alloc_restoration_buffers(AV1_COMMON * cm)109 void av1_alloc_restoration_buffers(AV1_COMMON *cm) {
110 const int num_planes = av1_num_planes(cm);
111 for (int p = 0; p < num_planes; ++p)
112 av1_alloc_restoration_struct(cm, &cm->rst_info[p], p > 0);
113
114 if (cm->rst_tmpbuf == NULL) {
115 CHECK_MEM_ERROR(cm, cm->rst_tmpbuf,
116 (int32_t *)aom_memalign(16, RESTORATION_TMPBUF_SIZE));
117 }
118
119 if (cm->rlbs == NULL) {
120 CHECK_MEM_ERROR(cm, cm->rlbs, aom_malloc(sizeof(RestorationLineBuffers)));
121 }
122
123 // For striped loop restoration, we divide each row of tiles into "stripes",
124 // of height 64 luma pixels but with an offset by RESTORATION_UNIT_OFFSET
125 // luma pixels to match the output from CDEF. We will need to store 2 *
126 // RESTORATION_CTX_VERT lines of data for each stripe, and also need to be
127 // able to quickly answer the question "Where is the <n>'th stripe for tile
128 // row <m>?" To make that efficient, we generate the rst_last_stripe array.
129 int num_stripes = 0;
130 for (int i = 0; i < cm->tile_rows; ++i) {
131 TileInfo tile_info;
132 av1_tile_set_row(&tile_info, cm, i);
133 const int mi_h = tile_info.mi_row_end - tile_info.mi_row_start;
134 const int ext_h = RESTORATION_UNIT_OFFSET + (mi_h << MI_SIZE_LOG2);
135 const int tile_stripes = (ext_h + 63) / 64;
136 num_stripes += tile_stripes;
137 }
138
139 // Now we need to allocate enough space to store the line buffers for the
140 // stripes
141 const int frame_w = cm->superres_upscaled_width;
142 const int use_highbd = cm->seq_params.use_highbitdepth;
143
144 for (int p = 0; p < num_planes; ++p) {
145 const int is_uv = p > 0;
146 const int ss_x = is_uv && cm->seq_params.subsampling_x;
147 const int plane_w = ((frame_w + ss_x) >> ss_x) + 2 * RESTORATION_EXTRA_HORZ;
148 const int stride = ALIGN_POWER_OF_TWO(plane_w, 5);
149 const int buf_size = num_stripes * stride * RESTORATION_CTX_VERT
150 << use_highbd;
151 RestorationStripeBoundaries *boundaries = &cm->rst_info[p].boundaries;
152
153 if (buf_size != boundaries->stripe_boundary_size ||
154 boundaries->stripe_boundary_above == NULL ||
155 boundaries->stripe_boundary_below == NULL) {
156 aom_free(boundaries->stripe_boundary_above);
157 aom_free(boundaries->stripe_boundary_below);
158
159 CHECK_MEM_ERROR(cm, boundaries->stripe_boundary_above,
160 (uint8_t *)aom_memalign(32, buf_size));
161 CHECK_MEM_ERROR(cm, boundaries->stripe_boundary_below,
162 (uint8_t *)aom_memalign(32, buf_size));
163
164 boundaries->stripe_boundary_size = buf_size;
165 }
166 boundaries->stripe_boundary_stride = stride;
167 }
168 }
169
av1_free_restoration_buffers(AV1_COMMON * cm)170 void av1_free_restoration_buffers(AV1_COMMON *cm) {
171 int p;
172 for (p = 0; p < MAX_MB_PLANE; ++p)
173 av1_free_restoration_struct(&cm->rst_info[p]);
174 aom_free(cm->rst_tmpbuf);
175 cm->rst_tmpbuf = NULL;
176 aom_free(cm->rlbs);
177 cm->rlbs = NULL;
178 for (p = 0; p < MAX_MB_PLANE; ++p) {
179 RestorationStripeBoundaries *boundaries = &cm->rst_info[p].boundaries;
180 aom_free(boundaries->stripe_boundary_above);
181 aom_free(boundaries->stripe_boundary_below);
182 boundaries->stripe_boundary_above = NULL;
183 boundaries->stripe_boundary_below = NULL;
184 }
185
186 aom_free_frame_buffer(&cm->rst_frame);
187 }
188
av1_free_above_context_buffers(AV1_COMMON * cm,int num_free_above_contexts)189 void av1_free_above_context_buffers(AV1_COMMON *cm,
190 int num_free_above_contexts) {
191 int i;
192 const int num_planes = cm->num_allocated_above_context_planes;
193
194 for (int tile_row = 0; tile_row < num_free_above_contexts; tile_row++) {
195 for (i = 0; i < num_planes; i++) {
196 aom_free(cm->above_context[i][tile_row]);
197 cm->above_context[i][tile_row] = NULL;
198 }
199 aom_free(cm->above_seg_context[tile_row]);
200 cm->above_seg_context[tile_row] = NULL;
201
202 aom_free(cm->above_txfm_context[tile_row]);
203 cm->above_txfm_context[tile_row] = NULL;
204 }
205 for (i = 0; i < num_planes; i++) {
206 aom_free(cm->above_context[i]);
207 cm->above_context[i] = NULL;
208 }
209 aom_free(cm->above_seg_context);
210 cm->above_seg_context = NULL;
211
212 aom_free(cm->above_txfm_context);
213 cm->above_txfm_context = NULL;
214
215 cm->num_allocated_above_contexts = 0;
216 cm->num_allocated_above_context_mi_col = 0;
217 cm->num_allocated_above_context_planes = 0;
218 }
219
av1_free_context_buffers(AV1_COMMON * cm)220 void av1_free_context_buffers(AV1_COMMON *cm) {
221 cm->free_mi(cm);
222
223 av1_free_above_context_buffers(cm, cm->num_allocated_above_contexts);
224
225 #if LOOP_FILTER_BITMASK
226 free_loop_filter_mask(cm);
227 #endif
228 }
229
av1_alloc_above_context_buffers(AV1_COMMON * cm,int num_alloc_above_contexts)230 int av1_alloc_above_context_buffers(AV1_COMMON *cm,
231 int num_alloc_above_contexts) {
232 const int num_planes = av1_num_planes(cm);
233 int plane_idx;
234 const int aligned_mi_cols =
235 ALIGN_POWER_OF_TWO(cm->mi_cols, MAX_MIB_SIZE_LOG2);
236
237 // Allocate above context buffers
238 cm->num_allocated_above_contexts = num_alloc_above_contexts;
239 cm->num_allocated_above_context_mi_col = aligned_mi_cols;
240 cm->num_allocated_above_context_planes = num_planes;
241 for (plane_idx = 0; plane_idx < num_planes; plane_idx++) {
242 cm->above_context[plane_idx] = (ENTROPY_CONTEXT **)aom_calloc(
243 num_alloc_above_contexts, sizeof(cm->above_context[0]));
244 if (!cm->above_context[plane_idx]) return 1;
245 }
246
247 cm->above_seg_context = (PARTITION_CONTEXT **)aom_calloc(
248 num_alloc_above_contexts, sizeof(cm->above_seg_context));
249 if (!cm->above_seg_context) return 1;
250
251 cm->above_txfm_context = (TXFM_CONTEXT **)aom_calloc(
252 num_alloc_above_contexts, sizeof(cm->above_txfm_context));
253 if (!cm->above_txfm_context) return 1;
254
255 for (int tile_row = 0; tile_row < num_alloc_above_contexts; tile_row++) {
256 for (plane_idx = 0; plane_idx < num_planes; plane_idx++) {
257 cm->above_context[plane_idx][tile_row] = (ENTROPY_CONTEXT *)aom_calloc(
258 aligned_mi_cols, sizeof(*cm->above_context[0][tile_row]));
259 if (!cm->above_context[plane_idx][tile_row]) return 1;
260 }
261
262 cm->above_seg_context[tile_row] = (PARTITION_CONTEXT *)aom_calloc(
263 aligned_mi_cols, sizeof(*cm->above_seg_context[tile_row]));
264 if (!cm->above_seg_context[tile_row]) return 1;
265
266 cm->above_txfm_context[tile_row] = (TXFM_CONTEXT *)aom_calloc(
267 aligned_mi_cols, sizeof(*cm->above_txfm_context[tile_row]));
268 if (!cm->above_txfm_context[tile_row]) return 1;
269 }
270
271 return 0;
272 }
273
av1_alloc_context_buffers(AV1_COMMON * cm,int width,int height)274 int av1_alloc_context_buffers(AV1_COMMON *cm, int width, int height) {
275 int new_mi_size;
276
277 av1_set_mb_mi(cm, width, height);
278 new_mi_size = cm->mi_stride * calc_mi_size(cm->mi_rows);
279 if (cm->mi_alloc_size < new_mi_size) {
280 cm->free_mi(cm);
281 if (cm->alloc_mi(cm, new_mi_size)) goto fail;
282 }
283
284 return 0;
285
286 fail:
287 // clear the mi_* values to force a realloc on resync
288 av1_set_mb_mi(cm, 0, 0);
289 av1_free_context_buffers(cm);
290 return 1;
291 }
292
av1_remove_common(AV1_COMMON * cm)293 void av1_remove_common(AV1_COMMON *cm) {
294 av1_free_context_buffers(cm);
295
296 aom_free(cm->fc);
297 cm->fc = NULL;
298 aom_free(cm->default_frame_context);
299 cm->default_frame_context = NULL;
300 }
301
av1_init_context_buffers(AV1_COMMON * cm)302 void av1_init_context_buffers(AV1_COMMON *cm) { cm->setup_mi(cm); }
303