1 /* $Id: test.c,v 1.82 2005/11/19 08:25:54 titer Exp $
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. */
13 static int debug = HB_DEBUG_NONE;
14 static int update = 0;
15 static char * input = NULL;
16 static char * output = NULL;
17 static char * format = NULL;
18 static int titleindex = 1;
19 static int twoPass = 0;
20 static int deinterlace = 0;
21 static int grayscale = 0;
22 static int vcodec = HB_VCODEC_FFMPEG;
23 static int h264_13 = 0;
24 static char * audios = NULL;
27 static int height = 0;
28 static int crop[4] = { -1,-1,-1,-1 };
32 static float vquality = -1.0;
33 static int vbitrate = 0;
35 static int abitrate = 0;
37 static int acodec = 0;
38 static int chapter_start = 0;
39 static int chapter_end = 0;
41 /* Exit cleanly on Ctrl-C */
42 static volatile int die = 0;
43 static void SigHandler( int );
46 static void ShowCommands();
47 static void ShowHelp();
48 static int ParseOptions( int argc, char ** argv );
49 static int CheckOptions( int argc, char ** argv );
50 static int HandleEvents( hb_handle_t * h );
52 int main( int argc, char ** argv )
58 /* Parse command line */
59 if( ParseOptions( argc, argv ) ||
60 CheckOptions( argc, argv ) )
66 h = hb_init( debug, update );
69 fprintf( stderr, "HandBrake %s (%d) - http://handbrake.m0k.org/\n",
70 hb_get_version( h ), hb_get_build( h ) );
72 /* Check for update */
75 if( ( build = hb_check_update( h, &version ) ) > -1 )
77 fprintf( stderr, "You are using an old version of "
78 "HandBrake.\nLatest is %s (build %d).\n", version,
83 fprintf( stderr, "Your version of HandBrake is up to "
91 fprintf( stderr, "%d CPU%s detected\n", hb_get_cpu_count(),
92 hb_get_cpu_count( h ) > 1 ? "s" : "" );
95 fprintf( stderr, "Forcing %d CPU%s\n", cpu,
97 hb_set_cpu_count( h, cpu );
100 /* Exit ASAP on Ctrl-C */
101 signal( SIGINT, SigHandler );
103 /* Feed libhb with a DVD to scan */
104 fprintf( stderr, "Opening %s...\n", input );
105 hb_scan( h, input, titleindex );
110 #if !defined(SYS_BEOS)
120 FD_SET( STDIN_FILENO, &fds );
121 ret = select( STDIN_FILENO + 1, &fds, NULL, NULL, &tv );
128 read( STDIN_FILENO, &buf[size], 1 ) > 0 )
130 if( buf[size] == '\n' )
137 if( size >= 256 || buf[size] == '\n' )
165 if( input ) free( input );
166 if( output ) free( output );
167 if( format ) free( format );
168 if( audios ) free( audios );
170 fprintf( stderr, "HandBrake has exited.\n" );
175 static void ShowCommands()
177 fprintf( stderr, "Commands:\n" );
178 fprintf( stderr, " [h]elp Show this message\n" );
179 fprintf( stderr, " [q]uit Exit HBTest\n" );
180 fprintf( stderr, " [p]ause Pause encoding\n" );
181 fprintf( stderr, " [r]esume Resume encoding\n" );
184 static void PrintTitleInfo( hb_title_t * title )
186 hb_chapter_t * chapter;
188 hb_subtitle_t * subtitle;
191 fprintf( stderr, "+ title %d:\n", title->index );
192 fprintf( stderr, " + vts %d, ttn %d, cells %d->%d (%d blocks)\n",
193 title->vts, title->ttn, title->cell_start, title->cell_end,
194 title->block_count );
195 fprintf( stderr, " + duration: %02d:%02d:%02d\n",
196 title->hours, title->minutes, title->seconds );
197 fprintf( stderr, " + size: %dx%d, aspect: %.2f, %.3f fps\n",
198 title->width, title->height,
199 (float) title->aspect / HB_ASPECT_BASE,
200 (float) title->rate / title->rate_base );
201 fprintf( stderr, " + autocrop: %d/%d/%d/%d\n", title->crop[0],
202 title->crop[1], title->crop[2], title->crop[3] );
203 fprintf( stderr, " + chapters:\n" );
204 for( i = 0; i < hb_list_count( title->list_chapter ); i++ )
206 chapter = hb_list_item( title->list_chapter, i );
207 fprintf( stderr, " + %d: cells %d->%d, %d blocks, duration "
208 "%02d:%02d:%02d\n", chapter->index,
209 chapter->cell_start, chapter->cell_end,
210 chapter->block_count, chapter->hours, chapter->minutes,
213 fprintf( stderr, " + audio tracks:\n" );
214 for( i = 0; i < hb_list_count( title->list_audio ); i++ )
216 audio = hb_list_item( title->list_audio, i );
217 if( audio->codec & HB_ACODEC_AC3 )
219 fprintf( stderr, " + %x, %s, %dHz, %dbps\n", audio->id,
220 audio->lang, audio->rate, audio->bitrate );
224 fprintf( stderr, " + %x, %s\n", audio->id, audio->lang );
227 fprintf( stderr, " + subtitle tracks:\n" );
228 for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
230 subtitle = hb_list_item( title->list_subtitle, i );
231 fprintf( stderr, " + %x, %s\n", subtitle->id, subtitle->lang );
235 static int HandleEvents( hb_handle_t * h )
238 hb_get_state( h, &s );
245 #define p s.param.scanning
246 case HB_STATE_SCANNING:
247 /* Show what title is currently being scanned */
248 fprintf( stderr, "Scanning title %d", p.title_cur );
250 fprintf( stderr, " of %d", p.title_count );
251 fprintf( stderr, "...\n" );
255 case HB_STATE_SCANDONE:
261 list = hb_get_titles( h );
263 if( !hb_list_count( list ) )
265 /* No valid title, stop right there */
266 fprintf( stderr, "No title found.\n" );
272 /* Scan-only mode, print infos and exit */
274 for( i = 0; i < hb_list_count( list ); i++ )
276 title = hb_list_item( list, i );
277 PrintTitleInfo( title );
283 /* Set job settings */
284 title = hb_list_item( list, 0 );
287 PrintTitleInfo( title );
289 if( chapter_start && chapter_end )
291 job->chapter_start = MAX( job->chapter_start,
293 job->chapter_end = MIN( job->chapter_end,
295 job->chapter_end = MAX( job->chapter_start,
299 if( crop[0] >= 0 && crop[1] >= 0 &&
300 crop[2] >= 0 && crop[3] >= 0 )
302 memcpy( job->crop, crop, 4 * sizeof( int ) );
305 job->deinterlace = deinterlace;
306 job->grayscale = grayscale;
308 if( width && height )
311 job->height = height;
316 hb_fix_aspect( job, HB_KEEP_WIDTH );
320 job->height = height;
321 hb_fix_aspect( job, HB_KEEP_HEIGHT );
325 hb_fix_aspect( job, HB_KEEP_WIDTH );
328 if( vquality >= 0.0 && vquality <= 1.0 )
330 job->vquality = vquality;
335 job->vquality = -1.0;
336 job->vbitrate = vbitrate;
340 job->vcodec = vcodec;
344 job->h264_13 = h264_13;
348 job->vrate = 27000000;
349 job->vrate_base = vrate;
358 if( strcasecmp( audios, "none" ) )
364 if( *tmp < '0' || *tmp > '9' )
366 /* Skip non numeric char */
370 job->audios[audio_count++] =
371 strtol( tmp, &tmp, 0 ) - 1;
373 job->audios[audio_count] = -1;
382 job->abitrate = abitrate;
386 job->acodec = acodec;
391 job->vbitrate = hb_calc_bitrate( job, size );
392 fprintf( stderr, "Calculated bitrate: %d kbps\n",
398 job->subtitle = sub - 1;
405 job->file = strdup( output );
423 #define p s.param.working
424 case HB_STATE_WORKING:
425 fprintf( stderr, "\rEncoding: task %d of %d, %.2f %%",
426 p.job_cur, p.job_count, 100.0 * p.progress );
429 fprintf( stderr, " (%.2f fps, avg %.2f fps, ETA "
430 "%02dh%02dm%02ds)", p.rate_cur, p.rate_avg,
431 p.hours, p.minutes, p.seconds );
436 #define p s.param.workdone
437 case HB_STATE_WORKDONE:
438 /* Print error if any, then exit */
442 fprintf( stderr, "\nRip done!\n" );
444 case HB_ERROR_CANCELED:
445 fprintf( stderr, "\nRip canceled.\n" );
448 fprintf( stderr, "\nRip failed (error %x).\n",
458 /****************************************************************************
460 ****************************************************************************/
461 static volatile int64_t i_die_date = 0;
462 void SigHandler( int i_signal )
467 i_die_date = hb_get_date();
468 fprintf( stderr, "Signal %d received, terminating - do it "
469 "again in case it gets stuck\n", i_signal );
471 else if( i_die_date + 500 < hb_get_date() )
473 fprintf( stderr, "Dying badly, files might remain in your /tmp\n" );
478 /****************************************************************************
480 ****************************************************************************/
481 static void ShowHelp()
486 "Syntax: HBTest [options] -i <device> -o <file>\n"
488 " -h, --help Print help\n"
489 " -u, --update Check for updates and exit\n"
490 " -v, --verbose Be verbose\n"
491 " -C, --cpu Set CPU count (default: autodetected)\n"
493 " -f, --format <string> Set output format (avi/mp4/ogm, default:\n"
494 " autodetected from file name)\n"
495 " -i, --input <string> Set input device\n"
496 " -o, --output <string> Set output file name\n"
498 " -t, --title <number> Select a title to encode (0 to scan only,\n"
500 " -c, --chapters <string> Select chapters (e.g. \"1-3\" for chapters\n"
501 " 1 to 3, or \"3\" for chapter 3 only,\n"
502 " default: all chapters)\n"
503 " -a, --audio <string> Select audio channel(s) (\"none\" for no \n"
504 " audio, default: first one)\n"
506 " -s, --subtitle <number> Select subtitle (default: none)\n"
507 " -e, --encoder <string> Set video library encoder (ffmpeg,xvid,\n"
508 " x264,x264b13, default: ffmpeg)\n"
509 " -E, --aencoder <string> Set audio encoder (faac/lame/vorbis/ac3, ac3\n"
510 " meaning passthrough, default: guessed)\n"
511 " -2, --two-pass Use two-pass mode\n"
512 " -d, --deinterlace Deinterlace video\n"
513 " -g, --grayscale Grayscale encoding\n"
515 " -r, --rate Set video framerate (" );
516 for( i = 0; i < hb_video_rates_count; i++ )
518 fprintf( stderr, hb_video_rates[i].string );
519 if( i != hb_video_rates_count - 1 )
520 fprintf( stderr, "/" );
522 fprintf( stderr, ")\n"
523 " -R, --arate Set audio samplerate (" );
524 for( i = 0; i < hb_audio_rates_count; i++ )
526 fprintf( stderr, hb_audio_rates[i].string );
527 if( i != hb_audio_rates_count - 1 )
528 fprintf( stderr, "/" );
530 fprintf( stderr, ")\n"
531 " -b, --vb <kb/s> Set video bitrate (default: 1000)\n"
532 " -q, --quality <float> Set video quality (0.0..1.0)\n"
533 " -S, --size <MB> Set target size\n"
534 " -B, --ab <kb/s> Set audio bitrate (default: 128)\n"
535 " -w, --width <number> Set picture width\n"
536 " -l, --height <number> Set picture height\n"
537 " --crop <T:B:L:R> Set cropping values (default: autocrop)\n" );
540 /****************************************************************************
542 ****************************************************************************/
543 static int ParseOptions( int argc, char ** argv )
547 static struct option long_options[] =
549 { "help", no_argument, NULL, 'h' },
550 { "update", no_argument, NULL, 'u' },
551 { "verbose", no_argument, NULL, 'v' },
552 { "cpu", required_argument, NULL, 'C' },
554 { "format", required_argument, NULL, 'f' },
555 { "input", required_argument, NULL, 'i' },
556 { "output", required_argument, NULL, 'o' },
558 { "title", required_argument, NULL, 't' },
559 { "chapters", required_argument, NULL, 'c' },
560 { "audio", required_argument, NULL, 'a' },
561 { "subtitle", required_argument, NULL, 's' },
563 { "encoder", required_argument, NULL, 'e' },
564 { "aencoder", required_argument, NULL, 'E' },
565 { "two-pass", no_argument, NULL, '2' },
566 { "deinterlace", no_argument, NULL, 'd' },
567 { "grayscale", no_argument, NULL, 'g' },
568 { "width", required_argument, NULL, 'w' },
569 { "height", required_argument, NULL, 'l' },
570 { "crop", required_argument, NULL, 'n' },
572 { "vb", required_argument, NULL, 'b' },
573 { "quality", required_argument, NULL, 'q' },
574 { "size", required_argument, NULL, 'S' },
575 { "ab", required_argument, NULL, 'B' },
576 { "rate", required_argument, NULL, 'r' },
577 { "arate", required_argument, NULL, 'R' },
582 int option_index = 0;
585 c = getopt_long( argc, argv,
586 "hvuC:f:i:o:t:c:a:s:e:E:2dgw:l:n:b:q:S:B:r:R:",
587 long_options, &option_index );
602 debug = HB_DEBUG_ALL;
605 cpu = atoi( optarg );
609 format = strdup( optarg );
612 input = strdup( optarg );
615 output = strdup( optarg );
619 titleindex = atoi( optarg );
624 if( sscanf( optarg, "%d-%d", &start, &end ) == 2 )
626 chapter_start = start;
629 else if( sscanf( optarg, "%d", &start ) == 1 )
631 chapter_start = start;
632 chapter_end = chapter_start;
636 fprintf( stderr, "chapters: invalid syntax (%s)\n",
643 audios = strdup( optarg );
646 sub = atoi( optarg );
659 if( !strcasecmp( optarg, "ffmpeg" ) )
661 vcodec = HB_VCODEC_FFMPEG;
663 else if( !strcasecmp( optarg, "xvid" ) )
665 vcodec = HB_VCODEC_XVID;
667 else if( !strcasecmp( optarg, "x264" ) )
669 vcodec = HB_VCODEC_X264;
671 else if( !strcasecmp( optarg, "x264b13" ) )
673 vcodec = HB_VCODEC_X264;
678 fprintf( stderr, "invalid codec (%s)\n", optarg );
683 if( !strcasecmp( optarg, "ac3" ) )
685 acodec = HB_ACODEC_AC3;
687 else if( !strcasecmp( optarg, "lame" ) )
689 acodec = HB_ACODEC_LAME;
693 width = atoi( optarg );
696 height = atoi( optarg );
702 for( i = 0; i < 4; i++ )
706 crop[i] = strtol( tmp, &tmp, 0 );
715 for( i = 0; i < hb_video_rates_count; i++ )
717 if( !strcmp( optarg, hb_video_rates[i].string ) )
719 vrate = hb_video_rates[i].rate;
725 fprintf( stderr, "invalid framerate %s\n", optarg );
733 for( i = 0; i < hb_audio_rates_count; i++ )
735 if( !strcmp( optarg, hb_audio_rates[i].string ) )
737 arate = hb_audio_rates[i].rate;
743 fprintf( stderr, "invalid framerate %s\n", optarg );
748 vbitrate = atoi( optarg );
751 vquality = atof( optarg );
754 size = atoi( optarg );
757 abitrate = atoi( optarg );
761 fprintf( stderr, "unknown option (%s)\n", argv[optind] );
769 static int CheckOptions( int argc, char ** argv )
776 if( input == NULL || *input == '\0' )
778 fprintf( stderr, "Missing input device. Run %s --help for "
779 "syntax.\n", argv[0] );
786 if( output == NULL || *output == '\0' )
788 fprintf( stderr, "Missing output file name. Run %s --help "
789 "for syntax.\n", argv[0] );
795 char * p = strrchr( output, '.' );
798 if( p && !strcasecmp( p, ".avi" ) )
802 else if( p && !strcasecmp( p, ".mp4" ) )
806 else if( p && ( !strcasecmp( p, ".ogm" ) ||
807 !strcasecmp( p, ".ogg" ) ) )
813 fprintf( stderr, "Output format couldn't be guessed "
814 "from file name, using default.\n" );
818 else if( !strcasecmp( format, "avi" ) )
822 else if( !strcasecmp( format, "mp4" ) )
826 else if( !strcasecmp( format, "ogm" ) ||
827 !strcasecmp( format, "ogg" ) )
833 fprintf( stderr, "Invalid output format (%s). Possible "
834 "choices are avi, mp4 and ogm\n.", format );
840 if( mux == HB_MUX_MP4 )
842 acodec = HB_ACODEC_FAAC;
844 else if( mux == HB_MUX_AVI )
846 acodec = HB_ACODEC_LAME;
848 else if( mux == HB_MUX_OGM )
850 acodec = HB_ACODEC_VORBIS;