OSDN Git Service

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