| Index: source/libvpx/vp9/common/vp9_pred_common.c
|
| ===================================================================
|
| --- source/libvpx/vp9/common/vp9_pred_common.c (revision 0)
|
| +++ source/libvpx/vp9/common/vp9_pred_common.c (revision 0)
|
| @@ -0,0 +1,465 @@
|
| +
|
| +/*
|
| + * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "vp9/common/vp9_pred_common.h"
|
| +#include "vp9/common/vp9_seg_common.h"
|
| +
|
| +// TBD prediction functions for various bitstream signals
|
| +
|
| +// Returns a context number for the given MB prediction signal
|
| +unsigned char vp9_get_pred_context(const VP9_COMMON *const cm,
|
| + const MACROBLOCKD *const xd,
|
| + PRED_ID pred_id) {
|
| + int pred_context;
|
| + MODE_INFO *m = xd->mode_info_context;
|
| +
|
| + // 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.
|
| + switch (pred_id) {
|
| + case PRED_SEG_ID:
|
| + pred_context = (m - 1)->mbmi.seg_id_predicted +
|
| + (m - cm->mode_info_stride)->mbmi.seg_id_predicted;
|
| + break;
|
| +
|
| +
|
| + case PRED_REF:
|
| + pred_context = (m - 1)->mbmi.ref_predicted +
|
| + (m - cm->mode_info_stride)->mbmi.ref_predicted;
|
| + break;
|
| +
|
| + case PRED_COMP:
|
| + // Context based on use of comp pred flag by neighbours
|
| + // pred_context =
|
| + // ((m - 1)->mbmi.second_ref_frame > INTRA_FRAME) +
|
| + // ((m - cm->mode_info_stride)->mbmi.second_ref_frame > INTRA_FRAME);
|
| +
|
| + // Context based on mode and reference frame
|
| + // if ( m->mbmi.ref_frame == LAST_FRAME )
|
| + // pred_context = 0 + (m->mbmi.mode != ZEROMV);
|
| + // else if ( m->mbmi.ref_frame == GOLDEN_FRAME )
|
| + // pred_context = 2 + (m->mbmi.mode != ZEROMV);
|
| + // else
|
| + // pred_context = 4 + (m->mbmi.mode != ZEROMV);
|
| +
|
| + if (m->mbmi.ref_frame == LAST_FRAME)
|
| + pred_context = 0;
|
| + else
|
| + pred_context = 1;
|
| +
|
| + break;
|
| +
|
| + case PRED_MBSKIP:
|
| + pred_context = (m - 1)->mbmi.mb_skip_coeff +
|
| + (m - cm->mode_info_stride)->mbmi.mb_skip_coeff;
|
| + break;
|
| +
|
| + case PRED_SWITCHABLE_INTERP:
|
| + {
|
| + int left_in_image = (m - 1)->mbmi.mb_in_image;
|
| + int above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
|
| + int left_mode = (m - 1)->mbmi.mode;
|
| + int above_mode = (m - cm->mode_info_stride)->mbmi.mode;
|
| + int left_interp, above_interp;
|
| + if (left_in_image && left_mode >= NEARESTMV && left_mode <= SPLITMV)
|
| + left_interp = vp9_switchable_interp_map[(m - 1)->mbmi.interp_filter];
|
| + else
|
| + left_interp = VP9_SWITCHABLE_FILTERS;
|
| + assert(left_interp != -1);
|
| + if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV)
|
| + above_interp = vp9_switchable_interp_map[
|
| + (m - cm->mode_info_stride)->mbmi.interp_filter];
|
| + else
|
| + above_interp = VP9_SWITCHABLE_FILTERS;
|
| + assert(above_interp != -1);
|
| +
|
| + if (left_interp == above_interp)
|
| + pred_context = left_interp;
|
| + else if (left_interp == VP9_SWITCHABLE_FILTERS &&
|
| + above_interp != VP9_SWITCHABLE_FILTERS)
|
| + pred_context = above_interp;
|
| + else if (left_interp != VP9_SWITCHABLE_FILTERS &&
|
| + above_interp == VP9_SWITCHABLE_FILTERS)
|
| + pred_context = left_interp;
|
| + else
|
| + pred_context = VP9_SWITCHABLE_FILTERS;
|
| + }
|
| + break;
|
| +
|
| + default:
|
| + // TODO *** add error trap code.
|
| + pred_context = 0;
|
| + break;
|
| + }
|
| +
|
| + return pred_context;
|
| +}
|
| +
|
| +// This function returns a context probability for coding a given
|
| +// prediction signal
|
| +vp9_prob vp9_get_pred_prob(const VP9_COMMON *const cm,
|
| + const MACROBLOCKD *const xd,
|
| + PRED_ID pred_id) {
|
| + vp9_prob pred_probability;
|
| + int pred_context;
|
| +
|
| + // Get the appropriate prediction context
|
| + pred_context = vp9_get_pred_context(cm, xd, pred_id);
|
| +
|
| + switch (pred_id) {
|
| + case PRED_SEG_ID:
|
| + pred_probability = cm->segment_pred_probs[pred_context];
|
| + break;
|
| +
|
| + case PRED_REF:
|
| + pred_probability = cm->ref_pred_probs[pred_context];
|
| + break;
|
| +
|
| + case PRED_COMP:
|
| + // In keeping with convention elsewhre the probability returned is
|
| + // the probability of a "0" outcome which in this case means the
|
| + // probability of comp pred off.
|
| + pred_probability = cm->prob_comppred[pred_context];
|
| + break;
|
| +
|
| + case PRED_MBSKIP:
|
| + pred_probability = cm->mbskip_pred_probs[pred_context];
|
| + break;
|
| +
|
| + default:
|
| + // TODO *** add error trap code.
|
| + pred_probability = 128;
|
| + break;
|
| + }
|
| +
|
| + return pred_probability;
|
| +}
|
| +
|
| +// This function returns a context probability ptr for coding a given
|
| +// prediction signal
|
| +const vp9_prob *vp9_get_pred_probs(const VP9_COMMON *const cm,
|
| + const MACROBLOCKD *const xd,
|
| + PRED_ID pred_id) {
|
| + const vp9_prob *pred_probability;
|
| + int pred_context;
|
| +
|
| + // Get the appropriate prediction context
|
| + pred_context = vp9_get_pred_context(cm, xd, pred_id);
|
| +
|
| + switch (pred_id) {
|
| + case PRED_SEG_ID:
|
| + pred_probability = &cm->segment_pred_probs[pred_context];
|
| + break;
|
| +
|
| + case PRED_REF:
|
| + pred_probability = &cm->ref_pred_probs[pred_context];
|
| + break;
|
| +
|
| + case PRED_COMP:
|
| + // In keeping with convention elsewhre the probability returned is
|
| + // the probability of a "0" outcome which in this case means the
|
| + // probability of comp pred off.
|
| + pred_probability = &cm->prob_comppred[pred_context];
|
| + break;
|
| +
|
| + case PRED_MBSKIP:
|
| + pred_probability = &cm->mbskip_pred_probs[pred_context];
|
| + break;
|
| +
|
| + case PRED_SWITCHABLE_INTERP:
|
| + pred_probability = &cm->fc.switchable_interp_prob[pred_context][0];
|
| + break;
|
| +
|
| + default:
|
| + // TODO *** add error trap code.
|
| + pred_probability = NULL;
|
| + break;
|
| + }
|
| +
|
| + return pred_probability;
|
| +}
|
| +
|
| +// This function returns the status of the given prediction signal.
|
| +// I.e. is the predicted value for the given signal correct.
|
| +unsigned char vp9_get_pred_flag(const MACROBLOCKD *const xd,
|
| + PRED_ID pred_id) {
|
| + unsigned char pred_flag = 0;
|
| +
|
| + switch (pred_id) {
|
| + case PRED_SEG_ID:
|
| + pred_flag = xd->mode_info_context->mbmi.seg_id_predicted;
|
| + break;
|
| +
|
| + case PRED_REF:
|
| + pred_flag = xd->mode_info_context->mbmi.ref_predicted;
|
| + break;
|
| +
|
| + case PRED_MBSKIP:
|
| + pred_flag = xd->mode_info_context->mbmi.mb_skip_coeff;
|
| + break;
|
| +
|
| + default:
|
| + // TODO *** add error trap code.
|
| + pred_flag = 0;
|
| + break;
|
| + }
|
| +
|
| + return pred_flag;
|
| +}
|
| +
|
| +// This function sets the status of the given prediction signal.
|
| +// I.e. is the predicted value for the given signal correct.
|
| +void vp9_set_pred_flag(MACROBLOCKD *const xd,
|
| + PRED_ID pred_id,
|
| + unsigned char pred_flag) {
|
| +#if CONFIG_SUPERBLOCKS
|
| + const int mis = xd->mode_info_stride;
|
| +#endif
|
| +
|
| + switch (pred_id) {
|
| + case PRED_SEG_ID:
|
| + xd->mode_info_context->mbmi.seg_id_predicted = pred_flag;
|
| +#if CONFIG_SUPERBLOCKS
|
| + if (xd->mode_info_context->mbmi.encoded_as_sb) {
|
| + if (xd->mb_to_right_edge >= 0)
|
| + xd->mode_info_context[1].mbmi.seg_id_predicted = pred_flag;
|
| + if (xd->mb_to_bottom_edge >= 0) {
|
| + xd->mode_info_context[mis].mbmi.seg_id_predicted = pred_flag;
|
| + if (xd->mb_to_right_edge >= 0)
|
| + xd->mode_info_context[mis + 1].mbmi.seg_id_predicted = pred_flag;
|
| + }
|
| + }
|
| +#endif
|
| + break;
|
| +
|
| + case PRED_REF:
|
| + xd->mode_info_context->mbmi.ref_predicted = pred_flag;
|
| +#if CONFIG_SUPERBLOCKS
|
| + if (xd->mode_info_context->mbmi.encoded_as_sb) {
|
| + if (xd->mb_to_right_edge >= 0)
|
| + xd->mode_info_context[1].mbmi.ref_predicted = pred_flag;
|
| + if (xd->mb_to_bottom_edge >= 0) {
|
| + xd->mode_info_context[mis].mbmi.ref_predicted = pred_flag;
|
| + if (xd->mb_to_right_edge >= 0)
|
| + xd->mode_info_context[mis + 1].mbmi.ref_predicted = pred_flag;
|
| + }
|
| + }
|
| +#endif
|
| + break;
|
| +
|
| + case PRED_MBSKIP:
|
| + xd->mode_info_context->mbmi.mb_skip_coeff = pred_flag;
|
| +#if CONFIG_SUPERBLOCKS
|
| + if (xd->mode_info_context->mbmi.encoded_as_sb) {
|
| + if (xd->mb_to_right_edge >= 0)
|
| + xd->mode_info_context[1].mbmi.mb_skip_coeff = pred_flag;
|
| + if (xd->mb_to_bottom_edge >= 0) {
|
| + xd->mode_info_context[mis].mbmi.mb_skip_coeff = pred_flag;
|
| + if (xd->mb_to_right_edge >= 0)
|
| + xd->mode_info_context[mis + 1].mbmi.mb_skip_coeff = pred_flag;
|
| + }
|
| + }
|
| +#endif
|
| + break;
|
| +
|
| + default:
|
| + // TODO *** add error trap code.
|
| + break;
|
| + }
|
| +}
|
| +
|
| +
|
| +// The following contain the guts of the prediction code used to
|
| +// peredict various bitstream signals.
|
| +
|
| +// Macroblock segment id prediction function
|
| +unsigned char vp9_get_pred_mb_segid(const VP9_COMMON *const cm,
|
| + const MACROBLOCKD *const xd, int MbIndex) {
|
| + // Currently the prediction for the macroblock segment ID is
|
| + // the value stored for this macroblock in the previous frame.
|
| +#if CONFIG_SUPERBLOCKS
|
| + if (!xd->mode_info_context->mbmi.encoded_as_sb) {
|
| +#endif
|
| + return cm->last_frame_seg_map[MbIndex];
|
| +#if CONFIG_SUPERBLOCKS
|
| + } else {
|
| + int seg_id = cm->last_frame_seg_map[MbIndex];
|
| + int mb_col = MbIndex % cm->mb_cols;
|
| + int mb_row = MbIndex / cm->mb_cols;
|
| + if (mb_col + 1 < cm->mb_cols)
|
| + seg_id = seg_id && cm->last_frame_seg_map[MbIndex + 1];
|
| + if (mb_row + 1 < cm->mb_rows) {
|
| + seg_id = seg_id && cm->last_frame_seg_map[MbIndex + cm->mb_cols];
|
| + if (mb_col + 1 < cm->mb_cols)
|
| + seg_id = seg_id && cm->last_frame_seg_map[MbIndex + cm->mb_cols + 1];
|
| + }
|
| + return seg_id;
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +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 seg_ref_active;
|
| + 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
|
| + 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;
|
| + 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;
|
| +
|
| + // 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;
|
| +}
|
| +
|
| +// Functions to computes a set of modified reference frame probabilities
|
| +// to use when the prediction of the reference frame value fails
|
| +void vp9_calc_ref_probs(int *count, vp9_prob *probs) {
|
| + int tot_count;
|
| +
|
| + tot_count = count[0] + count[1] + count[2] + count[3];
|
| + if (tot_count) {
|
| + probs[0] = (vp9_prob)((count[0] * 255 + (tot_count >> 1)) / tot_count);
|
| + probs[0] += !probs[0];
|
| + } else
|
| + probs[0] = 128;
|
| +
|
| + tot_count -= count[0];
|
| + if (tot_count) {
|
| + probs[1] = (vp9_prob)((count[1] * 255 + (tot_count >> 1)) / tot_count);
|
| + probs[1] += !probs[1];
|
| + } else
|
| + probs[1] = 128;
|
| +
|
| + tot_count -= count[1];
|
| + if (tot_count) {
|
| + probs[2] = (vp9_prob)((count[2] * 255 + (tot_count >> 1)) / tot_count);
|
| + probs[2] += !probs[2];
|
| + } else
|
| + probs[2] = 128;
|
| +
|
| +}
|
| +
|
| +// Computes a set of modified conditional probabilities for the reference frame
|
| +// Values willbe set to 0 for reference frame options that are not possible
|
| +// because wither they were predicted and prediction has failed or because
|
| +// they are not allowed for a given segment.
|
| +void vp9_compute_mod_refprobs(VP9_COMMON *const cm) {
|
| + int norm_cnt[MAX_REF_FRAMES];
|
| + int intra_count;
|
| + int inter_count;
|
| + int last_count;
|
| + int gfarf_count;
|
| + int gf_count;
|
| + int arf_count;
|
| +
|
| + intra_count = cm->prob_intra_coded;
|
| + inter_count = (255 - intra_count);
|
| + last_count = (inter_count * cm->prob_last_coded) / 255;
|
| + gfarf_count = inter_count - last_count;
|
| + gf_count = (gfarf_count * cm->prob_gf_coded) / 255;
|
| + arf_count = gfarf_count - gf_count;
|
| +
|
| + // Work out modified reference frame probabilities to use where prediction
|
| + // of the reference frame fails
|
| + norm_cnt[0] = 0;
|
| + norm_cnt[1] = last_count;
|
| + norm_cnt[2] = gf_count;
|
| + norm_cnt[3] = arf_count;
|
| + vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[INTRA_FRAME]);
|
| + cm->mod_refprobs[INTRA_FRAME][0] = 0; // This branch implicit
|
| +
|
| + norm_cnt[0] = intra_count;
|
| + norm_cnt[1] = 0;
|
| + norm_cnt[2] = gf_count;
|
| + norm_cnt[3] = arf_count;
|
| + vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[LAST_FRAME]);
|
| + cm->mod_refprobs[LAST_FRAME][1] = 0; // This branch implicit
|
| +
|
| + norm_cnt[0] = intra_count;
|
| + norm_cnt[1] = last_count;
|
| + norm_cnt[2] = 0;
|
| + norm_cnt[3] = arf_count;
|
| + vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[GOLDEN_FRAME]);
|
| + cm->mod_refprobs[GOLDEN_FRAME][2] = 0; // This branch implicit
|
| +
|
| + norm_cnt[0] = intra_count;
|
| + norm_cnt[1] = last_count;
|
| + norm_cnt[2] = gf_count;
|
| + norm_cnt[3] = 0;
|
| + vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[ALTREF_FRAME]);
|
| + cm->mod_refprobs[ALTREF_FRAME][2] = 0; // This branch implicit
|
| +
|
| + // Score the reference frames based on overal frequency.
|
| + // These scores contribute to the prediction choices.
|
| + // Max score 17 min 1
|
| + cm->ref_scores[INTRA_FRAME] = 1 + (intra_count * 16 / 255);
|
| + cm->ref_scores[LAST_FRAME] = 1 + (last_count * 16 / 255);
|
| + cm->ref_scores[GOLDEN_FRAME] = 1 + (gf_count * 16 / 255);
|
| + cm->ref_scores[ALTREF_FRAME] = 1 + (arf_count * 16 / 255);
|
| +}
|
|
|
| Property changes on: source/libvpx/vp9/common/vp9_pred_common.c
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|