]> granicus.if.org Git - libvpx/commitdiff
vp9 svc: Reuse scaled_temp in two stage downscaling.
authorJackyChen <jackychen@google.com>
Tue, 12 Jul 2016 00:06:10 +0000 (17:06 -0700)
committerJackyChen <jackychen@google.com>
Tue, 12 Jul 2016 17:09:55 +0000 (10:09 -0700)
This change eliminates redundant computation in the two stage
downscaling, which saves ~1% encoding time in 3-layer svc encoding.

Change-Id: Ib4b218811b68499a740af1f9b7b5a5445e28d671

vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_svc_layercontext.c
vp9/encoder/vp9_svc_layercontext.h

index 9413a436f682121a4e34374eed5ca920eefa5ba7..25501f2543d5beed8d22d15ce637b7229e791a51 100644 (file)
@@ -753,6 +753,26 @@ static void alloc_util_frame_buffers(VP9_COMP *cpi) {
     vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate scaled source buffer");
 
+  // For 1 pass cbr: allocate scaled_frame that may be used as an intermediate
+  // buffer for a 2 stage down-sampling: two stages of 1:2 down-sampling for a
+  // target of 1/4x1/4.
+  if (is_one_pass_cbr_svc(cpi) && !cpi->svc.scaled_temp_is_alloc) {
+    cpi->svc.scaled_temp_is_alloc = 1;
+    if (vpx_realloc_frame_buffer(&cpi->svc.scaled_temp,
+                                 cm->width >> 1,
+                                 cm->height >> 1,
+                                 cm->subsampling_x,
+                                 cm->subsampling_y,
+#if CONFIG_VP9_HIGHBITDEPTH
+                                 cm->use_highbitdepth,
+#endif
+                                 VP9_ENC_BORDER_IN_PIXELS,
+                                 cm->byte_alignment,
+                                 NULL, NULL, NULL))
+      vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
+                         "Failed to allocate scaled_frame for svc ");
+  }
+
   if (vpx_realloc_frame_buffer(&cpi->scaled_last_source,
                                cm->width, cm->height,
                                cm->subsampling_x, cm->subsampling_y,
@@ -3262,10 +3282,22 @@ static void encode_without_recode_loop(VP9_COMP *cpi,
       cpi->un_scaled_source->y_height == cm->height << 2 &&
       cpi->svc.scaled_temp.y_width == cm->width << 1 &&
       cpi->svc.scaled_temp.y_height == cm->height << 1) {
+    // For svc, if it is a 1/4x1/4 downscaling, do a two-stage scaling to take
+    // advantage of the 1:2 optimized scaler. In the process, the 1/2x1/2
+    // result will be saved in scaled_temp and might be used later.
     cpi->Source = vp9_svc_twostage_scale(cm,
                                          cpi->un_scaled_source,
                                          &cpi->scaled_source,
                                          &cpi->svc.scaled_temp);
+    cpi->svc.scaled_one_half = 1;
+  } else if (is_one_pass_cbr_svc(cpi) &&
+             cpi->un_scaled_source->y_width == cm->width << 1 &&
+             cpi->un_scaled_source->y_height == cm->height << 1 &&
+             cpi->svc.scaled_one_half) {
+    // If the spatial layer is 1/2x1/2 and the scaling is already done in the
+    // two-stage scaling, use the result directly.
+    cpi->Source = &cpi->svc.scaled_temp;
+    cpi->svc.scaled_one_half = 0;
   } else {
     cpi->Source = vp9_scale_if_required(cm,
                                         cpi->un_scaled_source,
index 1814a32c9749efab73a191485d1b1a18f1b21f6a..824146fe7a53d3838e95e9100b6396b166e33f3d 100644 (file)
@@ -33,6 +33,8 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
   svc->rc_drop_superframe = 0;
   svc->force_zero_mode_spatial_ref = 0;
   svc->use_base_mv = 0;
+  svc->scaled_temp_is_alloc = 0;
+  svc->scaled_one_half = 0;
   svc->current_superframe = 0;
   for (i = 0; i < REF_FRAMES; ++i)
     svc->ref_frame_index[i] = -1;
@@ -43,26 +45,6 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
     cpi->svc.ext_alt_fb_idx[sl] = 2;
   }
 
-  // For 1 pass cbr: allocate scaled_frame that may be used as an intermediate
-  // buffer for a 2 stage down-sampling: two stages of 1:2 down-sampling for a
-  // target of 1/4x1/4.
-  if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR) {
-    if (vpx_realloc_frame_buffer(&cpi->svc.scaled_temp,
-                                 cpi->common.width >> 1,
-                                 cpi->common.height >> 1,
-                                 cpi->common.subsampling_x,
-                                 cpi->common.subsampling_y,
-#if CONFIG_VP9_HIGHBITDEPTH
-                                 cpi->common.use_highbitdepth,
-#endif
-                                 VP9_ENC_BORDER_IN_PIXELS,
-                                 cpi->common.byte_alignment,
-                                 NULL, NULL, NULL))
-      vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
-                         "Failed to allocate scaled_frame for svc ");
-  }
-
-
   if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
     if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img,
                                  SMALL_FRAME_WIDTH, SMALL_FRAME_HEIGHT,
index 9f386fb081fd5c7794a9e3c88e6495269a61c992..39094fe02313f0ed2d2b61e1a1eaf586bed7af95 100644 (file)
@@ -72,6 +72,8 @@ typedef struct {
   YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
   // Temp buffer used for 2-stage down-sampling, for real-time mode.
   YV12_BUFFER_CONFIG scaled_temp;
+  int scaled_one_half;
+  int scaled_temp_is_alloc;
 
   // Layer context used for rate control in one pass temporal CBR mode or
   // two pass spatial mode.