OSDN Git Service

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