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