OSDN Git Service

A big batch of patches from eddyg.
[handbrake-jp/handbrake-jp-git.git] / test / test.c
1 /* $Id: test.c,v 1.82 2005/11/19 08:25:54 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.m0k.org/>.
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 /* Options */
17 static int    debug       = HB_DEBUG_NONE;
18 static int    update      = 0;
19 static char * input       = NULL;
20 static char * output      = NULL;
21 static char * format      = NULL;
22 static int    titleindex  = 1;
23 static int    longest_title = 0;
24 static int    subtitle_scan = 0;
25 static char * native_language = NULL;
26 static int    twoPass     = 0;
27 static int    deinterlace = 0;
28 static int    grayscale   = 0;
29 static int    vcodec      = HB_VCODEC_FFMPEG;
30 static int    h264_13     = 0;
31 static int    h264_30     = 0;
32 static char * audios      = NULL;
33 static int    audio_mixdown = HB_AMIXDOWN_DOLBYPLII;
34 static int    sub         = 0;
35 static int    width       = 0;
36 static int    height      = 0;
37 static int    crop[4]     = { -1,-1,-1,-1 };
38 static int    cpu         = 0;
39 static int    vrate       = 0;
40 static int    arate       = 0;
41 static float  vquality    = -1.0;
42 static int    vbitrate    = 0;
43 static int    size        = 0;
44 static int    abitrate    = 0;
45 static int    mux         = 0;
46 static int    acodec      = 0;
47 static int    pixelratio  = 0;
48 static int    chapter_start = 0;
49 static int    chapter_end   = 0;
50 static int    chapter_markers = 0;
51 static char * marker_file   = NULL;
52 static int        crf                   = 0;
53 static char       *x264opts             = NULL;
54 static char       *x264opts2    = NULL;
55 static int        maxHeight             = 0;
56 static int        maxWidth              = 0;
57 static int    turbo_opts_enabled = 0;
58 static char * turbo_opts = "no-fast-pskip=0:subme=1:me=dia:trellis=0:analyse=none";
59
60 /* Exit cleanly on Ctrl-C */
61 static volatile int die = 0;
62 static void SigHandler( int );
63
64 /* Utils */
65 static void ShowCommands();
66 static void ShowHelp();
67 static int  ParseOptions( int argc, char ** argv );
68 static int  CheckOptions( int argc, char ** argv );
69 static int  HandleEvents( hb_handle_t * h );
70
71 int main( int argc, char ** argv )
72 {
73     hb_handle_t * h;
74     int           build;
75     char        * version;
76
77     /* Parse command line */
78     if( ParseOptions( argc, argv ) ||
79         CheckOptions( argc, argv ) )
80     {
81         return 1;
82     }
83
84     /* Init libhb */
85     h = hb_init( debug, update );
86
87     /* Show version */
88     fprintf( stderr, "HandBrake %s (%d) - http://handbrake.m0k.org/\n",
89              hb_get_version( h ), hb_get_build( h ) );
90
91     /* Check for update */
92     if( update )
93     {
94         if( ( build = hb_check_update( h, &version ) ) > -1 )
95         {
96             fprintf( stderr, "You are using an old version of "
97                      "HandBrake.\nLatest is %s (build %d).\n", version,
98                      build );
99         }
100         else
101         {
102             fprintf( stderr, "Your version of HandBrake is up to "
103                      "date.\n" );
104         }
105         hb_close( &h );
106         return 0;
107     }
108
109     /* Geeky */
110     fprintf( stderr, "%d CPU%s detected\n", hb_get_cpu_count(),
111              hb_get_cpu_count( h ) > 1 ? "s" : "" );
112     if( cpu )
113     {
114         fprintf( stderr, "Forcing %d CPU%s\n", cpu,
115                  cpu > 1 ? "s" : "" );
116         hb_set_cpu_count( h, cpu );
117     }
118
119     /* Exit ASAP on Ctrl-C */
120     signal( SIGINT, SigHandler );
121
122     /* Feed libhb with a DVD to scan */
123     fprintf( stderr, "Opening %s...\n", input );
124
125     if (longest_title) {
126         /*
127          * We need to scan for all the titles in order to find the longest
128          */
129         titleindex = 0;
130     }
131     hb_scan( h, input, titleindex );
132
133     /* Wait... */
134     while( !die )
135     {
136 #if !defined(SYS_BEOS)
137         fd_set         fds;
138         struct timeval tv;
139         int            ret;
140         char           buf[257];
141
142         tv.tv_sec  = 0;
143         tv.tv_usec = 100000;
144
145         FD_ZERO( &fds );
146         FD_SET( STDIN_FILENO, &fds );
147         ret = select( STDIN_FILENO + 1, &fds, NULL, NULL, &tv );
148
149         if( ret > 0 )
150         {
151             int size = 0;
152
153             while( size < 256 &&
154                    read( STDIN_FILENO, &buf[size], 1 ) > 0 )
155             {
156                 if( buf[size] == '\n' )
157                 {
158                     break;
159                 }
160                 size++;
161             }
162
163             if( size >= 256 || buf[size] == '\n' )
164             {
165                 switch( buf[0] )
166                 {
167                     case 'q':
168                         die = 1;
169                         break;
170                     case 'p':
171                         hb_pause( h );
172                         break;
173                     case 'r':
174                         hb_resume( h );
175                         break;
176                     case 'h':
177                         ShowCommands();
178                         break;
179                 }
180             }
181         }
182         hb_snooze( 200 );
183 #else
184         hb_snooze( 200 );
185 #endif
186
187         HandleEvents( h );
188     }
189
190     /* Clean up */
191     hb_close( &h );
192     if( input )  free( input );
193     if( output ) free( output );
194     if( format ) free( format );
195     if( audios ) free( audios );
196     if (native_language ) free (native_language );
197         if( x264opts ) free (x264opts );
198         if( x264opts2 ) free (x264opts2 );
199         
200     fprintf( stderr, "HandBrake has exited.\n" );
201
202     return 0;
203 }
204
205 static void ShowCommands()
206 {
207     fprintf( stderr, "Commands:\n" );
208     fprintf( stderr, " [h]elp    Show this message\n" );
209     fprintf( stderr, " [q]uit    Exit HandBrakeCLI\n" );
210     fprintf( stderr, " [p]ause   Pause encoding\n" );
211     fprintf( stderr, " [r]esume  Resume encoding\n" );
212 }
213
214 static void PrintTitleInfo( hb_title_t * title )
215 {
216     hb_chapter_t  * chapter;
217     hb_audio_t    * audio;
218     hb_subtitle_t * subtitle;
219     int i;
220
221     fprintf( stderr, "+ title %d:\n", title->index );
222     fprintf( stderr, "  + vts %d, ttn %d, cells %d->%d (%d blocks)\n",
223              title->vts, title->ttn, title->cell_start, title->cell_end,
224              title->block_count );
225     fprintf( stderr, "  + duration: %02d:%02d:%02d\n",
226              title->hours, title->minutes, title->seconds );
227     fprintf( stderr, "  + size: %dx%d, aspect: %.2f, %.3f fps\n",
228              title->width, title->height,
229              (float) title->aspect / HB_ASPECT_BASE,
230              (float) title->rate / title->rate_base );
231     fprintf( stderr, "  + autocrop: %d/%d/%d/%d\n", title->crop[0],
232              title->crop[1], title->crop[2], title->crop[3] );
233     fprintf( stderr, "  + chapters:\n" );
234     for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
235     {
236         chapter = hb_list_item( title->list_chapter, i );
237         fprintf( stderr, "    + %d: cells %d->%d, %d blocks, duration "
238                  "%02d:%02d:%02d\n", chapter->index,
239                  chapter->cell_start, chapter->cell_end,
240                  chapter->block_count, chapter->hours, chapter->minutes,
241                  chapter->seconds );
242     }
243     fprintf( stderr, "  + audio tracks:\n" );
244     for( i = 0; i < hb_list_count( title->list_audio ); i++ )
245     {
246         audio = hb_list_item( title->list_audio, i );
247         if( ( audio->codec & HB_ACODEC_AC3 ) || ( audio->codec & HB_ACODEC_DCA) )
248         {
249             fprintf( stderr, "    + %d, %s, %dHz, %dbps\n", i + 1,
250                      audio->lang, audio->rate, audio->bitrate );
251         }
252         else
253         {
254             fprintf( stderr, "    + %d, %s\n", i + 1, audio->lang );
255         }
256     }
257     fprintf( stderr, "  + subtitle tracks:\n" );
258     for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
259     {
260         subtitle = hb_list_item( title->list_subtitle, i );
261         fprintf( stderr, "    + %d, %s (iso639-2: %s)\n", i + 1, subtitle->lang,
262             subtitle->iso639_2);
263     }
264 }
265
266 static int HandleEvents( hb_handle_t * h )
267 {
268     hb_state_t s;
269     hb_get_state( h, &s );
270     switch( s.state )
271     {
272         case HB_STATE_IDLE:
273             /* Nothing to do */
274             break;
275
276 #define p s.param.scanning
277         case HB_STATE_SCANNING:
278             /* Show what title is currently being scanned */
279             fprintf( stderr, "Scanning title %d", p.title_cur );
280             if( !titleindex )
281                 fprintf( stderr, " of %d", p.title_count );
282             fprintf( stderr, "...\n" );
283             break;
284 #undef p
285
286         case HB_STATE_SCANDONE:
287         {
288             hb_list_t  * list;
289             hb_title_t * title;
290             hb_job_t   * job;
291
292             list = hb_get_titles( h );
293
294             if( !hb_list_count( list ) )
295             {
296                 /* No valid title, stop right there */
297                 fprintf( stderr, "No title found.\n" );
298                 die = 1;
299                 break;
300             }
301             if( longest_title )
302             {
303                 int i;
304                 int longest_title_idx=0;
305                 int longest_title_pos=-1;
306                 int longest_title_time=0;
307                 int title_time;
308                 
309                 fprintf( stderr, "Searching for longest title...\n" );
310
311                 for( i = 0; i < hb_list_count( list ); i++ )
312                 {
313                     title = hb_list_item( list, i );
314                     title_time = (title->hours*60*60 ) + (title->minutes *60) + (title->seconds);
315                     fprintf( stderr, " + Title (%d) index %d has length %dsec\n", 
316                              i, title->index, title_time );
317                     if( longest_title_time < title_time )
318                     {
319                         longest_title_time = title_time;
320                         longest_title_pos = i;
321                         longest_title_idx = title->index;
322                     }               
323                 }
324                 if( longest_title_pos == -1 ) 
325                 {
326                     fprintf( stderr, "No longest title found.\n" );
327                     die = 1;
328                     break;
329                 }
330                 titleindex = longest_title_idx;
331                 fprintf( stderr, "Found longest title, setting title to %d\n", 
332                          longest_title_idx);
333
334                 title = hb_list_item( list, longest_title_pos);
335             } else {
336                 title = hb_list_item( list, 0 );
337             }
338
339             if( !titleindex )
340             {
341                 /* Scan-only mode, print infos and exit */
342                 int i;
343                 for( i = 0; i < hb_list_count( list ); i++ )
344                 {
345                     title = hb_list_item( list, i );
346                     PrintTitleInfo( title );
347                 }
348                 die = 1;
349                 break;
350             }
351
352             /* Set job settings */
353             job   = title->job;
354
355             PrintTitleInfo( title );
356
357             if( chapter_start && chapter_end )
358             {
359                 job->chapter_start = MAX( job->chapter_start,
360                                           chapter_start );
361                 job->chapter_end   = MIN( job->chapter_end,
362                                           chapter_end );
363                 job->chapter_end   = MAX( job->chapter_start,
364                                           job->chapter_end );
365             }
366
367                         if ( chapter_markers )
368                         {
369                                 job->chapter_markers = chapter_markers;
370
371                 if( marker_file != NULL )
372                 {
373                     hb_csv_file_t * file = hb_open_csv_file( marker_file );
374                     hb_csv_cell_t * cell;
375                     int row = 0;
376                     int chapter = 0;
377                     
378                     fprintf( stderr, "Reading chapter markers from file %s\n", marker_file );
379                     
380                     if( file == NULL )
381                     {
382                          fprintf( stderr, "Cannot open chapter marker file, using defaults\n" );
383                     }
384                     else
385                     {
386                         /* Parse the cells */
387                         while( NULL != ( cell = hb_read_next_cell( file ) ) )
388                         {                            
389                             /* We have a chapter number */
390                             if( cell->cell_col == 0 )
391                             {
392                                 row = cell->cell_row;
393                                 chapter = atoi( cell->cell_text );
394                             }
395                              
396                             /* We have a chapter name */
397                             if( cell->cell_col == 1 && row == cell->cell_row )
398                             {
399                                 /* If we have a valid chapter, copy the string an terminate it */
400                                 if( chapter >= job->chapter_start && chapter <= job->chapter_end )
401                                 {
402                                     hb_chapter_t * chapter_s;
403                                     
404                                     chapter_s = hb_list_item( job->title->list_chapter, chapter - 1);
405                                     strncpy(chapter_s->title, cell->cell_text, 1023);
406                                     chapter_s->title[1023] = '\0';
407                                 }
408                             }                               
409                         
410                                                            
411                             hb_dispose_cell( cell );
412                         }
413                         
414                         hb_close_csv_file( file );
415                     }
416                 }
417                         }
418
419             if( crop[0] >= 0 && crop[1] >= 0 &&
420                 crop[2] >= 0 && crop[3] >= 0 )
421             {
422                 memcpy( job->crop, crop, 4 * sizeof( int ) );
423             }
424
425             job->deinterlace = deinterlace;
426             job->grayscale   = grayscale;
427             job->pixel_ratio = pixelratio;
428
429             if( width && height )
430             {
431                 job->width  = width;
432                 job->height = height;
433             }
434             else if( width )
435             {
436                 job->width = width;
437                 hb_fix_aspect( job, HB_KEEP_WIDTH );
438             }
439             else if( height )
440             {
441                 job->height = height;
442                 hb_fix_aspect( job, HB_KEEP_HEIGHT );
443             }
444             else if( !width && !height && !pixelratio )
445             {
446                 hb_fix_aspect( job, HB_KEEP_WIDTH );
447             }
448
449             if( vquality >= 0.0 && vquality <= 1.0 )
450             {
451                 job->vquality = vquality;
452                 job->vbitrate = 0;
453             }
454             else if( vbitrate )
455             {
456                 job->vquality = -1.0;
457                 job->vbitrate = vbitrate;
458             }
459             if( vcodec )
460             {
461                 job->vcodec = vcodec;
462             }
463             if( h264_13 ) 
464             { 
465                 job->h264_level = 13; 
466             }
467                 if( h264_30 )
468                 {
469                     job->h264_level = 30;
470             }
471             if( vrate )
472             {
473                 job->vrate = 27000000;
474                 job->vrate_base = vrate;
475             }
476             if( arate )
477             {
478                 job->arate = arate;
479             }
480
481             if( audios )
482             {
483                 if( strcasecmp( audios, "none" ) )
484                 {
485                     int    audio_count = 0;
486                     char * tmp         = audios;
487                     while( *tmp )
488                     {
489                         if( *tmp < '0' || *tmp > '9' )
490                         {
491                             /* Skip non numeric char */
492                             tmp++;
493                             continue;
494                         }
495                                                 job->audio_mixdowns[audio_count] = audio_mixdown;
496                         job->audios[audio_count++] =
497                             strtol( tmp, &tmp, 0 ) - 1;
498                     }
499                     job->audios[audio_count] = -1;
500                 }
501                 else
502                 {
503                     job->audios[0] = -1;
504                 }
505             }
506                         else
507                         {
508                             /* default to the first audio track if none has been specified */
509                             job->audios[0] = 0;
510                             job->audio_mixdowns[0] = audio_mixdown;
511                         }
512             if( abitrate )
513             {
514                 job->abitrate = abitrate;
515             }
516             if( acodec )
517             {
518                 job->acodec = acodec;
519             }
520
521             if( size )
522             {
523                 job->vbitrate = hb_calc_bitrate( job, size );
524                 fprintf( stderr, "Calculated bitrate: %d kbps\n",
525                          job->vbitrate );
526             }
527
528             if( sub )
529             {
530                 job->subtitle = sub - 1;
531             }
532
533             if( native_language )
534             {
535                 job->native_language = strdup( native_language );
536             }
537
538             if( job->mux )
539             {
540                 job->mux = mux;
541             }
542             job->file = strdup( output );
543
544             if( crf )
545             {
546                 job->crf = 1;
547             }
548
549             if( x264opts != NULL && *x264opts != '\0' )
550             {
551                 fprintf( stderr, "Applying the following x264 options: %s\n", 
552                          x264opts);
553                 job->x264opts = x264opts;
554             }
555             else /*avoids a bus error crash when options aren't specified*/
556             {
557                 job->x264opts =  NULL;
558             }
559             if (maxWidth)
560                 job->maxWidth = maxWidth;
561             if (maxHeight)
562                 job->maxHeight = maxHeight;
563                                 
564             if( twoPass )
565             {
566                 /*
567                  * If subtitle_scan is enabled then only turn it on
568                  * for the first pass and then off again for the
569                  * second. 
570                  */
571                 job->pass = 1;
572                 job->subtitle_scan = subtitle_scan;
573                 if( subtitle_scan ) 
574                 {
575                     fprintf( stderr, "Subtitle Scan Enabled - enabling "
576                              "subtitles if found for foreign language segments\n");
577                     job->select_subtitle = malloc(sizeof(hb_subtitle_t*));
578                     *(job->select_subtitle) = NULL;
579                 } 
580
581                 /*
582                  * If turbo options have been selected then append them
583                  * to the x264opts now (size includes one ':' and the '\0')
584                  */
585                 if( turbo_opts_enabled ) 
586                 {
587                     int size = strlen(x264opts) + strlen(turbo_opts) + 2;
588                     char *tmp_x264opts;
589                         
590                     tmp_x264opts = malloc(size * sizeof(char));
591                     if( x264opts ) 
592                     {
593                         snprintf( tmp_x264opts, size, "%s:%s", 
594                                   x264opts, turbo_opts );  
595                         free( x264opts );
596                     } else {
597                         /*
598                          * No x264opts to modify, but apply the turbo options
599                          * anyway as they may be modifying defaults
600                          */
601                         snprintf( tmp_x264opts, size, "%s", 
602                                   turbo_opts );
603                     }
604                     x264opts = tmp_x264opts;
605
606                     fprintf( stderr, "Modified x264 options for pass 1 to append turbo options: %s\n",
607                              x264opts );
608
609                     job->x264opts = x264opts;
610                 }     
611                 hb_add( h, job );
612                 job->pass = 2;
613                 /*
614                  * On the second pass we turn off subtitle scan so that we
615                  * can actually encode using any subtitles that were auto
616                  * selected in the first pass (using the whacky select-subtitle
617                  * attribute of the job).
618                  */
619                 job->subtitle_scan = 0;
620
621                 job->x264opts = x264opts2;
622                 
623                 hb_add( h, job );
624             }
625             else
626             {
627                 /*
628                  * Turn on subtitle scan if requested, note that this option
629                  * precludes encoding of any actual subtitles.
630                  */
631                 job->subtitle_scan = subtitle_scan;
632                 if ( subtitle_scan ) 
633                 {
634                     fprintf( stderr, "Subtitle Scan Enabled, will scan all "
635                              "subtitles matching the audio language for any\n"
636                              "that meet our auto-selection criteria.\n");
637                 }
638                 job->pass = 0;
639                 hb_add( h, job );
640             }
641             hb_start( h );
642             break;
643         }
644
645 #define p s.param.working
646         case HB_STATE_WORKING:
647             fprintf( stderr, "\rEncoding: task %d of %d, %.2f %%",
648                      p.job_cur, p.job_count, 100.0 * p.progress );
649             if( p.seconds > -1 )
650             {
651                 fprintf( stderr, " (%.2f fps, avg %.2f fps, ETA "
652                          "%02dh%02dm%02ds)", p.rate_cur, p.rate_avg,
653                          p.hours, p.minutes, p.seconds );
654             }
655             break;
656 #undef p
657
658 #define p s.param.muxing
659         case HB_STATE_MUXING:
660         {
661             fprintf( stderr, "\rMuxing: %.2f %%", 100.0 * p.progress );
662             break;
663         }
664 #undef p
665
666 #define p s.param.workdone
667         case HB_STATE_WORKDONE:
668             /* Print error if any, then exit */
669             switch( p.error )
670             {
671                 case HB_ERROR_NONE:
672                     fprintf( stderr, "\nRip done!\n" );
673                     break;
674                 case HB_ERROR_CANCELED:
675                     fprintf( stderr, "\nRip canceled.\n" );
676                     break;
677                 default:
678                     fprintf( stderr, "\nRip failed (error %x).\n",
679                              p.error );
680             }
681             die = 1;
682             break;
683 #undef p
684     }
685     return 0;
686 }
687
688 /****************************************************************************
689  * SigHandler:
690  ****************************************************************************/
691 static volatile int64_t i_die_date = 0;
692 void SigHandler( int i_signal )
693 {
694     if( die == 0 )
695     {
696         die = 1;
697         i_die_date = hb_get_date();
698         fprintf( stderr, "Signal %d received, terminating - do it "
699                  "again in case it gets stuck\n", i_signal );
700     }
701     else if( i_die_date + 500 < hb_get_date() )
702     {
703         fprintf( stderr, "Dying badly, files might remain in your /tmp\n" );
704         exit( 1 );
705     }
706 }
707
708 /****************************************************************************
709  * ShowHelp:
710  ****************************************************************************/
711 static void ShowHelp()
712 {
713     int i;
714     
715     fprintf( stderr,
716     "Syntax: HandBrakeCLI [options] -i <device> -o <file>\n"
717     "\n"
718         "### General Handbrake Options------------------------------------------------\n\n"
719     "    -h, --help              Print help\n"
720     "    -u, --update            Check for updates and exit\n"
721     "    -v, --verbose           Be verbose\n"
722     "    -C, --cpu               Set CPU count (default: autodetected)\n"
723     "\n"
724         
725         "### Source Options-----------------------------------------------------------\n\n"
726         "    -i, --input <string>    Set input device\n"
727         "    -t, --title <number>    Select a title to encode (0 to scan only,\n"
728     "                            default: 1)\n"
729     "    -L, --longest           Select the longest title\n"
730     "    -c, --chapters <string> Select chapters (e.g. \"1-3\" for chapters\n"
731     "                            1 to 3, or \"3\" for chapter 3 only,\n"
732     "                            default: all chapters)\n"
733         "\n"
734         
735         "### Destination Options------------------------------------------------------\n\n"
736     "    -o, --output <string>   Set output file name\n"
737         "    -f, --format <string>   Set output format (avi/mp4/ogm, default:\n"
738     "                            autodetected from file name)\n"
739     "\n"
740         
741         "### Picture Settings---------------------------------------------------------\n\n"
742     "    -w, --width <number>    Set picture width\n"
743     "    -l, --height <number>   Set picture height\n"
744     "        --crop <T:B:L:R>    Set cropping values (default: autocrop)\n"
745         "    -Y, --maxHeight <#>     Set maximum height\n"
746         "    -X, --maxWidth <#>      Set maximum width\n"
747         "    -s, --subtitle <number> Select subtitle (default: none)\n"
748     "    -U, --subtitle-scan     Scan for subtitles on the first pass, and choose\n"
749     "                            the one that's only used 20 percent of the time\n"
750     "                            or less. This should locate subtitles for short\n"
751     "                            foreign language segments. Only works with 2-pass.\n"
752     "    -N, --native-language   Select subtitles with this language if it does not\n"
753     "          <string>          match the Audio language. Provide the language's\n"
754     "                            iso639-2 code (fre, eng, spa, dut, et cetera)\n"
755         "    -m, --markers           Add chapter markers (mp4 output format only)\n"
756         "\n"
757         
758         "### Video Options------------------------------------------------------------\n\n"
759         "    -e, --encoder <string>  Set video library encoder (ffmpeg,xvid,\n"
760     "                            x264,x264b13,x264b30 default: ffmpeg)\n"
761         "    -q, --quality <float>   Set video quality (0.0..1.0)\n"
762         "    -Q, --crf               Use with -q for CRF instead of CQP\n"
763     "    -S, --size <MB>         Set target size\n"
764         "    -b, --vb <kb/s>         Set video bitrate (default: 1000)\n"
765         "    -r, --rate              Set video framerate (" );
766     for( i = 0; i < hb_video_rates_count; i++ )
767     {
768         fprintf( stderr, hb_video_rates[i].string );
769         if( i != hb_video_rates_count - 1 )
770             fprintf( stderr, "/" );
771     }
772     fprintf( stderr, ")\n"
773         "\n"
774         "    -2, --two-pass          Use two-pass mode\n"
775     "    -d, --deinterlace       Deinterlace video\n"
776     "    -g, --grayscale         Grayscale encoding\n"
777     "    -p, --pixelratio        Store pixel aspect ratio in video stream\n"
778         
779         "\n"
780         
781         
782         "### Audio Options-----------------------------------------------------------\n\n"
783         "    -E, --aencoder <string> Set audio encoder (faac/lame/vorbis/ac3, ac3\n"
784     "                            meaning passthrough, default: guessed)\n"
785         "    -B, --ab <kb/s>         Set audio bitrate (default: 128)\n"
786         "    -a, --audio <string>    Select audio channel(s) (\"none\" for no \n"
787     "                            audio, default: first one)\n"
788     "    -6, --mixdown <string>  Format for surround sound downmixing\n"
789     "                            (mono/stereo/dpl1/dpl2/6ch, default: dpl2)\n"
790     "    -R, --arate             Set audio samplerate (" );
791     for( i = 0; i < hb_audio_rates_count; i++ )
792     {
793         fprintf( stderr, hb_audio_rates[i].string );
794         if( i != hb_audio_rates_count - 1 )
795             fprintf( stderr, "/" );
796     }
797     fprintf( stderr, " kHz)\n"
798    
799     
800         
801         "\n"
802         
803         
804     "### Advanced H264 Options----------------------------------------------------\n\n"
805     "    -x, --x264opts <string> Specify advanced x264 options in the\n"
806     "                            same style as mencoder:\n"
807     "                            option1=value1:option2=value2\n"
808     "    -T, --turbo             When using 2-pass use the turbo options\n"
809     "                            on the first pass to improve speed\n"
810     "                            (only works with x264, affects PSNR by about 0.05dB,\n"
811     "                            and increases first pass speed two to four times)\n");
812 }
813
814 /****************************************************************************
815  * ParseOptions:
816  ****************************************************************************/
817 static int ParseOptions( int argc, char ** argv )
818 {
819     for( ;; )
820     {
821         static struct option long_options[] =
822           {
823             { "help",        no_argument,       NULL,    'h' },
824             { "update",      no_argument,       NULL,    'u' },
825             { "verbose",     no_argument,       NULL,    'v' },
826             { "cpu",         required_argument, NULL,    'C' },
827
828             { "format",      required_argument, NULL,    'f' },
829             { "input",       required_argument, NULL,    'i' },
830             { "output",      required_argument, NULL,    'o' },
831
832             { "title",       required_argument, NULL,    't' },
833             { "longest",     no_argument,       NULL,    'L' },
834             { "chapters",    required_argument, NULL,    'c' },
835             { "markers",     optional_argument, NULL,    'm' },
836             { "audio",       required_argument, NULL,    'a' },
837             { "mixdown",     required_argument, NULL,    '6' },
838             { "subtitle",    required_argument, NULL,    's' },
839             { "subtitle-scan", no_argument,     NULL,    'U' },
840             { "native-language", required_argument, NULL,'N' },
841
842             { "encoder",     required_argument, NULL,    'e' },
843             { "aencoder",    required_argument, NULL,    'E' },
844             { "two-pass",    no_argument,       NULL,    '2' },
845             { "deinterlace", no_argument,       NULL,    'd' },
846             { "grayscale",   no_argument,       NULL,    'g' },
847             { "pixelratio",  no_argument,       NULL,    'p' },
848             { "width",       required_argument, NULL,    'w' },
849             { "height",      required_argument, NULL,    'l' },
850             { "crop",        required_argument, NULL,    'n' },
851
852             { "vb",          required_argument, NULL,    'b' },
853             { "quality",     required_argument, NULL,    'q' },
854             { "size",        required_argument, NULL,    'S' },
855             { "ab",          required_argument, NULL,    'B' },
856             { "rate",        required_argument, NULL,    'r' },
857             { "arate",       required_argument, NULL,    'R' },
858             { "crf",         no_argument,       NULL,    'Q' },
859             { "x264opts",    required_argument, NULL,    'x' },
860             { "turbo",       no_argument,       NULL,    'T' },
861             
862             { "maxHeight",   required_argument, NULL,    'Y' },
863             { "maxWidth",    required_argument, NULL,    'X' },
864                         
865             { 0, 0, 0, 0 }
866           };
867
868         int option_index = 0;
869         int c;
870
871         c = getopt_long( argc, argv,
872                          "hvuC:f:i:o:t:Lc:ma:6:s:UN:e:E:2dgpw:l:n:b:q:S:B:r:R:Qx:TY:X:",
873                          long_options, &option_index );
874         if( c < 0 )
875         {
876             break;
877         }
878
879         switch( c )
880         {
881             case 'h':
882                 ShowHelp();
883                 exit( 0 );
884             case 'u':
885                 update = 1;
886                 break;
887             case 'v':
888                 debug = HB_DEBUG_ALL;
889                 break;
890             case 'C':
891                 cpu = atoi( optarg );
892                 break;
893
894             case 'f':
895                 format = strdup( optarg );
896                 break;
897             case 'i':
898                 input = strdup( optarg );
899                 break;
900             case 'o':
901                 output = strdup( optarg );
902                 break;
903
904             case 't':
905                 titleindex = atoi( optarg );
906                 break;
907             case 'L':
908                 longest_title = 1;
909                 break;
910             case 'c':
911             {
912                 int start, end;
913                 if( sscanf( optarg, "%d-%d", &start, &end ) == 2 )
914                 {
915                     chapter_start = start;
916                     chapter_end   = end;
917                 }
918                 else if( sscanf( optarg, "%d", &start ) == 1 )
919                 {
920                     chapter_start = start;
921                     chapter_end   = chapter_start;
922                 }
923                 else
924                 {
925                     fprintf( stderr, "chapters: invalid syntax (%s)\n",
926                              optarg );
927                     return -1;
928                 }
929                 break;
930             }
931             case 'm':
932                 if( optarg != NULL )
933                 {
934                     marker_file = strdup( optarg );
935                 }
936                 chapter_markers = 1;
937                 break;
938             case 'a':
939                 audios = strdup( optarg );
940                 break;
941             case '6':
942                 if( !strcasecmp( optarg, "mono" ) )
943                 {
944                     audio_mixdown = HB_AMIXDOWN_MONO;
945                 }
946                 else if( !strcasecmp( optarg, "stereo" ) )
947                 {
948                     audio_mixdown = HB_AMIXDOWN_STEREO;
949                 }
950                 else if( !strcasecmp( optarg, "dpl1" ) )
951                 {
952                     audio_mixdown = HB_AMIXDOWN_DOLBY;
953                 }
954                 else if( !strcasecmp( optarg, "dpl2" ) )
955                 {
956                     audio_mixdown = HB_AMIXDOWN_DOLBYPLII;
957                                 }
958                 else if( !strcasecmp( optarg, "6ch" ) )
959                 {
960                     audio_mixdown = HB_AMIXDOWN_6CH;
961                 }
962                 break;
963             case 's':
964                 sub = atoi( optarg );
965                 break;
966             case 'U':
967                 subtitle_scan = 1;
968                 break;
969             case 'N':
970                 native_language = strdup( optarg );
971                 break;
972             case '2':
973                 twoPass = 1;
974                 break;
975             case 'd':
976                 deinterlace = 1;
977                 break;
978             case 'g':
979                 grayscale = 1;
980                 break;
981             case 'p':
982                 pixelratio = 1;
983                 break;
984             case 'e':
985                 if( !strcasecmp( optarg, "ffmpeg" ) )
986                 {
987                     vcodec = HB_VCODEC_FFMPEG;
988                 }
989                 else if( !strcasecmp( optarg, "xvid" ) )
990                 {
991                     vcodec = HB_VCODEC_XVID;
992                 }
993                 else if( !strcasecmp( optarg, "x264" ) )
994                 {
995                     vcodec = HB_VCODEC_X264;
996                 }
997                 else if( !strcasecmp( optarg, "x264b13" ) )
998                 {
999                     vcodec = HB_VCODEC_X264;
1000                     h264_13 = 1;
1001                 }
1002                 else if( !strcasecmp( optarg, "x264b30" ) )
1003                 {
1004                     vcodec = HB_VCODEC_X264;
1005                     h264_30 = 1;
1006                 }
1007                 else
1008                 {
1009                     fprintf( stderr, "invalid codec (%s)\n", optarg );
1010                     return -1;
1011                 }
1012                 break;
1013             case 'E':
1014                 if( !strcasecmp( optarg, "ac3" ) )
1015                 {
1016                     acodec = HB_ACODEC_AC3;
1017                 }
1018                 else if( !strcasecmp( optarg, "lame" ) )
1019                 {
1020                     acodec = HB_ACODEC_LAME;
1021                 }
1022                 break;
1023             case 'w':
1024                 width = atoi( optarg );
1025                 break;
1026             case 'l':
1027                 height = atoi( optarg );
1028                 break;
1029             case 'n':
1030             {
1031                 int    i;
1032                 char * tmp = optarg;
1033                 for( i = 0; i < 4; i++ )
1034                 {
1035                     if( !*tmp )
1036                         break;
1037                     crop[i] = strtol( tmp, &tmp, 0 );
1038                     tmp++;
1039                 }
1040                 break;
1041             }
1042             case 'r':
1043             {
1044                 int i;
1045                 vrate = 0;
1046                 for( i = 0; i < hb_video_rates_count; i++ )
1047                 {
1048                     if( !strcmp( optarg, hb_video_rates[i].string ) )
1049                     {
1050                         vrate = hb_video_rates[i].rate;
1051                         break;
1052                     }
1053                 }
1054                 if( !vrate )
1055                 {
1056                     fprintf( stderr, "invalid framerate %s\n", optarg );
1057                 }
1058                 break;
1059             }
1060             case 'R':
1061             {
1062                 int i;
1063                 arate = 0;
1064                 for( i = 0; i < hb_audio_rates_count; i++ )
1065                 {
1066                     if( !strcmp( optarg, hb_audio_rates[i].string ) )
1067                     {
1068                         arate = hb_audio_rates[i].rate;
1069                         break;
1070                     }
1071                 }
1072                 if( !arate )
1073                 {
1074                     fprintf( stderr, "invalid framerate %s\n", optarg );
1075                 }
1076                 break;
1077             }
1078             case 'b':
1079                 vbitrate = atoi( optarg );
1080                 break;
1081             case 'q':
1082                 vquality = atof( optarg );
1083                 break;
1084             case 'S':
1085                 size = atoi( optarg );
1086                 break;
1087             case 'B':
1088                 abitrate = atoi( optarg );
1089                 break;
1090             case 'Q':
1091                 crf = 1;
1092                 break;
1093             case 'x':
1094                 x264opts = strdup( optarg );
1095                 x264opts2 = strdup( optarg );
1096                 break;
1097             case 'T':
1098                 turbo_opts_enabled = 1;
1099                 break;
1100             case 'Y':
1101                 maxHeight = atoi( optarg );
1102                 break;
1103             case 'X':
1104                 maxWidth = atoi (optarg );
1105                 break;
1106                                 
1107             default:
1108                 fprintf( stderr, "unknown option (%s)\n", argv[optind] );
1109                 return -1;
1110         }
1111     }
1112
1113     return 0;
1114 }
1115
1116 static int CheckOptions( int argc, char ** argv )
1117 {
1118     if( update )
1119     {
1120         return 0;
1121     }
1122
1123     if( input == NULL || *input == '\0' )
1124     {
1125         fprintf( stderr, "Missing input device. Run %s --help for "
1126                  "syntax.\n", argv[0] );
1127         return 1;
1128     }
1129
1130     /* Parse format */
1131     if( titleindex > 0 )
1132     {
1133         if( output == NULL || *output == '\0' )
1134         {
1135             fprintf( stderr, "Missing output file name. Run %s --help "
1136                      "for syntax.\n", argv[0] );
1137             return 1;
1138         }
1139
1140         if( !format )
1141         {
1142             char * p = strrchr( output, '.' );
1143
1144             /* autodetect */
1145             if( p && !strcasecmp( p, ".avi" ) )
1146             {
1147                 mux = HB_MUX_AVI;
1148             }
1149             else if( p && ( !strcasecmp( p, ".mp4" )  ||
1150                                                         !strcasecmp( p, ".m4v" ) ) )
1151             {
1152                 if ( h264_30 == 1 )
1153                     mux = HB_MUX_IPOD;
1154                 else
1155                     mux = HB_MUX_MP4;
1156             }
1157             else if( p && ( !strcasecmp( p, ".ogm" ) ||
1158                             !strcasecmp( p, ".ogg" ) ) )
1159             {
1160                 mux = HB_MUX_OGM;
1161             }
1162             else
1163             {
1164                 fprintf( stderr, "Output format couldn't be guessed "
1165                          "from file name, using default.\n" );
1166                 return 0;
1167             }
1168         }
1169         else if( !strcasecmp( format, "avi" ) )
1170         {
1171             mux = HB_MUX_AVI;
1172         }
1173         else if( !strcasecmp( format, "mp4" ) )
1174         {
1175             if ( h264_30 == 1)
1176                 mux = HB_MUX_IPOD;
1177             else
1178                 mux = HB_MUX_MP4;
1179         }
1180         else if( !strcasecmp( format, "ogm" ) ||
1181                  !strcasecmp( format, "ogg" ) )
1182         {
1183             mux = HB_MUX_OGM;
1184         }
1185         else
1186         {
1187             fprintf( stderr, "Invalid output format (%s). Possible "
1188                      "choices are avi, mp4 and ogm\n.", format );
1189             return 1;
1190         }
1191
1192         if( !acodec )
1193         {
1194             if( mux == HB_MUX_MP4 || mux == HB_MUX_IPOD )
1195             {
1196                 acodec = HB_ACODEC_FAAC;
1197             }
1198             else if( mux == HB_MUX_AVI )
1199             {
1200                 acodec = HB_ACODEC_LAME;
1201             }
1202             else if( mux == HB_MUX_OGM )
1203             {
1204                 acodec = HB_ACODEC_VORBIS;
1205             }
1206         }
1207
1208     }
1209
1210     return 0;
1211 }
1212