]> granicus.if.org Git - libvpx/commitdiff
vp9-svc: Fix to first superframe when inter_layer is off.
authorMarco Paniconi <marpan@google.com>
Wed, 4 Apr 2018 23:24:39 +0000 (16:24 -0700)
committerMarco Paniconi <marpan@google.com>
Fri, 6 Apr 2018 04:25:55 +0000 (21:25 -0700)
When the application selects the setting INTER_LAYER_PRED_OFF
each spatial stream should be decodeable separately.
For this we need to force key frames on all spatial layers
on the first superframe.

In order to maintain the quality at the beginning of the stream
the active_worst for spatial layer of the second superframe is set
to the last_QP of the correspondng spatial layer of the first superframe.
Also make sure nonrd_keyframe is set for non-base spatial layers.

Change only affects SVC mode wit number_spatial_layers > 1 and
svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF.
And only affects first and second frame of sequence.

Change-Id: I8ee9a0873ab1d3a02515774571f719617771ad41

vp9/encoder/vp9_ratectrl.c
vp9/encoder/vp9_speed_features.c

index b5f1a5c5c718a50f2d1fd3e6c7a16ef9cd084244..d7f677d66421edf7a7d732d4dfd2add1000d6b0e 100644 (file)
@@ -702,6 +702,14 @@ static int calc_active_worst_quality_one_pass_cbr(const VP9_COMP *cpi) {
   int active_worst_quality;
   int ambient_qp;
   unsigned int num_frames_weight_key = 5 * cpi->svc.number_temporal_layers;
+  // For SVC: when inter layer prediction is off, on the second superframe
+  // (superframe = 1) use the QP from the previous superframe. This needed to
+  // maintain quality since we can't temporally predict from the very first
+  // superframe.
+  if (cpi->use_svc && cpi->svc.current_superframe == 1 &&
+      cpi->svc.number_spatial_layers > 1 &&
+      cpi->svc.disable_inter_layer_pred == INTER_LAYER_PRED_OFF)
+    return rc->last_q[KEY_FRAME];
   if (cm->frame_type == KEY_FRAME || rc->reset_high_source_sad)
     return rc->worst_quality;
   // For ambient_qp we use minimum of avg_frame_qindex[KEY_FRAME/INTER_FRAME]
@@ -1727,8 +1735,13 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
       LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id, cpi->svc.temporal_layer_id,
                        cpi->svc.number_temporal_layers);
   // Periodic key frames is based on the super-frame counter
-  // (svc.current_superframe), also only base spatial layer is key frame.
-  if ((cm->current_video_frame == 0) || (cpi->frame_flags & FRAMEFLAGS_KEY) ||
+  // (svc.current_superframe), also only base spatial layer is key frame unless
+  // svc.disable_inter_layer_pred = INTER_LAYER_PRED_OFF.
+  int first_frame_iskey =
+      (cpi->svc.disable_inter_layer_pred == INTER_LAYER_PRED_OFF)
+          ? (cpi->svc.current_superframe == 0)
+          : (cm->current_video_frame == 0);
+  if (first_frame_iskey || (cpi->frame_flags & FRAMEFLAGS_KEY) ||
       (cpi->oxcf.auto_key &&
        (cpi->svc.current_superframe % cpi->oxcf.key_freq == 0) &&
        cpi->svc.spatial_layer_id == 0)) {
@@ -1738,7 +1751,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
       cpi->svc.layer_context[layer].is_key_frame = 1;
       cpi->ref_frame_flags &= (~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
     } else if (is_one_pass_cbr_svc(cpi)) {
-      if (cm->current_video_frame > 0) vp9_svc_reset_key_frame(cpi);
+      if (!first_frame_iskey) vp9_svc_reset_key_frame(cpi);
       layer = LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id,
                                cpi->svc.temporal_layer_id,
                                cpi->svc.number_temporal_layers);
@@ -1750,6 +1763,18 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
     }
   } else {
     cm->frame_type = INTER_FRAME;
+    // Special case for first superframe when inter_layer prediction is off.
+    // Force key frame on base spatial layer for second superframe.
+    // TODO(marpan): This condition may be removed, depending on #spatial_layer
+    // and scaling factor, but keep it for now for simplicity.
+    if (cpi->svc.disable_inter_layer_pred == INTER_LAYER_PRED_OFF &&
+        cpi->svc.current_superframe == 1 && cpi->svc.spatial_layer_id == 0 &&
+        cpi->svc.number_spatial_layers > 1) {
+      vp9_svc_reset_key_frame(cpi);
+      cm->frame_type = KEY_FRAME;
+      cpi->svc.layer_context[layer].is_key_frame = 1;
+      target = calc_iframe_target_size_one_pass_cbr(cpi);
+    }
     if (is_two_pass_svc(cpi)) {
       LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
       if (cpi->svc.spatial_layer_id == 0) {
index 879cd2070a127878f70ffbaf04e9c449b7fd2663..746fa36e94689145c8ad0c3973a7b74a26b8d5fc 100644 (file)
@@ -531,6 +531,9 @@ static void set_rt_speed_feature_framesize_independent(
       sf->limit_newmv_early_exit = 1;
       if (!cpi->use_svc) sf->bias_golden = 1;
     }
+    // Keep nonrd_keyframe = 1 for non-base spatial layers to prevent large
+    // encoding time.
+    if (cpi->use_svc && cpi->svc.spatial_layer_id > 0) sf->nonrd_keyframe = 1;
   }
 
   if (speed >= 6) {