OSDN Git Service

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