shithub: libvpx

Download patch

ref: ce11afb0e02a81a1e0e38ea9f3c3e13920439b1f
parent: 03fa7018737180d6ee7c495543410c2b2f9f6d09
author: Marco Paniconi <marpan@google.com>
date: Mon Apr 16 12:15:05 EDT 2018

vp9: Changes for scene detection overshoot and SVC.

Refactor the scene detection for 1 pass cbr to allow the
scene detection to be checked once per superframe (on the base layer),
using the full resolution sources.

If scene change is detected: check for re-encoding due to
large overshoot for all spatial layers withing the superframe.

Add speed feature to control the re-encode step.
Keep the re-encode step on for now.

Small change in nonrd_pickmode to remove the possible skip of golden
reference for SVC, when the high_source_sad is set for the superframe.

Change only affects SVC encoding with screen-content mode enabled.

Change-Id: If4cfb52cb0dd0f0fce1c4214fa8b413f8f803d56

--- a/examples/vp9_spatial_svc_encoder.c
+++ b/examples/vp9_spatial_svc_encoder.c
@@ -730,6 +730,8 @@
 
   vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, 0);
 
+  vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
+
   // Encode frames
   while (!end_of_stream) {
     vpx_codec_iter_t iter = NULL;
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -3683,12 +3683,15 @@
   // For other cases (e.g., CBR mode) use it for 5 <= speed < 8 for now
   // (need to check encoding time cost for doing this for speed 8).
   cpi->rc.high_source_sad = 0;
-  if (cpi->compute_source_sad_onepass && cm->show_frame &&
+  if (cm->show_frame &&
       (cpi->oxcf.rc_mode == VPX_VBR ||
        cpi->oxcf.content == VP9E_CONTENT_SCREEN ||
        (cpi->oxcf.speed >= 5 && cpi->oxcf.speed < 8 && !cpi->use_svc)))
     vp9_scene_detection_onepass(cpi);
 
+  if (cpi->svc.spatial_layer_id == 0)
+    cpi->svc.high_source_sad_superframe = cpi->rc.high_source_sad;
+
   // For 1 pass CBR SVC, only ZEROMV is allowed for spatial reference frame
   // when svc->force_zero_mode_spatial_ref = 1. Under those conditions we can
   // avoid this frame-level upsampling (for non intra_only frames).
@@ -3774,10 +3777,10 @@
 
   // Check if we should drop this frame because of high overshoot.
   // Only for frames where high temporal-source SAD is detected.
-  if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR &&
-      cpi->resize_state == ORIG && cm->frame_type != KEY_FRAME &&
-      cpi->oxcf.content == VP9E_CONTENT_SCREEN &&
-      cpi->rc.high_source_sad == 1) {
+  // For SVC: all spatial layers are checked for re-encoding.
+  if (cpi->sf.re_encode_overshoot_rt &&
+      (cpi->rc.high_source_sad ||
+       (cpi->use_svc && cpi->svc.high_source_sad_superframe))) {
     int frame_size = 0;
     // Get an estimate of the encoded frame size.
     save_coding_context(cpi);
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -1503,10 +1503,12 @@
   int svc_mv_col = 0;
   int svc_mv_row = 0;
   unsigned int thresh_svc_skip_golden = 500;
+  if (cpi->svc.spatial_layer_id > 0 && cpi->svc.high_source_sad_superframe)
+    thresh_svc_skip_golden = 0;
   // Lower the skip threshold if lower spatial layer is better quality relative
   // to current layer.
-  if (cpi->svc.spatial_layer_id > 0 && cm->base_qindex > 150 &&
-      cm->base_qindex > cpi->svc.lower_layer_qindex + 15)
+  else if (cpi->svc.spatial_layer_id > 0 && cm->base_qindex > 150 &&
+           cm->base_qindex > cpi->svc.lower_layer_qindex + 15)
     thresh_svc_skip_golden = 100;
   // Increase skip threshold if lower spatial layer is lower quality relative
   // to current layer.
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -2284,18 +2284,34 @@
 void vp9_scene_detection_onepass(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
   RATE_CONTROL *const rc = &cpi->rc;
+  YV12_BUFFER_CONFIG const *unscaled_src = cpi->un_scaled_source;
+  YV12_BUFFER_CONFIG const *unscaled_last_src = cpi->unscaled_last_source;
+  uint8_t *src_y;
+  int src_ystride;
+  int src_width;
+  int src_height;
+  uint8_t *last_src_y;
+  int last_src_ystride;
+  int last_src_width;
+  int last_src_height;
+  if (cpi->un_scaled_source == NULL || cpi->unscaled_last_source == NULL ||
+      (cpi->use_svc && cpi->svc.current_superframe == 0))
+    return;
+  src_y = unscaled_src->y_buffer;
+  src_ystride = unscaled_src->y_stride;
+  src_width = unscaled_src->y_width;
+  src_height = unscaled_src->y_height;
+  last_src_y = unscaled_last_src->y_buffer;
+  last_src_ystride = unscaled_last_src->y_stride;
+  last_src_width = unscaled_last_src->y_width;
+  last_src_height = unscaled_last_src->y_height;
 #if CONFIG_VP9_HIGHBITDEPTH
   if (cm->use_highbitdepth) return;
 #endif
   rc->high_source_sad = 0;
-  if (cpi->Last_Source != NULL &&
-      cpi->Last_Source->y_width == cpi->Source->y_width &&
-      cpi->Last_Source->y_height == cpi->Source->y_height) {
+  if (cpi->svc.spatial_layer_id == 0 && src_width == last_src_width &&
+      src_height == last_src_height) {
     YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = { NULL };
-    uint8_t *src_y = cpi->Source->y_buffer;
-    int src_ystride = cpi->Source->y_stride;
-    uint8_t *last_src_y = cpi->Last_Source->y_buffer;
-    int last_src_ystride = cpi->Last_Source->y_stride;
     int start_frame = 0;
     int frames_to_buffer = 1;
     int frame = 0;
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -374,6 +374,7 @@
   sf->use_compound_nonrd_pickmode = 0;
   sf->nonrd_keyframe = 0;
   sf->svc_use_lowres_part = 0;
+  sf->re_encode_overshoot_rt = 0;
 
   if (speed >= 1) {
     sf->allow_txfm_domain_distortion = 1;
@@ -534,6 +535,10 @@
     // Keep nonrd_keyframe = 1 for non-base spatial layers to prevent
     // increase in encoding time.
     if (cpi->use_svc && cpi->svc.spatial_layer_id > 0) sf->nonrd_keyframe = 1;
+    if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR &&
+        cm->frame_type != KEY_FRAME && cpi->resize_state == ORIG &&
+        cpi->oxcf.content == VP9E_CONTENT_SCREEN)
+      sf->re_encode_overshoot_rt = 1;
   }
 
   if (speed >= 6) {
--- a/vp9/encoder/vp9_speed_features.h
+++ b/vp9/encoder/vp9_speed_features.h
@@ -508,6 +508,10 @@
 
   // For SVC: enables use of partition from lower spatial resolution.
   int svc_use_lowres_part;
+
+  // Enable re-encoding on scene change with potential high overshoot,
+  // for real-time encoding flow.
+  int re_encode_overshoot_rt;
 } SPEED_FEATURES;
 
 struct VP9_COMP;
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -712,6 +712,8 @@
     cpi->svc.non_reference_frame = 1;
   }
 
+  if (cpi->svc.spatial_layer_id == 0) cpi->svc.high_source_sad_superframe = 0;
+
   if (vp9_set_size_literal(cpi, width, height) != 0)
     return VPX_CODEC_INVALID_PARAM;
 
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -118,6 +118,11 @@
   SVC_LAYER_DROP_MODE framedrop_mode;
 
   INTER_LAYER_PRED disable_inter_layer_pred;
+
+  // Flag to indicate scene change at current superframe, scene detection is
+  // currently checked for each superframe prior to encoding, on the full
+  // resolution source.
+  int high_source_sad_superframe;
 } SVC;
 
 struct VP9_COMP;