OSDN Git Service

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