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
19 #if defined( __MINGW32__ )
24 #if defined( PTW32_STATIC_LIB )
31 #include "openclwrapper.h"
34 #include "qsv_common.h"
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>
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;
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
;
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;
154 static int qsv_async_depth
= -1;
155 static int qsv_decode
= -1;
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 );
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
);
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
);
195 /* Only print the "Muxing..." message once */
196 static int show_mux_warning
= 1;
198 /****************************************************************************
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__ )
216 wchar_t **argv_utf16
= CommandLineToArgvW(GetCommandLineW(), &argc
);
220 int offset
= (argc
+1) * sizeof(char*);
223 for(i
= 0; i
< argc
; i
++)
224 size
+= WideCharToMultiByte(CP_UTF8
, 0, argv_utf16
[i
], -1, NULL
, 0, NULL
, 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
);
237 LocalFree(argv_utf16
);
246 // On other systems, assume command line is already utf8
251 int main( int argc
, char ** argv
)
258 hb_presets_builtin_update();
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
) )
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
);
281 fprintf( stderr
, "%s - %s - %s\n",
282 HB_PROJECT_TITLE
, HB_PROJECT_BUILD_TITLE
, HB_PROJECT_URL_WEBSITE
);
284 /* Check for update */
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
,
296 fprintf( stderr
, "Your version of HandBrake is up to "
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.
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
);
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
);
350 /* Feed libhb with a DVD to scan */
351 fprintf( stderr
, "Opening %s...\n", input
);
355 * We need to scan for all the titles in order to find the main feature
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);
374 #if defined( __MINGW32__ )
378 case 0x03: /* ctrl-c */
380 fprintf( stdout
, "\nEncoding Quit by user command\n" );
381 done_error
= HB_ERROR_CANCELED
;
386 "\nEncoding Paused by user command, 'r' to resume\n");
388 hb_system_sleep_allow(h
);
391 hb_system_sleep_prevent(h
);
400 #elif !defined(SYS_BEOS)
410 FD_SET( STDIN_FILENO
, &fds
);
411 ret
= select( STDIN_FILENO
+ 1, &fds
, NULL
, NULL
, &tv
);
418 read( STDIN_FILENO
, &buf
[size
], 1 ) > 0 )
420 if( buf
[size
] == '\n' )
427 if( size
>= 256 || buf
[size
] == '\n' )
432 fprintf( stdout
, "\nEncoding Quit by user command\n" );
433 done_error
= HB_ERROR_CANCELED
;
438 "\nEncoding Paused by user command, 'r' to resume\n");
440 hb_system_sleep_allow(h
);
443 hb_system_sleep_prevent(h
);
457 HandleEvents( h
, preset_dict
);
461 hb_value_free(&preset_dict
);
464 str_vfree(audio_copy_list
);
465 str_vfree(abitrates
);
466 str_vfree(acompressions
);
467 str_vfree(aqualities
);
468 str_vfree(audio_dither
);
472 str_vfree(audio_lang_list
);
473 str_vfree(audio_gain
);
474 str_vfree(dynamic_range_compression
);
476 str_vfree(subtitle_lang_list
);
477 str_vfree(subtracks
);
478 free(acodec_fallback
);
479 free(native_language
);
484 free(encoder_preset
);
487 free(encoder_profile
);
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");
509 static void PrintTitleInfo( hb_title_t
* title
, int feature
)
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
,
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",
566 audio
->lang
.description
,
567 audio
->lang
.iso639_2
,
568 audio
->in
.samplerate
,
573 fprintf( stderr
, " + %d, %s (iso639-2: %s)\n",
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
,
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
)
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
)
615 if ( list
== NULL
|| pos
== 0 )
618 if ( list
[0] == NULL
&& pos
== 1 )
621 for ( i
= 0; list
[i
] != NULL
; i
++ )
623 int idx
= strtol( list
[i
], NULL
, 0 );
630 void write_chapter_names(hb_dict_t
*job_dict
, const char *marker_file
)
632 if (marker_file
== NULL
)
635 hb_csv_file_t
* file
= hb_open_csv_file(marker_file
);
636 hb_csv_cell_t
* cell
;
641 fprintf(stderr
, "Cannot open chapter marker file, using defaults\n");
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"),
650 if (chapter_array
== NULL
)
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
);
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
)
694 hb_get_state( h
, &s
);
701 #define p s.param.scanning
702 case HB_STATE_SCANNING
:
703 /* Show what title is currently being scanned */
706 fprintf(stderr
, "\rScanning title %d of %d, preview %d, %.2f %%",
707 p
.title_cur
, p
.title_count
, p
.preview_cur
, 100 * p
.progress
);
711 fprintf(stderr
, "\rScanning title %d of %d, %.2f %%",
712 p
.title_cur
, p
.title_count
, 100 * p
.progress
);
718 case HB_STATE_SCANDONE
:
720 hb_title_set_t
* title_set
;
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
;
735 int main_feature_idx
=0;
736 int main_feature_pos
=-1;
737 int main_feature_time
=0;
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
;
761 if( main_feature_pos
== -1 )
763 fprintf( stderr
, "No main feature title found.\n" );
764 done_error
= HB_ERROR_WRONG_INPUT
;
768 titleindex
= main_feature_idx
;
769 fprintf(stderr
, "Found main feature title %d\n",
772 title
= hb_list_item(title_set
->list_title
, main_feature_pos
);
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
);
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
)
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");
811 hb_add_json(h
, json_job
);
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
);
823 fprintf( stdout
, " (ETA %02dh%02dm%02ds)",
824 p
.hours
, p
.minutes
, p
.seconds
);
829 case HB_STATE_WORKING
:
830 fprintf( stdout
, "\rEncoding: task %d of %d, %.2f %%",
831 p
.pass
, p
.pass_count
, 100.0 * p
.progress
);
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
);
842 #define p s.param.muxing
843 case HB_STATE_MUXING
:
845 if (show_mux_warning
)
847 fprintf( stdout
, "\rMuxing: this may take awhile..." );
849 show_mux_warning
= 0;
855 #define p s.param.workdone
856 case HB_STATE_WORKDONE
:
857 /* Print error if any, then exit */
861 fprintf( stderr
, "\nEncode done!\n" );
863 case HB_ERROR_CANCELED
:
864 fprintf( stderr
, "\nEncode canceled.\n" );
867 fprintf( stderr
, "\nEncode failed (error %x).\n",
870 done_error
= p
.error
;
878 /****************************************************************************
880 ****************************************************************************/
881 static volatile int64_t i_die_date
= 0;
882 void SigHandler( int i_signal
)
884 done_error
= HB_ERROR_CANCELED
;
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" );
899 /****************************************************************************
901 ****************************************************************************/
902 static void ShowHelp()
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
;
913 "Syntax: HandBrakeCLI [options] -i <device> -o <file>\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"
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"
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)"
961 "### Destination Options---------------------------------------------------\n\n"
962 " -o, --output <string> Set output file name\n"
963 " -f, --format <string> Set output container format (");
965 while ((container
= hb_container_get_next(container
)) != NULL
)
967 fprintf(out
, "%s", container
->short_name
);
968 if (hb_container_get_next(container
) != NULL
)
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"
992 "### Video Options------------------------------------------------------------\n\n"
993 " -e, --encoder <string> Set video library encoder\n"
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
)
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"
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
)
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"
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" );
1080 while ((encoder
= hb_audio_encoder_get_next(encoder
)) != NULL
)
1082 fprintf(out
, " %s\n",
1083 encoder
->short_name
);
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"
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
));
1100 " --audio-copy-mask Set audio codecs that are permitted when the\n"
1101 " <string> \"copy\" audio encoder option is specified\n"
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
))
1116 fprintf(out
, "%s", encoder
->short_name
+ 5);
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
);
1140 " Separate tracks by commas.\n"
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
));
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"
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
)
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"
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"
1182 " --adither <string> Apply dithering to the audio before encoding.\n"
1183 " Separate tracks by commas.\n"
1184 " Only supported by some encoders\n"
1188 while ((encoder
= hb_audio_encoder_get_next(encoder
)) != NULL
)
1190 if (hb_audio_dither_is_supported(encoder
->codec
))
1197 fprintf(out
, "%s", encoder
->short_name
);
1200 fprintf(out
, ").\n");
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
);
1213 fprintf(out
, " %s\n",
1214 dither
->short_name
);
1218 " -A, --aname <string> Audio track name(s),\n"
1219 " Separate tracks by commas.\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"
1242 " --itu-par Use wider, ITU pixel aspect values for loose and\n"
1243 " custom anamorphic, useful with underscanned\n"
1245 " --no-itu-par Disable preset 'itu-par'\n"
1246 " --modulus Set the number you want the scaled pixel\n"
1248 " <number> to divide cleanly by. Does not affect strict\n"
1249 " anamorphic mode, which is always mod 2\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"
1255 "### Filters---------------------------------------------------------------\n\n"
1256 " -d, --deinterlace Unconditionally deinterlaces all frames\n"
1257 " <fast/slow/slower/bob");
1259 if (hb_qsv_available())
1261 fprintf(out
, "/qsv");
1264 fprintf( out
, "> or omitted (default settings)\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"
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"
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"
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"
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"
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"
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"
1393 if (hb_qsv_available())
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"
1409 /****************************************************************************
1411 ****************************************************************************/
1413 reverse_search_char(const char *front
, const char *back
, char delim
)
1415 while (back
!= front
&& *back
!= delim
)
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;
1431 #define my_strndup strndup
1434 static char** str_width_split( const char *str
, int width
)
1443 if ( str
== NULL
|| str
[0] == 0 )
1445 ret
= malloc( sizeof(char*) );
1452 // Find number of elements in the string
1456 while (end
< str
+ len
)
1458 end
= reverse_search_char(pos
, end
, delem
);
1461 // Shouldn't happen for reasonable input
1469 ret
= calloc( ( count
+ 1 ), sizeof(char*) );
1473 for (ii
= 0; ii
< count
- 1 && end
< str
+ len
; ii
++)
1475 end
= reverse_search_char(pos
, end
, delem
);
1480 ret
[ii
] = my_strndup(pos
, end
- pos
);
1484 if (*pos
!= 0 && ii
< count
- 1)
1486 ret
[ii
] = my_strndup(pos
, width
);
1492 static void Indent(FILE *f
, char *whitespace
, int indent
)
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
);
1508 for (ii
= 0; ii
< count
; ii
++)
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")))
1517 fprintf(stderr
, "%s/\n", name
);
1518 hb_value_array_t
*children
;
1519 children
= hb_dict_get(preset_dict
, "ChildrenArray");
1520 if (children
== NULL
)
1522 ShowPresets(children
, indent
, descriptions
);
1527 fprintf(stderr
, "%s\n", name
);
1531 desc
= hb_value_get_string(hb_dict_get(preset_dict
,
1532 "PresetDescription"));
1533 if (desc
!= NULL
&& desc
[0] != 0)
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
]);
1549 static char* strchr_quote(char *pos
, char c
, char q
)
1554 while (*pos
!= 0 && *pos
!= c
)
1558 pos
= strchr_quote(pos
+1, q
, 0);
1563 else if (*pos
== '\\' && *(pos
+1) != 0)
1573 static char *strndup_quote(char *str
, char q
, int len
)
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
)
1587 else if (str
[src
] == '\\' && str
[src
+1] != 0)
1589 res
[dst
++] = str
[src
+1];
1593 res
[dst
++] = str
[src
++];
1599 static int str_vlen(char **strv
)
1604 for (i
= 0; strv
[i
]; i
++);
1608 static char** str_split( char *str
, char delem
)
1620 if ( str
== NULL
|| str
[0] == 0 )
1622 ret
= malloc( sizeof(char*) );
1627 // Find number of elements in the string
1630 while ( ( pos
= strchr_quote( pos
, delem
, quote
) ) != NULL
)
1636 ret
= calloc( ( count
+ 1 ), sizeof(char*) );
1639 for ( i
= 0; i
< count
- 1; i
++ )
1641 end
= strchr_quote( pos
, delem
, quote
);
1642 ret
[i
] = strndup_quote(pos
, quote
, end
- pos
);
1645 ret
[i
] = strndup_quote(pos
, quote
, strlen(pos
));
1650 static void str_vfree( char **strv
)
1657 for ( i
= 0; strv
[i
]; i
++ )
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;
1674 while ((str
= strtok(NULL
, ":")) != NULL
)
1675 duration
= 60*duration
+ strtod(str
, NULL
);
1679 /****************************************************************************
1681 ****************************************************************************/
1682 static int ParseOptions( int argc
, char ** argv
)
1685 #define PREVIEWS 257
1686 #define START_AT_PREVIEW 258
1687 #define START_AT 259
1691 #define DISPLAY_WIDTH 263
1692 #define PIXEL_ASPECT 264
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
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 },
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, },
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
},
1887 int option_index
= 0;
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
);
1904 /* option was handled entirely in getopt_long */
1913 if( optarg
!= NULL
)
1915 debug
= atoi( optarg
);
1923 preset_name
= strdup(optarg
);
1926 ShowPresets(NULL
, 0, 1);
1929 preset_export_name
= strdup(optarg
);
1931 case PRESET_EXPORT_DESC
:
1932 preset_export_desc
= strdup(optarg
);
1934 case PRESET_EXPORT_FILE
:
1935 preset_export_file
= strdup(optarg
);
1939 // Import list of preset files
1940 while (optind
< argc
&& argv
[optind
][0] != '-')
1942 int result
= hb_presets_add_path(argv
[optind
]);
1945 fprintf(stderr
, "Preset import failed, file (%s)\n",
1951 case PRESET_IMPORT_GUI
:
1952 hb_presets_gui_init();
1959 format
= strdup( optarg
);
1962 input
= strdup( optarg
);
1964 char *devName
= bsd_name_for_path( input
); // alloc
1965 if( devName
!= NULL
)
1967 if( device_is_dvd( devName
))
1970 input
= malloc( strlen( "/dev/" ) + strlen( devName
) + 1 );
1971 sprintf( input
, "/dev/%s", devName
);
1978 output
= strdup( optarg
);
1993 titleindex
= atoi( optarg
);
2004 if( sscanf( optarg
, "%d-%d", &start
, &end
) == 2 )
2006 chapter_start
= start
;
2009 else if( sscanf( optarg
, "%d", &start
) == 1 )
2011 chapter_start
= start
;
2012 chapter_end
= chapter_start
;
2016 fprintf( stderr
, "chapters: Invalid syntax (%s)\n",
2023 angle
= atoi( optarg
);
2026 if( optarg
!= NULL
)
2028 marker_file
= strdup( optarg
);
2030 chapter_markers
= 1;
2032 case AUDIO_LANG_LIST
:
2033 audio_lang_list
= str_split(optarg
, ',');
2035 case SUBTITLE_LANG_LIST
:
2036 subtitle_lang_list
= str_split(optarg
, ',');
2039 if( optarg
!= NULL
)
2041 atracks
= str_split(optarg
, ',');
2045 atracks
= str_split("1", ',');
2049 if( optarg
!= NULL
)
2051 mixdowns
= str_split(optarg
, ',');
2055 if( optarg
!= NULL
)
2057 dynamic_range_compression
= str_split(optarg
, ',');
2061 if( optarg
!= NULL
)
2063 audio_gain
= str_split(optarg
, ',');
2069 audio_dither
= str_split(optarg
, ',');
2073 normalize_mix_level
= str_split(optarg
, ',');
2076 subtracks
= str_split( optarg
, ',' );
2079 subforce
= str_split( optarg
, ',' );
2084 if (!strcasecmp(optarg
, "native") ||
2085 !strcasecmp(optarg
, "scan"))
2089 subburn
= strtol(optarg
, NULL
, 0);
2098 if (subtracks
!= NULL
&& str_vlen(subtracks
) >= subburn
&&
2099 !strcasecmp("scan", subtracks
[subburn
-1]))
2108 subdefault
= strtol(optarg
, NULL
, 0);
2117 const iso639_lang_t
*lang
= lang_lookup(optarg
);
2120 native_language
= strdup(lang
->iso639_2
);
2124 fprintf(stderr
, "Invalid native language (%s)\n", optarg
);
2132 srtfile
= str_split( optarg
, ',' );
2135 srtcodeset
= str_split( optarg
, ',' );
2138 srtoffset
= str_split( optarg
, ',' );
2141 srtlang
= str_split( optarg
, ',' );
2144 if( optarg
!= NULL
)
2146 srtdefault
= atoi( optarg
);
2154 if( optarg
!= NULL
)
2156 srtburn
= atoi( optarg
);
2170 deinterlace
= strdup(optarg
);
2174 deinterlace
= strdup("default");
2179 if( optarg
!= NULL
)
2181 deblock
= strdup(optarg
);
2185 deblock
= strdup("5");
2192 hqdn3d
= strdup(optarg
);
2196 hqdn3d
= strdup("default");
2199 case FILTER_NLMEANS
:
2203 nlmeans
= strdup(optarg
);
2207 nlmeans
= strdup("medium");
2210 case FILTER_NLMEANS_TUNE
:
2212 nlmeans_tune
= strdup(optarg
);
2218 detelecine
= strdup(optarg
);
2222 detelecine
= strdup("default");
2229 decomb
= strdup(optarg
);
2233 decomb
= strdup("default");
2243 rotate
= strdup(optarg
);
2247 rotate
= strdup("180:0");
2250 case KEEP_DISPLAY_ASPECT
:
2251 if( optarg
!= NULL
)
2253 keep_display_aspect
= atoi(optarg
);
2257 keep_display_aspect
= 1;
2261 if( optarg
!= NULL
)
2263 display_width
= atoi(optarg
);
2267 if( optarg
!= NULL
)
2269 sscanf(optarg
, "%i:%i", &par_width
, &par_height
);
2273 if( optarg
!= NULL
)
2275 modulus
= atoi(optarg
);
2280 vcodec
= strdup(optarg
);
2284 if( optarg
!= NULL
)
2286 acodecs
= str_split(optarg
, ',');
2290 width
= atoi( optarg
);
2293 height
= atoi( optarg
);
2298 char * tmp
= optarg
;
2299 for( i
= 0; i
< 4; i
++ )
2303 crop
[i
] = strtol( tmp
, &tmp
, 0 );
2310 loose_crop
= atoi(optarg
);
2316 vrate
= strdup(optarg
);
2324 arates
= str_split( optarg
, ',' );
2327 vbitrate
= atoi( optarg
);
2330 vquality
= atof( optarg
);
2333 abitrates
= str_split( optarg
, ',' );
2336 aqualities
= str_split( optarg
, ',' );
2339 acompressions
= str_split( optarg
, ',' );
2341 case ENCODER_PRESET
:
2342 encoder_preset
= strdup( optarg
);
2345 encoder_tune
= strdup( optarg
);
2348 advanced_opts
= strdup( optarg
);
2350 case ENCODER_PROFILE
:
2351 encoder_profile
= strdup( optarg
);
2354 encoder_level
= strdup( optarg
);
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
)),
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
)),
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
)),
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
)),
2388 maxHeight
= atoi( optarg
);
2391 maxWidth
= atoi (optarg
);
2394 if( optarg
!= NULL
)
2396 anames
= str_split( optarg
, ',' );
2400 sscanf( optarg
, "%i:%i", &preview_count
, &store_previews
);
2402 case START_AT_PREVIEW
:
2403 start_at_preview
= atoi( optarg
);
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
);
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
);
2453 case ALLOWED_AUDIO_COPY
:
2455 audio_copy_list
= str_split(optarg
, ',');
2458 case AUDIO_FALLBACK
:
2459 acodec_fallback
= strdup( optarg
);
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;
2473 min_title_duration
= strtol( optarg
, NULL
, 0 );
2477 hb_qsv_force_workarounds();
2479 case QSV_ASYNC_DEPTH
:
2480 qsv_async_depth
= atoi(optarg
);
2482 case QSV_IMPLEMENTATION
:
2483 hb_qsv_impl_set_preferred(optarg
);
2487 fprintf( stderr
, "unknown option (%s)\n", argv
[cur_optind
] );
2493 if (deblock
!= NULL
)
2495 if (deblock_disable
)
2498 "Incompatible options --deblock and --no-deblock\n");
2501 if (hb_validate_filter_settings(HB_FILTER_DEBLOCK
, deblock
))
2503 fprintf(stderr
, "Invalid deblock option %s\n", deblock
);
2508 if (detelecine
!= NULL
)
2510 if (detelecine_disable
)
2513 "Incompatible options --detelecine and --no-detelecine\n");
2516 if (!hb_validate_filter_preset(HB_FILTER_DETELECINE
,
2519 // Nothing to do, but must validate preset before
2520 // attempting to validate custom settings to prevent potential
2523 else if (!hb_validate_filter_settings(HB_FILTER_DETELECINE
, detelecine
))
2525 detelecine_custom
= 1;
2529 fprintf(stderr
, "Invalid detelecine option %s\n", detelecine
);
2534 if (deinterlace
!= NULL
)
2536 if (deinterlace_disable
)
2539 "Incompatible options --deinterlace and --no-deinterlace\n");
2542 if (!hb_validate_filter_preset(HB_FILTER_DEINTERLACE
,
2545 // Nothing to do, but must validate preset before
2546 // attempting to validate custom settings to prevent potential
2549 else if (!hb_validate_filter_settings(HB_FILTER_DEINTERLACE
, deinterlace
))
2551 deinterlace_custom
= 1;
2555 fprintf(stderr
, "Invalid deinterlace option %s\n", deinterlace
);
2565 "Incompatible options --decomb and --no-decomb\n");
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
2574 else if (!hb_validate_filter_settings(HB_FILTER_DECOMB
, decomb
))
2580 fprintf(stderr
, "Invalid decomb option %s\n", decomb
);
2590 "Incompatible options --hqdn3d and --no-hqdn3d\n");
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
2599 else if (!hb_validate_filter_settings(HB_FILTER_HQDN3D
, hqdn3d
))
2605 fprintf(stderr
, "Invalid hqdn3d option %s\n", hqdn3d
);
2610 if (nlmeans
!= NULL
)
2612 if (nlmeans_disable
)
2615 "Incompatible options --nlmeans and --no-nlmeans\n");
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
2624 else if (!hb_validate_filter_settings(HB_FILTER_NLMEANS
, nlmeans
))
2630 fprintf(stderr
, "Invalid nlmeans option %s\n", nlmeans
);
2638 static int foreign_audio_scan(char **subtracks
)
2640 if (subtracks
!= NULL
)
2642 int count
= str_vlen(subtracks
);
2644 for (ii
= 0; ii
< count
; ii
++)
2646 if (!strcasecmp(subtracks
[0], "scan"))
2655 static int count_subtitles(char **subtracks
)
2657 int subtitle_track_count
= 0;
2658 if (subtracks
!= NULL
)
2660 int count
= str_vlen(subtracks
);
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
)
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] );
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] );
2698 if (format
== NULL
&& output
!= NULL
)
2701 const char *extension
= strrchr(output
, '.');
2702 if (extension
!= NULL
)
2705 mux
= hb_container_get_from_extension(extension
+ 1);
2707 hb_container_t
* c
= hb_container_get_from_format(mux
);
2709 format
= strdup(c
->short_name
);
2713 int subtitle_track_count
= count_subtitles(subtracks
);
2714 if (subtitle_track_count
> 0 && subtitle_lang_list
!= NULL
)
2717 "Incompatible options: --subtitle-lang-list and --subtitle\n");
2721 if (subtitle_track_count
> 0 && subtitle_all
!= -1)
2724 "Incompatible options: --all-subtitles/--first-subtitle and --subtitle\n");
2728 if (atracks
!= NULL
&& audio_lang_list
!= NULL
)
2731 "Incompatible options: --audio-lang-list and --audio\n");
2735 if (atracks
!= NULL
&& audio_all
!= -1)
2738 "Incompatible options: --all-audio/--first-audio and --audio\n");
2742 if ((par_width
> 0 && par_height
> 0) && display_width
> 0)
2745 "Incompatible options: --display-width and --pixel-aspect\n");
2749 if (preset_export_file
!= NULL
&& preset_export_name
== NULL
)
2752 "Error: --preset-export-file requires option --preset-export\n");
2756 if (preset_export_desc
!= NULL
&& preset_export_name
== NULL
)
2759 "Error: --preset-export-desc requires option --preset-export\n");
2766 static hb_dict_t
* PreparePreset(const char *preset_name
)
2771 if (preset_name
!= NULL
)
2773 preset
= hb_preset_search(preset_name
, 1 /*recurse*/);
2776 fprintf(stderr
, "Invalid preset %s\n"
2777 "Valid presets are:\n", preset_name
);
2778 ShowPresets(NULL
, 1, 1);
2784 preset
= hb_presets_get_default();
2788 fprintf(stderr
, "Error loading presets! Aborting.\n");
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
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
]);
2827 hb_value_array_append(subtitle_lang_array
,
2828 hb_value_string(lang
->iso639_2
));
2832 fprintf(stderr
, "Warning: Invalid subtitle language (%s)\n",
2833 subtitle_lang_list
[ii
]);
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",
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
)
2866 else if (subburn
== 1)
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";
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
]);
2926 hb_value_array_append(audio_lang_array
,
2927 hb_value_string(lang
->iso639_2
));
2931 fprintf(stderr
, "Warning: Invalid audio language (%s)\n",
2932 audio_lang_list
[ii
]);
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"));
2953 if (atracks
== NULL
&& (
2955 abitrates
!= 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
||
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");
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
);
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]));
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",
3026 hb_dict_set(audio_dict
, "AudioTrackQuality",
3027 hb_value_double(strtod(aqualities
[ii
], NULL
)));
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")))
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")))
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]));
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",
3119 atoi(normalize_mix_level
[ii
-1])));
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",
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",
3141 strtod(dynamic_range_compression
[ii
-1],
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",
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",
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",
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",
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"));
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
);
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
));
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
));
3286 hb_dict_set(preset
, "VideoTwoPass", hb_value_bool(1));
3290 hb_dict_set(preset
, "VideoTurboTwoPass", hb_value_bool(1));
3295 hb_dict_set(preset
, "VideoFramerate", hb_value_string(vrate
));
3299 hb_dict_set(preset
, "VideoFramerate", hb_value_string("auto"));
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
));
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
));
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"));
3334 hb_dict_set(preset
, "PictureWidth", hb_value_int(maxWidth
));
3338 hb_dict_set(preset
, "PictureHeight", hb_value_int(maxHeight
));
3342 hb_dict_set(preset
, "PictureForceWidth", hb_value_int(width
));
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));
3354 hb_dict_set(preset
, "PictureTopCrop", hb_value_int(crop
[0]));
3358 hb_dict_set(preset
, "PictureBottomCrop", hb_value_int(crop
[1]));
3362 hb_dict_set(preset
, "PictureLeftCrop", hb_value_int(crop
[2]));
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
));
3396 hb_dict_set(preset
, "PictureItuPAR", hb_value_bool(itu_par
));
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
));
3420 hb_dict_set(preset
, "PictureDeinterlace",
3421 hb_value_string("custom"));
3422 hb_dict_set(preset
, "PictureDeinterlaceCustom",
3423 hb_value_string(deinterlace
));
3428 hb_dict_set(preset
, "PictureDecomb", hb_value_string("off"));
3432 hb_dict_set(preset
, "PictureDecombDeinterlace", hb_value_int(1));
3435 hb_dict_set(preset
, "PictureDecomb", hb_value_string(decomb
));
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
));
3456 hb_dict_set(preset
, "PictureDetelecine", hb_value_string("custom"));
3457 hb_dict_set(preset
, "PictureDetelecineCustom",
3458 hb_value_string(detelecine
));
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"));
3469 hb_dict_set(preset
, "PictureDenoiseFilter", hb_value_string("hqdn3d"));
3472 hb_dict_set(preset
, "PictureDenoisePreset",
3473 hb_value_string(hqdn3d
));
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
));
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
));
3518 hb_dict_set(preset
, "PictureRotate", hb_value_string(rotate
));
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",
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);
3544 !hb_subtitle_can_pass(subtitle
->source
, mux
))
3546 // Only allow one subtitle to be burned into video
3549 fprintf(stderr
, "Warning: Skipping subtitle track %d, can't have more than one track burnt in\n", track
+ 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
);
3563 static int add_srt(hb_value_array_t
*list
, int track
, int *one_burned
)
3565 char *codeset
= "ISO-8859-1";
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
]);
3582 iso639_2
= lang
->iso639_2
;
3586 fprintf(stderr
, "Warning: Invalid SRT language (%s)\n",
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
);
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",
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
);
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");
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
&&
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
));
3682 hb_dict_set(range_dict
, "Start", hb_value_int(range_start
));
3684 hb_dict_remove(range_dict
, "Start");
3686 hb_dict_set(range_dict
, "End", hb_value_int(range_end
));
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
));
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
)
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
);
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
);
3752 hb_preset_job_add_subtitles(h
, title
->index
,
3753 preset_dict
, job_dict
);
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
]);
3769 "Invalid codec %s, using default for container.\n",
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");
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
3790 audio_dict
= hb_value_array_get(audio_array
, ii
);
3791 hb_dict_set(audio_dict
, "Encoder", hb_value_int(acodec
));
3799 for (; arates
[ii
] != NULL
&& ii
< track_count
; ii
++)
3801 if (!strcasecmp(arates
[ii
], "auto"))
3807 arate
= hb_audio_samplerate_get_from_name(arates
[ii
]);
3811 fprintf(stderr
, "Invalid sample rate %s, using input rate\n",
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
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
));
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
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
));
3861 if (abitrates
!= NULL
)
3863 for (; abitrates
[ii
] != NULL
&& ii
< track_count
; 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
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
));
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"));
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
;
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
)
3937 "Dropping excess audio compression levels\n");
3940 // Compression levels are codec specific values. So don't
3941 // try to apply to other tracks.
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
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
));
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
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
));
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
4014 if (ii
== 1) for (; ii
< track_count
; ii
++)
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 */
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
)
4042 "Dropping excess audio mixdown normalizations\n");
4045 // If exactly one norm was specified, apply it to the reset
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 */
4057 for (; anames
[ii
] != NULL
&& ii
< track_count
; 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
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]));
4081 if (subtracks
!= NULL
)
4084 for (ii
= 0; subtracks
[ii
] != NULL
; ii
++)
4086 if (strcasecmp(subtracks
[ii
], "none" ) == 0)
4088 // Taken care of already when initializing the job
4092 if (strcasecmp(subtracks
[ii
], "scan" ) == 0)
4094 // Taken care of already when initializing the job
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
);
4113 fprintf(stderr
, "ERROR: unable to parse subtitle input \"%s\", skipping\n", subtracks
[ii
]);
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");
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
)
4157 for (ii
= 0; srtfile
[ii
] != NULL
; ii
++)
4159 add_srt(subtitle_array
, ii
, &one_burned
);
4167 static void print_string_list(FILE *out
, const char* const *list
, const char *prefix
)
4169 if (out
!= NULL
&& prefix
!= NULL
)
4173 while (*list
!= NULL
)
4175 fprintf(out
, "%s%s\n", prefix
, *list
++);
4180 fprintf(out
, "%s" "Option not supported by encoder\n", prefix
);
4186 /****************************************************************************
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
)
4196 err
= FSPathMakeRef( (const UInt8
*) input
, &ref
, NULL
);
4202 // Get the volume reference number.
4203 FSCatalogInfo catalogInfo
;
4204 err
= FSGetCatalogInfo( &ref
, kFSCatInfoVolume
, &catalogInfo
, NULL
, NULL
,
4210 FSVolumeRefNum volRefNum
= catalogInfo
.volume
;
4212 // Now let's get the device name
4213 GetVolParmsInfoBuffer volumeParms
;
4214 err
= FSGetVolumeParms( volRefNum
, &volumeParms
, sizeof( volumeParms
) );
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 )
4227 // vMDeviceID might be zero as is reported with experimental ZFS (zfs-119) support in Leopard.
4228 if( !volumeParms
.vMDeviceID
)
4233 return strdup( volumeParms
.vMDeviceID
);
4236 /****************************************************************************
4239 * Returns whether or not the passed in BSD device represents a DVD, or other
4241 ****************************************************************************/
4242 static int device_is_dvd(char *device
)
4244 io_service_t service
= get_iokit_service(device
);
4245 if( service
== IO_OBJECT_NULL
)
4249 int result
= is_dvd_service(service
);
4250 IOObjectRelease(service
);
4254 /****************************************************************************
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 /****************************************************************************
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
;
4288 // Create an iterator across all parents of the service object passed in.
4289 kernResult
= IORegistryEntryCreateIterator( service
,
4291 kIORegistryIterateRecursively
| kIORegistryIterateParents
,
4293 if( kernResult
!= KERN_SUCCESS
)
4297 if( iter
== IO_OBJECT_NULL
)
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
);
4309 if( is_whole_media_service( service
) &&
4310 IOObjectConformsTo( service
, kIODVDMediaClass
) )
4314 IOObjectRelease( service
);
4315 } while( !result
&& (service
= IOIteratorNext( iter
)) );
4316 IOObjectRelease( iter
);
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
)
4334 if( IOObjectConformsTo( service
, kIOMediaClass
) )
4336 CFTypeRef wholeMedia
= IORegistryEntryCreateCFProperty( service
,
4337 CFSTR( kIOMediaWholeKey
),
4338 kCFAllocatorDefault
,
4344 result
= CFBooleanGetValue( (CFBooleanRef
)wholeMedia
);
4345 CFRelease( wholeMedia
);
4350 #endif // __APPLE_CC__