OSDN Git Service

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