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