OSDN Git Service

MacGui: Add flexible dylib path manipulation so that we can handle external dylibs...
[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 && mux == HB_MUX_MKV )
1761                         {
1762                             job->select_subtitle_config.dest = PASSTHRUSUB;
1763                         }
1764                         else if ( burn )
1765                         {
1766                             if ( sub_burned )
1767                             {
1768                                 continue;
1769                             }
1770                             sub_burned = 1;
1771                         }
1772                         if ( !( !burn && mux == HB_MUX_MP4 ) )
1773                         {
1774                             job->select_subtitle_config.force = force;
1775                             job->select_subtitle_config.default_track = def;
1776                             subtitle_scan = 1;
1777                         } else {
1778                             fprintf( stderr, "Warning: Subtitle Scan for MP4 requires the '--subtitle-burn' option to be selected\n");
1779                         }
1780                     }
1781                     else
1782                     {
1783                         hb_subtitle_t        * subtitle;
1784                         hb_subtitle_config_t   sub_config;
1785                         int                    track;
1786                         int                    burn = 0, force = 0, def = 0;
1787
1788                         track = atoi(token) - 1;
1789                         subtitle = hb_list_item(title->list_subtitle, track);
1790                         if( subtitle == NULL ) 
1791                         {
1792                             fprintf( stderr, "Warning: Could not find subtitle track %d, skipped\n", track+1 );
1793                             continue;
1794                         }
1795                         sub_config = subtitle->config;
1796
1797                         if ( subburn != NULL )
1798                         {
1799                             burn = ( pos == 1 && subburn[0] == 0 ) ||
1800                                    ( strcmp( token, subburn ) == 0 );
1801                         }
1802                         if ( subdefault != NULL )
1803                         {
1804                             def =  ( pos == 1 && subdefault[0] == 0 ) ||
1805                                    ( strcmp( token, subdefault ) == 0 );
1806                         }
1807
1808                         force = test_sub_list(subforce, token, pos);
1809
1810                         if ( !burn && subtitle->format == PICTURESUB)
1811                         {
1812                             sub_config.dest = PASSTHRUSUB;
1813                         }
1814                         else if ( burn && subtitle->format == PICTURESUB )
1815                         {
1816                             // Only allow one subtitle to be burned into video
1817                             if ( sub_burned )
1818                             {
1819                                 fprintf( stderr, "Warning: Skipping subtitle track %d, can't have more than one track burnt in\n", track+1 );
1820                                 continue;
1821                             }
1822                             sub_burned = 1;
1823                         }
1824                         sub_config.force = force;
1825                         sub_config.default_track = def;
1826                         hb_subtitle_add( job, &sub_config, track );
1827                     }
1828                 }
1829             }
1830
1831             if( srtfile )
1832             {
1833                 char * token;
1834                 int i, pos;
1835                 hb_subtitle_config_t sub_config;
1836
1837                 pos = 0;
1838                 for( i=0; srtfile[i] != NULL; i++ )
1839                 {
1840                     char *codeset = "L1";
1841                     int64_t offset = 0;
1842                     char *lang = "und";
1843
1844                     pos++;
1845                     token = srtfile[i];
1846                     if( srtcodeset && srtcodeset[i] )
1847                     {
1848                         codeset = srtcodeset[i];
1849                     }
1850                     if( srtoffset && srtoffset[i] )
1851                     {
1852                         offset = strtoll( srtoffset[i], &srtoffset[i], 0 );
1853                     }
1854                     if ( srtlang && srtlang[i] )
1855                     {
1856                         lang = srtlang[i];
1857                     }
1858                     sub_config.default_track = 
1859                            ( srtdefault != -1 ) && ( srtdefault == i + 1 );
1860                     sub_config.force = 0;
1861                     strncpy( sub_config.src_filename, srtfile[i], 128);
1862                     strncpy( sub_config.src_codeset, codeset, 40);
1863                     sub_config.offset = offset;
1864
1865                     hb_srt_add( job, &sub_config, lang);
1866                 }
1867             }
1868
1869             if( native_language )
1870             {
1871                 char audio_lang[4];
1872                 
1873                 audio = hb_list_audio_config_item(job->list_audio, 0);
1874                 
1875                 if( audio ) 
1876                 {
1877                     strncpy( audio_lang, audio->lang.iso639_2, sizeof( audio_lang ) );
1878                     
1879                     if( strncasecmp( native_language, audio_lang, 
1880                                      sizeof( audio_lang ) ) != 0 )
1881                     {
1882                         /*
1883                          * Audio language is not the same as our native language. 
1884                          * If we have any subtitles in our native language they
1885                          * should be selected here if they haven't already been.
1886                          */
1887                         hb_subtitle_t *subtitle, *subtitle2 = NULL;
1888                         int matched_track = 0;
1889
1890                         for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1891                         {
1892                             subtitle = hb_list_item( title->list_subtitle, i );
1893                             matched_track = i;
1894                             if( strcmp( subtitle->iso639_2, native_language ) == 0 )
1895                             {  
1896                                 /*
1897                                  * Found the first matching subtitle in our
1898                                  * native language. Is it already selected?
1899                                  */
1900                                 for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
1901                                 {
1902                                     subtitle2 =  hb_list_item( job->list_subtitle, i );
1903                                     
1904                                     if( subtitle2->track == subtitle->track) {
1905                                         /*
1906                                          * Already selected
1907                                          */
1908                                         break;
1909                                     }
1910                                     subtitle2 = NULL;
1911                                 }
1912                                 
1913                                 if( subtitle2 == NULL ) 
1914                                 {
1915                                     /*
1916                                      * Not already selected, so select it.
1917                                      */
1918                                     hb_subtitle_config_t sub_config;
1919
1920                                     if( native_dub )
1921                                     {
1922                                         fprintf( stderr, "Warning: no matching audio for native language - using subtitles instead.\n");
1923                                     }
1924                                     sub_config = subtitle->config;
1925
1926                                     if( mux == HB_MUX_MKV || subtitle->format == TEXTSUB)
1927                                     {
1928                                         sub_config.dest = PASSTHRUSUB;
1929                                     }
1930
1931                                     sub_config.force = 0;
1932                                     sub_config.default_track = 1;
1933                                     hb_subtitle_add( job, &sub_config, matched_track);
1934                                 }
1935                                 /*
1936                                  * Stop searching.
1937                                  */
1938                                 break;
1939                             }
1940                         }
1941                     }
1942                 }
1943             }
1944
1945             if( job->mux )
1946             {
1947                 job->mux = mux;
1948             }
1949
1950             if ( largeFileSize )
1951             {
1952                 job->largeFileSize = 1;
1953             }
1954             if ( mp4_optimize )
1955             {
1956                 job->mp4_optimize = 1;
1957             }
1958             if ( ipod_atom )
1959             {
1960                 job->ipod_atom = 1;
1961             }
1962
1963             job->file = strdup( output );
1964
1965             if( color_matrix )
1966             {
1967                 job->color_matrix = color_matrix;
1968             }
1969
1970             if( x264opts != NULL && *x264opts != '\0' )
1971             {
1972                 job->x264opts = x264opts;
1973             }
1974             else /*avoids a bus error crash when options aren't specified*/
1975             {
1976                 job->x264opts =  NULL;
1977             }
1978             if (maxWidth)
1979                 job->maxWidth = maxWidth;
1980             if (maxHeight)
1981                 job->maxHeight = maxHeight;
1982
1983             if( start_at_preview )
1984             {
1985                 job->start_at_preview = start_at_preview - 1;
1986                 job->seek_points = preview_count;
1987             }
1988             
1989             if( stop_at_pts )
1990             {
1991                 job->pts_to_stop = stop_at_pts;
1992                 subtitle_scan = 0;
1993             }
1994             
1995             if( stop_at_frame )
1996             {
1997                 job->frame_to_stop = stop_at_frame;
1998                 subtitle_scan = 0;
1999             }
2000             
2001             if( start_at_pts )
2002             {
2003                 job->pts_to_start = start_at_pts;
2004                 subtitle_scan = 0;
2005             }
2006             
2007             if( start_at_frame )
2008             {
2009                 job->frame_to_start = start_at_frame;
2010                 subtitle_scan = 0;
2011             }
2012             
2013             if( subtitle_scan )
2014             {
2015                 char *x264opts_tmp;
2016
2017                 /*
2018                  * When subtitle scan is enabled do a fast pre-scan job
2019                  * which will determine which subtitles to enable, if any.
2020                  */
2021                 job->pass = -1;
2022
2023                 x264opts_tmp = job->x264opts;
2024
2025                 job->x264opts = NULL;
2026
2027                 job->indepth_scan = subtitle_scan;
2028                 fprintf( stderr, "Subtitle Scan Enabled - enabling "
2029                          "subtitles if found for foreign language segments\n");
2030
2031                 /*
2032                  * Add the pre-scan job
2033                  */
2034                 hb_add( h, job );
2035
2036                 job->x264opts = x264opts_tmp;
2037             }
2038
2039             if( twoPass )
2040             {
2041                 /*
2042                  * If subtitle_scan is enabled then only turn it on
2043                  * for the first pass and then off again for the
2044                  * second.
2045                  */
2046                 job->pass = 1;
2047
2048                 job->indepth_scan = 0;
2049
2050                 if (x264opts)
2051                 {
2052                     x264opts2 = strdup(x264opts);
2053                 }
2054
2055                 /*
2056                  * If turbo options have been selected then append them
2057                  * to the x264opts now (size includes one ':' and the '\0')
2058                  */
2059                 if( turbo_opts_enabled )
2060                 {
2061                     int size = (x264opts ? strlen(x264opts) : 0) + strlen(turbo_opts) + 2;
2062                     char *tmp_x264opts;
2063
2064                     tmp_x264opts = malloc(size * sizeof(char));
2065                     if( x264opts )
2066                     {
2067                         snprintf( tmp_x264opts, size, "%s:%s",
2068                                   x264opts, turbo_opts );
2069                         free( x264opts );
2070                     } else {
2071                         /*
2072                          * No x264opts to modify, but apply the turbo options
2073                          * anyway as they may be modifying defaults
2074                          */
2075                         snprintf( tmp_x264opts, size, "%s",
2076                                   turbo_opts );
2077                     }
2078                     x264opts = tmp_x264opts;
2079
2080                     fprintf( stderr, "Modified x264 options for pass 1 to append turbo options: %s\n",
2081                              x264opts );
2082
2083                     job->x264opts = x264opts;
2084                 }
2085                 hb_add( h, job );
2086
2087                 job->pass = 2;
2088                 /*
2089                  * On the second pass we turn off subtitle scan so that we
2090                  * can actually encode using any subtitles that were auto
2091                  * selected in the first pass (using the whacky select-subtitle
2092                  * attribute of the job).
2093                  */
2094                 job->indepth_scan = 0;
2095
2096                 job->x264opts = x264opts2;
2097
2098                 hb_add( h, job );
2099             }
2100             else
2101             {
2102                 /*
2103                  * Turn on subtitle scan if requested, note that this option
2104                  * precludes encoding of any actual subtitles.
2105                  */
2106
2107                 job->indepth_scan = 0;
2108                 job->pass = 0;
2109                 hb_add( h, job );
2110             }
2111             hb_start( h );
2112             break;
2113         }
2114
2115 #define p s.param.working
2116         case HB_STATE_SEARCHING:
2117             fprintf( stdout, "\rEncoding: task %d of %d, Searching for start time, %.2f %%",
2118                      p.job_cur, p.job_count, 100.0 * p.progress );
2119             if( p.seconds > -1 )
2120             {
2121                 fprintf( stdout, " (ETA %02dh%02dm%02ds)", 
2122                          p.hours, p.minutes, p.seconds );
2123             }
2124             fflush(stdout);
2125             break;
2126
2127         case HB_STATE_WORKING:
2128             fprintf( stdout, "\rEncoding: task %d of %d, %.2f %%",
2129                      p.job_cur, p.job_count, 100.0 * p.progress );
2130             if( p.seconds > -1 )
2131             {
2132                 fprintf( stdout, " (%.2f fps, avg %.2f fps, ETA "
2133                          "%02dh%02dm%02ds)", p.rate_cur, p.rate_avg,
2134                          p.hours, p.minutes, p.seconds );
2135             }
2136             fflush(stdout);
2137             break;
2138 #undef p
2139
2140 #define p s.param.muxing
2141         case HB_STATE_MUXING:
2142         {
2143             if (show_mux_warning)
2144             {
2145                 fprintf( stdout, "\rMuxing: this may take awhile..." );
2146                 fflush(stdout);
2147                 show_mux_warning = 0;
2148             }
2149             break;
2150         }
2151 #undef p
2152
2153 #define p s.param.workdone
2154         case HB_STATE_WORKDONE:
2155             /* Print error if any, then exit */
2156             switch( p.error )
2157             {
2158                 case HB_ERROR_NONE:
2159                     fprintf( stderr, "\nRip done!\n" );
2160                     break;
2161                 case HB_ERROR_CANCELED:
2162                     fprintf( stderr, "\nRip canceled.\n" );
2163                     break;
2164                 default:
2165                     fprintf( stderr, "\nRip failed (error %x).\n",
2166                              p.error );
2167             }
2168             die = 1;
2169             break;
2170 #undef p
2171     }
2172     return 0;
2173 }
2174
2175 /****************************************************************************
2176  * SigHandler:
2177  ****************************************************************************/
2178 static volatile int64_t i_die_date = 0;
2179 void SigHandler( int i_signal )
2180 {
2181     if( die == 0 )
2182     {
2183         die = 1;
2184         i_die_date = hb_get_date();
2185         fprintf( stderr, "Signal %d received, terminating - do it "
2186                  "again in case it gets stuck\n", i_signal );
2187     }
2188     else if( i_die_date + 500 < hb_get_date() )
2189     {
2190         fprintf( stderr, "Dying badly, files might remain in your /tmp\n" );
2191         exit( 1 );
2192     }
2193 }
2194
2195 /****************************************************************************
2196  * ShowHelp:
2197  ****************************************************************************/
2198 static void ShowHelp()
2199 {
2200     int i;
2201     FILE* const out = stdout;
2202
2203     fprintf( out,
2204     "Syntax: HandBrakeCLI [options] -i <device> -o <file>\n"
2205     "\n"
2206     "### General Handbrake Options------------------------------------------------\n\n"
2207     "    -h, --help              Print help\n"
2208     "    -u, --update            Check for updates and exit\n"
2209     "    -v, --verbose <#>       Be verbose (optional argument: logging level)\n"
2210     "    -C, --cpu               Set CPU count (default: autodetected)\n"
2211     "    -Z. --preset <string>   Use a built-in preset. Capitalization matters, and\n"
2212     "                            if the preset name has spaces, surround it with\n"
2213     "                            double quotation marks\n"
2214     "    -z, --preset-list       See a list of available built-in presets\n"
2215     "        --no-dvdnav         Do not use dvdnav for reading DVDs\n"
2216     "                            (experimental, enabled by default for testing)\n"
2217     "\n"
2218
2219     "### Source Options-----------------------------------------------------------\n\n"
2220     "    -i, --input <string>    Set input device\n"
2221     "    -t, --title <number>    Select a title to encode (0 to scan all titles only,\n"
2222     "                            default: 1)\n"
2223     "        --scan              Scan selected title only.\n"
2224     "        --main-feature      Detect and select the main feature title.\n"
2225     "    -c, --chapters <string> Select chapters (e.g. \"1-3\" for chapters\n"
2226     "                            1 to 3, or \"3\" for chapter 3 only,\n"
2227     "                            default: all chapters)\n"
2228     "        --angle <number>    Select the DVD angle\n"
2229     "        --previews <#:B>    Select how many preview images are generated (max 30),\n"
2230     "                            and whether or not they're stored to disk (0 or 1).\n"
2231     "                            (default: 10:0)\n"
2232     "    --start-at-preview <#>  Start encoding at a given preview.\n"
2233     "    --start-at    <unit:#>  Start encoding at a given frame, duration (in seconds),\n"
2234     "                            or pts (on a 90kHz clock)\n"
2235     "    --stop-at     <unit:#>  Stop encoding at a given frame, duration (in seconds),\n"
2236     "                            or pts (on a 90kHz clock)"
2237     "\n"
2238
2239     "### Destination Options------------------------------------------------------\n\n"
2240     "    -o, --output <string>   Set output file name\n"
2241     "    -f, --format <string>   Set output format (mp4/mkv, default:\n"
2242     "                            autodetected from file name)\n"
2243     "    -m, --markers           Add chapter markers (mp4 and mkv output formats only)\n"
2244     "    -4, --large-file        Use 64-bit mp4 files that can hold more than\n"
2245     "                            4 GB. Note: Breaks iPod, PS3 compatibility.\n"""
2246     "    -O, --optimize          Optimize mp4 files for HTTP streaming\n"
2247     "    -I, --ipod-atom         Mark mp4 files so 5.5G iPods will accept them\n"
2248     "\n"
2249
2250
2251     "### Video Options------------------------------------------------------------\n\n"
2252     "    -e, --encoder <string>  Set video library encoder (ffmpeg,x264,theora)\n"
2253     "                            (default: ffmpeg)\n"
2254     "    -x, --x264opts <string> Specify advanced x264 options in the\n"
2255     "                            same style as mencoder:\n"
2256     "                            option1=value1:option2=value2\n"
2257     "    -q, --quality <number>  Set video quality\n"
2258     "    -S, --size <MB>         Set target size\n"
2259     "    -b, --vb <kb/s>         Set video bitrate (default: 1000)\n"
2260     "    -2, --two-pass          Use two-pass mode\n"
2261     "    -T, --turbo             When using 2-pass use the turbo options\n"
2262     "                            on the first pass to improve speed\n"
2263     "                            (only works with x264, affects PSNR by about 0.05dB,\n"
2264     "                            and increases first pass speed two to four times)\n"
2265     "    -r, --rate              Set video framerate (" );
2266     for( i = 0; i < hb_video_rates_count; i++ )
2267     {
2268         fprintf( out, hb_video_rates[i].string );
2269         if( i != hb_video_rates_count - 1 )
2270             fprintf( out, "/" );
2271     }
2272     fprintf( out, ")\n"
2273     "                            Be aware that not specifying a framerate lets\n"
2274     "                            HandBrake preserve a source's time stamps,\n"
2275     "                            potentially creating variable framerate video\n"
2276     "    --vfr, --cfr, --pfr     Select variable, constant or peak-limited\n"
2277     "                            frame rate control. VFR preserves the source\n"
2278     "                            timing. CFR makes the output constant rate at\n"
2279     "                            the rate given by the -r flag (or the source's\n"
2280     "                            average rate if no -r is given). PFR doesn't\n"
2281     "                            allow the rate to go over the rate specified\n"
2282     "                            with the -r flag but won't change the source\n"
2283     "                            timing if it's below that rate.\n"
2284     "                            If none of these flags are given, the default\n"
2285     "                            is --cfr when -r is given and --vfr otherwise\n"
2286
2287     "\n"
2288     "### Audio Options-----------------------------------------------------------\n\n"
2289     "    -a, --audio <string>    Select audio track(s), separated by commas\n"
2290     "                            More than one output track can be used for one\n"
2291     "                            input.\n"
2292     "                            (\"none\" for no audio, \"1,2,3\" for multiple\n"
2293     "                             tracks, default: first one)\n" );
2294
2295 #ifdef __APPLE_CC__
2296     fprintf( out,
2297     "    -E, --aencoder <string> Audio encoder(s) (ca_aac/faac/lame/vorbis/ac3/dts) \n"
2298     "                            ac3 and dts meaning passthrough\n"
2299     "                            Separated by commas for more than one audio track.\n"
2300     "                            (default: guessed)\n" );
2301 #else
2302     fprintf( out,
2303     "    -E, --aencoder <string> Audio encoder(s) (faac/lame/vorbis/ac3/dts) \n"
2304     "                            ac3 and dts meaning passthrough\n"
2305     "                            Separated by commas for more than one audio track.\n"
2306     "                            (default: guessed)\n" );
2307 #endif
2308     fprintf( out,
2309     "    -B, --ab <kb/s>         Set audio bitrate(s)  (default: 160)\n"
2310     "                            Separated by commas for more than one audio track.\n"
2311     "    -6, --mixdown <string>  Format(s) for surround sound downmixing\n"
2312     "                            Separated by commas for more than one audio track.\n"
2313     "                            (mono/stereo/dpl1/dpl2/6ch, default: dpl2)\n"
2314     "    -R, --arate             Set audio samplerate(s) (" );
2315     for( i = 0; i < hb_audio_rates_count; i++ )
2316     {
2317         fprintf( out, hb_audio_rates[i].string );
2318         if( i != hb_audio_rates_count - 1 )
2319             fprintf( out, "/" );
2320     }
2321     fprintf( out, " kHz)\n"
2322     "                            Separated by commas for more than one audio track.\n"
2323     "    -D, --drc <float>       Apply extra dynamic range compression to the audio,\n"
2324     "                            making soft sounds louder. Range is 1.0 to 4.0\n"
2325     "                            (too loud), with 1.5 - 2.5 being a useful range.\n"
2326     "                            Separated by commas for more than one audio track.\n"
2327     "    -A, --aname <string>    Audio track name(s),\n"
2328     "                            Separated by commas for more than one audio track.\n"
2329     "\n"
2330
2331     "### Picture Settings---------------------------------------------------------\n\n"
2332     "    -w, --width <number>    Set picture width\n"
2333     "    -l, --height <number>   Set picture height\n"
2334     "        --crop <T:B:L:R>    Set cropping values (default: autocrop)\n"
2335     "    -Y, --maxHeight <#>     Set maximum height\n"
2336     "    -X, --maxWidth <#>      Set maximum width\n"
2337     "    --strict-anamorphic     Store pixel aspect ratio in video stream\n"
2338     "    --loose-anamorphic      Store pixel aspect ratio with specified width\n"
2339     "    --custom-anamorphic     Store pixel aspect ratio in video stream and\n"
2340     "                            directly control all parameters.\n"
2341     "    --display-width         Set the width to scale the actual pixels to\n"
2342     "      <number>              at playback, for custom anamorphic.\n"
2343     "    --keep-display-aspect   Preserve the source's display aspect ratio\n"
2344     "                            when using custom anamorphic\n"
2345     "    --pixel-aspect          Set a custom pixel aspect for custom anamorphic\n"
2346     "      <PARX:PARY>\n"
2347     "                            (--display-width and --pixel-aspect are mutually\n"
2348     "                             exclusive and the former will override the latter)\n"
2349     "    --itu-par               Use wider, ITU pixel aspect values for loose and\n"
2350     "                            custom anamorphic, useful with underscanned sources\n"
2351     "    --modulus               Set the number you want the scaled pixel dimensions\n"
2352     "      <number>              to divide cleanly by. Does not affect strict\n"
2353     "                            anamorphic mode, which is always mod 2 (default: 16)\n"
2354     "    -M  --color-matrix      Set the color space signaled by the output\n"
2355     "          <601 or 709>      (Bt.601 is mostly for SD content, Bt.709 for HD,\n"
2356     "                             default: set by resolution)\n"
2357     "\n"
2358
2359     "### Filters---------------------------------------------------------\n\n"
2360
2361      "    -d, --deinterlace       Deinterlace video with yadif/mcdeint filter\n"
2362      "          <YM:FD:MM:QP>     (default 0:-1:-1:1)\n"
2363      "           or\n"
2364      "          <fast/slow/slower>\n"
2365      "    -5, --decomb            Selectively deinterlaces when it detects combing\n"
2366      "          <MO:ME:MT:ST:BT:BX:BY:MG:VA:LA:DI:ER:NO:MD:PP:FD>\n"
2367      "          (default: 7:2:6:9:80:16:16:10:20:20:4:2:50:24:1:-1)\n"
2368      "    -9, --detelecine        Detelecine (ivtc) video with pullup filter\n"
2369      "                            Note: this filter drops duplicate frames to\n"
2370      "                            restore the pre-telecine framerate, unless you\n"
2371      "                            specify a constant framerate (--rate 29.97)\n"
2372      "          <L:R:T:B:SB:MP:FD>   (default 1:1:4:4:0:0:-1)\n"
2373      "    -8, --denoise           Denoise video with hqdn3d filter\n"
2374      "          <SL:SC:TL:TC>     (default 4:3:6:4.5)\n"
2375      "           or\n"
2376      "          <weak/medium/strong>\n"
2377      "    -7, --deblock           Deblock video with pp7 filter\n"
2378      "          <QP:M>            (default 5:2)\n"
2379      "        --rotate            Flips images axes\n"
2380      "          <M>               (default 3)\n"
2381     "    -g, --grayscale         Grayscale encoding\n"
2382     "\n"
2383
2384     "### Subtitle Options------------------------------------------------------------\n\n"
2385     "    -s, --subtitle <string> Select subtitle track(s), separated by commas\n"
2386     "                            More than one output track can be used for one\n"
2387     "                            input.\n"
2388     "                            (\"1,2,3\" for multiple tracks.\n"
2389     "                            A special track name \"scan\" adds an extra 1st pass.\n"
2390     "                            This extra pass scans subtitles matching the\n"
2391     "                            language of the first audio or the language \n"
2392     "                            selected by --native-language.\n"
2393     "                            The one that's only used 10 percent of the time\n"
2394     "                            or less is selected. This should locate subtitles\n"
2395     "                            for short foreign language segments. Best used in\n"
2396     "                            conjunction with --subtitle-forced.\n"
2397     "    -F, --subtitle-forced   Only display subtitles from the selected stream if\n"
2398     "          <string>          the subtitle has the forced flag set. May be used in\n"
2399     "                            conjunction with \"scan\" track to auto-select\n"
2400     "                            a stream if it contains forced subtitles.\n"
2401     "                            Separated by commas for more than one audio track.\n"
2402     "                            (\"1,2,3\" for multiple tracks.\n"
2403     "                            If \"string\" is omitted, the first trac is forced.\n"
2404     "        --subtitle-burn     \"Burn\" the selected subtitle into the video track\n"
2405     "          <number>          If \"number\" is omitted, the first trac is burned.\n"
2406     "        --subtitle-default  Flag the selected subtitle as the default subtitle\n"
2407     "          <number>          to be displayed upon playback.  Setting no default\n"
2408     "                            means no subtitle will be automatically displayed\n"
2409     "                            If \"number\" is omitted, the first trac is default.\n"
2410     "    -N, --native-language   Specifiy the your language preference. When the first\n"
2411     "          <string>          audio track does not match your native language then\n"
2412     "                            select the first subtitle that does. When used in\n"
2413     "                            conjunction with --native-dub the audio track is\n"
2414     "                            changed in preference to subtitles. Provide the\n"
2415     "                            language's iso639-2 code (fre, eng, spa, dut, et cetera)\n"
2416     "        --native-dub        Used in conjunction with --native-language\n"
2417     "                            requests that if no audio tracks are selected the\n"
2418     "                            default selected audio track will be the first one\n"
2419     "                            that matches the --native-language. If there are no\n"
2420     "                            matching audio tracks then the first matching\n"
2421     "                            subtitle track is used instead.\n"
2422     "        --srt-file <string> SubRip SRT filename(s), separated by commas.\n"
2423     "        --srt-codeset       Character codeset(s) that the SRT file(s) are\n"
2424     "          <string>          encoded in, separted by commas.\n"
2425     "                            Use 'iconv -l' for a list of valid\n"
2426     "                            codesets. If not specified latin1 is assumed\n"
2427     "        --srt-offset        Offset in milli-seconds to apply to the SRT file(s)\n"
2428     "          <string>          separted by commas. If not specified zero is assumed.\n"
2429     "                            Offsets may be negative.\n"
2430     "        --srt-lang <string> Language as an iso639-2 code fra, eng, spa et cetera)\n"
2431     "                            for the SRT file(s) separated by commas. If not specified\n"
2432     "                            then 'und' is used.\n"
2433     "        --srt-default       Flag the selected srt as the default subtitle\n"
2434     "          <number>          to be displayed upon playback.  Setting no default\n"
2435     "                            means no subtitle will be automatically displayed\n"
2436     "                            If \"number\" is omitted, the first srt is default.\n"
2437     "                            \"number\" is an 1 based index into the srt-file list\n"
2438     "\n"
2439
2440
2441     );
2442 }
2443
2444 /****************************************************************************
2445  * ShowPresets:
2446  ****************************************************************************/
2447 static void ShowPresets()
2448 {
2449     printf("\n< Apple\n");
2450
2451     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");
2452
2453     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");
2454
2455     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");
2456
2457     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");
2458
2459     printf("\n>\n");
2460
2461     printf("\n< Regular\n");
2462
2463     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");
2464
2465     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");
2466
2467     printf("\n>\n");
2468
2469     printf("\n< Legacy\n");
2470
2471     printf("\n   + Classic:  -b 1000 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4\n");
2472
2473     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");
2474
2475     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");
2476
2477     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");
2478
2479     printf("\n>\n");
2480 }
2481
2482 static char * hb_strndup( char * str, int len )
2483 {
2484         char * res;
2485         int str_len = strlen( str );
2486
2487         res = malloc( len > str_len ? str_len + 1 : len + 1 );
2488         strncpy( res, str, len );
2489         res[len] = '\0';
2490         return res;
2491 }
2492
2493 static char** str_split( char *str, char delem )
2494 {
2495     char *  pos;
2496     char *  end;
2497     char ** ret;
2498     int     count, i;
2499
2500     if ( str == NULL || str[0] == 0 )
2501     {
2502         ret = malloc( sizeof(char*) );
2503         *ret = NULL;
2504         return ret;
2505     }
2506
2507     // Find number of elements in the string
2508     count = 1;
2509     pos = str;
2510     while ( ( pos = strchr( pos, delem ) ) != NULL )
2511     {
2512         count++;
2513         pos++;
2514     }
2515
2516     ret = calloc( ( count + 1 ), sizeof(char*) );
2517
2518     pos = str;
2519     for ( i = 0; i < count - 1; i++ )
2520     {
2521         end = strchr( pos, delem );
2522         ret[i] = hb_strndup(pos, end - pos);
2523         pos = end + 1;
2524     }
2525     ret[i] = strdup(pos);
2526
2527     return ret;
2528 }
2529
2530 /****************************************************************************
2531  * ParseOptions:
2532  ****************************************************************************/
2533 static int ParseOptions( int argc, char ** argv )
2534 {
2535     
2536     #define PREVIEWS            257
2537     #define START_AT_PREVIEW    258
2538     #define START_AT            259
2539     #define STOP_AT             260
2540     #define ANGLE               261
2541     #define DVDNAV              262
2542     #define DISPLAY_WIDTH       263
2543     #define PIXEL_ASPECT        264
2544     #define MODULUS             265
2545     #define KEEP_DISPLAY_ASPECT 266
2546     #define SUB_BURNED          267
2547     #define SUB_DEFAULT         268
2548     #define NATIVE_DUB          269
2549     #define SRT_FILE            270
2550     #define SRT_CODESET         271
2551     #define SRT_OFFSET          272
2552     #define SRT_LANG            273
2553     #define SRT_DEFAULT         274
2554     #define ROTATE_FILTER       275
2555     #define SCAN_ONLY           276
2556     #define MAIN_FEATURE        277
2557     
2558     for( ;; )
2559     {
2560         static struct option long_options[] =
2561           {
2562             { "help",        no_argument,       NULL,    'h' },
2563             { "update",      no_argument,       NULL,    'u' },
2564             { "verbose",     optional_argument, NULL,    'v' },
2565             { "cpu",         required_argument, NULL,    'C' },
2566             { "no-dvdnav",      no_argument,       NULL,    DVDNAV },
2567
2568             { "format",      required_argument, NULL,    'f' },
2569             { "input",       required_argument, NULL,    'i' },
2570             { "output",      required_argument, NULL,    'o' },
2571             { "large-file",  no_argument,       NULL,    '4' },
2572             { "optimize",    no_argument,       NULL,    'O' },
2573             { "ipod-atom",   no_argument,       NULL,    'I' },
2574
2575             { "title",       required_argument, NULL,    't' },
2576             { "scan",        no_argument,       NULL,    SCAN_ONLY },
2577             { "main-feature",no_argument,       NULL,    MAIN_FEATURE },
2578             { "chapters",    required_argument, NULL,    'c' },
2579             { "angle",       required_argument, NULL,    ANGLE },
2580             { "markers",     optional_argument, NULL,    'm' },
2581             { "audio",       required_argument, NULL,    'a' },
2582             { "mixdown",     required_argument, NULL,    '6' },
2583             { "drc",         required_argument, NULL,    'D' },
2584             { "subtitle",    required_argument, NULL,    's' },
2585             { "subtitle-forced", optional_argument,   NULL,    'F' },
2586             { "subtitle-burned", optional_argument,   NULL,    SUB_BURNED },
2587             { "subtitle-default", optional_argument,   NULL,    SUB_DEFAULT },
2588             { "srt-file",    required_argument, NULL, SRT_FILE },
2589             { "srt-codeset", required_argument, NULL, SRT_CODESET },
2590             { "srt-offset",  required_argument, NULL, SRT_OFFSET },
2591             { "srt-lang",    required_argument, NULL, SRT_LANG },
2592             { "srt-default",    optional_argument, NULL, SRT_DEFAULT },
2593             { "native-language", required_argument, NULL,'N' },
2594             { "native-dub",  no_argument,       NULL,    NATIVE_DUB },
2595             { "encoder",     required_argument, NULL,    'e' },
2596             { "aencoder",    required_argument, NULL,    'E' },
2597             { "two-pass",    no_argument,       NULL,    '2' },
2598             { "deinterlace", optional_argument, NULL,    'd' },
2599             { "deblock",     optional_argument, NULL,    '7' },
2600             { "denoise",     optional_argument, NULL,    '8' },
2601             { "detelecine",  optional_argument, NULL,    '9' },
2602             { "decomb",      optional_argument, NULL,    '5' },
2603             { "grayscale",   no_argument,       NULL,    'g' },
2604             { "rotate",      optional_argument, NULL,   ROTATE_FILTER },
2605             { "strict-anamorphic",  no_argument, &anamorphic_mode, 1 },
2606             { "loose-anamorphic", no_argument, &anamorphic_mode, 2 },
2607             { "custom-anamorphic", no_argument, &anamorphic_mode, 3 },
2608             { "display-width", required_argument, NULL, DISPLAY_WIDTH },
2609             { "keep-display-aspect", no_argument, &keep_display_aspect, 1 },
2610             { "pixel-aspect", required_argument, NULL, PIXEL_ASPECT },
2611             { "modulus",     required_argument, NULL, MODULUS },
2612             { "itu-par",     no_argument,       &itu_par, 1  },
2613             { "width",       required_argument, NULL,    'w' },
2614             { "height",      required_argument, NULL,    'l' },
2615             { "crop",        required_argument, NULL,    'n' },
2616
2617             { "vb",          required_argument, NULL,    'b' },
2618             { "quality",     required_argument, NULL,    'q' },
2619             { "size",        required_argument, NULL,    'S' },
2620             { "ab",          required_argument, NULL,    'B' },
2621             { "rate",        required_argument, NULL,    'r' },
2622             { "arate",       required_argument, NULL,    'R' },
2623             { "x264opts",    required_argument, NULL,    'x' },
2624             { "turbo",       no_argument,       NULL,    'T' },
2625             { "maxHeight",   required_argument, NULL,    'Y' },
2626             { "maxWidth",    required_argument, NULL,    'X' },
2627             { "preset",      required_argument, NULL,    'Z' },
2628             { "preset-list", no_argument,       NULL,    'z' },
2629
2630             { "aname",       required_argument, NULL,    'A' },
2631             { "color-matrix",required_argument, NULL,    'M' },
2632             { "previews",    required_argument, NULL,    PREVIEWS },
2633             { "start-at-preview", required_argument, NULL, START_AT_PREVIEW },
2634             { "start-at",    required_argument, NULL,    START_AT },
2635             { "stop-at",    required_argument, NULL,     STOP_AT },
2636             { "vfr",         no_argument,       &cfr,    0 },
2637             { "cfr",         no_argument,       &cfr,    1 },
2638             { "pfr",         no_argument,       &cfr,    2 },
2639             { 0, 0, 0, 0 }
2640           };
2641
2642         int option_index = 0;
2643         int c;
2644
2645                 c = getopt_long( argc, argv,
2646                                                  "hv::uC:f:4i:Io:t:Lc:m::M:a:A:6:s:UF::N:e:E:2dD:7895gOw:l:n:b:q:S:B:r:R:x:TY:X:Z:z",
2647                          long_options, &option_index );
2648         if( c < 0 )
2649         {
2650             break;
2651         }
2652
2653         switch( c )
2654         {
2655             case 0:
2656                 /* option was handled entirely in getopt_long */
2657                 break;
2658             case 'h':
2659                 ShowHelp();
2660                 exit( 0 );
2661             case 'u':
2662                 update = 1;
2663                 break;
2664             case 'v':
2665                 if( optarg != NULL )
2666                 {
2667                     debug = atoi( optarg );
2668                 }
2669                 else
2670                 {
2671                     debug = 1;
2672                 }
2673                 break;
2674             case 'C':
2675                 cpu = atoi( optarg );
2676                 break;
2677
2678             case 'Z':
2679                 preset = 1;
2680                 preset_name = strdup(optarg);
2681                 break;
2682             case 'z':
2683                 ShowPresets();
2684                 exit ( 0 );
2685             case DVDNAV:
2686                 dvdnav = 0;
2687                 break;
2688
2689             case 'f':
2690                 format = strdup( optarg );
2691                 break;
2692             case 'i':
2693                 input = strdup( optarg );
2694 #ifdef __APPLE_CC__
2695                 char *devName = bsd_name_for_path( input ); // alloc
2696                 if( devName )
2697                 {
2698                     if( device_is_dvd( devName ))
2699                     {
2700                         free( input );
2701                         input = malloc( strlen( "/dev/" ) + strlen( devName ) + 1 );
2702                         sprintf( input, "/dev/%s", devName );
2703                     }
2704                     free( devName );
2705                 }
2706 #endif
2707                 break;
2708             case 'o':
2709                 output = strdup( optarg );
2710                 break;
2711             case '4':
2712                 largeFileSize = 1;
2713                 break;
2714             case 'O':
2715                 mp4_optimize = 1;
2716                 break;
2717             case 'I':
2718                 ipod_atom = 1;
2719                 break;
2720
2721             case 't':
2722                 titleindex = atoi( optarg );
2723                 break;
2724             case SCAN_ONLY:
2725                 titlescan = 1;
2726                 break;
2727             case MAIN_FEATURE:
2728                 main_feature = 1;
2729                 break;
2730             case 'c':
2731             {
2732                 int start, end;
2733                 if( sscanf( optarg, "%d-%d", &start, &end ) == 2 )
2734                 {
2735                     chapter_start = start;
2736                     chapter_end   = end;
2737                 }
2738                 else if( sscanf( optarg, "%d", &start ) == 1 )
2739                 {
2740                     chapter_start = start;
2741                     chapter_end   = chapter_start;
2742                 }
2743                 else
2744                 {
2745                     fprintf( stderr, "chapters: invalid syntax (%s)\n",
2746                              optarg );
2747                     return -1;
2748                 }
2749                 break;
2750             }
2751             case ANGLE:
2752                 angle = atoi( optarg );
2753                 break;
2754             case 'm':
2755                 if( optarg != NULL )
2756                 {
2757                     marker_file = strdup( optarg );
2758                 }
2759                 chapter_markers = 1;
2760                 break;
2761             case 'a':
2762                 if( optarg != NULL )
2763                 {
2764                     atracks = strdup( optarg );
2765                     audio_explicit = 1;
2766                 }
2767                 else
2768                 {
2769                     atracks = "1" ;
2770                 }
2771                 break;
2772             case '6':
2773                 if( optarg != NULL )
2774                 {
2775                     mixdowns = strdup( optarg );
2776                 }
2777                 break;
2778             case 'D':
2779                 if( optarg != NULL )
2780                 {
2781                     dynamic_range_compression = strdup( optarg );
2782                 }
2783                 break;
2784             case 's':
2785                 subtracks = str_split( optarg, ',' );
2786                 break;
2787             case 'F':
2788                 subforce = str_split( optarg, ',' );
2789                 break;
2790             case SUB_BURNED:
2791                 if( optarg != NULL )
2792                 {
2793                     subburn = strdup( optarg );
2794                 }
2795                 else
2796                 {
2797                     subburn = "" ;
2798                 }
2799                 break;
2800             case SUB_DEFAULT:
2801                 if( optarg != NULL )
2802                 {
2803                     subdefault = strdup( optarg );
2804                 }
2805                 else
2806                 {
2807                     subdefault = "" ;
2808                 }
2809                 break;
2810             case 'N':
2811                 native_language = strdup( optarg );
2812                 break;
2813             case NATIVE_DUB:
2814                 native_dub = 1;
2815                 break;
2816             case SRT_FILE:
2817                 srtfile = str_split( optarg, ',' );
2818                 break;
2819             case SRT_CODESET:
2820                 srtcodeset = str_split( optarg, ',' );
2821                 break;
2822             case SRT_OFFSET:
2823                 srtoffset = str_split( optarg, ',' );
2824                 break;
2825             case SRT_LANG:
2826                 srtlang = str_split( optarg, ',' );
2827                 break;
2828             case SRT_DEFAULT:
2829                 if( optarg != NULL )
2830                 {
2831                     srtdefault = atoi( optarg );
2832                 }
2833                 else
2834                 {
2835                     srtdefault = 1 ;
2836                 }
2837                 break;
2838             case '2':
2839                 twoPass = 1;
2840                 break;
2841             case 'd':
2842                 if( optarg != NULL )
2843                 {
2844                     if (!( strcmp( optarg, "fast" ) ))
2845                     {
2846                         deinterlace_opt = "-1";
2847                     }
2848                     else if (!( strcmp( optarg, "slow" ) ))
2849                     {
2850                         deinterlace_opt = "2";
2851                     }
2852                     else if (!( strcmp( optarg, "slower" ) ))
2853                     {
2854                         deinterlace_opt = "0";
2855                     }
2856                     else
2857                     {
2858                         deinterlace_opt = strdup( optarg );
2859                     }
2860                 }
2861                 deinterlace = 1;
2862                 break;
2863             case '7':
2864                 if( optarg != NULL )
2865                 {
2866                     deblock_opt = strdup( optarg );
2867                 }
2868                 deblock = 1;
2869                 break;
2870             case '8':
2871                 if( optarg != NULL )
2872                 {
2873                     if (!( strcmp( optarg, "weak" ) ))
2874                     {
2875                         denoise_opt = "2:1:2:3";
2876                     }
2877                     else if (!( strcmp( optarg, "medium" ) ))
2878                     {
2879                         denoise_opt = "3:2:2:3";
2880                     }
2881                     else if (!( strcmp( optarg, "strong" ) ))
2882                     {
2883                         denoise_opt = "7:7:5:5";
2884                     }
2885                     else
2886                     {
2887                         denoise_opt = strdup( optarg );
2888                     }
2889                 }
2890                 denoise = 1;
2891                 break;
2892             case '9':
2893                 if( optarg != NULL )
2894                 {
2895                     detelecine_opt = strdup( optarg );
2896                 }
2897                 detelecine = 1;
2898                 break;
2899             case '5':
2900                 if( optarg != NULL )
2901                 {
2902                     decomb_opt = strdup( optarg );
2903                 }
2904                 decomb = 1;
2905                 break;
2906             case 'g':
2907                 grayscale = 1;
2908                 break;
2909             case ROTATE_FILTER:
2910                 if( optarg != NULL )
2911                 {
2912                     rotate_opt = strdup( optarg );
2913                 }
2914                 rotate = 1;
2915                 break;
2916             case DISPLAY_WIDTH:
2917                 if( optarg != NULL )
2918                 {
2919                     sscanf( optarg, "%i", &display_width );
2920                 }
2921                 break;
2922             case PIXEL_ASPECT:
2923                 if( optarg != NULL )
2924                 {
2925                     sscanf( optarg, "%i:%i", &par_width, &par_height );
2926                 }
2927                 break;
2928             case MODULUS:
2929                 if( optarg != NULL )
2930                 {
2931                     sscanf( optarg, "%i", &modulus );
2932                 }
2933                 break;
2934             case 'e':
2935                 if( !strcasecmp( optarg, "ffmpeg" ) )
2936                 {
2937                     vcodec = HB_VCODEC_FFMPEG;
2938                 }
2939                 else if( !strcasecmp( optarg, "x264" ) )
2940                 {
2941                     vcodec = HB_VCODEC_X264;
2942                 }
2943                 else if( !strcasecmp( optarg, "x264b13" ) )
2944                 {
2945                     vcodec = HB_VCODEC_X264;
2946                     h264_13 = 1;
2947                 }
2948                 else if( !strcasecmp( optarg, "x264b30" ) )
2949                 {
2950                     vcodec = HB_VCODEC_X264;
2951                     h264_30 = 1;
2952                 }
2953                 else if( !strcasecmp( optarg, "theora" ) )
2954                 {
2955                     vcodec = HB_VCODEC_THEORA;
2956                 }
2957                 else
2958                 {
2959                     fprintf( stderr, "invalid codec (%s)\n", optarg );
2960                     return -1;
2961                 }
2962                 break;
2963             case 'E':
2964                 if( optarg != NULL )
2965                 {
2966                     acodecs = strdup( optarg );
2967                 }
2968                 break;
2969             case 'w':
2970                 width = atoi( optarg );
2971                 break;
2972             case 'l':
2973                 height = atoi( optarg );
2974                 break;
2975             case 'n':
2976             {
2977                 int    i;
2978                 char * tmp = optarg;
2979                 for( i = 0; i < 4; i++ )
2980                 {
2981                     if( !*tmp )
2982                         break;
2983                     crop[i] = strtol( tmp, &tmp, 0 );
2984                     tmp++;
2985                 }
2986                 break;
2987             }
2988             case 'r':
2989             {
2990                 int i;
2991                 vrate = 0;
2992                 for( i = 0; i < hb_video_rates_count; i++ )
2993                 {
2994                     if( !strcmp( optarg, hb_video_rates[i].string ) )
2995                     {
2996                         vrate = hb_video_rates[i].rate;
2997                         break;
2998                     }
2999                 }
3000                 if( !vrate )
3001                 {
3002                     fprintf( stderr, "invalid framerate %s\n", optarg );
3003                 }
3004                 else if ( cfr == 0 )
3005                 {
3006                     cfr = 1;
3007                 }
3008                 break;
3009             }
3010             case 'R':
3011                 if( optarg != NULL )
3012                 {
3013                     arates = strdup( optarg );
3014                 }
3015                 break;
3016             case 'b':
3017                 vbitrate = atoi( optarg );
3018                 break;
3019             case 'q':
3020                 vquality = atof( optarg );
3021                 break;
3022             case 'S':
3023                 size = atoi( optarg );
3024                 break;
3025             case 'B':
3026                 if( optarg != NULL )
3027                 {
3028                     abitrates = strdup( optarg );
3029                 }
3030                 break;
3031             case 'x':
3032                 x264opts = strdup( optarg );
3033                 break;
3034             case 'T':
3035                 turbo_opts_enabled = 1;
3036                 break;
3037             case 'Y':
3038                 maxHeight = atoi( optarg );
3039                 break;
3040             case 'X':
3041                 maxWidth = atoi (optarg );
3042                 break;
3043             case 'A':
3044                 if( optarg != NULL )
3045                 {
3046                     anames = strdup( optarg );
3047                 }
3048                 break;
3049             case PREVIEWS:
3050                 sscanf( optarg, "%i:%i", &preview_count, &store_previews );
3051                 break;
3052             case START_AT_PREVIEW:
3053                 start_at_preview = atoi( optarg );
3054                 break;
3055             case START_AT:
3056                 start_at_string = strdup( optarg );
3057                 start_at_token = strtok( start_at_string, ":");
3058                 if( !strcmp( start_at_token, "frame" ) )
3059                 {
3060                     start_at_token = strtok( NULL, ":");
3061                     start_at_frame = atoi(start_at_token);
3062                 }
3063                 else if( !strcmp( start_at_token, "pts" ) )
3064                 {
3065                     start_at_token = strtok( NULL, ":");
3066                     sscanf( start_at_token, "%"SCNd64, &start_at_pts );
3067                 }
3068                 else if( !strcmp( start_at_token, "duration" ) )
3069                 {
3070                     start_at_token = strtok( NULL, ":");
3071                     sscanf( start_at_token, "%"SCNd64, &start_at_pts );
3072                     start_at_pts *= 90000LL;
3073                 }
3074                 break;
3075             case STOP_AT:
3076                 stop_at_string = strdup( optarg );
3077                 stop_at_token = strtok( stop_at_string, ":");
3078                 if( !strcmp( stop_at_token, "frame" ) )
3079                 {
3080                     stop_at_token = strtok( NULL, ":");
3081                     stop_at_frame = atoi(stop_at_token);
3082                 }
3083                 else if( !strcmp( stop_at_token, "pts" ) )
3084                 {
3085                     stop_at_token = strtok( NULL, ":");
3086                     sscanf( stop_at_token, "%"SCNd64, &stop_at_pts );
3087                 }
3088                 else if( !strcmp( stop_at_token, "duration" ) )
3089                 {
3090                     stop_at_token = strtok( NULL, ":");
3091                     sscanf( stop_at_token, "%"SCNd64, &stop_at_pts );
3092                     stop_at_pts *= 90000LL;
3093                 }
3094                 break;
3095             case 'M':
3096                 if( atoi( optarg ) == 601 )
3097                     color_matrix = 1;
3098                 else if( atoi( optarg ) == 709 )
3099                     color_matrix = 2;
3100                 break;
3101             default:
3102                 fprintf( stderr, "unknown option (%s)\n", argv[optind] );
3103                 return -1;
3104         }
3105     }
3106
3107     return 0;
3108 }
3109
3110 static int CheckOptions( int argc, char ** argv )
3111 {
3112     if( update )
3113     {
3114         return 0;
3115     }
3116
3117     if( input == NULL || *input == '\0' )
3118     {
3119         fprintf( stderr, "Missing input device. Run %s --help for "
3120                  "syntax.\n", argv[0] );
3121         return 1;
3122     }
3123
3124     /* Parse format */
3125     if( titleindex > 0 && !titlescan )
3126     {
3127         if( output == NULL || *output == '\0' )
3128         {
3129             fprintf( stderr, "Missing output file name. Run %s --help "
3130                      "for syntax.\n", argv[0] );
3131             return 1;
3132         }
3133
3134         if( !format )
3135         {
3136             char * p = strrchr( output, '.' );
3137
3138             /* autodetect */
3139             if( p && ( !strcasecmp( p, ".mp4" )  ||
3140                             !strcasecmp( p, ".m4v" ) ) )
3141             {
3142                 if ( h264_30 == 1 )
3143                     mux = HB_MUX_IPOD;
3144                 else
3145                     mux = HB_MUX_MP4;
3146                 default_acodec = HB_ACODEC_FAAC;
3147             }
3148             else if( p && !strcasecmp(p, ".mkv" ) )
3149             {
3150                 mux = HB_MUX_MKV;
3151                 default_acodec = HB_ACODEC_AC3;
3152             }
3153             else
3154             {
3155                 fprintf( stderr, "Output format couldn't be guessed "
3156                          "from file name, using default.\n" );
3157                 return 0;
3158             }
3159         }
3160         else if( !strcasecmp( format, "mp4" ) ||
3161                  !strcasecmp( format, "m4v" ) )
3162         {
3163             if ( h264_30 == 1)
3164                 mux = HB_MUX_IPOD;
3165             else
3166                 mux = HB_MUX_MP4;
3167             default_acodec = HB_ACODEC_FAAC;
3168         }
3169         else if( !strcasecmp( format, "mkv" ) )
3170         {
3171             mux = HB_MUX_MKV;
3172             default_acodec = HB_ACODEC_AC3;
3173         }
3174         else
3175         {
3176             fprintf( stderr, "Invalid output format (%s). Possible "
3177                      "choices are mp4, m4v and mkv\n.", format );
3178             return 1;
3179         }
3180     }
3181
3182     return 0;
3183 }
3184
3185 static int get_acodec_for_string( char *codec )
3186 {
3187     if( !strcasecmp( codec, "ac3" ) )
3188     {
3189         return HB_ACODEC_AC3;
3190     }
3191     else if( !strcasecmp( codec, "dts" ) || !strcasecmp( codec, "dca" ) )
3192     {
3193         return HB_ACODEC_DCA;
3194     }
3195     else if( !strcasecmp( codec, "lame" ) )
3196     {
3197         return HB_ACODEC_LAME;
3198     }
3199     else if( !strcasecmp( codec, "faac" ) )
3200     {
3201         return HB_ACODEC_FAAC;
3202     }
3203     else if( !strcasecmp( codec, "vorbis") )
3204     {
3205         return HB_ACODEC_VORBIS;
3206     }
3207 #ifdef __APPLE__
3208     else if( !strcasecmp( codec, "ca_aac") )
3209     {
3210         return HB_ACODEC_CA_AAC;
3211     }
3212 #endif
3213     else
3214     {
3215         return -1;
3216     }
3217 }
3218
3219 static int is_sample_rate_valid(int rate)
3220 {
3221     int i;
3222     for( i = 0; i < hb_audio_rates_count; i++ )
3223     {
3224             if (rate == hb_audio_rates[i].rate)
3225                 return 1;
3226     }
3227     return 0;
3228 }
3229
3230 #ifdef __APPLE_CC__
3231 /****************************************************************************
3232  * bsd_name_for_path
3233  *
3234  * Returns the BSD device name for the block device that contains the
3235  * passed-in path. Returns NULL on failure.
3236  ****************************************************************************/
3237 static char* bsd_name_for_path(char *path)
3238 {
3239     OSStatus err;
3240     FSRef ref;
3241     err = FSPathMakeRef( (const UInt8 *) input, &ref, NULL );
3242     if( err != noErr )
3243     {
3244         return NULL;
3245     }
3246
3247     // Get the volume reference number.
3248     FSCatalogInfo catalogInfo;
3249     err = FSGetCatalogInfo( &ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL,
3250                             NULL);
3251     if( err != noErr )
3252     {
3253         return NULL;
3254     }
3255     FSVolumeRefNum volRefNum = catalogInfo.volume;
3256
3257     // Now let's get the device name
3258     GetVolParmsInfoBuffer volumeParms;
3259     err = FSGetVolumeParms( volRefNum, &volumeParms, sizeof( volumeParms ) );
3260     if( err != noErr )
3261     {
3262         return NULL;
3263     }
3264
3265     // A version 4 GetVolParmsInfoBuffer contains the BSD node name in the vMDeviceID field.
3266     // It is actually a char * value. This is mentioned in the header CoreServices/CarbonCore/Files.h.
3267     if( volumeParms.vMVersion < 4 )
3268     {
3269         return NULL;
3270     }
3271
3272     // vMDeviceID might be zero as is reported with experimental ZFS (zfs-119) support in Leopard.
3273     if( !volumeParms.vMDeviceID )
3274     {
3275         return NULL;
3276     }
3277
3278     return strdup( volumeParms.vMDeviceID );
3279 }
3280
3281 /****************************************************************************
3282  * device_is_dvd
3283  *
3284  * Returns whether or not the passed in BSD device represents a DVD, or other
3285  * optical media.
3286  ****************************************************************************/
3287 static int device_is_dvd(char *device)
3288 {
3289     io_service_t service = get_iokit_service(device);
3290     if( service == IO_OBJECT_NULL )
3291     {
3292         return 0;
3293     }
3294     int result = is_dvd_service(service);
3295     IOObjectRelease(service);
3296     return result;
3297 }
3298
3299 /****************************************************************************
3300  * get_iokit_service
3301  *
3302  * Returns the IOKit service object for the passed in BSD device name.
3303  ****************************************************************************/
3304 static io_service_t get_iokit_service( char *device )
3305 {
3306     CFMutableDictionaryRef matchingDict;
3307     matchingDict = IOBSDNameMatching( kIOMasterPortDefault, 0, device );
3308     if( matchingDict == NULL )
3309     {
3310         return IO_OBJECT_NULL;
3311     }
3312     // Fetch the object with the matching BSD node name. There should only be
3313     // one match, so IOServiceGetMatchingService is used instead of
3314     // IOServiceGetMatchingServices to simplify the code.
3315     return IOServiceGetMatchingService( kIOMasterPortDefault, matchingDict );
3316 }
3317
3318 /****************************************************************************
3319  * is_dvd_service
3320  *
3321  * Returns whether or not the service passed in is a DVD.
3322  *
3323  * Searches for an IOMedia object that represents the entire (whole) media that
3324  * the volume is on. If the volume is on partitioned media, the whole media
3325  * object will be a parent of the volume's media object. If the media is not
3326  * partitioned, the volume's media object will be the whole media object.
3327  ****************************************************************************/
3328 static int is_dvd_service( io_service_t service )
3329 {
3330     kern_return_t  kernResult;
3331     io_iterator_t  iter;
3332
3333     // Create an iterator across all parents of the service object passed in.
3334     kernResult = IORegistryEntryCreateIterator( service,
3335                                                 kIOServicePlane,
3336                                                 kIORegistryIterateRecursively | kIORegistryIterateParents,
3337                                                 &iter );
3338     if( kernResult != KERN_SUCCESS )
3339     {
3340         return 0;
3341     }
3342     if( iter == IO_OBJECT_NULL )
3343     {
3344         return 0;
3345     }
3346
3347     // A reference on the initial service object is released in the do-while
3348     // loop below, so add a reference to balance.
3349     IOObjectRetain( service );
3350
3351     int result = 0;
3352     do
3353     {
3354         if( is_whole_media_service( service ) &&
3355             IOObjectConformsTo( service, kIODVDMediaClass) )
3356         {
3357             result = 1;
3358         }
3359         IOObjectRelease( service );
3360     } while( !result && (service = IOIteratorNext( iter )) );
3361     IOObjectRelease( iter );
3362
3363     return result;
3364 }
3365
3366 /****************************************************************************
3367  * is_whole_media_service
3368  *
3369  * Returns whether or not the service passed in is an IOMedia service and
3370  * represents the "whole" media instead of just a partition.
3371  *
3372  * The whole media object is indicated in the IORegistry by the presence of a
3373  * property with the key "Whole" and value "Yes".
3374  ****************************************************************************/
3375 static int is_whole_media_service( io_service_t service )
3376 {
3377     int result = 0;
3378
3379     if( IOObjectConformsTo( service, kIOMediaClass ) )
3380     {
3381         CFTypeRef wholeMedia = IORegistryEntryCreateCFProperty( service,
3382                                                                 CFSTR( kIOMediaWholeKey ),
3383                                                                 kCFAllocatorDefault,
3384                                                                 0 );
3385         if ( !wholeMedia )
3386         {
3387             return 0;
3388         }
3389         result = CFBooleanGetValue( (CFBooleanRef)wholeMedia );
3390         CFRelease( wholeMedia );
3391     }
3392
3393     return result;
3394 }
3395 #endif // __APPLE_CC__