• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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