OSDN Git Service

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