WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / test / test.c
blob7aa8aad0aea063cd47c5841cee8fcdced4b7ae62
1 /* test.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 http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <signal.h>
13 #include <getopt.h>
14 #include <sys/time.h>
15 #include <time.h>
16 #include <unistd.h>
17 #include <inttypes.h>
19 #if defined( __MINGW32__ )
20 #include <windows.h>
21 #include <conio.h>
22 #endif
24 #if defined( PTW32_STATIC_LIB )
25 #include <pthread.h>
26 #endif
28 #include "hb.h"
29 #include "lang.h"
30 #include "parsecsv.h"
31 #include "openclwrapper.h"
33 #ifdef USE_QSV
34 #include "qsv_common.h"
35 #endif
37 #if defined( __APPLE_CC__ )
38 #import <CoreServices/CoreServices.h>
39 #include <IOKit/IOKitLib.h>
40 #include <IOKit/storage/IOMedia.h>
41 #include <IOKit/storage/IODVDMedia.h>
42 #endif
44 /* Options */
45 static int debug = HB_DEBUG_ALL;
46 static int update = 0;
47 static int dvdnav = 1;
48 static char * input = NULL;
49 static char * output = NULL;
50 static char * format = NULL;
51 static int titleindex = 1;
52 static int titlescan = 0;
53 static int main_feature = 0;
54 static char * native_language = NULL;
55 static int native_dub = 0;
56 static int twoPass = 0;
57 static int deinterlace_disable = 0;
58 static int deinterlace_custom = 0;
59 static char * deinterlace = NULL;
60 static int deblock_disable = 0;
61 static char * deblock = NULL;
62 static int hqdn3d_disable = 0;
63 static int hqdn3d_custom = 0;
64 static char * hqdn3d = NULL;
65 static int nlmeans_disable = 0;
66 static int nlmeans_custom = 0;
67 static char * nlmeans = NULL;
68 static char * nlmeans_tune = NULL;
69 static int detelecine_disable = 0;
70 static int detelecine_custom = 0;
71 static char * detelecine = NULL;
72 static int decomb_disable = 0;
73 static int decomb_custom = 0;
74 static char * decomb = NULL;
75 static char * rotate = NULL;
76 static int grayscale = -1;
77 static char * vcodec = NULL;
78 static int audio_all = -1;
79 static char ** audio_copy_list = NULL;
80 static char ** audio_lang_list = NULL;
81 static char ** atracks = NULL;
82 static char ** acodecs = NULL;
83 static char ** abitrates = NULL;
84 static char ** aqualities = NULL;
85 static char ** arates = NULL;
86 static char ** mixdowns = NULL;
87 static char ** normalize_mix_level = NULL;
88 static char ** audio_dither = NULL;
89 static char ** dynamic_range_compression = NULL;
90 static char ** audio_gain = NULL;
91 static char ** acompressions = NULL;
92 static char * acodec_fallback = NULL;
93 static char ** anames = NULL;
94 static char ** subtitle_lang_list = NULL;
95 static char ** subtracks = NULL;
96 static char ** subforce = NULL;
97 static int subtitle_all = -1;
98 static int subburn = 0;
99 static int subburn_native = 0;
100 static int subdefault = 0;
101 static char ** srtfile = NULL;
102 static char ** srtcodeset = NULL;
103 static char ** srtoffset = NULL;
104 static char ** srtlang = NULL;
105 static int srtdefault = -1;
106 static int srtburn = -1;
107 static int width = 0;
108 static int height = 0;
109 static int crop[4] = { -1,-1,-1,-1 };
110 static int loose_crop = -1;
111 static char * vrate = NULL;
112 static float vquality = -1.0;
113 static int vbitrate = 0;
114 static int mux = 0;
115 static int anamorphic_mode = -1;
116 static int modulus = 0;
117 static int par_height = -1;
118 static int par_width = -1;
119 static int display_width = -1;
120 static int keep_display_aspect = 0;
121 static int itu_par = -1;
122 static int angle = 0;
123 static int chapter_start = 0;
124 static int chapter_end = 0;
125 static int chapter_markers = -1;
126 static char * marker_file = NULL;
127 static char * encoder_preset = NULL;
128 static char * encoder_tune = NULL;
129 static char * encoder_profile = NULL;
130 static char * encoder_level = NULL;
131 static char * advanced_opts = NULL;
132 static int maxHeight = 0;
133 static int maxWidth = 0;
134 static int fastfirstpass = 0;
135 static char * preset_export_name = NULL;
136 static char * preset_export_desc = NULL;
137 static char * preset_export_file = NULL;
138 static char * preset_name = NULL;
139 static int cfr = -1;
140 static int mp4_optimize = -1;
141 static int ipod_atom = -1;
142 static int color_matrix_code = -1;
143 static int preview_count = 10;
144 static int store_previews = 0;
145 static int start_at_preview = 0;
146 static int64_t start_at_pts = 0;
147 static int start_at_frame = 0;
148 static int64_t stop_at_pts = 0;
149 static int stop_at_frame = 0;
150 static uint64_t min_title_duration = 10;
151 static int use_opencl = -1;
152 static int use_hwd = -1;
153 #ifdef USE_QSV
154 static int qsv_async_depth = -1;
155 static int qsv_decode = -1;
156 #endif
158 /* Exit cleanly on Ctrl-C */
159 static volatile hb_error_code done_error = HB_ERROR_NONE;
160 static volatile int die = 0;
161 static void SigHandler( int );
163 /* Utils */
164 static void ShowHelp();
165 static void ShowCommands()
167 fprintf(stdout, "\nCommands:\n");
168 fprintf(stdout, " [h]elp Show this message\n");
169 fprintf(stdout, " [q]uit Exit HandBrakeCLI\n");
170 fprintf(stdout, " [p]ause Pause encoding\n");
171 fprintf(stdout, " [r]esume Resume encoding\n");
174 static int ParseOptions( int argc, char ** argv );
175 static int CheckOptions( int argc, char ** argv );
176 static int HandleEvents( hb_handle_t * h, hb_dict_t *preset_dict );
177 static hb_dict_t * PreparePreset( const char *preset_name );
178 static hb_dict_t * PrepareJob( hb_handle_t *h, hb_title_t *title,
179 hb_dict_t *preset_dict );
181 static int str_vlen(char **strv);
182 static void str_vfree( char **strv );
183 static char** str_split( char *str, char delem );
185 static void print_string_list(FILE *out, const char* const *list, const char *prefix);
187 #ifdef __APPLE_CC__
188 static char* bsd_name_for_path(char *path);
189 static int device_is_dvd(char *device);
190 static io_service_t get_iokit_service( char *device );
191 static int is_dvd_service( io_service_t service );
192 static int is_whole_media_service( io_service_t service );
193 #endif
195 /* Only print the "Muxing..." message once */
196 static int show_mux_warning = 1;
198 /****************************************************************************
199 * hb_error_handler
201 * When using the CLI just display using hb_log as we always did in the past
202 * make sure that we prefix with a nice ERROR message to catch peoples eyes.
203 ****************************************************************************/
204 static void hb_cli_error_handler ( const char *errmsg )
206 fprintf( stderr, "ERROR: %s\n", errmsg );
209 static int get_argv_utf8(int *argc_ptr, char ***argv_ptr)
211 #if defined( __MINGW32__ )
212 int ret = 0;
213 int argc;
214 char **argv;
216 wchar_t **argv_utf16 = CommandLineToArgvW(GetCommandLineW(), &argc);
217 if (argv_utf16)
219 int i;
220 int offset = (argc+1) * sizeof(char*);
221 int size = offset;
223 for(i = 0; i < argc; i++)
224 size += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, NULL, 0, NULL, NULL );
226 argv = malloc(size);
227 if (argv != NULL)
229 for (i = 0; i < argc; i++)
231 argv[i] = (char*)argv + offset;
232 offset += WideCharToMultiByte(CP_UTF8, 0, argv_utf16[i], -1, argv[i], size-offset, NULL, NULL);
234 argv[argc] = NULL;
235 ret = 1;
237 LocalFree(argv_utf16);
239 if (ret)
241 *argc_ptr = argc;
242 *argv_ptr = argv;
244 return ret;
245 #else
246 // On other systems, assume command line is already utf8
247 return 1;
248 #endif
251 int main( int argc, char ** argv )
253 hb_handle_t * h;
254 int build;
255 char * version;
257 hb_global_init();
258 hb_presets_builtin_update();
260 /* Init libhb */
261 h = hb_init(4, 0); // Show all logging until debug level is parsed
263 // Get utf8 command line if windows
264 get_argv_utf8(&argc, &argv);
266 /* Parse command line */
267 if( ParseOptions( argc, argv ) ||
268 CheckOptions( argc, argv ) )
270 return 1;
273 hb_log_level_set(h, debug);
275 /* Register our error handler */
276 hb_register_error_handler(&hb_cli_error_handler);
278 hb_dvd_set_dvdnav( dvdnav );
280 /* Show version */
281 fprintf( stderr, "%s - %s - %s\n",
282 HB_PROJECT_TITLE, HB_PROJECT_BUILD_TITLE, HB_PROJECT_URL_WEBSITE );
284 /* Check for update */
285 if( update )
287 hb_update_poll(h);
288 if( ( build = hb_check_update( h, &version ) ) > -1 )
290 fprintf( stderr, "You are using an old version of "
291 "HandBrake.\nLatest is %s (build %d).\n", version,
292 build );
294 else
296 fprintf( stderr, "Your version of HandBrake is up to "
297 "date.\n" );
299 hb_close( &h );
300 hb_global_close();
301 return 0;
304 /* Geeky */
305 fprintf( stderr, "%d CPU%s detected\n", hb_get_cpu_count(),
306 hb_get_cpu_count() > 1 ? "s" : "" );
308 /* Exit ASAP on Ctrl-C */
309 signal( SIGINT, SigHandler );
311 // Apply all command line overrides to the preset that are possible.
312 // Some command line options are applied later to the job
313 // (e.g. chapter names, explicit audio & subtitle tracks).
314 hb_dict_t *preset_dict = PreparePreset(preset_name);
315 if (preset_dict == NULL)
317 // An appropriate error message should have already
318 // been spilled by PreparePreset.
319 return 1;
322 if (preset_export_name != NULL)
324 hb_dict_set(preset_dict, "PresetName",
325 hb_value_string(preset_export_name));
326 if (preset_export_desc != NULL)
328 hb_dict_set(preset_dict, "PresetDescription",
329 hb_value_string(preset_export_desc));
331 if (preset_export_file != NULL)
333 hb_presets_write_json(preset_dict, preset_export_file);
335 else
337 char *json;
338 json = hb_presets_package_json(preset_dict);
339 fprintf(stdout, "%s\n", json);
341 // If the user requested to export a preset, but not to
342 // transcode or scan a file, exit here.
343 if (input == NULL || (!titlescan && titleindex != 0 && output == NULL))
345 hb_value_free(&preset_dict);
346 return 0;
350 /* Feed libhb with a DVD to scan */
351 fprintf( stderr, "Opening %s...\n", input );
353 if (main_feature) {
355 * We need to scan for all the titles in order to find the main feature
357 titleindex = 0;
360 hb_system_sleep_prevent(h);
362 // FIXME: When hardware decode is enabled, the scan must be performed
363 // with hardware decode enabled because the decoder context used during
364 // encoding phase comes from the context used during scan. This is
365 // broken by design and I would very much like to fix this someday.
366 hb_hwd_set_enable(h, hb_value_get_bool(
367 hb_dict_get(preset_dict, "VideoHWDecode")));
368 hb_scan(h, input, titleindex, preview_count, store_previews,
369 min_title_duration * 90000LL);
371 /* Wait... */
372 while( !die )
374 #if defined( __MINGW32__ )
375 if( _kbhit() ) {
376 switch( _getch() )
378 case 0x03: /* ctrl-c */
379 case 'q':
380 fprintf( stdout, "\nEncoding Quit by user command\n" );
381 done_error = HB_ERROR_CANCELED;
382 die = 1;
383 break;
384 case 'p':
385 fprintf(stdout,
386 "\nEncoding Paused by user command, 'r' to resume\n");
387 hb_pause(h);
388 hb_system_sleep_allow(h);
389 break;
390 case 'r':
391 hb_system_sleep_prevent(h);
392 hb_resume(h);
393 break;
394 case 'h':
395 ShowCommands();
396 break;
399 hb_snooze( 200 );
400 #elif !defined(SYS_BEOS)
401 fd_set fds;
402 struct timeval tv;
403 int ret;
404 char buf[257];
406 tv.tv_sec = 0;
407 tv.tv_usec = 100000;
409 FD_ZERO( &fds );
410 FD_SET( STDIN_FILENO, &fds );
411 ret = select( STDIN_FILENO + 1, &fds, NULL, NULL, &tv );
413 if( ret > 0 )
415 int size = 0;
417 while( size < 256 &&
418 read( STDIN_FILENO, &buf[size], 1 ) > 0 )
420 if( buf[size] == '\n' )
422 break;
424 size++;
427 if( size >= 256 || buf[size] == '\n' )
429 switch( buf[0] )
431 case 'q':
432 fprintf( stdout, "\nEncoding Quit by user command\n" );
433 done_error = HB_ERROR_CANCELED;
434 die = 1;
435 break;
436 case 'p':
437 fprintf(stdout,
438 "\nEncoding Paused by user command, 'r' to resume\n");
439 hb_pause(h);
440 hb_system_sleep_allow(h);
441 break;
442 case 'r':
443 hb_system_sleep_prevent(h);
444 hb_resume(h);
445 break;
446 case 'h':
447 ShowCommands();
448 break;
452 hb_snooze( 200 );
453 #else
454 hb_snooze( 200 );
455 #endif
457 HandleEvents( h, preset_dict );
460 /* Clean up */
461 hb_value_free(&preset_dict);
462 hb_close(&h);
463 hb_global_close();
464 str_vfree(audio_copy_list);
465 str_vfree(abitrates);
466 str_vfree(acompressions);
467 str_vfree(aqualities);
468 str_vfree(audio_dither);
469 str_vfree(acodecs);
470 str_vfree(arates);
471 str_vfree(atracks);
472 str_vfree(audio_lang_list);
473 str_vfree(audio_gain);
474 str_vfree(dynamic_range_compression);
475 str_vfree(mixdowns);
476 str_vfree(subtitle_lang_list);
477 str_vfree(subtracks);
478 free(acodec_fallback);
479 free(native_language);
480 free(format);
481 free(input);
482 free(output);
483 free(preset_name);
484 free(encoder_preset);
485 free(encoder_tune);
486 free(advanced_opts);
487 free(encoder_profile);
488 free(encoder_level);
489 free(rotate);
490 free(deblock);
491 free(detelecine);
492 free(deinterlace);
493 free(decomb);
494 free(hqdn3d);
495 free(nlmeans);
496 free(nlmeans_tune);
497 free(preset_export_name);
498 free(preset_export_desc);
499 free(preset_export_file);
501 // write a carriage return to stdout
502 // avoids overlap / line wrapping when stderr is redirected
503 fprintf(stdout, "\n");
504 fprintf(stderr, "HandBrake has exited.\n");
506 return done_error;
509 static void PrintTitleInfo( hb_title_t * title, int feature )
511 int i;
513 fprintf( stderr, "+ title %d:\n", title->index );
514 if ( title->index == feature )
516 fprintf( stderr, " + Main Feature\n" );
518 if ( title->type == HB_STREAM_TYPE || title->type == HB_FF_STREAM_TYPE )
520 fprintf( stderr, " + stream: %s\n", title->path );
522 else if ( title->type == HB_DVD_TYPE )
524 fprintf( stderr, " + vts %d, ttn %d, cells %d->%d (%"PRIu64" blocks)\n",
525 title->vts, title->ttn, title->cell_start, title->cell_end,
526 title->block_count );
528 else if( title->type == HB_BD_TYPE )
530 fprintf( stderr, " + playlist: %05d.MPLS\n", title->playlist );
532 if (title->angle_count > 1)
533 fprintf( stderr, " + angle(s) %d\n", title->angle_count );
534 fprintf( stderr, " + duration: %02d:%02d:%02d\n",
535 title->hours, title->minutes, title->seconds );
536 fprintf( stderr, " + size: %dx%d, pixel aspect: %d/%d, display aspect: %.2f, %.3f fps\n",
537 title->geometry.width, title->geometry.height,
538 title->geometry.par.num, title->geometry.par.den,
539 (float)title->dar.num / title->dar.den,
540 (float)title->vrate.num / title->vrate.den );
541 fprintf( stderr, " + autocrop: %d/%d/%d/%d\n", title->crop[0],
542 title->crop[1], title->crop[2], title->crop[3] );
544 fprintf(stderr, " + support opencl: %s\n", title->opencl_support ? "yes" : "no");
546 fprintf( stderr, " + chapters:\n" );
547 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
549 hb_chapter_t * chapter;
550 chapter = hb_list_item( title->list_chapter, i );
551 fprintf( stderr, " + %d: cells %d->%d, %"PRIu64" blocks, duration "
552 "%02d:%02d:%02d\n", chapter->index,
553 chapter->cell_start, chapter->cell_end,
554 chapter->block_count, chapter->hours, chapter->minutes,
555 chapter->seconds );
557 fprintf( stderr, " + audio tracks:\n" );
558 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
560 hb_audio_config_t *audio;
561 audio = hb_list_audio_config_item( title->list_audio, i );
562 if( ( audio->in.codec == HB_ACODEC_AC3 ) || ( audio->in.codec == HB_ACODEC_DCA) )
564 fprintf( stderr, " + %d, %s (iso639-2: %s), %dHz, %dbps\n",
565 i + 1,
566 audio->lang.description,
567 audio->lang.iso639_2,
568 audio->in.samplerate,
569 audio->in.bitrate );
571 else
573 fprintf( stderr, " + %d, %s (iso639-2: %s)\n",
574 i + 1,
575 audio->lang.description,
576 audio->lang.iso639_2 );
579 fprintf( stderr, " + subtitle tracks:\n" );
580 for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
582 hb_subtitle_t *subtitle;
583 subtitle = hb_list_item( title->list_subtitle, i );
584 fprintf( stderr, " + %d, %s (iso639-2: %s) (%s)(%s)\n",
585 i + 1, subtitle->lang,
586 subtitle->iso639_2,
587 (subtitle->format == TEXTSUB) ? "Text" : "Bitmap",
588 hb_subsource_name(subtitle->source));
591 if(title->detected_interlacing)
593 /* Interlacing was found in half or more of the preview frames */
594 fprintf( stderr, " + combing detected, may be interlaced or telecined\n");
599 static void PrintTitleSetInfo( hb_title_set_t * title_set )
601 int i;
602 hb_title_t * title;
604 for( i = 0; i < hb_list_count( title_set->list_title ); i++ )
606 title = hb_list_item( title_set->list_title, i );
607 PrintTitleInfo( title, title_set->feature );
611 static int test_sub_list( char ** list, int pos )
613 int i;
615 if ( list == NULL || pos == 0 )
616 return 0;
618 if ( list[0] == NULL && pos == 1 )
619 return 1;
621 for ( i = 0; list[i] != NULL; i++ )
623 int idx = strtol( list[i], NULL, 0 );
624 if ( idx == pos )
625 return 1;
627 return 0;
630 void write_chapter_names(hb_dict_t *job_dict, const char *marker_file)
632 if (marker_file == NULL)
633 return;
635 hb_csv_file_t * file = hb_open_csv_file(marker_file);
636 hb_csv_cell_t * cell;
637 int row = 0;
639 if (file == NULL)
641 fprintf(stderr, "Cannot open chapter marker file, using defaults\n");
642 return;
644 fprintf(stderr, "Reading chapter markers from file %s\n", marker_file);
646 hb_value_array_t *chapter_array;
647 chapter_array = hb_dict_get(hb_dict_get(job_dict, "Destination"),
648 "ChapterList");
650 if (chapter_array == NULL)
651 return;
653 /* Parse the cells */
654 while (NULL != (cell = hb_read_next_cell(file)))
656 /* We have a chapter number */
657 if (cell->cell_col == 0)
659 row = cell->cell_row;
662 /* We have a chapter name */
663 if (cell->cell_col == 1 && row == cell->cell_row)
665 /* If we have a valid chapter, add chapter entry */
666 hb_dict_t *chapter_dict = hb_value_array_get(chapter_array, row);
667 if (chapter_dict != NULL)
669 hb_dict_set(chapter_dict, "Name",
670 hb_value_string(cell->cell_text));
673 hb_dispose_cell( cell );
675 hb_close_csv_file( file );
678 static void lang_list_remove(hb_value_array_t *list, const char *lang)
680 int count = hb_value_array_len(list);
681 int ii;
682 for (ii = count - 1; ii >= 0; ii--)
684 const char *tmp = hb_value_get_string(hb_value_array_get(list, ii));
685 if (!strncmp(lang, tmp, 4))
686 hb_value_array_remove(list, ii);
690 static int HandleEvents(hb_handle_t * h, hb_dict_t *preset_dict)
692 hb_state_t s;
694 hb_get_state( h, &s );
695 switch( s.state )
697 case HB_STATE_IDLE:
698 /* Nothing to do */
699 break;
701 #define p s.param.scanning
702 case HB_STATE_SCANNING:
703 /* Show what title is currently being scanned */
704 if (p.preview_cur)
706 fprintf(stderr, "\rScanning title %d of %d, preview %d, %.2f %%",
707 p.title_cur, p.title_count, p.preview_cur, 100 * p.progress);
709 else
711 fprintf(stderr, "\rScanning title %d of %d, %.2f %%",
712 p.title_cur, p.title_count, 100 * p.progress);
714 fflush(stderr);
715 break;
716 #undef p
718 case HB_STATE_SCANDONE:
720 hb_title_set_t * title_set;
721 hb_title_t * title;
723 title_set = hb_get_title_set( h );
724 if( !title_set || !hb_list_count( title_set->list_title ) )
726 /* No valid title, stop right there */
727 fprintf( stderr, "No title found.\n" );
728 done_error = HB_ERROR_WRONG_INPUT;
729 die = 1;
730 break;
732 if (main_feature)
734 int i;
735 int main_feature_idx=0;
736 int main_feature_pos=-1;
737 int main_feature_time=0;
738 int title_time;
740 fprintf( stderr, "Searching for main feature title...\n" );
742 for( i = 0; i < hb_list_count( title_set->list_title ); i++ )
744 title = hb_list_item( title_set->list_title, i );
745 title_time = (title->hours*60*60 ) + (title->minutes *60) + (title->seconds);
746 fprintf( stderr, " + Title (%d) index %d has length %dsec\n",
747 i, title->index, title_time );
748 if( main_feature_time < title_time )
750 main_feature_time = title_time;
751 main_feature_pos = i;
752 main_feature_idx = title->index;
754 if( title_set->feature == title->index )
756 main_feature_pos = i;
757 main_feature_idx = title->index;
758 break;
761 if( main_feature_pos == -1 )
763 fprintf( stderr, "No main feature title found.\n" );
764 done_error = HB_ERROR_WRONG_INPUT;
765 die = 1;
766 break;
768 titleindex = main_feature_idx;
769 fprintf(stderr, "Found main feature title %d\n",
770 main_feature_idx);
772 title = hb_list_item(title_set->list_title, main_feature_pos);
773 } else {
774 title = hb_list_item(title_set->list_title, 0);
777 if (!titleindex || titlescan)
779 /* Scan-only mode, print infos and exit */
780 PrintTitleSetInfo( title_set );
781 die = 1;
782 break;
785 fprintf( stderr, "+ Using preset: %s\n",
786 hb_value_get_string(hb_dict_get(preset_dict, "PresetName")));
788 PrintTitleInfo(title, title_set->feature);
790 // All overrides to the preset are complete
791 // Initialize the job from preset + overrides
792 // and apply job specific command line overrides
793 hb_dict_t *job_dict = PrepareJob(h, title, preset_dict);
794 if (job_dict == NULL)
796 die = 1;
797 return -1;
800 char * json_job;
801 json_job = hb_value_get_json(job_dict);
802 hb_value_free(&job_dict);
803 if (json_job == NULL)
805 fprintf(stderr, "Error in setting up job! Aborting.\n");
806 die = 1;
807 return -1;
811 hb_add_json(h, json_job);
812 free(json_job);
813 hb_start( h );
814 break;
817 #define p s.param.working
818 case HB_STATE_SEARCHING:
819 fprintf( stdout, "\rEncoding: task %d of %d, Searching for start time, %.2f %%",
820 p.pass, p.pass_count, 100.0 * p.progress );
821 if( p.seconds > -1 )
823 fprintf( stdout, " (ETA %02dh%02dm%02ds)",
824 p.hours, p.minutes, p.seconds );
826 fflush(stdout);
827 break;
829 case HB_STATE_WORKING:
830 fprintf( stdout, "\rEncoding: task %d of %d, %.2f %%",
831 p.pass, p.pass_count, 100.0 * p.progress );
832 if( p.seconds > -1 )
834 fprintf( stdout, " (%.2f fps, avg %.2f fps, ETA "
835 "%02dh%02dm%02ds)", p.rate_cur, p.rate_avg,
836 p.hours, p.minutes, p.seconds );
838 fflush(stdout);
839 break;
840 #undef p
842 #define p s.param.muxing
843 case HB_STATE_MUXING:
845 if (show_mux_warning)
847 fprintf( stdout, "\rMuxing: this may take awhile..." );
848 fflush(stdout);
849 show_mux_warning = 0;
851 break;
853 #undef p
855 #define p s.param.workdone
856 case HB_STATE_WORKDONE:
857 /* Print error if any, then exit */
858 switch( p.error )
860 case HB_ERROR_NONE:
861 fprintf( stderr, "\nEncode done!\n" );
862 break;
863 case HB_ERROR_CANCELED:
864 fprintf( stderr, "\nEncode canceled.\n" );
865 break;
866 default:
867 fprintf( stderr, "\nEncode failed (error %x).\n",
868 p.error );
870 done_error = p.error;
871 die = 1;
872 break;
873 #undef p
875 return 0;
878 /****************************************************************************
879 * SigHandler:
880 ****************************************************************************/
881 static volatile int64_t i_die_date = 0;
882 void SigHandler( int i_signal )
884 done_error = HB_ERROR_CANCELED;
885 if( die == 0 )
887 die = 1;
888 i_die_date = hb_get_date();
889 fprintf( stderr, "Signal %d received, terminating - do it "
890 "again in case it gets stuck\n", i_signal );
892 else if( i_die_date + 500 < hb_get_date() )
894 fprintf( stderr, "Dying badly, files might remain in your /tmp\n" );
895 exit( done_error );
899 /****************************************************************************
900 * ShowHelp:
901 ****************************************************************************/
902 static void ShowHelp()
904 int i;
905 const hb_rate_t *rate;
906 const hb_dither_t *dither;
907 const hb_mixdown_t *mixdown;
908 const hb_encoder_t *encoder;
909 const hb_container_t *container;
910 FILE* const out = stdout;
912 fprintf( out,
913 "Syntax: HandBrakeCLI [options] -i <device> -o <file>\n"
914 "\n"
915 "### General Handbrake Options---------------------------------------------\n\n"
916 " -h, --help Print help\n"
917 " -u, --update Check for updates and exit\n"
918 " -v, --verbose <#> Be verbose (optional argument: logging level)\n"
919 " -Z. --preset <string> Use a built-in preset. Capitalization matters,\n"
920 " and if the preset name has spaces, surround it\n"
921 " with double quotation marks\n"
922 " -z, --preset-list See a list of available built-in presets\n"
923 " --preset-import-file Import presets from a json preset file.\n"
924 " <filespec> 'filespec' may be a list of files separated\n"
925 " by spaces, or it may use shell wildcards.\n"
926 " --preset-import-gui Import presets from GUI config preset file.\n"
927 " --preset-export Create a new preset from command line options and\n"
928 " <name> write a json representation of the preset to the\n"
929 " console or a file if '--preset-export-file' is\n"
930 " specified. The required 'name' argument will be\n"
931 " the new preset's name.\n"
932 " --preset-export-file Write new preset generated by '--preset-export'\n"
933 " <filename> to file 'filename'.\n"
934 " --preset-export-description\n"
935 " <description> Add a description to the new preset created with\n"
936 " '--preset-export'\n"
937 " --no-dvdnav Do not use dvdnav for reading DVDs\n"
938 " --no-opencl Disable use of OpenCL\n"
939 "\n"
940 "### Source Options--------------------------------------------------------\n\n"
941 " -i, --input <string> Set input device\n"
942 " -t, --title <number> Select a title to encode (0 to scan all titles\n"
943 " only, default: 1)\n"
944 " --min-duration Set the minimum title duration (in seconds).\n"
945 " Shorter titles will be ignored (default: 10).\n"
946 " --scan Scan selected title only.\n"
947 " --main-feature Detect and select the main feature title.\n"
948 " -c, --chapters <string> Select chapters (e.g. \"1-3\" for chapters\n"
949 " 1 to 3, or \"3\" for chapter 3 only,\n"
950 " default: all chapters)\n"
951 " --angle <number> Select the video angle (DVD or Blu-ray only)\n"
952 " --previews <#:B> Select how many preview images are generated,\n"
953 " and whether to store to disk (0 or 1).\n"
954 " (default: 10:0)\n"
955 " --start-at-preview <#> Start encoding at a given preview.\n"
956 " --start-at <unit:#> Start encoding at a given frame, duration\n"
957 " (in seconds), or pts (on a 90kHz clock)\n"
958 " --stop-at <unit:#> Stop encoding at a given frame, duration\n"
959 " (in seconds), or pts (on a 90kHz clock)"
960 "\n"
961 "### Destination Options---------------------------------------------------\n\n"
962 " -o, --output <string> Set output file name\n"
963 " -f, --format <string> Set output container format (");
964 container = NULL;
965 while ((container = hb_container_get_next(container)) != NULL)
967 fprintf(out, "%s", container->short_name);
968 if (hb_container_get_next(container) != NULL)
970 fprintf(out, "/");
972 else
974 fprintf(out, ")\n");
977 fprintf(out,
978 " (default: autodetected from file name)\n"
979 " -m, --markers Add chapter markers\n"
980 " --no-markers Disable preset chapter markers\n"
981 " -O, --optimize Optimize mp4 files for HTTP streaming\n"
982 " (\"fast start\")\n"
983 " --no-optimize Disable preset 'optimize'\n"
984 " -I, --ipod-atom Mark mp4 files so 5.5G iPods will accept them\n"
985 " --no-ipod-atom Disable 5.5G iPod tag\n"
986 " -P, --use-opencl Use OpenCL where applicable\n"
987 " -U, --use-hwd Use DXVA2 hardware decoding\n"
988 " --no-hwd Disable DXVA2 hardware decoding\n"
989 "\n"
992 "### Video Options------------------------------------------------------------\n\n"
993 " -e, --encoder <string> Set video library encoder\n"
994 " Options: " );
995 encoder = NULL;
996 while ((encoder = hb_video_encoder_get_next(encoder)) != NULL)
998 fprintf(out, "%s", encoder->short_name);
999 if (hb_video_encoder_get_next(encoder) != NULL)
1001 fprintf(out, "/");
1003 else
1005 fprintf(out, "\n");
1008 fprintf(out,
1009 " --encoder-preset Adjust video encoding settings for a particular\n"
1010 " <string> speed/efficiency tradeoff (encoder-specific)\n"
1011 " --encoder-preset-list List supported --encoder-preset values for the\n"
1012 " <string> specified video encoder\n"
1013 " --encoder-tune Adjust video encoding settings for a particular\n"
1014 " <string> type of souce or situation (encoder-specific)\n"
1015 " --encoder-tune-list List supported --encoder-tune values for the\n"
1016 " <string> specified video encoder\n"
1017 " -x, --encopts <string> Specify advanced encoding options in the same\n"
1018 " style as mencoder (all encoders except theora):\n"
1019 " option1=value1:option2=value2\n"
1020 " --encoder-profile Ensures compliance with the requested codec\n"
1021 " <string> profile (encoder-specific)\n"
1022 " --encoder-profile-list List supported --encoder-profile values for the\n"
1023 " <string> specified video encoder\n"
1024 " --encoder-level Ensures compliance with the requested codec\n"
1025 " <string> level (encoder-specific)\n"
1026 " --encoder-level-list List supported --encoder-level values for the\n"
1027 " <string> specified video encoder\n"
1028 " -q, --quality <number> Set video quality\n"
1029 " -b, --vb <kb/s> Set video bitrate (default: 1000)\n"
1030 " -2, --two-pass Use two-pass mode\n"
1031 " -T, --turbo When using 2-pass use \"turbo\" options on the\n"
1032 " 1st pass to improve speed\n"
1033 " (works with x264 and x265)\n"
1034 " -r, --rate Set video framerate\n"
1035 " (" );
1036 rate = NULL;
1037 while ((rate = hb_video_framerate_get_next(rate)) != NULL)
1039 fprintf(out, "%s", rate->name);
1040 if (hb_video_framerate_get_next(rate) != NULL)
1042 fprintf(out, "/");
1045 fprintf( out, ")\n"
1046 " Be aware that not specifying a framerate lets\n"
1047 " HandBrake preserve a source's time stamps,\n"
1048 " potentially creating variable framerate video\n"
1049 " --vfr, --cfr, --pfr Select variable, constant or peak-limited\n"
1050 " frame rate control. VFR preserves the source\n"
1051 " timing. CFR makes the output constant rate at\n"
1052 " the rate given by the -r flag (or the source's\n"
1053 " average rate if no -r is given). PFR doesn't\n"
1054 " allow the rate to go over the rate specified\n"
1055 " with the -r flag but won't change the source\n"
1056 " timing if it's below that rate.\n"
1057 " If none of these flags are given, the default\n"
1058 " is --cfr when -r is given and --vfr otherwise\n"
1059 "\n"
1060 "### Audio Options---------------------------------------------------------\n\n"
1061 " --audio-lang-list Specifiy a comma separated list of audio\n"
1062 " <string> languages you would like to select from the\n"
1063 " source title. By default, the first audio\n"
1064 " matching each language will be added to your\n"
1065 " output. Provide the language's iso639-2 code\n"
1066 " (fre, eng, spa, dut, et cetera)\n"
1067 " Use code 'und' (Unknown) to match all languages.\n"
1068 " --all-audio Select all audio tracks matching languages in\n"
1069 " the specified language list (--audio-lang-list).\n"
1070 " Any language if list is not specified.\n"
1071 " --first-audio Select first audio track matching languages in\n"
1072 " the specified language list (--audio-lang-list).\n"
1073 " Any language if list is not specified.\n"
1074 " -a, --audio <string> Select audio track(s), separated by commas\n"
1075 " (\"none\" for no audio, \"1,2,3\" for multiple\n"
1076 " tracks, default: first one).\n"
1077 " Multiple output tracks can be used for one input.\n"
1078 " -E, --aencoder <string> Audio encoder(s):\n" );
1079 encoder = NULL;
1080 while ((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
1082 fprintf(out, " %s\n",
1083 encoder->short_name);
1085 fprintf(out,
1086 " copy:* will passthrough the corresponding\n"
1087 " audio unmodified to the muxer if it is a\n"
1088 " supported passthrough audio type.\n"
1089 " Separate tracks by commas.\n"
1090 " Defaults:\n");
1091 container = NULL;
1092 while ((container = hb_container_get_next(container)) != NULL)
1094 int audio_encoder = hb_audio_encoder_get_default(container->format);
1095 fprintf(out, " %-8s %s\n",
1096 container->short_name,
1097 hb_audio_encoder_get_short_name(audio_encoder));
1099 fprintf(out,
1100 " --audio-copy-mask Set audio codecs that are permitted when the\n"
1101 " <string> \"copy\" audio encoder option is specified\n"
1102 " (" );
1103 i = 0;
1104 encoder = NULL;
1105 while ((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
1107 if ((encoder->codec & HB_ACODEC_PASS_FLAG) &&
1108 (encoder->codec != HB_ACODEC_AUTO_PASS))
1110 if (i)
1112 fprintf(out, "/");
1114 i = 1;
1115 // skip "copy:"
1116 fprintf(out, "%s", encoder->short_name + 5);
1119 fprintf(out, ")\n"
1120 " Separated by commas for multiple allowed options.\n"
1121 " --audio-fallback Set audio codec to use when it is not possible\n"
1122 " <string> to copy an audio track without re-encoding.\n"
1123 " -B, --ab <kb/s> Set audio bitrate(s) (default: depends on the\n"
1124 " selected codec, mixdown and samplerate)\n"
1125 " Separate tracks by commas.\n"
1126 " -Q, --aq <quality> Set audio quality metric.\n"
1127 " Separate tracks by commas.\n"
1128 " -C, --ac <compression> Set audio compression metric.\n"
1129 " selected codec)\n"
1130 " Separate tracks by commas.\n"
1131 " -6, --mixdown <string> Format(s) for audio downmixing/upmixing:\n");
1132 // skip HB_AMIXDOWN_NONE
1133 mixdown = hb_mixdown_get_next(NULL);
1134 while((mixdown = hb_mixdown_get_next(mixdown)) != NULL)
1136 fprintf(out, " %s\n",
1137 mixdown->short_name);
1139 fprintf(out,
1140 " Separate tracks by commas.\n"
1141 " Defaults:\n");
1142 encoder = NULL;
1143 while((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
1145 if (!(encoder->codec & HB_ACODEC_PASS_FLAG))
1147 // layout: UINT64_MAX (all channels) should work with any mixdown
1148 int mixdown = hb_mixdown_get_default(encoder->codec, UINT64_MAX);
1149 // assumes that the encoder short name is <= 16 characters long
1150 fprintf(out, " %-16s up to %s\n",
1151 encoder->short_name, hb_mixdown_get_short_name(mixdown));
1154 fprintf(out,
1155 " --normalize-mix Normalize audio mix levels to prevent clipping.\n"
1156 " <string> Separate tracks by commas.\n"
1157 " 0 = Disable Normalization (default)\n"
1158 " 1 = Enable Normalization\n"
1159 " -R, --arate Set audio samplerate(s)\n"
1160 " (" );
1161 rate = NULL;
1162 while ((rate = hb_audio_samplerate_get_next(rate)) != NULL)
1164 fprintf(out, "%s", rate->name);
1165 if (hb_audio_samplerate_get_next(rate) != NULL)
1167 fprintf(out, "/");
1170 fprintf( out, " kHz)\n"
1171 " Separate tracks by commas.\n"
1172 " -D, --drc <float> Apply extra dynamic range compression to the\n"
1173 " audio, making soft sounds louder. Range is 1.0\n"
1174 " to 4.0 (too loud), with 1.5 - 2.5 being a useful\n"
1175 " range.\n"
1176 " Separate tracks by commas.\n"
1177 " --gain <float> Amplify or attenuate audio before encoding. Does\n"
1178 " NOT work with audio passthru (copy). Values are\n"
1179 " in dB. Negative values attenuate, positive\n"
1180 " values amplify. A 1 dB difference is barely\n"
1181 " audible.\n"
1182 " --adither <string> Apply dithering to the audio before encoding.\n"
1183 " Separate tracks by commas.\n"
1184 " Only supported by some encoders\n"
1185 " (");
1186 i = 0;
1187 encoder = NULL;
1188 while ((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
1190 if (hb_audio_dither_is_supported(encoder->codec))
1192 if (i)
1194 fprintf(out, "/");
1196 i = 1;
1197 fprintf(out, "%s", encoder->short_name);
1200 fprintf(out, ").\n");
1201 fprintf(out,
1202 " Options:\n");
1203 dither = NULL;
1204 while ((dither = hb_audio_dither_get_next(dither)) != NULL)
1206 if (dither->method == hb_audio_dither_get_default())
1208 fprintf(out, " %s (default)\n",
1209 dither->short_name);
1211 else
1213 fprintf(out, " %s\n",
1214 dither->short_name);
1217 fprintf(out,
1218 " -A, --aname <string> Audio track name(s),\n"
1219 " Separate tracks by commas.\n"
1220 "\n"
1221 "### Picture Settings------------------------------------------------------\n\n"
1222 " -w, --width <number> Set picture width\n"
1223 " -l, --height <number> Set picture height\n"
1224 " --crop <T:B:L:R> Set cropping values (default: autocrop)\n"
1225 " --loose-crop Always crop to a multiple of the modulus\n"
1226 " --no-loose-crop Disable preset 'loose-crop'\n"
1227 " -Y, --maxHeight <#> Set maximum height\n"
1228 " -X, --maxWidth <#> Set maximum width\n"
1229 " --non-anamorphic Set pixel aspect ratio to 1:1\n"
1230 " --strict-anamorphic Store pixel aspect ratio in video stream\n"
1231 " --loose-anamorphic Store pixel aspect ratio with specified width\n"
1232 " --custom-anamorphic Store pixel aspect ratio in video stream and\n"
1233 " directly control all parameters.\n"
1234 " --display-width Set the width to scale the actual pixels to\n"
1235 " <number> at playback, for custom anamorphic.\n"
1236 " --keep-display-aspect Preserve the source's display aspect ratio\n"
1237 " when using custom anamorphic\n"
1238 " --no-keep-display-aspect Disable preset 'keep-display-aspect'\n"
1239 " --pixel-aspect Set a custom pixel aspect for custom anamorphic\n"
1240 " <PARX:PARY> (--display-width and --pixel-aspect are mutually\n"
1241 " exclusive.\n"
1242 " --itu-par Use wider, ITU pixel aspect values for loose and\n"
1243 " custom anamorphic, useful with underscanned\n"
1244 " sources\n"
1245 " --no-itu-par Disable preset 'itu-par'\n"
1246 " --modulus Set the number you want the scaled pixel\n"
1247 " dimensions\n"
1248 " <number> to divide cleanly by. Does not affect strict\n"
1249 " anamorphic mode, which is always mod 2\n"
1250 " (default: 16)\n"
1251 " -M, --color-matrix Set the color space signaled by the output\n"
1252 " Values: 709, pal, ntsc, 601 (same as ntsc)\n"
1253 " (default: detected from source)\n"
1254 "\n"
1255 "### Filters---------------------------------------------------------------\n\n"
1256 " -d, --deinterlace Unconditionally deinterlaces all frames\n"
1257 " <fast/slow/slower/bob");
1258 #ifdef USE_QSV
1259 if (hb_qsv_available())
1261 fprintf(out, "/qsv");
1263 #endif
1264 fprintf( out, "> or omitted (default settings)\n"
1265 " or\n"
1266 " <YM:FD> (default 0:-1)\n"
1267 " --no-deinterlace Disable preset deinterlace filter\n"
1268 " -5, --decomb Selectively deinterlaces when it detects combing\n"
1269 " <fast/bob> or omitted (default settings)\n"
1270 " or\n"
1271 " <MO:ME:MT:ST:BT:BX:BY:MG:VA:LA:DI:ER:NO:MD:PP:FD>\n"
1272 " (default: 7:2:6:9:80:16:16:10:20:20:4:2:50:24:1:-1)\n"
1273 " --no-decomb Disable preset decomb filter\n"
1274 " -9, --detelecine Detelecine (ivtc) video with pullup filter\n"
1275 " Note: this filter drops duplicate frames to\n"
1276 " restore the pre-telecine framerate, unless you\n"
1277 " specify a constant framerate (--rate 29.97)\n"
1278 " <L:R:T:B:SB:MP:FD> (default 1:1:4:4:0:0:-1)\n"
1279 " --no-detelecine Disable preset detelecine filter\n"
1280 " -8, --hqdn3d Denoise video with hqdn3d filter\n"
1281 " <ultralight/light/medium/strong> or omitted (default settings)\n"
1282 " or\n"
1283 " <SL:SCb:SCr:TL:TCb:TCr>\n"
1284 " (default: 4:3:3:6:4.5:4.5)\n"
1285 " --no-hqdn3d Disable preset hqdn3d filter\n"
1286 " --denoise Legacy alias for '--hqdn3d'\n"
1287 " --nlmeans Denoise video with nlmeans filter\n"
1288 " <ultralight/light/medium/strong> or omitted\n"
1289 " or\n"
1290 " <SY:OTY:PSY:RY:FY:PY:Sb:OTb:PSb:Rb:Fb:Pb:Sr:OTr:PSr:Rr:Fr:Pr>\n"
1291 " (default 8:1:7:3:2:0)\n"
1292 " --no-nlmeans Disable preset nlmeans filter\n"
1293 " --nlmeans-tune Tune nlmeans filter to content type\n"
1294 " Note: only works in conjunction with presets\n"
1295 " ultralight/light/medium/strong.\n"
1296 " <none/film/grain/highmotion/animation> or omitted (default none)\n"
1297 " -7, --deblock Deblock video with pp7 filter\n"
1298 " <QP:M> (default 5:2)\n"
1299 " --no-deblock Disable preset deblock filter\n"
1300 " --rotate Rotate image or flip its axes.\n"
1301 " <angle>:<mirror> Angle rotates clockwise, can be one of:\n"
1302 " 0, 90, 180, 270\n"
1303 " Mirror flips the image on the x axis.\n"
1304 " Default: 180:0 (rotate 180 degrees)\n"
1305 " -g, --grayscale Grayscale encoding\n"
1306 " --no-grayscale Disable preset 'grayscale'\n"
1307 "\n"
1308 "### Subtitle Options------------------------------------------------------\n\n"
1309 " --subtitle-lang-list Specifiy a comma separated list of subtitle\n"
1310 " <string> languages you would like to select from the\n"
1311 " source title. By default, the first subtitle\n"
1312 " matching each language will be added to your\n"
1313 " output. Provide the language's iso639-2 code\n"
1314 " (fre, eng, spa, dut, et cetera)\n"
1315 " --all-subtitles Select all subtitle tracks matching languages in\n"
1316 " the specified language list\n"
1317 " (--subtitle-lang-list).\n"
1318 " Any language if list is not specified.\n"
1319 " --first-subtitle Select first subtitle track matching languages in\n"
1320 " the specified language list\n"
1321 " (--subtitle-lang-list).\n"
1322 " Any language if list is not specified.\n"
1323 " -s, --subtitle <string> Select subtitle track(s), separated by commas\n"
1324 " More than one output track can be used for one\n"
1325 " input. \"none\" for no subtitles.\n"
1326 " Example: \"1,2,3\" for multiple tracks.\n"
1327 " A special track name \"scan\" adds an extra 1st\n"
1328 " pass. This extra pass scans subtitles matching\n"
1329 " the language of the first audio or the language \n"
1330 " selected by --native-language.\n"
1331 " The one that's only used 10 percent of the time\n"
1332 " or less is selected. This should locate subtitles\n"
1333 " for short foreign language segments. Best used in\n"
1334 " conjunction with --subtitle-forced.\n"
1335 " -F, --subtitle-forced Only display subtitles from the selected stream\n"
1336 " <string> if the subtitle has the forced flag set. The\n"
1337 " values in \"string\" are indexes into the\n"
1338 " subtitle list specified with '--subtitle'.\n"
1339 " Separate tracks by commas.\n"
1340 " Example: \"1,2,3\" for multiple tracks.\n"
1341 " If \"string\" is omitted, the first track is\n"
1342 " forced.\n"
1343 " --subtitle-burned \"Burn\" the selected subtitle into the video\n"
1344 " <subtitle> track. If \"subtitle\" is omitted, the first\n"
1345 " track is burned. \"subtitle\" is an index into\n"
1346 " the subtitle list specified with '--subtitle'\n"
1347 " or \"native\" to burn the subtitle track that may\n"
1348 " be added by the 'native-language' option.\n"
1349 " --subtitle-default Flag the selected subtitle as the default\n"
1350 " <number> subtitle to be displayed upon playback. Setting\n"
1351 " no default means no subtitle will be displayed\n"
1352 " automatically. \"number\" is an index into the\n"
1353 " subtitle list specified with '--subtitle'.\n"
1354 " -N, --native-language Specifiy your language preference. When the first\n"
1355 " <string> audio track does not match your native language\n"
1356 " then select the first subtitle that does. When\n"
1357 " used in conjunction with --native-dub the audio\n"
1358 " track is changed in preference to subtitles.\n"
1359 " Provide the language's iso639-2 code:\n"
1360 " (fre, eng, spa, dut, et cetera)\n"
1361 " --native-dub Used in conjunction with --native-language\n"
1362 " requests that if no audio tracks are selected the\n"
1363 " default selected audio track will be the first\n"
1364 " one that matches the --native-language. If there\n"
1365 " are no matching audio tracks then the first\n"
1366 " matching subtitle track is used instead.\n"
1367 " --srt-file <string> SubRip SRT filename(s), separated by commas.\n"
1368 " --srt-codeset Character codeset(s) that the SRT file(s) are\n"
1369 " <string> encoded in, separated by commas.\n"
1370 " Use 'iconv -l' for a list of valid\n"
1371 " codesets. If not specified, 'latin1' is assumed\n"
1372 " --srt-offset Offset (in milliseconds) to apply to the SRT\n"
1373 " <string> file(s), separated by commas. If not specified,\n"
1374 " zero is assumed. Offsets may be negative.\n"
1375 " --srt-lang <string> SRT track language as an iso639-2 code:\n"
1376 " (fre, eng, spa, dut, et cetera)\n"
1377 " Separated by commas. If not specified, then 'und'\n"
1378 " is used.\n"
1379 " --srt-default Flag the selected srt as the default subtitle\n"
1380 " <number> to be displayed upon playback. Setting no default\n"
1381 " means no subtitle will be automatically displayed\n"
1382 " If \"number\" is omitted, the first SRT is the\n"
1383 " default. \"number\" is an 1 based index into the\n"
1384 " 'srt-file' list\n"
1385 " --srt-burn \"Burn\" the selected SRT subtitle into the\n"
1386 " <number> video track. If \"number\" is omitted, the first\n"
1387 " SRT is burned. \"number\" is an 1 based index\n"
1388 " into the 'srt-file' list\n"
1389 "\n"
1392 #ifdef USE_QSV
1393 if (hb_qsv_available())
1395 fprintf( out,
1396 "### Intel Quick Sync Video------------------------------------------------\n\n"
1397 " --disable-qsv-decoding Force software decoding of the video track.\n"
1398 " --enable-qsv-decoding Allow QSV hardware decoding of the video track.\n"
1399 " --qsv-async-depth Specifies how many asynchronous operations\n"
1400 " should be performed before the result is\n"
1401 " explicitly synchronized.\n"
1402 " Default: 4. If zero, the value is not specified.\n"
1403 "\n"
1406 #endif
1409 /****************************************************************************
1410 * ShowPresets:
1411 ****************************************************************************/
1412 static const char *
1413 reverse_search_char(const char *front, const char *back, char delim)
1415 while (back != front && *back != delim)
1416 back--;
1417 return back;
1420 #if defined( __MINGW32__ )
1421 static char * my_strndup(const char *src, int len)
1423 int src_len = strlen(src);
1424 int alloc = src_len < len ? src_len + 1 : len + 1;
1425 char *result = malloc(alloc);
1426 strncpy(result, src, alloc - 1);
1427 result[alloc - 1] = 0;
1428 return result;
1430 #else
1431 #define my_strndup strndup
1432 #endif
1434 static char** str_width_split( const char *str, int width )
1436 const char * pos;
1437 const char * end;
1438 char ** ret;
1439 int count, ii;
1440 int len;
1441 char delem = ' ';
1443 if ( str == NULL || str[0] == 0 )
1445 ret = malloc( sizeof(char*) );
1446 *ret = NULL;
1447 return ret;
1450 len = strlen(str);
1452 // Find number of elements in the string
1453 count = 1;
1454 pos = str;
1455 end = pos + width;
1456 while (end < str + len)
1458 end = reverse_search_char(pos, end, delem);
1459 if (end == pos)
1461 // Shouldn't happen for reasonable input
1462 break;
1464 count++;
1465 pos = end + 1;
1466 end = pos + width;
1468 count++;
1469 ret = calloc( ( count + 1 ), sizeof(char*) );
1471 pos = str;
1472 end = pos + width;
1473 for (ii = 0; ii < count - 1 && end < str + len; ii++)
1475 end = reverse_search_char(pos, end, delem);
1476 if (end == pos)
1478 break;
1480 ret[ii] = my_strndup(pos, end - pos);
1481 pos = end + 1;
1482 end = pos + width;
1484 if (*pos != 0 && ii < count - 1)
1486 ret[ii] = my_strndup(pos, width);
1489 return ret;
1492 static void Indent(FILE *f, char *whitespace, int indent)
1494 int ii;
1495 for (ii = 0; ii < indent; ii++)
1497 fprintf(f, "%s", whitespace);
1501 static void ShowPresets(hb_value_array_t *presets, int indent, int descriptions)
1503 if (presets == NULL)
1504 presets = hb_presets_get();
1506 int count = hb_value_array_len(presets);
1507 int ii;
1508 for (ii = 0; ii < count; ii++)
1510 const char *name;
1511 hb_dict_t *preset_dict = hb_value_array_get(presets, ii);
1512 name = hb_value_get_string(hb_dict_get(preset_dict, "PresetName"));
1513 Indent(stderr, " ", indent);
1514 if (hb_value_get_bool(hb_dict_get(preset_dict, "Folder")))
1516 indent++;
1517 fprintf(stderr, "%s/\n", name);
1518 hb_value_array_t *children;
1519 children = hb_dict_get(preset_dict, "ChildrenArray");
1520 if (children == NULL)
1521 continue;
1522 ShowPresets(children, indent, descriptions);
1523 indent--;
1525 else
1527 fprintf(stderr, "%s\n", name);
1528 if (descriptions)
1530 const char *desc;
1531 desc = hb_value_get_string(hb_dict_get(preset_dict,
1532 "PresetDescription"));
1533 if (desc != NULL && desc[0] != 0)
1535 int ii;
1536 char **split = str_width_split(desc, 60);
1537 for (ii = 0; split[ii] != NULL; ii++)
1539 Indent(stderr, " ", indent+1);
1540 fprintf(stderr, "%s\n", split[ii]);
1542 str_vfree(split);
1549 static char* strchr_quote(char *pos, char c, char q)
1551 if (pos == NULL)
1552 return NULL;
1554 while (*pos != 0 && *pos != c)
1556 if (*pos == q)
1558 pos = strchr_quote(pos+1, q, 0);
1559 if (pos == NULL)
1560 return NULL;
1561 pos++;
1563 else if (*pos == '\\' && *(pos+1) != 0)
1564 pos += 2;
1565 else
1566 pos++;
1568 if (*pos != c)
1569 return NULL;
1570 return pos;
1573 static char *strndup_quote(char *str, char q, int len)
1575 if (str == NULL)
1576 return NULL;
1578 char * res;
1579 int str_len = strlen( str );
1580 int src = 0, dst = 0;
1581 res = malloc( len > str_len ? str_len + 1 : len + 1 );
1583 while (str[src] != 0 && src < len)
1585 if (str[src] == q)
1586 src++;
1587 else if (str[src] == '\\' && str[src+1] != 0)
1589 res[dst++] = str[src+1];
1590 src += 2;
1592 else
1593 res[dst++] = str[src++];
1595 res[dst] = '\0';
1596 return res;
1599 static int str_vlen(char **strv)
1601 int i;
1602 if (strv == NULL)
1603 return 0;
1604 for (i = 0; strv[i]; i++);
1605 return i;
1608 static char** str_split( char *str, char delem )
1610 char * pos;
1611 char * end;
1612 char ** ret;
1613 int count, i;
1614 char quote = '"';
1616 if (delem == '"')
1618 quote = '\'';
1620 if ( str == NULL || str[0] == 0 )
1622 ret = malloc( sizeof(char*) );
1623 *ret = NULL;
1624 return ret;
1627 // Find number of elements in the string
1628 count = 1;
1629 pos = str;
1630 while ( ( pos = strchr_quote( pos, delem, quote ) ) != NULL )
1632 count++;
1633 pos++;
1636 ret = calloc( ( count + 1 ), sizeof(char*) );
1638 pos = str;
1639 for ( i = 0; i < count - 1; i++ )
1641 end = strchr_quote( pos, delem, quote );
1642 ret[i] = strndup_quote(pos, quote, end - pos);
1643 pos = end + 1;
1645 ret[i] = strndup_quote(pos, quote, strlen(pos));
1647 return ret;
1650 static void str_vfree( char **strv )
1652 int i;
1654 if (strv == NULL)
1655 return;
1657 for ( i = 0; strv[i]; i++ )
1659 free( strv[i] );
1661 free( strv );
1664 static double parse_hhmmss_strtok()
1666 /* Assumes strtok has already been called on a string. Intends to parse
1667 * hh:mm:ss.ss or mm:ss.ss or ss.ss or ss into double seconds. Actually
1668 * parses a list of doubles separated by colons, multiplying the current
1669 * result by 60 then adding in the next value. Malformed input does not
1670 * result in a explicit error condition but instead returns an
1671 * intermediate result. */
1672 double duration = 0;
1673 char* str;
1674 while ((str = strtok(NULL, ":")) != NULL)
1675 duration = 60*duration + strtod(str, NULL);
1676 return duration;
1679 /****************************************************************************
1680 * ParseOptions:
1681 ****************************************************************************/
1682 static int ParseOptions( int argc, char ** argv )
1685 #define PREVIEWS 257
1686 #define START_AT_PREVIEW 258
1687 #define START_AT 259
1688 #define STOP_AT 260
1689 #define ANGLE 261
1690 #define DVDNAV 262
1691 #define DISPLAY_WIDTH 263
1692 #define PIXEL_ASPECT 264
1693 #define MODULUS 265
1694 #define KEEP_DISPLAY_ASPECT 266
1695 #define SUB_BURNED 267
1696 #define SUB_DEFAULT 268
1697 #define NATIVE_DUB 269
1698 #define SRT_FILE 270
1699 #define SRT_CODESET 271
1700 #define SRT_OFFSET 272
1701 #define SRT_LANG 273
1702 #define SRT_DEFAULT 274
1703 #define SRT_BURN 275
1704 #define ROTATE_FILTER 276
1705 #define SCAN_ONLY 277
1706 #define MAIN_FEATURE 278
1707 #define MIN_DURATION 279
1708 #define AUDIO_GAIN 280
1709 #define ALLOWED_AUDIO_COPY 281
1710 #define AUDIO_FALLBACK 282
1711 #define LOOSE_CROP 283
1712 #define ENCODER_PRESET 284
1713 #define ENCODER_PRESET_LIST 285
1714 #define ENCODER_TUNE 286
1715 #define ENCODER_TUNE_LIST 287
1716 #define ENCODER_PROFILE 288
1717 #define ENCODER_PROFILE_LIST 289
1718 #define ENCODER_LEVEL 290
1719 #define ENCODER_LEVEL_LIST 291
1720 #define NORMALIZE_MIX 293
1721 #define AUDIO_DITHER 294
1722 #define QSV_BASELINE 295
1723 #define QSV_ASYNC_DEPTH 296
1724 #define QSV_IMPLEMENTATION 297
1725 #define FILTER_NLMEANS 298
1726 #define FILTER_NLMEANS_TUNE 299
1727 #define AUDIO_LANG_LIST 300
1728 #define SUBTITLE_LANG_LIST 301
1729 #define PRESET_EXPORT 302
1730 #define PRESET_EXPORT_DESC 303
1731 #define PRESET_EXPORT_FILE 304
1732 #define PRESET_IMPORT 305
1733 #define PRESET_IMPORT_GUI 306
1735 for( ;; )
1737 static struct option long_options[] =
1739 { "help", no_argument, NULL, 'h' },
1740 { "update", no_argument, NULL, 'u' },
1741 { "verbose", optional_argument, NULL, 'v' },
1742 { "no-dvdnav", no_argument, NULL, DVDNAV },
1743 { "no-opencl", no_argument, &use_opencl, 0 },
1745 #ifdef USE_QSV
1746 { "qsv-baseline", no_argument, NULL, QSV_BASELINE, },
1747 { "qsv-async-depth", required_argument, NULL, QSV_ASYNC_DEPTH, },
1748 { "qsv-implementation", required_argument, NULL, QSV_IMPLEMENTATION, },
1749 { "disable-qsv-decoding", no_argument, &qsv_decode, 0, },
1750 { "enable-qsv-decoding", no_argument, &qsv_decode, 1, },
1751 #endif
1753 { "format", required_argument, NULL, 'f' },
1754 { "input", required_argument, NULL, 'i' },
1755 { "output", required_argument, NULL, 'o' },
1756 { "optimize", no_argument, NULL, 'O' },
1757 { "no-optimize", no_argument, &mp4_optimize, 0 },
1758 { "ipod-atom", no_argument, NULL, 'I' },
1759 { "no-ipod-atom",no_argument, &ipod_atom, 0 },
1760 { "use-opencl", no_argument, NULL, 'P' },
1761 { "use-hwd", no_argument, NULL, 'U' },
1762 { "no-hwd", no_argument, &use_hwd, 0 },
1764 { "title", required_argument, NULL, 't' },
1765 { "min-duration",required_argument, NULL, MIN_DURATION },
1766 { "scan", no_argument, NULL, SCAN_ONLY },
1767 { "main-feature",no_argument, NULL, MAIN_FEATURE },
1768 { "chapters", required_argument, NULL, 'c' },
1769 { "angle", required_argument, NULL, ANGLE },
1770 { "markers", optional_argument, NULL, 'm' },
1771 { "no-markers", no_argument, &chapter_markers, 0 },
1772 { "audio-lang-list", required_argument, NULL, AUDIO_LANG_LIST },
1773 { "all-audio", no_argument, &audio_all, 1 },
1774 { "first-audio", no_argument, &audio_all, 0 },
1775 { "audio", required_argument, NULL, 'a' },
1776 { "mixdown", required_argument, NULL, '6' },
1777 { "normalize-mix", required_argument, NULL, NORMALIZE_MIX },
1778 { "drc", required_argument, NULL, 'D' },
1779 { "gain", required_argument, NULL, AUDIO_GAIN },
1780 { "adither", required_argument, NULL, AUDIO_DITHER },
1781 { "subtitle-lang-list", required_argument, NULL, SUBTITLE_LANG_LIST },
1782 { "all-subtitles", no_argument, &subtitle_all, 1 },
1783 { "first-subtitle", no_argument, &subtitle_all, 0 },
1784 { "subtitle", required_argument, NULL, 's' },
1785 { "subtitle-forced", optional_argument, NULL, 'F' },
1786 { "subtitle-burned", optional_argument, NULL, SUB_BURNED },
1787 { "subtitle-default", optional_argument, NULL, SUB_DEFAULT },
1788 { "srt-file", required_argument, NULL, SRT_FILE },
1789 { "srt-codeset", required_argument, NULL, SRT_CODESET },
1790 { "srt-offset", required_argument, NULL, SRT_OFFSET },
1791 { "srt-lang", required_argument, NULL, SRT_LANG },
1792 { "srt-default", optional_argument, NULL, SRT_DEFAULT },
1793 { "srt-burn", optional_argument, NULL, SRT_BURN },
1794 { "native-language", required_argument, NULL,'N' },
1795 { "native-dub", no_argument, NULL, NATIVE_DUB },
1796 { "encoder", required_argument, NULL, 'e' },
1797 { "aencoder", required_argument, NULL, 'E' },
1798 { "two-pass", no_argument, NULL, '2' },
1799 { "deinterlace", optional_argument, NULL, 'd' },
1800 { "no-deinterlace", no_argument, &deinterlace_disable, 1 },
1801 { "deblock", optional_argument, NULL, '7' },
1802 { "no-deblock", no_argument, &deblock_disable, 1 },
1803 { "denoise", optional_argument, NULL, '8' },
1804 { "hqdn3d", optional_argument, NULL, '8' },
1805 { "no-hqdn3d", no_argument, &hqdn3d_disable, 1 },
1806 { "nlmeans", optional_argument, NULL, FILTER_NLMEANS },
1807 { "no-nlmeans", no_argument, &nlmeans_disable, 1 },
1808 { "nlmeans-tune",required_argument, NULL, FILTER_NLMEANS_TUNE },
1809 { "detelecine", optional_argument, NULL, '9' },
1810 { "no-detelecine", no_argument, &detelecine_disable, 1 },
1811 { "decomb", optional_argument, NULL, '5' },
1812 { "no-decomb", no_argument, &decomb_disable, 1 },
1813 { "grayscale", no_argument, NULL, 'g' },
1814 { "no-grayscale",no_argument, &grayscale, 0 },
1815 { "rotate", optional_argument, NULL, ROTATE_FILTER },
1816 { "non-anamorphic", no_argument, &anamorphic_mode, 0 },
1817 { "strict-anamorphic", no_argument, &anamorphic_mode, 1 },
1818 { "loose-anamorphic", no_argument, &anamorphic_mode, 2 },
1819 { "custom-anamorphic", no_argument, &anamorphic_mode, 3 },
1820 { "display-width", required_argument, NULL, DISPLAY_WIDTH },
1821 { "keep-display-aspect", optional_argument, NULL, KEEP_DISPLAY_ASPECT },
1822 { "no-keep-display-aspect", no_argument, &keep_display_aspect, 0 },
1823 { "pixel-aspect", required_argument, NULL, PIXEL_ASPECT },
1824 { "modulus", required_argument, NULL, MODULUS },
1825 { "itu-par", no_argument, &itu_par, 1 },
1826 { "no-itu-par", no_argument, &itu_par, 0 },
1827 { "width", required_argument, NULL, 'w' },
1828 { "height", required_argument, NULL, 'l' },
1829 { "crop", required_argument, NULL, 'n' },
1830 { "loose-crop", optional_argument, NULL, LOOSE_CROP },
1831 { "no-loose-crop", no_argument, &loose_crop, 0 },
1833 // mapping of legacy option names for backwards compatibility
1834 { "qsv-preset", required_argument, NULL, ENCODER_PRESET, },
1835 { "x264-preset", required_argument, NULL, ENCODER_PRESET, },
1836 { "x265-preset", required_argument, NULL, ENCODER_PRESET, },
1837 { "x264-tune", required_argument, NULL, ENCODER_TUNE, },
1838 { "x265-tune", required_argument, NULL, ENCODER_TUNE, },
1839 { "x264-profile", required_argument, NULL, ENCODER_PROFILE, },
1840 { "h264-profile", required_argument, NULL, ENCODER_PROFILE, },
1841 { "h265-profile", required_argument, NULL, ENCODER_PROFILE, },
1842 { "h264-level", required_argument, NULL, ENCODER_LEVEL, },
1843 { "h265-level", required_argument, NULL, ENCODER_LEVEL, },
1844 // encoder preset/tune/options/profile/level
1845 { "encoder-preset", required_argument, NULL, ENCODER_PRESET, },
1846 { "encoder-preset-list", required_argument, NULL, ENCODER_PRESET_LIST, },
1847 { "encoder-tune", required_argument, NULL, ENCODER_TUNE, },
1848 { "encoder-tune-list", required_argument, NULL, ENCODER_TUNE_LIST, },
1849 { "encopts", required_argument, NULL, 'x', },
1850 { "encoder-profile", required_argument, NULL, ENCODER_PROFILE, },
1851 { "encoder-profile-list", required_argument, NULL, ENCODER_PROFILE_LIST, },
1852 { "encoder-level", required_argument, NULL, ENCODER_LEVEL, },
1853 { "encoder-level-list", required_argument, NULL, ENCODER_LEVEL_LIST, },
1855 { "vb", required_argument, NULL, 'b' },
1856 { "quality", required_argument, NULL, 'q' },
1857 { "ab", required_argument, NULL, 'B' },
1858 { "aq", required_argument, NULL, 'Q' },
1859 { "ac", required_argument, NULL, 'C' },
1860 { "rate", required_argument, NULL, 'r' },
1861 { "arate", required_argument, NULL, 'R' },
1862 { "turbo", no_argument, NULL, 'T' },
1863 { "maxHeight", required_argument, NULL, 'Y' },
1864 { "maxWidth", required_argument, NULL, 'X' },
1865 { "preset", required_argument, NULL, 'Z' },
1866 { "preset-list", no_argument, NULL, 'z' },
1867 { "preset-import-file", no_argument, NULL, PRESET_IMPORT },
1868 { "preset-import-gui", no_argument, NULL, PRESET_IMPORT_GUI },
1869 { "preset-export", required_argument, NULL, PRESET_EXPORT },
1870 { "preset-export-file", required_argument, NULL, PRESET_EXPORT_FILE },
1871 { "preset-export-description", required_argument, NULL, PRESET_EXPORT_DESC },
1873 { "aname", required_argument, NULL, 'A' },
1874 { "color-matrix",required_argument, NULL, 'M' },
1875 { "previews", required_argument, NULL, PREVIEWS },
1876 { "start-at-preview", required_argument, NULL, START_AT_PREVIEW },
1877 { "start-at", required_argument, NULL, START_AT },
1878 { "stop-at", required_argument, NULL, STOP_AT },
1879 { "vfr", no_argument, &cfr, 0 },
1880 { "cfr", no_argument, &cfr, 1 },
1881 { "pfr", no_argument, &cfr, 2 },
1882 { "audio-copy-mask", required_argument, NULL, ALLOWED_AUDIO_COPY },
1883 { "audio-fallback", required_argument, NULL, AUDIO_FALLBACK },
1884 { 0, 0, 0, 0 }
1887 int option_index = 0;
1888 int c;
1889 int cur_optind;
1891 cur_optind = optind;
1892 c = getopt_long( argc, argv,
1893 "hv::uC:f:4i:Io:PUt:c:m::M:a:A:6:s:F::N:e:E:Q:C:"
1894 "2dD:7895gOw:l:n:b:q:S:B:r:R:x:TY:X:Z:z",
1895 long_options, &option_index );
1896 if( c < 0 )
1898 break;
1901 switch( c )
1903 case 0:
1904 /* option was handled entirely in getopt_long */
1905 break;
1906 case 'h':
1907 ShowHelp();
1908 exit( 0 );
1909 case 'u':
1910 update = 1;
1911 break;
1912 case 'v':
1913 if( optarg != NULL )
1915 debug = atoi( optarg );
1917 else
1919 debug = 1;
1921 break;
1922 case 'Z':
1923 preset_name = strdup(optarg);
1924 break;
1925 case 'z':
1926 ShowPresets(NULL, 0, 1);
1927 exit ( 0 );
1928 case PRESET_EXPORT:
1929 preset_export_name = strdup(optarg);
1930 break;
1931 case PRESET_EXPORT_DESC:
1932 preset_export_desc = strdup(optarg);
1933 break;
1934 case PRESET_EXPORT_FILE:
1935 preset_export_file = strdup(optarg);
1936 break;
1937 case PRESET_IMPORT:
1939 // Import list of preset files
1940 while (optind < argc && argv[optind][0] != '-')
1942 int result = hb_presets_add_path(argv[optind]);
1943 if (result < 0)
1945 fprintf(stderr, "Preset import failed, file (%s)\n",
1946 argv[optind]);
1948 optind++;
1950 } break;
1951 case PRESET_IMPORT_GUI:
1952 hb_presets_gui_init();
1953 break;
1954 case DVDNAV:
1955 dvdnav = 0;
1956 break;
1958 case 'f':
1959 format = strdup( optarg );
1960 break;
1961 case 'i':
1962 input = strdup( optarg );
1963 #ifdef __APPLE_CC__
1964 char *devName = bsd_name_for_path( input ); // alloc
1965 if( devName != NULL )
1967 if( device_is_dvd( devName ))
1969 free( input );
1970 input = malloc( strlen( "/dev/" ) + strlen( devName ) + 1 );
1971 sprintf( input, "/dev/%s", devName );
1973 free( devName );
1975 #endif
1976 break;
1977 case 'o':
1978 output = strdup( optarg );
1979 break;
1980 case 'O':
1981 mp4_optimize = 1;
1982 break;
1983 case 'I':
1984 ipod_atom = 1;
1985 break;
1986 case 'P':
1987 use_opencl = 1;
1988 break;
1989 case 'U':
1990 use_hwd = 1;
1991 break;
1992 case 't':
1993 titleindex = atoi( optarg );
1994 break;
1995 case SCAN_ONLY:
1996 titlescan = 1;
1997 break;
1998 case MAIN_FEATURE:
1999 main_feature = 1;
2000 break;
2001 case 'c':
2003 int start, end;
2004 if( sscanf( optarg, "%d-%d", &start, &end ) == 2 )
2006 chapter_start = start;
2007 chapter_end = end;
2009 else if( sscanf( optarg, "%d", &start ) == 1 )
2011 chapter_start = start;
2012 chapter_end = chapter_start;
2014 else
2016 fprintf( stderr, "chapters: Invalid syntax (%s)\n",
2017 optarg );
2018 return -1;
2020 break;
2022 case ANGLE:
2023 angle = atoi( optarg );
2024 break;
2025 case 'm':
2026 if( optarg != NULL )
2028 marker_file = strdup( optarg );
2030 chapter_markers = 1;
2031 break;
2032 case AUDIO_LANG_LIST:
2033 audio_lang_list = str_split(optarg, ',');
2034 break;
2035 case SUBTITLE_LANG_LIST:
2036 subtitle_lang_list = str_split(optarg, ',');
2037 break;
2038 case 'a':
2039 if( optarg != NULL )
2041 atracks = str_split(optarg, ',');
2043 else
2045 atracks = str_split("1", ',');
2047 break;
2048 case '6':
2049 if( optarg != NULL )
2051 mixdowns = str_split(optarg, ',');
2053 break;
2054 case 'D':
2055 if( optarg != NULL )
2057 dynamic_range_compression = str_split(optarg, ',');
2059 break;
2060 case AUDIO_GAIN:
2061 if( optarg != NULL )
2063 audio_gain = str_split(optarg, ',');
2065 break;
2066 case AUDIO_DITHER:
2067 if (optarg != NULL)
2069 audio_dither = str_split(optarg, ',');
2071 break;
2072 case NORMALIZE_MIX:
2073 normalize_mix_level = str_split(optarg, ',');
2074 break;
2075 case 's':
2076 subtracks = str_split( optarg, ',' );
2077 break;
2078 case 'F':
2079 subforce = str_split( optarg, ',' );
2080 break;
2081 case SUB_BURNED:
2082 if (optarg != NULL)
2084 if (!strcasecmp(optarg, "native") ||
2085 !strcasecmp(optarg, "scan"))
2086 subburn_native = 1;
2087 else
2089 subburn = strtol(optarg, NULL, 0);
2092 else
2094 subburn = 1;
2096 if (subburn > 0)
2098 if (subtracks != NULL && str_vlen(subtracks) >= subburn &&
2099 !strcasecmp("scan", subtracks[subburn-1]))
2101 subburn_native = 1;
2104 break;
2105 case SUB_DEFAULT:
2106 if (optarg != NULL)
2108 subdefault = strtol(optarg, NULL, 0);
2110 else
2112 subdefault = 1;
2114 break;
2115 case 'N':
2117 const iso639_lang_t *lang = lang_lookup(optarg);
2118 if (lang != NULL)
2120 native_language = strdup(lang->iso639_2);
2122 else
2124 fprintf(stderr, "Invalid native language (%s)\n", optarg);
2125 return -1;
2127 } break;
2128 case NATIVE_DUB:
2129 native_dub = 1;
2130 break;
2131 case SRT_FILE:
2132 srtfile = str_split( optarg, ',' );
2133 break;
2134 case SRT_CODESET:
2135 srtcodeset = str_split( optarg, ',' );
2136 break;
2137 case SRT_OFFSET:
2138 srtoffset = str_split( optarg, ',' );
2139 break;
2140 case SRT_LANG:
2141 srtlang = str_split( optarg, ',' );
2142 break;
2143 case SRT_DEFAULT:
2144 if( optarg != NULL )
2146 srtdefault = atoi( optarg );
2148 else
2150 srtdefault = 1 ;
2152 break;
2153 case SRT_BURN:
2154 if( optarg != NULL )
2156 srtburn = atoi( optarg );
2158 else
2160 srtburn = 1 ;
2162 break;
2163 case '2':
2164 twoPass = 1;
2165 break;
2166 case 'd':
2167 free(deinterlace);
2168 if (optarg != NULL)
2170 deinterlace = strdup(optarg);
2172 else
2174 deinterlace = strdup("default");
2176 break;
2177 case '7':
2178 free(deblock);
2179 if( optarg != NULL )
2181 deblock = strdup(optarg);
2183 else
2185 deblock = strdup("5");
2187 break;
2188 case '8':
2189 free(hqdn3d);
2190 if (optarg != NULL)
2192 hqdn3d = strdup(optarg);
2194 else
2196 hqdn3d = strdup("default");
2198 break;
2199 case FILTER_NLMEANS:
2200 free(nlmeans);
2201 if (optarg != NULL)
2203 nlmeans = strdup(optarg);
2205 else
2207 nlmeans = strdup("medium");
2209 break;
2210 case FILTER_NLMEANS_TUNE:
2211 free(nlmeans_tune);
2212 nlmeans_tune = strdup(optarg);
2213 break;
2214 case '9':
2215 free(detelecine);
2216 if (optarg != NULL)
2218 detelecine = strdup(optarg);
2220 else
2222 detelecine = strdup("default");
2224 break;
2225 case '5':
2226 free(decomb);
2227 if (optarg != NULL)
2229 decomb = strdup(optarg);
2231 else
2233 decomb = strdup("default");
2235 break;
2236 case 'g':
2237 grayscale = 1;
2238 break;
2239 case ROTATE_FILTER:
2240 free(rotate);
2241 if (optarg != NULL)
2243 rotate = strdup(optarg);
2245 else
2247 rotate = strdup("180:0");
2249 break;
2250 case KEEP_DISPLAY_ASPECT:
2251 if( optarg != NULL )
2253 keep_display_aspect = atoi(optarg);
2255 else
2257 keep_display_aspect = 1;
2259 break;
2260 case DISPLAY_WIDTH:
2261 if( optarg != NULL )
2263 display_width = atoi(optarg);
2265 break;
2266 case PIXEL_ASPECT:
2267 if( optarg != NULL )
2269 sscanf(optarg, "%i:%i", &par_width, &par_height);
2271 break;
2272 case MODULUS:
2273 if( optarg != NULL )
2275 modulus = atoi(optarg);
2277 break;
2278 case 'e':
2280 vcodec = strdup(optarg);
2281 break;
2283 case 'E':
2284 if( optarg != NULL )
2286 acodecs = str_split(optarg, ',');
2288 break;
2289 case 'w':
2290 width = atoi( optarg );
2291 break;
2292 case 'l':
2293 height = atoi( optarg );
2294 break;
2295 case 'n':
2297 int i;
2298 char * tmp = optarg;
2299 for( i = 0; i < 4; i++ )
2301 if( !*tmp )
2302 break;
2303 crop[i] = strtol( tmp, &tmp, 0 );
2304 tmp++;
2306 break;
2308 case LOOSE_CROP:
2309 if (optarg != NULL)
2310 loose_crop = atoi(optarg);
2311 else
2312 loose_crop = 1;
2313 break;
2314 case 'r':
2316 vrate = strdup(optarg);
2317 if (!cfr)
2319 cfr = 1;
2321 break;
2323 case 'R':
2324 arates = str_split( optarg, ',' );
2325 break;
2326 case 'b':
2327 vbitrate = atoi( optarg );
2328 break;
2329 case 'q':
2330 vquality = atof( optarg );
2331 break;
2332 case 'B':
2333 abitrates = str_split( optarg, ',' );
2334 break;
2335 case 'Q':
2336 aqualities = str_split( optarg, ',' );
2337 break;
2338 case 'C':
2339 acompressions = str_split( optarg, ',' );
2340 break;
2341 case ENCODER_PRESET:
2342 encoder_preset = strdup( optarg );
2343 break;
2344 case ENCODER_TUNE:
2345 encoder_tune = strdup( optarg );
2346 break;
2347 case 'x':
2348 advanced_opts = strdup( optarg );
2349 break;
2350 case ENCODER_PROFILE:
2351 encoder_profile = strdup( optarg );
2352 break;
2353 case ENCODER_LEVEL:
2354 encoder_level = strdup( optarg );
2355 break;
2356 case ENCODER_PRESET_LIST:
2357 fprintf(stderr, "Available --encoder-preset values for '%s' encoder:\n",
2358 hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(optarg)));
2359 print_string_list(stderr,
2360 hb_video_encoder_get_presets(hb_video_encoder_get_from_name(optarg)),
2361 " ");
2362 exit(0);
2363 case ENCODER_TUNE_LIST:
2364 fprintf(stderr, "Available --encoder-tune values for '%s' encoder:\n",
2365 hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(optarg)));
2366 print_string_list(stderr,
2367 hb_video_encoder_get_tunes(hb_video_encoder_get_from_name(optarg)),
2368 " ");
2369 exit(0);
2370 case ENCODER_PROFILE_LIST:
2371 fprintf(stderr, "Available --encoder-profile values for '%s' encoder:\n",
2372 hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(optarg)));
2373 print_string_list(stderr,
2374 hb_video_encoder_get_profiles(hb_video_encoder_get_from_name(optarg)),
2375 " ");
2376 exit(0);
2377 case ENCODER_LEVEL_LIST:
2378 fprintf(stderr, "Available --encoder-level values for '%s' encoder:\n",
2379 hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(optarg)));
2380 print_string_list(stderr,
2381 hb_video_encoder_get_levels(hb_video_encoder_get_from_name(optarg)),
2382 " ");
2383 exit(0);
2384 case 'T':
2385 fastfirstpass = 1;
2386 break;
2387 case 'Y':
2388 maxHeight = atoi( optarg );
2389 break;
2390 case 'X':
2391 maxWidth = atoi (optarg );
2392 break;
2393 case 'A':
2394 if( optarg != NULL )
2396 anames = str_split( optarg, ',' );
2398 break;
2399 case PREVIEWS:
2400 sscanf( optarg, "%i:%i", &preview_count, &store_previews );
2401 break;
2402 case START_AT_PREVIEW:
2403 start_at_preview = atoi( optarg );
2404 break;
2405 case START_AT:
2407 char * start_at_string = NULL;
2408 char * start_at_token = NULL;
2409 start_at_string = strdup( optarg );
2410 start_at_token = strtok( start_at_string, ":");
2411 if( !strcmp( start_at_token, "frame" ) )
2413 start_at_token = strtok( NULL, ":");
2414 start_at_frame = atoi(start_at_token);
2416 else if( !strcmp( start_at_token, "pts" ) )
2418 start_at_token = strtok( NULL, ":");
2419 sscanf( start_at_token, "%"SCNd64, &start_at_pts );
2421 else if( !strcmp( start_at_token, "duration" ) )
2423 double duration_seconds = parse_hhmmss_strtok();
2424 start_at_pts = (int64_t)(duration_seconds * 90e3);
2426 free( start_at_string );
2427 break;
2429 case STOP_AT:
2431 char * stop_at_string = NULL;
2432 char * stop_at_token = NULL;
2433 stop_at_string = strdup( optarg );
2434 stop_at_token = strtok( stop_at_string, ":");
2435 if( !strcmp( stop_at_token, "frame" ) )
2437 stop_at_token = strtok( NULL, ":");
2438 stop_at_frame = atoi(stop_at_token);
2440 else if( !strcmp( stop_at_token, "pts" ) )
2442 stop_at_token = strtok( NULL, ":");
2443 sscanf( stop_at_token, "%"SCNd64, &stop_at_pts );
2445 else if( !strcmp( stop_at_token, "duration" ) )
2447 double duration_seconds = parse_hhmmss_strtok();
2448 stop_at_pts = (int64_t)(duration_seconds * 90e3);
2450 free( stop_at_string );
2451 break;
2453 case ALLOWED_AUDIO_COPY:
2455 audio_copy_list = str_split(optarg, ',');
2456 break;
2458 case AUDIO_FALLBACK:
2459 acodec_fallback = strdup( optarg );
2460 break;
2461 case 'M':
2462 if( optarg != NULL )
2464 if( !strcmp( optarg, "601" ) ||
2465 !strcmp( optarg, "ntsc" ) )
2466 color_matrix_code = 1;
2467 else if( !strcmp( optarg, "pal" ) )
2468 color_matrix_code = 2;
2469 else if( !strcmp( optarg, "709" ) )
2470 color_matrix_code = 3;
2471 } break;
2472 case MIN_DURATION:
2473 min_title_duration = strtol( optarg, NULL, 0 );
2474 break;
2475 #ifdef USE_QSV
2476 case QSV_BASELINE:
2477 hb_qsv_force_workarounds();
2478 break;
2479 case QSV_ASYNC_DEPTH:
2480 qsv_async_depth = atoi(optarg);
2481 break;
2482 case QSV_IMPLEMENTATION:
2483 hb_qsv_impl_set_preferred(optarg);
2484 break;
2485 #endif
2486 default:
2487 fprintf( stderr, "unknown option (%s)\n", argv[cur_optind] );
2488 return -1;
2493 if (deblock != NULL)
2495 if (deblock_disable)
2497 fprintf(stderr,
2498 "Incompatible options --deblock and --no-deblock\n");
2499 return -1;
2501 if (hb_validate_filter_settings(HB_FILTER_DEBLOCK, deblock))
2503 fprintf(stderr, "Invalid deblock option %s\n", deblock);
2504 return -1;
2508 if (detelecine != NULL)
2510 if (detelecine_disable)
2512 fprintf(stderr,
2513 "Incompatible options --detelecine and --no-detelecine\n");
2514 return -1;
2516 if (!hb_validate_filter_preset(HB_FILTER_DETELECINE,
2517 detelecine, NULL))
2519 // Nothing to do, but must validate preset before
2520 // attempting to validate custom settings to prevent potential
2521 // false positive
2523 else if (!hb_validate_filter_settings(HB_FILTER_DETELECINE, detelecine))
2525 detelecine_custom = 1;
2527 else
2529 fprintf(stderr, "Invalid detelecine option %s\n", detelecine);
2530 return -1;
2534 if (deinterlace != NULL)
2536 if (deinterlace_disable)
2538 fprintf(stderr,
2539 "Incompatible options --deinterlace and --no-deinterlace\n");
2540 return -1;
2542 if (!hb_validate_filter_preset(HB_FILTER_DEINTERLACE,
2543 deinterlace, NULL))
2545 // Nothing to do, but must validate preset before
2546 // attempting to validate custom settings to prevent potential
2547 // false positive
2549 else if (!hb_validate_filter_settings(HB_FILTER_DEINTERLACE, deinterlace))
2551 deinterlace_custom = 1;
2553 else
2555 fprintf(stderr, "Invalid deinterlace option %s\n", deinterlace);
2556 return -1;
2560 if (decomb != NULL)
2562 if (decomb_disable)
2564 fprintf(stderr,
2565 "Incompatible options --decomb and --no-decomb\n");
2566 return -1;
2568 if (!hb_validate_filter_preset(HB_FILTER_DECOMB, decomb, NULL))
2570 // Nothing to do, but must validate preset before
2571 // attempting to validate custom settings to prevent potential
2572 // false positive
2574 else if (!hb_validate_filter_settings(HB_FILTER_DECOMB, decomb))
2576 decomb_custom = 1;
2578 else
2580 fprintf(stderr, "Invalid decomb option %s\n", decomb);
2581 return -1;
2585 if (hqdn3d != NULL)
2587 if (hqdn3d_disable)
2589 fprintf(stderr,
2590 "Incompatible options --hqdn3d and --no-hqdn3d\n");
2591 return -1;
2593 if (!hb_validate_filter_preset(HB_FILTER_HQDN3D, hqdn3d, NULL))
2595 // Nothing to do, but must validate preset before
2596 // attempting to validate custom settings to prevent potential
2597 // false positive
2599 else if (!hb_validate_filter_settings(HB_FILTER_HQDN3D, hqdn3d))
2601 hqdn3d_custom = 1;
2603 else
2605 fprintf(stderr, "Invalid hqdn3d option %s\n", hqdn3d);
2606 return -1;
2610 if (nlmeans != NULL)
2612 if (nlmeans_disable)
2614 fprintf(stderr,
2615 "Incompatible options --nlmeans and --no-nlmeans\n");
2616 return -1;
2618 if (!hb_validate_filter_preset(HB_FILTER_NLMEANS, nlmeans, nlmeans_tune))
2620 // Nothing to do, but must validate preset before
2621 // attempting to validate custom settings to prevent potential
2622 // false positive
2624 else if (!hb_validate_filter_settings(HB_FILTER_NLMEANS, nlmeans))
2626 nlmeans_custom = 1;
2628 else
2630 fprintf(stderr, "Invalid nlmeans option %s\n", nlmeans);
2631 return -1;
2635 return 0;
2638 static int foreign_audio_scan(char **subtracks)
2640 if (subtracks != NULL)
2642 int count = str_vlen(subtracks);
2643 int ii;
2644 for (ii = 0; ii < count; ii++)
2646 if (!strcasecmp(subtracks[0], "scan"))
2648 return 1;
2652 return 0;
2655 static int count_subtitles(char **subtracks)
2657 int subtitle_track_count = 0;
2658 if (subtracks != NULL)
2660 int count = str_vlen(subtracks);
2661 int ii;
2662 for (ii = 0; ii < count; ii++)
2664 if (strcasecmp(subtracks[0], "scan") &&
2665 strcasecmp(subtracks[0], "none"))
2667 subtitle_track_count++;
2671 return subtitle_track_count;
2674 static int CheckOptions( int argc, char ** argv )
2676 if( update )
2678 return 0;
2681 if (preset_export_name == NULL && (input == NULL || *input == '\0'))
2683 fprintf( stderr, "Missing input device. Run %s --help for "
2684 "syntax.\n", argv[0] );
2685 return 1;
2688 /* Parse format */
2689 if (titleindex > 0 && !titlescan)
2691 if (preset_export_name == NULL && (output == NULL || *output == '\0'))
2693 fprintf( stderr, "Missing output file name. Run %s --help "
2694 "for syntax.\n", argv[0] );
2695 return 1;
2698 if (format == NULL && output != NULL)
2700 /* autodetect */
2701 const char *extension = strrchr(output, '.');
2702 if (extension != NULL)
2704 // skip '.'
2705 mux = hb_container_get_from_extension(extension + 1);
2707 hb_container_t * c = hb_container_get_from_format(mux);
2708 if (c != NULL)
2709 format = strdup(c->short_name);
2713 int subtitle_track_count = count_subtitles(subtracks);
2714 if (subtitle_track_count > 0 && subtitle_lang_list != NULL)
2716 fprintf(stderr,
2717 "Incompatible options: --subtitle-lang-list and --subtitle\n");
2718 return 1;
2721 if (subtitle_track_count > 0 && subtitle_all != -1)
2723 fprintf(stderr,
2724 "Incompatible options: --all-subtitles/--first-subtitle and --subtitle\n");
2725 return 1;
2728 if (atracks != NULL && audio_lang_list != NULL)
2730 fprintf(stderr,
2731 "Incompatible options: --audio-lang-list and --audio\n");
2732 return 1;
2735 if (atracks != NULL && audio_all != -1)
2737 fprintf(stderr,
2738 "Incompatible options: --all-audio/--first-audio and --audio\n");
2739 return 1;
2742 if ((par_width > 0 && par_height > 0) && display_width > 0)
2744 fprintf(stderr,
2745 "Incompatible options: --display-width and --pixel-aspect\n");
2746 return 1;
2749 if (preset_export_file != NULL && preset_export_name == NULL)
2751 fprintf(stderr,
2752 "Error: --preset-export-file requires option --preset-export\n");
2753 return 1;
2756 if (preset_export_desc != NULL && preset_export_name == NULL)
2758 fprintf(stderr,
2759 "Error: --preset-export-desc requires option --preset-export\n");
2760 return 1;
2763 return 0;
2766 static hb_dict_t * PreparePreset(const char *preset_name)
2768 int ii;
2769 hb_dict_t *preset;
2771 if (preset_name != NULL)
2773 preset = hb_preset_search(preset_name, 1 /*recurse*/);
2774 if (preset == NULL)
2776 fprintf(stderr, "Invalid preset %s\n"
2777 "Valid presets are:\n", preset_name);
2778 ShowPresets(NULL, 1, 1);
2779 return NULL;
2782 else
2784 preset = hb_presets_get_default();
2786 if (preset == NULL)
2788 fprintf(stderr, "Error loading presets! Aborting.\n");
2789 return NULL;
2791 preset = hb_value_dup(preset);
2793 int subtitle_track_count = count_subtitles(subtracks);
2794 // Apply any overrides that can be made directly to the preset
2795 if (format != NULL)
2797 hb_dict_set(preset, "FileFormat", hb_value_string(format));
2799 if (mp4_optimize != -1)
2801 hb_dict_set(preset, "Mp4HttpOptimize", hb_value_bool(mp4_optimize));
2803 if (ipod_atom != -1)
2805 hb_dict_set(preset, "Mp4iPodCompatible", hb_value_bool(ipod_atom));
2807 if (chapter_markers != -1)
2809 hb_dict_set(preset, "ChapterMarkers", hb_value_bool(chapter_markers));
2811 hb_value_array_t *subtitle_lang_array;
2812 subtitle_lang_array = hb_dict_get(preset, "SubtitleLanguageList");
2813 if (subtitle_lang_array == NULL)
2815 subtitle_lang_array = hb_value_array_init();
2816 hb_dict_set(preset, "SubtitleLanguageList", subtitle_lang_array);
2818 if (subtitle_lang_list != NULL)
2820 hb_value_array_clear(subtitle_lang_array);
2821 int count = str_vlen(subtitle_lang_list);
2822 for (ii = 0; ii < count; ii++)
2824 const iso639_lang_t *lang = lang_lookup(subtitle_lang_list[ii]);
2825 if (lang != NULL)
2827 hb_value_array_append(subtitle_lang_array,
2828 hb_value_string(lang->iso639_2));
2830 else
2832 fprintf(stderr, "Warning: Invalid subtitle language (%s)\n",
2833 subtitle_lang_list[ii]);
2834 return NULL;
2837 hb_dict_set(preset, "SubtitleTrackSelectionBehavior",
2838 hb_value_string("first"));
2840 if (native_language != NULL)
2842 // Add native language subtitles if audio is not native
2843 lang_list_remove(subtitle_lang_array, native_language);
2844 hb_value_array_insert(subtitle_lang_array, 0,
2845 hb_value_string(native_language));
2846 hb_dict_set(preset, "SubtitleAddForeignAudioSubtitle",
2847 hb_value_bool(1));
2849 if (foreign_audio_scan(subtracks))
2851 // Add foreign audio search
2852 hb_dict_set(preset, "SubtitleAddForeignAudioSearch", hb_value_bool(1));
2854 // Subtitle burn behavior
2855 const char *burn = "none";
2856 if (subtitle_track_count == 0)
2858 if (subburn_native && subburn == 1)
2860 burn = "foreign_first";
2862 else if (subburn_native)
2864 burn = "foreign";
2866 else if (subburn == 1)
2868 burn = "first";
2871 else
2873 if (subburn_native)
2875 burn = "foreign";
2878 hb_dict_set(preset, "SubtitleBurnBehavior", hb_value_string(burn));
2879 const char *selection = NULL;
2880 if (subtitle_track_count == 0 && subtitle_all != -1)
2882 selection = subtitle_all == 1 ? "all" : "first";
2884 else
2886 selection = "none";
2888 if (selection != NULL)
2890 hb_dict_set(preset, "SubtitleTrackSelectionBehavior",
2891 hb_value_string(selection));
2894 if (audio_copy_list != NULL)
2896 // Create autopassthru copy mask
2897 hb_value_array_t *array = hb_value_array_init();
2898 for (ii = 0; audio_copy_list[ii] != NULL; ii++)
2900 hb_value_array_append(array, hb_value_string(audio_copy_list[ii]));
2902 hb_dict_set(preset, "AudioCopyMask", array);
2904 if (acodec_fallback != NULL)
2906 hb_dict_set(preset, "AudioEncoderFallback",
2907 hb_value_string(acodec_fallback));
2910 hb_value_array_t *audio_lang_array;
2911 audio_lang_array = hb_dict_get(preset, "AudioLanguageList");
2912 if (audio_lang_array == NULL)
2914 audio_lang_array = hb_value_array_init();
2915 hb_dict_set(preset, "AudioLanguageList", audio_lang_array);
2917 if (audio_lang_list != NULL)
2919 hb_value_array_clear(audio_lang_array);
2920 int count = str_vlen(audio_lang_list);
2921 for (ii = 0; ii < count; ii++)
2923 const iso639_lang_t *lang = lang_lookup(audio_lang_list[ii]);
2924 if (lang != NULL)
2926 hb_value_array_append(audio_lang_array,
2927 hb_value_string(lang->iso639_2));
2929 else
2931 fprintf(stderr, "Warning: Invalid audio language (%s)\n",
2932 audio_lang_list[ii]);
2933 return NULL;
2936 hb_dict_set(preset, "AudioTrackSelectionBehavior",
2937 hb_value_string("first"));
2939 if (native_dub && native_language)
2941 // Add native language audio
2942 lang_list_remove(audio_lang_array, native_language);
2943 hb_value_array_insert(audio_lang_array, 0,
2944 hb_value_string(native_language));
2946 if (audio_all != -1)
2948 hb_dict_set(preset, "AudioTrackSelectionBehavior",
2949 hb_value_string(audio_all == 1 ? "all" : "first"));
2952 // Audio overrides
2953 if (atracks == NULL && (
2954 acodecs != NULL ||
2955 abitrates != NULL ||
2956 arates != NULL ||
2957 mixdowns != NULL ||
2958 normalize_mix_level != NULL ||
2959 audio_dither != NULL ||
2960 dynamic_range_compression != NULL ||
2961 audio_gain != NULL ||
2962 aqualities != NULL ||
2963 acompressions != NULL ||
2964 anames != NULL))
2966 // No explicit audio tracks, but track settings modified.
2967 // Modify the presets audio settings.
2968 hb_value_array_t *list;
2969 list = hb_dict_get(preset, "AudioList");
2970 if (list == NULL)
2972 list = hb_value_array_init();
2973 hb_dict_set(preset, "AudioList", list);
2975 int count = MAX(str_vlen(mixdowns),
2976 MAX(str_vlen(dynamic_range_compression),
2977 MAX(str_vlen(audio_gain),
2978 MAX(str_vlen(audio_dither),
2979 MAX(str_vlen(normalize_mix_level),
2980 MAX(str_vlen(arates),
2981 MAX(str_vlen(abitrates),
2982 MAX(str_vlen(aqualities),
2983 MAX(str_vlen(acompressions),
2984 MAX(str_vlen(acodecs),
2985 str_vlen(anames)))))))))));
2987 hb_dict_t *audio_dict;
2988 // Add audio dict entries to list if needed
2989 for (ii = 0; ii < count; ii++)
2991 audio_dict = hb_value_array_get(list, ii);
2992 if (audio_dict == NULL)
2994 audio_dict = hb_dict_init();
2995 hb_value_array_append(list, audio_dict);
2999 // Update codecs
3000 if (str_vlen(acodecs) > 0)
3002 for (ii = 0; acodecs[ii] != NULL; ii++)
3004 audio_dict = hb_value_array_get(list, ii);
3005 hb_dict_set(audio_dict, "AudioEncoder",
3006 hb_value_string(acodecs[ii]));
3008 // Apply last codec in list to all other entries
3009 for (; ii < count; ii++)
3011 audio_dict = hb_value_array_get(list, ii);
3012 hb_dict_set(audio_dict, "AudioEncoder",
3013 hb_value_string(acodecs[ii-1]));
3017 // Update qualities
3018 if (str_vlen(aqualities) > 0)
3020 for (ii = 0; aqualities[ii] != NULL &&
3021 aqualities[ii][0] != 0; ii++)
3023 audio_dict = hb_value_array_get(list, ii);
3024 hb_dict_set(audio_dict, "AudioTrackQualityEnable",
3025 hb_value_bool(1));
3026 hb_dict_set(audio_dict, "AudioTrackQuality",
3027 hb_value_double(strtod(aqualities[ii], NULL)));
3031 // Update bitrates
3032 if (str_vlen(abitrates) > 0)
3034 for (ii = 0; abitrates[ii] != NULL &&
3035 abitrates[ii][0] != 0; ii++)
3037 audio_dict = hb_value_array_get(list, ii);
3038 if (hb_value_get_bool(hb_dict_get(audio_dict,
3039 "AudioTrackQualityEnable")))
3041 continue;
3043 hb_dict_set(audio_dict, "AudioBitrate",
3044 hb_value_int(atoi(abitrates[ii])));
3046 // Apply last bitrate in list to all other entries
3047 if (abitrates[ii-1][0] != 0)
3048 for (; ii < count; ii++)
3050 audio_dict = hb_value_array_get(list, ii);
3051 if (hb_value_get_bool(hb_dict_get(audio_dict,
3052 "AudioTrackQualityEnable")))
3054 continue;
3056 hb_dict_set(audio_dict, "AudioBitrate",
3057 hb_value_int(atoi(abitrates[ii-1])));
3061 // Update samplerates
3062 if (str_vlen(arates) > 0)
3064 for (ii = 0; arates[ii] != NULL &&
3065 arates[ii][0] != 0; ii++)
3067 audio_dict = hb_value_array_get(list, ii);
3068 hb_dict_set(audio_dict, "AudioSamplerate",
3069 hb_value_string(arates[ii]));
3071 // Apply last samplerate in list to all other entries
3072 if (arates[ii-1][0] != 0)
3073 for (; ii < count; ii++)
3075 audio_dict = hb_value_array_get(list, ii);
3076 hb_dict_set(audio_dict, "AudioSamplerate",
3077 hb_value_string(arates[ii-1]));
3081 // Update mixdowns
3082 if (str_vlen(mixdowns) > 0)
3084 for (ii = 0; mixdowns[ii] != NULL &&
3085 mixdowns[ii][0] != 0; ii++)
3087 audio_dict = hb_value_array_get(list, ii);
3088 hb_dict_set(audio_dict, "AudioMixdown",
3089 hb_value_string(mixdowns[ii]));
3091 // Apply last codec in list to all other entries
3092 if (mixdowns[ii-1][0] != 0)
3093 for (; ii < count; ii++)
3095 audio_dict = hb_value_array_get(list, ii);
3096 hb_dict_set(audio_dict, "AudioMixdown",
3097 hb_value_string(mixdowns[ii-1]));
3101 // Update mixdowns normalization
3102 if (str_vlen(normalize_mix_level) > 0)
3104 for (ii = 0; normalize_mix_level[ii] != NULL &&
3105 normalize_mix_level[ii][0] != 0; ii++)
3107 audio_dict = hb_value_array_get(list, ii);
3108 hb_dict_set(audio_dict, "AudioNormalizeMixLevel",
3109 hb_value_bool(atoi(normalize_mix_level[ii])));
3111 // Apply last mix norm in list to all other entries
3112 if (normalize_mix_level[ii-1][0] != 0)
3113 for (; ii < count; ii++)
3115 audio_dict = hb_value_array_get(list, ii);
3116 hb_dict_set(audio_dict,
3117 "AudioNormalizeMixLevel",
3118 hb_value_bool(
3119 atoi(normalize_mix_level[ii-1])));
3123 // Update DRC
3124 if (str_vlen(dynamic_range_compression) > 0)
3126 for (ii = 0;dynamic_range_compression[ii] != NULL &&
3127 dynamic_range_compression[ii][0] != 0; ii++)
3129 audio_dict = hb_value_array_get(list, ii);
3130 hb_dict_set(audio_dict, "AudioTrackDRCSlider",
3131 hb_value_double(
3132 strtod(dynamic_range_compression[ii], NULL)));
3134 // Apply last DRC in list to all other entries
3135 if (dynamic_range_compression[ii-1][0] != 0)
3136 for (; ii < count; ii++)
3138 audio_dict = hb_value_array_get(list, ii);
3139 hb_dict_set(audio_dict, "AudioTrackDRCSlider",
3140 hb_value_double(
3141 strtod(dynamic_range_compression[ii-1],
3142 NULL)));
3146 // Update Gain
3147 if (str_vlen(audio_gain) > 0)
3149 for (ii = 0; audio_gain[ii] != NULL &&
3150 audio_gain[ii][0] != 0; ii++)
3152 audio_dict = hb_value_array_get(list, ii);
3153 hb_dict_set(audio_dict, "AudioTrackGainSlider",
3154 hb_value_double(
3155 strtod(audio_gain[ii], NULL)));
3157 // Apply last gain in list to all other entries
3158 if (audio_gain[ii-1][0] != 0)
3159 for (; ii < count; ii++)
3161 audio_dict = hb_value_array_get(list, ii);
3162 hb_dict_set(audio_dict, "AudioTrackGainSlider",
3163 hb_value_double(
3164 strtod(audio_gain[ii-1], NULL)));
3168 // Update dither method
3169 if (str_vlen(audio_dither) > 0)
3171 for (ii = 0; audio_dither[ii] != NULL &&
3172 audio_dither[ii][0] != 0; ii++)
3174 audio_dict = hb_value_array_get(list, ii);
3175 hb_dict_set(audio_dict, "AudioDitherMethod",
3176 hb_value_string(audio_dither[ii]));
3178 // Apply last dither in list to all other entries
3179 if (audio_dither[ii-1][0] != 0)
3180 for (; ii < count; ii++)
3182 audio_dict = hb_value_array_get(list, ii);
3183 hb_dict_set(audio_dict, "AudioDitherMethod",
3184 hb_value_string(audio_dither[ii-1]));
3188 // Update compression
3189 if (str_vlen(acompressions) > 0)
3191 for (ii = 0; acompressions[ii] != NULL &&
3192 acompressions[ii][0] != 0; ii++)
3194 audio_dict = hb_value_array_get(list, ii);
3195 hb_dict_set(audio_dict, "AudioCompressionLevel",
3196 hb_value_double(
3197 strtod(acompressions[ii], NULL)));
3199 // Apply last compression in list to all other entries
3200 if (acompressions[ii-1][0] != 0)
3201 for (; ii < count; ii++)
3203 audio_dict = hb_value_array_get(list, ii);
3204 hb_dict_set(audio_dict, "AudioCompressionLevel",
3205 hb_value_double(
3206 strtod(acompressions[ii-1], NULL)));
3210 // Update track names
3211 if (str_vlen(anames) > 0)
3213 for (ii = 0; anames[ii] != NULL &&
3214 anames[ii][0] != 0; ii++)
3216 audio_dict = hb_value_array_get(list, ii);
3217 hb_dict_set(audio_dict, "AudioTrackName",
3218 hb_value_string(acodecs[ii]));
3223 if (atracks != NULL)
3225 // User has specified explicit audio tracks
3226 // Disable preset's audio track selection
3227 hb_dict_set(preset, "AudioTrackSelectionBehavior",
3228 hb_value_string("none"));
3231 if (vcodec != NULL)
3233 const char *s;
3234 int old, new;
3236 s = hb_value_get_string(hb_dict_get(preset, "VideoEncoder"));
3237 old = hb_video_encoder_get_from_name(s);
3238 new = hb_video_encoder_get_from_name(vcodec);
3239 if (old != new)
3241 // If the user explicitly changes a video encoder, remove the
3242 // preset VideoPreset, VideoTune, VideoProfile, VideoLevel, and
3243 // VideoOptionExtra.
3245 // Use defaults for the encoder since these settings may not be
3246 // compatible across encoders.
3247 hb_dict_remove(preset, "VideoPreset");
3248 hb_dict_remove(preset, "VideoTune");
3249 hb_dict_remove(preset, "VideoProfile");
3250 hb_dict_remove(preset, "VideoLevel");
3251 hb_dict_remove(preset, "VideoOptionExtra");
3253 hb_dict_set(preset, "VideoEncoder", hb_value_string(vcodec));
3255 if (encoder_preset != NULL)
3257 hb_dict_set(preset, "VideoPreset", hb_value_string(encoder_preset));
3259 if (encoder_tune != NULL)
3261 hb_dict_set(preset, "VideoTune", hb_value_string(encoder_tune));
3263 if (encoder_profile != NULL)
3265 hb_dict_set(preset, "VideoProfile", hb_value_string(encoder_profile));
3267 if (encoder_level != NULL)
3269 hb_dict_set(preset, "VideoLevel", hb_value_string(encoder_level));
3271 if (advanced_opts != NULL)
3273 hb_dict_set(preset, "VideoOptionExtra", hb_value_string(advanced_opts));
3275 if (vquality >= 0)
3277 hb_dict_set(preset, "VideoQualityType", hb_value_int(2));
3278 hb_dict_set(preset, "VideoQualitySlider", hb_value_double(vquality));
3280 else if (vbitrate != 0)
3282 hb_dict_set(preset, "VideoQualityType", hb_value_int(1));
3283 hb_dict_set(preset, "VideoAvgBitrate", hb_value_int(vbitrate));
3284 if (twoPass)
3286 hb_dict_set(preset, "VideoTwoPass", hb_value_bool(1));
3288 if (fastfirstpass)
3290 hb_dict_set(preset, "VideoTurboTwoPass", hb_value_bool(1));
3293 if (vrate != NULL)
3295 hb_dict_set(preset, "VideoFramerate", hb_value_string(vrate));
3297 else
3299 hb_dict_set(preset, "VideoFramerate", hb_value_string("auto"));
3301 if (cfr != -1)
3303 hb_dict_set(preset, "VideoFramerateMode",
3304 hb_value_string(cfr == 0 ? "vfr" :
3305 cfr == 1 ? "cfr" : "pfr"));
3307 if (color_matrix_code > 0)
3309 hb_dict_set(preset, "VideoColorMatrixCode",
3310 hb_value_int(color_matrix_code));
3312 #ifdef USE_QSV
3313 if (qsv_async_depth >= 0)
3315 hb_dict_set(preset, "VideoQSVAsyncDepth",
3316 hb_value_int(qsv_async_depth));
3318 if (qsv_decode != -1)
3320 hb_dict_set(preset, "VideoQSVDecode", hb_value_int(qsv_decode));
3322 #endif
3323 if (use_hwd != -1)
3325 hb_dict_set(preset, "VideoHWDecode", hb_value_bool(use_hwd));
3327 if (use_opencl != -1)
3329 hb_dict_set(preset, "VideoScaler",
3330 hb_value_string(use_opencl ? "opencl" : "swscale"));
3332 if (maxWidth > 0)
3334 hb_dict_set(preset, "PictureWidth", hb_value_int(maxWidth));
3336 if (maxHeight > 0)
3338 hb_dict_set(preset, "PictureHeight", hb_value_int(maxHeight));
3340 if (width > 0)
3342 hb_dict_set(preset, "PictureForceWidth", hb_value_int(width));
3344 if (height > 0)
3346 hb_dict_set(preset, "PictureForceHeight", hb_value_int(height));
3348 if (crop[0] >= 0 || crop[1] >= 0 || crop[2] >= 0 || crop[3] >= 0)
3350 hb_dict_set(preset, "PictureAutoCrop", hb_value_bool(0));
3352 if (crop[0] >= 0)
3354 hb_dict_set(preset, "PictureTopCrop", hb_value_int(crop[0]));
3356 if (crop[1] >= 0)
3358 hb_dict_set(preset, "PictureBottomCrop", hb_value_int(crop[1]));
3360 if (crop[2] >= 0)
3362 hb_dict_set(preset, "PictureLeftCrop", hb_value_int(crop[2]));
3364 if (crop[3] >= 0)
3366 hb_dict_set(preset, "PictureRightCrop", hb_value_int(crop[3]));
3368 if (loose_crop != -1)
3370 hb_dict_set(preset, "PictureLooseCrop", hb_value_bool(loose_crop));
3372 if (display_width > 0)
3374 keep_display_aspect = 0;
3375 anamorphic_mode = 3;
3376 hb_dict_set(preset, "PictureDARWidth", hb_value_int(display_width));
3378 else if (par_width > 0 && par_height > 0)
3380 keep_display_aspect = 0;
3381 anamorphic_mode = 3;
3382 hb_dict_set(preset, "PicturePARWidth", hb_value_int(par_width));
3383 hb_dict_set(preset, "PicturePARHeight", hb_value_int(par_height));
3385 if (anamorphic_mode != -1)
3387 hb_dict_set(preset, "PicturePAR", hb_value_int(anamorphic_mode));
3389 if (keep_display_aspect != -1)
3391 hb_dict_set(preset, "PictureKeepRatio",
3392 hb_value_bool(keep_display_aspect));
3394 if (itu_par != -1)
3396 hb_dict_set(preset, "PictureItuPAR", hb_value_bool(itu_par));
3398 if (modulus > 0)
3400 hb_dict_set(preset, "PictureModulus", hb_value_int(modulus));
3402 if (grayscale != -1)
3404 hb_dict_set(preset, "VideoGrayScale", hb_value_bool(grayscale));
3406 if (deinterlace_disable)
3408 hb_dict_set(preset, "PictureDeinterlace", hb_value_string("off"));
3410 if (deinterlace != NULL)
3412 hb_dict_set(preset, "PictureDecombDeinterlace", hb_value_int(0));
3413 if (!deinterlace_custom)
3415 hb_dict_set(preset, "PictureDeinterlace",
3416 hb_value_string(deinterlace));
3418 else
3420 hb_dict_set(preset, "PictureDeinterlace",
3421 hb_value_string("custom"));
3422 hb_dict_set(preset, "PictureDeinterlaceCustom",
3423 hb_value_string(deinterlace));
3426 if (decomb_disable)
3428 hb_dict_set(preset, "PictureDecomb", hb_value_string("off"));
3430 if (decomb != NULL)
3432 hb_dict_set(preset, "PictureDecombDeinterlace", hb_value_int(1));
3433 if (!decomb_custom)
3435 hb_dict_set(preset, "PictureDecomb", hb_value_string(decomb));
3437 else
3439 hb_dict_set(preset, "PictureDecomb", hb_value_string("custom"));
3440 hb_dict_set(preset, "PictureDecombCustom", hb_value_string(decomb));
3443 if (detelecine_disable)
3445 hb_dict_set(preset, "PictureDetelecine", hb_value_string("off"));
3447 if (detelecine != NULL)
3449 if (!detelecine_custom)
3451 hb_dict_set(preset, "PictureDetelecine",
3452 hb_value_string(detelecine));
3454 else
3456 hb_dict_set(preset, "PictureDetelecine", hb_value_string("custom"));
3457 hb_dict_set(preset, "PictureDetelecineCustom",
3458 hb_value_string(detelecine));
3461 const char *s;
3462 s = hb_value_get_string(hb_dict_get(preset, "PictureDenoiseFilter"));
3463 if (hqdn3d_disable && !strcasecmp(s, "hqdn3d"))
3465 hb_dict_set(preset, "PictureDenoiseFilter", hb_value_string("off"));
3467 if (hqdn3d != NULL)
3469 hb_dict_set(preset, "PictureDenoiseFilter", hb_value_string("hqdn3d"));
3470 if (!hqdn3d_custom)
3472 hb_dict_set(preset, "PictureDenoisePreset",
3473 hb_value_string(hqdn3d));
3475 else
3477 hb_dict_set(preset, "PictureDenoisePreset",
3478 hb_value_string("custom"));
3479 hb_dict_set(preset, "PictureDenoiseCustom",
3480 hb_value_string(hqdn3d));
3483 if (nlmeans_disable && !strcasecmp(s, "nlmeans"))
3485 hb_dict_set(preset, "PictureDenoiseFilter", hb_value_string("off"));
3487 if (nlmeans != NULL)
3489 hb_dict_set(preset, "PictureDenoiseFilter", hb_value_string("nlmeans"));
3490 if (!nlmeans_custom)
3492 hb_dict_set(preset, "PictureDenoisePreset",
3493 hb_value_string(nlmeans));
3494 if (nlmeans_tune != NULL)
3496 hb_dict_set(preset, "PictureDenoiseTune",
3497 hb_value_string(nlmeans_tune));
3500 else
3502 hb_dict_set(preset, "PictureDenoisePreset",
3503 hb_value_string("custom"));
3504 hb_dict_set(preset, "PictureDenoiseCustom",
3505 hb_value_string(nlmeans));
3508 if (deblock_disable)
3510 hb_dict_set(preset, "PictureDeblock", hb_value_string("0"));
3512 if (deblock != NULL)
3514 hb_dict_set(preset, "PictureDeblock", hb_value_string(deblock));
3516 if (rotate != NULL)
3518 hb_dict_set(preset, "PictureRotate", hb_value_string(rotate));
3521 return preset;
3525 static int add_sub(hb_value_array_t *list, hb_title_t *title, int track, int *one_burned)
3527 hb_subtitle_t *subtitle;
3528 // Check that the track exists
3529 subtitle = hb_list_item(title->list_subtitle, track);
3530 if (subtitle == NULL)
3532 fprintf(stderr, "Warning: Could not find subtitle track %d, skipped\n",
3533 track + 1);
3534 return -1;
3537 int burn = !*one_burned && subburn == track + 1 &&
3538 hb_subtitle_can_burn(subtitle->source);
3539 *one_burned |= burn;
3540 int def = subdefault == track + 1;
3541 int force = test_sub_list(subforce, track + 1);
3543 if (!burn &&
3544 !hb_subtitle_can_pass(subtitle->source, mux))
3546 // Only allow one subtitle to be burned into video
3547 if (*one_burned)
3549 fprintf(stderr, "Warning: Skipping subtitle track %d, can't have more than one track burnt in\n", track + 1);
3550 return -1;
3552 *one_burned = 1;
3554 hb_dict_t *subtitle_dict = hb_dict_init();
3555 hb_dict_set(subtitle_dict, "Track", hb_value_int(track));
3556 hb_dict_set(subtitle_dict, "Default", hb_value_bool(def));
3557 hb_dict_set(subtitle_dict, "Forced", hb_value_bool(force));
3558 hb_dict_set(subtitle_dict, "Burn", hb_value_bool(burn));
3559 hb_value_array_append(list, subtitle_dict);
3560 return 0;
3563 static int add_srt(hb_value_array_t *list, int track, int *one_burned)
3565 char *codeset = "ISO-8859-1";
3566 int64_t offset = 0;
3567 char *iso639_2 = "und";
3568 int burn = !*one_burned && srtburn == track + 1 &&
3569 hb_subtitle_can_burn(SRTSUB);
3570 *one_burned |= burn;
3571 int def = srtdefault == track + 1;
3573 if (srtcodeset && track < str_vlen(srtcodeset) && srtcodeset[track])
3574 codeset = srtcodeset[track];
3575 if (srtoffset && track < str_vlen(srtoffset) && srtoffset[track])
3576 offset = strtoll(srtoffset[track], NULL, 0);
3577 if (srtlang && track < str_vlen(srtlang) && srtlang[track])
3579 const iso639_lang_t *lang = lang_lookup(srtlang[track]);
3580 if (lang != NULL)
3582 iso639_2 = lang->iso639_2;
3584 else
3586 fprintf(stderr, "Warning: Invalid SRT language (%s)\n",
3587 srtlang[track]);
3591 hb_dict_t *subtitle_dict = hb_dict_init();
3592 hb_dict_t *srt_dict = hb_dict_init();
3593 hb_dict_set(subtitle_dict, "SRT", srt_dict);
3594 hb_dict_set(subtitle_dict, "Default", hb_value_bool(def));
3595 hb_dict_set(subtitle_dict, "Burn", hb_value_bool(burn));
3596 hb_dict_set(subtitle_dict, "Offset", hb_value_int(offset));
3597 hb_dict_set(srt_dict, "Filename", hb_value_string(srtfile[track]));
3598 hb_dict_set(srt_dict, "Language", hb_value_string(iso639_2));
3599 hb_dict_set(srt_dict, "Codeset", hb_value_string(codeset));
3600 hb_value_array_append(list, subtitle_dict);
3601 return 0;
3604 static int add_audio(hb_value_array_t *list, hb_title_t *title, int track)
3606 // Check that the track exists
3607 if (hb_list_item(title->list_audio, track-1) == NULL)
3609 fprintf(stderr, "Warning: Could not find audio track %d, skipped\n",
3610 track);
3611 return -1;
3613 hb_dict_t *audio_dict = hb_dict_init();
3614 hb_dict_set(audio_dict, "Track", hb_value_int(track-1));
3615 hb_value_array_append(list, audio_dict);
3617 return 0;
3620 static hb_dict_t*
3621 PrepareJob(hb_handle_t *h, hb_title_t *title, hb_dict_t *preset_dict)
3623 hb_dict_t *job_dict;
3624 job_dict = hb_preset_job_init(h, title->index, preset_dict);
3625 if (job_dict == NULL)
3627 fprintf(stderr, "Failed to initialize job\n");
3628 return NULL;
3631 if (hb_value_get_bool(hb_dict_get(job_dict, "ChapterMarkers")))
3633 write_chapter_names(job_dict, marker_file);
3636 hb_dict_t *dest_dict = hb_dict_get(job_dict, "Destination");
3637 hb_dict_set(dest_dict, "File", hb_value_string(output));
3639 // Now that the job is initialized, we need to find out
3640 // what muxer is being used.
3641 mux = hb_container_get_from_name(
3642 hb_value_get_string(hb_dict_get(dest_dict, "Mux")));
3644 // Now set non-preset settings in the job dict
3645 int range_start = 0, range_end = 0, range_seek_points = 0;
3646 const char *range_type = "chapter";
3647 if (chapter_start && chapter_end &&
3648 !start_at_pts && !stop_at_pts &&
3649 !start_at_frame && !stop_at_frame &&
3650 !start_at_preview )
3652 range_type = "chapter";
3653 int chapter_count = hb_list_count(title->list_chapter);
3654 range_start = MAX(1, chapter_start);
3655 range_end = MAX(chapter_start, MIN(chapter_count, chapter_end));
3657 else if (start_at_preview)
3659 range_type = "preview";
3660 range_start = start_at_preview -1;
3661 range_end = stop_at_pts;
3662 range_seek_points = preview_count;
3664 else if (start_at_pts || stop_at_pts)
3666 range_type = "time";
3667 range_start = start_at_pts;
3668 range_end = stop_at_pts;
3670 else if (start_at_frame || stop_at_frame)
3672 range_type = "frame";
3673 range_start = start_at_frame;
3674 range_end = stop_at_frame;
3676 if (range_start || range_end)
3678 hb_dict_t *range_dict = hb_dict_get(
3679 hb_dict_get(job_dict, "Source"), "Range");
3680 hb_dict_set(range_dict, "Type", hb_value_string(range_type));
3681 if (range_start)
3682 hb_dict_set(range_dict, "Start", hb_value_int(range_start));
3683 else
3684 hb_dict_remove(range_dict, "Start");
3685 if (range_end)
3686 hb_dict_set(range_dict, "End", hb_value_int(range_end));
3687 else
3688 hb_dict_remove(range_dict, "End");
3689 if (range_seek_points)
3690 hb_dict_set(range_dict, "SeekPoints",
3691 hb_value_int(range_seek_points));
3694 if (angle)
3696 hb_dict_t *source_dict = hb_dict_get(job_dict, "Source");
3697 hb_dict_set(source_dict, "Angle", hb_value_int(angle));
3700 hb_dict_t *subtitles_dict = hb_dict_get(job_dict, "Subtitle");
3701 hb_value_array_t * subtitle_array;
3702 subtitle_array = hb_dict_get(subtitles_dict, "SubtitleList");
3704 hb_dict_t *audios_dict = hb_dict_get(job_dict, "Audio");
3705 hb_value_array_t * audio_array = hb_dict_get(audios_dict, "AudioList");
3706 hb_dict_t *audio_dict;
3708 /* Grab audio tracks */
3709 if (atracks != NULL)
3711 int track_count;
3712 int ii;
3713 if (atracks[0] != NULL && strcasecmp("none", atracks[0]))
3715 // First "track" is not "none", add tracks
3716 for (ii = 0; atracks[ii] != NULL; ii++)
3718 int first, last, track;
3719 if (sscanf(atracks[ii], "%d-%d", &first, &last ) == 2)
3721 for (track = first - 1; track < last; track++)
3723 add_audio(audio_array, title, track);
3726 else if (sscanf(atracks[ii], "%d", &track) == 1)
3728 add_audio(audio_array, title, track);
3730 else
3732 fprintf(stderr, "ERROR: unable to parse audio input \"%s\", skipping\n", atracks[ii]);
3736 track_count = hb_value_array_len(audio_array);
3738 // Now we need to take care of initializing subtitle selection
3739 // for foreign audio since this could not be done by the preset
3740 // due to disabling of preset audio selection.
3742 // Determine the language of the first audio track
3743 if (track_count > 0)
3745 audio_dict = hb_value_array_get(audio_array, 0);
3746 int track = hb_value_get_int(hb_dict_get(audio_dict, "Track"));
3748 hb_audio_config_t *audio;
3749 audio = hb_list_audio_config_item(title->list_audio, track);
3750 if (audio != NULL)
3752 hb_preset_job_add_subtitles(h, title->index,
3753 preset_dict, job_dict);
3757 /* Audio Codecs */
3758 int acodec;
3759 ii = 0;
3760 if (acodecs != NULL)
3762 for (; acodecs[ii] != NULL && ii < track_count; ii++)
3764 audio_dict = hb_value_array_get(audio_array, ii);
3765 acodec = hb_audio_encoder_get_from_name(acodecs[ii]);
3766 if (acodec <= 0)
3768 fprintf(stderr,
3769 "Invalid codec %s, using default for container.\n",
3770 acodecs[ii]);
3771 acodec = hb_audio_encoder_get_default(mux);
3773 hb_dict_set(audio_dict, "Encoder", hb_value_int(acodec));
3775 if (acodecs[ii] != NULL)
3777 fprintf(stderr, "Dropping excess audio encoders\n");
3780 if (ii != 1)
3782 acodec = hb_audio_encoder_get_default(mux);
3784 for (; ii < track_count; ii++)
3786 // We have fewer inputs than audio tracks, use the
3787 // default codec for this container for the remaining
3788 // tracks. Unless we only have one input then use that
3789 // codec instead.
3790 audio_dict = hb_value_array_get(audio_array, ii);
3791 hb_dict_set(audio_dict, "Encoder", hb_value_int(acodec));
3794 /* Sample Rate */
3795 int arate;
3796 ii = 0;
3797 if (arates != NULL)
3799 for (; arates[ii] != NULL && ii < track_count; ii++)
3801 if (!strcasecmp(arates[ii], "auto"))
3803 arate = 0;
3805 else
3807 arate = hb_audio_samplerate_get_from_name(arates[ii]);
3809 if (arate <= 0)
3811 fprintf(stderr, "Invalid sample rate %s, using input rate\n",
3812 arates[ii]);
3813 arate = 0;
3815 audio_dict = hb_value_array_get(audio_array, ii);
3816 hb_dict_set(audio_dict, "Samplerate", hb_value_int(arate));
3818 if (arates[ii] != NULL)
3820 fprintf(stderr, "Dropping excess audio sample rates\n");
3823 // If exactly one samplerate was specified, apply it to the reset
3824 // of the tracks.
3826 // For any tracks that we do not set the rate for, libhb will
3827 // assign the source audio track's rate
3828 if (ii == 1) for (; ii < track_count; ii++)
3830 audio_dict = hb_value_array_get(audio_array, ii);
3831 hb_dict_set(audio_dict, "Samplerate", hb_value_int(arate));
3834 /* Audio Mixdown */
3835 int mix;
3836 ii = 0;
3837 if (mixdowns != NULL)
3839 for (; mixdowns[ii] != NULL && ii < track_count; ii++)
3841 mix = hb_mixdown_get_from_name(mixdowns[ii]);
3842 audio_dict = hb_value_array_get(audio_array, ii);
3843 hb_dict_set(audio_dict, "Mixdown", hb_value_int(mix));
3845 if (mixdowns[ii] != NULL)
3847 fprintf(stderr, "Dropping excess audio mixdowns\n");
3850 // If exactly one mix was specified, apply it to the reset
3851 // of the tracks
3852 if (ii == 1) for (; ii < track_count; ii++)
3854 audio_dict = hb_value_array_get(audio_array, ii);
3855 hb_dict_set(audio_dict, "Mixdown", hb_value_int(mix));
3858 /* Audio Bitrate */
3859 int abitrate;
3860 ii = 0;
3861 if (abitrates != NULL)
3863 for (; abitrates[ii] != NULL && ii < track_count; ii++)
3865 if (*abitrates[ii])
3867 abitrate = atoi(abitrates[ii]);
3868 audio_dict = hb_value_array_get(audio_array, ii);
3869 hb_dict_set(audio_dict, "Bitrate", hb_value_int(abitrate));
3872 if (abitrates[ii] != NULL)
3874 fprintf(stderr, "Dropping excess audio bitrates\n");
3877 // If exactly one bitrate was specified, apply it to the reset
3878 // of the tracks
3879 if (ii == 1) for (; ii < track_count; ii++)
3881 audio_dict = hb_value_array_get(audio_array, ii);
3882 hb_dict_set(audio_dict, "Bitrate", hb_value_int(abitrate));
3885 /* Audio Quality */
3886 double aquality;
3887 ii = 0;
3888 if (aqualities != NULL)
3890 for (; aqualities[ii] != NULL && ii < track_count; ii++)
3892 if (*aqualities[ii])
3894 aquality = atof(aqualities[ii]);
3895 audio_dict = hb_value_array_get(audio_array, ii);
3896 hb_dict_set(audio_dict, "Quality",
3897 hb_value_double(aquality));
3898 hb_dict_set(audio_dict, "Bitrate", hb_value_int(-1));
3901 if (aqualities[ii] != NULL)
3903 fprintf(stderr, "Dropping excess audio qualities\n");
3906 // If exactly one quality was specified, apply it to the reset
3907 // of the tracks that do not already have the bitrate set.
3908 if (ii == 1) for (; ii < track_count; ii++)
3910 audio_dict = hb_value_array_get(audio_array, ii);
3911 abitrate = hb_value_get_int(hb_dict_get(audio_dict, "Bitrate"));
3912 if (abitrate <= 0)
3914 hb_dict_set(audio_dict, "Quality", hb_value_double(aquality));
3915 hb_dict_set(audio_dict, "Bitrate", hb_value_int(-1));
3919 /* Audio Compression Level */
3920 double acompression;
3921 ii = 0;
3922 if (acompressions != NULL)
3924 for (; acompressions[ii] != NULL && ii < track_count; ii++)
3926 if (*acompressions[ii])
3928 acompression = atof(acompressions[ii]);
3929 audio_dict = hb_value_array_get(audio_array, ii);
3930 hb_dict_set(audio_dict, "CompressionLevel",
3931 hb_value_double(acompression));
3934 if (acompressions[ii] != NULL)
3936 fprintf(stderr,
3937 "Dropping excess audio compression levels\n");
3940 // Compression levels are codec specific values. So don't
3941 // try to apply to other tracks.
3943 /* Audio DRC */
3944 ii = 0;
3945 double drc;
3946 if (dynamic_range_compression)
3948 char **drcs = dynamic_range_compression;
3949 for (; drcs[ii] != NULL && ii < track_count; ii++)
3951 drc = atof(drcs[ii]);
3952 audio_dict = hb_value_array_get(audio_array, ii);
3953 hb_dict_set(audio_dict, "DRC", hb_value_double(drc));
3955 if (drcs[ii] != NULL)
3957 fprintf(stderr, "Dropping excess audio dynamic range controls\n");
3960 // If exactly one DRC was specified, apply it to the reset
3961 // of the tracks
3962 if (ii == 1) for (; ii < track_count; ii++)
3964 audio_dict = hb_value_array_get(audio_array, ii);
3965 hb_dict_set(audio_dict, "DRC", hb_value_double(drc));
3968 /* Audio Gain */
3969 ii = 0;
3970 double gain;
3971 if (audio_gain)
3973 for (; audio_gain[ii] != NULL && ii < track_count; ii++)
3975 gain = atof(audio_gain[ii]);
3976 audio_dict = hb_value_array_get(audio_array, ii);
3977 hb_dict_set(audio_dict, "Gain", hb_value_double(gain));
3979 if (audio_gain[ii] != NULL)
3981 fprintf(stderr, "Dropping excess audio gains\n");
3984 // If exactly one gain was specified, apply it to the reset
3985 // of the tracks
3986 if (ii == 1) for (; ii < track_count; ii++)
3988 audio_dict = hb_value_array_get(audio_array, ii);
3989 hb_dict_set(audio_dict, "Gain", hb_value_double(gain));
3992 /* Audio Dither */
3993 int dither;
3994 ii = 0;
3995 if (audio_dither != NULL)
3997 for (; audio_dither[ii] != NULL && ii < track_count; ii++)
3999 if (*audio_dither[ii])
4001 dither = hb_audio_dither_get_from_name(audio_dither[ii]);
4002 audio_dict = hb_value_array_get(audio_array, ii);
4003 hb_dict_set(audio_dict, "DitherMethod",
4004 hb_value_int(dither));
4007 if (audio_dither[ii] != NULL)
4009 fprintf(stderr, "Dropping excess audio dither methods\n");
4012 // If exactly one dither was specified, apply it to the reset
4013 // of the tracks
4014 if (ii == 1) for (; ii < track_count; ii++)
4016 int codec;
4017 audio_dict = hb_value_array_get(audio_array, ii);
4018 codec = hb_value_get_int(hb_dict_get(audio_dict, "Encoder"));
4019 if (hb_audio_dither_is_supported(codec))
4021 hb_dict_set(audio_dict, "DitherMethod",
4022 hb_value_double(dither));
4026 /* Audio Mix Normalization */
4027 int norm = 0;
4028 ii = 0;
4029 if (normalize_mix_level)
4031 char **nmls = normalize_mix_level;
4032 for (; nmls[ii] != NULL && ii < track_count; ii++)
4034 norm = atoi(nmls[ii]);
4035 audio_dict = hb_value_array_get(audio_array, ii);
4036 hb_dict_set(audio_dict, "NormalizeMixLevel",
4037 hb_value_int(norm));
4039 if (nmls[ii] != NULL)
4041 fprintf(stderr,
4042 "Dropping excess audio mixdown normalizations\n");
4045 // If exactly one norm was specified, apply it to the reset
4046 // of the tracks
4047 if (ii == 1) for (; ii < track_count; ii++)
4049 audio_dict = hb_value_array_get(audio_array, ii);
4050 hb_dict_set(audio_dict, "NormalizeMixLevel", hb_value_int(norm));
4053 /* Audio Track Names */
4054 ii = 0;
4055 if (anames != NULL)
4057 for (; anames[ii] != NULL && ii < track_count; ii++)
4059 if (*anames[ii])
4061 audio_dict = hb_value_array_get(audio_array, ii);
4062 hb_dict_set(audio_dict, "Name",
4063 hb_value_string(anames[ii]));
4066 if (anames[ii] != NULL)
4068 fprintf(stderr, "Dropping excess audio track names\n");
4071 // If exactly one name was specified, apply it to the reset
4072 // of the tracks
4073 if (ii == 1 && *anames[0]) for (; ii < track_count; ii++)
4075 audio_dict = hb_value_array_get(audio_array, ii);
4076 hb_dict_set(audio_dict, "Name", hb_value_string(anames[0]));
4080 int one_burned = 0;
4081 if (subtracks != NULL)
4083 int ii;
4084 for (ii = 0; subtracks[ii] != NULL; ii++)
4086 if (strcasecmp(subtracks[ii], "none" ) == 0)
4088 // Taken care of already when initializing the job
4089 // from a preset
4090 continue;
4092 if (strcasecmp(subtracks[ii], "scan" ) == 0)
4094 // Taken care of already when initializing the job
4095 // from a preset
4096 continue;
4099 int first, last, track;
4100 if (sscanf(subtracks[ii], "%d-%d", &first, &last ) == 2)
4102 for (track = first - 1; track < last; track++)
4104 add_sub(subtitle_array, title, track-1, &one_burned);
4107 else if (sscanf(subtracks[ii], "%d", &track) == 1)
4109 add_sub(subtitle_array, title, track-1, &one_burned);
4111 else
4113 fprintf(stderr, "ERROR: unable to parse subtitle input \"%s\", skipping\n", subtracks[ii]);
4117 else
4119 if (subdefault > 0)
4121 // "Default" flag can not be applied till after subtitles have
4122 // been selected. Apply it here if subtitle selection was
4123 // made by the preset.
4124 hb_value_t *sub_dict = hb_dict_get(job_dict, "Subtitle");
4125 hb_value_t *sub_list = hb_dict_get(sub_dict, "SubtitleList");
4126 if (hb_value_array_len(sub_list) >= subdefault)
4128 hb_value_t *sub = hb_value_array_get(sub_list, subdefault - 1);
4129 hb_dict_set(sub, "Default", hb_value_bool(1));
4133 if (subforce != NULL)
4135 // "Forced" flag is not set during preset initialization except
4136 // for "foreign audio" subtitles. Set additional request forced
4137 // subtitle tracks here.
4138 hb_value_t *sub_dict = hb_dict_get(job_dict, "Subtitle");
4139 hb_value_t *sub_list = hb_dict_get(sub_dict, "SubtitleList");
4141 int ii;
4142 for (ii = 0; subforce[ii] != NULL; ii++ )
4144 int idx = strtol(subforce[ii], NULL, 0) - 1;
4145 if (idx >= 0 && hb_value_array_len(sub_list) > idx)
4147 hb_value_t *sub = hb_value_array_get(sub_list, idx);
4148 hb_dict_set(sub, "Forced", hb_value_bool(1));
4154 if (srtfile != NULL)
4156 int ii;
4157 for (ii = 0; srtfile[ii] != NULL; ii++)
4159 add_srt(subtitle_array, ii, &one_burned);
4163 return job_dict;
4167 static void print_string_list(FILE *out, const char* const *list, const char *prefix)
4169 if (out != NULL && prefix != NULL)
4171 if (list != NULL)
4173 while (*list != NULL)
4175 fprintf(out, "%s%s\n", prefix, *list++);
4178 else
4180 fprintf(out, "%s" "Option not supported by encoder\n", prefix);
4185 #ifdef __APPLE_CC__
4186 /****************************************************************************
4187 * bsd_name_for_path
4189 * Returns the BSD device name for the block device that contains the
4190 * passed-in path. Returns NULL on failure.
4191 ****************************************************************************/
4192 static char* bsd_name_for_path(char *path)
4194 OSStatus err;
4195 FSRef ref;
4196 err = FSPathMakeRef( (const UInt8 *) input, &ref, NULL );
4197 if( err != noErr )
4199 return NULL;
4202 // Get the volume reference number.
4203 FSCatalogInfo catalogInfo;
4204 err = FSGetCatalogInfo( &ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL,
4205 NULL);
4206 if( err != noErr )
4208 return NULL;
4210 FSVolumeRefNum volRefNum = catalogInfo.volume;
4212 // Now let's get the device name
4213 GetVolParmsInfoBuffer volumeParms;
4214 err = FSGetVolumeParms( volRefNum, &volumeParms, sizeof( volumeParms ) );
4215 if( err != noErr )
4217 return NULL;
4220 // A version 4 GetVolParmsInfoBuffer contains the BSD node name in the vMDeviceID field.
4221 // It is actually a char * value. This is mentioned in the header CoreServices/CarbonCore/Files.h.
4222 if( volumeParms.vMVersion < 4 )
4224 return NULL;
4227 // vMDeviceID might be zero as is reported with experimental ZFS (zfs-119) support in Leopard.
4228 if( !volumeParms.vMDeviceID )
4230 return NULL;
4233 return strdup( volumeParms.vMDeviceID );
4236 /****************************************************************************
4237 * device_is_dvd
4239 * Returns whether or not the passed in BSD device represents a DVD, or other
4240 * optical media.
4241 ****************************************************************************/
4242 static int device_is_dvd(char *device)
4244 io_service_t service = get_iokit_service(device);
4245 if( service == IO_OBJECT_NULL )
4247 return 0;
4249 int result = is_dvd_service(service);
4250 IOObjectRelease(service);
4251 return result;
4254 /****************************************************************************
4255 * get_iokit_service
4257 * Returns the IOKit service object for the passed in BSD device name.
4258 ****************************************************************************/
4259 static io_service_t get_iokit_service( char *device )
4261 CFMutableDictionaryRef matchingDict;
4262 matchingDict = IOBSDNameMatching( kIOMasterPortDefault, 0, device );
4263 if( matchingDict == NULL )
4265 return IO_OBJECT_NULL;
4267 // Fetch the object with the matching BSD node name. There should only be
4268 // one match, so IOServiceGetMatchingService is used instead of
4269 // IOServiceGetMatchingServices to simplify the code.
4270 return IOServiceGetMatchingService( kIOMasterPortDefault, matchingDict );
4273 /****************************************************************************
4274 * is_dvd_service
4276 * Returns whether or not the service passed in is a DVD.
4278 * Searches for an IOMedia object that represents the entire (whole) media that
4279 * the volume is on. If the volume is on partitioned media, the whole media
4280 * object will be a parent of the volume's media object. If the media is not
4281 * partitioned, the volume's media object will be the whole media object.
4282 ****************************************************************************/
4283 static int is_dvd_service( io_service_t service )
4285 kern_return_t kernResult;
4286 io_iterator_t iter;
4288 // Create an iterator across all parents of the service object passed in.
4289 kernResult = IORegistryEntryCreateIterator( service,
4290 kIOServicePlane,
4291 kIORegistryIterateRecursively | kIORegistryIterateParents,
4292 &iter );
4293 if( kernResult != KERN_SUCCESS )
4295 return 0;
4297 if( iter == IO_OBJECT_NULL )
4299 return 0;
4302 // A reference on the initial service object is released in the do-while
4303 // loop below, so add a reference to balance.
4304 IOObjectRetain( service );
4306 int result = 0;
4309 if( is_whole_media_service( service ) &&
4310 IOObjectConformsTo( service, kIODVDMediaClass) )
4312 result = 1;
4314 IOObjectRelease( service );
4315 } while( !result && (service = IOIteratorNext( iter )) );
4316 IOObjectRelease( iter );
4318 return result;
4321 /****************************************************************************
4322 * is_whole_media_service
4324 * Returns whether or not the service passed in is an IOMedia service and
4325 * represents the "whole" media instead of just a partition.
4327 * The whole media object is indicated in the IORegistry by the presence of a
4328 * property with the key "Whole" and value "Yes".
4329 ****************************************************************************/
4330 static int is_whole_media_service( io_service_t service )
4332 int result = 0;
4334 if( IOObjectConformsTo( service, kIOMediaClass ) )
4336 CFTypeRef wholeMedia = IORegistryEntryCreateCFProperty( service,
4337 CFSTR( kIOMediaWholeKey ),
4338 kCFAllocatorDefault,
4339 0 );
4340 if ( !wholeMedia )
4342 return 0;
4344 result = CFBooleanGetValue( (CFBooleanRef)wholeMedia );
4345 CFRelease( wholeMedia );
4348 return result;
4350 #endif // __APPLE_CC__