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