pred_common.c 56.3 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11
 */

12 13 14
#include "av1/common/common.h"
#include "av1/common/pred_common.h"
#include "av1/common/reconinter.h"
hui su's avatar
hui su committed
15 16 17
#if CONFIG_EXT_INTRA
#include "av1/common/reconintra.h"
#endif  // CONFIG_EXT_INTRA
18
#include "av1/common/seg_common.h"
Jingning Han's avatar
Jingning Han committed
19 20

// Returns a context number for the given MB prediction signal
21
#if CONFIG_DUAL_FILTER
James Zern's avatar
James Zern committed
22 23 24 25
static InterpFilter get_ref_filter_type(const MODE_INFO *mi,
                                        const MACROBLOCKD *xd, int dir,
                                        MV_REFERENCE_FRAME ref_frame) {
  InterpFilter ref_type = SWITCHABLE_FILTERS;
26 27
  const MB_MODE_INFO *ref_mbmi = &mi->mbmi;
  int use_subpel[2] = {
clang-format's avatar
clang-format committed
28 29
    has_subpel_mv_component(mi, xd, dir),
    has_subpel_mv_component(mi, xd, dir + 2),
30 31 32 33 34 35 36 37 38 39
  };

  if (ref_mbmi->ref_frame[0] == ref_frame && use_subpel[0])
    ref_type = ref_mbmi->interp_filter[(dir & 0x01)];
  else if (ref_mbmi->ref_frame[1] == ref_frame && use_subpel[1])
    ref_type = ref_mbmi->interp_filter[(dir & 0x01) + 2];

  return ref_type;
}

Yaowu Xu's avatar
Yaowu Xu committed
40
int av1_get_pred_context_switchable_interp(const MACROBLOCKD *xd, int dir) {
41
  const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
42 43
  const int ctx_offset =
      (mbmi->ref_frame[1] > INTRA_FRAME) * INTER_FILTER_COMP_OFFSET;
clang-format's avatar
clang-format committed
44 45
  MV_REFERENCE_FRAME ref_frame =
      (dir < 2) ? mbmi->ref_frame[0] : mbmi->ref_frame[1];
46 47 48 49
  // Note:
  // The mode info data structure has a one element border above and to the
  // left of the entries corresponding to real macroblocks.
  // The prediction flags in these dummy entries are initialized to 0.
50
  int filter_type_ctx = ctx_offset + (dir & 0x01) * INTER_FILTER_DIR_OFFSET;
51 52 53
  int left_type = SWITCHABLE_FILTERS;
  int above_type = SWITCHABLE_FILTERS;

54
  if (xd->left_available)
55
    left_type = get_ref_filter_type(xd->mi[-1], xd, dir, ref_frame);
56

57
  if (xd->up_available)
clang-format's avatar
clang-format committed
58 59
    above_type =
        get_ref_filter_type(xd->mi[-xd->mi_stride], xd, dir, ref_frame);
60

61
  if (left_type == above_type) {
62
    filter_type_ctx += left_type;
63 64
  } else if (left_type == SWITCHABLE_FILTERS) {
    assert(above_type != SWITCHABLE_FILTERS);
65
    filter_type_ctx += above_type;
66 67
  } else if (above_type == SWITCHABLE_FILTERS) {
    assert(left_type != SWITCHABLE_FILTERS);
68
    filter_type_ctx += left_type;
69
  } else {
70
    filter_type_ctx += SWITCHABLE_FILTERS;
71
  }
72 73

  return filter_type_ctx;
74 75
}
#else
Yaowu Xu's avatar
Yaowu Xu committed
76
int av1_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
Jingning Han's avatar
Jingning Han committed
77 78
  // Note:
  // The mode info data structure has a one element border above and to the
hui su's avatar
hui su committed
79 80
  // left of the entries corresponding to real macroblocks.
  // The prediction flags in these dummy entries are initialized to 0.
Jingning Han's avatar
Jingning Han committed
81
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
clang-format's avatar
clang-format committed
82 83 84
  const int left_type = xd->left_available && is_inter_block(left_mbmi)
                            ? left_mbmi->interp_filter
                            : SWITCHABLE_FILTERS;
Jingning Han's avatar
Jingning Han committed
85
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
clang-format's avatar
clang-format committed
86 87 88
  const int above_type = xd->up_available && is_inter_block(above_mbmi)
                             ? above_mbmi->interp_filter
                             : SWITCHABLE_FILTERS;
Jingning Han's avatar
Jingning Han committed
89

90
  if (left_type == above_type) {
Jingning Han's avatar
Jingning Han committed
91
    return left_type;
92 93
  } else if (left_type == SWITCHABLE_FILTERS) {
    assert(above_type != SWITCHABLE_FILTERS);
Jingning Han's avatar
Jingning Han committed
94
    return above_type;
95 96
  } else if (above_type == SWITCHABLE_FILTERS) {
    assert(left_type != SWITCHABLE_FILTERS);
Jingning Han's avatar
Jingning Han committed
97
    return left_type;
98
  } else {
Jingning Han's avatar
Jingning Han committed
99
    return SWITCHABLE_FILTERS;
100
  }
Jingning Han's avatar
Jingning Han committed
101
}
102
#endif
Jingning Han's avatar
Jingning Han committed
103

