Index: source/libvpx/test/error_resilience_test.cc |
diff --git a/source/libvpx/test/error_resilience_test.cc b/source/libvpx/test/error_resilience_test.cc |
index 182547bdfaa1d3d3e8dbe0c49ed790106ba01512..9a99a80f8f5287ac1a5263c57aa6aa9b46530278 100644 |
--- a/source/libvpx/test/error_resilience_test.cc |
+++ b/source/libvpx/test/error_resilience_test.cc |
@@ -37,6 +37,7 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest, |
void Reset() { |
error_nframes_ = 0; |
droppable_nframes_ = 0; |
+ pattern_switch_ = 0; |
} |
virtual void SetUp() { |
@@ -62,19 +63,37 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest, |
// 1 3 |
// 0 2 ..... |
// LAST is updated on base/layer 0, GOLDEN updated on layer 1. |
- int SetFrameFlags(int frame_num, int num_temp_layers) { |
+ // Non-zero pattern_switch parameter means pattern will switch to |
+ // not using LAST for frame_num >= pattern_switch. |
+ int SetFrameFlags(int frame_num, |
+ int num_temp_layers, |
+ int pattern_switch) { |
int frame_flags = 0; |
if (num_temp_layers == 2) { |
- if (frame_num % 2 == 0) { |
- // Layer 0: predict from L and ARF, update L. |
- frame_flags = VP8_EFLAG_NO_REF_GF | |
- VP8_EFLAG_NO_UPD_GF | |
- VP8_EFLAG_NO_UPD_ARF; |
- } else { |
- // Layer 1: predict from L, GF, and ARF, and update GF. |
- frame_flags = VP8_EFLAG_NO_UPD_ARF | |
- VP8_EFLAG_NO_UPD_LAST; |
- } |
+ if (frame_num % 2 == 0) { |
+ if (frame_num < pattern_switch || pattern_switch == 0) { |
+ // Layer 0: predict from LAST and ARF, update LAST. |
+ frame_flags = VP8_EFLAG_NO_REF_GF | |
+ VP8_EFLAG_NO_UPD_GF | |
+ VP8_EFLAG_NO_UPD_ARF; |
+ } else { |
+ // Layer 0: predict from GF and ARF, update GF. |
+ frame_flags = VP8_EFLAG_NO_REF_LAST | |
+ VP8_EFLAG_NO_UPD_LAST | |
+ VP8_EFLAG_NO_UPD_ARF; |
+ } |
+ } else { |
+ if (frame_num < pattern_switch || pattern_switch == 0) { |
+ // Layer 1: predict from L, GF, and ARF, update GF. |
+ frame_flags = VP8_EFLAG_NO_UPD_ARF | |
+ VP8_EFLAG_NO_UPD_LAST; |
+ } else { |
+ // Layer 1: predict from GF and ARF, update GF. |
+ frame_flags = VP8_EFLAG_NO_REF_LAST | |
+ VP8_EFLAG_NO_UPD_LAST | |
+ VP8_EFLAG_NO_UPD_ARF; |
+ } |
+ } |
} |
return frame_flags; |
} |
@@ -86,7 +105,9 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest, |
VP8_EFLAG_NO_UPD_ARF); |
// For temporal layer case. |
if (cfg_.ts_number_layers > 1) { |
- frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers); |
+ frame_flags_ = SetFrameFlags(video->frame(), |
+ cfg_.ts_number_layers, |
+ pattern_switch_); |
for (unsigned int i = 0; i < droppable_nframes_; ++i) { |
if (droppable_frames_[i] == video->frame()) { |
std::cout << "Encoding droppable frame: " |
@@ -168,11 +189,16 @@ class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest, |
return mismatch_nframes_; |
} |
+ void SetPatternSwitch(int frame_switch) { |
+ pattern_switch_ = frame_switch; |
+ } |
+ |
private: |
double psnr_; |
unsigned int nframes_; |
unsigned int error_nframes_; |
unsigned int droppable_nframes_; |
+ unsigned int pattern_switch_; |
double mismatch_psnr_; |
unsigned int mismatch_nframes_; |
unsigned int error_frames_[kMaxErrorFrames]; |
@@ -299,6 +325,7 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) { |
// Error resilient mode ON. |
cfg_.g_error_resilient = 1; |
cfg_.kf_mode = VPX_KF_DISABLED; |
+ SetPatternSwitch(0); |
// The odd frames are the enhancement layer for 2 layer pattern, so set |
// those frames as droppable. Drop the last 7 frames. |
@@ -316,6 +343,45 @@ TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) { |
Reset(); |
} |
+// Check for successful decoding and no encoder/decoder mismatch |
+// for a two layer temporal pattern, where at some point in the |
+// sequence, the LAST ref is not used anymore. |
+TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) { |
+ const vpx_rational timebase = { 33333333, 1000000000 }; |
+ cfg_.g_timebase = timebase; |
+ cfg_.rc_target_bitrate = 500; |
+ cfg_.g_lag_in_frames = 0; |
+ |
+ cfg_.rc_end_usage = VPX_CBR; |
+ // 2 Temporal layers, no spatial layers, CBR mode. |
+ cfg_.ss_number_layers = 1; |
+ cfg_.ts_number_layers = 2; |
+ cfg_.ts_rate_decimator[0] = 2; |
+ cfg_.ts_rate_decimator[1] = 1; |
+ cfg_.ts_periodicity = 2; |
+ cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100; |
+ cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate; |
+ |
+ init_flags_ = VPX_CODEC_USE_PSNR; |
+ |
+ libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288, |
+ timebase.den, timebase.num, 0, 100); |
+ |
+ // Error resilient mode ON. |
+ cfg_.g_error_resilient = 1; |
+ cfg_.kf_mode = VPX_KF_DISABLED; |
+ SetPatternSwitch(60); |
+ |
+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); |
+ // Test that no mismatches have been found |
+ std::cout << " Mismatch frames: " |
+ << GetMismatchFrames() << "\n"; |
+ EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0); |
+ |
+ // Reset previously set of error/droppable frames. |
+ Reset(); |
+} |
+ |
class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest, |
public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> { |
protected: |