From 8082614e81a5047bef66c25abfd8181c9f1f4713 Mon Sep 17 00:00:00 2001 From: Thomas Daede Date: Mon, 20 Mar 2017 15:44:24 -0700 Subject: [PATCH] Remove rt deadline. The "good" speed levels are universally better than the "rt" ones, running faster to achieve the same quality. rt mode also turned off alt refs and lag-in-frames, but these are still accessible separately (and the low latency test case explicitly sets them). Some features were used by the rt scale and not the good scale. Two additional "good" levels, 7 and 8, were added to accomidate these features and not reduce test coverage. Change-Id: I3a6a78ddb664511762c197bc41f3a9909665b565 --- aom/aom_encoder.h | 4 +- aomenc.c | 24 +---- av1/av1_cx_iface.c | 1 - av1/encoder/encoder.h | 10 +- av1/encoder/speed_features.c | 195 +++-------------------------------- av1/encoder/speed_features.h | 3 +- examples/simple_encoder.c | 3 +- test/encode_test_driver.cc | 14 ++- test/encode_test_driver.h | 3 +- warnings.c | 12 +-- 10 files changed, 34 insertions(+), 235 deletions(-) diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h index e9923342e..14c9f0c26 100644 --- a/aom/aom_encoder.h +++ b/aom/aom_encoder.h @@ -695,8 +695,6 @@ aom_codec_err_t aom_codec_enc_config_set(aom_codec_ctx_t *ctx, */ aom_fixed_buf_t *aom_codec_get_global_headers(aom_codec_ctx_t *ctx); -/*!\brief deadline parameter analogous to AVx REALTIME mode. */ -#define AOM_DL_REALTIME (1) /*!\brief deadline parameter analogous to AVx GOOD QUALITY mode. */ #define AOM_DL_GOOD_QUALITY (1000000) /*!\brief Encode a frame @@ -712,7 +710,7 @@ aom_fixed_buf_t *aom_codec_get_global_headers(aom_codec_ctx_t *ctx); * best possible frame by specifying a deadline of '0'. This deadline * supercedes the AVx notion of "best quality, good quality, realtime". * Applications that wish to map these former settings to the new deadline - * based system can use the symbols #AOM_DL_REALTIME and #AOM_DL_GOOD_QUALITY. + * based system can use the symbol #AOM_DL_GOOD_QUALITY. * * When the last frame has been passed to the encoder, this function should * continue to be called, with the img parameter set to NULL. This will diff --git a/aomenc.c b/aomenc.c index 5982f5026..fb43d09d7 100644 --- a/aomenc.c +++ b/aomenc.c @@ -157,8 +157,6 @@ static const arg_def_t deadline = ARG_DEF("d", "deadline", 1, "Deadline per frame (usec)"); static const arg_def_t good_dl = ARG_DEF(NULL, "good", 0, "Use Good Quality Deadline"); -static const arg_def_t rt_dl = - ARG_DEF(NULL, "rt", 0, "Use Realtime Quality Deadline"); static const arg_def_t quietarg = ARG_DEF("q", "quiet", 0, "Do not print encode progress"); static const arg_def_t verbosearg = @@ -219,7 +217,6 @@ static const arg_def_t *main_args[] = { &debugmode, &skip, &deadline, &good_dl, - &rt_dl, &quietarg, &verbosearg, &psnrarg, @@ -935,8 +932,6 @@ static void parse_global_config(struct AvxEncoderConfig *global, char **argv) { global->deadline = arg_parse_uint(&arg); else if (arg_match(&arg, &good_dl, argi)) global->deadline = AOM_DL_GOOD_QUALITY; - else if (arg_match(&arg, &rt_dl, argi)) - global->deadline = AOM_DL_REALTIME; else if (arg_match(&arg, &use_yv12, argi)) global->color_type = YV12; else if (arg_match(&arg, &use_i420, argi)) @@ -993,19 +988,11 @@ static void parse_global_config(struct AvxEncoderConfig *global, char **argv) { // Make default AV1 passes = 2 until there is a better quality 1-pass // encoder if (global->codec != NULL && global->codec->name != NULL) - global->passes = (strcmp(global->codec->name, "av1") == 0 && - global->deadline != AOM_DL_REALTIME) - ? 2 - : 1; + global->passes = (strcmp(global->codec->name, "av1") == 0) ? 2 : 1; #else global->passes = 1; #endif } - - if (global->deadline == AOM_DL_REALTIME && global->passes > 1) { - warn("Enforcing one-pass encoding in realtime mode\n"); - global->passes = 1; - } } static void open_input_file(struct AvxInputContext *input) { @@ -1102,10 +1089,6 @@ static struct stream_state *new_stream(struct AvxEncoderConfig *global, /* Allows removal of the application version from the EBML tags */ stream->webm_ctx.debug = global->debug; - - /* Default lag_in_frames is 0 in realtime mode */ - if (global->deadline == AOM_DL_REALTIME) - stream->config.cfg.g_lag_in_frames = 0; } /* Output files must be specified for each stream */ @@ -1193,11 +1176,6 @@ static int parse_stream_params(struct AvxEncoderConfig *global, config->cfg.g_error_resilient = arg_parse_uint(&arg); } else if (arg_match(&arg, &lag_in_frames, argi)) { config->cfg.g_lag_in_frames = arg_parse_uint(&arg); - if (global->deadline == AOM_DL_REALTIME && - config->cfg.g_lag_in_frames != 0) { - warn("non-zero %s option ignored in realtime mode.\n", arg.name); - config->cfg.g_lag_in_frames = 0; - } } else if (arg_match(&arg, &dropframe_thresh, argi)) { config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg); } else if (arg_match(&arg, &resize_allowed, argi)) { diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index 29b641b77..e8c445b2c 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c @@ -917,7 +917,6 @@ static void pick_quickcompress_mode(aom_codec_alg_priv_t *ctx, switch (ctx->cfg.g_pass) { case AOM_RC_ONE_PASS: switch (deadline) { - case AOM_DL_REALTIME: new_mode = REALTIME; break; default: new_mode = GOOD; break; } break; diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 5c4a6a6e2..2299f0114 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h @@ -99,12 +99,7 @@ typedef enum { typedef enum { // Good Quality Fast Encoding. The encoder balances quality with the amount of // time it takes to encode the output. Speed setting controls how fast. - GOOD, - - // Realtime/Live Encoding. This mode is optimized for realtime encoding (for - // example, capturing a television signal or feed from a live camera). Speed - // setting controls how fast. - REALTIME + GOOD } MODE; typedef enum { @@ -815,8 +810,7 @@ YV12_BUFFER_CONFIG *av1_scale_if_required(AV1_COMMON *cm, void av1_apply_encoding_flags(AV1_COMP *cpi, aom_enc_frame_flags_t flags); static INLINE int is_altref_enabled(const AV1_COMP *const cpi) { - return cpi->oxcf.mode != REALTIME && cpi->oxcf.lag_in_frames > 0 && - cpi->oxcf.enable_auto_arf; + return cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.enable_auto_arf; } // TODO(zoeliu): To set up cpi->oxcf.enable_auto_brf diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index b10260417..bf99c5dc4 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c @@ -241,129 +241,17 @@ static void set_good_speed_feature(AV1_COMP *cpi, AV1_COMMON *cm, sf->mv.reduce_first_step_size = 1; sf->simple_model_rd_from_var = 1; } -} - -static void set_rt_speed_feature_framesize_dependent(AV1_COMP *cpi, - SPEED_FEATURES *sf, - int speed) { - AV1_COMMON *const cm = &cpi->common; - if (speed >= 1) { - if (AOMMIN(cm->width, cm->height) >= 720) { - sf->disable_split_mask = - cm->show_frame ? DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT; - } else { - sf->disable_split_mask = DISABLE_COMPOUND_SPLIT; - } - } - - if (speed >= 2) { - if (AOMMIN(cm->width, cm->height) >= 720) { - sf->disable_split_mask = - cm->show_frame ? DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT; - } else { - sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY; - } - } - - if (speed >= 5) { - if (AOMMIN(cm->width, cm->height) >= 720) { - sf->partition_search_breakout_dist_thr = (1 << 25); - } else { - sf->partition_search_breakout_dist_thr = (1 << 23); - } - } -} - -static void set_rt_speed_feature(AV1_COMP *cpi, SPEED_FEATURES *sf, int speed, - aom_tune_content content) { - AV1_COMMON *const cm = &cpi->common; - const int is_keyframe = cm->frame_type == KEY_FRAME; - const int frames_since_key = is_keyframe ? 0 : cpi->rc.frames_since_key; - sf->static_segmentation = 0; - sf->adaptive_rd_thresh = 1; - sf->use_fast_coef_costing = 1; - sf->allow_exhaustive_searches = 0; - sf->exhaustive_searches_thresh = INT_MAX; - sf->use_upsampled_references = 0; -#if CONFIG_EXT_INTER - sf->disable_wedge_search_var_thresh = 100; - sf->fast_wedge_sign_estimate = 1; -#endif // CONFIG_EXT_INTER - - // Use transform domain distortion computation - // Note var-tx expt always uses pixel domain distortion. - sf->use_transform_domain_distortion = 1; - - if (speed >= 1) { - sf->use_square_partition_only = !frame_is_intra_only(cm); - sf->less_rectangular_check = 1; - sf->tx_size_search_method = - frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL; - - sf->use_rd_breakout = 1; - - sf->adaptive_motion_search = 1; - sf->adaptive_pred_interp_filter = 1; - sf->mv.auto_mv_step_size = 1; - sf->adaptive_rd_thresh = 2; -#if CONFIG_TX64X64 - sf->intra_y_mode_mask[TX_64X64] = INTRA_DC_H_V; - sf->intra_uv_mode_mask[TX_64X64] = INTRA_DC_H_V; -#endif // CONFIG_TX64X64 - sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V; - sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V; - sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V; - } - - if (speed >= 2) { - sf->mode_search_skip_flags = - (cm->frame_type == KEY_FRAME) - ? 0 - : FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER | - FLAG_SKIP_COMP_BESTINTRA | FLAG_SKIP_INTRA_LOWVAR; - sf->adaptive_pred_interp_filter = 2; - sf->disable_filter_search_var_thresh = 50; - sf->comp_inter_joint_search_thresh = BLOCK_SIZES; - sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX; - sf->lf_motion_threshold = LOW_MOTION_THRESHOLD; - sf->adjust_partitioning_from_last_frame = 1; - sf->last_partitioning_redo_frequency = 3; - sf->mode_skip_start = 11; - sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V; - } - - if (speed >= 3) { - sf->use_square_partition_only = 1; - sf->disable_filter_search_var_thresh = 100; - sf->mv.subpel_iters_per_step = 1; - sf->adaptive_rd_thresh = 4; - sf->mode_skip_start = 6; - sf->optimize_coefficients = 0; - sf->disable_split_mask = DISABLE_ALL_SPLIT; - sf->lpf_pick = LPF_PICK_FROM_Q; - } - - if (speed >= 4) { - int i; - sf->last_partitioning_redo_frequency = 4; - sf->adaptive_rd_thresh = 5; - sf->use_fast_coef_costing = 0; - sf->auto_min_max_partition_size = STRICT_NEIGHBORING_MIN_MAX; - sf->adjust_partitioning_from_last_frame = - cm->last_frame_type != cm->frame_type || - (0 == (frames_since_key + 1) % sf->last_partitioning_redo_frequency); - sf->mv.subpel_force_stop = 1; - for (i = 0; i < TX_SIZES; i++) { - sf->intra_y_mode_mask[i] = INTRA_DC_H_V; - sf->intra_uv_mode_mask[i] = INTRA_DC; - } + if (speed >= 7) { + const int is_keyframe = cm->frame_type == KEY_FRAME; + const int frames_since_key = is_keyframe ? 0 : cpi->rc.frames_since_key; + sf->default_max_partition_size = BLOCK_32X32; + sf->default_min_partition_size = BLOCK_8X8; #if CONFIG_TX64X64 sf->intra_y_mode_mask[TX_64X64] = INTRA_DC; #endif // CONFIG_TX64X64 sf->intra_y_mode_mask[TX_32X32] = INTRA_DC; sf->frame_parameter_update = 0; sf->mv.search_method = FAST_HEX; - sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEAR_NEW; sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST; sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST; @@ -373,69 +261,20 @@ static void set_rt_speed_feature(AV1_COMP *cpi, SPEED_FEATURES *sf, int speed, sf->inter_mode_mask[BLOCK_128X64] = INTER_NEAREST; sf->inter_mode_mask[BLOCK_128X128] = INTER_NEAREST; #endif // CONFIG_EXT_PARTITION - sf->max_intra_bsize = BLOCK_32X32; - } - - if (speed >= 5) { - sf->auto_min_max_partition_size = - is_keyframe ? RELAXED_NEIGHBORING_MIN_MAX : STRICT_NEIGHBORING_MIN_MAX; - sf->default_max_partition_size = BLOCK_32X32; + sf->partition_search_type = REFERENCE_PARTITION; sf->default_min_partition_size = BLOCK_8X8; + sf->reuse_inter_pred_sby = 1; sf->force_frame_boost = is_keyframe || (frames_since_key % (sf->last_partitioning_redo_frequency << 1) == 1); sf->max_delta_qindex = is_keyframe ? 20 : 15; - sf->partition_search_type = REFERENCE_PARTITION; - sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEW_ZERO; - sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST_NEW_ZERO; - sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST_NEW_ZERO; - sf->inter_mode_mask[BLOCK_64X64] = INTER_NEAREST_NEW_ZERO; -#if CONFIG_EXT_PARTITION - sf->inter_mode_mask[BLOCK_64X128] = INTER_NEAREST_NEW_ZERO; - sf->inter_mode_mask[BLOCK_128X64] = INTER_NEAREST_NEW_ZERO; - sf->inter_mode_mask[BLOCK_128X128] = INTER_NEAREST_NEW_ZERO; -#endif // CONFIG_EXT_PARTITION - sf->adaptive_rd_thresh = 2; - // This feature is only enabled when partition search is disabled. - sf->reuse_inter_pred_sby = 1; - sf->partition_search_breakout_rate_thr = 200; sf->coeff_prob_appx_step = 4; - sf->use_fast_coef_updates = is_keyframe ? TWO_LOOP : ONE_LOOP_REDUCED; - sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH; - sf->tx_size_search_method = is_keyframe ? USE_LARGESTALL : USE_TX_8X8; - sf->simple_model_rd_from_var = 1; - - if (!is_keyframe) { - int i; - if (content == AOM_CONTENT_SCREEN) { - for (i = 0; i < BLOCK_SIZES; ++i) - sf->intra_y_mode_bsize_mask[i] = INTRA_DC_TM_H_V; - } else { - for (i = 0; i < BLOCK_SIZES; ++i) - if (i >= BLOCK_16X16) - sf->intra_y_mode_bsize_mask[i] = INTRA_DC; - else - // Use H and V intra mode for block sizes <= 16X16. - sf->intra_y_mode_bsize_mask[i] = INTRA_DC_H_V; - } - } - } - - if (speed >= 6) { - // Adaptively switch between SOURCE_VAR_BASED_PARTITION and FIXED_PARTITION. - sf->partition_search_type = VAR_BASED_PARTITION; - // Turn on this to use non-RD key frame coding mode. - sf->mv.search_method = NSTEP; - sf->mv.reduce_first_step_size = 1; - } - - if (speed >= 7) { - sf->adaptive_rd_thresh = 3; - sf->mv.search_method = FAST_DIAMOND; - sf->mv.fullpel_search_step_param = 10; + sf->mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH; } if (speed >= 8) { - sf->adaptive_rd_thresh = 4; + sf->mv.search_method = FAST_DIAMOND; + sf->partition_search_type = VAR_BASED_PARTITION; + sf->mv.fullpel_search_step_param = 10; sf->mv.subpel_force_stop = 2; sf->lpf_pick = LPF_PICK_MINIMAL_LPF; } @@ -469,9 +308,7 @@ void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi) { } #endif // CONFIG_EXT_REFS - if (oxcf->mode == REALTIME) { - set_rt_speed_feature_framesize_dependent(cpi, sf, oxcf->speed); - } else if (oxcf->mode == GOOD) { + if (oxcf->mode == GOOD) { set_good_speed_feature_framesize_dependent(cpi, sf, oxcf->speed); } @@ -576,13 +413,11 @@ void av1_set_speed_features_framesize_independent(AV1_COMP *cpi) { sf->use_transform_domain_distortion = 0; #endif // CONFIG_EXT_TILE - if (oxcf->mode == REALTIME) - set_rt_speed_feature(cpi, sf, oxcf->speed, oxcf->content); - else if (oxcf->mode == GOOD + if (oxcf->mode == GOOD #if CONFIG_XIPHRC - || oxcf->pass == 1 + || oxcf->pass == 1 #endif - ) + ) set_good_speed_feature(cpi, cm, sf, oxcf->speed); // sf->partition_search_breakout_dist_thr is set assuming max 64x64 diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h index 5a1d83c85..af54a1a9a 100644 --- a/av1/encoder/speed_features.h +++ b/av1/encoder/speed_features.h @@ -134,8 +134,7 @@ typedef enum { typedef enum { NOT_IN_USE = 0, - RELAXED_NEIGHBORING_MIN_MAX = 1, - STRICT_NEIGHBORING_MIN_MAX = 2 + RELAXED_NEIGHBORING_MIN_MAX = 1 } AUTO_MIN_MAX_MODE; typedef enum { diff --git a/examples/simple_encoder.c b/examples/simple_encoder.c index 033068f05..996f6dacf 100644 --- a/examples/simple_encoder.c +++ b/examples/simple_encoder.c @@ -61,8 +61,7 @@ // is passed, indicating the End-Of-Stream condition to the encoder. The // `frame_cnt` is reused as the presentation time stamp (PTS) and each // frame is shown for one frame-time in duration. The flags parameter is -// unused in this example. The deadline is set to AOM_DL_REALTIME to -// make the example run as quickly as possible. +// unused in this example. // Forced Keyframes // ---------------- diff --git a/test/encode_test_driver.cc b/test/encode_test_driver.cc index 962ff7b1b..a9e1f703d 100644 --- a/test/encode_test_driver.cc +++ b/test/encode_test_driver.cc @@ -105,14 +105,15 @@ void EncoderTest::InitializeConfig() { void EncoderTest::SetMode(TestMode mode) { switch (mode) { - case kRealTime: deadline_ = AOM_DL_REALTIME; break; - case kOnePassGood: case kTwoPassGood: deadline_ = AOM_DL_GOOD_QUALITY; break; - + case kRealTime: + deadline_ = AOM_DL_GOOD_QUALITY; + cfg_.g_lag_in_frames = 0; + break; default: ASSERT_TRUE(false) << "Unexpected mode " << mode; } - + mode_ = mode; if (mode == kTwoPassGood) passes_ = 2; else @@ -232,6 +233,11 @@ void EncoderTest::RunLoop(VideoSource *video) { ASSERT_NO_FATAL_FAILURE(video->Begin()); encoder->InitEncoder(video); + + if (mode_ == kRealTime) { + encoder->Control(AOME_SET_ENABLEAUTOALTREF, 0); + } + ASSERT_FALSE(::testing::Test::HasFatalFailure()); unsigned long dec_init_flags = 0; // NOLINT diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h index dd07b9422..91027b4f6 100644 --- a/test/encode_test_driver.h +++ b/test/encode_test_driver.h @@ -163,7 +163,7 @@ class EncoderTest { protected: explicit EncoderTest(const CodecFactory *codec) : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0), - last_pts_(0) { + last_pts_(0), mode_(kRealTime) { // Default to 1 thread. cfg_.g_threads = 1; } @@ -239,6 +239,7 @@ class EncoderTest { unsigned long init_flags_; unsigned long frame_flags_; aom_codec_pts_t last_pts_; + TestMode mode_; }; } // namespace libaom_test diff --git a/warnings.c b/warnings.c index 7575925d4..16d5c6c18 100644 --- a/warnings.c +++ b/warnings.c @@ -24,8 +24,6 @@ static const char quantizer_warning_string[] = "Bad quantizer values. Quantizer values should not be equal, and should " "differ by at least 8."; -static const char lag_in_frames_with_realtime[] = - "Lag in frames is ignored when deadline is set to realtime."; struct WarningListNode { const char *warning_string; @@ -77,23 +75,15 @@ static void check_quantizer(int min_q, int max_q, add_warning(quantizer_warning_string, warning_list); } -static void check_lag_in_frames_realtime_deadline( - int lag_in_frames, int deadline, struct WarningList *warning_list) { - if (deadline == AOM_DL_REALTIME && lag_in_frames != 0) - add_warning(lag_in_frames_with_realtime, warning_list); -} - void check_encoder_config(int disable_prompt, const struct AvxEncoderConfig *global_config, const struct aom_codec_enc_cfg *stream_config) { int num_warnings = 0; struct WarningListNode *warning = NULL; struct WarningList warning_list = { 0 }; - + (void)global_config; check_quantizer(stream_config->rc_min_quantizer, stream_config->rc_max_quantizer, &warning_list); - check_lag_in_frames_realtime_deadline(stream_config->g_lag_in_frames, - global_config->deadline, &warning_list); /* Count and print warnings. */ for (warning = warning_list.warning_node; warning != NULL; warning = warning->next_warning, ++num_warnings) {