From ceb5174205460f2d19e5ea701349ecdeed4e7402 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Wed, 14 Sep 2011 18:20:25 +0100 Subject: [PATCH] Segment Feature Signaling Plumbing for tuning new segment features on and off. Change-Id: If86cd6f103296b73030e8af7cf85c5b9bbffdbaf --- vp8/common/blockd.h | 3 +++ vp8/common/loopfilter.c | 10 +++++++-- vp8/decoder/decodframe.c | 44 ++++++++++++++++++++++++++++++++-------- vp8/decoder/threading.c | 10 ++++++++- vp8/encoder/bitstream.c | 9 +++++++- vp8/encoder/ethreading.c | 11 +++++++++- vp8/encoder/onyx_if.c | 39 +++++++++++++++++++++++------------ vp8/encoder/onyx_int.h | 3 +++ vp8/encoder/picklpf.c | 17 +++++++++++----- vp8/encoder/quantize.c | 37 ++++++++++++++++++++++++--------- 10 files changed, 141 insertions(+), 42 deletions(-) diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h index 72f848c03..65ad43559 100644 --- a/vp8/common/blockd.h +++ b/vp8/common/blockd.h @@ -254,6 +254,9 @@ typedef struct MacroBlockD // Segment features signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; +#if CONFIG_SEGFEATURES + unsigned int segment_feature_mask[MAX_MB_SEGMENTS]; +#endif /* mode_based Loop filter adjustment */ unsigned char mode_ref_lf_delta_enabled; diff --git a/vp8/common/loopfilter.c b/vp8/common/loopfilter.c index 346a43560..a8855531e 100644 --- a/vp8/common/loopfilter.c +++ b/vp8/common/loopfilter.c @@ -215,8 +215,14 @@ void vp8_loop_filter_frame_init(VP8_COMMON *cm, int lvl_seg = default_filt_lvl; int lvl_ref, lvl_mode; - /* Note the baseline filter values for each segment */ - if (mbd->segmentation_enabled) + + // Set the baseline filter values for each segment +#if CONFIG_SEGFEATURES + if ( mbd->segmentation_enabled && + ( mbd->segment_feature_mask[seg] & (1 << SEG_LVL_ALT_LF) ) ) +#else + if ( mbd->segmentation_enabled ) +#endif { /* Abs value */ if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA) diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 33102f274..69f2905d4 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -72,21 +72,27 @@ void mb_init_dequantizer(VP8D_COMP *pbi, MACROBLOCKD *xd) { int i; int QIndex; - MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi; VP8_COMMON *const pc = & pbi->common; + int segment_id = xd->mode_info_context->mbmi.segment_id; - /* Decide whether to use the default or alternate baseline Q value. */ - if (xd->segmentation_enabled) + + // Set the Q baseline allowing for any segment level adjustment +#if CONFIG_SEGFEATURES + if ( xd->segmentation_enabled && + ( xd->segment_feature_mask[segment_id] & (1 << SEG_LVL_ALT_Q) ) ) +#else + if ( xd->segmentation_enabled ) +#endif { /* Abs Value */ if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA) - QIndex = xd->segment_feature_data[mbmi->segment_id][SEG_LVL_ALT_Q]; + QIndex = xd->segment_feature_data[segment_id][SEG_LVL_ALT_Q]; /* Delta Value */ else { QIndex = pc->base_qindex + - xd->segment_feature_data[mbmi->segment_id][SEG_LVL_ALT_Q]; + xd->segment_feature_data[segment_id][SEG_LVL_ALT_Q]; QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0; /* Clamp to valid range */ } } @@ -727,8 +733,15 @@ static void init_frame(VP8D_COMP *pbi) vp8_default_coef_probs(pc); vp8_kf_default_bmode_probs(pc->kf_bmode_prob); - /* reset the segment feature data to 0 with delta coding (Default state). */ - vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data)); + // Reset the segment feature data to the default stats: + // Features disabled, 0, with delta coding (Default state). +#if CONFIG_SEGFEATURES + vpx_memset(xd->segment_feature_mask, 0, + sizeof(xd->segment_feature_mask)); +#endif + vpx_memset(xd->segment_feature_data, 0, + sizeof(xd->segment_feature_data)); + xd->mb_segement_abs_delta = SEGMENT_DELTADATA; /* reset the mode ref deltasa for loop filter */ @@ -937,9 +950,15 @@ int vp8_decode_frame(VP8D_COMP *pbi) { xd->mb_segement_abs_delta = (unsigned char)vp8_read_bit(bc); - vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data)); + // Clear down feature data structure + vpx_memset(xd->segment_feature_data, 0, + sizeof(xd->segment_feature_data)); #if CONFIG_SEGFEATURES + // Clear down feature enabled masks + vpx_memset(xd->segment_feature_mask, 0, + sizeof(xd->segment_feature_mask)); + // For each segmentation... for (j = 0; j < MAX_MB_SEGMENTS; j++) { @@ -955,16 +974,23 @@ int vp8_decode_frame(VP8D_COMP *pbi) for (j = 0; j < MAX_MB_SEGMENTS; j++) { #endif - /* Frame level data */ + // Is the feature enabled if (vp8_read_bit(bc)) { +#if CONFIG_SEGFEATURES + // Update the feature data and mask + xd->segment_feature_mask[j] |= (1 << i); +#endif + xd->segment_feature_data[j][i] = (signed char)vp8_read_literal(bc, mb_feature_data_bits[i]); if (vp8_read_bit(bc)) xd->segment_feature_data[j][i] = -xd->segment_feature_data[j][i]; } else + { xd->segment_feature_data[j][i] = 0; + } } } } diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c index fdde04a88..b60b7e8bf 100644 --- a/vp8/decoder/threading.c +++ b/vp8/decoder/threading.c @@ -66,7 +66,15 @@ static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_D vp8_build_block_doffsets(mbd); mbd->segmentation_enabled = xd->segmentation_enabled; mbd->mb_segement_abs_delta = xd->mb_segement_abs_delta; - vpx_memcpy(mbd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data)); + + vpx_memcpy(mbd->segment_feature_data, + xd->segment_feature_data, + sizeof(xd->segment_feature_data)); +#if CONFIG_SEGFEATURES + vpx_memcpy(mbd->segment_feature_mask, + xd->segment_feature_mask, + sizeof(xd->segment_feature_mask)); +#endif /*signed char ref_lf_deltas[MAX_REF_LF_DELTAS];*/ vpx_memcpy(mbd->ref_lf_deltas, xd->ref_lf_deltas, sizeof(xd->ref_lf_deltas)); diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index c4901bf7b..e872a433d 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -1862,11 +1862,18 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) { Data = xd->segment_feature_data[j][i]; - // Frame level data +#if CONFIG_SEGFEATURES + // If the feature is enabled... + if ( xd->segment_feature_mask[j] & (0x01 << i)) +#else + // If the feature is enabled...Indicated by non zero + // value in VP8 if (Data) +#endif { vp8_write_bit(bc, 1); + // Encode the relevant feature data if (Data < 0) { Data = - Data; diff --git a/vp8/encoder/ethreading.c b/vp8/encoder/ethreading.c index 6b9dff8d9..4820729ea 100644 --- a/vp8/encoder/ethreading.c +++ b/vp8/encoder/ethreading.c @@ -395,7 +395,16 @@ static void setup_mbby_copy(MACROBLOCK *mbdst, MACROBLOCK *mbsrc) zd->subpixel_predict16x16 = xd->subpixel_predict16x16; zd->segmentation_enabled = xd->segmentation_enabled; zd->mb_segement_abs_delta = xd->mb_segement_abs_delta; - vpx_memcpy(zd->segment_feature_data, xd->segment_feature_data, sizeof(xd->segment_feature_data)); + + vpx_memcpy(zd->segment_feature_data, + xd->segment_feature_data, + sizeof(xd->segment_feature_data)); + +#if CONFIG_SEGFEATURES + vpx_memcpy(zd->segment_feature_mask, + xd->segment_feature_mask, + sizeof(xd->segment_feature_mask)); +#endif for (i = 0; i < 25; i++) { diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 866f542b8..c97e10825 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -317,23 +317,29 @@ extern FILE *vpxlogc; static void setup_features(VP8_COMP *cpi) { + MACROBLOCKD *xd = &cpi->mb.e_mbd; + // Set up default state for MB feature flags #if CONFIG_SEGMENTATION - cpi->mb.e_mbd.segmentation_enabled = 1; + xd->segmentation_enabled = 1; #else - cpi->mb.e_mbd.segmentation_enabled = 0; + xd->segmentation_enabled = 0; #endif - cpi->mb.e_mbd.update_mb_segmentation_map = 0; - cpi->mb.e_mbd.update_mb_segmentation_data = 0; - vpx_memset(cpi->mb.e_mbd.mb_segment_tree_probs, 255, sizeof(cpi->mb.e_mbd.mb_segment_tree_probs)); - vpx_memset(cpi->mb.e_mbd.segment_feature_data, 0, sizeof(cpi->mb.e_mbd.segment_feature_data)); + xd->update_mb_segmentation_map = 0; + xd->update_mb_segmentation_data = 0; + vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs)); + vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data)); - cpi->mb.e_mbd.mode_ref_lf_delta_enabled = 0; - cpi->mb.e_mbd.mode_ref_lf_delta_update = 0; - vpx_memset(cpi->mb.e_mbd.ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas)); - vpx_memset(cpi->mb.e_mbd.mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas)); - vpx_memset(cpi->mb.e_mbd.last_ref_lf_deltas, 0, sizeof(cpi->mb.e_mbd.ref_lf_deltas)); - vpx_memset(cpi->mb.e_mbd.last_mode_lf_deltas, 0, sizeof(cpi->mb.e_mbd.mode_lf_deltas)); +#if CONFIG_SEGFEATURES + vpx_memset(xd->segment_feature_mask, 0, sizeof(xd->segment_feature_mask)); +#endif + + xd->mode_ref_lf_delta_enabled = 0; + xd->mode_ref_lf_delta_update = 0; + vpx_memset(xd->ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas)); + vpx_memset(xd->mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas)); + vpx_memset(xd->last_ref_lf_deltas, 0, sizeof(xd->ref_lf_deltas)); + vpx_memset(xd->last_mode_lf_deltas, 0, sizeof(xd->mode_lf_deltas)); set_default_lf_deltas(cpi); @@ -439,7 +445,14 @@ static void set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned ch VP8_COMP *cpi = (VP8_COMP *)(ptr); cpi->mb.e_mbd.mb_segement_abs_delta = abs_delta; - vpx_memcpy(cpi->segment_feature_data, feature_data, sizeof(cpi->segment_feature_data)); + vpx_memcpy(cpi->segment_feature_data, feature_data, + sizeof(cpi->segment_feature_data)); + +#if CONFIG_SEGFEATURES + // TBD ?? Set the feature mask + // vpx_memset(xd->segment_feature_mask, 0, sizeof(xd->segment_feature_mask)); +#endif + } diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index b01392c8e..00e7788f9 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -479,6 +479,9 @@ typedef struct VP8_COMP // Segment data (can be deltas or absolute values) signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; +#if CONFIG_SEGFEATURES +unsigned int segment_feature_mask[MAX_MB_SEGMENTS]; +#endif // segment threashold for encode breakout int segment_encode_breakout[MAX_MB_SEGMENTS]; diff --git a/vp8/encoder/picklpf.c b/vp8/encoder/picklpf.c index 0585d66e2..c6c5ec056 100644 --- a/vp8/encoder/picklpf.c +++ b/vp8/encoder/picklpf.c @@ -257,12 +257,19 @@ void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val) { MACROBLOCKD *mbd = &cpi->mb.e_mbd; - (void) filt_val; + int i; - mbd->segment_feature_data[0][SEG_LVL_ALT_LF] = cpi->segment_feature_data[0][SEG_LVL_ALT_LF]; - mbd->segment_feature_data[1][SEG_LVL_ALT_LF] = cpi->segment_feature_data[1][SEG_LVL_ALT_LF]; - mbd->segment_feature_data[2][SEG_LVL_ALT_LF] = cpi->segment_feature_data[2][SEG_LVL_ALT_LF]; - mbd->segment_feature_data[3][SEG_LVL_ALT_LF] = cpi->segment_feature_data[3][SEG_LVL_ALT_LF]; + for ( i = 0; i < MAX_MB_SEGMENTS; i++ ) + { + mbd->segment_feature_data[i][SEG_LVL_ALT_LF] = + cpi->segment_feature_data[i][SEG_LVL_ALT_LF]; + +#if CONFIG_SEGFEATURES + mbd->segment_feature_mask[i] &= ~(1 << SEG_LVL_ALT_LF); + mbd->segment_feature_mask[i] |= + cpi->segment_feature_mask[i] & (1 << SEG_LVL_ALT_LF); +#endif + } } void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) diff --git a/vp8/encoder/quantize.c b/vp8/encoder/quantize.c index 13009bb3f..156989fc3 100644 --- a/vp8/encoder/quantize.c +++ b/vp8/encoder/quantize.c @@ -1167,19 +1167,28 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x) int QIndex; MACROBLOCKD *xd = &x->e_mbd; int zbin_extra; + int segment_id = xd->mode_info_context->mbmi.segment_id; - // Select the baseline MB Q index. - if (xd->segmentation_enabled) + // Select the baseline MB Q index allowing for any segment level change. +#if CONFIG_SEGFEATURES + if ( xd->segmentation_enabled && + ( xd->segment_feature_mask[segment_id] & (0x01 << SEG_LVL_ALT_Q) ) ) +#else + if ( xd->segmentation_enabled ) +#endif { // Abs Value if (xd->mb_segement_abs_delta == SEGMENT_ABSDATA) + QIndex = xd->segment_feature_data[segment_id][SEG_LVL_ALT_Q]; - QIndex = xd->segment_feature_data[xd->mode_info_context->mbmi.segment_id][SEG_LVL_ALT_Q]; // Delta Value else { - QIndex = cpi->common.base_qindex + xd->segment_feature_data[xd->mode_info_context->mbmi.segment_id][SEG_LVL_ALT_Q]; - QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0; // Clamp to valid range + QIndex = cpi->common.base_qindex + + xd->segment_feature_data[segment_id][SEG_LVL_ALT_Q]; + + // Clamp to valid range + QIndex = (QIndex >= 0) ? ((QIndex <= MAXQ) ? QIndex : MAXQ) : 0; } } else @@ -1294,6 +1303,7 @@ void vp8_set_quantizer(struct VP8_COMP *cpi, int Q) MACROBLOCKD *mbd = &cpi->mb.e_mbd; int update = 0; int new_delta_q; + int i; cm->base_qindex = Q; /* if any of the delta_q values are changing update flag has to be set */ @@ -1315,11 +1325,18 @@ void vp8_set_quantizer(struct VP8_COMP *cpi, int Q) cm->y2dc_delta_q = new_delta_q; - // Set Segment specific quatizers - mbd->segment_feature_data[0][SEG_LVL_ALT_Q] = cpi->segment_feature_data[0][SEG_LVL_ALT_Q]; - mbd->segment_feature_data[1][SEG_LVL_ALT_Q] = cpi->segment_feature_data[1][SEG_LVL_ALT_Q]; - mbd->segment_feature_data[2][SEG_LVL_ALT_Q] = cpi->segment_feature_data[2][SEG_LVL_ALT_Q]; - mbd->segment_feature_data[3][SEG_LVL_ALT_Q] = cpi->segment_feature_data[3][SEG_LVL_ALT_Q]; + // Set Segment specific quatizers if enabled + for ( i = 0; i < MAX_MB_SEGMENTS; i++ ) + { + mbd->segment_feature_data[i][SEG_LVL_ALT_Q] = + cpi->segment_feature_data[i][SEG_LVL_ALT_Q]; + +#if CONFIG_SEGFEATURES + mbd->segment_feature_mask[i] &= ~(1 << SEG_LVL_ALT_Q); + mbd->segment_feature_mask[i] |= + cpi->segment_feature_mask[i] & (1 << SEG_LVL_ALT_Q); +#endif + } /* quantizer has to be reinitialized for any delta_q changes */ if(update) -- 2.40.0