From e8e0e7596a72d4e2f197f3240e9170afad8413a0 Mon Sep 17 00:00:00 2001 From: Miika Metsoila Date: Fri, 22 Dec 2017 12:10:41 +0200 Subject: [PATCH] Add a step-cutoff parameter for motion estimation search --- README.md | 3 +++ src/cfg.c | 5 +++++ src/cli.c | 4 ++++ src/kvazaar.h | 3 +++ src/search_inter.c | 20 ++++++++++++++------ 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e492b083..0c467b5d 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,9 @@ Compression tools: - full: Full Search - full8, full16, full32, full64 - dia: Diamond Search + --me-steps : How many search steps does the motion estimation + do before cutting off, -1 for no limits [-1] + Has effect only for 'hexbs' and 'dia' --subme : Set fractional pixel motion estimation level - 0: only integer motion estimation - 1: + 1/2-pixel horizontal and vertical diff --git a/src/cfg.c b/src/cfg.c index cee8c0f7..2739758a 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -130,6 +130,8 @@ int kvz_config_init(kvz_config *cfg) cfg->force_level = true; // don't care about level limits by-default cfg->high_tier = false; + cfg->me_max_steps = (uint32_t)-1; + return 1; } @@ -1153,6 +1155,9 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value) else if (OPT("high-tier")) { cfg->high_tier = true; } + else if (OPT("me-steps")) { + cfg->me_max_steps = (uint32_t)atoi(value); // fix + } else { return 0; } diff --git a/src/cli.c b/src/cli.c index 9040fd3d..0d3528b6 100644 --- a/src/cli.c +++ b/src/cli.c @@ -125,6 +125,7 @@ static const struct option long_options[] = { { "level", required_argument, NULL, 0 }, { "force-level", required_argument, NULL, 0 }, { "high-tier", no_argument, NULL, 0 }, + { "me-steps", required_argument, NULL, 0 }, {0, 0, 0, 0} }; @@ -431,6 +432,9 @@ void print_help(void) " - full: Full Search\n" " - full8, full16, full32, full64\n" " - dia: Diamond Search\n" + " --me-steps : How many search steps does the motion estimation\n" + " do before cutting off, -1 for no limits [-1]\n" + " Has effect only for 'hexbs' and 'dia'\n" " --subme : Set fractional pixel motion estimation level\n" " - 0: only integer motion estimation\n" " - 1: + 1/2-pixel horizontal and vertical\n" diff --git a/src/kvazaar.h b/src/kvazaar.h index f8275ba3..b7f5e445 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -361,6 +361,9 @@ typedef struct kvz_config uint8_t high_tier; /** \brief The maximum allowed bitrate for this level and tier. */ uint32_t max_bitrate; + + /** \brief Maximum steps that hexagonal and diagonal motion estimation can use. -1 to disable */ + uint32_t me_max_steps; } kvz_config; /** diff --git a/src/search_inter.c b/src/search_inter.c index 55975658..77dbb612 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -640,7 +640,7 @@ static void tz_search(inter_search_info_t *info, vector2d_t extra_mv) * the predicted motion vector is way off. In the future even more additional * points like 0,0 might be used, such as vectors from top or left. */ -static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv) +static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv, uint32_t max_steps) { // The start of the hexagonal pattern has been repeated at the end so that // the indices between 1-6 can be used as the start of a 3-point list of new @@ -689,9 +689,14 @@ static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv) } } + uint32_t steps_left = max_steps; + // Iteratively search the 3 new points around the best match, until the best // match is in the center. - while (best_index != 0) { + while (best_index != 0 && steps_left != 0) { + // decrement count if enabled + if (steps_left > 0 && max_steps != (uint32_t)-1) steps_left -= 1; + // Starting point of the 3 offsets to be searched. unsigned start; if (best_index == 1) { @@ -727,7 +732,7 @@ static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv) } -static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv) +static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv, uint32_t max_steps) { enum diapos { DIA_UP = 0, @@ -786,9 +791,12 @@ static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv) // whether we found a better candidate this iteration uint8_t better_found; + uint32_t steps_left = max_steps; do { better_found = 0; + // decrement count if enabled + if (steps_left > 0 && max_steps != (uint32_t) -1) steps_left -= 1; // search the points of the diamond for (int i = 0; i < 4; ++i) { @@ -810,7 +818,7 @@ static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv) // the xor operation flips the orientation from_dir = best_index ^ 0x3; } - } while (better_found); + } while (better_found && steps_left != 0); // and we're done } @@ -1250,11 +1258,11 @@ static void search_pu_inter_ref(inter_search_info_t *info, break; case KVZ_IME_DIA: - diamond_search(info, mv); + diamond_search(info, mv, info->state->encoder_control->cfg.me_max_steps); break; default: - hexagon_search(info, mv); + hexagon_search(info, mv, info->state->encoder_control->cfg.me_max_steps); break; }