WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / param.c
blob494badf397054b151fcd16a37f715edc552b06ec
1 /* param.c
3 * Copyright (c) 2003-2015 HandBrake Team
4 * This file is part of the HandBrake source code
5 * Homepage: <http://handbrake.fr/>.
6 * It may be used under the terms of the GNU General Public License v2.
7 * For full terms see the file COPYING file or visit
8 * http://www.gnu.org/licenses/gpl-2.0.html
9 */
11 #include "param.h"
12 #include "common.h"
13 #include <regex.h>
15 const char hb_filter_off[] = "off";
17 static hb_filter_param_t nlmeans_presets[] =
19 { 1, "Custom", "custom", NULL },
20 { 5, "Ultralight", "ultralight", NULL },
21 { 2, "Light", "light", NULL },
22 { 3, "Medium", "medium", NULL },
23 { 4, "Strong", "strong", NULL },
24 { 0, NULL, NULL, NULL }
27 static hb_filter_param_t nlmeans_tunes[] =
29 { 0, "None", "none", NULL },
30 { 1, "Film", "film", NULL },
31 { 2, "Grain", "grain", NULL },
32 { 3, "High Motion", "highmotion", NULL },
33 { 4, "Animation", "animation", NULL },
34 { 0, NULL, NULL, NULL }
37 static hb_filter_param_t hqdn3d_presets[] =
39 { 1, "Custom", "custom", NULL },
40 { 5, "Ultralight", "ultralight", "1:0.7:0.7:1:2:2" },
41 { 2, "Light", "light", "2:1:1:2:3:3" },
42 { 3, "Medium", "medium", "3:2:2:2:3:3" },
43 { 4, "Strong", "strong", "7:7:7:5:5:5" },
44 { 0, NULL, NULL, NULL },
45 // Legacy and aliases go below the NULL
46 { 2, "Weak", "weak", "2:1:1:2:3:3" },
47 { 2, "Default", "default", "2:1:1:2:3:3" },
50 static hb_filter_param_t detelecine_presets[] =
52 { 0, "Off", "off", hb_filter_off },
53 { 1, "Custom", "custom", NULL },
54 { 2, "Default", "default", "" },
55 { 0, NULL, NULL, NULL }
58 static hb_filter_param_t decomb_presets[] =
60 { 0, "Off", "off", hb_filter_off },
61 { 1, "Custom", "custom", NULL },
62 { 2, "Default", "default", "" },
63 { 3, "Fast", "fast", "7:2:6:9:1:80" },
64 { 4, "Bob", "bob", "455" },
65 { 0, NULL, NULL, NULL }
68 static hb_filter_param_t deinterlace_presets[] =
70 { 0, "Off", "off", hb_filter_off },
71 { 1, "Custom", "custom", NULL },
72 { 2, "Fast", "fast", "0:-1:-1:0:1" },
73 { 3, "Slow", "slow", "1:-1:-1:0:1" },
74 { 4, "Slower", "slower", "3:-1:-1:0:1" },
75 { 5, "Bob", "bob", "15:-1:-1:0:1" },
76 { 0, NULL, NULL, NULL },
77 { 2, "Default", "default", "0:-1:-1:0:1" }
80 typedef struct
82 int filter_id;
83 hb_filter_param_t *presets;
84 hb_filter_param_t *tunes;
85 int count;
86 } filter_param_map_t;
88 static filter_param_map_t param_map[] =
90 { HB_FILTER_NLMEANS, nlmeans_presets, nlmeans_tunes,
91 sizeof(nlmeans_presets) / sizeof(hb_filter_param_t) },
93 { HB_FILTER_HQDN3D, hqdn3d_presets, NULL,
94 sizeof(hqdn3d_presets) / sizeof(hb_filter_param_t) },
96 { HB_FILTER_DETELECINE, detelecine_presets, NULL,
97 sizeof(detelecine_presets) / sizeof(hb_filter_param_t) },
99 { HB_FILTER_DECOMB, decomb_presets, NULL,
100 sizeof(decomb_presets) / sizeof(hb_filter_param_t) },
102 { HB_FILTER_DEINTERLACE, deinterlace_presets, NULL,
103 sizeof(deinterlace_presets) / sizeof(hb_filter_param_t) },
105 { HB_FILTER_INVALID, NULL, NULL, 0 }
108 /* NL-means presets and tunes
110 * Presets adjust strength:
111 * ultralight - visually transparent
112 * light
113 * medium
114 * strong
116 * Tunes adjust settings to the specified content type:
117 * none
118 * film - most content, live action
119 * grain - like film but preserves luma grain
120 * highmotion - like film but avoids color smearing with stronger settings
121 * animation - cel animation such as cartoons, anime
123 static char * generate_nlmeans_settings(const char *preset, const char *tune)
125 char *opt = NULL;
127 if (preset == NULL)
128 return NULL;
130 if (!strcasecmp(preset, "custom") && tune != NULL)
132 return strdup(tune);
134 if (!strcasecmp(preset, "ultralight") ||
135 !strcasecmp(preset, "light") ||
136 !strcasecmp(preset, "medium") ||
137 !strcasecmp(preset, "strong"))
139 double strength[2],
140 origin_tune[2];
141 int patch_size[2],
142 range[2],
143 frames[2],
144 prefilter[2];
146 if (tune == NULL || !strcasecmp(tune, "none"))
148 strength[0] = strength[1] = 6;
149 origin_tune[0] = origin_tune[1] = 1;
150 patch_size[0] = patch_size[1] = 7;
151 range[0] = range[1] = 3;
152 frames[0] = frames[1] = 2;
153 prefilter[0] = prefilter[1] = 0;
154 if (!strcasecmp(preset, "ultralight"))
156 strength[0] = strength[1] = 1.5;
158 else if (!strcasecmp(preset, "light"))
160 strength[0] = strength[1] = 3;
162 else if (!strcasecmp(preset, "strong"))
164 strength[0] = strength[1] = 10;
167 else if (!strcasecmp(tune, "film"))
169 strength[0] = 6; strength[1] = 8;
170 origin_tune[0] = origin_tune[1] = 0.8;
171 patch_size[0] = patch_size[1] = 7;
172 range[0] = range[1] = 3;
173 frames[0] = frames[1] = 2;
174 prefilter[0] = prefilter[1] = 0;
175 if (!strcasecmp(preset, "ultralight"))
177 strength[0] = 1.5; strength[1] = 2.4;
178 origin_tune[0] = 0.9; origin_tune[1] = 0.9;
180 else if (!strcasecmp(preset, "light"))
182 strength[0] = 3; strength[1] = 4;
183 origin_tune[0] = 0.9; origin_tune[1] = 0.9;
185 else if (!strcasecmp(preset, "strong"))
187 strength[0] = 8; strength[1] = 10;
188 origin_tune[0] = 0.6; origin_tune[1] = 0.6;
191 else if (!strcasecmp(tune, "grain"))
193 strength[0] = 0; strength[1] = 6;
194 origin_tune[0] = origin_tune[1] = 0.8;
195 patch_size[0] = patch_size[1] = 7;
196 range[0] = range[1] = 3;
197 frames[0] = frames[1] = 2;
198 prefilter[0] = prefilter[1] = 0;
199 if (!strcasecmp(preset, "ultralight"))
201 strength[0] = 0; strength[1] = 2.4;
202 origin_tune[0] = 0.9; origin_tune[1] = 0.9;
204 else if (!strcasecmp(preset, "light"))
206 strength[0] = 0; strength[1] = 3.5;
207 origin_tune[0] = 0.9; origin_tune[1] = 0.9;
209 else if (!strcasecmp(preset, "strong"))
211 strength[0] = 0; strength[1] = 8;
212 origin_tune[0] = 0.6; origin_tune[1] = 0.6;
215 else if (!strcasecmp(tune, "highmotion"))
217 strength[0] = 6; strength[1] = 6;
218 origin_tune[0] = 0.8; origin_tune[1] = 0.7;
219 patch_size[0] = 7; patch_size[1] = 7;
220 range[0] = 3; range[1] = 5;
221 frames[0] = 2; frames[1] = 1;
222 prefilter[0] = 0; prefilter[1] = 0;
223 if (!strcasecmp(preset, "ultralight"))
225 strength[0] = 1.5; strength[1] = 2.4;
226 origin_tune[0] = 0.9; origin_tune[1] = 0.9;
228 else if (!strcasecmp(preset, "light"))
230 strength[0] = 3; strength[1] = 3.25;
231 origin_tune[0] = 0.9; origin_tune[1] = 0.8;
233 else if (!strcasecmp(preset, "strong"))
235 strength[0] = 8; strength[1] = 6.75;
236 origin_tune[0] = 0.6; origin_tune[1] = 0.5;
239 else if (!strcasecmp(tune, "animation"))
241 strength[0] = 5; strength[1] = 4;
242 origin_tune[0] = origin_tune[1] = 0.15;
243 patch_size[0] = patch_size[1] = 5;
244 range[0] = range[1] = 7;
245 frames[0] = frames[1] = 4;
246 prefilter[0] = prefilter[1] = 0;
247 if (!strcasecmp(preset, "ultralight"))
249 strength[0] = 2.5; strength[1] = 2;
250 frames[0] = 2; frames[1] = 2;
252 else if (!strcasecmp(preset, "light"))
254 strength[0] = 3; strength[1] = 2.25;
255 frames[0] = 3; frames[1] = 3;
257 else if (!strcasecmp(preset, "strong"))
259 strength[0] = 10; strength[1] = 8;
262 else
264 fprintf(stderr, "Unrecognized nlmeans tune (%s).\n", tune);
265 return NULL;
268 opt = hb_strdup_printf("%lf:%lf:%d:%d:%d:%d:%lf:%lf:%d:%d:%d:%d",
269 strength[0], origin_tune[0], patch_size[0],
270 range[0], frames[0], prefilter[0],
271 strength[1], origin_tune[1], patch_size[1],
272 range[1], frames[1], prefilter[1]);
276 else
278 opt = strdup(preset);
279 if (tune != NULL)
281 fprintf(stderr, "Custom nlmeans parameters specified; ignoring nlmeans tune (%s).\n", tune);
285 return opt;
288 int hb_validate_param_string(const char *regex_pattern, const char *param_string)
290 regex_t regex_temp;
292 if (regcomp(&regex_temp, regex_pattern, REG_EXTENDED) == 0)
294 if (regexec(&regex_temp, param_string, 0, NULL, 0) == 0)
296 regfree(&regex_temp);
297 return 0;
300 else
302 fprintf(stderr, "hb_validate_param_string: Error compiling regex for pattern (%s).\n", param_string);
305 regfree(&regex_temp);
306 return 1;
309 int hb_validate_filter_settings(int filter_id, const char *filter_param)
311 if (filter_param == NULL)
312 return 0;
314 // Regex matches "number" followed by one or more ":number", where number is int or float
315 const char *hb_colon_separated_params_regex = "^(((([\\-])?[0-9]+([.,][0-9]+)?)|(([\\-])?[.,][0-9]+))((:((([\\-])?[0-9]+([,.][0-9]+)?)|(([\\-])?[,.][0-9]+)))+)?)$";
317 const char *regex_pattern = NULL;
319 switch (filter_id)
321 case HB_FILTER_ROTATE:
322 case HB_FILTER_DEBLOCK:
323 case HB_FILTER_DETELECINE:
324 case HB_FILTER_DECOMB:
325 case HB_FILTER_DEINTERLACE:
326 case HB_FILTER_NLMEANS:
327 case HB_FILTER_HQDN3D:
328 if (filter_param[0] == 0)
330 return 0;
332 regex_pattern = hb_colon_separated_params_regex;
333 break;
334 default:
335 fprintf(stderr, "hb_validate_filter_settings: Unrecognized filter (%d).\n",
336 filter_id);
337 return 1;
338 break;
341 if (hb_validate_param_string(regex_pattern, filter_param) == 0)
343 return 0;
345 return 1;
348 static hb_filter_param_t*
349 filter_param_get_presets_internal(int filter_id, int *count)
351 int ii;
352 for (ii = 0; param_map[ii].filter_id != HB_FILTER_INVALID; ii++)
354 if (param_map[ii].filter_id == filter_id)
356 if (count != NULL)
357 *count = param_map[ii].count;
358 return param_map[ii].presets;
361 return NULL;
364 static hb_filter_param_t*
365 filter_param_get_tunes_internal(int filter_id, int *count)
367 int ii;
368 for (ii = 0; param_map[ii].filter_id != HB_FILTER_INVALID; ii++)
370 if (param_map[ii].filter_id == filter_id)
372 if (count != NULL)
373 *count = param_map[ii].count;
374 return param_map[ii].tunes;
377 return NULL;
380 static hb_filter_param_t*
381 filter_param_get_entry(hb_filter_param_t *table, const char *name, int count)
383 if (table == NULL || name == NULL)
384 return NULL;
386 int ii;
387 for (ii = 0; ii < count; ii++)
389 if ((table[ii].name != NULL && !strcasecmp(name, table[ii].name)) ||
390 (table[ii].short_name != NULL &&
391 !strcasecmp(name, table[ii].short_name)))
393 return &table[ii];
396 return NULL;
399 static hb_filter_param_t*
400 filter_param_get_entry_by_index(hb_filter_param_t *table, int index, int count)
402 if (table == NULL)
403 return NULL;
405 int ii;
406 for (ii = 0; ii < count; ii++)
408 if (table[ii].name != NULL && table[ii].index == index)
410 return &table[ii];
413 return NULL;
416 static char *
417 generate_generic_settings(int filter_id, const char *preset, const char *tune)
419 char *opt = NULL;
420 int preset_count, tune_count;
421 hb_filter_param_t *preset_table, *tune_table;
422 hb_filter_param_t *preset_entry, *tune_entry;
424 preset_table = filter_param_get_presets_internal(filter_id, &preset_count);
425 tune_table = filter_param_get_tunes_internal(filter_id, &tune_count);
426 preset_entry = filter_param_get_entry(preset_table, preset, preset_count);
427 tune_entry = filter_param_get_entry(tune_table, tune, tune_count);
428 if (preset_entry != NULL)
430 if (!strcasecmp(preset, "custom") && tune != NULL)
432 opt = strdup(tune);
434 else if (preset_entry->settings == hb_filter_off)
436 return (char*)hb_filter_off;
438 else if (preset_entry->settings != NULL)
440 opt = hb_strdup_printf("%s%s%s", preset_entry->settings,
441 tune_entry != NULL ? ":" : "",
442 tune_entry != NULL ? tune_entry->settings : "");
445 else if (preset != NULL)
447 return strdup(preset);
449 return opt;
452 // Legacy: old presets store filter falues as indexes :(
453 static char *
454 generate_generic_settings_by_index(int filter_id, int preset,
455 const char *custom)
457 char *opt = NULL;
458 int preset_count;
459 hb_filter_param_t *preset_table;
460 hb_filter_param_t *preset_entry;
462 preset_table = filter_param_get_presets_internal(filter_id, &preset_count);
463 preset_entry = filter_param_get_entry_by_index(preset_table, preset,
464 preset_count);
465 if (preset_entry != NULL)
467 if (!strcasecmp(preset_entry->short_name, "custom") && custom != NULL)
469 opt = strdup(custom);
471 else if (preset_entry->settings == hb_filter_off)
473 return (char*)hb_filter_off;
475 else if (preset_entry->settings != NULL)
477 opt = hb_strdup_printf("%s", preset_entry->settings);
480 return opt;
483 char *
484 hb_generate_filter_settings_by_index(int filter_id, int preset,
485 const char *custom)
487 char *filter_param = NULL;
489 switch (filter_id)
491 case HB_FILTER_ROTATE:
492 if (preset <= 0)
493 filter_param = (char*)hb_filter_off;
494 else
495 filter_param = hb_strdup_printf("%d", preset);
496 break;
497 case HB_FILTER_DEBLOCK:
498 if (preset < 5)
499 filter_param = (char*)hb_filter_off;
500 else
501 filter_param = hb_strdup_printf("%d", preset);
502 break;
503 case HB_FILTER_DECOMB:
504 case HB_FILTER_DEINTERLACE:
505 case HB_FILTER_DETELECINE:
506 case HB_FILTER_HQDN3D:
507 filter_param = generate_generic_settings_by_index(filter_id,
508 preset, custom);
509 break;
510 default:
511 fprintf(stderr,
512 "hb_generate_filter_settings: Unrecognized filter (%d).\n",
513 filter_id);
514 break;
517 if (filter_param == hb_filter_off)
518 return filter_param;
520 if (filter_param != NULL &&
521 hb_validate_filter_settings(filter_id, filter_param) == 0)
523 return filter_param;
525 free(filter_param);
526 return NULL;
529 char *
530 hb_generate_filter_settings(int filter_id, const char *preset, const char *tune)
532 char *filter_param = NULL;
534 switch (filter_id)
536 case HB_FILTER_NLMEANS:
537 filter_param = generate_nlmeans_settings(preset, tune);
538 break;
539 case HB_FILTER_ROTATE:
540 if (atoi(preset) == 0)
541 filter_param = (char*)hb_filter_off;
542 else
543 filter_param = strdup(preset);
544 break;
545 case HB_FILTER_DEBLOCK:
546 if (atoi(preset) < 5)
547 filter_param = (char*)hb_filter_off;
548 else
549 filter_param = strdup(preset);
550 break;
551 case HB_FILTER_DECOMB:
552 case HB_FILTER_DEINTERLACE:
553 case HB_FILTER_DETELECINE:
554 case HB_FILTER_HQDN3D:
555 filter_param = generate_generic_settings(filter_id, preset, tune);
556 break;
557 default:
558 fprintf(stderr,
559 "hb_generate_filter_settings: Unrecognized filter (%d).\n",
560 filter_id);
561 break;
564 if (filter_param == hb_filter_off)
565 return filter_param;
567 if (filter_param != NULL &&
568 hb_validate_filter_settings(filter_id, filter_param) == 0)
570 return filter_param;
572 free(filter_param);
573 return NULL;
577 hb_validate_filter_preset(int filter_id, const char *preset, const char *tune)
579 if (preset == NULL && tune == NULL)
580 return 1;
582 int preset_count, tune_count;
583 hb_filter_param_t *preset_table, *tune_table;
584 hb_filter_param_t *preset_entry, *tune_entry;
586 preset_table = filter_param_get_presets_internal(filter_id, &preset_count);
587 preset_entry = filter_param_get_entry(preset_table, preset, preset_count);
588 if (preset_entry == NULL || preset_entry->name == NULL)
589 return 1;
590 if (tune != NULL)
592 if (!strcasecmp(preset, "custom") && tune != NULL)
594 return hb_validate_filter_settings(filter_id, tune);
596 tune_table = filter_param_get_tunes_internal(filter_id, &tune_count);
597 tune_entry = filter_param_get_entry(tune_table, tune, tune_count);
598 if (tune_entry == NULL)
599 return 1;
601 return 0;
605 hb_validate_filter_preset_by_index(int filter_id, int preset, const char *tune)
607 int preset_count, tune_count;
608 hb_filter_param_t *preset_table, *tune_table;
609 hb_filter_param_t *preset_entry, *tune_entry;
611 preset_table = filter_param_get_presets_internal(filter_id, &preset_count);
612 preset_entry = filter_param_get_entry_by_index(preset_table, preset, preset_count);
613 if (preset_entry == NULL || preset_entry->name == NULL)
614 return 1;
615 if (tune != NULL)
617 if (!strcasecmp(preset_entry->short_name, "custom") && tune != NULL)
619 return hb_validate_filter_settings(filter_id, tune);
621 tune_table = filter_param_get_tunes_internal(filter_id, &tune_count);
622 tune_entry = filter_param_get_entry(tune_table, tune, tune_count);
623 if (tune_entry == NULL)
624 return 1;
626 return 0;
630 hb_filter_preset_index(int filter_id, const char *preset)
632 if (preset == NULL)
633 return -1;
635 int preset_count;
636 hb_filter_param_t *preset_table;
637 hb_filter_param_t *preset_entry;
639 preset_table = filter_param_get_presets_internal(filter_id, &preset_count);
640 preset_entry = filter_param_get_entry(preset_table, preset, preset_count);
641 if (preset_entry == NULL)
642 return -1;
643 return preset_entry->index;
647 hb_filter_tune_index(int filter_id, const char *tune)
649 if (tune == NULL)
650 return -1;
652 int tune_count;
653 hb_filter_param_t *tune_table;
654 hb_filter_param_t *tune_entry;
656 tune_table = filter_param_get_tunes_internal(filter_id, &tune_count);
657 tune_entry = filter_param_get_entry(tune_table, tune, tune_count);
658 if (tune_entry == NULL)
660 return -1;
662 return tune_entry->index;
665 hb_filter_param_t* hb_filter_param_get_presets(int filter_id)
667 return filter_param_get_presets_internal(filter_id, NULL);
670 hb_filter_param_t* hb_filter_param_get_tunes(int filter_id)
672 return filter_param_get_tunes_internal(filter_id, NULL);