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
#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
(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 )
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
\ No newline at end of file
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 );
int segment_id,
SEG_LVL_FEATURES feature_id );
+int is_segfeature_signed( SEG_LVL_FEATURES feature_id );
+
#endif /* __INC_SEG_COMMON_H__ */
{
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++)
// 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++)
{
// 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
{
{
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);
#if CONFIG_SEGFEATURES
// debug output
-#if 0
+#if DBG_PRNT_SEGMAP
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
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,
// 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
}
}
+// 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
(
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]++;
}
}
// 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);
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));
// 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) )
+ // 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->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;
-
- // 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);
+ 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_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;
}
}