104
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
105
#if CONFIG_INTRA_INTERP
106 107 108
// Obtain the reference filter type from the above/left neighbor blocks.
static INTRA_FILTER get_ref_intra_filter(const MB_MODE_INFO *ref_mbmi) {
  INTRA_FILTER ref_type = INTRA_FILTERS;
109

110
  if (ref_mbmi->sb_type >= BLOCK_8X8) {
hui su's avatar
hui su committed
111
    const PREDICTION_MODE mode = ref_mbmi->mode;
112
    if (is_inter_block(ref_mbmi)) {
113 114 115
#if CONFIG_DUAL_FILTER
      switch (ref_mbmi->interp_filter[0]) {
#else
116
      switch (ref_mbmi->interp_filter) {
117
#endif
clang-format's avatar
clang-format committed
118 119 120 121 122
        case EIGHTTAP_REGULAR: ref_type = INTRA_FILTER_8TAP; break;
        case EIGHTTAP_SMOOTH: ref_type = INTRA_FILTER_8TAP_SMOOTH; break;
        case MULTITAP_SHARP: ref_type = INTRA_FILTER_8TAP_SHARP; break;
        case BILINEAR: ref_type = INTRA_FILTERS; break;
        default: break;
123 124
      }
    } else {
hui su's avatar
hui su committed
125
      if (av1_is_directional_mode(mode, ref_mbmi->sb_type)) {
hui su's avatar
hui su committed
126 127
        const int p_angle =
            mode_to_angle_map[mode] + ref_mbmi->angle_delta[0] * ANGLE_STEP;
Yaowu Xu's avatar
Yaowu Xu committed
128
        if (av1_is_intra_filter_switchable(p_angle)) {
129
          ref_type = ref_mbmi->intra_filter;
130 131 132 133
        }
      }
    }
  }
134 135
  return ref_type;
}
136

Yaowu Xu's avatar
Yaowu Xu committed
137
int av1_get_pred_context_intra_interp(const MACROBLOCKD *xd) {
138 139
  int left_type = INTRA_FILTERS, above_type = INTRA_FILTERS;

clang-format's avatar
clang-format committed
140
  if (xd->left_available) left_type = get_ref_intra_filter(xd->left_mbmi);
141

clang-format's avatar
clang-format committed
142
  if (xd->up_available) above_type = get_ref_intra_filter(xd->above_mbmi);
143 144 145 146 147 148 149 150 151 152

  if (left_type == above_type)
    return left_type;
  else if (left_type == INTRA_FILTERS && above_type != INTRA_FILTERS)
    return above_type;
  else if (left_type != INTRA_FILTERS && above_type == INTRA_FILTERS)
    return left_type;
  else
    return INTRA_FILTERS;
}
hui su's avatar
hui su committed
153
#endif  // CONFIG_INTRA_INTERP
154 155
#endif  // CONFIG_EXT_INTRA

Jingning Han's avatar
Jingning Han committed
156 157 158 159 160 161 162
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
// 0 - inter/inter, inter/--, --/inter, --/--
// 1 - intra/inter, inter/intra
// 2 - intra/--, --/intra
// 3 - intra/intra
Yaowu Xu's avatar
Yaowu Xu committed
163
int av1_get_intra_inter_context(const MACROBLOCKD *xd) {
Jingning Han's avatar
Jingning Han committed
164 165 166 167 168 169 170 171
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int has_above = xd->up_available;
  const int has_left = xd->left_available;

  if (has_above && has_left) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);
clang-format's avatar
clang-format committed
172
    return left_intra && above_intra ? 3 : left_intra || above_intra;
Jingning Han's avatar
Jingning Han committed
173 174 175 176 177 178 179
  } else if (has_above || has_left) {  // one edge available
    return 2 * !is_inter_block(has_above ? above_mbmi : left_mbmi);
  } else {
    return 0;
  }
}

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
// The compound/single mode info data structure has one element border above and
// to the left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
// 0 - single/single
// 1 - single/--, --/single, --/--
// 2 - single/comp, comp/single
// 3 - comp/comp, comp/--, --/comp
int av1_get_inter_mode_context(const MACROBLOCKD *xd) {
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int has_above = xd->up_available;
  const int has_left = xd->left_available;

  if (has_above && has_left) {  // both edges available (0/2/3)
    const int above_inter_comp_mode = is_inter_compound_mode(above_mbmi->mode);
    const int left_inter_comp_mode = is_inter_compound_mode(left_mbmi->mode);
    return (above_inter_comp_mode && left_inter_comp_mode)
               ? 3
               : (above_inter_comp_mode || left_inter_comp_mode) * 2;
  } else if (has_above || has_left) {  // one edge available (1/3)
    const MB_MODE_INFO *const edge_mbmi = has_above ? above_mbmi : left_mbmi;
    return is_inter_compound_mode(edge_mbmi->mode) ? 3 : 1;
  } else {  // no edge available (1)
    return 1;
  }
}
#endif  // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF

209
#if CONFIG_EXT_REFS
Zoe Liu's avatar
Zoe Liu committed
210 211 212 213 214 215
#define CHECK_BACKWARD_REFS(ref_frame) \
  (((ref_frame) >= BWDREF_FRAME) && ((ref_frame) <= ALTREF_FRAME))
