OSDN Git Service

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