/* param.c * * Copyright (c) 2003-2015 HandBrake Team * This file is part of the HandBrake source code * Homepage: . * It may be used under the terms of the GNU General Public License v2. * For full terms see the file COPYING file or visit * http://www.gnu.org/licenses/gpl-2.0.html */ #include "hb.h" #include /* NL-means presets and tunes * * Presets adjust strength: * ultralight - visually transparent * light * medium * strong * * Tunes adjust settings to the specified content type: * none * film - most content, live action * grain - like film but preserves luma grain * highmotion - like film but avoids color smearing with stronger settings * animation - cel animation such as cartoons, anime */ static char * generate_nlmeans_settings(const char *preset, const char *tune) { char *opt = NULL; if (preset == NULL) return NULL; if (!strcasecmp(preset, "ultralight") || !strcasecmp(preset, "light") || !strcasecmp(preset, "medium") || !strcasecmp(preset, "strong")) { double strength[2], origin_tune[2]; int patch_size[2], range[2], frames[2], prefilter[2]; if (tune == NULL || !strcasecmp(tune, "none")) { strength[0] = strength[1] = 6; origin_tune[0] = origin_tune[1] = 1; patch_size[0] = patch_size[1] = 7; range[0] = range[1] = 3; frames[0] = frames[1] = 2; prefilter[0] = prefilter[1] = 0; if (!strcasecmp(preset, "ultralight")) { strength[0] = strength[1] = 1.5; } else if (!strcasecmp(preset, "light")) { strength[0] = strength[1] = 3; } else if (!strcasecmp(preset, "strong")) { strength[0] = strength[1] = 10; } } else if (!strcasecmp(tune, "film")) { strength[0] = 6; strength[1] = 8; origin_tune[0] = origin_tune[1] = 0.8; patch_size[0] = patch_size[1] = 7; range[0] = range[1] = 3; frames[0] = frames[1] = 2; prefilter[0] = prefilter[1] = 0; if (!strcasecmp(preset, "ultralight")) { strength[0] = 1.5; strength[1] = 2.4; origin_tune[0] = 0.9; origin_tune[1] = 0.9; } else if (!strcasecmp(preset, "light")) { strength[0] = 3; strength[1] = 4; origin_tune[0] = 0.9; origin_tune[1] = 0.9; } else if (!strcasecmp(preset, "strong")) { strength[0] = 8; strength[1] = 10; origin_tune[0] = 0.6; origin_tune[1] = 0.6; } } else if (!strcasecmp(tune, "grain")) { strength[0] = 0; strength[1] = 6; origin_tune[0] = origin_tune[1] = 0.8; patch_size[0] = patch_size[1] = 7; range[0] = range[1] = 3; frames[0] = frames[1] = 2; prefilter[0] = prefilter[1] = 0; if (!strcasecmp(preset, "ultralight")) { strength[0] = 0; strength[1] = 2.4; origin_tune[0] = 0.9; origin_tune[1] = 0.9; } else if (!strcasecmp(preset, "light")) { strength[0] = 0; strength[1] = 3.5; origin_tune[0] = 0.9; origin_tune[1] = 0.9; } else if (!strcasecmp(preset, "strong")) { strength[0] = 0; strength[1] = 8; origin_tune[0] = 0.6; origin_tune[1] = 0.6; } } else if (!strcasecmp(tune, "highmotion")) { strength[0] = 6; strength[1] = 6; origin_tune[0] = 0.8; origin_tune[1] = 0.7; patch_size[0] = 7; patch_size[1] = 7; range[0] = 3; range[1] = 5; frames[0] = 2; frames[1] = 1; prefilter[0] = 0; prefilter[1] = 0; if (!strcasecmp(preset, "ultralight")) { strength[0] = 1.5; strength[1] = 2.4; origin_tune[0] = 0.9; origin_tune[1] = 0.9; } else if (!strcasecmp(preset, "light")) { strength[0] = 3; strength[1] = 3.25; origin_tune[0] = 0.9; origin_tune[1] = 0.8; } else if (!strcasecmp(preset, "strong")) { strength[0] = 8; strength[1] = 6.75; origin_tune[0] = 0.6; origin_tune[1] = 0.5; } } else if (!strcasecmp(tune, "animation")) { strength[0] = 5; strength[1] = 4; origin_tune[0] = origin_tune[1] = 0.15; patch_size[0] = patch_size[1] = 5; range[0] = range[1] = 7; frames[0] = frames[1] = 4; prefilter[0] = prefilter[1] = 0; if (!strcasecmp(preset, "ultralight")) { strength[0] = 2.5; strength[1] = 2; frames[0] = 2; frames[1] = 2; } else if (!strcasecmp(preset, "light")) { strength[0] = 3; strength[1] = 2.25; frames[0] = 3; frames[1] = 3; } else if (!strcasecmp(preset, "strong")) { strength[0] = 10; strength[1] = 8; } } else { fprintf(stderr, "Unrecognized nlmeans tune (%s).\n", tune); return NULL; } opt = hb_strdup_printf("%lf:%lf:%d:%d:%d:%d:%lf:%lf:%d:%d:%d:%d", strength[0], origin_tune[0], patch_size[0], range[0], frames[0], prefilter[0], strength[1], origin_tune[1], patch_size[1], range[1], frames[1], prefilter[1]); } else { opt = strdup(preset); if (tune != NULL) { fprintf(stderr, "Custom nlmeans parameters specified; ignoring nlmeans tune (%s).\n", tune); } } return opt; } /* HQDN3D presets * * Presets adjust strength: * ultralight - visually transparent * light * medium * strong */ static char * generate_hqdn3d_settings(const char *preset, const char *tune) { if (preset == NULL) return NULL; if (!strcasecmp(preset, "strong")) return strdup("7:7:7:5:5:5"); else if (!strcasecmp(preset, "medium")) return strdup("3:2:2:2:3:3"); else if (!strcasecmp(preset, "light") || !strcasecmp(preset, "weak")) return strdup("2:1:1:2:3:3"); else if (!strcasecmp(preset, "ultralight")) return strdup("1:0.7:0.7:1:2:2"); else return strdup(preset); } int hb_validate_param_string(const char *regex_pattern, const char *param_string) { regex_t regex_temp; if (regcomp(®ex_temp, regex_pattern, REG_EXTENDED) == 0) { if (regexec(®ex_temp, param_string, 0, NULL, 0) == 0) { regfree(®ex_temp); return 0; } } else { fprintf(stderr, "hb_validate_param_string: Error compiling regex for pattern (%s).\n", param_string); } regfree(®ex_temp); return 1; } int hb_validate_filter_settings(int filter_id, const char *filter_param) { // Regex matches "number" followed by one or more ":number", where number is uint or ufloat const char *hb_colon_separated_params_regex = "^((([0-9]+([.,][0-9]+)?)|([.,][0-9]+))((:(([0-9]+([.,][0-9]+)?)|([.,][0-9]+)))+)?)$"; const char *regex_pattern = NULL; switch (filter_id) { case HB_FILTER_NLMEANS: case HB_FILTER_HQDN3D: if (filter_param == NULL) { return 0; } regex_pattern = hb_colon_separated_params_regex; break; default: fprintf(stderr, "hb_validate_filter_settings: Unrecognized filter (%d).\n", filter_id); return 1; break; } if (hb_validate_param_string(regex_pattern, filter_param) == 0) { return 0; } return 1; } char * hb_generate_filter_settings(int filter_id, const char *preset, const char *tune) { char *filter_param = NULL; switch (filter_id) { case HB_FILTER_NLMEANS: filter_param = generate_nlmeans_settings(preset, tune); break; case HB_FILTER_HQDN3D: filter_param = generate_hqdn3d_settings(preset, tune); break; default: fprintf(stderr, "hb_generate_filter_settings: Unrecognized filter (%d).\n", filter_id); break; } if (hb_validate_filter_settings(filter_id, filter_param) == 0) { return filter_param; } return NULL; }