#define IS_BACKWARD_REF_FRAME(ref_frame) CHECK_BACKWARD_REFS(ref_frame)
#else
#define IS_BACKWARD_REF_FRAME(ref_frame) ((ref_frame) == cm->comp_fixed_ref)
#endif  // CONFIG_EXT_REFS
216

Yaowu Xu's avatar
Yaowu Xu committed
217 218
int av1_get_reference_mode_context(const AV1_COMMON *cm,
                                   const MACROBLOCKD *xd) {
219 220 221 222 223
  int ctx;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int has_above = xd->up_available;
  const int has_left = xd->left_available;
224

Zoe Liu's avatar
Zoe Liu committed
225
#if CONFIG_EXT_REFS
226
  (void)cm;
Zoe Liu's avatar
Zoe Liu committed
227
#endif  // CONFIG_EXT_REFS
228

229 230 231 232 233 234 235
  // Note:
  // The mode info data structure has a one element border above and to the
  // left of the entries corresponding to real macroblocks.
  // The prediction flags in these dummy entries are initialized to 0.
  if (has_above && has_left) {  // both edges available
    if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi))
      // neither edge uses comp pred (0/1)
Zoe Liu's avatar
Zoe Liu committed
236 237
      ctx = IS_BACKWARD_REF_FRAME(above_mbmi->ref_frame[0]) ^
            IS_BACKWARD_REF_FRAME(left_mbmi->ref_frame[0]);
Jingning Han's avatar
Jingning Han committed
238 239
    else if (!has_second_ref(above_mbmi))
      // one of two edges uses comp pred (2/3)
Zoe Liu's avatar
Zoe Liu committed
240
      ctx = 2 + (IS_BACKWARD_REF_FRAME(above_mbmi->ref_frame[0]) ||
Jingning Han's avatar
Jingning Han committed
241 242 243
                 !is_inter_block(above_mbmi));
    else if (!has_second_ref(left_mbmi))
      // one of two edges uses comp pred (2/3)
Zoe Liu's avatar
Zoe Liu committed
244
      ctx = 2 + (IS_BACKWARD_REF_FRAME(left_mbmi->ref_frame[0]) ||
Jingning Han's avatar
Jingning Han committed
245 246 247 248 249 250 251 252
                 !is_inter_block(left_mbmi));
    else  // both edges use comp pred (4)
      ctx = 4;
  } else if (has_above || has_left) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;

    if (!has_second_ref(edge_mbmi))
      // edge does not use comp pred (0/1)
Zoe Liu's avatar
Zoe Liu committed
253
      ctx = IS_BACKWARD_REF_FRAME(edge_mbmi->ref_frame[0]);
Jingning Han's avatar
Jingning Han committed
254 255 256 257 258 259 260 261 262 263
    else
      // edge uses comp pred (3)
      ctx = 3;
  } else {  // no edges available (1)
    ctx = 1;
  }
  assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS);
  return ctx;
}

264 265 266
#if CONFIG_EXT_REFS

// TODO(zoeliu): Future work will be conducted to optimize the context design
267
//               for the coding of the reference frames.
268 269 270 271

#define CHECK_LAST_OR_LAST2(ref_frame) \
  ((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))

272 273
#define CHECK_GOLDEN_OR_LAST3(ref_frame) \
  ((ref_frame == GOLDEN_FRAME) || (ref_frame == LAST3_FRAME))
274

Jingning Han's avatar
Jingning Han committed
275
// Returns a context number for the given MB prediction signal
276 277
// Signal the first reference frame for a compound mode be either
// GOLDEN/LAST3, or LAST/LAST2.
278 279
//
// NOTE(zoeliu): The probability of ref_frame[0] is either
280
//               GOLDEN_FRAME or LAST3_FRAME.
281 282 283 284
#if CONFIG_LOWDELAY_COMPOUND
int av1_get_pred_context_comp_ref_p(UNUSED const AV1_COMMON *cm,
                                    const MACROBLOCKD *xd) {
#else
Yaowu Xu's avatar
Yaowu Xu committed
285 286
int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
                                    const MACROBLOCKD *xd) {
287
#endif
288 289 290 291 292 293
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int above_in_image = xd->up_available;
  const int left_in_image = xd->left_available;

294 295 296 297 298 299 300 301
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
#if CONFIG_LOWDELAY_COMPOUND  // No change to bitstream
  // Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
  const int bwd_ref_sign_idx = 1;
#else
302
  const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
303
#endif
304
  const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
305 306 307 308 309 310 311 312 313 314 315

  if (above_in_image && left_in_image) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra (2)
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;

      if (!has_second_ref(edge_mbmi))  // single pred (1/3)
clang-format's avatar
clang-format committed
316 317
        pred_context =
            1 + 2 * (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]));
318
      else  // comp pred (1/3)
clang-format's avatar
clang-format committed
319 320 321
        pred_context = 1 +
                       2 * (!CHECK_GOLDEN_OR_LAST3(
                               edge_mbmi->ref_frame[fwd_ref_sign_idx]));
