• 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 #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