OSDN Git Service

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