From f362bf981c4648b426aa2a0735d4fb6bda4136c0 Mon Sep 17 00:00:00 2001 From: Marco Paniconi Date: Mon, 7 May 2018 22:54:48 -0700 Subject: [PATCH] vp9-svc: Fix when whole superframe is dropped. When the whole superframe is dropped (due to rate control), don't increment the temporal layer counter. This is a temporary fix to prevent an issue where temporal prediction pattern is possibly broken. Updated svc_datarate tests to handle this case. Change-Id: Icac44fdc9d0f08a957776c937584db4b2c7927c7 --- test/encode_test_driver.cc | 2 +- test/encode_test_driver.h | 2 +- test/svc_datarate_test.cc | 7 +++++-- vp9/encoder/vp9_encoder.c | 12 +++++++++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc index 63e972a00..b2cbc3f05 100644 --- a/test/encode_test_driver.cc +++ b/test/encode_test_driver.cc @@ -201,7 +201,7 @@ void EncoderTest::RunLoop(VideoSource *video) { PreEncodeFrameHook(video, encoder.get()); encoder->EncodeFrame(video, frame_flags_); - PostEncodeFrameHook(); + PostEncodeFrameHook(encoder.get()); CxDataIterator iter = encoder->GetCxData(); diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h index a301e21cc..03624d110 100644 --- a/test/encode_test_driver.h +++ b/test/encode_test_driver.h @@ -226,7 +226,7 @@ class EncoderTest { virtual void PreEncodeFrameHook(VideoSource * /*video*/, Encoder * /*encoder*/) {} - virtual void PostEncodeFrameHook() {} + virtual void PostEncodeFrameHook(Encoder * /*encoder*/) {} // Hook to be called on every compressed data packet. virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {} diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc index be3a1969c..608f27ebf 100644 --- a/test/svc_datarate_test.cc +++ b/test/svc_datarate_test.cc @@ -297,7 +297,10 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest { duration_ = 0; } - virtual void PostEncodeFrameHook() { + virtual void PostEncodeFrameHook(::libvpx_test::Encoder *encoder) { + vpx_svc_layer_id_t layer_id; + encoder->Control(VP9E_GET_SVC_LAYER_ID, &layer_id); + temporal_layer_id_ = layer_id.temporal_layer_id; for (int sl = 0; sl < number_spatial_layers_; ++sl) { for (int tl = temporal_layer_id_; tl < number_temporal_layers_; ++tl) { const int layer = sl * number_temporal_layers_ + tl; @@ -848,7 +851,7 @@ TEST_P(DatarateOnePassCbrSvcFrameDropMultiBR, OnePassCbrSvc2SL3TL4Threads) { layer_target_avg_bandwidth_, bits_in_buffer_model_); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); CheckLayerRateTargeting(&cfg_, number_spatial_layers_, - number_temporal_layers_, file_datarate_, 0.75, 1.2); + number_temporal_layers_, file_datarate_, 0.75, 1.45); #if CONFIG_VP9_DECODER // The non-reference frames are expected to be mismatched frames as the // encoder will avoid loopfilter on these frames. diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 3384de7ea..13f01a3ab 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -4560,8 +4560,18 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, if (cpi->use_svc) { cpi->svc.last_layer_dropped[cpi->svc.spatial_layer_id] = 1; cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id] = 1; - vp9_inc_frame_in_layer(cpi); cpi->svc.skip_enhancement_layer = 1; + if (cpi->svc.framedrop_mode != CONSTRAINED_LAYER_DROP || + cpi->svc.drop_spatial_layer[0] == 0) { + // For the case of CONSTRAINED_LAYER_DROP where the base is dropped + // (drop_spatial_layer[0] == 1), which means full superframe dropped, + // we don't increment the svc frame counters. In particular temporal + // layer counter (which is incremented in vp9_inc_frame_in_layer()) + // won't be incremented, so on a dropped frame we try the same + // temporal_layer_id on next incoming frame. This is to avoid an + // issue with temporal alignement with full superframe dropping. + vp9_inc_frame_in_layer(cpi); + } if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) { int i; int all_layers_drop = 1; -- 2.40.0