OSDN Git Service

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