322 323 324
    } else {  // inter/inter
      const int l_sg = !has_second_ref(left_mbmi);
      const int a_sg = !has_second_ref(above_mbmi);
clang-format's avatar
clang-format committed
325 326 327 328 329 330
      const MV_REFERENCE_FRAME frfa =
          a_sg ? above_mbmi->ref_frame[0]
               : above_mbmi->ref_frame[fwd_ref_sign_idx];
      const MV_REFERENCE_FRAME frfl =
          l_sg ? left_mbmi->ref_frame[0]
               : left_mbmi->ref_frame[fwd_ref_sign_idx];
331

332
      if (frfa == frfl && CHECK_GOLDEN_OR_LAST3(frfa)) {
333 334
        pred_context = 0;
      } else if (l_sg && a_sg) {  // single/single
Zoe Liu's avatar
Zoe Liu committed
335 336
        if ((CHECK_BACKWARD_REFS(frfa) && CHECK_LAST_OR_LAST2(frfl)) ||
            (CHECK_BACKWARD_REFS(frfl) && CHECK_LAST_OR_LAST2(frfa))) {
337
          pred_context = 4;
clang-format's avatar
clang-format committed
338
        } else if (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl)) {
339
          pred_context = 1;
340 341
        } else {
          pred_context = 3;
342 343
        }
      } else if (l_sg || a_sg) {  // single/comp
344 345
        const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
        const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
346

347
        if (CHECK_GOLDEN_OR_LAST3(frfc) && !CHECK_GOLDEN_OR_LAST3(rfs))
348
          pred_context = 1;
349
        else if (CHECK_GOLDEN_OR_LAST3(rfs) && !CHECK_GOLDEN_OR_LAST3(frfc))
350 351 352 353
          pred_context = 2;
        else
          pred_context = 4;
      } else {  // comp/comp
354
        if ((CHECK_LAST_OR_LAST2(frfa) && CHECK_LAST_OR_LAST2(frfl))) {
355 356 357
          pred_context = 4;
        } else {
          // NOTE(zoeliu): Following assert may be removed once confirmed.
358
          assert(CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl));
359 360 361 362 363 364 365 366 367 368 369
          pred_context = 2;
        }
      }
    }
  } else if (above_in_image || left_in_image) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;

    if (!is_inter_block(edge_mbmi)) {
      pred_context = 2;
    } else {
      if (has_second_ref(edge_mbmi))
clang-format's avatar
clang-format committed
370 371
        pred_context =
            4 *
372
            (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[fwd_ref_sign_idx]));
373
      else
374
        pred_context = 3 * (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]));
375 376 377 378 379 380 381 382 383 384 385
    }
  } else {  // no edges available (2)
    pred_context = 2;
  }

  assert(pred_context >= 0 && pred_context < REF_CONTEXTS);

  return pred_context;
}

// Returns a context number for the given MB prediction signal
386
// Signal the first reference frame for a compound mode be LAST,
387 388 389 390
// conditioning on that it is known either LAST/LAST2.
//
// NOTE(zoeliu): The probability of ref_frame[0] is LAST_FRAME,
// conditioning on it is either LAST_FRAME or LAST2_FRAME.
391 392 393 394
#if CONFIG_LOWDELAY_COMPOUND
int av1_get_pred_context_comp_ref_p1(UNUSED const AV1_COMMON *cm,
                                     const MACROBLOCKD *xd) {
#else
Yaowu Xu's avatar
Yaowu Xu committed
395 396
int av1_get_pred_context_comp_ref_p1(const AV1_COMMON *cm,
                                     const MACROBLOCKD *xd) {
397
#endif
398 399 400 401 402 403
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int above_in_image = xd->up_available;
  const int left_in_image = xd->left_available;

404 405 406 407 408 409 410 411
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
#if CONFIG_LOWDELAY_COMPOUND  // No change to bitstream
  // Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
  const int bwd_ref_sign_idx = 1;
#else
412
  const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
413
#endif
414
  const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
415 416 417 418 419 420 421 422 423 424 425 426 427

  if (above_in_image && left_in_image) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra (2)
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;

      if (!has_second_ref(edge_mbmi))  // single pred (1/3)
        pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != LAST_FRAME);
      else  // comp pred (1/3)
clang-format's avatar
clang-format committed
428 429
        pred_context =
            1 + 2 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != LAST_FRAME);
430 431 432
    } else {  // inter/inter
      const int l_sg = !has_second_ref(left_mbmi);
      const int a_sg = !has_second_ref(above_mbmi);
clang-format's avatar
clang-format committed
433 434 435 436 437 438
      const MV_REFERENCE_FRAME frfa =
          a_sg ? above_mbmi->ref_frame[0]
               : above_mbmi->ref_frame[fwd_ref_sign_idx];
      const MV_REFERENCE_FRAME frfl =
          l_sg ? left_mbmi->ref_frame[0]
               : left_mbmi->ref_frame[fwd_ref_sign_idx];
439

440
      if (frfa == frfl && frfa == LAST_FRAME)
441 442
        pred_context = 0;
      else if (l_sg && a_sg) {  // single/single
443
        if (frfa == LAST_FRAME || frfl == LAST_FRAME)
444
          pred_context = 1;
445 446 447
        else if (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl))
          pred_context = 2 + (frfa != frfl);
        else if (frfa == frfl ||
Zoe Liu's avatar
Zoe Liu committed
448
                 (CHECK_BACKWARD_REFS(frfa) && CHECK_BACKWARD_REFS(frfl)))
449 450 451 452
          pred_context = 3;
        else
          pred_context = 4;
      } else if (l_sg || a_sg) {  // single/comp
453 454
        const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
        const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
455

456
        if (frfc == LAST_FRAME && rfs != LAST_FRAME)
457
          pred_context = 1;
458
        else if (rfs == LAST_FRAME && frfc != LAST_FRAME)
459 460
          pred_context = 2;
        else
clang-format's avatar
clang-format committed
461 462
          pred_context =
              3 + (frfc == LAST2_FRAME || CHECK_GOLDEN_OR_LAST3(rfs));
463
      } else {  // comp/comp
464
        if (frfa == LAST_FRAME || frfl == LAST_FRAME)
465 466
          pred_context = 2;
        else
clang-format's avatar
clang-format committed
467 468
          pred_context =
              3 + (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl));
