OSDN Git Service

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