OSDN Git Service

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