469 470 471 472 473 474 475 476 477
      }
    }
  } else if (above_in_image || left_in_image) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;

    if (!is_inter_block(edge_mbmi)) {
      pred_context = 2;
    } else {
      if (has_second_ref(edge_mbmi)) {
clang-format's avatar
clang-format committed
478 479
        pred_context =
            4 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != LAST_FRAME);
480 481 482 483
      } else {
        if (edge_mbmi->ref_frame[0] == LAST_FRAME)
          pred_context = 0;
        else
484
          pred_context = 2 + CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]);
485 486 487 488 489 490 491 492 493 494 495 496
      }
    }
  } else {  // no edges available (2)
    pred_context = 2;
  }

  assert(pred_context >= 0 && pred_context < REF_CONTEXTS);

  return pred_context;
}

// Returns a context number for the given MB prediction signal
497 498
// Signal the first reference frame for a compound mode be GOLDEN,
// conditioning on that it is known either GOLDEN or LAST3.
499 500
//
// NOTE(zoeliu): The probability of ref_frame[0] is GOLDEN_FRAME,
501
// conditioning on it is either GOLDEN or LAST3.
502 503 504 505
#if CONFIG_LOWDELAY_COMPOUND
int av1_get_pred_context_comp_ref_p2(UNUSED const AV1_COMMON *cm,
                                     const MACROBLOCKD *xd) {
#else
Yaowu Xu's avatar
Yaowu Xu committed
506 507
int av1_get_pred_context_comp_ref_p2(const AV1_COMMON *cm,
                                     const MACROBLOCKD *xd) {
508
#endif
509 510 511 512 513 514
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int above_in_image = xd->up_available;
  const int left_in_image = xd->left_available;

515 516 517 518 519 520 521 522
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
#if CONFIG_LOWDELAY_COMPOUND  // No change to bitstream
  // Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
  const int bwd_ref_sign_idx = 1;
#else
523
  const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
524
#endif
525
  const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
526 527 528 529 530 531 532 533 534 535 536 537 538

  if (above_in_image && left_in_image) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra (2)
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;

      if (!has_second_ref(edge_mbmi))  // single pred (1/3)
        pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != GOLDEN_FRAME);
      else  // comp pred (1/3)
clang-format's avatar
clang-format committed
539 540
        pred_context =
            1 + 2 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != GOLDEN_FRAME);
541 542 543
    } else {  // inter/inter
      const int l_sg = !has_second_ref(left_mbmi);
      const int a_sg = !has_second_ref(above_mbmi);
clang-format's avatar
clang-format committed
544 545 546 547 548 549
      const MV_REFERENCE_FRAME frfa =
          a_sg ? above_mbmi->ref_frame[0]
               : above_mbmi->ref_frame[fwd_ref_sign_idx];
      const MV_REFERENCE_FRAME frfl =
          l_sg ? left_mbmi->ref_frame[0]
               : left_mbmi->ref_frame[fwd_ref_sign_idx];
550

551
      if (frfa == frfl && frfa == GOLDEN_FRAME)
552 553
        pred_context = 0;
      else if (l_sg && a_sg) {  // single/single
554
        if (frfa == GOLDEN_FRAME || frfl == GOLDEN_FRAME)
555
          pred_context = 1;
556 557 558
        else if (CHECK_LAST_OR_LAST2(frfa) || CHECK_LAST_OR_LAST2(frfl))
          pred_context = 2 + (frfa != frfl);
        else if (frfa == frfl ||
Zoe Liu's avatar
Zoe Liu committed
559
                 (CHECK_BACKWARD_REFS(frfa) && CHECK_BACKWARD_REFS(frfl)))
560 561 562 563
          pred_context = 3;
        else
          pred_context = 4;
      } else if (l_sg || a_sg) {  // single/comp
564 565
        const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
        const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
566

567
        if (frfc == GOLDEN_FRAME && rfs != GOLDEN_FRAME)
568
          pred_context = 1;
569
        else if (rfs == GOLDEN_FRAME && frfc != GOLDEN_FRAME)
570 571
          pred_context = 2;
        else
clang-format's avatar
clang-format committed
572
          pred_context = 3 + (frfc == LAST3_FRAME || CHECK_LAST_OR_LAST2(rfs));
573
      } else {  // comp/comp
574
        if (frfa == GOLDEN_FRAME || frfl == GOLDEN_FRAME)
575 576
          pred_context = 2;
        else
clang-format's avatar
clang-format committed
577 578
          pred_context =
              3 + (CHECK_LAST_OR_LAST2(frfa) || CHECK_LAST_OR_LAST2(frfl));
579 580 581 582 583 584 585 586 587
      }
    }
  } else if (above_in_image || left_in_image) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;

    if (!is_inter_block(edge_mbmi)) {
      pred_context = 2;
    } else {
      if (has_second_ref(edge_mbmi)) {
clang-format's avatar
clang-format committed
588 589
        pred_context =
            4 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != GOLDEN_FRAME);
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
      } else {
        if (edge_mbmi->ref_frame[0] == GOLDEN_FRAME)
          pred_context = 0;
        else
          pred_context = 2 + CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]);
      }
    }
  } else {  // no edges available (2)
    pred_context = 2;
  }

  assert(pred_context >= 0 && pred_context < REF_CONTEXTS);

  return pred_context;
}

