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 #ifndef AOM_AV1_COMMON_PRED_COMMON_H_
13 #define AOM_AV1_COMMON_PRED_COMMON_H_
14
15 #include "av1/common/blockd.h"
16 #include "av1/common/mvref_common.h"
17 #include "av1/common/onyxc_int.h"
18 #include "aom_dsp/aom_dsp_common.h"
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23
get_segment_id(const AV1_COMMON * const cm,const uint8_t * segment_ids,BLOCK_SIZE bsize,int mi_row,int mi_col)24 static INLINE int get_segment_id(const AV1_COMMON *const cm,
25 const uint8_t *segment_ids, BLOCK_SIZE bsize,
26 int mi_row, int mi_col) {
27 const int mi_offset = mi_row * cm->mi_cols + mi_col;
28 const int bw = mi_size_wide[bsize];
29 const int bh = mi_size_high[bsize];
30 const int xmis = AOMMIN(cm->mi_cols - mi_col, bw);
31 const int ymis = AOMMIN(cm->mi_rows - mi_row, bh);
32 int x, y, segment_id = MAX_SEGMENTS;
33
34 for (y = 0; y < ymis; ++y)
35 for (x = 0; x < xmis; ++x)
36 segment_id =
37 AOMMIN(segment_id, segment_ids[mi_offset + y * cm->mi_cols + x]);
38
39 assert(segment_id >= 0 && segment_id < MAX_SEGMENTS);
40 return segment_id;
41 }
42
av1_get_spatial_seg_pred(const AV1_COMMON * const cm,const MACROBLOCKD * const xd,int mi_row,int mi_col,int * cdf_index)43 static INLINE int av1_get_spatial_seg_pred(const AV1_COMMON *const cm,
44 const MACROBLOCKD *const xd,
45 int mi_row, int mi_col,
46 int *cdf_index) {
47 int prev_ul = -1; // top left segment_id
48 int prev_l = -1; // left segment_id
49 int prev_u = -1; // top segment_id
50 if ((xd->up_available) && (xd->left_available)) {
51 prev_ul = get_segment_id(cm, cm->cur_frame->seg_map, BLOCK_4X4, mi_row - 1,
52 mi_col - 1);
53 }
54 if (xd->up_available) {
55 prev_u = get_segment_id(cm, cm->cur_frame->seg_map, BLOCK_4X4, mi_row - 1,
56 mi_col - 0);
57 }
58 if (xd->left_available) {
59 prev_l = get_segment_id(cm, cm->cur_frame->seg_map, BLOCK_4X4, mi_row - 0,
60 mi_col - 1);
61 }
62 // This property follows from the fact that get_segment_id() returns a
63 // nonnegative value. This allows us to test for all edge cases with a simple
64 // prev_ul < 0 check.
65 assert(IMPLIES(prev_ul >= 0, prev_u >= 0 && prev_l >= 0));
66
67 // Pick CDF index based on number of matching/out-of-bounds segment IDs.
68 if (prev_ul < 0) /* Edge cases */
69 *cdf_index = 0;
70 else if ((prev_ul == prev_u) && (prev_ul == prev_l))
71 *cdf_index = 2;
72 else if ((prev_ul == prev_u) || (prev_ul == prev_l) || (prev_u == prev_l))
73 *cdf_index = 1;
74 else
75 *cdf_index = 0;
76
77 // If 2 or more are identical returns that as predictor, otherwise prev_l.
78 if (prev_u == -1) // edge case
79 return prev_l == -1 ? 0 : prev_l;
80 if (prev_l == -1) // edge case
81 return prev_u;
82 return (prev_ul == prev_u) ? prev_u : prev_l;
83 }
84
av1_get_pred_context_seg_id(const MACROBLOCKD * xd)85 static INLINE int av1_get_pred_context_seg_id(const MACROBLOCKD *xd) {
86 const MB_MODE_INFO *const above_mi = xd->above_mbmi;
87 const MB_MODE_INFO *const left_mi = xd->left_mbmi;
88 const int above_sip = (above_mi != NULL) ? above_mi->seg_id_predicted : 0;
89 const int left_sip = (left_mi != NULL) ? left_mi->seg_id_predicted : 0;
90
91 return above_sip + left_sip;
92 }
93
get_comp_index_context(const AV1_COMMON * cm,const MACROBLOCKD * xd)94 static INLINE int get_comp_index_context(const AV1_COMMON *cm,
95 const MACROBLOCKD *xd) {
96 MB_MODE_INFO *mbmi = xd->mi[0];
97 const RefCntBuffer *const bck_buf = get_ref_frame_buf(cm, mbmi->ref_frame[0]);
98 const RefCntBuffer *const fwd_buf = get_ref_frame_buf(cm, mbmi->ref_frame[1]);
99 int bck_frame_index = 0, fwd_frame_index = 0;
100 int cur_frame_index = cm->cur_frame->order_hint;
101
102 if (bck_buf != NULL) bck_frame_index = bck_buf->order_hint;
103 if (fwd_buf != NULL) fwd_frame_index = fwd_buf->order_hint;
104
105 int fwd = abs(get_relative_dist(&cm->seq_params.order_hint_info,
106 fwd_frame_index, cur_frame_index));
107 int bck = abs(get_relative_dist(&cm->seq_params.order_hint_info,
108 cur_frame_index, bck_frame_index));
109
110 const MB_MODE_INFO *const above_mi = xd->above_mbmi;
111 const MB_MODE_INFO *const left_mi = xd->left_mbmi;
112
113 int above_ctx = 0, left_ctx = 0;
114 const int offset = (fwd == bck);
115
116 if (above_mi != NULL) {
117 if (has_second_ref(above_mi))
118 above_ctx = above_mi->compound_idx;
119 else if (above_mi->ref_frame[0] == ALTREF_FRAME)
120 above_ctx = 1;
121 }
122
123 if (left_mi != NULL) {
124 if (has_second_ref(left_mi))
125 left_ctx = left_mi->compound_idx;
126 else if (left_mi->ref_frame[0] == ALTREF_FRAME)
127 left_ctx = 1;
128 }
129
130 return above_ctx + left_ctx + 3 * offset;
131 }
132
get_comp_group_idx_context(const MACROBLOCKD * xd)133 static INLINE int get_comp_group_idx_context(const MACROBLOCKD *xd) {
134 const MB_MODE_INFO *const above_mi = xd->above_mbmi;
135 const MB_MODE_INFO *const left_mi = xd->left_mbmi;
136 int above_ctx = 0, left_ctx = 0;
137
138 if (above_mi) {
139 if (has_second_ref(above_mi))
140 above_ctx = above_mi->comp_group_idx;
141 else if (above_mi->ref_frame[0] == ALTREF_FRAME)
142 above_ctx = 3;
143 }
144 if (left_mi) {
145 if (has_second_ref(left_mi))
146 left_ctx = left_mi->comp_group_idx;
147 else if (left_mi->ref_frame[0] == ALTREF_FRAME)
148 left_ctx = 3;
149 }
150
151 return AOMMIN(5, above_ctx + left_ctx);
152 }
153
av1_get_pred_cdf_seg_id(struct segmentation_probs * segp,const MACROBLOCKD * xd)154 static INLINE aom_cdf_prob *av1_get_pred_cdf_seg_id(
155 struct segmentation_probs *segp, const MACROBLOCKD *xd) {
156 return segp->pred_cdf[av1_get_pred_context_seg_id(xd)];
157 }
158
av1_get_skip_mode_context(const MACROBLOCKD * xd)159 static INLINE int av1_get_skip_mode_context(const MACROBLOCKD *xd) {
160 const MB_MODE_INFO *const above_mi = xd->above_mbmi;
161 const MB_MODE_INFO *const left_mi = xd->left_mbmi;
162 const int above_skip_mode = above_mi ? above_mi->skip_mode : 0;
163 const int left_skip_mode = left_mi ? left_mi->skip_mode : 0;
164 return above_skip_mode + left_skip_mode;
165 }
166
av1_get_skip_context(const MACROBLOCKD * xd)167 static INLINE int av1_get_skip_context(const MACROBLOCKD *xd) {
168 const MB_MODE_INFO *const above_mi = xd->above_mbmi;
169 const MB_MODE_INFO *const left_mi = xd->left_mbmi;
170 const int above_skip = above_mi ? above_mi->skip : 0;
171 const int left_skip = left_mi ? left_mi->skip : 0;
172 return above_skip + left_skip;
173 }
174
175 int av1_get_pred_context_switchable_interp(const MACROBLOCKD *xd, int dir);
176
177 // Get a list of palette base colors that are used in the above and left blocks,
178 // referred to as "color cache". The return value is the number of colors in the
179 // cache (<= 2 * PALETTE_MAX_SIZE). The color values are stored in "cache"
180 // in ascending order.
181 int av1_get_palette_cache(const MACROBLOCKD *const xd, int plane,
182 uint16_t *cache);
183
av1_get_palette_bsize_ctx(BLOCK_SIZE bsize)184 static INLINE int av1_get_palette_bsize_ctx(BLOCK_SIZE bsize) {
185 return num_pels_log2_lookup[bsize] - num_pels_log2_lookup[BLOCK_8X8];
186 }
187
av1_get_palette_mode_ctx(const MACROBLOCKD * xd)188 static INLINE int av1_get_palette_mode_ctx(const MACROBLOCKD *xd) {
189 const MB_MODE_INFO *const above_mi = xd->above_mbmi;
190 const MB_MODE_INFO *const left_mi = xd->left_mbmi;
191 int ctx = 0;
192 if (above_mi) ctx += (above_mi->palette_mode_info.palette_size[0] > 0);
193 if (left_mi) ctx += (left_mi->palette_mode_info.palette_size[0] > 0);
194 return ctx;
195 }
196
197 int av1_get_intra_inter_context(const MACROBLOCKD *xd);
198
199 int av1_get_reference_mode_context(const MACROBLOCKD *xd);
200
av1_get_reference_mode_cdf(const MACROBLOCKD * xd)201 static INLINE aom_cdf_prob *av1_get_reference_mode_cdf(const MACROBLOCKD *xd) {
202 return xd->tile_ctx->comp_inter_cdf[av1_get_reference_mode_context(xd)];
203 }
204
205 int av1_get_comp_reference_type_context(const MACROBLOCKD *xd);
206
207 // == Uni-directional contexts ==
208
209 int av1_get_pred_context_uni_comp_ref_p(const MACROBLOCKD *xd);
210
211 int av1_get_pred_context_uni_comp_ref_p1(const MACROBLOCKD *xd);
212
213 int av1_get_pred_context_uni_comp_ref_p2(const MACROBLOCKD *xd);
214
av1_get_comp_reference_type_cdf(const MACROBLOCKD * xd)215 static INLINE aom_cdf_prob *av1_get_comp_reference_type_cdf(
216 const MACROBLOCKD *xd) {
217 const int pred_context = av1_get_comp_reference_type_context(xd);
218 return xd->tile_ctx->comp_ref_type_cdf[pred_context];
219 }
220
av1_get_pred_cdf_uni_comp_ref_p(const MACROBLOCKD * xd)221 static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p(
222 const MACROBLOCKD *xd) {
223 const int pred_context = av1_get_pred_context_uni_comp_ref_p(xd);
224 return xd->tile_ctx->uni_comp_ref_cdf[pred_context][0];
225 }
226
av1_get_pred_cdf_uni_comp_ref_p1(const MACROBLOCKD * xd)227 static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p1(
228 const MACROBLOCKD *xd) {
229 const int pred_context = av1_get_pred_context_uni_comp_ref_p1(xd);
230 return xd->tile_ctx->uni_comp_ref_cdf[pred_context][1];
231 }
232
av1_get_pred_cdf_uni_comp_ref_p2(const MACROBLOCKD * xd)233 static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p2(
234 const MACROBLOCKD *xd) {
235 const int pred_context = av1_get_pred_context_uni_comp_ref_p2(xd);
236 return xd->tile_ctx->uni_comp_ref_cdf[pred_context][2];
237 }
238
239 // == Bi-directional contexts ==
240
241 int av1_get_pred_context_comp_ref_p(const MACROBLOCKD *xd);
242
243 int av1_get_pred_context_comp_ref_p1(const MACROBLOCKD *xd);
244
245 int av1_get_pred_context_comp_ref_p2(const MACROBLOCKD *xd);
246
247 int av1_get_pred_context_comp_bwdref_p(const MACROBLOCKD *xd);
248
249 int av1_get_pred_context_comp_bwdref_p1(const MACROBLOCKD *xd);
250
av1_get_pred_cdf_comp_ref_p(const MACROBLOCKD * xd)251 static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p(const MACROBLOCKD *xd) {
252 const int pred_context = av1_get_pred_context_comp_ref_p(xd);
253 return xd->tile_ctx->comp_ref_cdf[pred_context][0];
254 }
255
av1_get_pred_cdf_comp_ref_p1(const MACROBLOCKD * xd)256 static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p1(
257 const MACROBLOCKD *xd) {
258 const int pred_context = av1_get_pred_context_comp_ref_p1(xd);
259 return xd->tile_ctx->comp_ref_cdf[pred_context][1];
260 }
261
av1_get_pred_cdf_comp_ref_p2(const MACROBLOCKD * xd)262 static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p2(
263 const MACROBLOCKD *xd) {
264 const int pred_context = av1_get_pred_context_comp_ref_p2(xd);
265 return xd->tile_ctx->comp_ref_cdf[pred_context][2];
266 }
267
av1_get_pred_cdf_comp_bwdref_p(const MACROBLOCKD * xd)268 static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_bwdref_p(
269 const MACROBLOCKD *xd) {
270 const int pred_context = av1_get_pred_context_comp_bwdref_p(xd);
271 return xd->tile_ctx->comp_bwdref_cdf[pred_context][0];
272 }
273
av1_get_pred_cdf_comp_bwdref_p1(const MACROBLOCKD * xd)274 static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_bwdref_p1(
275 const MACROBLOCKD *xd) {
276 const int pred_context = av1_get_pred_context_comp_bwdref_p1(xd);
277 return xd->tile_ctx->comp_bwdref_cdf[pred_context][1];
278 }
279
280 // == Single contexts ==
281
282 int av1_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
283
284 int av1_get_pred_context_single_ref_p2(const MACROBLOCKD *xd);
285
286 int av1_get_pred_context_single_ref_p3(const MACROBLOCKD *xd);
287
288 int av1_get_pred_context_single_ref_p4(const MACROBLOCKD *xd);
289
290 int av1_get_pred_context_single_ref_p5(const MACROBLOCKD *xd);
291
292 int av1_get_pred_context_single_ref_p6(const MACROBLOCKD *xd);
293
av1_get_pred_cdf_single_ref_p1(const MACROBLOCKD * xd)294 static INLINE aom_cdf_prob *av1_get_pred_cdf_single_ref_p1(
295 const MACROBLOCKD *xd) {
296 return xd->tile_ctx
297 ->single_ref_cdf[av1_get_pred_context_single_ref_p1(xd)][0];
298 }
av1_get_pred_cdf_single_ref_p2(const MACROBLOCKD * xd)299 static INLINE aom_cdf_prob *av1_get_pred_cdf_single_ref_p2(
300 const MACROBLOCKD *xd) {
301 return xd->tile_ctx
302 ->single_ref_cdf[av1_get_pred_context_single_ref_p2(xd)][1];
303 }
av1_get_pred_cdf_single_ref_p3(const MACROBLOCKD * xd)304 static INLINE aom_cdf_prob *av1_get_pred_cdf_single_ref_p3(
305 const MACROBLOCKD *xd) {
306 return xd->tile_ctx
307 ->single_ref_cdf[av1_get_pred_context_single_ref_p3(xd)][2];
308 }
av1_get_pred_cdf_single_ref_p4(const MACROBLOCKD * xd)309 static INLINE aom_cdf_prob *av1_get_pred_cdf_single_ref_p4(
310 const MACROBLOCKD *xd) {
311 return xd->tile_ctx
312 ->single_ref_cdf[av1_get_pred_context_single_ref_p4(xd)][3];
313 }
av1_get_pred_cdf_single_ref_p5(const MACROBLOCKD * xd)314 static INLINE aom_cdf_prob *av1_get_pred_cdf_single_ref_p5(
315 const MACROBLOCKD *xd) {
316 return xd->tile_ctx
317 ->single_ref_cdf[av1_get_pred_context_single_ref_p5(xd)][4];
318 }
av1_get_pred_cdf_single_ref_p6(const MACROBLOCKD * xd)319 static INLINE aom_cdf_prob *av1_get_pred_cdf_single_ref_p6(
320 const MACROBLOCKD *xd) {
321 return xd->tile_ctx
322 ->single_ref_cdf[av1_get_pred_context_single_ref_p6(xd)][5];
323 }
324
325 // Returns a context number for the given MB prediction signal
326 // The mode info data structure has a one element border above and to the
327 // left of the entries corresponding to real blocks.
328 // The prediction flags in these dummy entries are initialized to 0.
get_tx_size_context(const MACROBLOCKD * xd)329 static INLINE int get_tx_size_context(const MACROBLOCKD *xd) {
330 const MB_MODE_INFO *mbmi = xd->mi[0];
331 const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
332 const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
333 const TX_SIZE max_tx_size = max_txsize_rect_lookup[mbmi->sb_type];
334 const int max_tx_wide = tx_size_wide[max_tx_size];
335 const int max_tx_high = tx_size_high[max_tx_size];
336 const int has_above = xd->up_available;
337 const int has_left = xd->left_available;
338
339 int above = xd->above_txfm_context[0] >= max_tx_wide;
340 int left = xd->left_txfm_context[0] >= max_tx_high;
341
342 if (has_above)
343 if (is_inter_block(above_mbmi))
344 above = block_size_wide[above_mbmi->sb_type] >= max_tx_wide;
345
346 if (has_left)
347 if (is_inter_block(left_mbmi))
348 left = block_size_high[left_mbmi->sb_type] >= max_tx_high;
349
350 if (has_above && has_left)
351 return (above + left);
352 else if (has_above)
353 return above;
354 else if (has_left)
355 return left;
356 else
357 return 0;
358 }
359
360 #ifdef __cplusplus
361 } // extern "C"
362 #endif
363
364 #endif // AOM_AV1_COMMON_PRED_COMMON_H_
365