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
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" }
83 hb_filter_param_t
*presets
;
84 hb_filter_param_t
*tunes
;
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
116 * Tunes adjust settings to the specified content type:
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
)
130 if (!strcasecmp(preset
, "custom") && tune
!= NULL
)
134 if (!strcasecmp(preset
, "ultralight") ||
135 !strcasecmp(preset
, "light") ||
136 !strcasecmp(preset
, "medium") ||
137 !strcasecmp(preset
, "strong"))
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;
264 fprintf(stderr
, "Unrecognized nlmeans tune (%s).\n", tune
);
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]);
278 opt
= strdup(preset
);
281 fprintf(stderr
, "Custom nlmeans parameters specified; ignoring nlmeans tune (%s).\n", tune
);
288 int hb_validate_param_string(const char *regex_pattern
, const char *param_string
)
292 if (regcomp(®ex_temp
, regex_pattern
, REG_EXTENDED
) == 0)
294 if (regexec(®ex_temp
, param_string
, 0, NULL
, 0) == 0)
296 regfree(®ex_temp
);
302 fprintf(stderr
, "hb_validate_param_string: Error compiling regex for pattern (%s).\n", param_string
);
305 regfree(®ex_temp
);
309 int hb_validate_filter_settings(int filter_id
, const char *filter_param
)
311 if (filter_param
== NULL
)
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
;
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)
332 regex_pattern
= hb_colon_separated_params_regex
;
335 fprintf(stderr
, "hb_validate_filter_settings: Unrecognized filter (%d).\n",
341 if (hb_validate_param_string(regex_pattern
, filter_param
) == 0)
348 static hb_filter_param_t
*
349 filter_param_get_presets_internal(int filter_id
, int *count
)
352 for (ii
= 0; param_map
[ii
].filter_id
!= HB_FILTER_INVALID
; ii
++)
354 if (param_map
[ii
].filter_id
== filter_id
)
357 *count
= param_map
[ii
].count
;
358 return param_map
[ii
].presets
;
364 static hb_filter_param_t
*
365 filter_param_get_tunes_internal(int filter_id
, int *count
)
368 for (ii
= 0; param_map
[ii
].filter_id
!= HB_FILTER_INVALID
; ii
++)
370 if (param_map
[ii
].filter_id
== filter_id
)
373 *count
= param_map
[ii
].count
;
374 return param_map
[ii
].tunes
;
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
)
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
)))
399 static hb_filter_param_t
*
400 filter_param_get_entry_by_index(hb_filter_param_t
*table
, int index
, int count
)
406 for (ii
= 0; ii
< count
; ii
++)
408 if (table
[ii
].name
!= NULL
&& table
[ii
].index
== index
)
417 generate_generic_settings(int filter_id
, const char *preset
, const char *tune
)
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
)
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
);
452 // Legacy: old presets store filter falues as indexes :(
454 generate_generic_settings_by_index(int filter_id
, int preset
,
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
,
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
);
484 hb_generate_filter_settings_by_index(int filter_id
, int preset
,
487 char *filter_param
= NULL
;
491 case HB_FILTER_ROTATE
:
493 filter_param
= (char*)hb_filter_off
;
495 filter_param
= hb_strdup_printf("%d", preset
);
497 case HB_FILTER_DEBLOCK
:
499 filter_param
= (char*)hb_filter_off
;
501 filter_param
= hb_strdup_printf("%d", preset
);
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
,
512 "hb_generate_filter_settings: Unrecognized filter (%d).\n",
517 if (filter_param
== hb_filter_off
)
520 if (filter_param
!= NULL
&&
521 hb_validate_filter_settings(filter_id
, filter_param
) == 0)
530 hb_generate_filter_settings(int filter_id
, const char *preset
, const char *tune
)
532 char *filter_param
= NULL
;
536 case HB_FILTER_NLMEANS
:
537 filter_param
= generate_nlmeans_settings(preset
, tune
);
539 case HB_FILTER_ROTATE
:
540 if (atoi(preset
) == 0)
541 filter_param
= (char*)hb_filter_off
;
543 filter_param
= strdup(preset
);
545 case HB_FILTER_DEBLOCK
:
546 if (atoi(preset
) < 5)
547 filter_param
= (char*)hb_filter_off
;
549 filter_param
= strdup(preset
);
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
);
559 "hb_generate_filter_settings: Unrecognized filter (%d).\n",
564 if (filter_param
== hb_filter_off
)
567 if (filter_param
!= NULL
&&
568 hb_validate_filter_settings(filter_id
, filter_param
) == 0)
577 hb_validate_filter_preset(int filter_id
, const char *preset
, const char *tune
)
579 if (preset
== NULL
&& tune
== NULL
)
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
)
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
)
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
)
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
)
630 hb_filter_preset_index(int filter_id
, const char *preset
)
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
)
643 return preset_entry
->index
;
647 hb_filter_tune_index(int filter_id
, const char *tune
)
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
)
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
);