OSDN Git Service

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