606
// Returns a context number for the given MB prediction signal
607 608 609 610
#if CONFIG_LOWDELAY_COMPOUND
int av1_get_pred_context_comp_bwdref_p(UNUSED const AV1_COMMON *cm,
                                       const MACROBLOCKD *xd) {
#else
Yaowu Xu's avatar
Yaowu Xu committed
611 612
int av1_get_pred_context_comp_bwdref_p(const AV1_COMMON *cm,
                                       const MACROBLOCKD *xd) {
613
#endif
614 615 616 617 618 619
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int above_in_image = xd->up_available;
  const int left_in_image = xd->left_available;

620 621 622 623 624 625 626 627
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
#if CONFIG_LOWDELAY_COMPOUND  // No change to bitstream
  // Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
  const int bwd_ref_sign_idx = 1;
#else
628
  const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
629
#endif
630 631 632 633 634 635 636 637 638 639 640 641
  const int fwd_ref_sign_idx = !bwd_ref_sign_idx;

  if (above_in_image && left_in_image) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra (2)
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;

      if (!has_second_ref(edge_mbmi))  // single pred (1/3)
642
        pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_bwd_ref[1]);
643
      else  // comp pred (1/3)
clang-format's avatar
clang-format committed
644 645 646
        pred_context =
            1 +
            2 * (edge_mbmi->ref_frame[bwd_ref_sign_idx] != cm->comp_bwd_ref[1]);
647 648 649 650
    } else {  // inter/inter
      const int l_comp = has_second_ref(left_mbmi);
      const int a_comp = has_second_ref(above_mbmi);

clang-format's avatar
clang-format committed
651
      const MV_REFERENCE_FRAME l_brf =
Emil Keyder's avatar
Emil Keyder committed
652
          l_comp ? left_mbmi->ref_frame[bwd_ref_sign_idx] : NONE_FRAME;
clang-format's avatar
clang-format committed
653
      const MV_REFERENCE_FRAME a_brf =
Emil Keyder's avatar
Emil Keyder committed
654
          a_comp ? above_mbmi->ref_frame[bwd_ref_sign_idx] : NONE_FRAME;
655

clang-format's avatar
clang-format committed
656 657 658 659 660 661
      const MV_REFERENCE_FRAME l_frf =
          !l_comp ? left_mbmi->ref_frame[0]
                  : left_mbmi->ref_frame[fwd_ref_sign_idx];
      const MV_REFERENCE_FRAME a_frf =
          !a_comp ? above_mbmi->ref_frame[0]
                  : above_mbmi->ref_frame[fwd_ref_sign_idx];
662

663
      if (l_comp && a_comp) {  // comp/comp
664 665 666 667 668 669 670 671 672 673
        if (l_brf == a_brf && l_brf == cm->comp_bwd_ref[1]) {
          pred_context = 0;
        } else if (l_brf == cm->comp_bwd_ref[1] ||
                   a_brf == cm->comp_bwd_ref[1]) {
          pred_context = 1;
        } else {
          // NOTE: Backward ref should be either BWDREF or ALTREF.
          assert(l_brf == a_brf && l_brf != cm->comp_bwd_ref[1]);
          pred_context = 3;
        }
674
      } else if (!l_comp && !a_comp) {  // single/single
675 676 677 678 679 680 681 682
        if (l_frf == a_frf && l_frf == cm->comp_bwd_ref[1]) {
          pred_context = 0;
        } else if (l_frf == cm->comp_bwd_ref[1] ||
                   a_frf == cm->comp_bwd_ref[1]) {
          pred_context = 1;
        } else if (l_frf == a_frf) {
          pred_context = 3;
        } else {
clang-format's avatar
clang-format committed
683 684
          assert(l_frf != a_frf && l_frf != cm->comp_bwd_ref[1] &&
                 a_frf != cm->comp_bwd_ref[1]);
685 686
          pred_context = 4;
        }
687
      } else {  // comp/single
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
        assert((l_comp && !a_comp) || (!l_comp && a_comp));

        if ((l_comp && l_brf == cm->comp_bwd_ref[1] &&
             a_frf == cm->comp_bwd_ref[1]) ||
            (a_comp && a_brf == cm->comp_bwd_ref[1] &&
             l_frf == cm->comp_bwd_ref[1])) {
          pred_context = 1;
        } else if ((l_comp && l_brf == cm->comp_bwd_ref[1]) ||
                   (a_comp && a_brf == cm->comp_bwd_ref[1]) ||
                   (!l_comp && l_frf == cm->comp_bwd_ref[1]) ||
                   (!a_comp && a_frf == cm->comp_bwd_ref[1])) {
          pred_context = 2;
        } else {
          pred_context = 4;
        }
      }
    }
  } else if (above_in_image || left_in_image) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;

    if (!is_inter_block(edge_mbmi)) {
      pred_context = 2;
    } else {
      if (has_second_ref(edge_mbmi)) {
clang-format's avatar
clang-format committed
712 713
        pred_context =
            4 * (edge_mbmi->ref_frame[bwd_ref_sign_idx] != cm->comp_bwd_ref[1]);
714 715 716 717 718 719 720 721 722 723 724 725
      } else {
        pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_bwd_ref[1]);
      }
    }
  } else {  // no edges available (2)
    pred_context = 2;
  }
  assert(pred_context >= 0 && pred_context < REF_CONTEXTS);

  return pred_context;
}

