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