// This function encodes the reference frame static void write_ref_frames(const VP9_COMMON *cm, const MACROBLOCKD *xd, vpx_writer *w) { const MODE_INFO *const mi = xd->mi[0]; const int is_compound = has_second_ref(mi); const int segment_id = mi->segment_id; // If segment level coding of this signal is disabled... // or the segment allows multiple reference frame options if (segfeature_active(&cm->seg, segment_id, SEG_LVL_REF_FRAME)) { assert(!is_compound); assert(mi->ref_frame[0] == get_segdata(&cm->seg, segment_id, SEG_LVL_REF_FRAME)); } else { // does the feature use compound prediction or not // (if not specified at the frame/segment level) if (cm->reference_mode == REFERENCE_MODE_SELECT) { vpx_write(w, is_compound, vp9_get_reference_mode_prob(cm, xd)); } else { assert(!is_compound == (cm->reference_mode == SINGLE_REFERENCE)); } if (is_compound) { vpx_write(w, mi->ref_frame[0] == GOLDEN_FRAME, vp9_get_pred_prob_comp_ref_p(cm, xd)); } else { const int bit0 = mi->ref_frame[0] != LAST_FRAME; vpx_write(w, bit0, vp9_get_pred_prob_single_ref_p1(cm, xd)); if (bit0) { const int bit1 = mi->ref_frame[0] != GOLDEN_FRAME; vpx_write(w, bit1, vp9_get_pred_prob_single_ref_p2(cm, xd)); } } } }
unsigned char vp9_get_pred_context_comp_inter_inter(const VP9_COMMON *cm, const MACROBLOCKD *xd) { int pred_context; const MODE_INFO *const above_mi = get_above_mi(xd); const MODE_INFO *const left_mi = get_left_mi(xd); const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi); const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi); const int above_in_image = above_mi != NULL; const int left_in_image = left_mi != NULL; if (above_in_image && left_in_image) { if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi)) pred_context = (above_mbmi->ref_frame[0] == cm->comp_fixed_ref) ^ (left_mbmi->ref_frame[0] == cm->comp_fixed_ref); else if (!has_second_ref(above_mbmi)) pred_context = 2 + (above_mbmi->ref_frame[0] == cm->comp_fixed_ref || !is_inter_block(above_mbmi)); else if (!has_second_ref(left_mbmi)) pred_context = 2 + (left_mbmi->ref_frame[0] == cm->comp_fixed_ref || !is_inter_block(left_mbmi)); else pred_context = 4; } else if (above_in_image || left_in_image) { const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi; if (!has_second_ref(edge_mbmi)) pred_context = edge_mbmi->ref_frame[0] == cm->comp_fixed_ref; else pred_context = 3; } else { pred_context = 1; } assert(pred_context >= 0 && pred_context < COMP_INTER_CONTEXTS); return pred_context; }
int vp9_get_reference_mode_context(const VP9_COMMON *cm, const MACROBLOCKD *xd) { int ctx; const MODE_INFO *const above_mi = xd->above_mi; const MODE_INFO *const left_mi = xd->left_mi; const int has_above = !!above_mi; const int has_left = !!left_mi; // 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_mi) && !has_second_ref(left_mi)) // neither edge uses comp pred (0/1) ctx = (above_mi->ref_frame[0] == cm->comp_fixed_ref) ^ (left_mi->ref_frame[0] == cm->comp_fixed_ref); else if (!has_second_ref(above_mi)) // one of two edges uses comp pred (2/3) ctx = 2 + (above_mi->ref_frame[0] == cm->comp_fixed_ref || !is_inter_block(above_mi)); else if (!has_second_ref(left_mi)) // one of two edges uses comp pred (2/3) ctx = 2 + (left_mi->ref_frame[0] == cm->comp_fixed_ref || !is_inter_block(left_mi)); else // both edges use comp pred (4) ctx = 4; } else if (has_above || has_left) { // one edge available const MODE_INFO *edge_mi = has_above ? above_mi : left_mi; if (!has_second_ref(edge_mi)) // edge does not use comp pred (0/1) ctx = edge_mi->ref_frame[0] == cm->comp_fixed_ref; else // edge uses comp pred (3) ctx = 3; } else { // no edges available (1) ctx = 1; } assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS); return ctx; }
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); } }
static void pack_inter_mode_mvs(VP9_COMP *cpi, const MODE_INFO *mi, vpx_writer *w) { VP9_COMMON *const cm = &cpi->common; const nmv_context *nmvc = &cm->fc->nmvc; const MACROBLOCK *const x = &cpi->td.mb; const MACROBLOCKD *const xd = &x->e_mbd; const struct segmentation *const seg = &cm->seg; const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext; const PREDICTION_MODE mode = mi->mode; const int segment_id = mi->segment_id; const BLOCK_SIZE bsize = mi->sb_type; const int allow_hp = cm->allow_high_precision_mv; const int is_inter = is_inter_block(mi); const int is_compound = has_second_ref(mi); int skip, ref; if (seg->update_map) { if (seg->temporal_update) { const int pred_flag = mi->seg_id_predicted; vpx_prob pred_prob = vp9_get_pred_prob_seg_id(seg, xd); vpx_write(w, pred_flag, pred_prob); if (!pred_flag) write_segment_id(w, seg, segment_id); } else { write_segment_id(w, seg, segment_id); } } skip = write_skip(cm, xd, segment_id, mi, w); if (!segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) vpx_write(w, is_inter, vp9_get_intra_inter_prob(cm, xd)); if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT && !(is_inter && skip)) { write_selected_tx_size(cm, xd, w); } if (!is_inter) { if (bsize >= BLOCK_8X8) { write_intra_mode(w, mode, cm->fc->y_mode_prob[size_group_lookup[bsize]]); } else { int idx, idy; const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; for (idy = 0; idy < 2; idy += num_4x4_h) { for (idx = 0; idx < 2; idx += num_4x4_w) { const PREDICTION_MODE b_mode = mi->bmi[idy * 2 + idx].as_mode; write_intra_mode(w, b_mode, cm->fc->y_mode_prob[0]); } } } write_intra_mode(w, mi->uv_mode, cm->fc->uv_mode_prob[mode]); } else { const int mode_ctx = mbmi_ext->mode_context[mi->ref_frame[0]]; const vpx_prob *const inter_probs = cm->fc->inter_mode_probs[mode_ctx]; write_ref_frames(cm, xd, w); // If segment skip is not enabled code the mode. if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) { if (bsize >= BLOCK_8X8) { write_inter_mode(w, mode, inter_probs); } } if (cm->interp_filter == SWITCHABLE) { const int ctx = vp9_get_pred_context_switchable_interp(xd); vp9_write_token(w, vp9_switchable_interp_tree, cm->fc->switchable_interp_prob[ctx], &switchable_interp_encodings[mi->interp_filter]); ++cpi->interp_filter_selected[0][mi->interp_filter]; } else { assert(mi->interp_filter == cm->interp_filter); } if (bsize < BLOCK_8X8) { const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; int idx, idy; for (idy = 0; idy < 2; idy += num_4x4_h) { for (idx = 0; idx < 2; idx += num_4x4_w) { const int j = idy * 2 + idx; const PREDICTION_MODE b_mode = mi->bmi[j].as_mode; write_inter_mode(w, b_mode, inter_probs); if (b_mode == NEWMV) { for (ref = 0; ref < 1 + is_compound; ++ref) vp9_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv, &mbmi_ext->ref_mvs[mi->ref_frame[ref]][0].as_mv, nmvc, allow_hp); } } } } else { if (mode == NEWMV) { for (ref = 0; ref < 1 + is_compound; ++ref) vp9_encode_mv(cpi, w, &mi->mv[ref].as_mv, &mbmi_ext->ref_mvs[mi->ref_frame[ref]][0].as_mv, nmvc, allow_hp); } } } }
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); } }
unsigned char vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) { int pred_context; const MODE_INFO *const above_mi = get_above_mi(xd); const MODE_INFO *const left_mi = get_left_mi(xd); const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi); const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi); const int above_in_image = above_mi != NULL; const int left_in_image = left_mi != NULL; const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1; const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1; if (above_in_image && left_in_image) { if (above_intra && left_intra) { pred_context = 2; } else if (above_intra || left_intra) { const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi; if (!has_second_ref(edge_mbmi)) { if (edge_mbmi->ref_frame[0] == LAST_FRAME) pred_context = 3; else pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME); } else { pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME || edge_mbmi->ref_frame[1] == GOLDEN_FRAME); } } else { if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi)) { if (above_mbmi->ref_frame[0] == LAST_FRAME && left_mbmi->ref_frame[0] == LAST_FRAME) { pred_context = 3; } else if (above_mbmi->ref_frame[0] == LAST_FRAME || left_mbmi->ref_frame[0] == LAST_FRAME) { const MB_MODE_INFO *edge_mbmi = above_mbmi->ref_frame[0] == LAST_FRAME ? left_mbmi : above_mbmi; pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME); } else { pred_context = 2 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME) + 2 * (left_mbmi->ref_frame[0] == GOLDEN_FRAME); } } else if (has_second_ref(above_mbmi) && has_second_ref(left_mbmi)) { if (above_mbmi->ref_frame[0] == left_mbmi->ref_frame[0] && above_mbmi->ref_frame[1] == left_mbmi->ref_frame[1]) pred_context = 3 * (above_mbmi->ref_frame[0] == GOLDEN_FRAME || above_mbmi->ref_frame[1] == GOLDEN_FRAME || left_mbmi->ref_frame[0] == GOLDEN_FRAME || left_mbmi->ref_frame[1] == GOLDEN_FRAME); else pred_context = 2; } else { const MV_REFERENCE_FRAME rfs = !has_second_ref(above_mbmi) ? above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0]; const MV_REFERENCE_FRAME crf1 = has_second_ref(above_mbmi) ? above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0]; const MV_REFERENCE_FRAME crf2 = has_second_ref(above_mbmi) ? above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1]; if (rfs == GOLDEN_FRAME) pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME); else if (rfs == ALTREF_FRAME) pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME; else pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME); } } } else if (above_in_image || left_in_image) { const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi; if (!is_inter_block(edge_mbmi) || (edge_mbmi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mbmi))) pred_context = 2; else if (!has_second_ref(edge_mbmi)) pred_context = 4 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME); else pred_context = 3 * (edge_mbmi->ref_frame[0] == GOLDEN_FRAME || edge_mbmi->ref_frame[1] == GOLDEN_FRAME); } else { pred_context = 2; } assert(pred_context >= 0 && pred_context < REF_CONTEXTS); return pred_context; }
unsigned char vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm, const MACROBLOCKD *xd) { int pred_context; const MODE_INFO *const above_mi = get_above_mi(xd); const MODE_INFO *const left_mi = get_left_mi(xd); const MB_MODE_INFO *const above_mbmi = get_above_mbmi(above_mi); const MB_MODE_INFO *const left_mbmi = get_left_mbmi(left_mi); const int above_in_image = above_mi != NULL; const int left_in_image = left_mi != NULL; const int above_intra = above_in_image ? !is_inter_block(above_mbmi) : 1; const int left_intra = left_in_image ? !is_inter_block(left_mbmi) : 1; 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) { if (above_intra && left_intra) { pred_context = 2; } else if (above_intra || left_intra) { const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi; if (!has_second_ref(edge_mbmi)) pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]); else pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]); } else { const int l_sg = !has_second_ref(left_mbmi); const int a_sg = !has_second_ref(above_mbmi); MV_REFERENCE_FRAME vrfa = a_sg ? above_mbmi->ref_frame[0] : above_mbmi->ref_frame[var_ref_idx]; MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0] : left_mbmi->ref_frame[var_ref_idx]; if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) { pred_context = 0; } else if (l_sg && a_sg) { 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) { MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl; 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) { pred_context = 4; } else { pred_context = 2; } } } else if (above_in_image || left_in_image) { 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)) pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]); else pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_var_ref[1]); } } else { pred_context = 2; } assert(pred_context >= 0 && pred_context < REF_CONTEXTS); return pred_context; }
// Returns a context number for the given MB prediction signal int vp9_get_pred_context_comp_ref_p(const VP9_COMMON *cm, const MACROBLOCKD *xd) { int pred_context; const MODE_INFO *const above_mi = xd->above_mi; const MODE_INFO *const left_mi = xd->left_mi; const int above_in_image = !!above_mi; const int left_in_image = !!left_mi; // 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. 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_mi); const int left_intra = !is_inter_block(left_mi); if (above_intra && left_intra) { // intra/intra (2) pred_context = 2; } else if (above_intra || left_intra) { // intra/inter const MODE_INFO *edge_mi = above_intra ? left_mi : above_mi; if (!has_second_ref(edge_mi)) // single pred (1/3) pred_context = 1 + 2 * (edge_mi->ref_frame[0] != cm->comp_var_ref[1]); else // comp pred (1/3) pred_context = 1 + 2 * (edge_mi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]); } else { // inter/inter const int l_sg = !has_second_ref(left_mi); const int a_sg = !has_second_ref(above_mi); const MV_REFERENCE_FRAME vrfa = a_sg ? above_mi->ref_frame[0] : above_mi->ref_frame[var_ref_idx]; const MV_REFERENCE_FRAME vrfl = l_sg ? left_mi->ref_frame[0] : left_mi->ref_frame[var_ref_idx]; 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 MODE_INFO *edge_mi = above_in_image ? above_mi : left_mi; if (!is_inter_block(edge_mi)) { pred_context = 2; } else { if (has_second_ref(edge_mi)) pred_context = 4 * (edge_mi->ref_frame[var_ref_idx] != cm->comp_var_ref[1]); else pred_context = 3 * (edge_mi->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; }
int vp9_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) { int pred_context; const MODE_INFO *const above_mi = xd->above_mi; const MODE_INFO *const left_mi = xd->left_mi; const int has_above = !!above_mi; const int has_left = !!left_mi; // 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 const int above_intra = !is_inter_block(above_mi); const int left_intra = !is_inter_block(left_mi); if (above_intra && left_intra) { // intra/intra pred_context = 2; } else if (above_intra || left_intra) { // intra/inter or inter/intra const MODE_INFO *edge_mi = above_intra ? left_mi : above_mi; if (!has_second_ref(edge_mi)) { if (edge_mi->ref_frame[0] == LAST_FRAME) pred_context = 3; else pred_context = 4 * (edge_mi->ref_frame[0] == GOLDEN_FRAME); } else { pred_context = 1 + 2 * (edge_mi->ref_frame[0] == GOLDEN_FRAME || edge_mi->ref_frame[1] == GOLDEN_FRAME); } } else { // inter/inter const int above_has_second = has_second_ref(above_mi); const int left_has_second = has_second_ref(left_mi); const MV_REFERENCE_FRAME above0 = above_mi->ref_frame[0]; const MV_REFERENCE_FRAME above1 = above_mi->ref_frame[1]; const MV_REFERENCE_FRAME left0 = left_mi->ref_frame[0]; const MV_REFERENCE_FRAME left1 = left_mi->ref_frame[1]; if (above_has_second && left_has_second) { if (above0 == left0 && above1 == left1) pred_context = 3 * (above0 == GOLDEN_FRAME || above1 == GOLDEN_FRAME || left0 == GOLDEN_FRAME || left1 == GOLDEN_FRAME); else pred_context = 2; } else if (above_has_second || left_has_second) { 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; if (rfs == GOLDEN_FRAME) pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME); else if (rfs == ALTREF_FRAME) pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME; else pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME); } else { if (above0 == LAST_FRAME && left0 == LAST_FRAME) { pred_context = 3; } else if (above0 == LAST_FRAME || left0 == LAST_FRAME) { const MV_REFERENCE_FRAME edge0 = (above0 == LAST_FRAME) ? left0 : above0; pred_context = 4 * (edge0 == GOLDEN_FRAME); } else { pred_context = 2 * (above0 == GOLDEN_FRAME) + 2 * (left0 == GOLDEN_FRAME); } } } } else if (has_above || has_left) { // one edge available const MODE_INFO *edge_mi = has_above ? above_mi : left_mi; if (!is_inter_block(edge_mi) || (edge_mi->ref_frame[0] == LAST_FRAME && !has_second_ref(edge_mi))) pred_context = 2; else if (!has_second_ref(edge_mi)) pred_context = 4 * (edge_mi->ref_frame[0] == GOLDEN_FRAME); else pred_context = 3 * (edge_mi->ref_frame[0] == GOLDEN_FRAME || edge_mi->ref_frame[1] == GOLDEN_FRAME); } else { // no edges available (2) pred_context = 2; } assert(pred_context >= 0 && pred_context < REF_CONTEXTS); return pred_context; }
int vp9_get_pred_context_single_ref_p1(const MACROBLOCKD *xd) { int pred_context; const MB_MODE_INFO *const above_mbmi = get_mbmi(get_above_mi(xd)); const MB_MODE_INFO *const left_mbmi = get_mbmi(get_left_mi(xd)); const int has_above = above_mbmi != NULL; const int has_left = left_mbmi != NULL; // 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; if (!has_second_ref(edge_mbmi)) pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME); else pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME || edge_mbmi->ref_frame[1] == LAST_FRAME); } else { // inter/inter const int above_has_second = has_second_ref(above_mbmi); const int left_has_second = has_second_ref(left_mbmi); if (above_has_second && left_has_second) { pred_context = 1 + (above_mbmi->ref_frame[0] == LAST_FRAME || above_mbmi->ref_frame[1] == LAST_FRAME || left_mbmi->ref_frame[0] == LAST_FRAME || left_mbmi->ref_frame[1] == LAST_FRAME); } else if (above_has_second || left_has_second) { const MV_REFERENCE_FRAME rfs = !above_has_second ? above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0]; const MV_REFERENCE_FRAME crf1 = above_has_second ? above_mbmi->ref_frame[0] : left_mbmi->ref_frame[0]; const MV_REFERENCE_FRAME crf2 = above_has_second ? above_mbmi->ref_frame[1] : left_mbmi->ref_frame[1]; if (rfs == LAST_FRAME) pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME); else pred_context = (crf1 == LAST_FRAME || crf2 == LAST_FRAME); } else { pred_context = 2 * (above_mbmi->ref_frame[0] == LAST_FRAME) + 2 * (left_mbmi->ref_frame[0] == LAST_FRAME); } } } 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; } else { // inter if (!has_second_ref(edge_mbmi)) pred_context = 4 * (edge_mbmi->ref_frame[0] == LAST_FRAME); else pred_context = 1 + (edge_mbmi->ref_frame[0] == LAST_FRAME || edge_mbmi->ref_frame[1] == LAST_FRAME); } } else { // no edges available pred_context = 2; } assert(pred_context >= 0 && pred_context < REF_CONTEXTS); return pred_context; }