Allintra: Skip the application of post-processing filters This CL generalizes the logic to skip the application of post-processing filters on the reconstructed frame. The application of a post-processing filter is disabled if subsequent post-processing stages are not dependent on the filtered output from the current stage or subsequent post-processing stages are disabled. This is a bit-exact change. Change-Id: Ia1a97042cf09d26d6dc99ae4660b92af68a323d5
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index c87fe9e..39a6999 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -2215,7 +2215,8 @@ */ static void cdef_restoration_frame(AV1_COMP *cpi, AV1_COMMON *cm, MACROBLOCKD *xd, int use_restoration, - int use_cdef) { + int use_cdef, + unsigned int skip_apply_postproc_filters) { #if !CONFIG_REALTIME_ONLY if (use_restoration) av1_loop_restoration_save_boundary_lines(&cm->cur_frame->buf, cm, 0); @@ -2241,7 +2242,8 @@ cpi->ppi->rtc_ref.non_reference_frame); // Apply the filter - if (!cpi->ppi->rtc_ref.non_reference_frame) { + if (!cpi->ppi->rtc_ref.non_reference_frame && + (skip_apply_postproc_filters & SKIP_APPLY_CDEF) == 0) { if (num_workers > 1) { // Extension of frame borders is multi-threaded along with cdef. const int do_extend_border = @@ -2259,7 +2261,12 @@ #endif } - av1_superres_post_encode(cpi); + const int use_superres = av1_superres_scaled(cm); + if (use_superres) { + if ((skip_apply_postproc_filters & SKIP_APPLY_SUPERRES) == 0) { + av1_superres_post_encode(cpi); + } + } #if !CONFIG_REALTIME_ONLY #if CONFIG_COLLECT_COMPONENT_TIMING @@ -2270,9 +2277,10 @@ const int num_workers = mt_info->num_mod_workers[MOD_LR]; av1_loop_restoration_save_boundary_lines(&cm->cur_frame->buf, cm, 1); av1_pick_filter_restoration(cpi->source, cpi); - if (cm->rst_info[0].frame_restoration_type != RESTORE_NONE || - cm->rst_info[1].frame_restoration_type != RESTORE_NONE || - cm->rst_info[2].frame_restoration_type != RESTORE_NONE) { + if ((skip_apply_postproc_filters & SKIP_APPLY_RESTORATION) == 0 && + (cm->rst_info[0].frame_restoration_type != RESTORE_NONE || + cm->rst_info[1].frame_restoration_type != RESTORE_NONE || + cm->rst_info[2].frame_restoration_type != RESTORE_NONE)) { if (num_workers > 1) { // Extension of frame borders is multi-threaded along with loop // restoration filter. @@ -2324,17 +2332,22 @@ const int use_loopfilter = is_loopfilter_used(cm) && !cpi->mt_info.pipeline_lpf_mt_with_enc; const int use_cdef = is_cdef_used(cm); + const int use_superres = av1_superres_scaled(cm); const int use_restoration = is_restoration_used(cm); + const unsigned int skip_apply_postproc_filters = + derive_skip_apply_postproc_filters(cpi, use_loopfilter, use_cdef, + use_superres, use_restoration); + #if CONFIG_COLLECT_COMPONENT_TIMING start_timing(cpi, loop_filter_time); #endif if (use_loopfilter) { av1_pick_filter_level(cpi->source, cpi, cpi->sf.lpf_sf.lpf_pick); - if (should_skip_postproc_filtering(cpi, use_cdef, use_restoration)) return; struct loopfilter *lf = &cm->lf; if ((lf->filter_level[0] || lf->filter_level[1]) && - !cpi->ppi->rtc_ref.non_reference_frame) { + !cpi->ppi->rtc_ref.non_reference_frame && + (skip_apply_postproc_filters & SKIP_APPLY_LOOPFILTER) == 0) { // lpf_opt_level = 1 : Enables dual/quad loop-filtering. // lpf_opt_level is set to 1 if transform size search depth in inter // blocks is limited to one as quad loop filtering assumes that all the @@ -2354,7 +2367,8 @@ end_timing(cpi, loop_filter_time); #endif - cdef_restoration_frame(cpi, cm, xd, use_restoration, use_cdef); + cdef_restoration_frame(cpi, cm, xd, use_restoration, use_cdef, + skip_apply_postproc_filters); } static void update_motion_stat(AV1_COMP *const cpi) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 75d45d8..83e634e 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -232,6 +232,17 @@ 3, /*!< Disable loopfilter on frames with low motion. */ } LOOPFILTER_CONTROL; +/*!\enum SKIP_APPLY_POSTPROC_FILTER + * \brief This enum controls the application of post-processing filters on a + * reconstructed frame. + */ +typedef enum { + SKIP_APPLY_RESTORATION = 1 << 0, + SKIP_APPLY_SUPERRES = 1 << 1, + SKIP_APPLY_CDEF = 1 << 2, + SKIP_APPLY_LOOPFILTER = 1 << 3, +} SKIP_APPLY_POSTPROC_FILTER; + /*! * \brief Encoder config related to resize. */ @@ -4121,24 +4132,34 @@ // filters on the reconstructed frame can be skipped at the encoder side. // However the computation of different filter parameters that are signaled in // the bitstream is still required. -static INLINE bool should_skip_postproc_filtering(AV1_COMP *cpi, int use_cdef, - int use_restoration) { +static INLINE unsigned int derive_skip_apply_postproc_filters( + const AV1_COMP *cpi, int use_loopfilter, int use_cdef, int use_superres, + int use_restoration) { if (!cpi->oxcf.algo_cfg.skip_postproc_filtering || cpi->ppi->b_calculate_psnr) - return false; + return 0; assert(cpi->oxcf.mode == ALLINTRA); - const AV1_COMMON *const cm = &cpi->common; - // The post-processing filters are applied one after the other. In case of + // The post-processing filters are applied one after the other in the + // following order: deblocking->cdef->superres->restoration. In case of // ALLINTRA encoding, the reconstructed frame is not used as a reference // frame. Hence, the application of these filters can be skipped when // 1. filter parameters of the subsequent stages are not dependent on the // filtered output of the current stage or // 2. subsequent filtering stages are disabled - // In case of ALLINTRA encode, CDEF is disabled by default and loop - // restoration is disabled for speed >= 5. Hence, the application of - // deblocking filters is skipped currently if there are no further filtering - // stages. - return (!use_cdef && !av1_superres_scaled(cm) && !use_restoration); + if (use_restoration) return SKIP_APPLY_RESTORATION; + if (use_superres) return SKIP_APPLY_SUPERRES; + if (use_cdef) { + // CDEF parameter selection is not dependent on the deblocked frame if + // cdef_pick_method is CDEF_PICK_FROM_Q. Hence the application of deblocking + // filters and cdef filters can be skipped in this case. + return (cpi->sf.lpf_sf.cdef_pick_method == CDEF_PICK_FROM_Q && + use_loopfilter) + ? (SKIP_APPLY_LOOPFILTER | SKIP_APPLY_CDEF) + : SKIP_APPLY_CDEF; + } + if (use_loopfilter) return SKIP_APPLY_LOOPFILTER; + + return 0; // All post-processing stages disabled. } static INLINE void set_postproc_filter_default_params(AV1_COMMON *cm) {
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c index 7aadc1d..55bb232 100644 --- a/av1/encoder/ethread.c +++ b/av1/encoder/ethread.c
@@ -1603,22 +1603,26 @@ // decides the filter level. Loop-filtering is disabled in case // of non-reference frames and for frames with intra block copy tool enabled. AV1_COMMON *cm = &cpi->common; + const int use_loopfilter = is_loopfilter_used(cm); + const int use_superres = av1_superres_scaled(cm); const int use_cdef = is_cdef_used(cm); const int use_restoration = is_restoration_used(cm); - const int skip_postproc_filtering = - should_skip_postproc_filtering(cpi, use_cdef, use_restoration); + + const unsigned int skip_apply_postproc_filters = + derive_skip_apply_postproc_filters(cpi, use_loopfilter, use_cdef, + use_superres, use_restoration); cpi->mt_info.pipeline_lpf_mt_with_enc = (cpi->oxcf.mode == REALTIME) && (cpi->oxcf.speed >= 5) && (cpi->sf.lpf_sf.lpf_pick == LPF_PICK_FROM_Q) && (cpi->oxcf.algo_cfg.loopfilter_control != LOOPFILTER_SELECTIVELY) && !cpi->ppi->rtc_ref.non_reference_frame && !cm->features.allow_intrabc && - !skip_postproc_filtering; + ((skip_apply_postproc_filters & SKIP_APPLY_LOOPFILTER) == 0); if (!cpi->mt_info.pipeline_lpf_mt_with_enc) return; set_postproc_filter_default_params(cm); - if (!is_loopfilter_used(cm)) return; + if (!use_loopfilter) return; const LPF_PICK_METHOD method = cpi->sf.lpf_sf.lpf_pick; assert(method == LPF_PICK_FROM_Q);
diff --git a/av1/encoder/superres_scale.c b/av1/encoder/superres_scale.c index 283faab..f439e70 100644 --- a/av1/encoder/superres_scale.c +++ b/av1/encoder/superres_scale.c
@@ -399,8 +399,6 @@ void av1_superres_post_encode(AV1_COMP *cpi) { AV1_COMMON *cm = &cpi->common; - if (!av1_superres_scaled(cm)) return; - assert(cpi->oxcf.superres_cfg.enable_superres); assert(!is_lossless_requested(&cpi->oxcf.rc_cfg)); assert(!cm->features.all_lossless);