ref: b9be7a464f065c3700f937eea01d9298002b37eb
parent: 7288cdf79dd179d5bbf927db6240e3b9a4da412b
author: John Koleszar <jkoleszar@google.com>
date: Wed Sep 29 09:04:04 EDT 2010
Fix loopfilter delta zero transitions Loopfilter deltas are initialized to zero on keyframes in the decoder. The values then persist from the previous frame unless an update bit is set in the bitstream. This data is not included in the entropy data saved by the 'refresh entropy' bit in the bitstream, so it is effectively an additional contextual element beyond the 3 ref-frames and the entropy data. The encoder was treating this delta update bit as update-if-nonzero, meaning that the value would be refreshed even if it hadn't changed, and more significantly, if the correct value for the delta changed to zero, the update wouldn't be sent, and the decoder would preserve the last (presumably non-zero) value. This patch updates the encoder to send an update only if the value has changed from the previously transmitted value. It also forces the value to be transmitted in error resilient mode, to account for lost context in the event of lost frames. Change-Id: I56671d5b42965d0166ac226765dbfce3e5301868
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -262,9 +262,9 @@
unsigned char mode_ref_lf_delta_update;
// Delta values have the range +/- MAX_LOOP_FILTER
- //char ref_lf_deltas[MAX_REF_LF_DELTAS]; // 0 = Intra, Last, GF, ARF
- //char mode_lf_deltas[MAX_MODE_LF_DELTAS]; // 0 = BPRED, ZERO_MV, MV, SPLIT
+ signed char last_ref_lf_deltas[MAX_REF_LF_DELTAS]; // 0 = Intra, Last, GF, ARF
signed char ref_lf_deltas[MAX_REF_LF_DELTAS]; // 0 = Intra, Last, GF, ARF
+ signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS]; // 0 = BPRED, ZERO_MV, MV, SPLIT
signed char mode_lf_deltas[MAX_MODE_LF_DELTAS]; // 0 = BPRED, ZERO_MV, MV, SPLIT
// Distance of MB away from frame edges
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -1490,9 +1490,11 @@
if (xd->mode_ref_lf_delta_enabled)
{
// Do the deltas need to be updated
- vp8_write_bit(bc, (xd->mode_ref_lf_delta_update) ? 1 : 0);
+ int send_update = xd->mode_ref_lf_delta_update
+ || cpi->oxcf.error_resilient_mode;
- if (xd->mode_ref_lf_delta_update)
+ vp8_write_bit(bc, send_update);
+ if (send_update)
{
int Data;
@@ -1502,8 +1504,10 @@
Data = xd->ref_lf_deltas[i];
// Frame level data
- if (Data)
+ if (xd->ref_lf_deltas[i] != xd->last_ref_lf_deltas[i]
+ || cpi->oxcf.error_resilient_mode)
{
+ xd->last_ref_lf_deltas[i] = xd->ref_lf_deltas[i];
vp8_write_bit(bc, 1);
if (Data > 0)
@@ -1527,8 +1531,10 @@
{
Data = xd->mode_lf_deltas[i];
- if (Data)
+ if (xd->mode_lf_deltas[i] != xd->last_mode_lf_deltas[i]
+ || cpi->oxcf.error_resilient_mode)
{
+ xd->last_mode_lf_deltas[i] = xd->mode_lf_deltas[i];
vp8_write_bit(bc, 1);
if (Data > 0)
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -272,6 +272,8 @@
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));
// jbb trial !
mode_ref_lf_test_function(cpi);
@@ -4093,6 +4095,9 @@
{
int i;
+ // Reset the loop filter deltas and segmentation map
+ setup_features(cpi);
+
// If segmentation is enabled force a map update for key frames
if (cpi->mb.e_mbd.segmentation_enabled)
{
@@ -4100,12 +4105,6 @@
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
}
- // If mode or reference frame based loop filter deltas are enabled then force an update for key frames.
- if (cpi->mb.e_mbd.mode_ref_lf_delta_enabled)
- {
- cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
- }
-
// The alternate reference frame cannot be active for a key frame
cpi->source_alt_ref_active = FALSE;
@@ -4527,17 +4526,14 @@
// Clear the Alt reference frame active flag when we have a key frame
cpi->source_alt_ref_active = FALSE;
+ // Reset the loop filter deltas and segmentation map
+ setup_features(cpi);
+
// If segmentation is enabled force a map update for key frames
if (cpi->mb.e_mbd.segmentation_enabled)
{
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
- }
-
- // If mode or reference frame based loop filter deltas are enabled then force an update for key frames.
- if (cpi->mb.e_mbd.mode_ref_lf_delta_enabled)
- {
- cpi->mb.e_mbd.mode_ref_lf_delta_update = 1;
}
vp8_restore_coding_context(cpi);