diff --git a/src/cfg.c b/src/cfg.c index 9b5efec4..cee8c0f7 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -349,7 +349,7 @@ static int parse_slice_specification(const char* const arg, int32_t * const nsli int kvz_config_parse(kvz_config *cfg, const char *name, const char *value) { - static const char * const me_names[] = { "hexbs", "tz", "full", "full8", "full16", "full32", "full64", NULL }; + static const char * const me_names[] = { "hexbs", "tz", "full", "full8", "full16", "full32", "full64", "dia", NULL }; static const char * const source_scan_type_names[] = { "progressive", "tff", "bff", NULL }; static const char * const overscan_names[] = { "undef", "show", "crop", NULL }; diff --git a/src/kvazaar.h b/src/kvazaar.h index 8dd61ce2..f8275ba3 100644 --- a/src/kvazaar.h +++ b/src/kvazaar.h @@ -92,6 +92,7 @@ enum kvz_ime_algorithm { KVZ_IME_FULL16 = 4, //! \since 3.6.0 KVZ_IME_FULL32 = 5, //! \since 3.6.0 KVZ_IME_FULL64 = 6, //! \since 3.6.0 + KVZ_IME_DIA = 7, // Experimental. TODO: change into a proper doc comment }; /** diff --git a/src/search_inter.c b/src/search_inter.c index 5f2e8f12..55975658 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -679,7 +679,7 @@ static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv) vector2d_t mv = { info->best_mv.x >> 2, info->best_mv.y >> 2 }; - // Current best index, either to merge_cands, large_hebx or small_hexbs. + // Current best index, either to merge_cands, large_hexbs or small_hexbs. int best_index = 0; // Search the initial 7 points of the hexagon. @@ -717,9 +717,8 @@ static void hexagon_search(inter_search_info_t *info, vector2d_t extra_mv) } // Move the center to the best match. - mv.x += large_hexbs[best_index].x; - mv.y += large_hexbs[best_index].y; - best_index = 0; + //mv.x += large_hexbs[best_index].x; + //mv.y += large_hexbs[best_index].y; // Do the final step of the search with a small pattern. for (int i = 1; i < 5; ++i) { @@ -728,6 +727,94 @@ 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) +{ + enum diapos { + DIA_UP = 0, + DIA_RIGHT = 1, + DIA_LEFT = 2, + DIA_DOWN = 3, + DIA_CENTER = 4, + }; + + // a diamond shape with the center included + // 0 + // 2 4 1 + // 3 + static const vector2d_t diamond[5] = { + {0, -1}, {1, 0}, {0, 1}, {-1, 0}, + {0, 0} + }; + + info->best_cost = UINT32_MAX; + + // Select starting point from among merge candidates. These should + // include both mv_cand vectors and (0, 0). + select_starting_point(info, extra_mv); + + // Check if we should stop search + if (info->state->encoder_control->cfg.me_early_termination && + early_terminate(info)) + { + return; + } + + // current motion vector + vector2d_t mv = { info->best_mv.x >> 2, info->best_mv.y >> 2 }; + + // current best index + enum diapos best_index = DIA_CENTER; + + // initial search of the points of the diamond + for (int i = 0; i < 5; ++i) { + if (check_mv_cost(info, mv.x + diamond[i].x, mv.y + diamond[i].y)) { + best_index = i; + } + } + + if (best_index == DIA_CENTER) { + // the center point was the best in initial check + return; + } + + // Move the center to the best match. + mv.x += diamond[best_index].x; + mv.y += diamond[best_index].y; + + // the arrival direction, the index of the diamond member that will be excluded + enum diapos from_dir = DIA_CENTER; + + // whether we found a better candidate this iteration + uint8_t better_found; + + do { + better_found = 0; + + // search the points of the diamond + for (int i = 0; i < 4; ++i) { + // this is where we came from so it's checked already + if (i == from_dir) continue; + + if (check_mv_cost(info, mv.x + diamond[i].x, mv.y + diamond[i].y)) { + best_index = i; + better_found = 1; + } + } + + if (better_found) { + // Move the center to the best match. + mv.x += diamond[best_index].x; + mv.y += diamond[best_index].y; + + // record where we came from to the next iteration + // the xor operation flips the orientation + from_dir = best_index ^ 0x3; + } + } while (better_found); + // and we're done +} + + static void search_mv_full(inter_search_info_t *info, int32_t search_range, vector2d_t extra_mv) @@ -1162,6 +1249,10 @@ static void search_pu_inter_ref(inter_search_info_t *info, search_mv_full(info, search_range, mv); break; + case KVZ_IME_DIA: + diamond_search(info, mv); + break; + default: hexagon_search(info, mv); break;