OSDN Git Service

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