OSDN Git Service

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