Ejemplo n.º 1
0
void vp9_tokenize_sb(VP9_COMP *cpi, TOKENEXTRA **t, int dry_run,
                     BLOCK_SIZE bsize) {
  VP9_COMMON *const cm = &cpi->common;
  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
  MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
  TOKENEXTRA *t_backup = *t;
  const int ctx = vp9_get_skip_context(xd);
  const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
                                              SEG_LVL_SKIP);
  struct tokenize_b_args arg = {cpi, xd, t, mbmi->tx_size, cpi->mb.token_cache};
  if (mbmi->skip_coeff) {
    if (!dry_run)
      cm->counts.mbskip[ctx][1] += skip_inc;
    reset_skip_context(xd, bsize);
    if (dry_run)
      *t = t_backup;
    return;
  }

  if (!dry_run) {
    cm->counts.mbskip[ctx][0] += skip_inc;
    foreach_transformed_block(xd, bsize, tokenize_b, &arg);
  } else {
    foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
    *t = t_backup;
  }
}
Ejemplo n.º 2
0
void vp9_tokenize_sb(VP9_COMP *cpi, ThreadData *td, TOKENEXTRA **t,
                     int dry_run, BLOCK_SIZE bsize) {
  VP9_COMMON *const cm = &cpi->common;
  MACROBLOCK *const x = &td->mb;
  MACROBLOCKD *const xd = &x->e_mbd;
  MB_MODE_INFO *const mbmi = &xd->mi[0].src_mi->mbmi;
  TOKENEXTRA *t_backup = *t;
  const int ctx = vp9_get_skip_context(xd);
  const int skip_inc = !vp9_segfeature_active(&cm->seg, mbmi->segment_id,
                                              SEG_LVL_SKIP);
  struct tokenize_b_args arg = {cpi, td, t};
  if (mbmi->skip) {
    if (!dry_run)
      td->counts->skip[ctx][1] += skip_inc;
    reset_skip_context(xd, bsize);
    if (dry_run)
      *t = t_backup;
    return;
  }

  if (!dry_run) {
    td->counts->skip[ctx][0] += skip_inc;
    vp9_foreach_transformed_block(xd, bsize, tokenize_b, &arg);
  } else {
    vp9_foreach_transformed_block(xd, bsize, set_entropy_context_b, &arg);
    *t = t_backup;
  }
}
Ejemplo n.º 3
0
static int write_skip(const VP9_COMMON *cm, const MACROBLOCKD *xd,
                      int segment_id, const MODE_INFO *mi, vp9_writer *w) {
  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
    vp9_write(w, skip, vp9_get_skip_prob(cm, xd));
    return skip;
  }
}
Ejemplo n.º 4
0
static uint8_t read_skip_coeff(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                               int segment_id, vp9_reader *r) {
    int skip_coeff = vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP);
    if (!skip_coeff) {
        const int ctx = vp9_get_pred_context_mbskip(xd);
        skip_coeff = vp9_read(r, vp9_get_pred_prob_mbskip(cm, xd));
        if (!cm->frame_parallel_decoding_mode)
            ++cm->counts.mbskip[ctx][skip_coeff];
    }
    return skip_coeff;
}
Ejemplo n.º 5
0
int vp9_get_qindex(const struct segmentation *seg, int segment_id,
                   int base_qindex) {
  if (vp9_segfeature_active(seg, segment_id, SEG_LVL_ALT_Q)) {
    const int data = vp9_get_segdata(seg, segment_id, SEG_LVL_ALT_Q);
    const int seg_qindex = seg->abs_delta == SEGMENT_ABSDATA ?
        data : base_qindex + data;
    return clamp(seg_qindex, 0, MAXQ);
  } else {
    return base_qindex;
  }
}
Ejemplo n.º 6
0
static int write_skip(const VP9_COMP *cpi, int segment_id, const MODE_INFO *mi,
                      vp9_writer *w) {
  const MACROBLOCKD *const xd = &cpi->mb.e_mbd;
  if (vp9_segfeature_active(&cpi->common.seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int skip = mi->mbmi.skip;
    vp9_write(w, skip, vp9_get_skip_prob(&cpi->common, xd));
    return skip;
  }
}
Ejemplo n.º 7
0
static int read_skip_coeff(VP9_COMMON *cm, const MACROBLOCKD *xd,
                           int segment_id, vp9_reader *r) {
  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int ctx = vp9_get_skip_context(xd);
    const int skip = vp9_read(r, cm->fc.mbskip_probs[ctx]);
    if (!cm->frame_parallel_decoding_mode)
      ++cm->counts.mbskip[ctx][skip];
    return skip;
  }
}
Ejemplo n.º 8
0
static int read_skip(VP9_COMMON *cm, const MACROBLOCKD *xd,
                     int segment_id, vp9_reader *r) {
  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
    return 1;
  } else {
    const int ctx = vp9_get_skip_context(xd);
    const int skip = vp9_read(r, cm->fc->skip_probs[ctx]);
    FRAME_COUNTS *counts = xd->counts;
    if (counts)
      ++counts->skip[ctx][skip];
    return skip;
  }
}
Ejemplo n.º 9
0
static int read_is_inter_block(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                               int segment_id, vp9_reader *r) {
  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
    return vp9_get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME) !=
           INTRA_FRAME;
  } else {
    const int ctx = vp9_get_intra_inter_context(xd);
    const int is_inter = vp9_read(r, cm->fc.intra_inter_prob[ctx]);
    if (!cm->frame_parallel_decoding_mode)
      ++cm->counts.intra_inter[ctx][is_inter];
    return is_inter;
  }
}
Ejemplo n.º 10
0
static int read_is_inter_block(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                               int segment_id, vp9_reader *r) {
  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
    return vp9_get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME) !=
           INTRA_FRAME;
  } else {
    const int ctx = vp9_get_intra_inter_context(xd);
    const int is_inter = vp9_read(r, cm->fc->intra_inter_prob[ctx]);
    FRAME_COUNTS *counts = xd->counts;
    if (counts)
      ++counts->intra_inter[ctx][is_inter];
    return is_inter;
  }
}
Ejemplo n.º 11
0
// Read the referncence frame
static void read_ref_frames(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                            vp9_reader *r,
                            int segment_id, MV_REFERENCE_FRAME ref_frame[2]) {
    FRAME_CONTEXT *const fc = &cm->fc;
    FRAME_COUNTS *const counts = &cm->counts;

    if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
        ref_frame[0] = vp9_get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
        ref_frame[1] = NONE;
    } else {
        const int comp_ctx = vp9_get_pred_context_comp_inter_inter(cm, xd);
        int is_comp;

        if (cm->comp_pred_mode == HYBRID_PREDICTION) {
            is_comp = vp9_read(r, fc->comp_inter_prob[comp_ctx]);
            if (!cm->frame_parallel_decoding_mode)
                ++counts->comp_inter[comp_ctx][is_comp];
        } else {
            is_comp = cm->comp_pred_mode == COMP_PREDICTION_ONLY;
        }

        // FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding
        if (is_comp) {
            const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
            const int ref_ctx = vp9_get_pred_context_comp_ref_p(cm, xd);
            const int b = vp9_read(r, fc->comp_ref_prob[ref_ctx]);
            if (!cm->frame_parallel_decoding_mode)
                ++counts->comp_ref[ref_ctx][b];
            ref_frame[fix_ref_idx] = cm->comp_fixed_ref;
            ref_frame[!fix_ref_idx] = cm->comp_var_ref[b];
        } else {
            const int ctx0 = vp9_get_pred_context_single_ref_p1(xd);
            const int bit0 = vp9_read(r, fc->single_ref_prob[ctx0][0]);
            if (!cm->frame_parallel_decoding_mode)
                ++counts->single_ref[ctx0][0][bit0];
            if (bit0) {
                const int ctx1 = vp9_get_pred_context_single_ref_p2(xd);
                const int bit1 = vp9_read(r, fc->single_ref_prob[ctx1][1]);
                ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME;
                if (!cm->frame_parallel_decoding_mode)
                    ++counts->single_ref[ctx1][1][bit1];
            } else {
                ref_frame[0] = LAST_FRAME;
            }

            ref_frame[1] = NONE;
        }
    }
}
Ejemplo n.º 12
0
// Read the referncence frame
static void read_ref_frames(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                            vp9_reader *r,
                            int segment_id, MV_REFERENCE_FRAME ref_frame[2]) {
  FRAME_CONTEXT *const fc = &cm->fc;
  FRAME_COUNTS *const counts = &cm->counts;

  if (vp9_segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) {
    ref_frame[0] = vp9_get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME);
    ref_frame[1] = NONE;
  } else {
    const REFERENCE_MODE mode = (cm->reference_mode == REFERENCE_MODE_SELECT)
                                      ? read_reference_mode(cm, xd, r)
                                      : cm->reference_mode;

    // FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding
    if (mode == COMPOUND_REFERENCE) {
      const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
      const int ctx = vp9_get_pred_context_comp_ref_p(cm, xd);
      const int bit = vp9_read(r, fc->comp_ref_prob[ctx]);
      if (!cm->frame_parallel_decoding_mode)
        ++counts->comp_ref[ctx][bit];
      ref_frame[idx] = cm->comp_fixed_ref;
      ref_frame[!idx] = cm->comp_var_ref[bit];
    } else if (mode == SINGLE_REFERENCE) {
      const int ctx0 = vp9_get_pred_context_single_ref_p1(xd);
      const int bit0 = vp9_read(r, fc->single_ref_prob[ctx0][0]);
      if (!cm->frame_parallel_decoding_mode)
        ++counts->single_ref[ctx0][0][bit0];
      if (bit0) {
        const int ctx1 = vp9_get_pred_context_single_ref_p2(xd);
        const int bit1 = vp9_read(r, fc->single_ref_prob[ctx1][1]);
        if (!cm->frame_parallel_decoding_mode)
          ++counts->single_ref[ctx1][1][bit1];
        ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME;
      } else {
        ref_frame[0] = LAST_FRAME;
      }

      ref_frame[1] = NONE;
    } else {
      assert(0 && "Invalid prediction mode.");
    }
  }
}
Ejemplo n.º 13
0
static void read_inter_block_mode_info(VP9_COMMON *const cm,
                                       MACROBLOCKD *const xd,
                                       const TileInfo *const tile,
                                       MODE_INFO *const mi,
                                       int mi_row, int mi_col, vp9_reader *r) {
  MB_MODE_INFO *const mbmi = &mi->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
  const int allow_hp = cm->allow_high_precision_mv;

  int_mv nearest[2], nearmv[2], best[2];
  int inter_mode_ctx, ref, is_compound;

  read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
  is_compound = has_second_ref(mbmi);

  for (ref = 0; ref < 1 + is_compound; ++ref) {
    const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
    vp9_find_mv_refs(cm, xd, tile, mi, xd->last_mi, frame, mbmi->ref_mvs[frame],
                     mi_row, mi_col);
  }

  inter_mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];

  if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    mbmi->mode = ZEROMV;
    if (bsize < BLOCK_8X8) {
        vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
                           "Invalid usage of segement feature on small blocks");
        return;
    }
  } else {
    if (bsize >= BLOCK_8X8)
      mbmi->mode = read_inter_mode(cm, r, inter_mode_ctx);
  }

  if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) {
    for (ref = 0; ref < 1 + is_compound; ++ref) {
      vp9_find_best_ref_mvs(xd, allow_hp, mbmi->ref_mvs[mbmi->ref_frame[ref]],
                            &nearest[ref], &nearmv[ref]);
      best[ref].as_int = nearest[ref].as_int;
    }
  }

  mbmi->interp_filter = (cm->mcomp_filter_type == SWITCHABLE)
                      ? read_switchable_filter_type(cm, xd, r)
                      : cm->mcomp_filter_type;

  if (bsize < BLOCK_8X8) {
    const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];  // 1 or 2
    const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];  // 1 or 2
    int idx, idy;
    int b_mode;
    for (idy = 0; idy < 2; idy += num_4x4_h) {
      for (idx = 0; idx < 2; idx += num_4x4_w) {
        int_mv block[2];
        const int j = idy * 2 + idx;
        b_mode = read_inter_mode(cm, r, inter_mode_ctx);

        if (b_mode == NEARESTMV || b_mode == NEARMV)
          for (ref = 0; ref < 1 + is_compound; ++ref)
            vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col,
                                          &nearest[ref], &nearmv[ref]);

        if (!assign_mv(cm, b_mode, block, best, nearest, nearmv,
                       is_compound, allow_hp, r)) {
          xd->corrupted |= 1;
          break;
        };

        mi->bmi[j].as_mv[0].as_int = block[0].as_int;
        if (is_compound)
          mi->bmi[j].as_mv[1].as_int = block[1].as_int;

        if (num_4x4_h == 2)
          mi->bmi[j + 2] = mi->bmi[j];
        if (num_4x4_w == 2)
          mi->bmi[j + 1] = mi->bmi[j];
      }
    }

    mi->mbmi.mode = b_mode;

    mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
    mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
  } else {
    xd->corrupted |= !assign_mv(cm, mbmi->mode, mbmi->mv,
                                best, nearest, nearmv,
                                is_compound, allow_hp, r);
  }
}
Ejemplo n.º 14
0
static void tokenize_b(int plane, int block, BLOCK_SIZE_TYPE plane_bsize,
                       TX_SIZE tx_size, void *arg) {
  struct tokenize_b_args* const args = arg;
  VP9_COMP *cpi = args->cpi;
  MACROBLOCKD *xd = args->xd;
  TOKENEXTRA **tp = args->tp;
  struct macroblockd_plane *pd = &xd->plane[plane];
  MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
  int pt; /* near block/prev token context index */
  int c = 0, rc = 0;
  TOKENEXTRA *t = *tp;        /* store tokens starting here */
  const int eob = pd->eobs[block];
  const PLANE_TYPE type = pd->plane_type;
  const int16_t *qcoeff_ptr = BLOCK_OFFSET(pd->qcoeff, block);
  int seg_eob;
  const int segment_id = mbmi->segment_id;
  const int16_t *scan, *nb;
  vp9_coeff_count *const counts = cpi->coef_counts[tx_size];
  vp9_coeff_probs_model *const coef_probs = cpi->common.fc.coef_probs[tx_size];
  const int ref = is_inter_block(mbmi);
  ENTROPY_CONTEXT above_ec, left_ec;
  uint8_t token_cache[1024];
  const uint8_t *band_translate;
  ENTROPY_CONTEXT *A, *L;
  int aoff, loff;
  txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &aoff, &loff);

  A = pd->above_context + aoff;
  L = pd->left_context + loff;

  assert((!type && !plane) || (type && plane));

  switch (tx_size) {
    case TX_4X4:
      above_ec = A[0] != 0;
      left_ec = L[0] != 0;
      seg_eob = 16;
      scan = get_scan_4x4(get_tx_type_4x4(type, xd, block));
      band_translate = vp9_coefband_trans_4x4;
      break;
    case TX_8X8:
      above_ec = !!*(uint16_t *)A;
      left_ec  = !!*(uint16_t *)L;
      seg_eob = 64;
      scan = get_scan_8x8(get_tx_type_8x8(type, xd));
      band_translate = vp9_coefband_trans_8x8plus;
      break;
    case TX_16X16:
      above_ec = !!*(uint32_t *)A;
      left_ec  = !!*(uint32_t *)L;
      seg_eob = 256;
      scan = get_scan_16x16(get_tx_type_16x16(type, xd));
      band_translate = vp9_coefband_trans_8x8plus;
      break;
    case TX_32X32:
      above_ec = !!*(uint64_t *)A;
      left_ec  = !!*(uint64_t *)L;
      seg_eob = 1024;
      scan = vp9_default_scan_32x32;
      band_translate = vp9_coefband_trans_8x8plus;
      break;
    default:
      assert(!"Invalid transform size");
  }

  pt = combine_entropy_contexts(above_ec, left_ec);
  nb = vp9_get_coef_neighbors_handle(scan);

  if (vp9_segfeature_active(&cpi->common.seg, segment_id, SEG_LVL_SKIP))
    seg_eob = 0;

  c = 0;
  do {
    const int band = get_coef_band(band_translate, c);
    int token;
    int v = 0;
    rc = scan[c];
    if (c)
      pt = get_coef_context(nb, token_cache, c);
    if (c < eob) {
      v = qcoeff_ptr[rc];
      assert(-DCT_MAX_VALUE <= v  &&  v < DCT_MAX_VALUE);

      t->extra = vp9_dct_value_tokens_ptr[v].extra;
      token    = vp9_dct_value_tokens_ptr[v].token;
    } else {
      token = DCT_EOB_TOKEN;
    }

    t->token = token;
    t->context_tree = coef_probs[type][ref][band][pt];
    t->skip_eob_node = (c > 0) && (token_cache[scan[c - 1]] == 0);

    assert(vp9_coef_encodings[t->token].len - t->skip_eob_node > 0);

    ++counts[type][ref][band][pt][token];
    if (!t->skip_eob_node)
      ++cpi->common.counts.eob_branch[tx_size][type][ref][band][pt];

    token_cache[rc] = vp9_pt_energy_class[token];
    ++t;
  } while (c < eob && ++c < seg_eob);

  *tp = t;

  set_contexts(xd, pd, plane_bsize, tx_size, c > 0, aoff, loff);
}
Ejemplo n.º 15
0
static INLINE int get_tx_eob(const struct segmentation *seg, int segment_id,
                             TX_SIZE tx_size) {
  const int eob_max = 16 << (tx_size << 1);
  return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
}
Ejemplo n.º 16
0
static void read_inter_block_mode_info(VP9Decoder *const pbi,
                                       MACROBLOCKD *const xd,
                                       const TileInfo *const tile,
                                       MODE_INFO *const mi,
                                       int mi_row, int mi_col, vp9_reader *r) {
  VP9_COMMON *const cm = &pbi->common;
  MB_MODE_INFO *const mbmi = &mi->mbmi;
  const BLOCK_SIZE bsize = mbmi->sb_type;
  const int allow_hp = cm->allow_high_precision_mv;
  int_mv nearestmv[2], nearmv[2];
  int inter_mode_ctx, ref, is_compound;

  read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
  is_compound = has_second_ref(mbmi);

  for (ref = 0; ref < 1 + is_compound; ++ref) {
    const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
    RefBuffer *ref_buf = &cm->frame_refs[frame - LAST_FRAME];
    xd->block_refs[ref] = ref_buf;
    if ((!vp9_is_valid_scale(&ref_buf->sf)))
      vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
                         "Reference frame has invalid dimensions");
    vp9_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col,
                         &ref_buf->sf);
    vp9_find_mv_refs(cm, xd, tile, mi, frame, mbmi->ref_mvs[frame],
                     mi_row, mi_col, fpm_sync, (void *)pbi);
  }

  inter_mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];

  if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
    mbmi->mode = ZEROMV;
    if (bsize < BLOCK_8X8) {
        vpx_internal_error(xd->error_info, VPX_CODEC_UNSUP_BITSTREAM,
                           "Invalid usage of segement feature on small blocks");
        return;
    }
  } else {
    if (bsize >= BLOCK_8X8)
      mbmi->mode = read_inter_mode(cm, xd, r, inter_mode_ctx);
  }

  if (bsize < BLOCK_8X8 || mbmi->mode != ZEROMV) {
    for (ref = 0; ref < 1 + is_compound; ++ref) {
      vp9_find_best_ref_mvs(xd, allow_hp, mbmi->ref_mvs[mbmi->ref_frame[ref]],
                            &nearestmv[ref], &nearmv[ref]);
    }
  }

  mbmi->interp_filter = (cm->interp_filter == SWITCHABLE)
                      ? read_switchable_interp_filter(cm, xd, r)
                      : cm->interp_filter;

  if (bsize < BLOCK_8X8) {
    const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];  // 1 or 2
    const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];  // 1 or 2
    int idx, idy;
    PREDICTION_MODE b_mode;
    int_mv nearest_sub8x8[2], near_sub8x8[2];
    for (idy = 0; idy < 2; idy += num_4x4_h) {
      for (idx = 0; idx < 2; idx += num_4x4_w) {
        int_mv block[2];
        const int j = idy * 2 + idx;
        b_mode = read_inter_mode(cm, xd, r, inter_mode_ctx);

        if (b_mode == NEARESTMV || b_mode == NEARMV)
          for (ref = 0; ref < 1 + is_compound; ++ref)
            vp9_append_sub8x8_mvs_for_idx(cm, xd, tile, j, ref, mi_row, mi_col,
                                          &nearest_sub8x8[ref],
                                          &near_sub8x8[ref]);

        if (!assign_mv(cm, xd, b_mode, block, nearestmv,
                       nearest_sub8x8, near_sub8x8,
                       is_compound, allow_hp, r)) {
          xd->corrupted |= 1;
          break;
        };

        mi->bmi[j].as_mv[0].as_int = block[0].as_int;
        if (is_compound)
          mi->bmi[j].as_mv[1].as_int = block[1].as_int;

        if (num_4x4_h == 2)
          mi->bmi[j + 2] = mi->bmi[j];
        if (num_4x4_w == 2)
          mi->bmi[j + 1] = mi->bmi[j];
      }
    }

    mi->mbmi.mode = b_mode;

    mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
    mbmi->mv[1].as_int = mi->bmi[3].as_mv[1].as_int;
  } else {
    xd->corrupted |= !assign_mv(cm, xd, mbmi->mode, mbmi->mv, nearestmv,
                                nearestmv, nearmv, is_compound, allow_hp, r);
  }
}
MV_REFERENCE_FRAME vp9_get_pred_ref(const VP9_COMMON *const cm,
                                    const MACROBLOCKD *const xd) {
  MODE_INFO *m = xd->mode_info_context;

  MV_REFERENCE_FRAME left;
  MV_REFERENCE_FRAME above;
  MV_REFERENCE_FRAME above_left;
  MV_REFERENCE_FRAME pred_ref = LAST_FRAME;

  int segment_id = xd->mode_info_context->mbmi.segment_id;
  int i;

  unsigned char frame_allowed[MAX_REF_FRAMES] = {1, 1, 1, 1};
  unsigned char ref_score[MAX_REF_FRAMES];
  unsigned char best_score = 0;
  unsigned char left_in_image;
  unsigned char above_in_image;
  unsigned char above_left_in_image;

  // Is segment coding ennabled
  int seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME);

  // Special case treatment if segment coding is enabled.
  // Dont allow prediction of a reference frame that the segment
  // does not allow
  if (seg_ref_active) {
    for (i = 0; i < MAX_REF_FRAMES; i++) {
      frame_allowed[i] =
        vp9_check_segref(xd, segment_id, i);

      // Score set to 0 if ref frame not allowed
      ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
    }
  } else
    vpx_memcpy(ref_score, cm->ref_scores, sizeof(ref_score));

  // Reference frames used by neighbours
  left = (m - 1)->mbmi.ref_frame;
  above = (m - cm->mode_info_stride)->mbmi.ref_frame;
  above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame;

  // Are neighbours in image
  left_in_image = (m - 1)->mbmi.mb_in_image && xd->left_available;
  above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
  above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image &&
                        xd->left_available;

  // Adjust scores for candidate reference frames based on neigbours
  if (frame_allowed[left] && left_in_image) {
    ref_score[left] += 16;
    if (above_left_in_image && (left == above_left))
      ref_score[left] += 4;
  }
  if (frame_allowed[above] && above_in_image) {
    ref_score[above] += 16;
    if (above_left_in_image && (above == above_left))
      ref_score[above] += 4;
  }

  // Now choose the candidate with the highest score
  for (i = 0; i < MAX_REF_FRAMES; i++) {
    if (ref_score[i] > best_score) {
      pred_ref = i;
      best_score = ref_score[i];
    }
  }

  return pred_ref;
}