OSDN Git Service

CLI: SubRip Subtitle import
[handbrake-jp/handbrake-jp-git.git] / test / test.c
1 /* $Id: test.c,v 1.82 2005/11/19 08:25:54 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include <signal.h>
8 #include <getopt.h>
9 #include <sys/time.h>
10 #include <time.h>
11 #include <unistd.h>
12 #include <inttypes.h>
13
14 #if defined( __MINGW32__ )
15 #include <conio.h>
16 #endif
17
18 #if defined( PTW32_STATIC_LIB )
19 #include <pthread.h>
20 #endif
21
22 #include "hb.h"
23 #include "parsecsv.h"
24
25 #if defined( __APPLE_CC__ )
26 #import <CoreServices/CoreServices.h>
27 #include <IOKit/IOKitLib.h>
28 #include <IOKit/storage/IOMedia.h>
29 #include <IOKit/storage/IODVDMedia.h>
30 #endif
31
32 /* Options */
33 static int    debug       = HB_DEBUG_NONE;
34 static int    update      = 0;
35 static int    dvdnav      = 0;
36 static char * input       = NULL;
37 static char * output      = NULL;
38 static char * format      = NULL;
39 static int    titleindex  = 1;
40 static int    longest_title = 0;
41 static char * native_language = NULL;
42 static int    native_dub  = 0;
43 static int    twoPass     = 0;
44 static int    deinterlace           = 0;
45 static char * deinterlace_opt       = 0;
46 static int    deblock               = 0;
47 static char * deblock_opt           = 0;
48 static int    denoise               = 0;
49 static char * denoise_opt           = 0;
50 static int    detelecine            = 0;
51 static char * detelecine_opt        = 0;
52 static int    decomb                = 0;
53 static char * decomb_opt            = 0;
54 static int    grayscale   = 0;
55 static int    vcodec      = HB_VCODEC_FFMPEG;
56 static int    h264_13     = 0;
57 static int    h264_30     = 0;
58 static hb_list_t * audios = NULL;
59 static hb_audio_config_t * audio = NULL;
60 static int    num_audio_tracks = 0;
61 static char * mixdowns    = NULL;
62 static char * dynamic_range_compression = NULL;
63 static char * atracks     = NULL;
64 static char * arates      = NULL;
65 static char * abitrates   = NULL;
66 static char * acodecs     = NULL;
67 static char * anames      = NULL;
68 static int    default_acodec = HB_ACODEC_FAAC;
69 static int    default_abitrate = 160;
70 static int    audio_explicit = 0;
71 static char ** subtracks   = NULL;
72 static char ** subforce    = NULL;
73 static char * subburn     = NULL;
74 static char * subdefault  = NULL;
75 static char ** srtfile     = NULL;
76 static char ** srtcodeset  = NULL;
77 static char ** srtoffset   = NULL;
78 static char ** srtlang     = NULL;
79 static int    subtitle_scan = 0;
80 static int    width       = 0;
81 static int    height      = 0;
82 static int    crop[4]     = { -1,-1,-1,-1 };
83 static int    cpu         = 0;
84 static int    vrate       = 0;
85 static float  vquality    = -1.0;
86 static int    vbitrate    = 0;
87 static int    size        = 0;
88 static int    mux         = 0;
89 static int    anamorphic_mode  = 0;
90 static int    modulus       = 0;
91 static int    par_height    = 0;
92 static int    par_width     = 0;
93 static int    display_width = 0;
94 static int    keep_display_aspect = 0;
95 static int    itu_par       = 0;
96 static int    angle = 0;
97 static int    chapter_start = 0;
98 static int    chapter_end   = 0;
99 static int    chapter_markers = 0;
100 static char * marker_file   = NULL;
101 static int        crf                   = 1;
102 static char       *x264opts             = NULL;
103 static char       *x264opts2    = NULL;
104 static int        maxHeight             = 0;
105 static int        maxWidth              = 0;
106 static int    turbo_opts_enabled = 0;
107 static char * turbo_opts = "ref=1:subme=1:me=dia:analyse=none:trellis=0:no-fast-pskip=0:8x8dct=0:weightb=0";
108 static int    largeFileSize = 0;
109 static int    preset        = 0;
110 static char * preset_name   = 0;
111 static int    cfr           = 0;
112 static int    mp4_optimize  = 0;
113 static int    ipod_atom     = 0;
114 static int    color_matrix  = 0;
115 static int    preview_count = 10;
116 static int    store_previews = 0;
117 static int    start_at_preview = 0;
118 static int64_t stop_at_pts    = 0;
119 static int    stop_at_frame = 0;
120 static char * stop_at_string = NULL;
121 static char * stop_at_token = NULL;
122
123 /* Exit cleanly on Ctrl-C */
124 static volatile int die = 0;
125 static void SigHandler( int );
126
127 /* Utils */
128 static void ShowCommands();
129 static void ShowHelp();
130 static void ShowPresets();
131
132 static int  ParseOptions( int argc, char ** argv );
133 static int  CheckOptions( int argc, char ** argv );
134 static int  HandleEvents( hb_handle_t * h );
135
136 static int get_acodec_for_string( char *codec );
137 static int is_sample_rate_valid(int rate);
138
139 #ifdef __APPLE_CC__
140 static char* bsd_name_for_path(char *path);
141 static int device_is_dvd(char *device);
142 static io_service_t get_iokit_service( char *device );
143 static int is_dvd_service( io_service_t service );
144 static int is_whole_media_service( io_service_t service );
145 #endif
146
147 /* Only print the "Muxing..." message once */
148 static int show_mux_warning = 1;
149
150 /****************************************************************************
151  * hb_error_handler
152  *
153  * When using the CLI just display using hb_log as we always did in the past
154  * make sure that we prefix with a nice ERROR message to catch peoples eyes.
155  ****************************************************************************/
156 static void hb_cli_error_handler ( const char *errmsg )
157 {
158     fprintf( stderr, "ERROR: %s\n", errmsg );
159 }
160
161 int main( int argc, char ** argv )
162 {
163     hb_handle_t * h;
164     int           build;
165     char        * version;
166
167 /* win32 _IOLBF (line-buffering) is the same as _IOFBF (full-buffering).
168  * force it to unbuffered otherwise informative output is not easily parsed.
169  */
170 #if defined( _WIN32 ) || defined( __MINGW32__ )
171     setvbuf( stdout, NULL, _IONBF, 0 );
172     setvbuf( stderr, NULL, _IONBF, 0 );
173 #endif
174
175     audios = hb_list_init();
176
177     /* Parse command line */
178     if( ParseOptions( argc, argv ) ||
179         CheckOptions( argc, argv ) )
180     {
181         return 1;
182     }
183
184 #if defined( PTW32_STATIC_LIB )
185     pthread_win32_process_attach_np();
186     pthread_win32_thread_attach_np();
187 #endif
188
189     /* Register our error handler */
190     hb_register_error_handler(&hb_cli_error_handler);
191
192     /* Init libhb */
193     h = hb_init( debug, update );
194     hb_dvd_set_dvdnav( dvdnav );
195
196     /* Show version */
197     fprintf( stderr, "%s - %s - %s\n",
198              HB_PROJECT_TITLE, HB_PROJECT_BUILD_TITLE, HB_PROJECT_URL_WEBSITE );
199
200     /* Check for update */
201     if( update )
202     {
203         if( ( build = hb_check_update( h, &version ) ) > -1 )
204         {
205             fprintf( stderr, "You are using an old version of "
206                      "HandBrake.\nLatest is %s (build %d).\n", version,
207                      build );
208         }
209         else
210         {
211             fprintf( stderr, "Your version of HandBrake is up to "
212                      "date.\n" );
213         }
214         hb_close( &h );
215         return 0;
216     }
217
218     /* Geeky */
219     fprintf( stderr, "%d CPU%s detected\n", hb_get_cpu_count(),
220              hb_get_cpu_count( h ) > 1 ? "s" : "" );
221     if( cpu )
222     {
223         fprintf( stderr, "Forcing %d CPU%s\n", cpu,
224                  cpu > 1 ? "s" : "" );
225         hb_set_cpu_count( h, cpu );
226     }
227
228     /* Exit ASAP on Ctrl-C */
229     signal( SIGINT, SigHandler );
230
231     /* Feed libhb with a DVD to scan */
232     fprintf( stderr, "Opening %s...\n", input );
233
234     if (longest_title) {
235         /*
236          * We need to scan for all the titles in order to find the longest
237          */
238         titleindex = 0;
239     }
240
241     hb_scan( h, input, titleindex, preview_count, store_previews );
242
243     /* Wait... */
244     while( !die )
245     {
246 #if defined( __MINGW32__ )
247         if( _kbhit() ) {
248             switch( _getch() )
249             {
250                 case 0x03: /* ctrl-c */
251                 case 'q':
252                     fprintf( stdout, "\nEncoding Quit by user command\n" );
253                     die = 1;
254                     break;
255                 case 'p':
256                     fprintf( stdout, "\nEncoding Paused by user command, 'r' to resume\n" );
257                     hb_pause( h );
258                     break;
259                 case 'r':
260                     hb_resume( h );
261                     break;
262                 case 'h':
263                     ShowCommands();
264                     break;
265             }
266         }
267         hb_snooze( 200 );
268 #elif !defined(SYS_BEOS)
269         fd_set         fds;
270         struct timeval tv;
271         int            ret;
272         char           buf[257];
273
274         tv.tv_sec  = 0;
275         tv.tv_usec = 100000;
276
277         FD_ZERO( &fds );
278         FD_SET( STDIN_FILENO, &fds );
279         ret = select( STDIN_FILENO + 1, &fds, NULL, NULL, &tv );
280
281         if( ret > 0 )
282         {
283             int size = 0;
284
285             while( size < 256 &&
286                    read( STDIN_FILENO, &buf[size], 1 ) > 0 )
287             {
288                 if( buf[size] == '\n' )
289                 {
290                     break;
291                 }
292                 size++;
293             }
294
295             if( size >= 256 || buf[size] == '\n' )
296             {
297                 switch( buf[0] )
298                 {
299                     case 'q':
300                         fprintf( stdout, "\nEncoding Quit by user command\n" );
301                         die = 1;
302                         break;
303                     case 'p':
304                         fprintf( stdout, "\nEncoding Paused by user command, 'r' to resume\n" );
305                         hb_pause( h );
306                         break;
307                     case 'r':
308                         hb_resume( h );
309                         break;
310                     case 'h':
311                         ShowCommands();
312                         break;
313                 }
314             }
315         }
316         hb_snooze( 200 );
317 #else
318         hb_snooze( 200 );
319 #endif
320
321         HandleEvents( h );
322     }
323
324     /* Clean up */
325     hb_close( &h );
326     if( input )  free( input );
327     if( output ) free( output );
328     if( format ) free( format );
329     if( audios )
330     {
331         while( ( audio = hb_list_item( audios, 0 ) ) )
332         {
333             hb_list_rem( audios, audio );
334             if( audio->out.name )
335             {
336                 free( audio->out.name );
337             }
338             free( audio );
339         }
340         hb_list_close( &audios );
341     }
342     if( mixdowns ) free( mixdowns );
343     if( dynamic_range_compression ) free( dynamic_range_compression );
344     if( atracks ) free( atracks );
345     if( arates ) free( arates );
346     if( abitrates ) free( abitrates );
347     if( acodecs ) free( acodecs );
348     if( anames ) free( anames );
349     if (native_language ) free (native_language );
350         if( x264opts ) free (x264opts );
351         if( x264opts2 ) free (x264opts2 );
352     if (preset_name) free (preset_name);
353     if( stop_at_string ) free( stop_at_string );
354
355     fprintf( stderr, "HandBrake has exited.\n" );
356
357 #if defined( PTW32_STATIC_LIB )
358     pthread_win32_thread_detach_np();
359     pthread_win32_process_detach_np();
360 #endif
361
362     return 0;
363 }
364
365 static void ShowCommands()
366 {
367     fprintf( stdout, "\nCommands:\n" );
368     fprintf( stdout, " [h]elp    Show this message\n" );
369     fprintf( stdout, " [q]uit    Exit HandBrakeCLI\n" );
370     fprintf( stdout, " [p]ause   Pause encoding\n" );
371     fprintf( stdout, " [r]esume  Resume encoding\n" );
372 }
373
374 static void PrintTitleInfo( hb_title_t * title )
375 {
376     hb_chapter_t  * chapter;
377     hb_subtitle_t * subtitle;
378     int i;
379
380     fprintf( stderr, "+ title %d:\n", title->index );
381     fprintf( stderr, "  + vts %d, ttn %d, cells %d->%d (%d blocks)\n",
382              title->vts, title->ttn, title->cell_start, title->cell_end,
383              title->block_count );
384     if (dvdnav)
385         fprintf( stderr, "  + angle(s) %d\n", title->angle_count );
386     fprintf( stderr, "  + duration: %02d:%02d:%02d\n",
387              title->hours, title->minutes, title->seconds );
388     fprintf( stderr, "  + size: %dx%d, pixel aspect: %d/%d, display aspect: %.2f, %.3f fps\n",
389              title->width, title->height,
390              title->pixel_aspect_width,
391              title->pixel_aspect_height,
392              (float) title->aspect,
393              (float) title->rate / title->rate_base );
394     fprintf( stderr, "  + autocrop: %d/%d/%d/%d\n", title->crop[0],
395              title->crop[1], title->crop[2], title->crop[3] );
396     fprintf( stderr, "  + chapters:\n" );
397     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
398     {
399         chapter = hb_list_item( title->list_chapter, i );
400         fprintf( stderr, "    + %d: cells %d->%d, %d blocks, duration "
401                  "%02d:%02d:%02d\n", chapter->index,
402                  chapter->cell_start, chapter->cell_end,
403                  chapter->block_count, chapter->hours, chapter->minutes,
404                  chapter->seconds );
405     }
406     fprintf( stderr, "  + audio tracks:\n" );
407     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
408     {
409         audio = hb_list_audio_config_item( title->list_audio, i );
410         if( ( audio->in.codec == HB_ACODEC_AC3 ) || ( audio->in.codec == HB_ACODEC_DCA) )
411         {
412             fprintf( stderr, "    + %d, %s, %dHz, %dbps\n", i + 1,
413                      audio->lang.description, audio->in.samplerate, audio->in.bitrate );
414         }
415         else
416         {
417             fprintf( stderr, "    + %d, %s\n", i + 1, audio->lang.description );
418         }
419     }
420     fprintf( stderr, "  + subtitle tracks:\n" );
421     for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
422     {
423         subtitle = hb_list_item( title->list_subtitle, i );
424         fprintf( stderr, "    + %d, %s (iso639-2: %s) (%s)\n", 
425                  i + 1, subtitle->lang,
426                  subtitle->iso639_2,
427                  (subtitle->format == TEXTSUB) ? "Text" : "Bitmap");
428     }
429
430     if(title->detected_interlacing)
431     {
432         /* Interlacing was found in half or more of the preview frames */
433         fprintf( stderr, "  + combing detected, may be interlaced or telecined\n");
434     }
435
436 }
437
438 static int test_sub_list( char ** list, char * needle, int pos )
439 {
440     int i;
441
442     if ( list == NULL || needle == NULL )
443         return 0;
444
445     if ( list[0] == NULL && pos == 1 )
446         return 1;
447
448     for ( i = 0; list[i] != NULL; i++ )
449     {
450         if ( strcasecmp( list[i], needle ) == 0 )
451             return i + 1;
452     }
453     return 0;
454 }
455
456 static int HandleEvents( hb_handle_t * h )
457 {
458     hb_state_t s;
459     int tmp_num_audio_tracks;
460
461     hb_get_state( h, &s );
462     switch( s.state )
463     {
464         case HB_STATE_IDLE:
465             /* Nothing to do */
466             break;
467
468 #define p s.param.scanning
469         case HB_STATE_SCANNING:
470             /* Show what title is currently being scanned */
471             fprintf( stderr, "Scanning title %d", p.title_cur );
472             if( !titleindex )
473                 fprintf( stderr, " of %d", p.title_count );
474             fprintf( stderr, "...\n" );
475             break;
476 #undef p
477
478         case HB_STATE_SCANDONE:
479         {
480             hb_list_t  * list;
481             hb_title_t * title;
482             hb_job_t   * job;
483             int i;
484             int sub_burned = 0;
485
486             /* Audio argument string parsing variables */
487             int acodec = 0;
488             int abitrate = 0;
489             int arate = 0;
490             int mixdown = HB_AMIXDOWN_DOLBYPLII;
491             double d_r_c = 0;
492             /* Audio argument string parsing variables */
493
494             list = hb_get_titles( h );
495
496             if( !hb_list_count( list ) )
497             {
498                 /* No valid title, stop right there */
499                 fprintf( stderr, "No title found.\n" );
500                 die = 1;
501                 break;
502             }
503                 if( longest_title )
504                 {
505                 int i;
506                 int longest_title_idx=0;
507                 int longest_title_pos=-1;
508                 int longest_title_time=0;
509                 int title_time;
510
511                 fprintf( stderr, "Searching for longest title...\n" );
512
513                 for( i = 0; i < hb_list_count( list ); i++ )
514                 {
515                     title = hb_list_item( list, i );
516                     title_time = (title->hours*60*60 ) + (title->minutes *60) + (title->seconds);
517                     fprintf( stderr, " + Title (%d) index %d has length %dsec\n",
518                              i, title->index, title_time );
519                     if( longest_title_time < title_time )
520                     {
521                         longest_title_time = title_time;
522                         longest_title_pos = i;
523                         longest_title_idx = title->index;
524                     }
525                 }
526                 if( longest_title_pos == -1 )
527                 {
528                     fprintf( stderr, "No longest title found.\n" );
529                     die = 1;
530                     break;
531                 }
532                 titleindex = longest_title_idx;
533                 fprintf( stderr, "Found longest title, setting title to %d\n",
534                          longest_title_idx);
535
536                 title = hb_list_item( list, longest_title_pos);
537             } else {
538                 title = hb_list_item( list, 0 );
539             }
540
541             if( !titleindex )
542             {
543                 /* Scan-only mode, print infos and exit */
544                 int i;
545                 for( i = 0; i < hb_list_count( list ); i++ )
546                 {
547                     title = hb_list_item( list, i );
548                     PrintTitleInfo( title );
549                 }
550                 die = 1;
551                 break;
552             }
553
554             /* Set job settings */
555             job   = title->job;
556
557             PrintTitleInfo( title );
558
559             if( chapter_start && chapter_end && !stop_at_pts && !start_at_preview && !stop_at_frame )
560             {
561                 job->chapter_start = MAX( job->chapter_start,
562                                           chapter_start );
563                 job->chapter_end   = MIN( job->chapter_end,
564                                           chapter_end );
565                 job->chapter_end   = MAX( job->chapter_start,
566                                           job->chapter_end );
567             }
568
569             if ( angle )
570             {
571                 job->angle = angle;
572             }
573
574             if (preset)
575             {
576                 fprintf( stderr, "+ Using preset: %s", preset_name);
577
578                 if (!strcmp(preset_name, "Universal"))
579                 {
580                     if( !mux )
581                     {
582                         mux = HB_MUX_MP4;
583                     }
584                     vcodec = HB_VCODEC_X264;
585                     job->vquality = 20.0;
586                     job->crf = 1;
587                     if( !atracks )
588                     {
589                         atracks = strdup("1,1");
590                     }
591                     if( !acodecs )
592                     {
593                         acodecs = strdup("faac,ac3");
594                     }
595                     if( !abitrates )
596                     {
597                         abitrates = strdup("160,160");
598                     }
599                     if( !mixdowns )
600                     {
601                         mixdowns = strdup("dpl2,auto");
602                     }
603                     if( !arates )
604                     {
605                         arates = strdup("48,Auto");
606                     }
607                     if( !dynamic_range_compression )
608                     {
609                         dynamic_range_compression = strdup("0.0,0.0");
610                     }
611                     maxWidth = 720;
612                     if( !x264opts )
613                     {
614                         x264opts = strdup("cabac=0:ref=2:mixed-refs=1:me=umh");
615                     }
616                     anamorphic_mode = 2;
617                     job->chapter_markers = 1;
618                 }
619
620                 if (!strcmp(preset_name, "iPod"))
621                 {
622                     if( !mux )
623                     {
624                         mux = HB_MUX_MP4;
625                     }
626                     job->ipod_atom = 1;
627                     vcodec = HB_VCODEC_X264;
628                     job->vbitrate = 700;
629                     if( !atracks )
630                     {
631                         atracks = strdup("1");
632                     }
633                     if( !acodecs )
634                     {
635                         acodecs = strdup("faac");
636                     }
637                     if( !abitrates )
638                     {
639                         abitrates = strdup("160");
640                     }
641                     if( !mixdowns )
642                     {
643                         mixdowns = strdup("dpl2");
644                     }
645                     if( !arates )
646                     {
647                         arates = strdup("48");
648                     }
649                     if( !dynamic_range_compression )
650                     {
651                         dynamic_range_compression = strdup("0.0");
652                     }
653                     maxWidth = 320;
654                     if( !x264opts )
655                     {
656                         x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1");
657                     }
658                     job->chapter_markers = 1;
659                 }
660
661                 if (!strcmp(preset_name, "iPhone & iPod Touch"))
662                 {
663                     if( !mux )
664                     {
665                         mux = HB_MUX_MP4;
666                     }
667                     vcodec = HB_VCODEC_X264;
668                     job->vquality = 20.0;
669                     job->crf = 1;
670                     if( !atracks )
671                     {
672                         atracks = strdup("1");
673                     }
674                     if( !acodecs )
675                     {
676                         acodecs = strdup("faac");
677                     }
678                     if( !abitrates )
679                     {
680                         abitrates = strdup("128");
681                     }
682                     if( !mixdowns )
683                     {
684                         mixdowns = strdup("dpl2");
685                     }
686                     if( !arates )
687                     {
688                         arates = strdup("48");
689                     }
690                     if( !dynamic_range_compression )
691                     {
692                         dynamic_range_compression = strdup("0.0");
693                     }
694                     maxWidth = 480;
695                     if( !x264opts )
696                     {
697                         x264opts = strdup("cabac=0:ref=2:mixed-refs:me=umh");
698                     }
699                     job->chapter_markers = 1;
700                 }
701
702                 if (!strcmp(preset_name, "AppleTV"))
703                 {
704                     if( !mux )
705                     {
706                         mux = HB_MUX_MP4;
707                     }
708                     job->largeFileSize = 1;
709                     vcodec = HB_VCODEC_X264;
710                     job->vquality = 20.0;
711                     job->crf = 1;
712                     if( !atracks )
713                     {
714                         atracks = strdup("1,1");
715                     }
716                     if( !acodecs )
717                     {
718                         acodecs = strdup("faac,ac3");
719                     }
720                     if( !abitrates )
721                     {
722                         abitrates = strdup("160,160");
723                     }
724                     if( !mixdowns )
725                     {
726                         mixdowns = strdup("dpl2,auto");
727                     }
728                     if( !arates )
729                     {
730                         arates = strdup("48,Auto");
731                     }
732                     if( !dynamic_range_compression )
733                     {
734                         dynamic_range_compression = strdup("0.0,0.0");
735                     }
736                     maxWidth = 960;
737                     if( !x264opts )
738                     {
739                         x264opts = strdup("cabac=0:ref=2:mixed-refs=1:bframes=3:me=umh:subme=7:b-adapt=2:8x8dct=1");
740                     }
741                     anamorphic_mode = 2;
742                     job->chapter_markers = 1;
743                 }
744
745                 if (!strcmp(preset_name, "Normal"))
746                 {
747                     if( !mux )
748                     {
749                         mux = HB_MUX_MP4;
750                     }
751                     vcodec = HB_VCODEC_X264;
752                     job->vquality = 20.0;
753                     job->crf = 1;
754                     if( !atracks )
755                     {
756                         atracks = strdup("1");
757                     }
758                     if( !acodecs )
759                     {
760                         acodecs = strdup("faac");
761                     }
762                     if( !abitrates )
763                     {
764                         abitrates = strdup("160");
765                     }
766                     if( !mixdowns )
767                     {
768                         mixdowns = strdup("dpl2");
769                     }
770                     if( !arates )
771                     {
772                         arates = strdup("48");
773                     }
774                     if( !dynamic_range_compression )
775                     {
776                         dynamic_range_compression = strdup("0.0");
777                     }
778                     if( !x264opts )
779                     {
780                         x264opts = strdup("ref=2:bframes=2:me=umh");
781                     }
782                     anamorphic_mode = 1;
783                     job->chapter_markers = 1;
784                 }
785
786                 if (!strcmp(preset_name, "High Profile"))
787                 {
788                     if( !mux )
789                     {
790                         mux = HB_MUX_MP4;
791                     }
792                     vcodec = HB_VCODEC_X264;
793                     job->vquality = 20.0;
794                     job->crf = 1;
795                     if( !atracks )
796                     {
797                         atracks = strdup("1,1");
798                     }
799                     if( !acodecs )
800                     {
801                         acodecs = strdup("faac,ac3");
802                     }
803                     if( !abitrates )
804                     {
805                         abitrates = strdup("160,160");
806                     }
807                     if( !mixdowns )
808                     {
809                         mixdowns = strdup("dpl2,auto");
810                     }
811                     if( !arates )
812                     {
813                         arates = strdup("48,Auto");
814                     }
815                     if( !dynamic_range_compression )
816                     {
817                         dynamic_range_compression = strdup("0.0,0.0");
818                     }
819                     if( !x264opts )
820                     {
821                         x264opts = strdup("ref=3:mixed-refs:bframes=3:weightb:b-pyramid:b-adapt=2:me=umh:subme=9:analyse=all:8x8dct");
822                     }
823                     detelecine = 1;
824                     decomb = 1;
825                     anamorphic_mode = 2;
826                     job->chapter_markers = 1;
827                 }
828
829                 if (!strcmp(preset_name, "Classic"))
830                 {
831                     if( !mux )
832                     {
833                         mux = HB_MUX_MP4;
834                     }
835                     job->vbitrate = 1000;
836                     if( !atracks )
837                     {
838                         atracks = strdup("1");
839                     }
840                     if( !acodecs )
841                     {
842                         acodecs = strdup("faac");
843                     }
844                     if( !abitrates )
845                     {
846                         abitrates = strdup("160");
847                     }
848                     if( !mixdowns )
849                     {
850                         mixdowns = strdup("dpl2");
851                     }
852                     if( !arates )
853                     {
854                         arates = strdup("48");
855                     }
856                     if( !dynamic_range_compression )
857                     {
858                         dynamic_range_compression = strdup("0.0");
859                     }
860                 }
861
862                 if (!strcmp(preset_name, "AppleTV Legacy"))
863                 {
864                     if( !mux )
865                     {
866                         mux = HB_MUX_MP4;
867                     }
868                     job->largeFileSize = 1;
869                     vcodec = HB_VCODEC_X264;
870                     job->vbitrate = 2500;
871                     if( !atracks )
872                     {
873                         atracks = strdup("1,1");
874                     }
875                     if( !acodecs )
876                     {
877                         acodecs = strdup("faac,ac3");
878                     }
879                     if( !abitrates )
880                     {
881                         abitrates = strdup("160,160");
882                     }
883                     if( !mixdowns )
884                     {
885                         mixdowns = strdup("dpl2,auto");
886                     }
887                     if( !arates )
888                     {
889                         arates = strdup("48,Auto");
890                     }
891                     if( !dynamic_range_compression )
892                     {
893                         dynamic_range_compression = strdup("0.0,0.0");
894                     }
895                     if( !x264opts )
896                     {
897                         x264opts = strdup("bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:cabac=0");
898                     }
899                     anamorphic_mode = 1;
900                     job->chapter_markers = 1;
901                 }
902
903                 if (!strcmp(preset_name, "iPhone Legacy"))
904                 {
905                     if( !mux )
906                     {
907                         mux = HB_MUX_MP4;
908                     }
909                     job->ipod_atom = 1;
910                     vcodec = HB_VCODEC_X264;
911                     job->vbitrate = 960;
912                     if( !atracks )
913                     {
914                         atracks = strdup("1");
915                     }
916                     if( !acodecs )
917                     {
918                         acodecs = strdup("faac");
919                     }
920                     if( !abitrates )
921                     {
922                         abitrates = strdup("128");
923                     }
924                     if( !mixdowns )
925                     {
926                         mixdowns = strdup("dpl2");
927                     }
928                     if( !arates )
929                     {
930                         arates = strdup("48");
931                     }
932                     if( !dynamic_range_compression )
933                     {
934                         dynamic_range_compression = strdup("0.0");
935                     }
936                     maxWidth = 480;
937                     if( !x264opts )
938                     {
939                         x264opts = strdup("level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0");
940                     }
941                     job->chapter_markers = 1;
942                 }
943
944                 if (!strcmp(preset_name, "iPod Legacy"))
945                 {
946                     if( !mux )
947                     {
948                         mux = HB_MUX_MP4;
949                     }
950                     job->ipod_atom = 1;
951                     vcodec = HB_VCODEC_X264;
952                     job->vbitrate = 1500;
953                     if( !atracks )
954                     {
955                         atracks = strdup("1");
956                     }
957                     if( !acodecs )
958                     {
959                         acodecs = strdup("faac");
960                     }
961                     if( !abitrates )
962                     {
963                         abitrates = strdup("160");
964                     }
965                     if( !mixdowns )
966                     {
967                         mixdowns = strdup("dpl2");
968                     }
969                     if( !arates )
970                     {
971                         arates = strdup("48");
972                     }
973                     if( !dynamic_range_compression )
974                     {
975                         dynamic_range_compression = strdup("0.0");
976                     }
977                     maxWidth = 640;
978                     if( !x264opts )
979                     {
980                         x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0");
981                     }
982                     job->chapter_markers = 1;
983                 }
984             }
985
986                         if ( chapter_markers )
987                         {
988                                 job->chapter_markers = chapter_markers;
989
990                 if( marker_file != NULL )
991                 {
992                     hb_csv_file_t * file = hb_open_csv_file( marker_file );
993                     hb_csv_cell_t * cell;
994                     int row = 0;
995                     int chapter = 0;
996
997                     fprintf( stderr, "Reading chapter markers from file %s\n", marker_file );
998
999                     if( file == NULL )
1000                     {
1001                          fprintf( stderr, "Cannot open chapter marker file, using defaults\n" );
1002                     }
1003                     else
1004                     {
1005                         /* Parse the cells */
1006                         while( NULL != ( cell = hb_read_next_cell( file ) ) )
1007                         {
1008                             /* We have a chapter number */
1009                             if( cell->cell_col == 0 )
1010                             {
1011                                 row = cell->cell_row;
1012                                 chapter = atoi( cell->cell_text );
1013                             }
1014
1015                             /* We have a chapter name */
1016                             if( cell->cell_col == 1 && row == cell->cell_row )
1017                             {
1018                                 /* If we have a valid chapter, copy the string an terminate it */
1019                                 if( chapter >= job->chapter_start && chapter <= job->chapter_end )
1020                                 {
1021                                     hb_chapter_t * chapter_s;
1022
1023                                     chapter_s = hb_list_item( job->title->list_chapter, chapter - 1);
1024                                     strncpy(chapter_s->title, cell->cell_text, 1023);
1025                                     chapter_s->title[1023] = '\0';
1026                                 }
1027                             }
1028
1029
1030                             hb_dispose_cell( cell );
1031                         }
1032
1033                         hb_close_csv_file( file );
1034                     }
1035                 }
1036                 else
1037                 {
1038                     /* No marker file */
1039
1040                     int number_of_chapters = hb_list_count(job->title->list_chapter);
1041                     int chapter;
1042
1043                     for(chapter = 0; chapter <= number_of_chapters - 1 ; chapter++)
1044                     {
1045                         hb_chapter_t * chapter_s;
1046                         chapter_s = hb_list_item( job->title->list_chapter, chapter);
1047                         snprintf( chapter_s->title, 1023, "Chapter %i", chapter + 1 );
1048                         chapter_s->title[1023] = '\0';
1049                     }
1050                 }
1051                         }
1052
1053             if( crop[0] >= 0 && crop[1] >= 0 &&
1054                 crop[2] >= 0 && crop[3] >= 0 )
1055             {
1056                 memcpy( job->crop, crop, 4 * sizeof( int ) );
1057             }
1058
1059             job->deinterlace = deinterlace;
1060             job->grayscale   = grayscale;
1061             
1062             /* Add selected filters */
1063             job->filters = hb_list_init();
1064             if( detelecine )
1065             {
1066                 hb_filter_detelecine.settings = detelecine_opt;
1067                 hb_list_add( job->filters, &hb_filter_detelecine );
1068             }
1069             if( decomb )
1070             {
1071                 hb_filter_decomb.settings = decomb_opt;
1072                 hb_list_add( job->filters, &hb_filter_decomb );
1073             }
1074             if( deinterlace )
1075             {
1076                 hb_filter_deinterlace.settings = deinterlace_opt;
1077                 hb_list_add( job->filters, &hb_filter_deinterlace );
1078             }
1079             if( deblock )
1080             {
1081                 hb_filter_deblock.settings = deblock_opt;
1082                 hb_list_add( job->filters, &hb_filter_deblock );
1083             }
1084             if( denoise )
1085             {
1086                 hb_filter_denoise.settings = denoise_opt;
1087                 hb_list_add( job->filters, &hb_filter_denoise );
1088             }
1089
1090             switch( anamorphic_mode )
1091             {
1092                 case 0: // Non-anamorphic
1093                     
1094                     if( width && height )
1095                     {
1096                         job->width  = width;
1097                         job->height = height;
1098                     }
1099                     else if( width )
1100                     {
1101                         job->width = width;
1102                         hb_fix_aspect( job, HB_KEEP_WIDTH );
1103                     }
1104                     else if( height )
1105                     {
1106                         job->height = height;
1107                         hb_fix_aspect( job, HB_KEEP_HEIGHT );
1108                     }
1109                     else if( !width && !height )
1110                     {
1111                         hb_fix_aspect( job, HB_KEEP_WIDTH );
1112                     }
1113
1114                 break;
1115                 
1116                 case 1: // Strict anammorphic
1117                     job->anamorphic.mode = anamorphic_mode;
1118                 break;
1119                 
1120                 case 2: // Loose anamorphic
1121                     job->anamorphic.mode = 2;
1122                     
1123                     if (modulus)
1124                     {
1125                         job->anamorphic.modulus = modulus;
1126                     }
1127                     
1128                     if( itu_par )
1129                     {
1130                         job->anamorphic.itu_par = itu_par;
1131                     }
1132                     
1133                     if( width )
1134                     {
1135                         job->width = width;
1136                     }
1137                     else if( !width && !height )
1138                     {
1139                         /* Default to full width when one isn't specified for loose anamorphic */
1140                         job->width = title->width - job->crop[2] - job->crop[3];
1141                     }
1142                     
1143                 break;
1144                 
1145                 case 3: // Custom Anamorphic 3: Power User Jamboree 
1146                     job->anamorphic.mode = 3;
1147                     
1148                     if (modulus)
1149                     {
1150                         job->anamorphic.modulus = modulus;
1151                     }
1152                     
1153                     if( itu_par )
1154                     {
1155                         job->anamorphic.itu_par = itu_par;
1156                     }
1157                     
1158                     if( par_width && par_height )
1159                     {
1160                         job->anamorphic.par_width = par_width;
1161                         job->anamorphic.par_height = par_height;
1162                     }
1163                     
1164                     if( keep_display_aspect )
1165                     {
1166                         job->anamorphic.keep_display_aspect = 1;
1167                         
1168                         /* First, what *is* the display aspect? */
1169                         int cropped_width = title->width - job->crop[2] - job->crop[3];
1170                         int cropped_height = title->height - job->crop[0] - job->crop[1];
1171                         
1172                         /* XXX -- I'm assuming people want to keep the source
1173                            display AR even though they might have already
1174                            asked for ITU values instead. */
1175                         float source_display_width = (float)cropped_width *
1176                             (float)title->pixel_aspect_width / (float)title->pixel_aspect_height;
1177                         float display_aspect = source_display_width / (float)cropped_height;
1178                         /* When keeping display aspect, we have to rank some values
1179                            by priority in order to consistently handle situations
1180                            when more than one might be specified by default.
1181                            
1182                            * First off, PAR gets ignored. (err make this reality)
1183                            * Height will be respected over all other settings,
1184                            * If it isn't set, display_width will be followed.
1185                            * If it isn't set, width will be followed.          */
1186                         if( height )
1187                         {
1188                             /* We scale the display width to the new height */
1189                             display_width = (int)( (double)height * display_aspect );
1190                         }
1191                         else if( display_width )
1192                         {
1193                             /* We scale the height to the new display width */
1194                             height = (int)( (double)display_width / display_aspect );
1195                         }
1196                     }
1197                     
1198                     if( display_width )
1199                     {
1200                         /* Adjust the PAR to create the new display width
1201                            from the default job width. */
1202                         job->anamorphic.dar_width = display_width;
1203                         
1204                         job->anamorphic.dar_height = height ?
1205                                                         height :
1206                                                         title->height - job->crop[0] - job->crop[1];
1207                     }
1208                     
1209                     if( width && height )
1210                     {
1211                         /* Use these storage dimensions */
1212                         job->width  = width;
1213                         job->height = height;
1214                     }
1215                     else if( width )
1216                     {
1217                         /* Use just this storage width */
1218                         job->width = width;
1219                         job->height = title->height - job->crop[0] - job->crop[1];
1220                     }
1221                     else if( height )
1222                     {
1223                         /* Use just this storage height. */
1224                         job->height = height;
1225                         job->width = title->width - job->crop[2] - job->crop[3];
1226                     }
1227                     else if( !width && !height )
1228                     {
1229                         /* Assume source dimensions after cropping. */
1230                         job->width = title->width - job->crop[2] - job->crop[3];
1231                         job->height = title->height - job->crop[0] - job->crop[1];
1232                     }
1233                     
1234                 break;
1235             }
1236
1237             if( vquality >= 0.0 && ( ( vquality <= 1.0 ) || ( vcodec == HB_VCODEC_X264 ) || (vcodec == HB_VCODEC_FFMPEG) ) )
1238             {
1239                 job->vquality = vquality;
1240                 job->vbitrate = 0;
1241             }
1242             else if( vbitrate )
1243             {
1244                 job->vquality = -1.0;
1245                 job->vbitrate = vbitrate;
1246             }
1247             if( vcodec )
1248             {
1249                 job->vcodec = vcodec;
1250             }
1251             if( h264_13 )
1252             {
1253                 job->h264_level = 13;
1254             }
1255                 if( h264_30 )
1256                 {
1257                     job->h264_level = 30;
1258             }
1259             if( vrate )
1260             {
1261                 job->cfr = cfr;
1262                 job->vrate = 27000000;
1263                 job->vrate_base = vrate;
1264             }
1265             else if ( cfr )
1266             {
1267                 // cfr or pfr flag with no rate specified implies
1268                 // use the title rate.
1269                 job->cfr = cfr;
1270                 job->vrate = title->rate;
1271                 job->vrate_base = title->rate_base;
1272             }
1273
1274             /* Grab audio tracks */
1275             if( atracks )
1276             {
1277                 char * token = strtok(atracks, ",");
1278                 if (token == NULL)
1279                     token = optarg;
1280                 int track_start, track_end;
1281                 while( token != NULL )
1282                 {
1283                     audio = calloc(1, sizeof(*audio));
1284                     hb_audio_config_init(audio);
1285                     if (strlen(token) >= 3)
1286                     {
1287                         if (sscanf(token, "%d-%d", &track_start, &track_end) == 2)
1288                         {
1289                             int i;
1290                             for (i = track_start - 1; i < track_end; i++)
1291                             {
1292                                 if (i != track_start - 1)
1293                                 {
1294                                     audio = calloc(1, sizeof(*audio));
1295                                     hb_audio_config_init(audio);
1296                                 }
1297                                 audio->in.track = i;
1298                                 audio->out.track = num_audio_tracks++;
1299                                 hb_list_add(audios, audio);
1300                             }
1301                         }
1302                         else if( !strcasecmp(token, "none" ) )
1303                         {
1304                             audio->in.track = audio->out.track = -1;
1305                             audio->out.codec = 0;
1306                             hb_list_add(audios, audio);
1307                             break;
1308                         }
1309                         else
1310                         {
1311                             fprintf(stderr, "ERROR: Unable to parse audio input \"%s\", skipping.",
1312                                     token);
1313                             free(audio);
1314                         }
1315                     }
1316                     else
1317                     {
1318                         audio->in.track = atoi(token) - 1;
1319                         audio->out.track = num_audio_tracks++;
1320                         hb_list_add(audios, audio);
1321                     }
1322                     token = strtok(NULL, ",");
1323                 }
1324             }
1325
1326             /* Parse audio tracks */
1327             if( native_language && native_dub )
1328             {
1329                 if( hb_list_count( audios ) == 0 || !audio_explicit )
1330                 {
1331                     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
1332                     {
1333                         char audio_lang[4];
1334                         int track = i;
1335                         
1336                         audio = hb_list_audio_config_item( title->list_audio, i );
1337                         
1338                         strncpy( audio_lang, audio->lang.iso639_2, sizeof( audio_lang ) );
1339                         
1340                         if( strncasecmp( native_language, audio_lang, 
1341                                          sizeof( audio_lang ) ) == 0 &&
1342                             audio->lang.type != 3 && // Directors 1
1343                             audio->lang.type != 4)   // Directors 2
1344                         {
1345                             /*
1346                              * Matched an audio to our native language - use it.
1347                              * Replace any existing audio tracks that a preset may
1348                              * have put here.
1349                              */
1350                             if( hb_list_count(audios) == 0) {
1351                                 audio = calloc(1, sizeof(*audio));
1352                                 hb_audio_config_init(audio);
1353                                 audio->in.track = track;
1354                                 audio->out.track = num_audio_tracks++;
1355                                 /* Add it to our audios */
1356                                 hb_list_add(audios, audio);
1357                             } else {
1358                                 /*
1359                                  * Update the track numbers on what is already in
1360                                  * there.
1361                                  */
1362                                 for( i=0; i < hb_list_count( audios ); i++ )
1363                                 {
1364                                     audio = hb_list_item( audios, i );
1365
1366                                     audio->in.track = track;
1367                                 }
1368                             }
1369                             break;
1370                         }
1371                     }
1372                 } else {
1373                     fprintf( stderr, "Warning: Native language (dubbing) selection ignored since an audio track has already been selected\n");
1374                 }
1375             }
1376
1377             if( hb_list_count(audios) == 0 )
1378             {        
1379                 /* Create a new audio track with default settings */
1380                 audio = calloc(1, sizeof(*audio));
1381                 hb_audio_config_init(audio);
1382                 /* Add it to our audios */
1383                 hb_list_add(audios, audio);
1384             }
1385
1386             tmp_num_audio_tracks = num_audio_tracks = hb_list_count(audios);
1387             for (i = 0; i < tmp_num_audio_tracks; i++)
1388             {
1389                 audio = hb_list_item(audios, 0);
1390                 if( (audio == NULL) || (audio->in.track == -1) ||
1391                     (audio->out.track == -1) || (audio->out.codec == 0) )
1392                 {
1393                     num_audio_tracks--;
1394                 }
1395                 else
1396                 {
1397                     if( hb_audio_add( job, audio ) == 0 )
1398                     {
1399                         fprintf(stderr, "ERROR: Invalid audio input track '%u', exiting.\n", 
1400                                 audio->in.track + 1 );
1401                         num_audio_tracks--;
1402                         exit(3);
1403                     }
1404                 }
1405                 hb_list_rem(audios, audio);
1406                 if( audio != NULL)
1407                     if( audio->out.name )
1408                     {
1409                         free( audio->out.name);
1410                     }
1411                     free( audio );
1412             }
1413
1414             /* Audio Codecs */
1415             i = 0;
1416             if( acodecs )
1417             {
1418                 char * token = strtok(acodecs, ",");
1419                 if( token == NULL )
1420                     token = acodecs;
1421                 while ( token != NULL )
1422                 {
1423                     if ((acodec = get_acodec_for_string(token)) == -1)
1424                     {
1425                         fprintf(stderr, "Invalid codec %s, using default for container.\n", token);
1426                         acodec = default_acodec;
1427                     }
1428                     if( i < num_audio_tracks )
1429                     {
1430                         audio = hb_list_audio_config_item(job->list_audio, i);
1431                         audio->out.codec = acodec;
1432                     }
1433                     else
1434                     {
1435                         hb_audio_config_t * last_audio = hb_list_audio_config_item( job->list_audio, i - 1 );
1436                         hb_audio_config_t audio;
1437
1438                         if( last_audio )
1439                         {
1440                             fprintf(stderr, "More audio codecs than audio tracks, copying track %i and using encoder %s\n",
1441                                     i, token);
1442                             hb_audio_config_init(&audio);
1443                             audio.in.track = last_audio->in.track;
1444                             audio.out.track = num_audio_tracks++;
1445                             audio.out.codec = acodec;
1446                             hb_audio_add(job, &audio);
1447                         }
1448                         else
1449                         {
1450                             fprintf(stderr, "Audio codecs and no valid audio tracks, skipping codec %s\n", token);
1451                         }
1452                     }
1453                     token = strtok(NULL, ",");
1454                     i++;
1455                 }
1456             }
1457             if( i < num_audio_tracks )
1458             {
1459                 /* We have fewer inputs than audio tracks, use the default codec for
1460                  * this container for the remaining tracks. Unless we only have one input
1461                  * then use that codec instead.
1462                  */
1463                 if (i != 1)
1464                     acodec = default_acodec;
1465                 for ( ; i < num_audio_tracks; i++)
1466                 {
1467                     audio = hb_list_audio_config_item(job->list_audio, i);
1468                     audio->out.codec = acodec;
1469                 }
1470             }
1471             /* Audio Codecs */
1472
1473             /* Sample Rate */
1474             i = 0;
1475             if( arates )
1476             {
1477                 char * token = strtok(arates, ",");
1478                 if (token == NULL)
1479                     token = arates;
1480                 while ( token != NULL )
1481                 {
1482                     arate = atoi(token);
1483                     audio = hb_list_audio_config_item(job->list_audio, i);
1484                     int j;
1485
1486                     for( j = 0; j < hb_audio_rates_count; j++ )
1487                     {
1488                         if( !strcmp( token, hb_audio_rates[j].string ) )
1489                         {
1490                             arate = hb_audio_rates[j].rate;
1491                             break;
1492                         }
1493                     }
1494
1495                     if( audio != NULL )
1496                     {
1497                         if (!is_sample_rate_valid(arate))
1498                         {
1499                             fprintf(stderr, "Invalid sample rate %d, using input rate %d\n", arate, audio->in.samplerate);
1500                             arate = audio->in.samplerate;
1501                         }
1502                         
1503                         audio->out.samplerate = arate;
1504                         if( (++i) >= num_audio_tracks )
1505                             break;  /* We have more inputs than audio tracks, oops */
1506                     }
1507                     else 
1508                     {
1509                         fprintf(stderr, "Ignoring sample rate %d, no audio tracks\n", arate);
1510                     }
1511                     token = strtok(NULL, ",");
1512                 }
1513             }
1514             if (i < num_audio_tracks)
1515             {
1516                 /* We have fewer inputs than audio tracks, use default sample rate.
1517                  * Unless we only have one input, then use that for all tracks.
1518                  */
1519                 if (i != 1)
1520                     arate = audio->in.samplerate;
1521                 for ( ; i < num_audio_tracks; i++)
1522                 {
1523                     audio = hb_list_audio_config_item(job->list_audio, i);
1524                     audio->out.samplerate = arate;
1525                 }
1526             }
1527             /* Sample Rate */
1528
1529             /* Audio Bitrate */
1530             i = 0;
1531             if( abitrates )
1532             {
1533                 char * token = strtok(abitrates, ",");
1534                 if (token == NULL)
1535                     token = abitrates;
1536                 while ( token != NULL )
1537                 {
1538                     abitrate = atoi(token);
1539                     audio = hb_list_audio_config_item(job->list_audio, i);
1540
1541                     if( audio != NULL )
1542                     {
1543                         audio->out.bitrate = abitrate;
1544                         if( (++i) >= num_audio_tracks )
1545                             break;  /* We have more inputs than audio tracks, oops */
1546                     }
1547                     else 
1548                     {
1549                         fprintf(stderr, "Ignoring bitrate %d, no audio tracks\n", abitrate);
1550                     }
1551                     token = strtok(NULL, ",");
1552                 }
1553             }
1554             if (i < num_audio_tracks)
1555             {
1556                 /* We have fewer inputs than audio tracks, use the default bitrate
1557                  * for the remaining tracks. Unless we only have one input, then use
1558                  * that for all tracks.
1559                  */
1560                 if (i != 1)
1561                     abitrate = default_abitrate;
1562                 for (; i < num_audio_tracks; i++)
1563                 {
1564                     audio = hb_list_audio_config_item(job->list_audio, i);
1565                     audio->out.bitrate = abitrate;
1566                 }
1567             }
1568             /* Audio Bitrate */
1569
1570             /* Audio DRC */
1571             i = 0;
1572             if ( dynamic_range_compression )
1573             {
1574                 char * token = strtok(dynamic_range_compression, ",");
1575                 if (token == NULL)
1576                     token = dynamic_range_compression;
1577                 while ( token != NULL )
1578                 {
1579                     d_r_c = atof(token);
1580                     audio = hb_list_audio_config_item(job->list_audio, i);
1581                     if( audio != NULL )
1582                     {
1583                         audio->out.dynamic_range_compression = d_r_c;
1584                         if( (++i) >= num_audio_tracks )
1585                             break;  /* We have more inputs than audio tracks, oops */
1586                     } 
1587                     else
1588                     {
1589                         fprintf(stderr, "Ignoring drc, no audio tracks\n");
1590                     }
1591                     token = strtok(NULL, ",");
1592                 }
1593             }
1594             if (i < num_audio_tracks)
1595             {
1596                 /* We have fewer inputs than audio tracks, use no DRC for the remaining
1597                  * tracks. Unless we only have one input, then use the same DRC for all
1598                  * tracks.
1599                  */
1600                 if (i != 1)
1601                     d_r_c = 0;
1602                 for (; i < num_audio_tracks; i++)
1603                 {
1604                     audio = hb_list_audio_config_item(job->list_audio, i);
1605                     audio->out.dynamic_range_compression = d_r_c;
1606                 }
1607             }
1608             /* Audio DRC */
1609
1610             /* Audio Mixdown */
1611             i = 0;
1612             if ( mixdowns )
1613             {
1614                 char * token = strtok(mixdowns, ",");
1615                 if (token == NULL)
1616                     token = mixdowns;
1617                 while ( token != NULL )
1618                 {
1619                     mixdown = hb_mixdown_get_mixdown_from_short_name(token);
1620                     audio = hb_list_audio_config_item(job->list_audio, i);
1621                     if( audio != NULL )
1622                     {
1623                         audio->out.mixdown = mixdown;
1624                         if( (++i) >= num_audio_tracks )
1625                             break;  /* We have more inputs than audio tracks, oops */
1626                     }
1627                     else
1628                     {
1629                         fprintf(stderr, "Ignoring mixdown, no audio tracks\n");
1630                     }
1631                     token = strtok(NULL, ",");
1632                 }
1633             }
1634             if (i < num_audio_tracks)
1635             {
1636                 /* We have fewer inputs than audio tracks, use DPLII for the rest. Unless
1637                  * we only have one input, then use that.
1638                  */
1639                 if (i != 1)
1640                     mixdown = HB_AMIXDOWN_DOLBYPLII;
1641                 for (; i < num_audio_tracks; i++)
1642                 {
1643                    audio = hb_list_audio_config_item(job->list_audio, i);
1644                    audio->out.mixdown = mixdown;
1645                 }
1646             }
1647             /* Audio Mixdown */
1648
1649             /* Audio Track Names */
1650             i = 0;
1651             if ( anames )
1652             {
1653                 char * token = strtok(anames, ",");
1654                 if (token == NULL)
1655                     token = anames;
1656                 while ( token != NULL )
1657                 {
1658                     audio = hb_list_audio_config_item(job->list_audio, i);
1659                     if( audio != NULL )
1660                     {
1661                         audio->out.name = strdup(token);
1662                         if( (++i) >= num_audio_tracks )
1663                             break;  /* We have more names than audio tracks, oops */
1664                     }
1665                     else
1666                     {
1667                         fprintf(stderr, "Ignoring aname '%s', no audio track\n",
1668                                 token);
1669                     }
1670                     token = strtok(NULL, ",");
1671                 }
1672             }
1673             if( i < num_audio_tracks && i == 1 )
1674             {
1675                 /* We have exactly one name and more than one audio track. Use the same
1676                  * name for all tracks. */
1677                 for ( ; i < num_audio_tracks; i++)
1678                 {
1679                     audio = hb_list_audio_config_item(job->list_audio, i);
1680                     audio->out.name = strdup(anames);
1681                 }
1682             }
1683             /* Audio Track Names */
1684
1685             if( size )
1686             {
1687                 job->vbitrate = hb_calc_bitrate( job, size );
1688                 fprintf( stderr, "Calculated bitrate: %d kbps\n",
1689                          job->vbitrate );
1690             }
1691
1692             if( subtracks )
1693             {
1694                 char * token;
1695                 int    i, pos;
1696
1697                 pos = 0;
1698                 for ( i = 0; subtracks[i] != NULL; i++ )
1699                 {
1700                     pos++;
1701                     token = subtracks[i];
1702                     if( strcasecmp(token, "scan" ) == 0 )
1703                     {
1704                         int burn = 0, force = 0, def = 0;
1705
1706                         if ( subburn != NULL )
1707                         {
1708                             burn = ( pos == 1 && subburn[0] == 0 ) ||
1709                                    ( strcmp( "scan", subburn ) == 0 );
1710                         }
1711                         if ( subdefault != NULL )
1712                         {
1713                             def =  ( pos == 1 && subdefault[0] == 0 ) ||
1714                                    ( strcmp( "scan", subdefault ) == 0 );
1715                         }
1716                         force = test_sub_list( subforce, "scan", pos );
1717
1718                         if ( !burn && mux == HB_MUX_MKV )
1719                         {
1720                             job->select_subtitle_config.dest = PASSTHRUSUB;
1721                         }
1722                         else if ( burn )
1723                         {
1724                             if ( sub_burned )
1725                             {
1726                                 continue;
1727                             }
1728                             sub_burned = 1;
1729                         }
1730                         if ( !( !burn && mux == HB_MUX_MP4 ) )
1731                         {
1732                             job->select_subtitle_config.force = force;
1733                             job->select_subtitle_config.default_track = def;
1734                             subtitle_scan = 1;
1735                         } else {
1736                             fprintf( stderr, "Warning: Subtitle Scan for MP4 requires the '--subtitle-burn' option to be selected\n");
1737                         }
1738                     }
1739                     else
1740                     {
1741                         hb_subtitle_t        * subtitle;
1742                         hb_subtitle_config_t   sub_config;
1743                         int                    track;
1744                         int                    burn = 0, force = 0, def = 0;
1745
1746                         track = atoi(token) - 1;
1747                         subtitle = hb_list_item(title->list_subtitle, track);
1748                         if( subtitle == NULL ) 
1749                         {
1750                             fprintf( stderr, "Warning: Could not find subtitle track %d, skipped\n", track+1 );
1751                             continue;
1752                         }
1753                         sub_config = subtitle->config;
1754
1755                         if ( subburn != NULL )
1756                         {
1757                             burn = ( pos == 1 && subburn[0] == 0 ) ||
1758                                    ( strcmp( token, subburn ) == 0 );
1759                         }
1760                         if ( subdefault != NULL )
1761                         {
1762                             def =  ( pos == 1 && subdefault[0] == 0 ) ||
1763                                    ( strcmp( token, subdefault ) == 0 );
1764                         }
1765
1766                         force = test_sub_list(subforce, token, pos);
1767
1768                         if ( !burn && mux == HB_MUX_MKV && 
1769                              subtitle->format == PICTURESUB)
1770                         {
1771                             sub_config.dest = PASSTHRUSUB;
1772                         }
1773                         else if (!burn && mux == HB_MUX_MP4 &&
1774                              subtitle->format == PICTURESUB)
1775                         {
1776                             // Skip any non-burned vobsubs when output is mp4
1777                             fprintf( stderr, "Warning: Skipping subtitle track %d, can't pass-through VOBSUBs in an MP4 container,\nadd '--subtitle-burn %d' to the command line\n", track+1, track+1 );
1778                             continue;
1779                         }
1780                         else if ( burn && subtitle->format == PICTURESUB )
1781                         {
1782                             // Only allow one subtitle to be burned into video
1783                             if ( sub_burned )
1784                             {
1785                                 fprintf( stderr, "Warning: Skipping subtitle track %d, can't have more than one track burnt in\n", track+1 );
1786                                 continue;
1787                             }
1788                             sub_burned = 1;
1789                         }
1790                         sub_config.force = force;
1791                         sub_config.default_track = def;
1792                         hb_subtitle_add( job, &sub_config, track );
1793                     }
1794                 }
1795             }
1796
1797             if( srtfile )
1798             {
1799                 char * token;
1800                 int i, pos;
1801                 hb_subtitle_config_t sub_config;
1802
1803                 pos = 0;
1804                 for( i=0; srtfile[i] != NULL; i++ )
1805                 {
1806                     char *codeset = "L1";
1807                     int64_t offset = 0;
1808                     char *lang = "und";
1809
1810                     pos++;
1811                     token = srtfile[i];
1812                     if( srtcodeset && srtcodeset[i] )
1813                     {
1814                         codeset = srtcodeset[i];
1815                     }
1816                     if( srtoffset && srtoffset[i] )
1817                     {
1818                         offset = strtoll( srtoffset[i], &srtoffset[i], 0 );
1819                     }
1820                     if ( srtlang && srtlang[i] )
1821                     {
1822                         lang = srtlang[i];
1823                     }
1824                     sub_config.force = 0;
1825                     sub_config.default_track = 0;
1826                     strncpy( sub_config.src_filename, srtfile[i], 128);
1827                     strncpy( sub_config.src_codeset, codeset, 40);
1828                     sub_config.offset = offset;
1829
1830                     hb_srt_add( job, &sub_config, lang);
1831                 }
1832             }
1833
1834             if( native_language )
1835             {
1836                 char audio_lang[4];
1837                 
1838                 audio = hb_list_audio_config_item(job->list_audio, 0);
1839                 
1840                 if( audio ) 
1841                 {
1842                     strncpy( audio_lang, audio->lang.iso639_2, sizeof( audio_lang ) );
1843                     
1844                     if( strncasecmp( native_language, audio_lang, 
1845                                      sizeof( audio_lang ) ) != 0 )
1846                     {
1847                         /*
1848                          * Audio language is not the same as our native language. 
1849                          * If we have any subtitles in our native language they
1850                          * should be selected here if they haven't already been.
1851                          */
1852                         hb_subtitle_t *subtitle, *subtitle2 = NULL;
1853                         int matched_track = 0;
1854
1855                         for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1856                         {
1857                             subtitle = hb_list_item( title->list_subtitle, i );
1858                             matched_track = i;
1859                             if( strcmp( subtitle->iso639_2, native_language ) == 0 )
1860                             {  
1861                                 /*
1862                                  * Found the first matching subtitle in our
1863                                  * native language. Is it already selected?
1864                                  */
1865                                 for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
1866                                 {
1867                                     subtitle2 =  hb_list_item( job->list_subtitle, i );
1868                                     
1869                                     if( subtitle2->track == subtitle->track) {
1870                                         /*
1871                                          * Already selected
1872                                          */
1873                                         break;
1874                                     }
1875                                     subtitle2 = NULL;
1876                                 }
1877                                 
1878                                 if( subtitle2 == NULL ) 
1879                                 {
1880                                     /*
1881                                      * Not already selected, so select it.
1882                                      */
1883                                     hb_subtitle_config_t sub_config;
1884
1885                                     if( native_dub )
1886                                     {
1887                                         fprintf( stderr, "Warning: no matching audio for native language - using subtitles instead.\n");
1888                                     }
1889                                     sub_config = subtitle->config;
1890
1891                                     if( mux == HB_MUX_MKV || subtitle->format == TEXTSUB)
1892                                     {
1893                                         sub_config.dest = PASSTHRUSUB;
1894                                     }
1895
1896                                     sub_config.force = 0;
1897                                     sub_config.default_track = 1;
1898                                     hb_subtitle_add( job, &sub_config, matched_track);
1899                                 }
1900                                 /*
1901                                  * Stop searching.
1902                                  */
1903                                 break;
1904                             }
1905                         }
1906                     }
1907                 }
1908             }
1909
1910             if( job->mux )
1911             {
1912                 job->mux = mux;
1913             }
1914
1915             if ( largeFileSize )
1916             {
1917                 job->largeFileSize = 1;
1918             }
1919             if ( mp4_optimize )
1920             {
1921                 job->mp4_optimize = 1;
1922             }
1923             if ( ipod_atom )
1924             {
1925                 job->ipod_atom = 1;
1926             }
1927
1928             job->file = strdup( output );
1929
1930             if( crf )
1931             {
1932                 job->crf = 1;
1933             }
1934             
1935             if( color_matrix )
1936             {
1937                 job->color_matrix = color_matrix;
1938             }
1939
1940             if( x264opts != NULL && *x264opts != '\0' )
1941             {
1942                 job->x264opts = x264opts;
1943             }
1944             else /*avoids a bus error crash when options aren't specified*/
1945             {
1946                 job->x264opts =  NULL;
1947             }
1948             if (maxWidth)
1949                 job->maxWidth = maxWidth;
1950             if (maxHeight)
1951                 job->maxHeight = maxHeight;
1952
1953             if( start_at_preview )
1954             {
1955                 job->start_at_preview = start_at_preview - 1;
1956                 job->seek_points = preview_count;
1957             }
1958             
1959             if( stop_at_pts )
1960             {
1961                 job->pts_to_stop = stop_at_pts;
1962                 subtitle_scan = 0;
1963             }
1964             
1965             if( stop_at_frame )
1966             {
1967                 job->frame_to_stop = stop_at_frame;
1968                 subtitle_scan = 0;
1969             }
1970             
1971             if( subtitle_scan )
1972             {
1973                 char *x264opts_tmp;
1974
1975                 /*
1976                  * When subtitle scan is enabled do a fast pre-scan job
1977                  * which will determine which subtitles to enable, if any.
1978                  */
1979                 job->pass = -1;
1980
1981                 x264opts_tmp = job->x264opts;
1982
1983                 job->x264opts = NULL;
1984
1985                 job->indepth_scan = subtitle_scan;
1986                 fprintf( stderr, "Subtitle Scan Enabled - enabling "
1987                          "subtitles if found for foreign language segments\n");
1988
1989                 /*
1990                  * Add the pre-scan job
1991                  */
1992                 hb_add( h, job );
1993
1994                 job->x264opts = x264opts_tmp;
1995             }
1996
1997             if( twoPass )
1998             {
1999                 /*
2000                  * If subtitle_scan is enabled then only turn it on
2001                  * for the first pass and then off again for the
2002                  * second.
2003                  */
2004                 job->pass = 1;
2005
2006                 job->indepth_scan = 0;
2007
2008                 if (x264opts)
2009                 {
2010                     x264opts2 = strdup(x264opts);
2011                 }
2012
2013                 /*
2014                  * If turbo options have been selected then append them
2015                  * to the x264opts now (size includes one ':' and the '\0')
2016                  */
2017                 if( turbo_opts_enabled )
2018                 {
2019                     int size = (x264opts ? strlen(x264opts) : 0) + strlen(turbo_opts) + 2;
2020                     char *tmp_x264opts;
2021
2022                     tmp_x264opts = malloc(size * sizeof(char));
2023                     if( x264opts )
2024                     {
2025                         snprintf( tmp_x264opts, size, "%s:%s",
2026                                   x264opts, turbo_opts );
2027                         free( x264opts );
2028                     } else {
2029                         /*
2030                          * No x264opts to modify, but apply the turbo options
2031                          * anyway as they may be modifying defaults
2032                          */
2033                         snprintf( tmp_x264opts, size, "%s",
2034                                   turbo_opts );
2035                     }
2036                     x264opts = tmp_x264opts;
2037
2038                     fprintf( stderr, "Modified x264 options for pass 1 to append turbo options: %s\n",
2039                              x264opts );
2040
2041                     job->x264opts = x264opts;
2042                 }
2043                 hb_add( h, job );
2044
2045                 job->pass = 2;
2046                 /*
2047                  * On the second pass we turn off subtitle scan so that we
2048                  * can actually encode using any subtitles that were auto
2049                  * selected in the first pass (using the whacky select-subtitle
2050                  * attribute of the job).
2051                  */
2052                 job->indepth_scan = 0;
2053
2054                 job->x264opts = x264opts2;
2055
2056                 hb_add( h, job );
2057             }
2058             else
2059             {
2060                 /*
2061                  * Turn on subtitle scan if requested, note that this option
2062                  * precludes encoding of any actual subtitles.
2063                  */
2064
2065                 job->indepth_scan = 0;
2066                 job->pass = 0;
2067                 hb_add( h, job );
2068             }
2069             hb_start( h );
2070             break;
2071         }
2072
2073 #define p s.param.working
2074         case HB_STATE_WORKING:
2075             fprintf( stdout, "\rEncoding: task %d of %d, %.2f %%",
2076                      p.job_cur, p.job_count, 100.0 * p.progress );
2077             if( p.seconds > -1 )
2078             {
2079                 fprintf( stdout, " (%.2f fps, avg %.2f fps, ETA "
2080                          "%02dh%02dm%02ds)", p.rate_cur, p.rate_avg,
2081                          p.hours, p.minutes, p.seconds );
2082             }
2083             fflush(stdout);
2084             break;
2085 #undef p
2086
2087 #define p s.param.muxing
2088         case HB_STATE_MUXING:
2089         {
2090             if (show_mux_warning)
2091             {
2092                 fprintf( stdout, "\rMuxing: this may take awhile..." );
2093                 fflush(stdout);
2094                 show_mux_warning = 0;
2095             }
2096             break;
2097         }
2098 #undef p
2099
2100 #define p s.param.workdone
2101         case HB_STATE_WORKDONE:
2102             /* Print error if any, then exit */
2103             switch( p.error )
2104             {
2105                 case HB_ERROR_NONE:
2106                     fprintf( stderr, "\nRip done!\n" );
2107                     break;
2108                 case HB_ERROR_CANCELED:
2109                     fprintf( stderr, "\nRip canceled.\n" );
2110                     break;
2111                 default:
2112                     fprintf( stderr, "\nRip failed (error %x).\n",
2113                              p.error );
2114             }
2115             die = 1;
2116             break;
2117 #undef p
2118     }
2119     return 0;
2120 }
2121
2122 /****************************************************************************
2123  * SigHandler:
2124  ****************************************************************************/
2125 static volatile int64_t i_die_date = 0;
2126 void SigHandler( int i_signal )
2127 {
2128     if( die == 0 )
2129     {
2130         die = 1;
2131         i_die_date = hb_get_date();
2132         fprintf( stderr, "Signal %d received, terminating - do it "
2133                  "again in case it gets stuck\n", i_signal );
2134     }
2135     else if( i_die_date + 500 < hb_get_date() )
2136     {
2137         fprintf( stderr, "Dying badly, files might remain in your /tmp\n" );
2138         exit( 1 );
2139     }
2140 }
2141
2142 /****************************************************************************
2143  * ShowHelp:
2144  ****************************************************************************/
2145 static void ShowHelp()
2146 {
2147     int i;
2148     FILE* const out = stdout;
2149
2150     fprintf( out,
2151     "Syntax: HandBrakeCLI [options] -i <device> -o <file>\n"
2152     "\n"
2153     "### General Handbrake Options------------------------------------------------\n\n"
2154     "    -h, --help              Print help\n"
2155     "    -u, --update            Check for updates and exit\n"
2156     "    -v, --verbose <#>       Be verbose (optional argument: logging level)\n"
2157     "    -C, --cpu               Set CPU count (default: autodetected)\n"
2158     "    -Z. --preset <string>   Use a built-in preset. Capitalization matters, and\n"
2159     "                            if the preset name has spaces, surround it with\n"
2160     "                            double quotation marks\n"
2161     "    -z, --preset-list       See a list of available built-in presets\n"
2162     "        --dvdnav            Use dvdnav (Experimental)\n"
2163     "\n"
2164
2165     "### Source Options-----------------------------------------------------------\n\n"
2166     "    -i, --input <string>    Set input device\n"
2167     "    -t, --title <number>    Select a title to encode (0 to scan only,\n"
2168     "                            default: 1)\n"
2169     "    -L, --longest           Select the longest title\n"
2170     "    -c, --chapters <string> Select chapters (e.g. \"1-3\" for chapters\n"
2171     "                            1 to 3, or \"3\" for chapter 3 only,\n"
2172     "                            default: all chapters)\n"
2173     "        --angle <number>    Select the DVD angle\n"
2174     "        --previews <#:B>    Select how many preview images are generated (max 30),\n"
2175     "                            and whether or not they're stored to disk (0 or 1).\n"
2176     "                            (default: 10:0)\n"
2177     "    --start-at-preview <#>  Start encoding at a given preview.\n"
2178     "    --stop-at     <unit:#>  Stop encoding at a given frame, duration (in seconds),\n"
2179     "                            or pts (on a 90kHz clock)"
2180     "\n"
2181
2182     "### Destination Options------------------------------------------------------\n\n"
2183     "    -o, --output <string>   Set output file name\n"
2184     "    -f, --format <string>   Set output format (avi/mp4/ogm/mkv, default:\n"
2185     "                            autodetected from file name)\n"
2186     "    -m, --markers           Add chapter markers (mp4 and mkv output formats only)\n"
2187     "    -4, --large-file        Use 64-bit mp4 files that can hold more than\n"
2188     "                            4 GB. Note: Breaks iPod, PS3 compatibility.\n"""
2189     "    -O, --optimize          Optimize mp4 files for HTTP streaming\n"
2190     "    -I, --ipod-atom         Mark mp4 files so 5.5G iPods will accept them\n"
2191     "\n"
2192
2193
2194     "### Video Options------------------------------------------------------------\n\n"
2195     "    -e, --encoder <string>  Set video library encoder (ffmpeg,x264,theora)\n"
2196     "                            (default: ffmpeg)\n"
2197     "    -x, --x264opts <string> Specify advanced x264 options in the\n"
2198     "                            same style as mencoder:\n"
2199     "                            option1=value1:option2=value2\n"
2200     "    -q, --quality <float>   Set video quality (0.0..1.0)\n"
2201     "    -Q, --cqp               Use with -q for CQP instead of CRF\n"
2202     "    -S, --size <MB>         Set target size\n"
2203     "    -b, --vb <kb/s>         Set video bitrate (default: 1000)\n"
2204     "    -2, --two-pass          Use two-pass mode\n"
2205     "    -T, --turbo             When using 2-pass use the turbo options\n"
2206     "                            on the first pass to improve speed\n"
2207     "                            (only works with x264, affects PSNR by about 0.05dB,\n"
2208     "                            and increases first pass speed two to four times)\n"
2209     "    -r, --rate              Set video framerate (" );
2210     for( i = 0; i < hb_video_rates_count; i++ )
2211     {
2212         fprintf( out, hb_video_rates[i].string );
2213         if( i != hb_video_rates_count - 1 )
2214             fprintf( out, "/" );
2215     }
2216     fprintf( out, ")\n"
2217     "                            Be aware that not specifying a framerate lets\n"
2218     "                            HandBrake preserve a source's time stamps,\n"
2219     "                            potentially creating variable framerate video\n"
2220     "    --vfr, --cfr, --pfr     Select variable, constant or peak-limited\n"
2221     "                            frame rate control. VFR preserves the source\n"
2222     "                            timing. CFR makes the output constant rate at\n"
2223     "                            the rate given by the -r flag (or the source's\n"
2224     "                            average rate if no -r is given). PFR doesn't\n"
2225     "                            allow the rate to go over the rate specified\n"
2226     "                            with the -r flag but won't change the source\n"
2227     "                            timing if it's below that rate.\n"
2228     "                            If none of these flags are given, the default\n"
2229     "                            is --cfr when -r is given and --vfr otherwise\n"
2230
2231     "\n"
2232     "### Audio Options-----------------------------------------------------------\n\n"
2233     "    -a, --audio <string>    Select audio track(s), separated by commas\n"
2234     "                            More than one output track can be used for one\n"
2235     "                            input.\n"
2236     "                            (\"none\" for no audio, \"1,2,3\" for multiple\n"
2237     "                             tracks, default: first one)\n" );
2238
2239 #ifdef __APPLE_CC__
2240     fprintf( out,
2241     "    -E, --aencoder <string> Audio encoder(s) (ca_aac/faac/lame/vorbis/ac3/dts) \n"
2242     "                            ac3 and dts meaning passthrough\n"
2243     "                            Separated by commas for more than one audio track.\n"
2244     "                            (default: guessed)\n" );
2245 #else
2246     fprintf( out,
2247     "    -E, --aencoder <string> Audio encoder(s) (faac/lame/vorbis/ac3/dts) \n"
2248     "                            ac3 and dts meaning passthrough\n"
2249     "                            Separated by commas for more than one audio track.\n"
2250     "                            (default: guessed)\n" );
2251 #endif
2252     fprintf( out,
2253     "    -B, --ab <kb/s>         Set audio bitrate(s)  (default: 160)\n"
2254     "                            Separated by commas for more than one audio track.\n"
2255     "    -6, --mixdown <string>  Format(s) for surround sound downmixing\n"
2256     "                            Separated by commas for more than one audio track.\n"
2257     "                            (mono/stereo/dpl1/dpl2/6ch, default: dpl2)\n"
2258     "    -R, --arate             Set audio samplerate(s) (" );
2259     for( i = 0; i < hb_audio_rates_count; i++ )
2260     {
2261         fprintf( out, hb_audio_rates[i].string );
2262         if( i != hb_audio_rates_count - 1 )
2263             fprintf( out, "/" );
2264     }
2265     fprintf( out, " kHz)\n"
2266     "                            Separated by commas for more than one audio track.\n"
2267     "    -D, --drc <float>       Apply extra dynamic range compression to the audio,\n"
2268     "                            making soft sounds louder. Range is 1.0 to 4.0\n"
2269     "                            (too loud), with 1.5 - 2.5 being a useful range.\n"
2270     "                            Separated by commas for more than one audio track.\n"
2271     "    -A, --aname <string>    Audio track name(s),\n"
2272     "                            Separated by commas for more than one audio track.\n"
2273     "\n"
2274
2275     "### Picture Settings---------------------------------------------------------\n\n"
2276     "    -w, --width <number>    Set picture width\n"
2277     "    -l, --height <number>   Set picture height\n"
2278     "        --crop <T:B:L:R>    Set cropping values (default: autocrop)\n"
2279     "    -Y, --maxHeight <#>     Set maximum height\n"
2280     "    -X, --maxWidth <#>      Set maximum width\n"
2281     "    --strict-anamorphic     Store pixel aspect ratio in video stream\n"
2282     "    --loose-anamorphic      Store pixel aspect ratio with specified width\n"
2283     "    --custom-anamorphic     Store pixel aspect ratio in video stream and\n"
2284     "                            directly control all parameters.\n"
2285     "    --display-width         Set the width to scale the actual pixels to\n"
2286     "      <number>              at playback, for custom anamorphic.\n"
2287     "    --keep-display-aspect   Preserve the source's display aspect ratio\n"
2288     "                            when using custom anamorphic\n"
2289     "    --pixel-aspect          Set a custom pixel aspect for custom anamorphic\n"
2290     "      <PARX:PARY>\n"
2291     "                            (--display-width and --pixel-aspect are mutually\n"
2292     "                             exclusive and the former will override the latter)\n"
2293     "    --itu-par               Use wider, ITU pixel aspect values for loose and\n"
2294     "                            custom anamorphic, useful with underscanned sources\n"
2295     "    --modulus               Set the number you want the scaled pixel dimensions\n"
2296     "      <number>              to divide cleanly by, for loose and custom\n"
2297     "                            anamorphic modes (default: 16)\n"
2298     "    -M  --color-matrix      Set the color space signaled by the output\n"
2299     "          <601 or 709>      (Bt.601 is mostly for SD content, Bt.709 for HD,\n"
2300     "                             default: set by resolution)\n"
2301     "\n"
2302
2303     "### Filters---------------------------------------------------------\n\n"
2304
2305      "    -d, --deinterlace       Deinterlace video with yadif/mcdeint filter\n"
2306      "          <YM:FD:MM:QP>     (default 0:-1:-1:1)\n"
2307      "           or\n"
2308      "          <fast/slow/slower>\n"
2309      "    -5, --decomb            Selectively deinterlaces when it detects combing\n"
2310      "          <MO:ME:MT:ST:BT:BX:BY>     (default: 1:2:6:9:80:16:16)\n"
2311      "    -9, --detelecine        Detelecine (ivtc) video with pullup filter\n"
2312      "                            Note: this filter drops duplicate frames to\n"
2313      "                            restore the pre-telecine framerate, unless you\n"
2314      "                            specify a constant framerate (--rate 29.97)\n"
2315      "          <L:R:T:B:SB:MP>   (default 1:1:4:4:0:0)\n"
2316      "    -8, --denoise           Denoise video with hqdn3d filter\n"
2317      "          <SL:SC:TL:TC>     (default 4:3:6:4.5)\n"
2318      "           or\n"
2319      "          <weak/medium/strong>\n"
2320      "    -7, --deblock           Deblock video with pp7 filter\n"
2321      "          <QP:M>            (default 5:2)\n"
2322     "    -g, --grayscale         Grayscale encoding\n"
2323     "\n"
2324
2325     "### Subtitle Options------------------------------------------------------------\n\n"
2326     "    -s, --subtitle <string> Select subtitle track(s), separated by commas\n"
2327     "                            More than one output track can be used for one\n"
2328     "                            input.\n"
2329     "                            (\"1,2,3\" for multiple tracks.\n"
2330     "                            A special track name \"scan\" adds an extra 1st pass.\n"
2331     "                            This extra pass scans subtitles matching the\n"
2332     "                            language of the first audio or the language \n"
2333     "                            selected by --native-language.\n"
2334     "                            The one that's only used 10 percent of the time\n"
2335     "                            or less is selected. This should locate subtitles\n"
2336     "                            for short foreign language segments. Best used in\n"
2337     "                            conjunction with --subtitle-forced.\n"
2338     "    -F, --subtitle-forced   Only display subtitles from the selected stream if\n"
2339     "          <string>          the subtitle has the forced flag set. May be used in\n"
2340     "                            conjunction with \"scan\" track to auto-select\n"
2341     "                            a stream if it contains forced subtitles.\n"
2342     "                            Separated by commas for more than one audio track.\n"
2343     "                            (\"1,2,3\" for multiple tracks.\n"
2344     "                            If \"string\" is omitted, the first trac is forced.\n"
2345     "        --subtitle-burn     \"Burn\" the selected subtitle into the video track\n"
2346     "          <number>          If \"number\" is omitted, the first trac is burned.\n"
2347     "        --subtitle-default  Flag the selected subtitle as the default subtitle\n"
2348     "          <number>          to be displayed upon playback.  Settings no default\n"
2349     "                            means no subtitle will be automatically displayed\n"
2350     "                            If \"number\" is omitted, the first trac is default.\n"
2351     "    -N, --native-language   Specifiy the your language preference. When the first\n"
2352     "          <string>          audio track does not match your native language then\n"
2353     "                            select the first subtitle that does. When used in\n"
2354     "                            conjunction with --native-dub the audio track is\n"
2355     "                            changed in preference to subtitles. Provide the\n"
2356     "                            language's iso639-2 code (fre, eng, spa, dut, et cetera)\n"
2357     "        --native-dub        Used in conjunction with --native-language\n"
2358     "                            requests that if no audio tracks are selected the\n"
2359     "                            default selected audio track will be the first one\n"
2360     "                            that matches the --native-language. If there are no\n"
2361     "                            matching audio tracks then the first matching\n"
2362     "                            subtitle track is used instead.\n"
2363     "        --srt-file <string> SubRip SRT filename(s), separated by commas.\n"
2364     "        --srt-codeset       Character codeset(s) that the SRT file(s) are\n"
2365     "          <string>          encoded in, separted by commas.\n"
2366     "                            Use 'iconv -l' for a list of valid\n"
2367     "                            codesets. If not specified latin1 is assumed\n"
2368     "        --srt-offset        Offset in milli-seconds to apply to the SRT file(s)\n"
2369     "          <string>          separted by commas. If not specified zero is assumed.\n"
2370     "                            Offsets may be negative.\n"
2371     "        --srt-lang <string> Language as an iso639-2 code fra, eng, spa et cetera)\n"
2372     "                            for the SRT file(s) separated by commas. If not specified\n"
2373     "                            then 'und' is used.\n"
2374     "\n"
2375
2376
2377     );
2378 }
2379
2380 /****************************************************************************
2381  * ShowPresets:
2382  ****************************************************************************/
2383 static void ShowPresets()
2384 {
2385     printf("\n< Apple\n");
2386
2387     printf("\n   + Universal:  -e x264  -q 20.0 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 -X 720 --loose-anamorphic -m -x cabac=0:ref=2:mixed-refs=1:me=umh\n");
2388
2389     printf("\n   + iPod:  -e x264  -b 700 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4 -I -X 320 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1\n");
2390
2391     printf("\n   + iPhone & iPod Touch:  -e x264  -q 20.0 -a 1 -E faac -B 128 -6 dpl2 -R 48 -D 0.0 -f mp4 -X 480 -m -x cabac=0:ref=2:mixed-refs:me=umh\n");
2392
2393     printf("\n   + AppleTV:  -e x264  -q 20.0 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 -4 -X 960 --loose-anamorphic -m -x cabac=0:ref=2:mixed-refs=1:bframes=3:me=umh:subme=7:b-adapt=2:8x8dct=1\n");
2394
2395     printf("\n>\n");
2396
2397     printf("\n< Regular\n");
2398
2399     printf("\n   + Normal:  -e x264  -q 20.0 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4 --strict-anamorphic -m -x ref=2:bframes=2:me=umh\n");
2400
2401     printf("\n   + High Profile:  -e x264  -q 20.0 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 --detelecine --decomb --loose-anamorphic -m -x ref=3:mixed-refs:bframes=3:weightb:b-pyramid:b-adapt=2:me=umh:subme=9:analyse=all:8x8dct\n");
2402
2403     printf("\n>\n");
2404
2405     printf("\n< Legacy\n");
2406
2407     printf("\n   + Classic:  -b 1000 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4\n");
2408
2409     printf("\n   + AppleTV Legacy:  -e x264  -b 2500 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 -4 --strict-anamorphic -m -x bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:cabac=0\n");
2410
2411     printf("\n   + iPhone Legacy:  -e x264  -b 960 -a 1 -E faac -B 128 -6 dpl2 -R 48 -D 0.0 -f mp4 -I -X 480 -m -x level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0\n");
2412
2413     printf("\n   + iPod Legacy:  -e x264  -b 1500 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4 -I -X 640 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0\n");
2414
2415     printf("\n>\n");
2416 }
2417
2418 static char** str_split( char *str, char *delem )
2419 {
2420     char *  token;
2421     char *  copy_str;
2422     char *  pos;
2423     char ** ret;
2424     int     count, i;
2425
2426     if ( str == NULL || delem == NULL || str[0] == 0 )
2427     {
2428         ret = malloc( sizeof(char*) );
2429         *ret = NULL;
2430         return ret;
2431     }
2432
2433     // Find number of elements in the string
2434     count = 1;
2435     pos = str;
2436     while ( ( pos = strstr( pos+1, delem ) ) != NULL )
2437     {
2438         if ( *(pos+1) != 0 )
2439             count++;
2440     }
2441     ret = calloc( ( count + 1 ), sizeof(char*) );
2442
2443     copy_str = strdup( str );
2444     token = strtok( copy_str, delem );
2445
2446     i = 0;
2447     while( token != NULL && i < count )
2448     {
2449         ret[i] = strdup( token );
2450         token = strtok(NULL, ",");
2451         i++;
2452     }
2453     free( copy_str );
2454     return ret;
2455 }
2456
2457 /****************************************************************************
2458  * ParseOptions:
2459  ****************************************************************************/
2460 static int ParseOptions( int argc, char ** argv )
2461 {
2462     
2463     #define PREVIEWS            257
2464     #define START_AT_PREVIEW    258
2465     #define STOP_AT             259
2466     #define ANGLE               260
2467     #define DVDNAV              261
2468     #define DISPLAY_WIDTH       262
2469     #define PIXEL_ASPECT        263
2470     #define MODULUS             264
2471     #define KEEP_DISPLAY_ASPECT 265
2472     #define SUB_BURNED          266
2473     #define SUB_DEFAULT         267
2474     #define NATIVE_DUB          268
2475     #define SRT_FILE            269
2476     #define SRT_CODESET         270
2477     #define SRT_OFFSET          271
2478     #define SRT_LANG            272
2479     
2480     for( ;; )
2481     {
2482         static struct option long_options[] =
2483           {
2484             { "help",        no_argument,       NULL,    'h' },
2485             { "update",      no_argument,       NULL,    'u' },
2486             { "verbose",     optional_argument, NULL,    'v' },
2487             { "cpu",         required_argument, NULL,    'C' },
2488             { "dvdnav",      no_argument,       NULL,    DVDNAV },
2489
2490             { "format",      required_argument, NULL,    'f' },
2491             { "input",       required_argument, NULL,    'i' },
2492             { "output",      required_argument, NULL,    'o' },
2493             { "large-file",  no_argument,       NULL,    '4' },
2494             { "optimize",    no_argument,       NULL,    'O' },
2495             { "ipod-atom",   no_argument,       NULL,    'I' },
2496
2497             { "title",       required_argument, NULL,    't' },
2498             { "longest",     no_argument,       NULL,    'L' },
2499             { "chapters",    required_argument, NULL,    'c' },
2500             { "angle",       required_argument, NULL,    ANGLE },
2501             { "markers",     optional_argument, NULL,    'm' },
2502             { "audio",       required_argument, NULL,    'a' },
2503             { "mixdown",     required_argument, NULL,    '6' },
2504             { "drc",         required_argument, NULL,    'D' },
2505             { "subtitle",    required_argument, NULL,    's' },
2506             { "subtitle-forced", optional_argument,   NULL,    'F' },
2507             { "subtitle-burned", optional_argument,   NULL,    SUB_BURNED },
2508             { "subtitle-default", optional_argument,   NULL,    SUB_DEFAULT },
2509             { "srt-file",    required_argument, NULL, SRT_FILE },
2510             { "srt-codeset", required_argument, NULL, SRT_CODESET },
2511             { "srt-offset",  required_argument, NULL, SRT_OFFSET },
2512             { "srt-lang",    required_argument, NULL, SRT_LANG },
2513             { "native-language", required_argument, NULL,'N' },
2514             { "native-dub",  no_argument,       NULL,    NATIVE_DUB },
2515             { "encoder",     required_argument, NULL,    'e' },
2516             { "aencoder",    required_argument, NULL,    'E' },
2517             { "two-pass",    no_argument,       NULL,    '2' },
2518             { "deinterlace", optional_argument, NULL,    'd' },
2519             { "deblock",     optional_argument, NULL,    '7' },
2520             { "denoise",     optional_argument, NULL,    '8' },
2521             { "detelecine",  optional_argument, NULL,    '9' },
2522             { "decomb",      optional_argument, NULL,    '5' },
2523             { "grayscale",   no_argument,       NULL,    'g' },
2524             { "strict-anamorphic",  no_argument, &anamorphic_mode, 1 },
2525             { "loose-anamorphic", no_argument, &anamorphic_mode, 2 },
2526             { "custom-anamorphic", no_argument, &anamorphic_mode, 3 },
2527             { "display-width", required_argument, NULL, DISPLAY_WIDTH },
2528             { "keep-display-aspect", no_argument, &keep_display_aspect, 1 },
2529             { "pixel-aspect", required_argument, NULL, PIXEL_ASPECT },
2530             { "modulus",     required_argument, NULL, MODULUS },
2531             { "itu-par",     no_argument,       &itu_par, 1  },
2532             { "width",       required_argument, NULL,    'w' },
2533             { "height",      required_argument, NULL,    'l' },
2534             { "crop",        required_argument, NULL,    'n' },
2535
2536             { "vb",          required_argument, NULL,    'b' },
2537             { "quality",     required_argument, NULL,    'q' },
2538             { "size",        required_argument, NULL,    'S' },
2539             { "ab",          required_argument, NULL,    'B' },
2540             { "rate",        required_argument, NULL,    'r' },
2541             { "arate",       required_argument, NULL,    'R' },
2542             { "cqp",         no_argument,       NULL,    'Q' },
2543             { "x264opts",    required_argument, NULL,    'x' },
2544             { "turbo",       no_argument,       NULL,    'T' },
2545             { "maxHeight",   required_argument, NULL,    'Y' },
2546             { "maxWidth",    required_argument, NULL,    'X' },
2547             { "preset",      required_argument, NULL,    'Z' },
2548             { "preset-list", no_argument,       NULL,    'z' },
2549
2550             { "aname",       required_argument, NULL,    'A' },
2551             { "color-matrix",required_argument, NULL,    'M' },
2552             { "previews",    required_argument, NULL,    PREVIEWS },
2553             { "start-at-preview", required_argument, NULL, START_AT_PREVIEW },
2554             { "stop-at",    required_argument, NULL,     STOP_AT },
2555             { "vfr",         no_argument,       &cfr,    0 },
2556             { "cfr",         no_argument,       &cfr,    1 },
2557             { "pfr",         no_argument,       &cfr,    2 },
2558             { 0, 0, 0, 0 }
2559           };
2560
2561         int option_index = 0;
2562         int c;
2563
2564                 c = getopt_long( argc, argv,
2565                                                  "hv::uC:f:4i:Io:t:Lc:m::M:a:A:6:s:UFN:e:E:2dD:7895gOw:l:n:b:q:S:B:r:R:Qx:TY:X:Z:z",
2566                          long_options, &option_index );
2567         if( c < 0 )
2568         {
2569             break;
2570         }
2571
2572         switch( c )
2573         {
2574             case 0:
2575                 /* option was handled entirely in getopt_long */
2576                 break;
2577             case 'h':
2578                 ShowHelp();
2579                 exit( 0 );
2580             case 'u':
2581                 update = 1;
2582                 break;
2583             case 'v':
2584                 if( optarg != NULL )
2585                 {
2586                     debug = atoi( optarg );
2587                 }
2588                 else
2589                 {
2590                     debug = 1;
2591                 }
2592                 break;
2593             case 'C':
2594                 cpu = atoi( optarg );
2595                 break;
2596
2597             case 'Z':
2598                 preset = 1;
2599                 preset_name = strdup(optarg);
2600                 break;
2601             case 'z':
2602                 ShowPresets();
2603                 exit ( 0 );
2604             case DVDNAV:
2605                 dvdnav = 1;
2606                 break;
2607
2608             case 'f':
2609                 format = strdup( optarg );
2610                 break;
2611             case 'i':
2612                 input = strdup( optarg );
2613 #ifdef __APPLE_CC__
2614                 char *devName = bsd_name_for_path( input ); // alloc
2615                 if( devName )
2616                 {
2617                     if( device_is_dvd( devName ))
2618                     {
2619                         free( input );
2620                         input = malloc( strlen( "/dev/" ) + strlen( devName ) + 1 );
2621                         sprintf( input, "/dev/%s", devName );
2622                     }
2623                     free( devName );
2624                 }
2625 #endif
2626                 break;
2627             case 'o':
2628                 output = strdup( optarg );
2629                 break;
2630             case '4':
2631                 largeFileSize = 1;
2632                 break;
2633             case 'O':
2634                 mp4_optimize = 1;
2635                 break;
2636             case 'I':
2637                 ipod_atom = 1;
2638                 break;
2639
2640             case 't':
2641                 titleindex = atoi( optarg );
2642                 break;
2643             case 'L':
2644                 longest_title = 1;
2645                 break;
2646             case 'c':
2647             {
2648                 int start, end;
2649                 if( sscanf( optarg, "%d-%d", &start, &end ) == 2 )
2650                 {
2651                     chapter_start = start;
2652                     chapter_end   = end;
2653                 }
2654                 else if( sscanf( optarg, "%d", &start ) == 1 )
2655                 {
2656                     chapter_start = start;
2657                     chapter_end   = chapter_start;
2658                 }
2659                 else
2660                 {
2661                     fprintf( stderr, "chapters: invalid syntax (%s)\n",
2662                              optarg );
2663                     return -1;
2664                 }
2665                 break;
2666             }
2667             case ANGLE:
2668                 angle = atoi( optarg );
2669                 break;
2670             case 'm':
2671                 if( optarg != NULL )
2672                 {
2673                     marker_file = strdup( optarg );
2674                 }
2675                 chapter_markers = 1;
2676                 break;
2677             case 'a':
2678                 if( optarg != NULL )
2679                 {
2680                     atracks = strdup( optarg );
2681                     audio_explicit = 1;
2682                 }
2683                 else
2684                 {
2685                     atracks = "1" ;
2686                 }
2687                 break;
2688             case '6':
2689                 if( optarg != NULL )
2690                 {
2691                     mixdowns = strdup( optarg );
2692                 }
2693                 break;
2694             case 'D':
2695                 if( optarg != NULL )
2696                 {
2697                     dynamic_range_compression = strdup( optarg );
2698                 }
2699                 break;
2700             case 's':
2701                 subtracks = str_split( optarg, "," );
2702                 break;
2703             case 'F':
2704                 subforce = str_split( optarg, "," );
2705                 break;
2706             case SUB_BURNED:
2707                 if( optarg != NULL )
2708                 {
2709                     subburn = strdup( optarg );
2710                 }
2711                 else
2712                 {
2713                     subburn = "" ;
2714                 }
2715                 break;
2716             case SUB_DEFAULT:
2717                 if( optarg != NULL )
2718                 {
2719                     subdefault = strdup( optarg );
2720                 }
2721                 else
2722                 {
2723                     subdefault = "" ;
2724                 }
2725                 break;
2726             case 'N':
2727                 native_language = strdup( optarg );
2728                 break;
2729             case NATIVE_DUB:
2730                 native_dub = 1;
2731                 break;
2732             case SRT_FILE:
2733                 srtfile = str_split( optarg, "," );
2734                 break;
2735             case SRT_CODESET:
2736                 srtcodeset = str_split( optarg, "," );
2737                 break;
2738             case SRT_OFFSET:
2739                 srtoffset = str_split( optarg, "," );
2740                 break;
2741             case SRT_LANG:
2742                 srtlang = str_split( optarg, "," );
2743                 break;
2744             case '2':
2745                 twoPass = 1;
2746                 break;
2747             case 'd':
2748                 if( optarg != NULL )
2749                 {
2750                     if (!( strcmp( optarg, "fast" ) ))
2751                     {
2752                         deinterlace_opt = "-1";
2753                     }
2754                     else if (!( strcmp( optarg, "slow" ) ))
2755                     {
2756                         deinterlace_opt = "2";
2757                     }
2758                     else if (!( strcmp( optarg, "slower" ) ))
2759                     {
2760                         deinterlace_opt = "0";
2761                     }
2762                     else
2763                     {
2764                         deinterlace_opt = strdup( optarg );
2765                     }
2766                 }
2767                 deinterlace = 1;
2768                 break;
2769             case '7':
2770                 if( optarg != NULL )
2771                 {
2772                     deblock_opt = strdup( optarg );
2773                 }
2774                 deblock = 1;
2775                 break;
2776             case '8':
2777                 if( optarg != NULL )
2778                 {
2779                     if (!( strcmp( optarg, "weak" ) ))
2780                     {
2781                         denoise_opt = "2:1:2:3";
2782                     }
2783                     else if (!( strcmp( optarg, "medium" ) ))
2784                     {
2785                         denoise_opt = "3:2:2:3";
2786                     }
2787                     else if (!( strcmp( optarg, "strong" ) ))
2788                     {
2789                         denoise_opt = "7:7:5:5";
2790                     }
2791                     else
2792                     {
2793                         denoise_opt = strdup( optarg );
2794                     }
2795                 }
2796                 denoise = 1;
2797                 break;
2798             case '9':
2799                 if( optarg != NULL )
2800                 {
2801                     detelecine_opt = strdup( optarg );
2802                 }
2803                 detelecine = 1;
2804                 break;
2805             case '5':
2806                 if( optarg != NULL )
2807                 {
2808                     decomb_opt = strdup( optarg );
2809                 }
2810                 decomb = 1;
2811                 break;
2812             case 'g':
2813                 grayscale = 1;
2814                 break;
2815             case DISPLAY_WIDTH:
2816                 if( optarg != NULL )
2817                 {
2818                     sscanf( optarg, "%i", &display_width );
2819                 }
2820                 break;
2821             case PIXEL_ASPECT:
2822                 if( optarg != NULL )
2823                 {
2824                     sscanf( optarg, "%i:%i", &par_width, &par_height );
2825                 }
2826                 break;
2827             case MODULUS:
2828                 if( optarg != NULL )
2829                 {
2830                     sscanf( optarg, "%i", &modulus );
2831                 }
2832                 break;
2833             case 'e':
2834                 if( !strcasecmp( optarg, "ffmpeg" ) )
2835                 {
2836                     vcodec = HB_VCODEC_FFMPEG;
2837                 }
2838                 else if( !strcasecmp( optarg, "x264" ) )
2839                 {
2840                     vcodec = HB_VCODEC_X264;
2841                 }
2842                 else if( !strcasecmp( optarg, "x264b13" ) )
2843                 {
2844                     vcodec = HB_VCODEC_X264;
2845                     h264_13 = 1;
2846                 }
2847                 else if( !strcasecmp( optarg, "x264b30" ) )
2848                 {
2849                     vcodec = HB_VCODEC_X264;
2850                     h264_30 = 1;
2851                 }
2852                 else if( !strcasecmp( optarg, "theora" ) )
2853                 {
2854                     vcodec = HB_VCODEC_THEORA;
2855                 }
2856                 else
2857                 {
2858                     fprintf( stderr, "invalid codec (%s)\n", optarg );
2859                     return -1;
2860                 }
2861                 break;
2862             case 'E':
2863                 if( optarg != NULL )
2864                 {
2865                     acodecs = strdup( optarg );
2866                 }
2867                 break;
2868             case 'w':
2869                 width = atoi( optarg );
2870                 break;
2871             case 'l':
2872                 height = atoi( optarg );
2873                 break;
2874             case 'n':
2875             {
2876                 int    i;
2877                 char * tmp = optarg;
2878                 for( i = 0; i < 4; i++ )
2879                 {
2880                     if( !*tmp )
2881                         break;
2882                     crop[i] = strtol( tmp, &tmp, 0 );
2883                     tmp++;
2884                 }
2885                 break;
2886             }
2887             case 'r':
2888             {
2889                 int i;
2890                 vrate = 0;
2891                 for( i = 0; i < hb_video_rates_count; i++ )
2892                 {
2893                     if( !strcmp( optarg, hb_video_rates[i].string ) )
2894                     {
2895                         vrate = hb_video_rates[i].rate;
2896                         break;
2897                     }
2898                 }
2899                 if( !vrate )
2900                 {
2901                     fprintf( stderr, "invalid framerate %s\n", optarg );
2902                 }
2903                 else if ( cfr == 0 )
2904                 {
2905                     cfr = 1;
2906                 }
2907                 break;
2908             }
2909             case 'R':
2910                 if( optarg != NULL )
2911                 {
2912                     arates = strdup( optarg );
2913                 }
2914                 break;
2915             case 'b':
2916                 vbitrate = atoi( optarg );
2917                 break;
2918             case 'q':
2919                 vquality = atof( optarg );
2920                 break;
2921             case 'S':
2922                 size = atoi( optarg );
2923                 break;
2924             case 'B':
2925                 if( optarg != NULL )
2926                 {
2927                     abitrates = strdup( optarg );
2928                 }
2929                 break;
2930             case 'Q':
2931                 crf = 0;
2932                 break;
2933             case 'x':
2934                 x264opts = strdup( optarg );
2935                 break;
2936             case 'T':
2937                 turbo_opts_enabled = 1;
2938                 break;
2939             case 'Y':
2940                 maxHeight = atoi( optarg );
2941                 break;
2942             case 'X':
2943                 maxWidth = atoi (optarg );
2944                 break;
2945             case 'A':
2946                 if( optarg != NULL )
2947                 {
2948                     anames = strdup( optarg );
2949                 }
2950                 break;
2951             case PREVIEWS:
2952                 sscanf( optarg, "%i:%i", &preview_count, &store_previews );
2953                 break;
2954             case START_AT_PREVIEW:
2955                 start_at_preview = atoi( optarg );
2956                 break;
2957             case STOP_AT:
2958                 stop_at_string = strdup( optarg );
2959                 stop_at_token = strtok( stop_at_string, ":");
2960                 if( !strcmp( stop_at_token, "frame" ) )
2961                 {
2962                     stop_at_token = strtok( NULL, ":");
2963                     stop_at_frame = atoi(stop_at_token);
2964                 }
2965                 else if( !strcmp( stop_at_token, "pts" ) )
2966                 {
2967                     stop_at_token = strtok( NULL, ":");
2968                     sscanf( stop_at_token, "%"SCNd64, &stop_at_pts );
2969                 }
2970                 else if( !strcmp( stop_at_token, "duration" ) )
2971                 {
2972                     stop_at_token = strtok( NULL, ":");
2973                     sscanf( stop_at_token, "%"SCNd64, &stop_at_pts );
2974                     stop_at_pts *= 90000LL;
2975                 }
2976                 break;
2977             case 'M':
2978                 if( atoi( optarg ) == 601 )
2979                     color_matrix = 1;
2980                 else if( atoi( optarg ) == 709 )
2981                     color_matrix = 2;
2982                 break;
2983             default:
2984                 fprintf( stderr, "unknown option (%s)\n", argv[optind] );
2985                 return -1;
2986         }
2987     }
2988
2989     return 0;
2990 }
2991
2992 static int CheckOptions( int argc, char ** argv )
2993 {
2994     if( update )
2995     {
2996         return 0;
2997     }
2998
2999     if( input == NULL || *input == '\0' )
3000     {
3001         fprintf( stderr, "Missing input device. Run %s --help for "
3002                  "syntax.\n", argv[0] );
3003         return 1;
3004     }
3005
3006     /* Parse format */
3007     if( titleindex > 0 )
3008     {
3009         if( output == NULL || *output == '\0' )
3010         {
3011             fprintf( stderr, "Missing output file name. Run %s --help "
3012                      "for syntax.\n", argv[0] );
3013             return 1;
3014         }
3015
3016         if( !format )
3017         {
3018             char * p = strrchr( output, '.' );
3019
3020             /* autodetect */
3021             if( p && !strcasecmp( p, ".avi" ) )
3022             {
3023                 mux = HB_MUX_AVI;
3024                 default_acodec = HB_ACODEC_LAME;
3025             }
3026             else if( p && ( !strcasecmp( p, ".mp4" )  ||
3027                             !strcasecmp( p, ".m4v" ) ) )
3028             {
3029                 if ( h264_30 == 1 )
3030                     mux = HB_MUX_IPOD;
3031                 else
3032                     mux = HB_MUX_MP4;
3033                 default_acodec = HB_ACODEC_FAAC;
3034             }
3035             else if( p && ( !strcasecmp( p, ".ogm" ) ||
3036                             !strcasecmp( p, ".ogg" ) ) )
3037             {
3038                 mux = HB_MUX_OGM;
3039                 default_acodec = HB_ACODEC_VORBIS;
3040             }
3041             else if( p && !strcasecmp(p, ".mkv" ) )
3042             {
3043                 mux = HB_MUX_MKV;
3044                 default_acodec = HB_ACODEC_AC3;
3045             }
3046             else
3047             {
3048                 fprintf( stderr, "Output format couldn't be guessed "
3049                          "from file name, using default.\n" );
3050                 return 0;
3051             }
3052         }
3053         else if( !strcasecmp( format, "avi" ) )
3054         {
3055             mux = HB_MUX_AVI;
3056             default_acodec = HB_ACODEC_LAME;
3057         }
3058         else if( !strcasecmp( format, "mp4" ) ||
3059                  !strcasecmp( format, "m4v" ) )
3060         {
3061             if ( h264_30 == 1)
3062                 mux = HB_MUX_IPOD;
3063             else
3064                 mux = HB_MUX_MP4;
3065             default_acodec = HB_ACODEC_FAAC;
3066         }
3067         else if( !strcasecmp( format, "ogm" ) ||
3068                  !strcasecmp( format, "ogg" ) )
3069         {
3070             mux = HB_MUX_OGM;
3071             default_acodec = HB_ACODEC_VORBIS;
3072         }
3073         else if( !strcasecmp( format, "mkv" ) )
3074         {
3075             mux = HB_MUX_MKV;
3076             default_acodec = HB_ACODEC_AC3;
3077         }
3078         else
3079         {
3080             fprintf( stderr, "Invalid output format (%s). Possible "
3081                      "choices are avi, mp4, m4v, ogm, ogg and mkv\n.", format );
3082             return 1;
3083         }
3084     }
3085
3086     return 0;
3087 }
3088
3089 static int get_acodec_for_string( char *codec )
3090 {
3091     if( !strcasecmp( codec, "ac3" ) )
3092     {
3093         return HB_ACODEC_AC3;
3094     }
3095     else if( !strcasecmp( codec, "dts" ) || !strcasecmp( codec, "dca" ) )
3096     {
3097         return HB_ACODEC_DCA;
3098     }
3099     else if( !strcasecmp( codec, "lame" ) )
3100     {
3101         return HB_ACODEC_LAME;
3102     }
3103     else if( !strcasecmp( codec, "faac" ) )
3104     {
3105         return HB_ACODEC_FAAC;
3106     }
3107     else if( !strcasecmp( codec, "vorbis") )
3108     {
3109         return HB_ACODEC_VORBIS;
3110     }
3111 #ifdef __APPLE__
3112     else if( !strcasecmp( codec, "ca_aac") )
3113     {
3114         return HB_ACODEC_CA_AAC;
3115     }
3116 #endif
3117     else
3118     {
3119         return -1;
3120     }
3121 }
3122
3123 static int is_sample_rate_valid(int rate)
3124 {
3125     int i;
3126     for( i = 0; i < hb_audio_rates_count; i++ )
3127     {
3128             if (rate == hb_audio_rates[i].rate)
3129                 return 1;
3130     }
3131     return 0;
3132 }
3133
3134 #ifdef __APPLE_CC__
3135 /****************************************************************************
3136  * bsd_name_for_path
3137  *
3138  * Returns the BSD device name for the block device that contains the
3139  * passed-in path. Returns NULL on failure.
3140  ****************************************************************************/
3141 static char* bsd_name_for_path(char *path)
3142 {
3143     OSStatus err;
3144     FSRef ref;
3145     err = FSPathMakeRef( (const UInt8 *) input, &ref, NULL );
3146     if( err != noErr )
3147     {
3148         return NULL;
3149     }
3150
3151     // Get the volume reference number.
3152     FSCatalogInfo catalogInfo;
3153     err = FSGetCatalogInfo( &ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL,
3154                             NULL);
3155     if( err != noErr )
3156     {
3157         return NULL;
3158     }
3159     FSVolumeRefNum volRefNum = catalogInfo.volume;
3160
3161     // Now let's get the device name
3162     GetVolParmsInfoBuffer volumeParms;
3163     err = FSGetVolumeParms( volRefNum, &volumeParms, sizeof( volumeParms ) );
3164     if( err != noErr )
3165     {
3166         return NULL;
3167     }
3168
3169     // A version 4 GetVolParmsInfoBuffer contains the BSD node name in the vMDeviceID field.
3170     // It is actually a char * value. This is mentioned in the header CoreServices/CarbonCore/Files.h.
3171     if( volumeParms.vMVersion < 4 )
3172     {
3173         return NULL;
3174     }
3175
3176     // vMDeviceID might be zero as is reported with experimental ZFS (zfs-119) support in Leopard.
3177     if( !volumeParms.vMDeviceID )
3178     {
3179         return NULL;
3180     }
3181
3182     return strdup( volumeParms.vMDeviceID );
3183 }
3184
3185 /****************************************************************************
3186  * device_is_dvd
3187  *
3188  * Returns whether or not the passed in BSD device represents a DVD, or other
3189  * optical media.
3190  ****************************************************************************/
3191 static int device_is_dvd(char *device)
3192 {
3193     io_service_t service = get_iokit_service(device);
3194     if( service == IO_OBJECT_NULL )
3195     {
3196         return 0;
3197     }
3198     int result = is_dvd_service(service);
3199     IOObjectRelease(service);
3200     return result;
3201 }
3202
3203 /****************************************************************************
3204  * get_iokit_service
3205  *
3206  * Returns the IOKit service object for the passed in BSD device name.
3207  ****************************************************************************/
3208 static io_service_t get_iokit_service( char *device )
3209 {
3210     CFMutableDictionaryRef matchingDict;
3211     matchingDict = IOBSDNameMatching( kIOMasterPortDefault, 0, device );
3212     if( matchingDict == NULL )
3213     {
3214         return IO_OBJECT_NULL;
3215     }
3216     // Fetch the object with the matching BSD node name. There should only be
3217     // one match, so IOServiceGetMatchingService is used instead of
3218     // IOServiceGetMatchingServices to simplify the code.
3219     return IOServiceGetMatchingService( kIOMasterPortDefault, matchingDict );
3220 }
3221
3222 /****************************************************************************
3223  * is_dvd_service
3224  *
3225  * Returns whether or not the service passed in is a DVD.
3226  *
3227  * Searches for an IOMedia object that represents the entire (whole) media that
3228  * the volume is on. If the volume is on partitioned media, the whole media
3229  * object will be a parent of the volume's media object. If the media is not
3230  * partitioned, the volume's media object will be the whole media object.
3231  ****************************************************************************/
3232 static int is_dvd_service( io_service_t service )
3233 {
3234     kern_return_t  kernResult;
3235     io_iterator_t  iter;
3236
3237     // Create an iterator across all parents of the service object passed in.
3238     kernResult = IORegistryEntryCreateIterator( service,
3239                                                 kIOServicePlane,
3240                                                 kIORegistryIterateRecursively | kIORegistryIterateParents,
3241                                                 &iter );
3242     if( kernResult != KERN_SUCCESS )
3243     {
3244         return 0;
3245     }
3246     if( iter == IO_OBJECT_NULL )
3247     {
3248         return 0;
3249     }
3250
3251     // A reference on the initial service object is released in the do-while
3252     // loop below, so add a reference to balance.
3253     IOObjectRetain( service );
3254
3255     int result = 0;
3256     do
3257     {
3258         if( is_whole_media_service( service ) &&
3259             IOObjectConformsTo( service, kIODVDMediaClass) )
3260         {
3261             result = 1;
3262         }
3263         IOObjectRelease( service );
3264     } while( !result && (service = IOIteratorNext( iter )) );
3265     IOObjectRelease( iter );
3266
3267     return result;
3268 }
3269
3270 /****************************************************************************
3271  * is_whole_media_service
3272  *
3273  * Returns whether or not the service passed in is an IOMedia service and
3274  * represents the "whole" media instead of just a partition.
3275  *
3276  * The whole media object is indicated in the IORegistry by the presence of a
3277  * property with the key "Whole" and value "Yes".
3278  ****************************************************************************/
3279 static int is_whole_media_service( io_service_t service )
3280 {
3281     int result = 0;
3282
3283     if( IOObjectConformsTo( service, kIOMediaClass ) )
3284     {
3285         CFTypeRef wholeMedia = IORegistryEntryCreateCFProperty( service,
3286                                                                 CFSTR( kIOMediaWholeKey ),
3287                                                                 kCFAllocatorDefault,
3288                                                                 0 );
3289         if ( !wholeMedia )
3290         {
3291             return 0;
3292         }
3293         result = CFBooleanGetValue( (CFBooleanRef)wholeMedia );
3294         CFRelease( wholeMedia );
3295     }
3296
3297     return result;
3298 }
3299 #endif // __APPLE_CC__