OSDN Git Service

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