OSDN Git Service

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