OSDN Git Service

1a693fde7bc22188bd1b58397be1ba59f0b1212b
[handbrake-jp/handbrake-jp-git.git] / test / test.c
1 /* $Id: test.c,v 1.26 2004/01/22 19:36:55 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
10 #include "HandBrake.h"
11
12 /* Options */
13 static int    verbose     = 0;
14 static char * input       = NULL;
15 static char * output      = NULL;
16 static char * format      = NULL;
17 static int    titleindex  = 1;
18 static int    twoPass     = 0;
19 static int    deinterlace = 0;
20 static int    vcodec      = HB_CODEC_FFMPEG;
21 static char * audios      = NULL;
22 static int    width       = 0;
23 static int    top         = 0;
24 static int    bottom      = 0;
25 static int    left        = 0;
26 static int    right       = 0;
27 static int    autocrop    = 0;
28 static int    cpu         = 0;
29 static int    vbitrate    = 1024;
30 static int    size        = 0;
31 static int    abitrate    = 128;
32 static int    mux         = 0;
33 static int    acodec      = 0;
34
35 /* Exit cleanly on Ctrl-C */
36 static volatile int die = 0;
37 static void SigHandler( int );
38
39 /* Utils */
40 static void ShowHelp();
41 static int  ParseOptions( int argc, char ** argv );
42 static int  CheckOptions( int argc, char ** argv );
43
44 /* libhb callbacks */
45 static void Scanning( void * data, int title, int titleCount );
46 static void ScanDone( void * data, HBList * titleList );
47 static void Encoding( void * data, float position, int pass,
48                       int passCount, float frameRate,
49                       float avgFrameRate, int remainingTime );
50 static void RipDone( void * data, int result );
51
52 int main( int argc, char ** argv )
53 {
54     HBHandle    * h;
55     HBCallbacks   callbacks;
56
57     fprintf( stderr, "HandBrake " HB_VERSION
58              " - http://handbrake.m0k.org/\n" );
59
60     if( ParseOptions( argc, argv ) ||
61         CheckOptions( argc, argv ) )
62     {
63         return 1;
64     }
65
66     /* Exit ASAP on Ctrl-C */
67     signal( SIGINT, SigHandler );
68
69     /* Init libhb */
70     h = HBInit( verbose, cpu );
71
72     /* Set libhb callbacks */
73     callbacks.data     = h;
74     callbacks.scanning = Scanning;
75     callbacks.scanDone = ScanDone;
76     callbacks.encoding = Encoding;
77     callbacks.ripDone  = RipDone;
78     HBSetCallbacks( h, callbacks );
79
80     /* Feed libhb with a DVD to scan */
81     fprintf( stderr, "Opening %s...\n", input );
82     HBScanDVD( h, input, titleindex );
83
84     /* Wait... */
85     while( !die )
86     {
87         HBSnooze( 500000 );
88     }
89
90     /* Clean up */
91     HBClose( &h );
92
93     fprintf( stderr, "HandBrake has exited cleanly.\n" );
94
95     return 0;
96 }
97
98 /****************************************************************************
99  * SigHandler:
100  ****************************************************************************/
101 static volatile int64_t i_die_date = 0;
102 void SigHandler( int i_signal )
103 {
104     if( die == 0 )
105     {
106         i_die_date = HBGetDate();
107         fprintf( stderr, "Signal %d received, terminating - do it "
108                  "again in case it gets stuck\n", i_signal );
109     }
110     else if( i_die_date + 500000 < HBGetDate() )
111     {
112         fprintf( stderr, "Dying badly, files might remain in your /tmp\n" );
113         exit( 1 );
114     }
115     die = 1;
116 }
117
118 /****************************************************************************
119  * ShowHelp:
120  ****************************************************************************/
121 static void ShowHelp()
122 {
123     fprintf( stderr,
124     "Syntax: HBTest [options] -i <device> -o <file>\n"
125     "\n"
126     "    -h, --help            Print help\n"
127     "    -v, --verbose         Be verbose\n"
128     "    -C, --cpu             Set CPU count (default: autodetected)\n"
129     "\n"
130     "    -f, --format <string> Set output format (avi/mp4/ogm, default:\n"
131     "                          autodetected)\n"
132     "    -i, --input <string>  Set input device\n"
133     "    -o, --output <string> Set output file name\n"
134     "\n"
135     "        --scan            Only scan the device\n"
136     "    -t, --title <number>  Select a title to encode (0 to scan only,\n"
137     "                          default: 1)\n"
138     "    -a, --audio <string>  Select audio channel(s) (none for no audio,\n"
139     "                          default: first one)\n"
140     "        --noaudio         Disable audio\n"
141     "\n"
142     "    -c, --codec <string>  Set video library encoder (ffmpeg/xvid/x264,\n"
143     "                          default: ffmpeg)\n"
144     "    -2, --two-pass        Use two-pass mode\n"
145     "    -d, --deinterlace     Deinterlace video\n"
146     "\n"
147     "    -b, --vb <kb/s>       Set video bitrate (default: 1024)\n"
148     "    -s, --size <MB>       Set target size instead of bitrate\n"
149     "    -B, --ab <kb/s>       Set audio bitrate (default: 128)\n"
150     "    -w, --width <number>  Set picture width\n"
151     "        --crop <T:B:L:R>  Set cropping values\n"
152     "        --autocrop        Use autodetected cropping values\n" );
153 }
154
155
156 /****************************************************************************
157  * ParseOptions:
158  ****************************************************************************/
159 static int ParseOptions( int argc, char ** argv )
160 {
161     for( ;; )
162     {
163         static struct option long_options[] =
164           {
165             { "help",        no_argument,       NULL,    'h' },
166             { "verbose",     no_argument,       NULL,    'v' },
167             { "cpu",         required_argument, NULL,    'C' },
168
169             { "format",      required_argument, NULL,    'f' },
170             { "input",       required_argument, NULL,    'i' },
171             { "output",      required_argument, NULL,    'o' },
172
173             { "scan",        no_argument,       NULL,    'S' },
174             { "title",       required_argument, NULL,    't' },
175             { "audio",       required_argument, NULL,    'a' },
176             { "noaudio",     no_argument,       NULL,    'a' },
177
178             { "codec",       required_argument, NULL,    'c' },
179             { "two-pass",    no_argument,       NULL,    '2' },
180             { "deinterlace", no_argument,       NULL,    'd' },
181             { "width",       required_argument, NULL,    'w' },
182             { "crop",        required_argument, NULL,    'n' },
183             { "autocrop",    no_argument,       NULL,    'z' },
184
185             { "vb",          required_argument, NULL,    'b' },
186             { "size",        required_argument, NULL,    's' },
187             { "ab",          required_argument, NULL,    'B' },
188
189             { 0, 0, 0, 0 }
190           };
191
192         int option_index = 0;
193         int c;
194
195         c = getopt_long( argc, argv, "hvC:f:i:o:St:a:c:2dw:n:zb:s:B:",
196                          long_options, &option_index );
197         if( c < 0 )
198         {
199             break;
200         }
201
202         switch( c )
203         {
204             case 'h':
205                 ShowHelp();
206                 exit( 0 );
207             case 'v':
208                 verbose = 1;
209                 break;
210             case 'C':
211                 cpu = atoi( optarg );
212                 break;
213
214             case 'f':
215                 format = strdup( optarg );
216                 break;
217             case 'i':
218                 input = strdup( optarg );
219                 break;
220             case 'o':
221                 output = strdup( optarg );
222                 break;
223
224             case 'S':
225                 titleindex = 0;
226                 break;
227             case 't':
228                 titleindex = atoi( optarg );
229                 break;
230             case 'a':
231                 audios = strdup( optarg ? optarg : "none" );
232                 break;
233
234             case '2':
235                 twoPass = 1;
236                 break;
237             case 'd':
238                 deinterlace = 1;
239                 break;
240             case 'c':
241                 if( !strcasecmp( optarg, "ffmpeg" ) )
242                 {
243                     vcodec = HB_CODEC_FFMPEG;
244                 }
245                 else if( !strcasecmp( optarg, "xvid" ) )
246                 {
247                     vcodec = HB_CODEC_XVID;
248                 }
249                 else if( !strcasecmp( optarg, "x264" ) )
250                 {
251                     vcodec = HB_CODEC_X264;
252                 }
253                 else
254                 {
255                     fprintf( stderr, "invalid codec (%s)\n", optarg );
256                     return -1;
257                 }
258                 break;
259             case 'w':
260                 width = atoi( optarg );
261                 break;
262             case 'n':
263             {
264                 char * crop = strdup( optarg );
265                 char * _2be3 = crop;
266
267                 if( *crop )
268                 {
269                     top = strtol( crop, &crop, 0 ); crop++;
270                 }
271                 if( *crop )
272                 {
273                     bottom = strtol( crop, &crop, 0 ); crop++;
274                 }
275                 if( *crop )
276                 {
277                     left = strtol( crop, &crop, 0 ); crop++;
278                 }
279                 if( *crop )
280                 {
281                     right = strtol( crop, &crop, 0 ); crop++;
282                 }
283
284                 free( _2be3 );
285                 break;
286             }
287             case 'z':
288                autocrop = 1;
289                break;
290
291             case 'b':
292                 vbitrate = atoi( optarg );
293                 break;
294             case 's':
295                 size = atoi( optarg );
296                 break;
297             case 'B':
298                 abitrate = atoi( optarg );
299                 break;
300
301             default:
302                 fprintf( stderr, "unknown option (%s)\n", argv[optind] );
303                 return -1;
304         }
305     }
306
307     return 0;
308 }
309
310 static int CheckOptions( int argc, char ** argv )
311 {
312     if( input == NULL || *input == '\0' )
313     {
314         fprintf( stderr, "Missing input device. Run %s --help for "
315                  "syntax.\n", argv[0] );
316         return 1;
317     }
318
319     /* Parse format */
320     if( titleindex > 0 )
321     {
322         if( output == NULL || *output == '\0' )
323         {
324             fprintf( stderr, "Missing output file name. Run %s --help "
325                      "for syntax.\n", argv[0] );
326             return 1;
327         }
328
329         if( !format )
330         {
331             char *p = strrchr( output, '.' );
332             /* autodetect */
333             if( p && !strcasecmp( p, ".avi" ) )
334             {
335                 mux = HB_MUX_AVI;
336             }
337             else if( p && !strcasecmp( p, ".mp4" ) )
338             {
339                 mux = HB_MUX_MP4;
340             }
341             else if( p && ( !strcasecmp( p, ".ogm" ) ||
342                             !strcasecmp( p, ".ogg" ) ) )
343             {
344                 mux = HB_MUX_OGM;
345             }
346
347             else
348             {
349                 fprintf( stderr, "Output format couldn't be guessed "
350                          "from file name, please use --format.\n" );
351                 return 1;
352             }
353         }
354         else if( !strcasecmp( format, "avi" ) )
355         {
356             mux = HB_MUX_AVI;
357         }
358         else if( !strcasecmp( format, "mp4" ) )
359         {
360             mux = HB_MUX_MP4;
361         }
362         else if( !strcasecmp( format, "ogm" ) ||
363                  !strcasecmp( format, "ogg" ) )
364         {
365             mux = HB_MUX_OGM;
366         }
367         else
368         {
369             fprintf( stderr, "Invalid output format (%s). Possible "
370                      "choices are avi, mp4 and ogm\n.", format );
371             return 1;
372         }
373         if( mux == HB_MUX_MP4 )
374         {
375             acodec = HB_CODEC_AAC;
376         }
377         else if( mux == HB_MUX_AVI )
378         {
379             acodec = HB_CODEC_MP3;
380         }
381         else if( mux == HB_MUX_OGM )
382         {
383             acodec = HB_CODEC_VORBIS;
384         }
385     }
386
387     return 0;
388 }
389
390 static void Scanning( void * data, int title, int titleCount )
391 {
392     if( titleindex )
393     {
394         fprintf( stderr, "Scanning title %d...\n", title );
395     }
396     else
397     {
398         fprintf( stderr, "Scanning title %d/%d...\n", title, titleCount );
399     }
400 }
401
402 static void ScanDone( void * data, HBList * titleList )
403 {
404     HBHandle * h = (HBHandle*) data;
405     HBAudio  * audio;
406     HBTitle  * title;
407
408     if( !titleList )
409     {
410         fprintf( stderr, "No title found. Invalid device?\n" );
411         die = 1;
412         return;
413     }
414     if( !titleindex )
415     {
416         die = 1;
417         return;
418     }
419
420     title = HBListItemAt( titleList, 0 );
421     title->file = strdup( output );
422     title->twoPass = twoPass;
423     title->deinterlace = deinterlace;
424     if( width )
425     {
426         title->outWidth = width;
427     }
428     if( autocrop )
429     {
430         title->topCrop    = title->autoTopCrop;
431         title->bottomCrop = title->autoBottomCrop;
432         title->leftCrop   = title->autoLeftCrop;
433         title->rightCrop  = title->autoRightCrop;
434     }
435     else
436     {
437         title->topCrop    = top;
438         title->bottomCrop = bottom;
439         title->leftCrop   = left;
440         title->rightCrop  = right;
441     }
442     fprintf( stderr, "Cropping: T=%d,B=%d,L=%d,R=%d\n",
443              title->topCrop, title->bottomCrop,
444              title->leftCrop, title->rightCrop );
445     title->bitrate = vbitrate;
446     title->codec = vcodec;
447     title->mux = mux;
448
449     if( audios == NULL )
450     {
451         audio = HBListItemAt( title->audioList, 0 );
452         audio->outBitrate = abitrate;
453         audio->codec = acodec;
454         HBListAdd( title->ripAudioList, audio );
455     }
456     else if( strcasecmp( audios, "none" ) )
457     {
458         char *tmp = audios;
459
460         while( *tmp )
461         {
462             int i;
463
464             if( *tmp < '0' || *tmp > '9' )
465             {
466                 /* Skip non numeric char */
467                 tmp++;
468                 continue;
469             }
470
471             i = strtol( tmp, &tmp, 0 );
472             audio = HBListItemAt( title->audioList, i - 1 );
473             audio->outBitrate = abitrate;
474             audio->codec = acodec;
475             HBListAdd( title->ripAudioList, audio );
476
477             tmp++;
478         }
479     }
480     if( size )
481     {
482         title->bitrate = HBGetBitrateForSize( title, size, title->mux,
483                 HBListCount( title->ripAudioList ), abitrate );
484         fprintf( stderr, "Calculated bitrate: %d kbps\n", title->bitrate );
485     }
486
487     HBStartRip( h, title );
488 }
489
490 static void Encoding( void * data, float position, int pass,
491                       int passCount, float frameRate,
492                       float avgFrameRate, int remainingTime )
493 {
494     fprintf( stderr, "%6.2f %% (pass: %d/%d, cur/avg speed: "
495              "%5.2f/%5.2f fps, %02d:%02d:%02d remaining)\n",
496              100.0 * position, pass, passCount, frameRate, avgFrameRate,
497              remainingTime / 3600, ( remainingTime / 60 ) % 60,
498              remainingTime % 60 );
499 }
500
501 static void RipDone( void * data, int result )
502 {
503     switch( result )
504     {
505         case HB_SUCCESS:
506             fprintf( stderr, "Rip done!\n" );
507             break;
508         case HB_CANCELED:
509             fprintf( stderr, "Rip canceled.\n" );
510             break;
511         default:
512             fprintf( stderr, "Rip failed (error %x).\n", result );
513     }
514     die = 1;
515 }
516