shithub: libvpx

Download patch

ref: 884c4cae739f36e8778a8e6c0a33228d2121d405
parent: eca56ea29af4429b2068141117ec96b1f567d7c6
author: Jerome Jiang <jianj@google.com>
date: Thu Jun 28 14:43:37 EDT 2018

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

--- a/test/svc_end_to_end_test.cc
+++ b/test/svc_end_to_end_test.cc
@@ -28,7 +28,8 @@
       : 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 @@
                                   ::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 @@
   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:
@@ -253,6 +257,36 @@
   EXPECT_EQ(num_nonref_frames_, GetMismatchFrames());
 #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));
 
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -452,13 +452,13 @@
     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) {
--- a/vp9/encoder/vp9_denoiser.h
+++ b/vp9/encoder/vp9_denoiser.h
@@ -73,7 +73,7 @@
     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,
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -3021,28 +3021,28 @@
 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,7 +3058,7 @@
         &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
@@ -3065,7 +3065,6 @@
 
   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.