From 884c4cae739f36e8778a8e6c0a33228d2121d405 Mon Sep 17 00:00:00 2001 From: Jerome Jiang Date: Thu, 28 Jun 2018 18:43:37 -0700 Subject: [PATCH] vp9: copy source on sync frame in denoiser. Refresh all denoiser buffers on sync frame. Add sync frame test with denoiser enabled. Change-Id: I562a5ef5614b92a97565e6181a79eda51d9aeb99 --- test/svc_end_to_end_test.cc | 38 +++++++++++++++++++++++++++++++++++-- vp9/encoder/vp9_denoiser.c | 4 ++-- vp9/encoder/vp9_denoiser.h | 2 +- vp9/encoder/vp9_encoder.c | 23 +++++++++++----------- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/test/svc_end_to_end_test.cc b/test/svc_end_to_end_test.cc index d4c1a5cc2..5f5c7755f 100644 --- a/test/svc_end_to_end_test.cc +++ b/test/svc_end_to_end_test.cc @@ -28,7 +28,8 @@ class SyncFrameOnePassCbrSvc : public ::svc_test::OnePassCbrSvc, : OnePassCbrSvc(GET_PARAM(0)), current_video_frame_(0), frame_to_start_decode_(0), frame_to_sync_(0), mismatch_nframes_(0), num_nonref_frames_(0), inter_layer_pred_mode_(GET_PARAM(1)), - decode_to_layer_before_sync_(-1), decode_to_layer_after_sync_(-1) { + decode_to_layer_before_sync_(-1), decode_to_layer_after_sync_(-1), + denoiser_on_(0) { SetMode(::libvpx_test::kRealTime); memset(&svc_layer_sync_, 0, sizeof(svc_layer_sync_)); } @@ -75,8 +76,10 @@ class SyncFrameOnePassCbrSvc : public ::svc_test::OnePassCbrSvc, ::libvpx_test::Encoder *encoder) { current_video_frame_ = video->frame(); PreEncodeFrameHookSetup(video, encoder); - if (video->frame() == 0) + if (video->frame() == 0) { encoder->Control(VP9E_SET_SVC_INTER_LAYER_PRED, inter_layer_pred_mode_); + encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_); + } if (video->frame() == frame_to_sync_) { encoder->Control(VP9E_SET_SVC_SPATIAL_LAYER_SYNC, &svc_layer_sync_); } @@ -123,6 +126,7 @@ class SyncFrameOnePassCbrSvc : public ::svc_test::OnePassCbrSvc, int inter_layer_pred_mode_; int decode_to_layer_before_sync_; int decode_to_layer_after_sync_; + int denoiser_on_; vpx_svc_spatial_layer_sync_t svc_layer_sync_; private: @@ -254,6 +258,36 @@ TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc3SL3TLSyncFrameVGAHD) { #endif } +#if CONFIG_VP9_TEMPORAL_DENOISING +// Test for sync layer for 1 pass CBR SVC: 2 spatial layers and +// 3 temporal layers. Decoding QVGA before sync frame and decode up to +// VGA on and after sync. +TEST_P(SyncFrameOnePassCbrSvc, OnePassCbrSvc2SL3TLSyncFrameVGADenoise) { + Set2SpatialLayerConfig(); + frame_to_start_decode_ = 0; + frame_to_sync_ = 100; + decode_to_layer_before_sync_ = 0; + decode_to_layer_after_sync_ = 1; + + denoiser_on_ = 1; + // Set up svc layer sync structure. + svc_layer_sync_.base_layer_intra_only = 0; + svc_layer_sync_.spatial_layer_sync[0] = 0; + svc_layer_sync_.spatial_layer_sync[1] = 1; + + ::libvpx_test::I420VideoSource video("niklas_640_480_30.yuv", 640, 480, 30, 1, + 0, 400); + cfg_.rc_target_bitrate = 400; + AssignLayerBitrates(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); +#if CONFIG_VP9_DECODER + // The non-reference frames are expected to be mismatched frames as the + // encoder will avoid loopfilter on these frames. + EXPECT_EQ(num_nonref_frames_, GetMismatchFrames()); +#endif +} +#endif + VP9_INSTANTIATE_TEST_CASE(SyncFrameOnePassCbrSvc, ::testing::Range(0, 3)); } // namespace diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c index 011ab889f..6abb082cd 100644 --- a/vp9/encoder/vp9_denoiser.c +++ b/vp9/encoder/vp9_denoiser.c @@ -452,13 +452,13 @@ void vp9_denoiser_update_frame_info( VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type, int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame, int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, int resized, - int svc_base_is_key, int second_spatial_layer) { + int svc_refresh_denoiser_buffers, int second_spatial_layer) { const int shift = second_spatial_layer ? denoiser->num_ref_frames : 0; // Copy source into denoised reference buffers on KEY_FRAME or // if the just encoded frame was resized. For SVC, copy source if the base // spatial layer was key frame. if (frame_type == KEY_FRAME || resized != 0 || denoiser->reset || - svc_base_is_key) { + svc_refresh_denoiser_buffers) { int i; // Start at 1 so as not to overwrite the INTRA_FRAME for (i = 1; i < denoiser->num_ref_frames; ++i) { diff --git a/vp9/encoder/vp9_denoiser.h b/vp9/encoder/vp9_denoiser.h index 8f3724fa8..d25fe7edc 100644 --- a/vp9/encoder/vp9_denoiser.h +++ b/vp9/encoder/vp9_denoiser.h @@ -73,7 +73,7 @@ void vp9_denoiser_update_frame_info( VP9_DENOISER *denoiser, YV12_BUFFER_CONFIG src, FRAME_TYPE frame_type, int refresh_alt_ref_frame, int refresh_golden_frame, int refresh_last_frame, int alt_fb_idx, int gld_fb_idx, int lst_fb_idx, int resized, - int svc_base_is_key, int second_spatial_layer); + int svc_refresh_denoiser_buffers, int second_spatial_layer); void vp9_denoiser_denoise(struct VP9_COMP *cpi, MACROBLOCK *mb, int mi_row, int mi_col, BLOCK_SIZE bs, PICK_MODE_CONTEXT *ctx, diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 74e0d85a5..b69e45276 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3021,28 +3021,28 @@ void update_ref_frames(VP9_COMP *cpi) { void vp9_update_reference_frames(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; BufferPool *const pool = cm->buffer_pool; - + SVC *const svc = &cpi->svc; update_ref_frames(cpi); #if CONFIG_VP9_TEMPORAL_DENOISING if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) && cpi->denoiser.denoising_level > kDenLowLow) { - int svc_base_is_key = 0; + int svc_refresh_denoiser_buffers = 0; int denoise_svc_second_layer = 0; if (cpi->use_svc) { int realloc_fail = 0; const int svc_buf_shift = - cpi->svc.number_spatial_layers - cpi->svc.spatial_layer_id == 2 + svc->number_spatial_layers - svc->spatial_layer_id == 2 ? cpi->denoiser.num_ref_frames : 0; - int layer = LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id, - cpi->svc.temporal_layer_id, - cpi->svc.number_temporal_layers); - LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer]; - svc_base_is_key = lc->is_key_frame; + int layer = + LAYER_IDS_TO_IDX(svc->spatial_layer_id, svc->temporal_layer_id, + svc->number_temporal_layers); + LAYER_CONTEXT *const lc = &svc->layer_context[layer]; + svc_refresh_denoiser_buffers = + lc->is_key_frame || svc->spatial_layer_sync[svc->spatial_layer_id]; denoise_svc_second_layer = - cpi->svc.number_spatial_layers - cpi->svc.spatial_layer_id == 2 ? 1 - : 0; + svc->number_spatial_layers - svc->spatial_layer_id == 2 ? 1 : 0; // Check if we need to allocate extra buffers in the denoiser // for // refreshed frames. @@ -3058,14 +3058,13 @@ void vp9_update_reference_frames(VP9_COMP *cpi) { &cpi->denoiser, *cpi->Source, cpi->common.frame_type, cpi->refresh_alt_ref_frame, cpi->refresh_golden_frame, cpi->refresh_last_frame, cpi->alt_fb_idx, cpi->gld_fb_idx, - cpi->lst_fb_idx, cpi->resize_pending, svc_base_is_key, + cpi->lst_fb_idx, cpi->resize_pending, svc_refresh_denoiser_buffers, denoise_svc_second_layer); } #endif if (is_one_pass_cbr_svc(cpi)) { // Keep track of frame index for each reference frame. - SVC *const svc = &cpi->svc; if (cm->frame_type == KEY_FRAME) { int i; // On key frame update all reference frame slots. -- 2.40.0