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
This commit is contained in:
Родитель
00cec8f9e9
Коммит
b9a18344cf
|
@ -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
|
||||
|
|
|
@ -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->up_available)
|
||||
above_id = (mi-pc->mb_cols)->mbmi.segment_id;
|
||||
else
|
||||
above_id = 0;
|
||||
|
||||
if (vp8_read(bc, xd->mb_segment_tree_probs[0]))
|
||||
if (xd->temporal_update)
|
||||
{
|
||||
for(i = 0; i < MAX_MB_SEGMENTS; i++)
|
||||
sum = 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[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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 (count2 > 0)
|
||||
prob[2] = (segment_counts[14] * 255) /count2;
|
||||
|
||||
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;
|
||||
|
||||
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[6] + segment_counts[9];
|
||||
if (tot_count)
|
||||
xd->mb_segment_tree_probs[5] = (segment_counts[6] * 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];
|
||||
|
||||
if (tot_count)
|
||||
xd->mb_segment_tree_probs[0] = (count3 * 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;
|
||||
}
|
||||
|
||||
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[1] = (segment_counts[10] * 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]);
|
||||
|
||||
tot_count = segment_counts[0] + segment_counts[4] ;
|
||||
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 (tot_count > 0)
|
||||
xd->mb_segment_tree_probs[2] = (segment_counts[0] * 255) / tot_count;
|
||||
|
||||
tot_count = segment_counts[1] + segment_counts[5];
|
||||
|
||||
if (tot_count > 0)
|
||||
xd->mb_segment_tree_probs[3] = (segment_counts[1] * 255) / tot_count;
|
||||
|
||||
tot_count = segment_counts[2] + segment_counts[6];
|
||||
|
||||
if (tot_count > 0)
|
||||
xd->mb_segment_tree_probs[4] = (segment_counts[2] * 255) / tot_count;
|
||||
|
||||
tot_count = segment_counts[3] + segment_counts[7];
|
||||
|
||||
if (tot_count > 0)
|
||||
xd->mb_segment_tree_probs[5] = (segment_counts[3] * 255) / tot_count;
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
#if CONFIG_SEGMENTATION
|
||||
segmentation_test_function((VP8_PTR) cpi);
|
||||
#endif
|
||||
//segmentation_test_function((VP8_PTR) cpi);
|
||||
#if CONFIG_SEGMENTATION
|
||||
cpi->mb.e_mbd.segmentation_enabled = 1;
|
||||
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
|
||||
#endif
|
||||
|
||||
// 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 && i<cpi->common.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 && i<cpi->common.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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче