From b2f64dff7dd60ae5e0e0ff994b298545dc340846 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Sat, 28 Jan 2012 10:07:08 +0000 Subject: [PATCH] Added common prediction modules. This function adds the common prediction modules, some data structures and a config option but does not use them. It also corrects a bug in clearing down the MODE_INFO border and introduces a new element that indicates if an entry corresponds to an "in image" macro block or is part of the border. Change-Id: Ib69eec0876173ebe9d1de9df9537d0b2447702e0 --- configure | 1 + vp8/common/alloccommon.c | 40 ++++-- vp8/common/blockd.h | 9 ++ vp8/common/onyxc_int.h | 5 + vp8/common/pred_common.c | 297 +++++++++++++++++++++++++++++++++++++++ vp8/common/pred_common.h | 56 ++++++++ vp8/vp8_common.mk | 3 +- 7 files changed, 401 insertions(+), 10 deletions(-) create mode 100644 vp8/common/pred_common.c create mode 100644 vp8/common/pred_common.h diff --git a/configure b/configure index c6bce0461..cdb5f4d1f 100755 --- a/configure +++ b/configure @@ -226,6 +226,7 @@ EXPERIMENT_LIST=" qimode uvintra newnear + compred newlpf enhanced_interp " diff --git a/vp8/common/alloccommon.c b/vp8/common/alloccommon.c index e643eff09..c49927c2c 100644 --- a/vp8/common/alloccommon.c +++ b/vp8/common/alloccommon.c @@ -20,17 +20,37 @@ extern void vp8_init_scan_order_mask(); -static void update_mode_info_border(MODE_INFO *mi, int rows, int cols) +static void update_mode_info_border( VP8_COMMON *cpi, MODE_INFO *mi_base ) { + int stride = cpi->mode_info_stride; int i; - vpx_memset(mi - cols - 2, 0, sizeof(MODE_INFO) * (cols + 1)); - for (i = 0; i < rows; i++) + // Clear down top border row + vpx_memset(mi_base, 0, sizeof(MODE_INFO) * cpi->mode_info_stride); + + // Clear left border column + for (i = 1; i < cpi->mb_rows+1; i++) { - /* TODO(holmer): Bug? This updates the last element of each row - * rather than the border element! - */ - vpx_memset(&mi[i*cols-1], 0, sizeof(MODE_INFO)); + vpx_memset(&mi_base[i*stride], 0, sizeof(MODE_INFO)); + } +} +static void update_mode_info_in_image( VP8_COMMON *cpi, MODE_INFO *mi ) +{ + int stride = cpi->mode_info_stride; + int rows = cpi->mb_rows; + int cols = cpi->mb_cols; + int i, j; + + // For each in image mode_info element set the in image flag to 1 + for (i = 0; i < cpi->mb_rows; i++) + { + for (j = 0; j < cpi->mb_cols; j++) + { + mi->mbmi.mb_in_image = 1; + mi++; // Next element in the row + } + + mi++; // Step over border element at start of next row } } @@ -139,9 +159,11 @@ int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height) return 1; } - update_mode_info_border(oci->mi, oci->mb_rows, oci->mb_cols); + update_mode_info_border(oci, oci->mip); + update_mode_info_in_image(oci, oci->mi); #if CONFIG_ERROR_CONCEALMENT - update_mode_info_border(oci->prev_mi, oci->mb_rows, oci->mb_cols); + update_mode_info_border(oci, oci->prev_mip); + update_mode_info_in_image(oci, oci->prev_mi); #endif return 0; diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h index 9c1453e2a..a2c5426ea 100644 --- a/vp8/common/blockd.h +++ b/vp8/common/blockd.h @@ -194,6 +194,15 @@ typedef struct // Flags used for prediction status of various bistream signals unsigned char seg_id_predicted; +#if CONFIG_COMPRED + unsigned char ref_predicted; +#endif + + // Indicates if the mb is part of the image (1) vs border (0) + // This can be useful in determining whether the MB provides + // a valid predictor + unsigned char mb_in_image; + } MB_MODE_INFO; typedef struct diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h index 75c1c001d..fd6a55801 100644 --- a/vp8/common/onyxc_int.h +++ b/vp8/common/onyxc_int.h @@ -234,6 +234,11 @@ typedef struct VP8Common vp8_prob segment_pred_probs[PREDICTION_PROBS]; unsigned char temporal_update; +#if CONFIG_COMPRED + // Context probabilities for reference frame prediction + vp8_prob ref_pred_probs[PREDICTION_PROBS]; + vp8_prob mod_refprobs[MAX_REF_FRAMES][PREDICTION_PROBS]; +#endif FRAME_CONTEXT lfc_a; /* last alt ref entropy */ FRAME_CONTEXT lfc; /* last frame entropy */ diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c new file mode 100644 index 000000000..1d1d107ea --- /dev/null +++ b/vp8/common/pred_common.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2010 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 "vp8/common/pred_common.h" + +// TBD prediction functions for various bitstream signals + +// Returns a context number for the given MB prediction signal +unsigned char get_pred_context( VP8_COMMON *const cm, + 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; + + +#if CONFIG_COMPRED + + case PRED_REF: + pred_context = (m - 1)->mbmi.ref_predicted + + (m - cm->mode_info_stride)->mbmi.ref_predicted; + break; +#endif + + 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 +vp8_prob get_pred_prob( VP8_COMMON *const cm, + MACROBLOCKD *const xd, + PRED_ID pred_id ) +{ + vp8_prob pred_probability; + int pred_context; + + // Get the appropriate prediction context + pred_context = get_pred_context( cm, xd, pred_id ); + + switch (pred_id) + { + case PRED_SEG_ID: + pred_probability = cm->segment_pred_probs[pred_context]; + break; + +#if CONFIG_COMPRED + + case PRED_REF: + pred_probability = cm->ref_pred_probs[pred_context]; + break; +#endif + + default: + // TODO *** add error trap code. + pred_probability = 128; + 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 get_pred_flag( 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; + +#if CONFIG_COMPRED + + case PRED_REF: + pred_flag = xd->mode_info_context->mbmi.ref_predicted; + break; +#endif + + 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 set_pred_flag( MACROBLOCKD *const xd, + PRED_ID pred_id, + unsigned char pred_flag) +{ + switch (pred_id) + { + case PRED_SEG_ID: + xd->mode_info_context->mbmi.seg_id_predicted = pred_flag; + break; + +#if CONFIG_COMPRED + + case PRED_REF: + xd->mode_info_context->mbmi.ref_predicted = pred_flag; + break; +#endif + + 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 get_pred_mb_segid( VP8_COMMON *const cm, int MbIndex ) +{ + // Currently the prediction for the macroblock segment ID is + // the value stored for this macroblock in the previous frame. + return cm->last_frame_seg_map[MbIndex]; +} + +#if CONFIG_COMPRED +MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, + MACROBLOCKD *const xd ) +{ + MODE_INFO *m = xd->mode_info_context; + + unsigned char left_pred; + unsigned char above_pred; + + MV_REFERENCE_FRAME left; + MV_REFERENCE_FRAME above; + MV_REFERENCE_FRAME above_left; + MV_REFERENCE_FRAME pred_ref = LAST_FRAME; + + // Reference frame 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; + + // Reference frame prediction status of immediate neigbours. + // This can only be set if the mb is "in image" + left_pred = (m - 1)->mbmi.ref_predicted; + above_pred = (m - cm->mode_info_stride)->mbmi.ref_predicted; + + // Boost prediction scores of above / left if they are predicted and match + // the above left. + if ( left_pred ) + left_pred += (left == above_left); + if ( above_pred ) + above_pred += (above == above_left); + + // Only consider "in image" mbs as giving valid prediction. + if ( (left == above) && + ((m - 1)->mbmi.mb_in_image || + (m - cm->mode_info_stride)->mbmi.mb_in_image) ) + { + pred_ref = left; + } + else if ( left_pred > above_pred ) + { + pred_ref = left; + } + else if ( above_pred > left_pred ) + { + pred_ref = above; + } + else + { + // Choose from above or left. + // For now this is based on a fixed preference order. + // Last,Altref,Golden + if ( (left == LAST_FRAME) || (above == LAST_FRAME) ) + pred_ref = LAST_FRAME; + else if ( (left == ALTREF_FRAME) || (above == ALTREF_FRAME) ) + pred_ref = ALTREF_FRAME; + else if ( (left == GOLDEN_FRAME) || (above == GOLDEN_FRAME) ) + pred_ref = GOLDEN_FRAME; + } + + 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 calc_ref_probs( int * count, vp8_prob * probs ) +{ + int tot_count; + + tot_count = count[0] + count[1] + count[2] + count[3]; + if ( tot_count ) + { + probs[0] = (vp8_prob)((count[0] * 255) / tot_count); + probs[0] += !probs[0]; + } + else + probs[0] = 128; + + tot_count -= count[0]; + if ( tot_count ) + { + probs[1] = (vp8_prob)((count[1] * 255) / tot_count); + probs[1] += !probs[1]; + } + else + probs[1] = 128; + + tot_count -= count[1]; + if ( tot_count ) + { + probs[2] = (vp8_prob)((count[2] * 255) / tot_count); + probs[2] += !probs[2]; + } + else + probs[2] = 128; + +} + +void compute_mod_refprobs( VP8_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; + 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; + 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; + 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; + calc_ref_probs( norm_cnt, cm->mod_refprobs[ALTREF_FRAME] ); + cm->mod_refprobs[ALTREF_FRAME][2] = 0; // This branch implicit + +} +#endif diff --git a/vp8/common/pred_common.h b/vp8/common/pred_common.h new file mode 100644 index 000000000..60476f9c5 --- /dev/null +++ b/vp8/common/pred_common.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010 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 "type_aliases.h" +#include "onyxc_int.h" +#include "vp8/common/blockd.h" + +#ifndef __INC_PRED_COMMON_H__ +#define __INC_PRED_COMMON_H__ 1 + + +// Predicted items +typedef enum +{ + PRED_SEG_ID = 0, // Segment identifier + +#if CONFIG_COMPRED + PRED_REF = 1 +#endif + +} PRED_ID; + + +extern unsigned char get_pred_context( VP8_COMMON *const cm, + MACROBLOCKD *const xd, + PRED_ID pred_id ); + +extern vp8_prob get_pred_prob( VP8_COMMON *const cm, + MACROBLOCKD *const xd, + PRED_ID pred_id ); + +extern unsigned char get_pred_flag( MACROBLOCKD *const xd, + PRED_ID pred_id ); + +extern void set_pred_flag( MACROBLOCKD *const xd, + PRED_ID pred_id, + unsigned char pred_flag); + + +extern unsigned char get_pred_mb_segid( VP8_COMMON *const cm, int MbIndex ); + +#if CONFIG_COMPRED +extern MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, + MACROBLOCKD *const xd ); +extern void compute_mod_refprobs( VP8_COMMON *const cm ); + +#endif + +#endif /* __INC_PRED_COMMON_H__ */ diff --git a/vp8/vp8_common.mk b/vp8/vp8_common.mk index 159514270..5a44cd1b1 100644 --- a/vp8/vp8_common.mk +++ b/vp8/vp8_common.mk @@ -45,6 +45,8 @@ VP8_COMMON_SRCS-yes += common/loopfilter.h VP8_COMMON_SRCS-yes += common/modecont.h VP8_COMMON_SRCS-yes += common/mv.h VP8_COMMON_SRCS-yes += common/onyxc_int.h +VP8_COMMON_SRCS-yes += common/pred_common.h +VP8_COMMON_SRCS-yes += common/pred_common.c VP8_COMMON_SRCS-yes += common/quant_common.h VP8_COMMON_SRCS-yes += common/recon.h VP8_COMMON_SRCS-yes += common/reconinter.h @@ -74,7 +76,6 @@ VP8_COMMON_SRCS-yes += common/swapyv12buffer.c VP8_COMMON_SRCS-$(CONFIG_POSTPROC_VISUALIZER) += common/textblit.c VP8_COMMON_SRCS-yes += common/treecoder.c VP8_COMMON_SRCS-yes += common/implicit_segmentation.c -VP8_COMMON_SRCS-yes += common/implicit_segmentation.h VP8_COMMON_SRCS-yes += common/predict_rotated.c VP8_COMMON_SRCS-yes += common/rotate.h VP8_COMMON_SRCS-yes += common/rotate2.h