diff --git a/README.md b/README.md index 0c467b5d..8f304bf9 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Compression tools: - 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] + do before cutting off [-1] Has effect only for 'hexbs' and 'dia' --subme : Set fractional pixel motion estimation level - 0: only integer motion estimation diff --git a/src/cfg.c b/src/cfg.c index 2739758a..e01238ec 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -1156,7 +1156,21 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value) cfg->high_tier = true; } else if (OPT("me-steps")) { - cfg->me_max_steps = (uint32_t)atoi(value); // fix + char * tailptr = NULL; + + errno = 0; + long steps = strtol(value, &tailptr, 0); + + if (*tailptr != '\0') { + fprintf(stderr, "Invalid me-steps value: \"%s\"", value); + return 0; + } + if (steps < -1 || errno == ERANGE || steps > UINT32_MAX) { + fprintf(stderr, "me-steps value is out of bounds: \"%s\"", value); + return 0; + } + + cfg->me_max_steps = (uint32_t)steps; } else { return 0; diff --git a/src/cli.c b/src/cli.c index 0d3528b6..e742a3a0 100644 --- a/src/cli.c +++ b/src/cli.c @@ -433,7 +433,7 @@ void print_help(void) " - 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" + " do before cutting off [-1]\n" " Has effect only for 'hexbs' and 'dia'\n" " --subme : Set fractional pixel motion estimation level\n" " - 0: only integer motion estimation\n" diff --git a/src/search_inter.c b/src/search_inter.c index 77dbb612..4e1a7c31 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -630,6 +630,7 @@ static void tz_search(inter_search_info_t *info, vector2d_t extra_mv) * * \param info search info * \param extra_mv extra motion vector to check + * \param steps how many steps are done at maximum before exiting, does not affect the final step * * Motion vector is searched by first searching iteratively with the large * hexagon pattern until the best match is at the center of the hexagon. @@ -640,7 +641,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, uint32_t max_steps) +static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv, uint32_t 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,13 +690,11 @@ static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv, uint3 } } - 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 && steps_left != 0) { + while (best_index != 0 && steps != 0) { // decrement count if enabled - if (steps_left > 0 && max_steps != (uint32_t)-1) steps_left -= 1; + if (steps > 0) steps -= 1; // Starting point of the 3 offsets to be searched. unsigned start; @@ -731,8 +730,23 @@ static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv, uint3 } } - -static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv, uint32_t max_steps) +/** +* \brief Do motion search using the diamond algorithm. +* +* \param info search info +* \param extra_mv extra motion vector to check +* \param steps how many steps are done at maximum before exiting +* +* Motion vector is searched by searching iteratively with a diamond-shaped +* pattern. We take care of not checking the direction we came from, but +* further checking for avoiding visits to already visited points is not done. +* +* If a non 0,0 predicted motion vector predictor is given as extra_mv, +* the 0,0 vector is also tried. This is hoped to help in the case where +* 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 diamond_search(inter_search_info_t *info, vector2d_t extra_mv, uint32_t steps) { enum diapos { DIA_UP = 0, @@ -791,12 +805,11 @@ static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv, uint3 // 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; + if (steps > 0) steps -= 1; // search the points of the diamond for (int i = 0; i < 4; ++i) { @@ -818,7 +831,7 @@ static void diamond_search(inter_search_info_t *info, vector2d_t extra_mv, uint3 // the xor operation flips the orientation from_dir = best_index ^ 0x3; } - } while (better_found && steps_left != 0); + } while (better_found && steps != 0); // and we're done }