Segmentation Features;
Only encode sign bit for feature data that can have a sign. Tweaks to the test segmentation rules so that it now actually gives a net benefit on the derf set of about 0.4% though much higher on some clips at the low end. Change-Id: I8e61f1aebf41c9037db7e67e2f8975aa18a0c986
This commit is contained in:
parent
01ce04bc06
commit
23701f4f87
@ -10,6 +10,9 @@
|
||||
|
||||
#include "vp8/common/seg_common.h"
|
||||
|
||||
const int segfeaturedata_signed[SEG_LVL_MAX] = {1, 1, 0, 0, 0, 0};
|
||||
|
||||
|
||||
// These functions provide access to new segment level features.
|
||||
// Eventually these function may be "optimized out" but for the moment,
|
||||
// the coding mechanism is still subject to change so these provide a
|
||||
@ -25,6 +28,12 @@ int segfeature_active( MACROBLOCKD *xd,
|
||||
(0x01 << feature_id) ) );
|
||||
}
|
||||
|
||||
void clearall_segfeatures( MACROBLOCKD *xd )
|
||||
{
|
||||
vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
|
||||
vpx_memset(xd->segment_feature_mask, 0, sizeof(xd->segment_feature_mask));
|
||||
}
|
||||
|
||||
void enable_segfeature( MACROBLOCKD *xd,
|
||||
int segment_id,
|
||||
SEG_LVL_FEATURES feature_id )
|
||||
@ -38,4 +47,9 @@ void disable_segfeature( MACROBLOCKD *xd,
|
||||
xd->segment_feature_mask[segment_id] &= ~(1 << feature_id);
|
||||
}
|
||||
|
||||
int is_segfeature_signed( SEG_LVL_FEATURES feature_id )
|
||||
{
|
||||
return ( segfeaturedata_signed[feature_id] );
|
||||
}
|
||||
|
||||
// TBD? Functions to read and write segment data with range / validity checking
|
@ -18,6 +18,8 @@ int segfeature_active( MACROBLOCKD *xd,
|
||||
int segment_id,
|
||||
SEG_LVL_FEATURES feature_id );
|
||||
|
||||
void clearall_segfeatures( MACROBLOCKD *xd );
|
||||
|
||||
void enable_segfeature( MACROBLOCKD *xd,
|
||||
int segment_id,
|
||||
SEG_LVL_FEATURES feature_id );
|
||||
@ -26,5 +28,7 @@ void disable_segfeature( MACROBLOCKD *xd,
|
||||
int segment_id,
|
||||
SEG_LVL_FEATURES feature_id );
|
||||
|
||||
int is_segfeature_signed( SEG_LVL_FEATURES feature_id );
|
||||
|
||||
#endif /* __INC_SEG_COMMON_H__ */
|
||||
|
||||
|
@ -1030,14 +1030,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
{
|
||||
xd->mb_segement_abs_delta = (unsigned char)vp8_read_bit(bc);
|
||||
|
||||
// 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));
|
||||
clearall_segfeatures( xd );
|
||||
|
||||
// For each segmentation...
|
||||
for (j = 0; j < MAX_MB_SEGMENTS; j++)
|
||||
@ -1045,8 +1039,11 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
// For each of the segments features...
|
||||
for (i = 0; i < SEG_LVL_MAX; i++)
|
||||
{
|
||||
|
||||
#else
|
||||
// Clear down feature data structure
|
||||
vpx_memset(xd->segment_feature_data, 0,
|
||||
sizeof(xd->segment_feature_data));
|
||||
|
||||
// For each segmentation feature...
|
||||
for (i = 0; i < SEG_LVL_MAX; i++)
|
||||
{
|
||||
@ -1061,10 +1058,23 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
||||
// Update the feature data and mask
|
||||
enable_segfeature(xd, j, i);
|
||||
#endif
|
||||
xd->segment_feature_data[j][i] = (signed char)vp8_read_literal(bc, mb_feature_data_bits[i]);
|
||||
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];
|
||||
#if CONFIG_SEGFEATURES
|
||||
// Is the segment data signed..
|
||||
if ( is_segfeature_signed(i) )
|
||||
#else
|
||||
if ( 1 )
|
||||
#endif
|
||||
{
|
||||
if (vp8_read_bit(bc))
|
||||
{
|
||||
xd->segment_feature_data[j][i] =
|
||||
-xd->segment_feature_data[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1987,20 +1987,32 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
|
||||
{
|
||||
vp8_write_bit(bc, 1);
|
||||
|
||||
// Encode the relevant feature data
|
||||
if (Data < 0)
|
||||
#if CONFIG_SEGFEATURES
|
||||
// Is the segment data signed..
|
||||
if ( is_segfeature_signed(i) )
|
||||
#else
|
||||
if ( 1 )
|
||||
#endif
|
||||
{
|
||||
Data = - Data;
|
||||
vp8_write_literal(bc, Data,
|
||||
mb_feature_data_bits[i]);
|
||||
vp8_write_bit(bc, 1);
|
||||
// Encode the relevant feature data
|
||||
if (Data < 0)
|
||||
{
|
||||
Data = - Data;
|
||||
vp8_write_literal(bc, Data,
|
||||
mb_feature_data_bits[i]);
|
||||
vp8_write_bit(bc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vp8_write_literal(bc, Data,
|
||||
mb_feature_data_bits[i]);
|
||||
vp8_write_bit(bc, 0);
|
||||
}
|
||||
}
|
||||
// Unsigned data element so no sign bit needed
|
||||
else
|
||||
{
|
||||
vp8_write_literal(bc, Data,
|
||||
mb_feature_data_bits[i]);
|
||||
vp8_write_bit(bc, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
vp8_write_bit(bc, 0);
|
||||
|
@ -969,7 +969,7 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
|
||||
#if CONFIG_SEGFEATURES
|
||||
// debug output
|
||||
#if 0
|
||||
#if DBG_PRNT_SEGMAP
|
||||
{
|
||||
FILE *statsfile;
|
||||
statsfile = fopen("segmap2.stt", "a");
|
||||
|
@ -143,6 +143,47 @@ static int do_16x16_motion_search
|
||||
return err;
|
||||
}
|
||||
|
||||
static int do_16x16_zerozero_search
|
||||
(
|
||||
VP8_COMP *cpi,
|
||||
int_mv *dst_mv,
|
||||
YV12_BUFFER_CONFIG *buf,
|
||||
int buf_mb_y_offset,
|
||||
YV12_BUFFER_CONFIG *ref,
|
||||
int mb_y_offset
|
||||
)
|
||||
{
|
||||
MACROBLOCK * const x = &cpi->mb;
|
||||
MACROBLOCKD * const xd = &x->e_mbd;
|
||||
unsigned int err, tmp_err;
|
||||
int_mv tmp_mv;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 16; n++) {
|
||||
BLOCKD *d = &xd->block[n];
|
||||
BLOCK *b = &x->block[n];
|
||||
|
||||
b->base_src = &buf->y_buffer;
|
||||
b->src_stride = buf->y_stride;
|
||||
b->src = buf->y_stride * (n & 12) + (n & 3) * 4 + buf_mb_y_offset;
|
||||
|
||||
d->base_pre = &ref->y_buffer;
|
||||
d->pre_stride = ref->y_stride;
|
||||
d->pre = ref->y_stride * (n & 12) + (n & 3) * 4 + mb_y_offset;
|
||||
}
|
||||
|
||||
// Try zero MV first
|
||||
// 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)
|
||||
(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;
|
||||
}
|
||||
static int find_best_16x16_intra
|
||||
(
|
||||
VP8_COMP *cpi,
|
||||
@ -227,10 +268,17 @@ static void update_mbgraph_mb_stats
|
||||
// Alt-ref frame MV search, if it exists and is different than last/golden frame
|
||||
if (alt_ref)
|
||||
{
|
||||
int a_motion_error = do_16x16_motion_search(cpi, prev_alt_ref_mv,
|
||||
&stats->ref[ALTREF_FRAME].m.mv,
|
||||
buf, mb_y_offset,
|
||||
alt_ref, arf_y_offset);
|
||||
//int a_motion_error = do_16x16_motion_search(cpi, prev_alt_ref_mv,
|
||||
// &stats->ref[ALTREF_FRAME].m.mv,
|
||||
// buf, mb_y_offset,
|
||||
// alt_ref, arf_y_offset);
|
||||
|
||||
int a_motion_error =
|
||||
do_16x16_zerozero_search( cpi,
|
||||
&stats->ref[ALTREF_FRAME].m.mv,
|
||||
buf, mb_y_offset,
|
||||
alt_ref, arf_y_offset);
|
||||
|
||||
stats->ref[ALTREF_FRAME].err = a_motion_error;
|
||||
}
|
||||
else
|
||||
@ -312,6 +360,15 @@ static void update_mbgraph_frame_stats
|
||||
}
|
||||
}
|
||||
|
||||
// Test for small magnitude (<= 1 pel mvs)
|
||||
int small_mv( MV mv )
|
||||
{
|
||||
if ( (abs( (int)mv.col ) > 2) || (abs( (int)mv.row ) > 2) )
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//void separate_arf_mbs_byzz
|
||||
void separate_arf_mbs
|
||||
(
|
||||
@ -350,16 +407,15 @@ void separate_arf_mbs
|
||||
int altref_err = mb_stats->ref[ALTREF_FRAME].err;
|
||||
|
||||
int intra_err =
|
||||
((mb_stats->ref[INTRA_FRAME ].err * 9) >> 3);
|
||||
mb_stats->ref[INTRA_FRAME ].err + 250;
|
||||
|
||||
int golden_err =
|
||||
250 + ((mb_stats->ref[GOLDEN_FRAME].err * 9) >> 3);
|
||||
mb_stats->ref[GOLDEN_FRAME].err + 250;
|
||||
|
||||
// Test for altref vs intra and gf and that its mv was 0,0.
|
||||
if ( mb_stats->ref[ALTREF_FRAME].m.mv.as_int ||
|
||||
( (altref_err > 500) &&
|
||||
( (altref_err > (intra_err >> 2)) ||
|
||||
(altref_err > golden_err) ) ) )
|
||||
if ( (altref_err > 1000) ||
|
||||
(altref_err > intra_err) ||
|
||||
(altref_err > golden_err) )
|
||||
{
|
||||
arf_not_zz[offset + mb_col]++;
|
||||
}
|
||||
@ -389,7 +445,8 @@ void separate_arf_mbs
|
||||
}
|
||||
|
||||
// Only bother with segmentation if over 10% of the MBs in static segment
|
||||
if ( ncnt[1] && (ncnt[0] / ncnt[1] < 10) )
|
||||
//if ( ncnt[1] && (ncnt[0] / ncnt[1] < 10) )
|
||||
if ( 1 )
|
||||
{
|
||||
cpi->mbgraph_use_arf_segmentation = ncnt[1];
|
||||
vp8_enable_segmentation((VP8_PTR) cpi);
|
||||
|
@ -489,8 +489,8 @@ static void init_seg_features(VP8_COMP *cpi)
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable and clear down for KF,ARF and low Q
|
||||
if ( cm->frame_type == KEY_FRAME || cm->refresh_alt_ref_frame )
|
||||
// Disable and clear down for KF
|
||||
if ( cm->frame_type == KEY_FRAME )
|
||||
{
|
||||
// Clear down the global segmentation map
|
||||
vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
|
||||
@ -499,59 +499,117 @@ static void init_seg_features(VP8_COMP *cpi)
|
||||
|
||||
// Disable segmentation
|
||||
vp8_disable_segmentation((VP8_PTR)cpi);
|
||||
|
||||
// Clear down the segment features.
|
||||
clearall_segfeatures(xd);
|
||||
}
|
||||
|
||||
// First normal frame in a valid alt ref group and we dont have low Q
|
||||
else if ( cpi->source_alt_ref_active &&
|
||||
(cpi->common.frames_since_golden == 1) )
|
||||
// If this is an alt ref frame
|
||||
else if ( cm->refresh_alt_ref_frame )
|
||||
{
|
||||
// Low Q test (only use segmentation at high q)
|
||||
if ( ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
|
||||
(cpi->cq_target_quality > 56 ) ) ||
|
||||
(cpi->ni_av_qi > 64) )
|
||||
{
|
||||
xd->segment_feature_data[1][SEG_LVL_REF_FRAME] = LAST_FRAME;
|
||||
xd->segment_feature_data[1][SEG_LVL_MODE] = ZEROMV;
|
||||
xd->segment_feature_data[1][SEG_LVL_EOB] = 10;
|
||||
xd->segment_feature_data[1][SEG_LVL_ALT_Q] = 10;
|
||||
xd->segment_feature_data[1][SEG_LVL_ALT_LF] = -5;
|
||||
// Clear down the global segmentation map
|
||||
vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
|
||||
xd->update_mb_segmentation_map = 0;
|
||||
xd->update_mb_segmentation_data = 0;
|
||||
|
||||
// Disable segmentation and individual segment features by default
|
||||
vp8_disable_segmentation((VP8_PTR)cpi);
|
||||
clearall_segfeatures(xd);
|
||||
|
||||
// Scan frames from current to arf frame.
|
||||
// This function re-enables segmentation if appropriate.
|
||||
vp8_update_mbgraph_stats(cpi);
|
||||
|
||||
// If segmentation was enabled set those features needed for the
|
||||
// arf itself.
|
||||
if ( xd->segmentation_enabled )
|
||||
{
|
||||
xd->update_mb_segmentation_map = 1;
|
||||
xd->update_mb_segmentation_data = 1;
|
||||
|
||||
xd->segment_feature_data[1][SEG_LVL_ALT_Q] = -3;
|
||||
xd->segment_feature_data[1][SEG_LVL_ALT_LF] = -2;
|
||||
|
||||
// Enable target features is the segment feature mask
|
||||
enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
|
||||
enable_segfeature(xd, 1, SEG_LVL_MODE);
|
||||
enable_segfeature(xd, 1, SEG_LVL_EOB);
|
||||
enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
|
||||
enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
|
||||
|
||||
// Where relevant assume segment data is delta data
|
||||
xd->mb_segement_abs_delta = SEGMENT_DELTADATA;
|
||||
|
||||
// Scan frames from current to arf frame and define segmentation
|
||||
vp8_update_mbgraph_stats(cpi);
|
||||
}
|
||||
}
|
||||
// Normal frames if segmentation got enabled.
|
||||
|
||||
// All other frames if segmentation has been enabled
|
||||
else if ( xd->segmentation_enabled )
|
||||
{
|
||||
// Special case where we are coding over the top of a previous
|
||||
// alt ref frame
|
||||
if ( cpi->is_src_frame_alt_ref )
|
||||
// First normal frame in a valid gf or alt ref group
|
||||
if ( cpi->common.frames_since_golden == 0 )
|
||||
{
|
||||
if ( cpi->source_alt_ref_pending )
|
||||
// Set up segment features for normal frames in an af group
|
||||
if ( cpi->source_alt_ref_active )
|
||||
{
|
||||
xd->update_mb_segmentation_map = 0;
|
||||
xd->update_mb_segmentation_data = 1;
|
||||
xd->segment_feature_data[1][SEG_LVL_REF_FRAME] = ALTREF_FRAME;
|
||||
xd->mb_segement_abs_delta = SEGMENT_DELTADATA;
|
||||
|
||||
xd->segment_feature_data[1][SEG_LVL_ALT_Q] = 5;
|
||||
xd->segment_feature_data[1][SEG_LVL_ALT_LF] = -2;
|
||||
|
||||
enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
|
||||
enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
|
||||
|
||||
if ( ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
|
||||
(cpi->cq_target_quality > 56 ) ) ||
|
||||
(cpi->ni_av_qi > 64) )
|
||||
{
|
||||
xd->segment_feature_data[1]
|
||||
[SEG_LVL_REF_FRAME] = LAST_FRAME;
|
||||
xd->segment_feature_data[1][SEG_LVL_MODE] = ZEROMV;
|
||||
xd->segment_feature_data[1][SEG_LVL_EOB] = 15;
|
||||
|
||||
enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
|
||||
enable_segfeature(xd, 1, SEG_LVL_MODE);
|
||||
enable_segfeature(xd, 1, SEG_LVL_EOB);
|
||||
}
|
||||
}
|
||||
|
||||
// Disable segmentation and clear down features if alt ref
|
||||
// is not active for this group
|
||||
else
|
||||
{
|
||||
vp8_disable_segmentation((VP8_PTR)cpi);
|
||||
|
||||
vpx_memset( cpi->segmentation_map, 0,
|
||||
(cm->mb_rows * cm->mb_cols));
|
||||
xd->update_mb_segmentation_map = 1;
|
||||
xd->update_mb_segmentation_data = 1;
|
||||
|
||||
xd->update_mb_segmentation_map = 0;
|
||||
xd->update_mb_segmentation_data = 0;
|
||||
|
||||
clearall_segfeatures(xd);
|
||||
}
|
||||
}
|
||||
|
||||
// Special case where we are coding over the top of a previous
|
||||
// alt ref frame
|
||||
else if ( cpi->is_src_frame_alt_ref )
|
||||
{
|
||||
// Enable mode and ref frame features for segment 0 as well
|
||||
enable_segfeature(xd, 0, SEG_LVL_REF_FRAME);
|
||||
enable_segfeature(xd, 0, SEG_LVL_MODE);
|
||||
|
||||
// All mbs should use ALTREF_FRAME, ZEROMV
|
||||
xd->segment_feature_data[0][SEG_LVL_REF_FRAME] = ALTREF_FRAME;
|
||||
xd->segment_feature_data[0][SEG_LVL_MODE] = ZEROMV;
|
||||
xd->segment_feature_data[1][SEG_LVL_REF_FRAME] = ALTREF_FRAME;
|
||||
xd->segment_feature_data[1][SEG_LVL_MODE] = ZEROMV;
|
||||
|
||||
// Enable data udpate
|
||||
xd->update_mb_segmentation_data = 1;
|
||||
}
|
||||
// All other frames.
|
||||
else
|
||||
{
|
||||
// No updeates.. leave things as they are.
|
||||
xd->update_mb_segmentation_map = 0;
|
||||
xd->update_mb_segmentation_data = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user