diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c index 1d1d107ea457f7d80afa540db6bd934764e2b8ae..e4cd037e860f735c901ced106386e92d0c3de5e1 100644 --- a/vp8/common/pred_common.c +++ b/vp8/common/pred_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * 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 @@ -157,12 +157,19 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, unsigned char left_pred; unsigned char above_pred; + unsigned char frame_allowed[MAX_REF_FRAMES]; 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; + + // Is segment coding ennabled + seg_ref_active = segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ); + // Reference frame used by neighbours left = (m - 1)->mbmi.ref_frame; above = (m - cm->mode_info_stride)->mbmi.ref_frame; @@ -173,6 +180,32 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, left_pred = (m - 1)->mbmi.ref_predicted; above_pred = (m - cm->mode_info_stride)->mbmi.ref_predicted; + // 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 ) + { + frame_allowed[INTRA_FRAME] = + check_segref( xd, segment_id, INTRA_FRAME ); + frame_allowed[LAST_FRAME] = + check_segref( xd, segment_id, LAST_FRAME ); + frame_allowed[GOLDEN_FRAME] = + check_segref( xd, segment_id, GOLDEN_FRAME ); + frame_allowed[ALTREF_FRAME] = + check_segref( xd, segment_id, ALTREF_FRAME ); + } + else + { + frame_allowed[INTRA_FRAME] = 1; + frame_allowed[LAST_FRAME] = 1; + frame_allowed[GOLDEN_FRAME] = 1; + frame_allowed[ALTREF_FRAME] = 1; + } + + // Dont predict if not allowed + left_pred = left_pred * frame_allowed[left]; + above_pred = above_pred * frame_allowed[above]; + // Boost prediction scores of above / left if they are predicted and match // the above left. if ( left_pred ) @@ -181,7 +214,7 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, above_pred += (above == above_left); // Only consider "in image" mbs as giving valid prediction. - if ( (left == above) && + if ( (left == above) && frame_allowed[left] && ((m - 1)->mbmi.mb_in_image || (m - cm->mode_info_stride)->mbmi.mb_in_image) ) { @@ -195,17 +228,44 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, { pred_ref = above; } - else + // If we reach this clause left_pred and above_pred must be the same + else if ( left_pred > 0 ) { // 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) ) + if ( frame_allowed[LAST_FRAME] && + ((left == LAST_FRAME) || (above == LAST_FRAME)) ) + { + pred_ref = LAST_FRAME; + } + else if ( frame_allowed[ALTREF_FRAME] && + ((left == ALTREF_FRAME) || (above == ALTREF_FRAME)) ) + { + pred_ref = ALTREF_FRAME; + } + else if ( frame_allowed[GOLDEN_FRAME] && + ((left == GOLDEN_FRAME) || (above == GOLDEN_FRAME)) ) + { + pred_ref = GOLDEN_FRAME; + } + else + { + pred_ref = INTRA_FRAME; + } + } + // No prediction case.. choose in fixed order from allowed options + // TBD could order based onf frequency. + else + { + if ( frame_allowed[LAST_FRAME] ) pred_ref = LAST_FRAME; - else if ( (left == ALTREF_FRAME) || (above == ALTREF_FRAME) ) + else if ( frame_allowed[ALTREF_FRAME] ) pred_ref = ALTREF_FRAME; - else if ( (left == GOLDEN_FRAME) || (above == GOLDEN_FRAME) ) + else if ( frame_allowed[GOLDEN_FRAME] ) pred_ref = GOLDEN_FRAME; + else + pred_ref = INTRA_FRAME; } return pred_ref; @@ -246,6 +306,10 @@ void calc_ref_probs( int * count, vp8_prob * probs ) } +// 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 compute_mod_refprobs( VP8_COMMON *const cm ) { int norm_cnt[MAX_REF_FRAMES]; @@ -255,6 +319,7 @@ void compute_mod_refprobs( VP8_COMMON *const cm ) int gfarf_count; int gf_count; int arf_count; + int i; intra_count = cm->prob_intra_coded; inter_count = (255 - intra_count); @@ -292,6 +357,5 @@ void compute_mod_refprobs( VP8_COMMON *const cm ) 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 index 60476f9c5d4d43c125e6766104a18e4d9c25bb23..9463937dbe95df4b30f0b140fe75a6b689cc8770 100644 --- a/vp8/common/pred_common.h +++ b/vp8/common/pred_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * 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 diff --git a/vp8/common/seg_common.h b/vp8/common/seg_common.h index 1f4e38dadeee39e6e2929070fc399e5d7454d49d..f3f2d9f1983ed4b74f7ad2ffc1b40c28fe23d97d 100644 --- a/vp8/common/seg_common.h +++ b/vp8/common/seg_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * 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 diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index 1dee3beea1326549c5be74c49be792cdf3979b9f..432b339b18e54f2f952480062cc68dbc8f3ed502 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -236,6 +236,7 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, { MV_REFERENCE_FRAME ref_frame; int seg_ref_active; + int seg_ref_count = 0; //#if CONFIG_SEGFEATURES VP8_COMMON *const cm = & pbi->common; @@ -245,8 +246,25 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, segment_id, SEG_LVL_REF_FRAME ); - // Segment reference frame features not available + +#if CONFIG_COMPRED + + // If segment coding enabled does the segment allow for more than one + // possible reference frame + if ( seg_ref_active ) + { + seg_ref_count = check_segref( xd, segment_id, INTRA_FRAME ) + + check_segref( xd, segment_id, LAST_FRAME ) + + check_segref( xd, segment_id, GOLDEN_FRAME ) + + check_segref( xd, segment_id, ALTREF_FRAME ); + } + + // Segment reference frame features not available or allows for + // multiple reference frame options + if ( !seg_ref_active || (seg_ref_count > 1) ) +#else if ( !seg_ref_active ) +#endif { #if CONFIG_COMPRED // Values used in prediction model coding @@ -274,7 +292,23 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, // else decode the explicitly coded value else { - vp8_prob * mod_refprobs = cm->mod_refprobs[pred_ref]; + //vp8_prob * mod_refprobs = cm->mod_refprobs[pred_ref]; + vp8_prob mod_refprobs[PREDICTION_PROBS]; + vpx_memcpy( mod_refprobs, + cm->mod_refprobs[pred_ref], sizeof(mod_refprobs) ); + + // If segment coding enabled blank out options that cant occur by + // setting the branch probability to 0. + if ( seg_ref_active ) + { + mod_refprobs[INTRA_FRAME] *= + check_segref( xd, segment_id, INTRA_FRAME ); + mod_refprobs[LAST_FRAME] *= + check_segref( xd, segment_id, LAST_FRAME ); + mod_refprobs[GOLDEN_FRAME] *= + ( check_segref( xd, segment_id, GOLDEN_FRAME ) * + check_segref( xd, segment_id, ALTREF_FRAME ) ); + } // Default to INTRA_FRAME (value 0) ref_frame = INTRA_FRAME; @@ -300,8 +334,19 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, ref_frame += vp8_read(bc, mod_refprobs[2]); else { - ref_frame = (pred_ref == GOLDEN_FRAME) - ? ALTREF_FRAME : GOLDEN_FRAME; + if ( seg_ref_active ) + { + if ( (pred_ref == GOLDEN_FRAME) || + !check_segref( xd, segment_id, GOLDEN_FRAME) ) + { + ref_frame = ALTREF_FRAME; + } + else + ref_frame = GOLDEN_FRAME; + } + else + ref_frame = (pred_ref == GOLDEN_FRAME) + ? ALTREF_FRAME : GOLDEN_FRAME; } } } @@ -330,8 +375,8 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, // if it is signaled at the segment level for the purposes of the // common prediction model set_pred_flag( xd, PRED_REF, 1 ); -#endif - + ref_frame = get_pred_ref( cm, xd ); +#else // If there are no inter reference frames enabled we can set INTRA if ( !check_segref_inter(xd, segment_id) ) { @@ -401,6 +446,7 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, } } } +#endif } return (MV_REFERENCE_FRAME)ref_frame; diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 2aee8249d51558f8d577b2e293933ae43ea816a7..26f1cb4877a34f5762f66069f9c87f8ecb0b3909 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -843,13 +843,27 @@ static void encode_ref_frame( vp8_writer *const w, MV_REFERENCE_FRAME rf ) { int seg_ref_active; + int seg_ref_count = 0; //#if CONFIG_SEGFEATURES seg_ref_active = segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ); +#if CONFIG_COMPRED + if ( seg_ref_active ) + { + seg_ref_count = check_segref( xd, segment_id, INTRA_FRAME ) + + check_segref( xd, segment_id, LAST_FRAME ) + + check_segref( xd, segment_id, GOLDEN_FRAME ) + + check_segref( xd, segment_id, ALTREF_FRAME ); + } + // If segment level coding of this signal is disabled... - if ( !seg_ref_active ) + // or the segment allows multiple reference frame options + if ( !seg_ref_active || (seg_ref_count > 1) ) +#else + if ( !seg_ref_active ) +#endif { #if CONFIG_COMPRED // Values used in prediction model coding @@ -869,7 +883,24 @@ static void encode_ref_frame( vp8_writer *const w, // Get the predicted value so that it can be excluded. MV_REFERENCE_FRAME pred_rf = get_pred_ref( cm, xd ); - vp8_prob * mod_refprobs = cm->mod_refprobs[pred_rf]; + //vp8_prob * mod_refprobs = cm->mod_refprobs[pred_rf]; + vp8_prob mod_refprobs[PREDICTION_PROBS]; + + vpx_memcpy( mod_refprobs, + cm->mod_refprobs[pred_rf], sizeof(mod_refprobs) ); + + // If segment coding enabled blank out options that cant occur by + // setting the branch probability to 0. + if ( seg_ref_active ) + { + mod_refprobs[INTRA_FRAME] *= + check_segref( xd, segment_id, INTRA_FRAME ); + mod_refprobs[LAST_FRAME] *= + check_segref( xd, segment_id, LAST_FRAME ); + mod_refprobs[GOLDEN_FRAME] *= + ( check_segref( xd, segment_id, GOLDEN_FRAME ) * + check_segref( xd, segment_id, ALTREF_FRAME ) ); + } if ( mod_refprobs[0] ) { @@ -915,7 +946,12 @@ static void encode_ref_frame( vp8_writer *const w, } #endif } + + // if using the prediction mdoel we have nothing further to do because + // the reference frame is fully coded by the segment + //#if CONFIG_SEGFEATURES +#if !CONFIG_COMPRED // Else use the segment else { @@ -958,6 +994,7 @@ static void encode_ref_frame( vp8_writer *const w, } } } +#endif } #if CONFIG_SUPERBLOCKS diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index a0a0245925b3ed57b717aecaa9175610e812ba9b..30352d7190452b257d9177a078d515a18bc588f5 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -1979,11 +1979,8 @@ int vp8cx_encode_inter_macroblock // SET VARIOUS PREDICTION FLAGS // Did the chosen reference frame match its predicted value. - // If the reference frame is predicted at the segment level we - // mark it as correctly predicted ref_pred_flag = ( (xd->mode_info_context->mbmi.ref_frame == - get_pred_ref( cm, xd )) || - seg_ref_active ); + get_pred_ref( cm, xd )) ); set_pred_flag( xd, PRED_REF, ref_pred_flag ); #endif diff --git a/vp8/encoder/mbgraph.c b/vp8/encoder/mbgraph.c index 18c30a4177b13d54c50251f38f9997d0e9b1c7d1..e0fed4a4741ff52f65d270c36839ae358d860bcc 100644 --- a/vp8/encoder/mbgraph.c +++ b/vp8/encoder/mbgraph.c @@ -91,7 +91,8 @@ static unsigned int do_16x16_motion_iteration vp8_set_mbmode_and_mvs(x, NEWMV, dst_mv); vp8_build_inter16x16_predictors_mby(xd); - VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + best_err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16) (xd->dst.y_buffer, xd->dst.y_stride, xd->predictor, 16, &best_err); @@ -138,7 +139,8 @@ static int do_16x16_motion_search // FIXME should really use something like near/nearest MV and/or MV prediction xd->pre.y_buffer = ref->y_buffer + mb_y_offset; xd->pre.y_stride = ref->y_stride; - VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16) (ref->y_buffer + mb_y_offset, ref->y_stride, xd->dst.y_buffer, xd->dst.y_stride, &err); @@ -203,10 +205,12 @@ static int do_16x16_zerozero_search // FIXME should really use something like near/nearest MV and/or MV prediction xd->pre.y_buffer = ref->y_buffer + mb_y_offset; xd->pre.y_stride = ref->y_stride; - VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16) (ref->y_buffer + mb_y_offset, ref->y_stride, xd->dst.y_buffer, xd->dst.y_stride, &err); + dst_mv->as_int = 0; return err; @@ -232,7 +236,8 @@ static int find_best_16x16_intra xd->mode_info_context->mbmi.mode = mode; RECON_INVOKE(&cpi->rtcd.common->recon, build_intra_predictors_mby)(xd); - VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + //VARIANCE_INVOKE(&cpi->rtcd.variance, satd16x16) + err = VARIANCE_INVOKE(&cpi->rtcd.variance, sad16x16) (xd->predictor, 16, buf->y_buffer + mb_y_offset, buf->y_stride, &err); diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index b3b0790ff1d94ef9b7dbaea524622eba7b941092..2ea41ab355d022f7f1bd85f90ec098acfc968d75 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -474,7 +474,7 @@ static void init_seg_features(VP8_COMP *cpi) VP8_COMMON *cm = &cpi->common; MACROBLOCKD *xd = &cpi->mb.e_mbd; - int high_q = (int)(cpi->avg_q > 32.0); + int high_q = (int)(cpi->avg_q > 48.0); int qi_delta; // For now at least dont enable seg features alongside cyclic refresh. @@ -575,15 +575,10 @@ static void init_seg_features(VP8_COMP *cpi) set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 ); enable_segfeature(xd, 1, SEG_LVL_ALT_LF); -#if CONFIG_COMPRED // Segment coding disabled for compred testing if ( high_q || (cpi->static_mb_pct == 100) ) - //if ( 0 ) -#else - if ( high_q || (cpi->static_mb_pct == 100) ) - //if ( 0 ) -#endif { + //set_segref(xd, 1, LAST_FRAME); set_segref(xd, 1, ALTREF_FRAME); enable_segfeature(xd, 1, SEG_LVL_REF_FRAME); @@ -618,14 +613,8 @@ static void init_seg_features(VP8_COMP *cpi) // Special case where we are coding over the top of a previous // alt ref frame -#if CONFIG_COMPRED // Segment coding disabled for compred testing else if ( cpi->is_src_frame_alt_ref ) - //else if ( 0 ) -#else - else if ( cpi->is_src_frame_alt_ref ) - //else if ( 0 ) -#endif { // Enable mode and ref frame features for segment 0 as well enable_segfeature(xd, 0, SEG_LVL_REF_FRAME); diff --git a/vp8/encoder/segmentation.c b/vp8/encoder/segmentation.c index 91dffe166c32dbf864769f1aa699fa7afb857034..4a1ce649c78463f325da0ffd09e8ce3dc4e2d55e 100644 --- a/vp8/encoder/segmentation.c +++ b/vp8/encoder/segmentation.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + * 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