OSDN Git Service

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