726
#else  // CONFIG_EXT_REFS
727

728
// Returns a context number for the given MB prediction signal
Yaowu Xu's avatar
Yaowu Xu committed
729 730
int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
                                    const MACROBLOCKD *xd) {
731 732 733 734 735 736 737 738
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int above_in_image = xd->up_available;
  const int left_in_image = xd->left_available;

  // Note:
  // The mode info data structure has a one element border above and to the
739 740
  // left of the entries corresponding to real macroblocks.
  // The prediction flags in these dummy entries are initialized to 0.
741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
  const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
  const int var_ref_idx = !fix_ref_idx;

  if (above_in_image && left_in_image) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra (2)
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;

      if (!has_second_ref(edge_mbmi))  // single pred (1/3)
        pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
      else  // comp pred (1/3)
clang-format's avatar
clang-format committed
756 757
        pred_context =
            1 + 2 * (edge_mbmi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]);
758 759 760
    } else {  // inter/inter
      const int l_sg = !has_second_ref(left_mbmi);
      const int a_sg = !has_second_ref(above_mbmi);
clang-format's avatar
clang-format committed
761 762 763 764
      const MV_REFERENCE_FRAME vrfa =
          a_sg ? above_mbmi->ref_frame[0] : above_mbmi->ref_frame[var_ref_idx];
      const MV_REFERENCE_FRAME vrfl =
          l_sg ? left_mbmi->ref_frame[0] : left_mbmi->ref_frame[var_ref_idx];
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797

      if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
        pred_context = 0;
      } else if (l_sg && a_sg) {  // single/single
        if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) ||
            (vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0]))
          pred_context = 4;
        else if (vrfa == vrfl)
          pred_context = 3;
        else
          pred_context = 1;
      } else if (l_sg || a_sg) {  // single/comp
        const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
        const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
        if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1])
          pred_context = 1;
        else if (rfs == cm->comp_var_ref[1] && vrfc != cm->comp_var_ref[1])
          pred_context = 2;
        else
          pred_context = 4;
      } else if (vrfa == vrfl) {  // comp/comp
        pred_context = 4;
      } else {
        pred_context = 2;
      }
    }
  } else if (above_in_image || left_in_image) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;

    if (!is_inter_block(edge_mbmi)) {
      pred_context = 2;
    } else {
      if (has_second_ref(edge_mbmi))
clang-format's avatar
clang-format committed
798 799
        pred_context =
            4 * (edge_mbmi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]);
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
      else
        pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]);
    }
  } else {  // no edges available (2)
    pred_context = 2;
  }
  assert(pred_context >= 0 && pred_context < REF_CONTEXTS);

  return pred_context;
}

#endif  // CONFIG_EXT_REFS

#if CONFIG_EXT_REFS

// For the bit to signal whether the single reference is a ALTREF_FRAME
816
// or a BWDREF_FRAME.
817
//
818
// NOTE(zoeliu): The probability of ref_frame[0] is ALTREF/BWDREF.
Yaowu Xu's avatar
Yaowu Xu committed
819
int av1_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) {
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int has_above = xd->up_available;
  const int has_left = xd->left_available;

  // Note:
  // The mode info data structure has a one element border above and to the
  // left of the entries correpsonding to real macroblocks.
  // The prediction flags in these dummy entries are initialised to 0.
  if (has_above && has_left) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter or inter/intra
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;

839
      if (!has_second_ref(edge_mbmi))  // single
Zoe Liu's avatar
Zoe Liu committed
840
        pred_context = 4 * (!CHECK_BACKWARD_REFS(edge_mbmi->ref_frame[0]));
841 842
      else  // comp
        pred_context = 2;
843 844
    } else {  // inter/inter
      const int above_has_second = has_second_ref(above_mbmi);
clang-format's avatar
clang-format committed
845
      const int left_has_second = has_second_ref(left_mbmi);
846 847 848 849

      const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
      const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];

850 851 852
      if (above_has_second && left_has_second) {  // comp/comp
        pred_context = 2;
      } else if (above_has_second || left_has_second) {  // single/comp
853 854
        const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;

855 856
        pred_context = (!CHECK_BACKWARD_REFS(rfs)) ? 4 : 1;
      } else {  // single/single
Zoe Liu's avatar
Zoe Liu committed
857 858
        pred_context = 2 * (!CHECK_BACKWARD_REFS(above0)) +
                       2 * (!CHECK_BACKWARD_REFS(left0));
859 860 861 862 863 864
      }
    }
  } else if (has_above || has_left) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
    if (!is_inter_block(edge_mbmi)) {  // intra
      pred_context = 2;
865 866
    } else {                           // inter
      if (!has_second_ref(edge_mbmi))  // single
Zoe Liu's avatar
Zoe Liu committed
867
        pred_context = 4 * (!CHECK_BACKWARD_REFS(edge_mbmi->ref_frame[0]));
868 869
      else  // comp
        pred_context = 2;
870 871 872 873 874 875 876 877 878 879
    }
  } else {  // no edges available
    pred_context = 2;
  }

  assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
  return pred_context;
}

