Home | History | Annotate | Download | only in common
      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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 }
    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 }
    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 }
    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 }
    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 }
    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.
    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