From b9a18344cf8e5283928525c5ac0897ede79f9e57 Mon Sep 17 00:00:00 2001 From: Suman Sunkara Date: Thu, 23 Sep 2010 18:25:33 -0400 Subject: [PATCH] Use of temporal context for encoding delta updates. - Used three probability approach for temporal context as follows: P0 - probability of no change if both above and left not changed P1 - probability of no change if one of above and left has changed P2 - probability of no change if both above and left have changed In addition, a 1 bit/frame has been used to decide whether to use temporal context or to encode directly. The cost of using both the schemes is calculated ahead and the temporal_update flag is set if the cost of using temporal context is lower than encoding the segment ids directly. This approach has given around 20% reduction in cost of bits needed to encode segmentation ids. Change-Id: I44a5509599eded215ae5be9554314280d3d35405 --- vp8/common/blockd.h | 2 + vp8/decoder/decodemv.c | 81 ++++++--------- vp8/decoder/decodframe.c | 7 +- vp8/decoder/demode.c | 61 +----------- vp8/decoder/onyxd_if.c | 6 +- vp8/decoder/onyxd_int.h | 2 +- vp8/encoder/bitstream.c | 184 +++++++--------------------------- vp8/encoder/encodeframe.c | 203 +++++++++++++++++++++++--------------- vp8/encoder/onyx_if.c | 48 +-------- 9 files changed, 203 insertions(+), 391 deletions(-) diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h index da8c0e1d8..7a7b06b36 100644 --- a/vp8/common/blockd.h +++ b/vp8/common/blockd.h @@ -172,6 +172,7 @@ typedef struct int mb_skip_coeff; //does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens int dc_diff; unsigned char segment_id; // Which set of segmentation parameters should be used for this MB + unsigned char segment_flag; int force_no_skip; B_MODE_INFO partition_bmi[16]; @@ -253,6 +254,7 @@ typedef struct // 0 (do not update) 1 (update) the macroblock segmentation feature data. unsigned char mb_segement_abs_delta; + unsigned char temporal_update; // Per frame flags that define which MB level features (such as quantizer or loop filter level) // are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO #if CONFIG_SEGMENTATION diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index dfa468084..f151ef3cc 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -113,7 +113,7 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi) VP8_COMMON *const pc = & pbi->common; vp8_reader *const bc = & pbi->bc; - + MACROBLOCKD *xd = &pbi->mb; MODE_INFO *mi = pc->mi, *ms; const int mis = pc->mode_info_stride; @@ -123,6 +123,8 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi) #if CONFIG_SEGMENTATION int left_id, above_id; int i; + int sum; + int index = 0; #endif vp8_prob prob_intra; vp8_prob prob_last; @@ -161,7 +163,9 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi) } read_mvcontexts(bc, mvc); - +#if CONFIG_SEGMENTATION + xd->temporal_update = vp8_read_bit(bc); +#endif while (++mb_row < pc->mb_rows) { int mb_col = -1; @@ -171,7 +175,7 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi) MB_MODE_INFO *const mbmi = & mi->mbmi; MV *const mv = & mbmi->mv.as_mv; VP8_COMMON *const pc = &pbi->common; - MACROBLOCKD *xd = &pbi->mb; + // MACROBLOCKD *xd = &pbi->mb; vp8dx_bool_decoder_fill(bc); // Distance of Mb to the various image edges. @@ -185,69 +189,40 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi) if (pbi->mb.update_mb_segmentation_map) { #if CONFIG_SEGMENTATION - xd->up_available = (mb_row != 0); - xd->left_available = (mb_col != 0); - int count = 0; - int j; - if(xd->left_available) - left_id = (mi-1)->mbmi.segment_id; - else - left_id = 0; + if (xd->temporal_update) + { + sum = 0; - if(xd->up_available) - above_id = (mi-pc->mb_cols)->mbmi.segment_id; - else - above_id = 0; + if (mb_col != 0) + sum += (mi-1)->mbmi.segment_flag; + if (mb_row != 0) + sum += (mi-pc->mb_cols)->mbmi.segment_flag; - if (vp8_read(bc, xd->mb_segment_tree_probs[0])) - { - for(i = 0; i < MAX_MB_SEGMENTS; i++) + if (vp8_read(bc, xd->mb_segment_tree_probs[3+sum]) == 0) { - if((left_id != i) && (above_id != i)) - { - if(left_id != above_id) - { - if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0) - mbmi->segment_id = i; - else - mbmi->segment_id = 6-left_id-above_id-i; - break; - } - else - { - if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0) - { - mbmi->segment_id = i; - break; - } - else - { - count++; - if(count == 1) - j = i; - if(count == 2) - { - mbmi->segment_id = 6-left_id-j-i; - break; - } - } - } - } + mbmi->segment_id = pbi->segmentation_map[index]; + mbmi->segment_flag = 0; + } + else + { + vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb); + mbmi->segment_flag = 1; + pbi->segmentation_map[index] = mbmi->segment_id; } + } else { - if (vp8_read(bc, xd->mb_segment_tree_probs[1])) - mbmi->segment_id = above_id; - else - mbmi->segment_id = left_id; - + vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb); + pbi->segmentation_map[index] = mbmi->segment_id; } + index++; #else vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb); #endif } + // Read the macroblock coeff skip flag if this feature is in use, else default to 0 if (pc->mb_no_coeff_skip) mbmi->mb_skip_coeff = vp8_read(bc, prob_skip_false); diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index a26056e35..01cd7aedf 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -632,7 +632,6 @@ int vp8_decode_frame(VP8D_COMP *pbi) // Is segmentation enabled xd->segmentation_enabled = (unsigned char)vp8_read_bit(bc); - if (xd->segmentation_enabled) { // Signal whether or not the segmentation map is being explicitly updated this frame. @@ -794,7 +793,6 @@ int vp8_decode_frame(VP8D_COMP *pbi) fclose(z); } - vp8dx_bool_decoder_fill(bc); { // read coef probability tree @@ -818,6 +816,11 @@ int vp8_decode_frame(VP8D_COMP *pbi) vpx_memcpy(&xd->pre, &pc->last_frame, sizeof(YV12_BUFFER_CONFIG)); vpx_memcpy(&xd->dst, &pc->new_frame, sizeof(YV12_BUFFER_CONFIG)); +#if CONFIG_SEGMENTATION + // Create the encoder segmentation map and set all entries to 0 + CHECK_MEM_ERROR(pbi->segmentation_map, vpx_calloc((pc->mb_rows * pc->mb_cols), 1)); +#endif + // set up frame new frame for intra coded blocks vp8_setup_intra_recon(&pc->new_frame); diff --git a/vp8/decoder/demode.c b/vp8/decoder/demode.c index 5b837ad9b..74fe91803 100644 --- a/vp8/decoder/demode.c +++ b/vp8/decoder/demode.c @@ -91,65 +91,8 @@ void vp8_kfread_modes(VP8D_COMP *pbi) { #if CONFIG_SEGMENTATION - MACROBLOCKD *xd = &pbi->mb; - xd->up_available = (mb_row != 0); - xd->left_available = (mb_col != 0); - int count = 0; - int j; - if(xd->left_available) - left_id = (m-1)->mbmi.segment_id; - else - left_id = 0; - - if(xd->up_available) - above_id = (m-cp->mb_cols)->mbmi.segment_id; - else - above_id = 0; - - if (vp8_read(bc, xd->mb_segment_tree_probs[0])) - { - for(i = 0; i < MAX_MB_SEGMENTS; i++) - { - if((left_id != i) && (above_id != i)) - { - if(left_id != above_id) - { - if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0) - m->mbmi.segment_id = i; - else - m->mbmi.segment_id = 6-left_id-above_id-i; - break; - } - else - { - if (vp8_read(bc, xd->mb_segment_tree_probs[2+i]) == 0) - { - m->mbmi.segment_id = i; - break; - } - else - { - count++; - if(count == 1) - j = i; - if(count == 2) - { - m->mbmi.segment_id = 6-left_id-j-i; - break; - } - } - } - } - } - } - else - { - if (vp8_read(bc, xd->mb_segment_tree_probs[1])) - m->mbmi.segment_id = above_id; - else - m->mbmi.segment_id = left_id; - - } + vp8_read_mb_features(bc, &m->mbmi, &pbi->mb); + pbi->segmentation_map[(mb_row * cp->mb_cols) + mb_col] = m->mbmi.segment_id; #else vp8_read_mb_features(bc, &m->mbmi, &pbi->mb); #endif diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c index c87f3afd5..8d2b267a9 100644 --- a/vp8/decoder/onyxd_if.c +++ b/vp8/decoder/onyxd_if.c @@ -137,7 +137,11 @@ void vp8dx_remove_decompressor(VP8D_PTR ptr) if (!pbi) return; - +#if CONFIG_SEGMENTATION + // Delete sementation map + if (pbi->segmentation_map != 0) + vpx_free(pbi->segmentation_map); +#endif vp8_decoder_remove_threads(pbi); vp8_remove_common(&pbi->common); vpx_free(pbi); diff --git a/vp8/decoder/onyxd_int.h b/vp8/decoder/onyxd_int.h index 218c23943..e8b5d409a 100644 --- a/vp8/decoder/onyxd_int.h +++ b/vp8/decoder/onyxd_int.h @@ -81,7 +81,7 @@ typedef struct VP8Decompressor const unsigned char *Source; unsigned int source_sz; - + unsigned char *segmentation_map; unsigned int CPUFreq; unsigned int decode_microseconds; unsigned int time_decoding; diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index f0b345b06..800892007 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -862,9 +862,12 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) VP8_COMMON *const pc = & cpi->common; vp8_writer *const w = & cpi->bc; const MV_CONTEXT *mvc = pc->fc.mvc; + MACROBLOCKD *xd = &cpi->mb.e_mbd; #if CONFIG_SEGMENTATION int left_id, above_id; int i; + int sum; + int index = 0; #endif const int *const rfct = cpi->count_mb_ref_frame_usage; const int rf_intra = rfct[INTRA_FRAME]; @@ -920,7 +923,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) update_mbintra_mode_probs(cpi); vp8_write_mvprobs(cpi); - +#if CONFIG_SEGMENTATION + vp8_write_bit(w, (xd->temporal_update) ? 1:0); +#endif while (++mb_row < pc->mb_rows) { int mb_col = -1; @@ -931,7 +936,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) const MV_REFERENCE_FRAME rf = mi->ref_frame; const MB_PREDICTION_MODE mode = mi->mode; - MACROBLOCKD *xd = &cpi->mb.e_mbd; + //MACROBLOCKD *xd = &cpi->mb.e_mbd; // Distance of Mb to the various image edges. // These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units @@ -948,87 +953,37 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) if (cpi->mb.e_mbd.update_mb_segmentation_map) { #if CONFIG_SEGMENTATION - if(xd->left_available) - left_id = (m-1)->mbmi.segment_id; - else - left_id = 0; - - if(xd->up_available) - above_id = (m-pc->mb_cols)->mbmi.segment_id; - else - above_id = 0; - - if ((m->mbmi.segment_id == left_id) || (m->mbmi.segment_id == above_id)) + if (xd->temporal_update) { - vp8_write(w, 0, xd->mb_segment_tree_probs[0]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[0]); + sum = 0; + if (mb_col != 0) + sum += (m-1)->mbmi.segment_flag; + if (mb_row != 0) + sum += (m-pc->mb_cols)->mbmi.segment_flag; - if (left_id != above_id) + if (m->mbmi.segment_flag == 0) { - if(m->mbmi.segment_id == left_id) - { - vp8_write(w, 0, xd->mb_segment_tree_probs[1]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]); - } - else - { - vp8_write(w, 1, xd->mb_segment_tree_probs[1]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[1]); - } + vp8_write(w,0,xd->mb_segment_tree_probs[3+sum]); + segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[3+sum]); } else { - vp8_write(w, 0, xd->mb_segment_tree_probs[1]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]); + vp8_write(w,1,xd->mb_segment_tree_probs[3+sum]); + segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[3+sum]); + write_mb_features(w, mi, &cpi->mb.e_mbd); + cpi->segmentation_map[index] = mi->segment_id; } } else { - vp8_write(w, 1, xd->mb_segment_tree_probs[0]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[0]); - int count = 0; - for(i = 0; i < MAX_MB_SEGMENTS; i++) - { - if((left_id != i) && (above_id != i)) - { - if(left_id != above_id) - { - if(m->mbmi.segment_id == i) - { - vp8_write(w, 0, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]); - } - else - { - vp8_write(w, 1, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]); - } - break; - } - else - { - if(m->mbmi.segment_id == i) - { - vp8_write(w, 0, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]); - break; - } - else - { - count++; - vp8_write(w, 1, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]); - if(count == 2) - break; - } - } - } - } + write_mb_features(w, mi, &cpi->mb.e_mbd); + cpi->segmentation_map[index] = mi->segment_id; } + index++; #else write_mb_features(w, mi, &cpi->mb.e_mbd); #endif - } + } if (pc->mb_no_coeff_skip) vp8_encode_bool(w, m->mbmi.mb_skip_coeff, prob_skip_false); @@ -1157,6 +1112,7 @@ static void write_kfmodes(VP8_COMP *cpi) #if CONFIG_SEGMENTATION int left_id, above_id; int i; + int index = 0; #endif int mb_row = -1; int prob_skip_false = 0; @@ -1190,85 +1146,12 @@ static void write_kfmodes(VP8_COMP *cpi) if (cpi->mb.e_mbd.update_mb_segmentation_map) { #if CONFIG_SEGMENTATION - if(xd->left_available) - left_id = (m-1)->mbmi.segment_id; - else - left_id = 0; - - if(xd->up_available) - above_id = (m-c->mb_cols)->mbmi.segment_id; - else - above_id = 0; - - if ((m->mbmi.segment_id == left_id) || (m->mbmi.segment_id == above_id)) - { - vp8_write(bc, 0, xd->mb_segment_tree_probs[0]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[0]); - if (left_id != above_id) - { - if(m->mbmi.segment_id == left_id) - { - vp8_write(bc, 0, xd->mb_segment_tree_probs[1]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]); - } - else - { - vp8_write(bc, 1, xd->mb_segment_tree_probs[1]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[1]); - } - } - else - { - vp8_write(bc, 0, xd->mb_segment_tree_probs[1]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[1]); - } - } - else - { - vp8_write(bc, 1, xd->mb_segment_tree_probs[0]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[0]); - int count = 0; - for(i = 0; i < MAX_MB_SEGMENTS; i++) - { - if((left_id != i) && (above_id != i)) - { - if(left_id != above_id) - { - if(m->mbmi.segment_id == i) - { - vp8_write(bc, 0, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]); - } - else - { - vp8_write(bc, 1, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]); - } - break; - } - else - { - if(m->mbmi.segment_id == i) - { - vp8_write(bc, 0, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_zero(xd->mb_segment_tree_probs[2+i]); - break; - } - else - { - count++; - vp8_write(bc, 1, xd->mb_segment_tree_probs[2+i]); - segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[2+i]); - if(count == 2) - break; - } - } - } - } - } + write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd); + cpi->segmentation_map[index] = m->mbmi.segment_id; + index++; #else - write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd); + write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd); #endif } @@ -1587,10 +1470,9 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) } else vp8_start_encode(bc, cx_data); -#if CONFIG_SEGMENTATION - //xd->segmentation_enabled =1; - xd->update_mb_segmentation_map = 1; -#endif + + xd->update_mb_segmentation_map = 1; + // Signal whether or not Segmentation is enabled vp8_write_bit(bc, (xd->segmentation_enabled) ? 1 : 0); @@ -1810,7 +1692,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) #endif } #if CONFIG_SEGMENTATION - //printf("\nseg_cost is %d\n",segment_cost); + //printf("%d\n",segment_cost); #endif vp8_stop_encode(bc); diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index 4af2fdd69..faf8e2bd4 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -29,6 +29,7 @@ #include "subpixel.h" #include "vpx_ports/vpx_timer.h" + #if CONFIG_RUNTIME_CPU_DETECT #define RTCD(x) &cpi->common.rtcd.x #define IF_RTCD(x) (x) @@ -36,6 +37,13 @@ #define RTCD(x) NULL #define IF_RTCD(x) NULL #endif + +#if CONFIG_SEGMENTATION +#define SEEK_SEGID 12 +#define SEEK_SAMEID 4 +#define SEEK_DIFFID 7 +#endif + extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ; extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex); @@ -260,6 +268,7 @@ void encode_mb_row(VP8_COMP *cpi, int seg_map_index = (mb_row * cpi->common.mb_cols); #if CONFIG_SEGMENTATION int left_id, above_id; + int sum; #endif // reset above block coeffs xd->above_context[Y1CONTEXT] = cm->above_context[Y1CONTEXT]; @@ -370,6 +379,11 @@ void encode_mb_row(VP8_COMP *cpi, xd->gf_active_ptr++; // Increment pointer into gf useage flags structure for next mb + if ((xd->mbmi.mode == ZEROMV) && (xd->mbmi.ref_frame == LAST_FRAME)) + xd->mbmi.segment_id = 0; + else + xd->mbmi.segment_id = 1; + // store macroblock mode info into context array vpx_memcpy(&xd->mode_info_context->mbmi, &xd->mbmi, sizeof(xd->mbmi)); @@ -385,66 +399,40 @@ void encode_mb_row(VP8_COMP *cpi, recon_uvoffset += 8; #if CONFIG_SEGMENTATION - if(xd->left_available) - left_id = cpi->segmentation_map[seg_map_index+mb_col-1]; - else - left_id = 0; - - if(xd->up_available) - above_id = cpi->segmentation_map[seg_map_index+mb_col-cpi->common.mb_cols]; - else - above_id = 0; - - if ((xd->mbmi.segment_id == left_id) || (xd->mbmi.segment_id == above_id)) - { - segment_counts[8]++; - if (left_id != above_id) + //cpi->segmentation_map[mb_row * cm->mb_cols + mb_col] = xd->mbmi.segment_id; + if (cm->frame_type == KEY_FRAME) { - if(xd->mbmi.segment_id == left_id) - segment_counts[10]++; - else - segment_counts[11]++; + segment_counts[xd->mode_info_context->mbmi.segment_id] ++; } else - segment_counts[10]++; - } - else - { - segment_counts[9]++; - int count =0; - for(i = 0; i < MAX_MB_SEGMENTS; i++) { - if((left_id != i) && (above_id != i)) + sum = 0; + if (mb_col != 0) + sum += (xd->mode_info_context-1)->mbmi.segment_flag; + if (mb_row != 0) + sum += (xd->mode_info_context-cm->mb_cols)->mbmi.segment_flag; + + if (xd->mbmi.segment_id == cpi->segmentation_map[(mb_row*cm->mb_cols) + mb_col]) + xd->mode_info_context->mbmi.segment_flag = 0; + else + xd->mode_info_context->mbmi.segment_flag = 1; + + if (xd->mode_info_context->mbmi.segment_flag == 0) { - if(above_id != left_id) - { - if(xd->mbmi.segment_id == i) - segment_counts[i]++; - else - segment_counts[MAX_MB_SEGMENTS + i]++; - break; - } - else - { - if(xd->mbmi.segment_id == i) - { - segment_counts[i]++; - break; - } - else - { - count++; - segment_counts[MAX_MB_SEGMENTS + i]++; - if(count == 2) - break; - } - } + segment_counts[SEEK_SAMEID + sum]++; + segment_counts[10]++; + } + else + { + segment_counts[SEEK_DIFFID + sum]++; + segment_counts[11]++; + //calculate individual segment ids + segment_counts[xd->mode_info_context->mbmi.segment_id] ++; } } - } - + segment_counts[SEEK_SEGID + xd->mbmi.segment_id] ++; #else - segment_counts[xd->mode_info_context->mbmi.segment_id] ++; + segment_counts[xd->mode_info_context->mbmi.segment_id] ++; #endif // skip to next mb xd->mode_info_context++; @@ -477,7 +465,9 @@ void vp8_encode_frame(VP8_COMP *cpi) int i; TOKENEXTRA *tp = cpi->tok; #if CONFIG_SEGMENTATION - int segment_counts[MAX_MB_SEGMENTS + 8]; + int segment_counts[MAX_MB_SEGMENTS + SEEK_SEGID]; + int prob[3]; + int new_cost, original_cost; #else int segment_counts[MAX_MB_SEGMENTS]; #endif @@ -738,61 +728,114 @@ void vp8_encode_frame(VP8_COMP *cpi) } - // Work out the segment probabilites if segmentation is enabled if (xd->segmentation_enabled) { int tot_count; - int i; + int i,j; + int count1,count2,count3,count4; // Set to defaults vpx_memset(xd->mb_segment_tree_probs, 255 , sizeof(xd->mb_segment_tree_probs)); #if CONFIG_SEGMENTATION - tot_count = segment_counts[8] + segment_counts[9]; + + tot_count = segment_counts[12] + segment_counts[13] + segment_counts[14] + segment_counts[15]; + count1 = segment_counts[12] + segment_counts[13]; + count2 = segment_counts[14] + segment_counts[15]; if (tot_count) - xd->mb_segment_tree_probs[0] = (segment_counts[8] * 255) / tot_count; + prob[0] = (count1 * 255) / tot_count; - tot_count = segment_counts[10] + segment_counts[11]; + if (count1 > 0) + prob[1] = (segment_counts[12] * 255) /count1; - if (tot_count > 0) - xd->mb_segment_tree_probs[1] = (segment_counts[10] * 255) / tot_count; + if (count2 > 0) + prob[2] = (segment_counts[14] * 255) /count2; - tot_count = segment_counts[0] + segment_counts[4] ; + if (cm->frame_type != KEY_FRAME) + { + tot_count = segment_counts[4] + segment_counts[7]; + if (tot_count) + xd->mb_segment_tree_probs[3] = (segment_counts[4] * 255)/tot_count; - if (tot_count > 0) - xd->mb_segment_tree_probs[2] = (segment_counts[0] * 255) / tot_count; + tot_count = segment_counts[5] + segment_counts[8]; + if (tot_count) + xd->mb_segment_tree_probs[4] = (segment_counts[5] * 255)/tot_count; - tot_count = segment_counts[1] + segment_counts[5]; + tot_count = segment_counts[6] + segment_counts[9]; + if (tot_count) + xd->mb_segment_tree_probs[5] = (segment_counts[6] * 255)/tot_count; + } - if (tot_count > 0) - xd->mb_segment_tree_probs[3] = (segment_counts[1] * 255) / tot_count; + tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3]; + count3 = segment_counts[0] + segment_counts[1]; + count4 = segment_counts[2] + segment_counts[3]; - tot_count = segment_counts[2] + segment_counts[6]; + if (tot_count) + xd->mb_segment_tree_probs[0] = (count3 * 255) / tot_count; - if (tot_count > 0) - xd->mb_segment_tree_probs[4] = (segment_counts[2] * 255) / tot_count; + if (count3 > 0) + xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) /count3; + + if (count4 > 0) + xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) /count4; + + for (i = 0; i < MB_FEATURE_TREE_PROBS+3; i++) + { + if (xd->mb_segment_tree_probs[i] == 0) + xd->mb_segment_tree_probs[i] = 1; + } - tot_count = segment_counts[3] + segment_counts[7]; + original_cost = count1 * vp8_cost_zero(prob[0]) + count2 * vp8_cost_one(prob[0]); + + if (count1 > 0) + original_cost += segment_counts[12] * vp8_cost_zero(prob[1]) + segment_counts[13] * vp8_cost_one(prob[1]); + + if (count2 > 0) + original_cost += segment_counts[14] * vp8_cost_zero(prob[2]) + segment_counts[15] * vp8_cost_one(prob[2]) ; + + new_cost = 0; + + if (cm->frame_type != KEY_FRAME) + { + new_cost = segment_counts[4] * vp8_cost_zero(xd->mb_segment_tree_probs[3]) + segment_counts[7] * vp8_cost_one(xd->mb_segment_tree_probs[3]); + + new_cost += segment_counts[5] * vp8_cost_zero(xd->mb_segment_tree_probs[4]) + segment_counts[8] * vp8_cost_one(xd->mb_segment_tree_probs[4]); + + new_cost += segment_counts[6] * vp8_cost_zero(xd->mb_segment_tree_probs[5]) + segment_counts[9] * vp8_cost_one (xd->mb_segment_tree_probs[5]); + } if (tot_count > 0) - xd->mb_segment_tree_probs[5] = (segment_counts[3] * 255) / tot_count; + new_cost += count3 * vp8_cost_zero(xd->mb_segment_tree_probs[0]) + count4 * vp8_cost_one(xd->mb_segment_tree_probs[0]); + + if (count3 > 0) + new_cost += segment_counts[0] * vp8_cost_zero(xd->mb_segment_tree_probs[1]) + segment_counts[1] * vp8_cost_one(xd->mb_segment_tree_probs[1]); + if (count4 > 0) + new_cost += segment_counts[2] * vp8_cost_zero(xd->mb_segment_tree_probs[2]) + segment_counts[3] * vp8_cost_one(xd->mb_segment_tree_probs[2]) ; + + if (new_cost < original_cost) + xd->temporal_update = 1; + else + { + xd->temporal_update = 0; + xd->mb_segment_tree_probs[0] = prob[0]; + xd->mb_segment_tree_probs[1] = prob[1]; + xd->mb_segment_tree_probs[2] = prob[2]; + } #else tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3]; + count1 = segment_counts[0] + segment_counts[1]; + count2 = segment_counts[2] + segment_counts[3]; if (tot_count) - xd->mb_segment_tree_probs[0] = ((segment_counts[0] + segment_counts[1]) * 255) / tot_count; + xd->mb_segment_tree_probs[0] = (count1 * 255) / tot_count; - tot_count = segment_counts[0] + segment_counts[1]; + if (count1 > 0) + xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) /count1; - if (tot_count > 0) - xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) / tot_count; - - tot_count = segment_counts[2] + segment_counts[3]; - - if (tot_count > 0) - xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) / tot_count; + if (count2 > 0) + xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) /count2; #endif // Zero probabilities not allowed diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index bab5f364a..9bc7f523a 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -277,27 +277,10 @@ static void set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned ch static void segmentation_test_function(VP8_PTR ptr) { VP8_COMP *cpi = (VP8_COMP *)(ptr); -#if CONFIG_SEGMENTATION - int i,j; -#endif unsigned char *seg_map; signed char feature_data[MB_LVL_MAX][MAX_MB_SEGMENTS]; CHECK_MEM_ERROR(seg_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1)); // Create a temporary map for segmentation data. -#if CONFIG_SEGMENTATION - // MB loop to set local segmentation map - for (i = 0; i < cpi->common.mb_rows; i++ ) - { - for (j = 0; j < cpi->common.mb_cols; j++ ) - { - if (j >= cpi->common.mb_cols/4 && j < (cpi->common.mb_cols*3)/4 ) - seg_map[(i*cpi->common.mb_cols) + j] = 2; - else - seg_map[(i*cpi->common.mb_cols) + j] = 0; - } - } - -#endif // MB loop to set local segmentation map /*for ( i = 0; i < cpi->common.mb_rows; i++ ) @@ -3542,17 +3525,16 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, unsigned long *size, unsign int drop_mark75 = drop_mark * 2 / 3; int drop_mark50 = drop_mark / 4; int drop_mark25 = drop_mark / 8; -#if CONFIG_SEGMENTATION - int i; -#endif + // Clear down mmx registers to allow floating point in what follows vp8_clear_system_state(); // Test code for segmentation of gf/arf (0,0) + //segmentation_test_function((VP8_PTR) cpi); #if CONFIG_SEGMENTATION - segmentation_test_function((VP8_PTR) cpi); + cpi->mb.e_mbd.segmentation_enabled = 1; + cpi->mb.e_mbd.update_mb_segmentation_map = 1; #endif - //segmentation_test_function((VP8_PTR) cpi); // For an alt ref frame in 2 pass we skip the call to the second pass function that sets the target bandwidth #if !(CONFIG_REALTIME_ONLY) @@ -4057,28 +4039,6 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, unsigned long *size, unsign vp8_setup_key_frame(cpi); // transform / motion compensation build reconstruction frame -#if CONFIG_SEGMENTATION - // MB loop to set local segmentation map - for (i = 0; i < cpi->common.mb_rows; i++ ) - { - int j = (cpi->common.mb_cols/4); - int k = (cpi->common.mb_cols*3)/4; - if((cm->current_video_frame%2 == 0 && icommon.mb_rows/2)||(cm->current_video_frame%2 == 1 && i>cpi->common.mb_rows/2)) - { - cpi->segmentation_map[(i*cpi->common.mb_cols) + j] = 2; - cpi->segmentation_map[(i*cpi->common.mb_cols) + j-1] = 2; - cpi->segmentation_map[(i*cpi->common.mb_cols) + k] = 2; - cpi->segmentation_map[(i*cpi->common.mb_cols) + k+1] = 2; - } - else if((cm->current_video_frame%2 == 1 && icommon.mb_rows/2)||(cm->current_video_frame%2 == 0 && i>cpi->common.mb_rows/2)) - { - cpi->segmentation_map[(i*cpi->common.mb_cols) + j] = 0; - cpi->segmentation_map[(i*cpi->common.mb_cols) + j-1] = 0; - cpi->segmentation_map[(i*cpi->common.mb_cols) + k] = 0; - cpi->segmentation_map[(i*cpi->common.mb_cols) + k+1] = 0; - } - } -#endif vp8_encode_frame(cpi); cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi); cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0; -- 2.40.0