// For the bit to signal whether the single reference is ALTREF_FRAME or
880
// BWDREF_FRAME, knowing that it shall be either of these 2 choices.
881 882
//
// NOTE(zoeliu): The probability of ref_frame[0] is ALTREF_FRAME, conditioning
883
// on it is either ALTREF_FRAME/BWDREF_FRAME.
Yaowu Xu's avatar
Yaowu Xu committed
884
int av1_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
  int pred_context;
  const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
  const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
  const int has_above = xd->up_available;
  const int has_left = xd->left_available;

  // Note:
  // The mode info data structure has a one element border above and to the
  // left of the entries correpsonding to real macroblocks.
  // The prediction flags in these dummy entries are initialised to 0.
  if (has_above && has_left) {  // both edges available
    const int above_intra = !is_inter_block(above_mbmi);
    const int left_intra = !is_inter_block(left_mbmi);

    if (above_intra && left_intra) {  // intra/intra
      pred_context = 2;
    } else if (above_intra || left_intra) {  // intra/inter or inter/intra
      const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
903
      if (!has_second_ref(edge_mbmi)) {  // single
Zoe Liu's avatar
Zoe Liu committed
904
        if (!CHECK_BACKWARD_REFS(edge_mbmi->ref_frame[0]))
905 906
          pred_context = 3;
        else
907
          pred_context = 4 * (edge_mbmi->ref_frame[0] == BWDREF_FRAME);
908
      } else {  // comp
clang-format's avatar
clang-format committed
909 910 911
        pred_context = 1 +
                       2 * (edge_mbmi->ref_frame[0] == BWDREF_FRAME ||
                            edge_mbmi->ref_frame[1] == BWDREF_FRAME);
912 913 914
      }
    } else {  // inter/inter
      const int above_has_second = has_second_ref(above_mbmi);
clang-format's avatar
clang-format committed
915
      const int left_has_second = has_second_ref(left_mbmi);
916 917 918 919 920
      const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
      const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
      const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
      const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];

921
      if (above_has_second && left_has_second) {  // comp/comp
922
        if (above0 == left0 && above1 == left1)
clang-format's avatar
clang-format committed
923 924 925
          pred_context =
              3 * (above0 == BWDREF_FRAME || above1 == BWDREF_FRAME ||
                   left0 == BWDREF_FRAME || left1 == BWDREF_FRAME);
926 927
        else
          pred_context = 2;
928
      } else if (above_has_second || left_has_second) {  // single/comp
929 930 931 932
        const MV_REFERENCE_FRAME rfs = !above_has_second ? above0 : left0;
        const MV_REFERENCE_FRAME crf1 = above_has_second ? above0 : left0;
        const MV_REFERENCE_FRAME crf2 = above_has_second ? above1 : left1;

933 934
        if (rfs == BWDREF_FRAME)
          pred_context = 3 + (crf1 == BWDREF_FRAME || crf2 == BWDREF_FRAME);
935
        else if (rfs == ALTREF_FRAME)
936
          pred_context = (crf1 == BWDREF_FRAME || crf2 == BWDREF_FRAME);
937
        else
938
          pred_context = 1 + 2 * (crf1 == BWDREF_FRAME || crf2 == BWDREF_FRAME);
939
      } else {  // single/single
Zoe Liu's avatar
Zoe Liu committed
940
        if (!CHECK_BACKWARD_REFS(above0) && !CHECK_BACKWARD_REFS(left0)) {
941
          pred_context = 2 + (above0 == left0);
Zoe Liu's avatar
Zoe Liu committed
942 943
        } else if (!CHECK_BACKWARD_REFS(above0) ||
                   !CHECK_BACKWARD_REFS(left0)) {
944
          const MV_REFERENCE_FRAME edge0 =
Zoe Liu's avatar
Zoe Liu committed
945
              !CHECK_BACKWARD_REFS(above0) ? left0 : above0;
946
          pred_context = 4 * (edge0 == BWDREF_FRAME);
947
        } else {
clang-format's avatar
clang-format committed
948 949
          pred_context =
              2 * (above0 == BWDREF_FRAME) + 2 * (left0 == BWDREF_FRAME);
950 951 952 953 954 955 956
        }
      }
    }
  } else if (has_above || has_left) {  // one edge available
    const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;

    if (!is_inter_block(edge_mbmi) ||
Zoe Liu's avatar
Zoe Liu committed
957
        (!CHECK_BACKWARD_REFS(edge_mbmi->ref_frame[0]) &&
958 959
         !has_second_ref(edge_mbmi)))
      pred_context = 2;
960
    else if (!has_second_ref(edge_mbmi))  // single
961
      pred_context = 4 * (edge_mbmi->ref_frame[0] == BWDREF_FRAME);
962
    else  // comp
963 964
      pred_context = 3 * (edge_mbmi->ref_frame[0] == BWDREF_FRAME ||
                          edge_mbmi->ref_frame[1] == BWDREF_FRAME);
965 966 967 968 969 970 971 972