OSDN Git Service

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