OSDN Git Service

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