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