rtc: Fix prediction on keyframes for spatial layers On superframes whose base is key: fix the reference predicton structure so that the SL layer (for SL > 0) only does the inter-layer prediction from the SL-1 layer. This requires fixes to the sample encoder and in the nonrd_pickmode. In the current code SL2 was either predicting only from SL0 (for ksvc), or it was predicting from both SL0 & SL1 (in non-ksvc mode), which was not the intended behavior. So this fix improves the key frame quality for ksvc and reduces the encode_time for non-ksvc. Change-Id: Ifde750c741b53b42e4f27d493945036fb7e0e334
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c index 8d96b86..2b3adcb 100644 --- a/av1/encoder/nonrd_pickmode.c +++ b/av1/encoder/nonrd_pickmode.c
@@ -1798,8 +1798,9 @@ int use_alt_ref_frame = cpi->ppi->use_svc || cpi->sf.rt_sf.use_nonrd_altref_frame; int use_golden_ref_frame = 1; + int use_last_ref_frame = 1; - use_ref_frame[LAST_FRAME] = 1; // we never skip LAST + use_ref_frame[LAST_FRAME] = 1; if (cpi->rc.frames_since_golden == 0 && gf_temporal_ref) { use_golden_ref_frame = 0; @@ -1836,8 +1837,14 @@ use_golden_ref_frame = cpi->ref_frame_flags & AOM_GOLD_FLAG ? use_golden_ref_frame : 0; + if (cpi->ppi->use_svc) + use_last_ref_frame = + cpi->ref_frame_flags & AOM_LAST_FLAG ? use_last_ref_frame : 0; + use_ref_frame[ALTREF_FRAME] = use_alt_ref_frame; use_ref_frame[GOLDEN_FRAME] = use_golden_ref_frame; + use_ref_frame[LAST_FRAME] = use_last_ref_frame; + assert(use_last_ref_frame || use_golden_ref_frame || use_alt_ref_frame); } /*!\brief Estimates best intra mode for inter mode search
diff --git a/examples/svc_encoder_rtc.c b/examples/svc_encoder_rtc.c index ac1238d..d745b79 100644 --- a/examples/svc_encoder_rtc.c +++ b/examples/svc_encoder_rtc.c
@@ -579,11 +579,9 @@ for (i = 0; i < REF_FRAMES; i++) ref_frame_config->refresh[i] = 0; if (ksvc_mode) { - // Same pattern as case 9. + // Same pattern as case 9, but the reference strucutre will be constrained + // below. layering_mode = 9; - if (!is_key_frame) - // No inter-layer prediction on inter-frames. - ref_frame_config->reference[SVC_LAST_FRAME] = 1; } switch (layering_mode) { case 0: @@ -852,10 +850,6 @@ ref_frame_config->ref_idx[SVC_GOLDEN_FRAME] = 3; } } - if (layer_id->spatial_layer_id > 0 && !ksvc_mode) { - // Reference GOLDEN. - ref_frame_config->reference[SVC_GOLDEN_FRAME] = 1; - } break; case 8: // 3 spatial and 3 temporal layer. @@ -985,9 +979,20 @@ ref_frame_config->ref_idx[SVC_GOLDEN_FRAME] = 4; } } - if (layer_id->spatial_layer_id > 0 && !ksvc_mode) - // Reference GOLDEN. + if (layer_id->spatial_layer_id > 0) { + // Always reference GOLDEN (inter-layer prediction). ref_frame_config->reference[SVC_GOLDEN_FRAME] = 1; + if (ksvc_mode) { + // KSVC: only keep the inter-layer reference (GOLDEN) for + // superframes whose base is key. + if (!is_key_frame) ref_frame_config->reference[SVC_GOLDEN_FRAME] = 0; + } + if (is_key_frame && layer_id->spatial_layer_id > 1) { + // On superframes whose base is key: remove LAST to avoid prediction + // off layer two levels below. + ref_frame_config->reference[SVC_LAST_FRAME] = 0; + } + } // For 3 spatial layer case 8 (where there is free buffer slot): // allow for top spatial layer to use additional temporal reference. // Additional reference is only updated on base temporal layer, every @@ -1305,7 +1310,8 @@ aom_codec_iter_t iter = NULL; const aom_codec_cx_pkt_t *pkt; int layer = 0; - int is_key_frame = (frame_cnt % cfg.kf_max_dist) == 0 && slx == 0; + // Flag for superframe whose base is key. + int is_key_frame = (frame_cnt % cfg.kf_max_dist) == 0; // For flexible mode: if (app_input.layering_mode >= 0) { // Set the reference/update flags, layer_id, and reference_map