diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index dcd0be686609e51ff0e653229f34af8e04f7238d..e64d402f24961dffedbd9991407b8d3d9788fb73 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -2309,7 +2309,8 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, sf->always_this_block_size); rd_use_partition(cpi, tile, mi, tp, mi_row, mi_col, BLOCK_64X64, &dummy_rate, &dummy_dist, 1, cpi->pc_root); - } else if (sf->partition_search_type == VAR_BASED_FIXED_PARTITION) { + } else if (cpi->skippable_frame || + sf->partition_search_type == VAR_BASED_FIXED_PARTITION) { BLOCK_SIZE bsize; set_offsets(cpi, tile, mi_row, mi_col, BLOCK_64X64); bsize = get_rd_var_based_fixed_partition(cpi, mi_row, mi_col); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index bc240ff556976cb120eddb86a1f3ec6c5b759504..571ad0c67c3af74df43fee8134dd61affe6463ce 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -743,6 +743,8 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) { cpi->alt_is_last = 0; cpi->gold_is_alt = 0; + cpi->skippable_frame = 0; + // Create the encoder segmentation map and set all entries to 0 CHECK_MEM_ERROR(cm, cpi->segmentation_map, vpx_calloc(cm->mi_rows * cm->mi_cols, 1)); @@ -1972,6 +1974,29 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm, } } +static void configure_skippable_frame(VP9_COMP *cpi) { + // If the current frame does not have non-zero motion vector detected in the + // first pass, and so do its previous and forward frames, then this frame + // can be skipped for partition check, and the partition size is assigned + // according to the variance + + SVC *const svc = &cpi->svc; + const int is_spatial_svc = (svc->number_spatial_layers > 1) && + (svc->number_temporal_layers == 1); + TWO_PASS *const twopass = is_spatial_svc ? + &svc->layer_context[svc->spatial_layer_id].twopass + : &cpi->twopass; + + cpi->skippable_frame = (!frame_is_intra_only(&cpi->common) && + twopass->stats_in - 2 > twopass->stats_in_start && + twopass->stats_in < twopass->stats_in_end && + (twopass->stats_in - 1)->pcnt_inter - (twopass->stats_in - 1)->pcnt_motion + == 1 && + (twopass->stats_in - 2)->pcnt_inter - (twopass->stats_in - 2)->pcnt_motion + == 1 && + twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1); +} + static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, uint8_t *dest, @@ -2067,6 +2092,13 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, if (cpi->pass == 2 && cpi->sf.static_segmentation) configure_static_seg_features(cpi); + // Check if the current frame is skippable for the partition search in the + // second pass according to the first pass stats + if (cpi->pass == 2 && + (!cpi->use_svc || cpi->svc.number_temporal_layers == 1)) { + configure_skippable_frame(cpi); + } + // For 1 pass CBR, check if we are dropping this frame. // Never drop on key frame. if (cpi->pass == 0 && diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index a80ab1bd6204628adf05b0b6fa876e381ce7a95e..a5b465a63c544c26dc4d78b1a7ecf9417c6d1939 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -266,6 +266,8 @@ typedef struct VP9_COMP { int alt_is_last; // Alt same as last ( short circuit altref search) int gold_is_alt; // don't do both alt and gold search ( just do gold). + int skippable_frame; + int scaled_ref_idx[3]; int lst_fb_idx; int gld_fb_idx;