X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=test%2Ftest.c;h=41bbe51e06abb7a93228371f22bd5112fe83464d;hb=f35d39f9adca67471b72f3e47398855d51481f87;hp=411c20c619384671eddba05630f5228be5c120c8;hpb=5f44f6b70650fcd3beee9db7873a5c9ac6fd98f4;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/test/test.c b/test/test.c index 411c20c6..41bbe51e 100644 --- a/test/test.c +++ b/test/test.c @@ -11,10 +11,18 @@ #include #include +#if defined( __MINGW32__ ) +#include +#endif + +#if defined( PTW32_STATIC_LIB ) +#include +#endif + #include "hb.h" #include "parsecsv.h" -#ifdef __APPLE_CC__ +#if defined( __APPLE_CC__ ) #import #include #include @@ -22,7 +30,7 @@ #endif /* Options */ -static int debug = HB_DEBUG_NONE; +static int debug = HB_DEBUG_ALL; static int update = 0; static int dvdnav = 0; static char * input = NULL; @@ -30,9 +38,8 @@ static char * output = NULL; static char * format = NULL; static int titleindex = 1; static int longest_title = 0; -static int subtitle_scan = 0; -static int subtitle_force = 0; static char * native_language = NULL; +static int native_dub = 0; static int twoPass = 0; static int deinterlace = 0; static char * deinterlace_opt = 0; @@ -59,9 +66,18 @@ static char * abitrates = NULL; static char * acodecs = NULL; static char * anames = NULL; static int default_acodec = HB_ACODEC_FAAC; -static int default_arate = 48000; static int default_abitrate = 160; -static int sub = 0; +static int audio_explicit = 0; +static char ** subtracks = NULL; +static char ** subforce = NULL; +static char * subburn = NULL; +static char * subdefault = NULL; +static char ** srtfile = NULL; +static char ** srtcodeset = NULL; +static char ** srtoffset = NULL; +static char ** srtlang = NULL; +static int srtdefault = -1; +static int subtitle_scan = 0; static int width = 0; static int height = 0; static int crop[4] = { -1,-1,-1,-1 }; @@ -71,11 +87,13 @@ static float vquality = -1.0; static int vbitrate = 0; static int size = 0; static int mux = 0; -static int pixelratio = 0; -static int loosePixelratio = 0; +static int anamorphic_mode = 0; static int modulus = 0; static int par_height = 0; static int par_width = 0; +static int display_width = 0; +static int keep_display_aspect = 0; +static int itu_par = 0; static int angle = 0; static int chapter_start = 0; static int chapter_end = 0; @@ -124,7 +142,7 @@ static char* bsd_name_for_path(char *path); static int device_is_dvd(char *device); static io_service_t get_iokit_service( char *device ); static int is_dvd_service( io_service_t service ); -static is_whole_media_service( io_service_t service ); +static int is_whole_media_service( io_service_t service ); #endif /* Only print the "Muxing..." message once */ @@ -147,6 +165,14 @@ int main( int argc, char ** argv ) int build; char * version; +/* win32 _IOLBF (line-buffering) is the same as _IOFBF (full-buffering). + * force it to unbuffered otherwise informative output is not easily parsed. + */ +#if defined( _WIN32 ) || defined( __MINGW32__ ) + setvbuf( stdout, NULL, _IONBF, 0 ); + setvbuf( stderr, NULL, _IONBF, 0 ); +#endif + audios = hb_list_init(); /* Parse command line */ @@ -156,7 +182,7 @@ int main( int argc, char ** argv ) return 1; } -#ifdef PTW32_STATIC_LIB +#if defined( PTW32_STATIC_LIB ) pthread_win32_process_attach_np(); pthread_win32_thread_attach_np(); #endif @@ -218,7 +244,29 @@ int main( int argc, char ** argv ) /* Wait... */ while( !die ) { -#if !defined(SYS_BEOS) && !defined(__MINGW32__) +#if defined( __MINGW32__ ) + if( _kbhit() ) { + switch( _getch() ) + { + case 0x03: /* ctrl-c */ + case 'q': + fprintf( stdout, "\nEncoding Quit by user command\n" ); + die = 1; + break; + case 'p': + fprintf( stdout, "\nEncoding Paused by user command, 'r' to resume\n" ); + hb_pause( h ); + break; + case 'r': + hb_resume( h ); + break; + case 'h': + ShowCommands(); + break; + } + } + hb_snooze( 200 ); +#elif !defined(SYS_BEOS) fd_set fds; struct timeval tv; int ret; @@ -307,7 +355,7 @@ int main( int argc, char ** argv ) fprintf( stderr, "HandBrake has exited.\n" ); -#ifdef PTW32_STATIC_LIB +#if defined( PTW32_STATIC_LIB ) pthread_win32_thread_detach_np(); pthread_win32_process_detach_np(); #endif @@ -327,7 +375,6 @@ static void ShowCommands() static void PrintTitleInfo( hb_title_t * title ) { hb_chapter_t * chapter; - hb_audio_config_t * audio; hb_subtitle_t * subtitle; int i; @@ -339,8 +386,10 @@ static void PrintTitleInfo( hb_title_t * title ) fprintf( stderr, " + angle(s) %d\n", title->angle_count ); fprintf( stderr, " + duration: %02d:%02d:%02d\n", title->hours, title->minutes, title->seconds ); - fprintf( stderr, " + size: %dx%d, aspect: %.2f, %.3f fps\n", + fprintf( stderr, " + size: %dx%d, pixel aspect: %d/%d, display aspect: %.2f, %.3f fps\n", title->width, title->height, + title->pixel_aspect_width, + title->pixel_aspect_height, (float) title->aspect, (float) title->rate / title->rate_base ); fprintf( stderr, " + autocrop: %d/%d/%d/%d\n", title->crop[0], @@ -361,20 +410,29 @@ static void PrintTitleInfo( hb_title_t * title ) audio = hb_list_audio_config_item( title->list_audio, i ); if( ( audio->in.codec == HB_ACODEC_AC3 ) || ( audio->in.codec == HB_ACODEC_DCA) ) { - fprintf( stderr, " + %d, %s, %dHz, %dbps\n", i + 1, - audio->lang.description, audio->in.samplerate, audio->in.bitrate ); + fprintf( stderr, " + %d, %s (iso639-2: %s), %dHz, %dbps\n", + i + 1, + audio->lang.description, + audio->lang.iso639_2, + audio->in.samplerate, + audio->in.bitrate ); } else { - fprintf( stderr, " + %d, %s\n", i + 1, audio->lang.description ); + fprintf( stderr, " + %d, %s (iso639-2: %s)\n", + i + 1, + audio->lang.description, + audio->lang.iso639_2 ); } } fprintf( stderr, " + subtitle tracks:\n" ); for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) { subtitle = hb_list_item( title->list_subtitle, i ); - fprintf( stderr, " + %d, %s (iso639-2: %s)\n", i + 1, subtitle->lang, - subtitle->iso639_2); + fprintf( stderr, " + %d, %s (iso639-2: %s) (%s)\n", + i + 1, subtitle->lang, + subtitle->iso639_2, + (subtitle->format == TEXTSUB) ? "Text" : "Bitmap"); } if(title->detected_interlacing) @@ -385,6 +443,24 @@ static void PrintTitleInfo( hb_title_t * title ) } +static int test_sub_list( char ** list, char * needle, int pos ) +{ + int i; + + if ( list == NULL || needle == NULL ) + return 0; + + if ( list[0] == NULL && pos == 1 ) + return 1; + + for ( i = 0; list[i] != NULL; i++ ) + { + if ( strcasecmp( list[i], needle ) == 0 ) + return i + 1; + } + return 0; +} + static int HandleEvents( hb_handle_t * h ) { hb_state_t s; @@ -413,6 +489,7 @@ static int HandleEvents( hb_handle_t * h ) hb_title_t * title; hb_job_t * job; int i; + int sub_burned = 0; /* Audio argument string parsing variables */ int acodec = 0; @@ -431,8 +508,8 @@ static int HandleEvents( hb_handle_t * h ) die = 1; break; } - if( longest_title ) - { + if( longest_title ) + { int i; int longest_title_idx=0; int longest_title_pos=-1; @@ -508,42 +585,52 @@ static int HandleEvents( hb_handle_t * h ) if (!strcmp(preset_name, "Universal")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } vcodec = HB_VCODEC_X264; - job->vquality = 0.589999973773956; + job->vquality = 20.0; job->crf = 1; if( !atracks ) { atracks = strdup("1,1"); } + if( !acodecs ) + { + acodecs = strdup("faac,ac3"); + } if( !abitrates ) { - abitrates = strdup("160,auto"); + abitrates = strdup("160,160"); + } + if( !mixdowns ) + { + mixdowns = strdup("dpl2,auto"); } if( !arates ) { arates = strdup("48,Auto"); } - if( !acodecs ) + if( !dynamic_range_compression ) { - acodecs = strdup("faac,ac3"); - } - if( !mixdowns ) - { - mixdowns = strdup("dpl2,auto"); + dynamic_range_compression = strdup("0.0,0.0"); } maxWidth = 720; if( !x264opts ) { - x264opts = strdup("level=30:cabac=0:ref=3:mixed-refs=1:analyse=all:me=umh:no-fast-pskip=1"); + x264opts = strdup("cabac=0:ref=2:me=umh:bframes=0:8x8dct=0:trellis=0:subme=6"); } - pixelratio = 2; + anamorphic_mode = 2; job->chapter_markers = 1; } if (!strcmp(preset_name, "iPod")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } job->ipod_atom = 1; vcodec = HB_VCODEC_X264; job->vbitrate = 700; @@ -551,537 +638,357 @@ static int HandleEvents( hb_handle_t * h ) { atracks = strdup("1"); } + if( !acodecs ) + { + acodecs = strdup("faac"); + } if( !abitrates ) { abitrates = strdup("160"); } - if( !arates ) + if( !mixdowns ) { - arates = strdup("48"); + mixdowns = strdup("dpl2"); } - if( !acodecs ) + if( !arates ) { - acodecs = strdup("faac"); + arates = strdup("48"); } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("dpl2"); + dynamic_range_compression = strdup("0.0"); } maxWidth = 320; if( !x264opts ) { - x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1"); + x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subme=6:8x8dct=0:trellis=0"); } job->chapter_markers = 1; } if (!strcmp(preset_name, "iPhone & iPod Touch")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } vcodec = HB_VCODEC_X264; - job->vquality = 0.589999973773956; + job->vquality = 20.0; job->crf = 1; if( !atracks ) { atracks = strdup("1"); } + if( !acodecs ) + { + acodecs = strdup("faac"); + } if( !abitrates ) { abitrates = strdup("128"); } - if( !arates ) + if( !mixdowns ) { - arates = strdup("48"); + mixdowns = strdup("dpl2"); } - if( !acodecs ) + if( !arates ) { - acodecs = strdup("faac"); + arates = strdup("48"); } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("dpl2"); + dynamic_range_compression = strdup("0.0"); } maxWidth = 480; if( !x264opts ) { - x264opts = strdup("level=30:cabac=0:ref=2:mixed-refs:analyse=all:me=umh:no-fast-pskip=1"); + x264opts = strdup("cabac=0:ref=2:me=umh:bframes=0:subme=6:8x8dct=0:trellis=0"); } job->chapter_markers = 1; } if (!strcmp(preset_name, "AppleTV")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } job->largeFileSize = 1; vcodec = HB_VCODEC_X264; - job->vquality = 0.589999973773956; + job->vquality = 20.0; job->crf = 1; if( !atracks ) { atracks = strdup("1,1"); } - if( !abitrates ) - { - abitrates = strdup("160,auto"); - } - if( !arates ) - { - arates = strdup("48,Auto"); - } if( !acodecs ) { acodecs = strdup("faac,ac3"); } - if( !mixdowns ) - { - mixdowns = strdup("dpl2,auto"); - } - maxWidth = 960; - if( !x264opts ) - { - x264opts = strdup("level=30:cabac=0:ref=3:mixed-refs=1:bframes=6:weightb=1:direct=auto:no-fast-pskip=1:me=umh:subq=7:analyse=all"); - } - pixelratio = 2; - job->chapter_markers = 1; - } - - if (!strcmp(preset_name, "QuickTime")) - { - mux = HB_MUX_MP4; - vcodec = HB_VCODEC_X264; - job->vbitrate = 1800; - if( !atracks ) - { - atracks = strdup("1"); - } if( !abitrates ) { - abitrates = strdup("160"); - } - if( !arates ) - { - arates = strdup("Auto"); - } - if( !acodecs ) - { - acodecs = strdup("faac"); + abitrates = strdup("160,160"); } if( !mixdowns ) { - mixdowns = strdup("dpl2"); - } - if( !x264opts ) - { - x264opts = strdup("ref=3:mixed-refs:bframes=3:weightb:direct=auto:me=umh:subme=7:analyse=all:8x8dct:trellis=1:no-fast-pskip=1:psy-rd=1,1"); - } - pixelratio = 1; - job->chapter_markers = 1; - twoPass = 1; - turbo_opts_enabled = 1; - } - - if (!strcmp(preset_name, "AppleTV Legacy")) - { - mux = HB_MUX_MP4; - job->largeFileSize = 1; - vcodec = HB_VCODEC_X264; - job->vbitrate = 2500; - if( !atracks ) - { - atracks = strdup("1,1"); - } - if( !abitrates ) - { - abitrates = strdup("160,auto"); + mixdowns = strdup("dpl2,auto"); } if( !arates ) { arates = strdup("48,Auto"); } - if( !acodecs ) - { - acodecs = strdup("faac,ac3"); - } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("dpl2,auto"); + dynamic_range_compression = strdup("0.0,0.0"); } + maxWidth = 960; if( !x264opts ) { - x264opts = strdup("bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:trellis=1:cabac=0"); + x264opts = strdup("cabac=0:ref=2:me=umh:b-adapt=2:weightb=0:trellis=0"); } - pixelratio = 1; + anamorphic_mode = 2; job->chapter_markers = 1; } - if (!strcmp(preset_name, "iPhone Legacy")) + if (!strcmp(preset_name, "Normal")) { - mux = HB_MUX_MP4; - job->ipod_atom = 1; + if( !mux ) + { + mux = HB_MUX_MP4; + } vcodec = HB_VCODEC_X264; - job->vbitrate = 960; + job->vquality = 20.0; + job->crf = 1; if( !atracks ) { atracks = strdup("1"); } - if( !abitrates ) - { - abitrates = strdup("128"); - } - if( !arates ) - { - arates = strdup("48"); - } if( !acodecs ) { acodecs = strdup("faac"); } - if( !mixdowns ) - { - mixdowns = strdup("dpl2"); - } - maxWidth = 480; - if( !x264opts ) - { - x264opts = strdup("level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:trellis=1"); - } - job->chapter_markers = 1; - } - - if (!strcmp(preset_name, "iPod Legacy")) - { - mux = HB_MUX_MP4; - job->ipod_atom = 1; - vcodec = HB_VCODEC_X264; - job->vbitrate = 1500; - if( !atracks ) - { - atracks = strdup("1"); - } if( !abitrates ) { abitrates = strdup("160"); } - if( !arates ) + if( !mixdowns ) { - arates = strdup("48"); + mixdowns = strdup("dpl2"); } - if( !acodecs ) + if( !arates ) { - acodecs = strdup("faac"); + arates = strdup("48"); } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("dpl2"); + dynamic_range_compression = strdup("0.0"); } - maxWidth = 640; if( !x264opts ) { - x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1"); + x264opts = strdup("ref=2:bframes=2:me=umh:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0"); } + anamorphic_mode = 1; job->chapter_markers = 1; } - if (!strcmp(preset_name, "Normal")) + if (!strcmp(preset_name, "High Profile")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } vcodec = HB_VCODEC_X264; - job->vbitrate = 1500; + job->vquality = 20.0; + job->crf = 1; if( !atracks ) { - atracks = strdup("1"); + atracks = strdup("1,1"); + } + if( !acodecs ) + { + acodecs = strdup("faac,ac3"); } if( !abitrates ) { - abitrates = strdup("160"); + abitrates = strdup("160,160"); } - if( !arates ) + if( !mixdowns ) { - arates = strdup("Auto"); + mixdowns = strdup("dpl2,auto"); } - if( !acodecs ) + if( !arates ) { - acodecs = strdup("faac"); + arates = strdup("48,Auto"); } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("dpl2"); + dynamic_range_compression = strdup("0.0,0.0"); } if( !x264opts ) { - x264opts = strdup("ref=2:bframes=2:me=umh"); + x264opts = strdup("b-pyramid:b-adapt=2:me=umh:subme=9:analyse=all:trellis=0"); } - pixelratio = 1; + detelecine = 1; + decomb = 1; + anamorphic_mode = 2; job->chapter_markers = 1; - twoPass = 1; - turbo_opts_enabled = 1; } if (!strcmp(preset_name, "Classic")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } job->vbitrate = 1000; if( !atracks ) { atracks = strdup("1"); } - if( !abitrates ) - { - abitrates = strdup("160"); - } - if( !arates ) - { - arates = strdup("Auto"); - } if( !acodecs ) { acodecs = strdup("faac"); } - if( !mixdowns ) - { - mixdowns = strdup("dpl2"); - } - } - - if (!strcmp(preset_name, "Animation")) - { - mux = HB_MUX_MKV; - vcodec = HB_VCODEC_X264; - job->vbitrate = 1000; - if( !atracks ) - { - atracks = strdup("1"); - } if( !abitrates ) { abitrates = strdup("160"); } - if( !arates ) - { - arates = strdup("Auto"); - } - if( !acodecs ) - { - acodecs = strdup("faac"); - } if( !mixdowns ) { mixdowns = strdup("dpl2"); } - if( !x264opts ) - { - x264opts = strdup("ref=5:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip:filter=2,2:psy-rd=1,1:subme=9"); - } - detelecine = 1; - decomb = 1; - pixelratio = 1; - job->chapter_markers = 1; - twoPass = 1; - turbo_opts_enabled = 1; - } - - if (!strcmp(preset_name, "Constant Quality Rate")) - { - mux = HB_MUX_MKV; - vcodec = HB_VCODEC_X264; - job->vquality = 0.600000023841858; - job->crf = 1; - if( !atracks ) - { - atracks = strdup("1"); - } - if( !abitrates ) - { - abitrates = strdup("auto"); - } if( !arates ) { - arates = strdup("Auto"); - } - if( !acodecs ) - { - acodecs = strdup("ac3"); - } - if( !mixdowns ) - { - mixdowns = strdup("auto"); + arates = strdup("48"); } - if( !x264opts ) + if( !dynamic_range_compression ) { - x264opts = strdup("ref=3:mixed-refs:bframes=3:b-pyramid:weightb:filter=-2,-1:trellis=1:analyse=all:8x8dct:me=umh:subme=9:psy-rd=1,1"); + dynamic_range_compression = strdup("0.0"); } - pixelratio = 1; - job->chapter_markers = 1; } - if (!strcmp(preset_name, "Film")) + if (!strcmp(preset_name, "AppleTV Legacy")) { - mux = HB_MUX_MKV; + if( !mux ) + { + mux = HB_MUX_MP4; + } + job->largeFileSize = 1; vcodec = HB_VCODEC_X264; - job->vbitrate = 1800; + job->vbitrate = 2500; if( !atracks ) { - atracks = strdup("1"); + atracks = strdup("1,1"); + } + if( !acodecs ) + { + acodecs = strdup("faac,ac3"); } if( !abitrates ) { - abitrates = strdup("auto"); + abitrates = strdup("160,160"); } - if( !arates ) + if( !mixdowns ) { - arates = strdup("Auto"); + mixdowns = strdup("dpl2,auto"); } - if( !acodecs ) + if( !arates ) { - acodecs = strdup("ac3"); + arates = strdup("48,Auto"); } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("auto"); + dynamic_range_compression = strdup("0.0,0.0"); } if( !x264opts ) { - x264opts = strdup("ref=3:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:subme=9:analyse=all:8x8dct:trellis=1:no-fast-pskip:psy-rd=1,1"); + x264opts = strdup("ref=1:subme=5:me=umh:no-fast-pskip=1:cabac=0:weightb=0:8x8dct=0:trellis=0"); } - pixelratio = 1; + anamorphic_mode = 1; job->chapter_markers = 1; - twoPass = 1; - turbo_opts_enabled = 1; } - if (!strcmp(preset_name, "Television")) + if (!strcmp(preset_name, "iPhone Legacy")) { - mux = HB_MUX_MKV; + if( !mux ) + { + mux = HB_MUX_MP4; + } + job->ipod_atom = 1; vcodec = HB_VCODEC_X264; - job->vbitrate = 1300; + job->vbitrate = 960; if( !atracks ) { atracks = strdup("1"); } - if( !abitrates ) - { - abitrates = strdup("160"); - } - if( !arates ) - { - arates = strdup("Auto"); - } if( !acodecs ) { acodecs = strdup("faac"); } - if( !mixdowns ) - { - mixdowns = strdup("dpl2"); - } - if( !x264opts ) - { - x264opts = strdup("ref=3:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:subme=9:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip=1:psy-rd=1,1"); - } - detelecine = 1; - decomb = 1; - pixelratio = 1; - job->chapter_markers = 1; - twoPass = 1; - turbo_opts_enabled = 1; - } - - if (!strcmp(preset_name, "PSP")) - { - mux = HB_MUX_MP4; - job->vbitrate = 1024; - if( !atracks ) - { - atracks = strdup("1"); - } if( !abitrates ) { abitrates = strdup("128"); } - if( !arates ) - { - arates = strdup("48"); - } - if( !acodecs ) - { - acodecs = strdup("faac"); - } if( !mixdowns ) { mixdowns = strdup("dpl2"); } - maxWidth = 368; - maxHeight = 208; - job->chapter_markers = 1; - } - - if (!strcmp(preset_name, "PS3")) - { - mux = HB_MUX_MP4; - vcodec = HB_VCODEC_X264; - job->vbitrate = 2500; - if( !atracks ) - { - atracks = strdup("1"); - } - if( !abitrates ) - { - abitrates = strdup("160"); - } if( !arates ) { arates = strdup("48"); } - if( !acodecs ) + if( !dynamic_range_compression ) { - acodecs = strdup("faac"); + dynamic_range_compression = strdup("0.0"); } - if( !mixdowns ) - { - mixdowns = strdup("dpl2"); - } - job->crop[0] = 0; - job->crop[1] = 0; - job->crop[2] = 0; - job->crop[4] - 0; + maxWidth = 480; if( !x264opts ) { - x264opts = strdup("level=41:me=umh"); + x264opts = strdup("level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:bframes=0:subme=6:8x8dct=0:trellis=0"); } - pixelratio = 1; + job->chapter_markers = 1; } - if (!strcmp(preset_name, "Xbox 360")) + if (!strcmp(preset_name, "iPod Legacy")) { - mux = HB_MUX_MP4; + if( !mux ) + { + mux = HB_MUX_MP4; + } + job->ipod_atom = 1; vcodec = HB_VCODEC_X264; - job->vbitrate = 2000; + job->vbitrate = 1500; if( !atracks ) { - atracks = strdup("1"); + atracks = strdup("1"); + } + if( !acodecs ) + { + acodecs = strdup("faac"); } if( !abitrates ) { abitrates = strdup("160"); } - if( !arates ) + if( !mixdowns ) { - arates = strdup("48"); + mixdowns = strdup("dpl2"); } - if( !acodecs ) + if( !arates ) { - acodecs = strdup("faac"); + arates = strdup("48"); } - if( !mixdowns ) + if( !dynamic_range_compression ) { - mixdowns = strdup("dpl2"); + dynamic_range_compression = strdup("0.0"); } + maxWidth = 640; if( !x264opts ) { - x264opts = strdup("level=40:ref=2:mixed-refs:bframes=3:weightb:subme=9:direct=auto:b-pyramid:me=umh:analyse=all:no-fast-pskip:filter=-2,-1"); - } - pixelratio = 1; + x264opts = strdup("level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:subme=6:8x8dct=0:trellis=0"); } + job->chapter_markers = 1; + } } if ( chapter_markers ) @@ -1159,25 +1066,7 @@ static int HandleEvents( hb_handle_t * h ) job->deinterlace = deinterlace; job->grayscale = grayscale; - if (loosePixelratio) - { - job->anamorphic.mode = 2; - if (modulus) - { - job->anamorphic.modulus = modulus; - } - if( par_width && par_height ) - { - job->anamorphic.mode = 3; - job->anamorphic.par_width = par_width; - job->anamorphic.par_height = par_height; - } - } - else - { - job->anamorphic.mode = pixelratio; - } - + /* Add selected filters */ job->filters = hb_list_init(); if( detelecine ) @@ -1206,31 +1095,151 @@ static int HandleEvents( hb_handle_t * h ) hb_list_add( job->filters, &hb_filter_denoise ); } - if( width && height ) - { - job->width = width; - job->height = height; - } - else if( width ) - { - job->width = width; - hb_fix_aspect( job, HB_KEEP_WIDTH ); - } - else if( height && !loosePixelratio) + switch( anamorphic_mode ) { - job->height = height; - hb_fix_aspect( job, HB_KEEP_HEIGHT ); - } - else if( !width && !height && !pixelratio && !loosePixelratio ) - { - hb_fix_aspect( job, HB_KEEP_WIDTH ); - } - else if (!width && loosePixelratio) - { - /* Default to full width when one isn't specified for loose anamorphic */ - job->width = title->width - job->crop[2] - job->crop[3]; - /* The height will be thrown away in hb.c but calculate it anyway */ - hb_fix_aspect( job, HB_KEEP_WIDTH ); + case 0: // Non-anamorphic + + if( width && height ) + { + job->width = width; + job->height = height; + } + else if( width ) + { + job->width = width; + hb_fix_aspect( job, HB_KEEP_WIDTH ); + } + else if( height ) + { + job->height = height; + hb_fix_aspect( job, HB_KEEP_HEIGHT ); + } + else if( !width && !height ) + { + hb_fix_aspect( job, HB_KEEP_WIDTH ); + } + + break; + + case 1: // Strict anammorphic + job->anamorphic.mode = anamorphic_mode; + break; + + case 2: // Loose anamorphic + job->anamorphic.mode = 2; + + if (modulus) + { + job->anamorphic.modulus = modulus; + } + + if( itu_par ) + { + job->anamorphic.itu_par = itu_par; + } + + if( width ) + { + job->width = width; + } + else if( !width && !height ) + { + /* Default to full width when one isn't specified for loose anamorphic */ + job->width = title->width - job->crop[2] - job->crop[3]; + } + + break; + + case 3: // Custom Anamorphic 3: Power User Jamboree + job->anamorphic.mode = 3; + + if (modulus) + { + job->anamorphic.modulus = modulus; + } + + if( itu_par ) + { + job->anamorphic.itu_par = itu_par; + } + + if( par_width && par_height ) + { + job->anamorphic.par_width = par_width; + job->anamorphic.par_height = par_height; + } + + if( keep_display_aspect ) + { + job->anamorphic.keep_display_aspect = 1; + + /* First, what *is* the display aspect? */ + int cropped_width = title->width - job->crop[2] - job->crop[3]; + int cropped_height = title->height - job->crop[0] - job->crop[1]; + + /* XXX -- I'm assuming people want to keep the source + display AR even though they might have already + asked for ITU values instead. */ + float source_display_width = (float)cropped_width * + (float)title->pixel_aspect_width / (float)title->pixel_aspect_height; + float display_aspect = source_display_width / (float)cropped_height; + /* When keeping display aspect, we have to rank some values + by priority in order to consistently handle situations + when more than one might be specified by default. + + * First off, PAR gets ignored. (err make this reality) + * Height will be respected over all other settings, + * If it isn't set, display_width will be followed. + * If it isn't set, width will be followed. */ + if( height ) + { + /* We scale the display width to the new height */ + display_width = (int)( (double)height * display_aspect ); + } + else if( display_width ) + { + /* We scale the height to the new display width */ + height = (int)( (double)display_width / display_aspect ); + } + } + + if( display_width ) + { + /* Adjust the PAR to create the new display width + from the default job width. */ + job->anamorphic.dar_width = display_width; + + job->anamorphic.dar_height = height ? + height : + title->height - job->crop[0] - job->crop[1]; + } + + if( width && height ) + { + /* Use these storage dimensions */ + job->width = width; + job->height = height; + } + else if( width ) + { + /* Use just this storage width */ + job->width = width; + job->height = title->height - job->crop[0] - job->crop[1]; + } + else if( height ) + { + /* Use just this storage height. */ + job->height = height; + job->width = title->width - job->crop[2] - job->crop[3]; + } + else if( !width && !height ) + { + /* Assume source dimensions after cropping. */ + job->width = title->width - job->crop[2] - job->crop[3]; + job->height = title->height - job->crop[0] - job->crop[1]; + } + + break; } if( vquality >= 0.0 && ( ( vquality <= 1.0 ) || ( vcodec == HB_VCODEC_X264 ) || (vcodec == HB_VCODEC_FFMPEG) ) ) @@ -1323,8 +1332,59 @@ static int HandleEvents( hb_handle_t * h ) } /* Parse audio tracks */ - if( hb_list_count(audios) == 0 ) + if( native_language && native_dub ) { + if( hb_list_count( audios ) == 0 || !audio_explicit ) + { + for( i = 0; i < hb_list_count( title->list_audio ); i++ ) + { + char audio_lang[4]; + int track = i; + + audio = hb_list_audio_config_item( title->list_audio, i ); + + strncpy( audio_lang, audio->lang.iso639_2, sizeof( audio_lang ) ); + + if( strncasecmp( native_language, audio_lang, + sizeof( audio_lang ) ) == 0 && + audio->lang.type != 3 && // Directors 1 + audio->lang.type != 4) // Directors 2 + { + /* + * Matched an audio to our native language - use it. + * Replace any existing audio tracks that a preset may + * have put here. + */ + if( hb_list_count(audios) == 0) { + audio = calloc(1, sizeof(*audio)); + hb_audio_config_init(audio); + audio->in.track = track; + audio->out.track = num_audio_tracks++; + /* Add it to our audios */ + hb_list_add(audios, audio); + } else { + /* + * Update the track numbers on what is already in + * there. + */ + for( i=0; i < hb_list_count( audios ); i++ ) + { + audio = hb_list_item( audios, i ); + + audio->in.track = track; + } + } + break; + } + } + } else { + fprintf( stderr, "Warning: Native language (dubbing) selection ignored since an audio track has already been selected\n"); + } + } + + if( hb_list_count(audios) == 0 && + hb_list_count(job->title->list_audio) > 0 ) + { /* Create a new audio track with default settings */ audio = calloc(1, sizeof(*audio)); hb_audio_config_init(audio); @@ -1638,22 +1698,223 @@ static int HandleEvents( hb_handle_t * h ) job->vbitrate ); } - if( sub ) + if( subtracks ) { - hb_subtitle_t *subtitle; - /* - * Find the subtitle with the same track as "sub" and - * add that to the job subtitle list - */ - subtitle = hb_list_item( title->list_subtitle, sub ); - if( subtitle ) { - hb_list_add( job->list_subtitle, subtitle ); + char * token; + int i, pos; + + pos = 0; + for ( i = 0; subtracks[i] != NULL; i++ ) + { + pos++; + token = subtracks[i]; + if( strcasecmp(token, "scan" ) == 0 ) + { + int burn = 0, force = 0, def = 0; + + if ( subburn != NULL ) + { + burn = ( pos == 1 && subburn[0] == 0 ) || + ( strcmp( "scan", subburn ) == 0 ); + } + if ( subdefault != NULL ) + { + def = ( pos == 1 && subdefault[0] == 0 ) || + ( strcmp( "scan", subdefault ) == 0 ); + } + force = test_sub_list( subforce, "scan", pos ); + + if ( !burn && mux == HB_MUX_MKV ) + { + job->select_subtitle_config.dest = PASSTHRUSUB; + } + else if ( burn ) + { + if ( sub_burned ) + { + continue; + } + sub_burned = 1; + } + if ( !( !burn && mux == HB_MUX_MP4 ) ) + { + job->select_subtitle_config.force = force; + job->select_subtitle_config.default_track = def; + subtitle_scan = 1; + } else { + fprintf( stderr, "Warning: Subtitle Scan for MP4 requires the '--subtitle-burn' option to be selected\n"); + } + } + else + { + hb_subtitle_t * subtitle; + hb_subtitle_config_t sub_config; + int track; + int burn = 0, force = 0, def = 0; + + track = atoi(token) - 1; + subtitle = hb_list_item(title->list_subtitle, track); + if( subtitle == NULL ) + { + fprintf( stderr, "Warning: Could not find subtitle track %d, skipped\n", track+1 ); + continue; + } + sub_config = subtitle->config; + + if ( subburn != NULL ) + { + burn = ( pos == 1 && subburn[0] == 0 ) || + ( strcmp( token, subburn ) == 0 ); + } + if ( subdefault != NULL ) + { + def = ( pos == 1 && subdefault[0] == 0 ) || + ( strcmp( token, subdefault ) == 0 ); + } + + force = test_sub_list(subforce, token, pos); + + if ( !burn && mux == HB_MUX_MKV && + subtitle->format == PICTURESUB) + { + sub_config.dest = PASSTHRUSUB; + } + else if (!burn && mux == HB_MUX_MP4 && + subtitle->format == PICTURESUB) + { + // Skip any non-burned vobsubs when output is mp4 + fprintf( stderr, "Warning: Skipping subtitle track %d, can't pass-through VOBSUBs in an MP4 container,\nadd '--subtitle-burn %d' to the command line\n", track+1, track+1 ); + continue; + } + else if ( burn && subtitle->format == PICTURESUB ) + { + // Only allow one subtitle to be burned into video + if ( sub_burned ) + { + fprintf( stderr, "Warning: Skipping subtitle track %d, can't have more than one track burnt in\n", track+1 ); + continue; + } + sub_burned = 1; + } + sub_config.force = force; + sub_config.default_track = def; + hb_subtitle_add( job, &sub_config, track ); + } + } + } + + if( srtfile ) + { + char * token; + int i, pos; + hb_subtitle_config_t sub_config; + + pos = 0; + for( i=0; srtfile[i] != NULL; i++ ) + { + char *codeset = "L1"; + int64_t offset = 0; + char *lang = "und"; + + pos++; + token = srtfile[i]; + if( srtcodeset && srtcodeset[i] ) + { + codeset = srtcodeset[i]; + } + if( srtoffset && srtoffset[i] ) + { + offset = strtoll( srtoffset[i], &srtoffset[i], 0 ); + } + if ( srtlang && srtlang[i] ) + { + lang = srtlang[i]; + } + sub_config.default_track = + ( srtdefault != -1 ) && ( srtdefault == i + 1 ); + sub_config.force = 0; + strncpy( sub_config.src_filename, srtfile[i], 128); + strncpy( sub_config.src_codeset, codeset, 40); + sub_config.offset = offset; + + hb_srt_add( job, &sub_config, lang); } } if( native_language ) { - job->native_language = strdup( native_language ); + char audio_lang[4]; + + audio = hb_list_audio_config_item(job->list_audio, 0); + + if( audio ) + { + strncpy( audio_lang, audio->lang.iso639_2, sizeof( audio_lang ) ); + + if( strncasecmp( native_language, audio_lang, + sizeof( audio_lang ) ) != 0 ) + { + /* + * Audio language is not the same as our native language. + * If we have any subtitles in our native language they + * should be selected here if they haven't already been. + */ + hb_subtitle_t *subtitle, *subtitle2 = NULL; + int matched_track = 0; + + for( i = 0; i < hb_list_count( title->list_subtitle ); i++ ) + { + subtitle = hb_list_item( title->list_subtitle, i ); + matched_track = i; + if( strcmp( subtitle->iso639_2, native_language ) == 0 ) + { + /* + * Found the first matching subtitle in our + * native language. Is it already selected? + */ + for( i = 0; i < hb_list_count( job->list_subtitle ); i++ ) + { + subtitle2 = hb_list_item( job->list_subtitle, i ); + + if( subtitle2->track == subtitle->track) { + /* + * Already selected + */ + break; + } + subtitle2 = NULL; + } + + if( subtitle2 == NULL ) + { + /* + * Not already selected, so select it. + */ + hb_subtitle_config_t sub_config; + + if( native_dub ) + { + fprintf( stderr, "Warning: no matching audio for native language - using subtitles instead.\n"); + } + sub_config = subtitle->config; + + if( mux == HB_MUX_MKV || subtitle->format == TEXTSUB) + { + sub_config.dest = PASSTHRUSUB; + } + + sub_config.force = 0; + sub_config.default_track = 1; + hb_subtitle_add( job, &sub_config, matched_track); + } + /* + * Stop searching. + */ + break; + } + } + } + } } if( job->mux ) @@ -1699,11 +1960,6 @@ static int HandleEvents( hb_handle_t * h ) if (maxHeight) job->maxHeight = maxHeight; - if( subtitle_force ) - { - job->subtitle_force = subtitle_force; - } - if( start_at_preview ) { job->start_at_preview = start_at_preview - 1; @@ -1739,8 +1995,6 @@ static int HandleEvents( hb_handle_t * h ) job->indepth_scan = subtitle_scan; fprintf( stderr, "Subtitle Scan Enabled - enabling " "subtitles if found for foreign language segments\n"); - job->select_subtitle = malloc(sizeof(hb_subtitle_t*)); - *(job->select_subtitle) = NULL; /* * Add the pre-scan job @@ -1757,10 +2011,6 @@ static int HandleEvents( hb_handle_t * h ) * for the first pass and then off again for the * second. */ - hb_subtitle_t **subtitle_tmp = job->select_subtitle; - - job->select_subtitle = NULL; - job->pass = 1; job->indepth_scan = 0; @@ -1802,8 +2052,6 @@ static int HandleEvents( hb_handle_t * h ) } hb_add( h, job ); - job->select_subtitle = subtitle_tmp; - job->pass = 2; /* * On the second pass we turn off subtitle scan so that we @@ -1943,7 +2191,7 @@ static void ShowHelp() "### Destination Options------------------------------------------------------\n\n" " -o, --output Set output file name\n" - " -f, --format Set output format (avi/mp4/ogm/mkv, default:\n" + " -f, --format Set output format (mp4/mkv, default:\n" " autodetected from file name)\n" " -m, --markers Add chapter markers (mp4 and mkv output formats only)\n" " -4, --large-file Use 64-bit mp4 files that can hold more than\n" @@ -1954,8 +2202,8 @@ static void ShowHelp() "### Video Options------------------------------------------------------------\n\n" - " -e, --encoder Set video library encoder (ffmpeg,xvid,\n" - " x264,theora default: ffmpeg)\n" + " -e, --encoder Set video library encoder (ffmpeg,x264,theora)\n" + " (default: ffmpeg)\n" " -x, --x264opts Specify advanced x264 options in the\n" " same style as mencoder:\n" " option1=value1:option2=value2\n" @@ -1996,11 +2244,22 @@ static void ShowHelp() " More than one output track can be used for one\n" " input.\n" " (\"none\" for no audio, \"1,2,3\" for multiple\n" - " tracks, default: first one)\n" + " tracks, default: first one)\n" ); + +#ifdef __APPLE_CC__ + fprintf( out, + " -E, --aencoder Audio encoder(s) (ca_aac/faac/lame/vorbis/ac3/dts) \n" + " ac3 and dts meaning passthrough\n" + " Separated by commas for more than one audio track.\n" + " (default: guessed)\n" ); +#else + fprintf( out, " -E, --aencoder Audio encoder(s) (faac/lame/vorbis/ac3/dts) \n" " ac3 and dts meaning passthrough\n" " Separated by commas for more than one audio track.\n" - " (default: guessed)\n" + " (default: guessed)\n" ); +#endif + fprintf( out, " -B, --ab Set audio bitrate(s) (default: 160)\n" " Separated by commas for more than one audio track.\n" " -6, --mixdown Format(s) for surround sound downmixing\n" @@ -2029,11 +2288,23 @@ static void ShowHelp() " --crop Set cropping values (default: autocrop)\n" " -Y, --maxHeight <#> Set maximum height\n" " -X, --maxWidth <#> Set maximum width\n" - " -p, --pixelratio Store pixel aspect ratio in video stream\n" - " -P, --loosePixelratio Store pixel aspect ratio with specified width\n" - " Takes as optional arguments what number you want\n" - " the dimensions to divide cleanly by (default 16)\n" - " and the pixel ratio to use (default autodetected)\n" + " --strict-anamorphic Store pixel aspect ratio in video stream\n" + " --loose-anamorphic Store pixel aspect ratio with specified width\n" + " --custom-anamorphic Store pixel aspect ratio in video stream and\n" + " directly control all parameters.\n" + " --display-width Set the width to scale the actual pixels to\n" + " at playback, for custom anamorphic.\n" + " --keep-display-aspect Preserve the source's display aspect ratio\n" + " when using custom anamorphic\n" + " --pixel-aspect Set a custom pixel aspect for custom anamorphic\n" + " \n" + " (--display-width and --pixel-aspect are mutually\n" + " exclusive and the former will override the latter)\n" + " --itu-par Use wider, ITU pixel aspect values for loose and\n" + " custom anamorphic, useful with underscanned sources\n" + " --modulus Set the number you want the scaled pixel dimensions\n" + " to divide cleanly by, for loose and custom\n" + " anamorphic modes (default: 16)\n" " -M --color-matrix Set the color space signaled by the output\n" " <601 or 709> (Bt.601 is mostly for SD content, Bt.709 for HD,\n" " default: set by resolution)\n" @@ -2062,21 +2333,59 @@ static void ShowHelp() "\n" "### Subtitle Options------------------------------------------------------------\n\n" - " -s, --subtitle Select subtitle (default: none)\n" - " -U, --subtitle-scan Scan for subtitles in an extra 1st pass, and choose\n" - " the one that's only used 10 percent of the time\n" - " or less. This should locate subtitles for short\n" - " foreign language segments. Best used in conjunction\n" - " with --subtitle-forced.\n" + " -s, --subtitle Select subtitle track(s), separated by commas\n" + " More than one output track can be used for one\n" + " input.\n" + " (\"1,2,3\" for multiple tracks.\n" + " A special track name \"scan\" adds an extra 1st pass.\n" + " This extra pass scans subtitles matching the\n" + " language of the first audio or the language \n" + " selected by --native-language.\n" + " The one that's only used 10 percent of the time\n" + " or less is selected. This should locate subtitles\n" + " for short foreign language segments. Best used in\n" + " conjunction with --subtitle-forced.\n" " -F, --subtitle-forced Only display subtitles from the selected stream if\n" - " the subtitle has the forced flag set. May be used in\n" - " conjunction with --subtitle-scan to auto-select\n" + " the subtitle has the forced flag set. May be used in\n" + " conjunction with \"scan\" track to auto-select\n" " a stream if it contains forced subtitles.\n" - " -N, --native-language Select subtitles with this language if it does not\n" - " match the Audio language. Provide the language's\n" - " iso639-2 code (fre, eng, spa, dut, et cetera)\n" - - + " Separated by commas for more than one audio track.\n" + " (\"1,2,3\" for multiple tracks.\n" + " If \"string\" is omitted, the first trac is forced.\n" + " --subtitle-burn \"Burn\" the selected subtitle into the video track\n" + " If \"number\" is omitted, the first trac is burned.\n" + " --subtitle-default Flag the selected subtitle as the default subtitle\n" + " to be displayed upon playback. Setting no default\n" + " means no subtitle will be automatically displayed\n" + " If \"number\" is omitted, the first trac is default.\n" + " -N, --native-language Specifiy the your language preference. When the first\n" + " audio track does not match your native language then\n" + " select the first subtitle that does. When used in\n" + " conjunction with --native-dub the audio track is\n" + " changed in preference to subtitles. Provide the\n" + " language's iso639-2 code (fre, eng, spa, dut, et cetera)\n" + " --native-dub Used in conjunction with --native-language\n" + " requests that if no audio tracks are selected the\n" + " default selected audio track will be the first one\n" + " that matches the --native-language. If there are no\n" + " matching audio tracks then the first matching\n" + " subtitle track is used instead.\n" + " --srt-file SubRip SRT filename(s), separated by commas.\n" + " --srt-codeset Character codeset(s) that the SRT file(s) are\n" + " encoded in, separted by commas.\n" + " Use 'iconv -l' for a list of valid\n" + " codesets. If not specified latin1 is assumed\n" + " --srt-offset Offset in milli-seconds to apply to the SRT file(s)\n" + " separted by commas. If not specified zero is assumed.\n" + " Offsets may be negative.\n" + " --srt-lang Language as an iso639-2 code fra, eng, spa et cetera)\n" + " for the SRT file(s) separated by commas. If not specified\n" + " then 'und' is used.\n" + " --srt-default Flag the selected srt as the default subtitle\n" + " to be displayed upon playback. Setting no default\n" + " means no subtitle will be automatically displayed\n" + " If \"number\" is omitted, the first srt is default.\n" + " \"number\" is an 1 based index into the srt-file list\n" "\n" @@ -2090,58 +2399,83 @@ static void ShowPresets() { printf("\n< Apple\n"); - printf("\n + Universal: -e x264 -q 0.589999973773956 -a 1,1 -E faac,ac3 -B 160,auto -R 48,Auto -6 dpl2,auto -f mp4 -X 720 -P -m -x level=30:cabac=0:ref=3:mixed-refs=1:analyse=all:me=umh:no-fast-pskip=1\n"); - - printf("\n + iPod: -e x264 -b 700 -a 1 -E faac -B 160 -R 48 -6 dpl2 -f mp4 -I -X 320 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1\n"); - - printf("\n + iPhone & iPod Touch: -e x264 -q 0.589999973773956 -a 1 -E faac -B 128 -R 48 -6 dpl2 -f mp4 -X 480 -m -x level=30:cabac=0:ref=2:mixed-refs:analyse=all:me=umh:no-fast-pskip=1\n"); - - printf("\n + AppleTV: -e x264 -q 0.589999973773956 -a 1,1 -E faac,ac3 -B 160,auto -R 48,Auto -6 dpl2,auto -f mp4 -4 -X 960 -P -m -x level=30:cabac=0:ref=3:mixed-refs=1:bframes=6:weightb=1:direct=auto:no-fast-pskip=1:me=umh:subq=7:analyse=all\n"); + printf("\n + Universal: -e x264 -q 20.0 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 -X 720 --loose-anamorphic -m -x cabac=0:ref=2:me=umh:bframes=0:8x8dct=0:trellis=0:subme=6\n"); - printf("\n + QuickTime: -e x264 -b 1800 -a 1 -E faac -B 160 -R Auto -6 dpl2 -f mp4 -p -m -2 -T -x ref=3:mixed-refs:bframes=3:weightb:direct=auto:me=umh:subme=7:analyse=all:8x8dct:trellis=1:no-fast-pskip=1:psy-rd=1,1\n"); + printf("\n + iPod: -e x264 -b 700 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4 -I -X 320 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subme=6:8x8dct=0:trellis=0\n"); - printf("\n << Legacy\n"); + printf("\n + iPhone & iPod Touch: -e x264 -q 20.0 -a 1 -E faac -B 128 -6 dpl2 -R 48 -D 0.0 -f mp4 -X 480 -m -x cabac=0:ref=2:me=umh:bframes=0:subme=6:8x8dct=0:trellis=0\n"); - printf("\n + AppleTV Legacy: -e x264 -b 2500 -a 1,1 -E faac,ac3 -B 160,auto -R 48,Auto -6 dpl2,auto -f mp4 -4 -p -m -x bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:trellis=1:cabac=0\n"); - - printf("\n + iPhone Legacy: -e x264 -b 960 -a 1 -E faac -B 128 -R 48 -6 dpl2 -f mp4 -I -X 480 -m -x level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:trellis=1\n"); - - printf("\n + iPod Legacy: -e x264 -b 1500 -a 1 -E faac -B 160 -R 48 -6 dpl2 -f mp4 -I -X 640 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1\n"); - - printf("\n >>\n"); + printf("\n + AppleTV: -e x264 -q 20.0 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 -4 -X 960 --loose-anamorphic -m -x cabac=0:ref=2:me=umh:b-adapt=2:weightb=0:trellis=0\n"); printf("\n>\n"); - printf("\n< Basic\n"); + printf("\n< Regular\n"); - printf("\n + Normal: -e x264 -b 1500 -a 1 -E faac -B 160 -R Auto -6 dpl2 -f mp4 -p -m -2 -T -x ref=2:bframes=2:me=umh\n"); + printf("\n + Normal: -e x264 -q 20.0 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4 --strict-anamorphic -m -x ref=2:bframes=2:me=umh:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0\n"); - printf("\n + Classic: -b 1000 -a 1 -E faac -B 160 -R Auto -6 dpl2 -f mp4\n"); + printf("\n + High Profile: -e x264 -q 20.0 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 --detelecine --decomb --loose-anamorphic -m -x b-pyramid:b-adapt=2:me=umh:subme=9:analyse=all:trellis=0\n"); printf("\n>\n"); - printf("\n< High Profile\n"); + printf("\n< Legacy\n"); - printf("\n + Animation: -e x264 -b 1000 -a 1 -E faac -B 160 -R Auto -6 dpl2 -f mkv --detelecine --decomb -p -m -2 -T -x ref=5:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip:filter=2,2:psy-rd=1,1:subme=9\n"); + printf("\n + Classic: -b 1000 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4\n"); - printf("\n + Constant Quality Rate: -e x264 -q 0.600000023841858 -a 1 -E ac3 -B 160 -R Auto -6 auto -f mkv -p -m -x ref=3:mixed-refs:bframes=3:b-pyramid:weightb:filter=-2,-1:trellis=1:analyse=all:8x8dct:me=umh:subme=9:psy-rd=1,1\n"); + printf("\n + AppleTV Legacy: -e x264 -b 2500 -a 1,1 -E faac,ac3 -B 160,160 -6 dpl2,auto -R 48,Auto -D 0.0,0.0 -f mp4 -4 --strict-anamorphic -m -x ref=1:subme=5:me=umh:no-fast-pskip=1:cabac=0:weightb=0:8x8dct=0:trellis=0\n"); - printf("\n + Film: -e x264 -b 1800 -a 1 -E ac3 -B 160 -R Auto -6 auto -f mkv -p -m -2 -T -x ref=3:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:subme=9:analyse=all:8x8dct:trellis=1:no-fast-pskip:psy-rd=1,1\n"); + printf("\n + iPhone Legacy: -e x264 -b 960 -a 1 -E faac -B 128 -6 dpl2 -R 48 -D 0.0 -f mp4 -I -X 480 -m -x level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:bframes=0:subme=6:8x8dct=0:trellis=0\n"); - printf("\n + Television: -e x264 -b 1300 -a 1 -E faac -B 160 -R Auto -6 dpl2 -f mkv --detelecine --decomb -p -m -2 -T -x ref=3:mixed-refs:bframes=6:weightb:direct=auto:b-pyramid:me=umh:subme=9:analyse=all:8x8dct:trellis=1:nr=150:no-fast-pskip=1:psy-rd=1,1\n"); + printf("\n + iPod Legacy: -e x264 -b 1500 -a 1 -E faac -B 160 -6 dpl2 -R 48 -D 0.0 -f mp4 -I -X 640 -m -x level=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:subme=6:8x8dct=0:trellis=0\n"); printf("\n>\n"); +} + +static char * hb_strndup( char * str, int len ) +{ + char * res; + int str_len = strlen( str ); + + res = malloc( len > str_len ? str_len + 1 : len + 1 ); + strncpy( res, str, len ); + res[len] = '\0'; + return res; +} - printf("\n< Gaming Consoles\n"); +static char** str_split( char *str, char delem ) +{ + char * pos; + char * end; + char ** ret; + int count, i; - printf("\n + PSP: -b 1024 -a 1 -E faac -B 128 -R 48 -6 dpl2 -f mp4 -X 368 -Y 208 -m\n"); + if ( str == NULL || str[0] == 0 ) + { + ret = malloc( sizeof(char*) ); + *ret = NULL; + return ret; + } - printf("\n + PS3: -e x264 -b 2500 -a 1 -E faac -B 160 -R 48 -6 dpl2 -f mp4 --crop 0:0:0:0 -p -x level=41:me=umh\n"); + // Find number of elements in the string + count = 1; + pos = str; + while ( ( pos = strchr( pos, delem ) ) != NULL ) + { + count++; + pos++; + } - printf("\n + Xbox 360: -e x264 -b 2000 -a 1 -E faac -B 160 -R 48 -6 dpl2 -f mp4 -p -x level=40:ref=2:mixed-refs:bframes=3:weightb:subme=9:direct=auto:b-pyramid:me=umh:analyse=all:no-fast-pskip:filter=-2,-1\n"); + ret = calloc( ( count + 1 ), sizeof(char*) ); - printf("\n>\n"); + pos = str; + for ( i = 0; i < count - 1; i++ ) + { + end = strchr( pos, delem ); + ret[i] = hb_strndup(pos, end - pos); + pos = end + 1; + } + ret[i] = strdup(pos); + return ret; } /**************************************************************************** @@ -2150,11 +2484,23 @@ static void ShowPresets() static int ParseOptions( int argc, char ** argv ) { - #define PREVIEWS 257 - #define START_AT_PREVIEW 258 - #define STOP_AT 259 - #define ANGLE 260 - #define DVDNAV 261 + #define PREVIEWS 257 + #define START_AT_PREVIEW 258 + #define STOP_AT 259 + #define ANGLE 260 + #define DVDNAV 261 + #define DISPLAY_WIDTH 262 + #define PIXEL_ASPECT 263 + #define MODULUS 264 + #define KEEP_DISPLAY_ASPECT 265 + #define SUB_BURNED 266 + #define SUB_DEFAULT 267 + #define NATIVE_DUB 268 + #define SRT_FILE 269 + #define SRT_CODESET 270 + #define SRT_OFFSET 271 + #define SRT_LANG 272 + #define SRT_DEFAULT 273 for( ;; ) { @@ -2182,10 +2528,16 @@ static int ParseOptions( int argc, char ** argv ) { "mixdown", required_argument, NULL, '6' }, { "drc", required_argument, NULL, 'D' }, { "subtitle", required_argument, NULL, 's' }, - { "subtitle-scan", no_argument, NULL, 'U' }, - { "subtitle-forced", no_argument, NULL, 'F' }, + { "subtitle-forced", optional_argument, NULL, 'F' }, + { "subtitle-burned", optional_argument, NULL, SUB_BURNED }, + { "subtitle-default", optional_argument, NULL, SUB_DEFAULT }, + { "srt-file", required_argument, NULL, SRT_FILE }, + { "srt-codeset", required_argument, NULL, SRT_CODESET }, + { "srt-offset", required_argument, NULL, SRT_OFFSET }, + { "srt-lang", required_argument, NULL, SRT_LANG }, + { "srt-default", optional_argument, NULL, SRT_DEFAULT }, { "native-language", required_argument, NULL,'N' }, - + { "native-dub", no_argument, NULL, NATIVE_DUB }, { "encoder", required_argument, NULL, 'e' }, { "aencoder", required_argument, NULL, 'E' }, { "two-pass", no_argument, NULL, '2' }, @@ -2195,8 +2547,14 @@ static int ParseOptions( int argc, char ** argv ) { "detelecine", optional_argument, NULL, '9' }, { "decomb", optional_argument, NULL, '5' }, { "grayscale", no_argument, NULL, 'g' }, - { "pixelratio", no_argument, NULL, 'p' }, - { "loosePixelratio", optional_argument, NULL, 'P' }, + { "strict-anamorphic", no_argument, &anamorphic_mode, 1 }, + { "loose-anamorphic", no_argument, &anamorphic_mode, 2 }, + { "custom-anamorphic", no_argument, &anamorphic_mode, 3 }, + { "display-width", required_argument, NULL, DISPLAY_WIDTH }, + { "keep-display-aspect", no_argument, &keep_display_aspect, 1 }, + { "pixel-aspect", required_argument, NULL, PIXEL_ASPECT }, + { "modulus", required_argument, NULL, MODULUS }, + { "itu-par", no_argument, &itu_par, 1 }, { "width", required_argument, NULL, 'w' }, { "height", required_argument, NULL, 'l' }, { "crop", required_argument, NULL, 'n' }, @@ -2230,7 +2588,7 @@ static int ParseOptions( int argc, char ** argv ) int c; c = getopt_long( argc, argv, - "hv::uC:f:4i:Io:t:Lc:m::M:a:A:6:s:UFN:e:E:2dD:7895gpOP::w:l:n:b:q:S:B:r:R:Qx:TY:X:Z:z", + "hv::uC:f:4i:Io:t:Lc:m::M:a:A:6:s:UF::N:e:E:2dD:7895gOw:l:n:b:q:S:B:r:R:Qx:TY:X:Z:z", long_options, &option_index ); if( c < 0 ) { @@ -2346,6 +2704,7 @@ static int ParseOptions( int argc, char ** argv ) if( optarg != NULL ) { atracks = strdup( optarg ); + audio_explicit = 1; } else { @@ -2365,17 +2724,59 @@ static int ParseOptions( int argc, char ** argv ) } break; case 's': - sub = atoi( optarg ); - break; - case 'U': - subtitle_scan = 1; + subtracks = str_split( optarg, ',' ); break; case 'F': - subtitle_force = 1; + subforce = str_split( optarg, ',' ); + break; + case SUB_BURNED: + if( optarg != NULL ) + { + subburn = strdup( optarg ); + } + else + { + subburn = "" ; + } + break; + case SUB_DEFAULT: + if( optarg != NULL ) + { + subdefault = strdup( optarg ); + } + else + { + subdefault = "" ; + } break; case 'N': native_language = strdup( optarg ); break; + case NATIVE_DUB: + native_dub = 1; + break; + case SRT_FILE: + srtfile = str_split( optarg, ',' ); + break; + case SRT_CODESET: + srtcodeset = str_split( optarg, ',' ); + break; + case SRT_OFFSET: + srtoffset = str_split( optarg, ',' ); + break; + case SRT_LANG: + srtlang = str_split( optarg, ',' ); + break; + case SRT_DEFAULT: + if( optarg != NULL ) + { + srtdefault = atoi( optarg ); + } + else + { + srtdefault = 1 ; + } + break; case '2': twoPass = 1; break; @@ -2447,14 +2848,22 @@ static int ParseOptions( int argc, char ** argv ) case 'g': grayscale = 1; break; - case 'p': - pixelratio = 1; + case DISPLAY_WIDTH: + if( optarg != NULL ) + { + sscanf( optarg, "%i", &display_width ); + } + break; + case PIXEL_ASPECT: + if( optarg != NULL ) + { + sscanf( optarg, "%i:%i", &par_width, &par_height ); + } break; - case 'P': - loosePixelratio = 1; + case MODULUS: if( optarg != NULL ) { - sscanf( optarg, "%i:%i:%i", &modulus, &par_width, &par_height ); + sscanf( optarg, "%i", &modulus ); } break; case 'e': @@ -2462,10 +2871,6 @@ static int ParseOptions( int argc, char ** argv ) { vcodec = HB_VCODEC_FFMPEG; } - else if( !strcasecmp( optarg, "xvid" ) ) - { - vcodec = HB_VCODEC_XVID; - } else if( !strcasecmp( optarg, "x264" ) ) { vcodec = HB_VCODEC_X264; @@ -2649,12 +3054,7 @@ static int CheckOptions( int argc, char ** argv ) char * p = strrchr( output, '.' ); /* autodetect */ - if( p && !strcasecmp( p, ".avi" ) ) - { - mux = HB_MUX_AVI; - default_acodec = HB_ACODEC_LAME; - } - else if( p && ( !strcasecmp( p, ".mp4" ) || + if( p && ( !strcasecmp( p, ".mp4" ) || !strcasecmp( p, ".m4v" ) ) ) { if ( h264_30 == 1 ) @@ -2663,12 +3063,6 @@ static int CheckOptions( int argc, char ** argv ) mux = HB_MUX_MP4; default_acodec = HB_ACODEC_FAAC; } - else if( p && ( !strcasecmp( p, ".ogm" ) || - !strcasecmp( p, ".ogg" ) ) ) - { - mux = HB_MUX_OGM; - default_acodec = HB_ACODEC_VORBIS; - } else if( p && !strcasecmp(p, ".mkv" ) ) { mux = HB_MUX_MKV; @@ -2681,11 +3075,6 @@ static int CheckOptions( int argc, char ** argv ) return 0; } } - else if( !strcasecmp( format, "avi" ) ) - { - mux = HB_MUX_AVI; - default_acodec = HB_ACODEC_LAME; - } else if( !strcasecmp( format, "mp4" ) || !strcasecmp( format, "m4v" ) ) { @@ -2695,12 +3084,6 @@ static int CheckOptions( int argc, char ** argv ) mux = HB_MUX_MP4; default_acodec = HB_ACODEC_FAAC; } - else if( !strcasecmp( format, "ogm" ) || - !strcasecmp( format, "ogg" ) ) - { - mux = HB_MUX_OGM; - default_acodec = HB_ACODEC_VORBIS; - } else if( !strcasecmp( format, "mkv" ) ) { mux = HB_MUX_MKV; @@ -2709,7 +3092,7 @@ static int CheckOptions( int argc, char ** argv ) else { fprintf( stderr, "Invalid output format (%s). Possible " - "choices are avi, mp4, m4v, ogm, ogg and mkv\n.", format ); + "choices are mp4, m4v and mkv\n.", format ); return 1; } } @@ -2739,6 +3122,12 @@ static int get_acodec_for_string( char *codec ) { return HB_ACODEC_VORBIS; } +#ifdef __APPLE__ + else if( !strcasecmp( codec, "ca_aac") ) + { + return HB_ACODEC_CA_AAC; + } +#endif else { return -1; @@ -2901,7 +3290,7 @@ static int is_dvd_service( io_service_t service ) * The whole media object is indicated in the IORegistry by the presence of a * property with the key "Whole" and value "Yes". ****************************************************************************/ -static is_whole_media_service( io_service_t service ) +static int is_whole_media_service( io_service_t service ) { int result = 0;