From 1db521ccbaed90dfbe1e922400ffc3334a19e66c Mon Sep 17 00:00:00 2001 From: sr55 Date: Sat, 15 Jun 2013 13:23:11 +0000 Subject: [PATCH] Merging Trunk into OpenCL git-svn-id: svn://svn.handbrake.fr/HandBrake/branches/opencl@5580 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- gtk/src/callbacks.c | 29 + gtk/src/hb-backend.c | 2 +- gtk/src/main.c | 2 + gtk/src/presets.c | 377 +++--- gtk/src/standard_presets.xml | 137 +- libhb/common.c | 1177 +++++++++++------ libhb/common.h | 7 +- libhb/hb.c | 135 +- libhb/hb.h | 3 + libhb/ports.c | 35 + libhb/ports.h | 1 + macosx/Controller.m | 78 +- macosx/HBAudio.m | 2 +- macosx/HBPreferencesController.m | 8 +- macosx/HBPresets.m | 105 ++ macosx/main.mm | 7 +- scripts/manicure.rb | 64 +- test/test.c | 107 +- win/CS/HandBrakeWPF/HandBrakeWPF.csproj | 2 + win/CS/HandBrakeWPF/Helpers/AppStyleHelper.cs | 37 + win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs | 30 +- win/CS/HandBrakeWPF/Model/SourceMenuItem.cs | 5 + .../Properties/Resources.Designer.cs | 45 + win/CS/HandBrakeWPF/Properties/Resources.resx | 15 + win/CS/HandBrakeWPF/UserSettingConstants.cs | 15 + .../HandBrakeWPF/ViewModels/MainViewModel.cs | 63 +- .../ViewModels/OptionsViewModel.cs | 47 + .../ViewModels/PictureSettingsViewModel.cs | 36 +- .../HandBrakeWPF/ViewModels/ShellViewModel.cs | 1 + .../HandBrakeWPF/ViewModels/VideoViewModel.cs | 14 +- .../HandBrakeWPF/ViewModels/ViewModelBase.cs | 12 + win/CS/HandBrakeWPF/Views/AudioView.xaml | 17 +- win/CS/HandBrakeWPF/Views/ChaptersView.xaml | 4 +- win/CS/HandBrakeWPF/Views/MainView.xaml | 111 +- win/CS/HandBrakeWPF/Views/OptionsView.xaml | 18 +- win/CS/HandBrakeWPF/Views/ShellView.xaml | 10 +- win/CS/HandBrakeWPF/Views/Styles/Styles.xaml | 35 +- win/CS/HandBrakeWPF/Views/SubtitlesView.xaml | 17 +- win/CS/HandBrakeWPF/Views/VideoView.xaml | 25 +- win/CS/HandBrakeWPF/defaultsettings.xml | 24 + 40 files changed, 1986 insertions(+), 873 deletions(-) create mode 100644 win/CS/HandBrakeWPF/Helpers/AppStyleHelper.cs diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index e6b4714cb..eead66275 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -1600,6 +1600,35 @@ set_title_settings(GValue *settings, gint titleindex) ghb_set_scale_settings(settings, GHB_PIC_KEEP_PAR|GHB_PIC_USE_MAX); ghb_settings_set_int(settings, "angle_count", title->angle_count); + + ghb_settings_set_string(settings, "MetaName", title->name); + if (title->metadata) + { + if (title->metadata->name) + { + ghb_settings_set_string(settings, "MetaName", + title->metadata->name); + } + ghb_settings_set_string(settings, "MetaArtist", + title->metadata->artist); + ghb_settings_set_string(settings, "MetaReleaseDate", + title->metadata->release_date); + ghb_settings_set_string(settings, "MetaComment", + title->metadata->comment); + if (!title->metadata->name && title->metadata->album) + { + ghb_settings_set_string(settings, "MetaName", + title->metadata->album); + } + ghb_settings_set_string(settings, "MetaAlbumArtist", + title->metadata->album_artist); + ghb_settings_set_string(settings, "MetaGenre", + title->metadata->genre); + ghb_settings_set_string(settings, "MetaDescription", + title->metadata->description); + ghb_settings_set_string(settings, "MetaLongDescription", + title->metadata->long_description); + } } update_chapter_list_settings(settings); ghb_set_pref_audio_settings(titleindex, settings); diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index b3f82067c..ace8291b4 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -1891,7 +1891,7 @@ mix_opts_set(GtkBuilder *builder, const gchar *name) 1, TRUE, 2, mix->short_name, 3, (gdouble)mix->amixdown, - 4, mix->internal_name, + 4, mix->short_name, -1); g_free(str); } diff --git a/gtk/src/main.c b/gtk/src/main.c index b990ec0c4..b656f7812 100644 --- a/gtk/src/main.c +++ b/gtk/src/main.c @@ -849,6 +849,8 @@ main(int argc, char *argv[]) GError *error = NULL; GOptionContext *context; + hb_global_init(); + #ifdef ENABLE_NLS bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); diff --git a/gtk/src/presets.c b/gtk/src/presets.c index 12fdfbd67..8562401e7 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -2018,158 +2018,6 @@ typedef struct const gchar *lin_val; } value_map_t; -static value_map_t vcodec_xlat_compat[] = -{ - {"MPEG-4 (FFmpeg)", "ffmpeg"}, - {"MPEG-4 (XviD)", "ffmpeg4"}, - {NULL,NULL} -}; - -static value_map_t *vcodec_xlat; - -static value_map_t acodec_xlat_compat[] = -{ - {"AAC (CoreAudio)", "faac"}, - {"HE-AAC (CoreAudio)", "faac"}, - {"AC3 (ffmpeg)", "ac3"}, - {"AC3", "ac3"}, - {"MP3 Passthru", "mp3pass"}, - {"AAC Passthru", "aacpass"}, - {"AC3 Passthru", "ac3pass"}, - {"DTS Passthru", "dtspass"}, - {"DTS-HD Passthru", "dtshdpass"}, - {"Auto Passthru", "auto"}, - {NULL,NULL} -}; - -static value_map_t *acodec_xlat; - -static value_map_t * create_video_encoder_xlat_tbl(value_map_t *compat) -{ - value_map_t *out; - int cc, ii, size = 0; - - for (cc = 0; compat[cc].mac_val != NULL; cc++); - - const hb_encoder_t *enc; - for (enc = hb_video_encoder_get_next(NULL); enc != NULL; - enc = hb_video_encoder_get_next(enc)) - { - size++; - } - out = calloc(cc + size + 1, sizeof(value_map_t)); - - for (ii = 0, enc = hb_video_encoder_get_next(NULL); enc != NULL; - ii++, enc = hb_video_encoder_get_next(enc)) - { - out[ii].mac_val = enc->name; - out[ii].lin_val = enc->short_name; - } - - for (ii = 0; ii < cc; ii++) - out[ii+size] = compat[ii]; - - return out; -} - -static value_map_t * create_audio_encoder_xlat_tbl(value_map_t *compat) -{ - value_map_t *out; - int cc, ii, size = 0; - - for (cc = 0; compat[cc].mac_val != NULL; cc++); - - const hb_encoder_t *enc; - for (enc = hb_audio_encoder_get_next(NULL); enc != NULL; - enc = hb_audio_encoder_get_next(enc)) - { - size++; - } - out = calloc(cc + size + 1, sizeof(value_map_t)); - - for (ii = 0, enc = hb_audio_encoder_get_next(NULL); enc != NULL; - ii++, enc = hb_audio_encoder_get_next(enc)) - { - out[ii].mac_val = enc->name; - out[ii].lin_val = enc->short_name; - } - - for (ii = 0; ii < cc; ii++) - out[ii+size] = compat[ii]; - - return out; -} - -static value_map_t * create_mix_xlat_tbl(value_map_t *compat) -{ - value_map_t *out; - int cc, ii, size = 0;; - - for (cc = 0; compat[cc].mac_val != NULL; cc++); - - const hb_mixdown_t *mix; - for (mix = hb_mixdown_get_next(NULL); mix != NULL; - mix = hb_mixdown_get_next(mix)) - { - size++; - } - out = calloc(cc + size + 1, sizeof(value_map_t)); - - for (ii = 0, mix = hb_mixdown_get_next(NULL); mix != NULL; - ii++, mix = hb_mixdown_get_next(mix)) - { - out[ii].mac_val = mix->name; - out[ii].lin_val = mix->short_name; - } - - for (ii = 0; ii < cc; ii++) - out[ii+size] = compat[ii]; - - return out; -} - -value_map_t framerate_xlat[] = -{ - {"Same as source", "source"}, - {"5", "5"}, - {"10", "10"}, - {"12", "12"}, - {"15", "15"}, - {"23.976 (NTSC Film)", "23.976"}, - {"24", "24"}, - {"25 (PAL Film/Video)", "25"}, - {"29.97 (NTSC Video)", "29.97"}, - {"30", "30"}, - {"50", "50"}, - {"59.94", "59.94"}, - {"60", "60"}, - {NULL, NULL} -}; - -value_map_t samplerate_xlat[] = -{ - {"Auto", "source"}, - {"22.05", "22.05"}, - {"24", "24"}, - {"32", "32"}, - {"44.1", "44.1"}, - {"48", "48"}, - {NULL, NULL} -}; - -// mix translation table filed in with hb_audio_mixdowns table contents -value_map_t *mix_xlat; - -// Backwards compatibility mappings for audio mix -value_map_t mix_xlat_compat[] = -{ - {"6-channel discrete", "5point1"}, - {"AC3 Passthru", "none"}, - {"DTS Passthru", "none"}, - {"DTS-HD Passthru", "none"}, - {NULL, NULL} -}; - value_map_t deint_xlat[] = { {"0", "off"}, @@ -2394,17 +2242,95 @@ export_value_xlat2(value_map_t *value_map, GValue *lin_val, GType mac_type) } static GValue* -export_value_xlat_container(GValue *lin_val) +export_value_video_framerate(GValue *lin_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *fr; + + str = ghb_value_string(lin_val); + fr = hb_video_framerate_get_name(hb_video_framerate_get_from_name(str)); + g_free(str); + if (fr != NULL) + sval = ghb_string_value_new(fr); + + return sval; +} + +static GValue* +export_value_audio_samplerate(GValue *lin_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *sr; + + str = ghb_value_string(lin_val); + sr = hb_audio_samplerate_get_name(hb_audio_samplerate_get_from_name(str)); + g_free(str); + if (sr != NULL) + sval = ghb_string_value_new(sr); + + return sval; +} + +static GValue* +export_value_mixdown(GValue *lin_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *mix; + + str = ghb_value_string(lin_val); + mix = hb_mixdown_get_name(hb_mixdown_get_from_name(str)); + g_free(str); + if (mix != NULL) + sval = ghb_string_value_new(mix); + + return sval; +} + +static GValue* +export_value_video_encoder(GValue *lin_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *enc; + + str = ghb_value_string(lin_val); + enc = hb_video_encoder_get_name(hb_video_encoder_get_from_name(str)); + g_free(str); + if (enc != NULL) + sval = ghb_string_value_new(enc); + + return sval; +} + +static GValue* +export_value_audio_encoder(GValue *lin_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *enc; + + str = ghb_value_string(lin_val); + enc = hb_audio_encoder_get_name(hb_audio_encoder_get_from_name(str)); + g_free(str); + if (enc != NULL) + sval = ghb_string_value_new(enc); + + return sval; +} + +static GValue* +export_value_container(GValue *lin_val) { GValue *sval = NULL; gchar *str; const gchar *mux; - int imux; str = ghb_value_string(lin_val); - imux = hb_container_get_from_name(str); + mux = hb_container_get_name(hb_container_get_from_name(str)); g_free(str); - mux = hb_container_get_name(imux); if (mux != NULL) sval = ghb_string_value_new(mux); @@ -2419,17 +2345,17 @@ export_value_xlat(GValue *dict) key = "VideoEncoder"; lin_val = ghb_dict_lookup(dict, key); - gval = export_value_xlat2(vcodec_xlat, lin_val, G_TYPE_STRING); + gval = export_value_video_encoder(lin_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); key = "FileFormat"; lin_val = ghb_dict_lookup(dict, key); - gval = export_value_xlat_container(lin_val); + gval = export_value_container(lin_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); key = "VideoFramerate"; lin_val = ghb_dict_lookup(dict, key); - gval = export_value_xlat2(framerate_xlat, lin_val, G_TYPE_STRING); + gval = export_value_video_framerate(lin_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); key = "PictureDetelecine"; @@ -2474,7 +2400,7 @@ export_value_xlat(GValue *dict) key = "AudioEncoderFallback"; lin_val = ghb_dict_lookup(dict, key); - gval = export_value_xlat2(acodec_xlat, lin_val, G_TYPE_STRING); + gval = export_value_audio_encoder(lin_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); @@ -2490,17 +2416,17 @@ export_value_xlat(GValue *dict) ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioEncoder"; lin_val = ghb_dict_lookup(adict, key); - gval = export_value_xlat2(acodec_xlat, lin_val, G_TYPE_STRING); + gval = export_value_audio_encoder(lin_val); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioSamplerate"; lin_val = ghb_dict_lookup(adict, key); - gval = export_value_xlat2(samplerate_xlat, lin_val, G_TYPE_STRING); + gval = export_value_audio_samplerate(lin_val); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioMixdown"; lin_val = ghb_dict_lookup(adict, key); - gval = export_value_xlat2(mix_xlat, lin_val, G_TYPE_STRING); + gval = export_value_mixdown(lin_val); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); } @@ -2579,26 +2505,100 @@ import_value_xlat2( } static GValue* -import_value_xlat_container(GValue *mac_val) +import_value_video_framerate(GValue *mac_val) { GValue *sval = NULL; gchar *str; - const gchar *mux; - int imux; + const gchar *fr; str = ghb_value_string(mac_val); - mux = hb_container_sanitize_name(str); + fr = hb_video_framerate_get_name(hb_video_framerate_get_from_name(str)); g_free(str); - if (mux == NULL) - { - imux = hb_container_get_from_extension("mp4"); - } - else - { - imux = hb_container_get_from_name(mux); - } - mux = hb_container_get_short_name(imux); + if (fr != NULL) + sval = ghb_string_value_new(fr); + + return sval; +} + +static GValue* +import_value_audio_samplerate(GValue *mac_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *sr; + + str = ghb_value_string(mac_val); + sr = hb_audio_samplerate_get_name(hb_audio_samplerate_get_from_name(str)); + g_free(str); + + if (sr != NULL) + sval = ghb_string_value_new(sr); + + return sval; +} + +static GValue* +import_value_mixdown(GValue *mac_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *mix; + + str = ghb_value_string(mac_val); + mix = hb_mixdown_get_short_name(hb_mixdown_get_from_name(str)); + g_free(str); + + if (mix != NULL) + sval = ghb_string_value_new(mix); + + return sval; +} + +static GValue* +import_value_video_encoder(GValue *mac_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *enc; + + str = ghb_value_string(mac_val); + enc = hb_video_encoder_get_short_name(hb_video_encoder_get_from_name(str)); + g_free(str); + + if (enc != NULL) + sval = ghb_string_value_new(enc); + + return sval; +} + +static GValue* +import_value_audio_encoder(GValue *mac_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *enc; + + str = ghb_value_string(mac_val); + enc = hb_audio_encoder_get_short_name(hb_audio_encoder_get_from_name(str)); + g_free(str); + + if (enc != NULL) + sval = ghb_string_value_new(enc); + + return sval; +} + +static GValue* +import_value_container(GValue *mac_val) +{ + GValue *sval = NULL; + gchar *str; + const gchar *mux; + + str = ghb_value_string(mac_val); + mux = hb_container_get_short_name(hb_container_get_from_name(str)); + g_free(str); if (mux != NULL) sval = ghb_string_value_new(mux); @@ -2615,17 +2615,17 @@ import_value_xlat(GValue *dict) defaults = plist_get_dict(internalPlist, "Presets"); key = "VideoEncoder"; mac_val = ghb_dict_lookup(dict, key); - gval = import_value_xlat2(defaults, vcodec_xlat, key, mac_val); + gval = import_value_video_encoder(mac_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); key = "FileFormat"; mac_val = ghb_dict_lookup(dict, key); - gval = import_value_xlat_container(mac_val); + gval = import_value_container(mac_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); key = "VideoFramerate"; mac_val = ghb_dict_lookup(dict, key); - gval = import_value_xlat2(defaults, framerate_xlat, key, mac_val); + gval = import_value_video_framerate(mac_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); key = "PictureDetelecine"; @@ -2725,7 +2725,7 @@ import_value_xlat(GValue *dict) key = "AudioEncoderFallback"; mac_val = ghb_dict_lookup(dict, key); - gval = import_value_xlat2(defaults, acodec_xlat, key, mac_val); + gval = import_value_audio_encoder(mac_val); if (gval) ghb_dict_insert(dict, g_strdup(key), gval); @@ -2745,17 +2745,23 @@ import_value_xlat(GValue *dict) ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioEncoder"; mac_val = ghb_dict_lookup(adict, key); - gval = import_value_xlat2(adefaults, acodec_xlat, key, mac_val); + gval = import_value_audio_encoder(mac_val); + if (gval == NULL) + gval = ghb_value_dup(ghb_dict_lookup(adefaults, key)); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioSamplerate"; mac_val = ghb_dict_lookup(adict, key); - gval = import_value_xlat2(adefaults, samplerate_xlat, key, mac_val); + gval = import_value_audio_samplerate(mac_val); + if (gval == NULL) + gval = ghb_value_dup(ghb_dict_lookup(adefaults, key)); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); key = "AudioMixdown"; mac_val = ghb_dict_lookup(adict, key); - gval = import_value_xlat2(adefaults, mix_xlat, key, mac_val); + gval = import_value_mixdown(mac_val); + if (gval == NULL) + gval = ghb_value_dup(ghb_dict_lookup(adefaults, key)); if (gval) ghb_dict_insert(adict, g_strdup(key), gval); @@ -3381,11 +3387,6 @@ update_standard_presets(signal_user_data_t *ud) void ghb_presets_load(signal_user_data_t *ud) { - // Create translation tables from libhb tables - mix_xlat = create_mix_xlat_tbl(mix_xlat_compat); - acodec_xlat = create_audio_encoder_xlat_tbl(acodec_xlat_compat); - vcodec_xlat = create_video_encoder_xlat_tbl(vcodec_xlat_compat); - presetsPlist = load_plist("presets"); if (presetsPlist == NULL) { diff --git a/gtk/src/standard_presets.xml b/gtk/src/standard_presets.xml index f73475bd8..989f892de 100644 --- a/gtk/src/standard_presets.xml +++ b/gtk/src/standard_presets.xml @@ -1266,13 +1266,146 @@ x264UseAdvancedOptions 0 + + AudioAllowAACPass + 1 + AudioAllowAC3Pass + 1 + AudioAllowDTSHDPass + 1 + AudioAllowDTSPass + 1 + AudioAllowMP3Pass + 1 + AudioEncoderFallback + AC3 (ffmpeg) + AudioList + + + AudioBitrate + 128 + AudioEncoder + AAC (faac) + AudioMixdown + Dolby Pro Logic II + AudioSamplerate + Auto + AudioTrack + 1 + AudioTrackDRCSlider + 0.0 + AudioTrackGainSlider + 0.0 + + + ChapterMarkers + 0 + Default + 0 + FileFormat + MP4 file + Folder + + Mp4HttpOptimize + 0 + Mp4LargeFile + 0 + Mp4iPodCompatible + 0 + PictureAutoCrop + 1 + PictureBottomCrop + 0 + PictureDeblock + 0 + PictureDecomb + 0 + PictureDecombCustom + + PictureDecombDeinterlace + 1 + PictureDeinterlace + 0 + PictureDeinterlaceCustom + + PictureDenoise + 0 + PictureDenoiseCustom + + PictureDetelecine + 0 + PictureDetelecineCustom + + PictureHeight + 720 + PictureKeepRatio + 0 + PictureLeftCrop + 0 + PictureModulus + 2 + PicturePAR + 2 + PictureRightCrop + 0 + PictureTopCrop + 0 + PictureWidth + 1280 + PresetDescription + HandBrake's preset for Windows Phone 8 devices + PresetName + Windows Phone 8 + Subtitles + None + Type + 0 + UsesPictureFilters + 1 + UsesPictureSettings + 1 + VideoAvgBitrate + 2500 + VideoEncoder + H.264 (x264) + VideoFramerate + 30 + VideoFramerateMode + pfr + VideoGrayScale + 0 + VideoQualitySlider + 22 + VideoQualityType + 2 + VideoTurboTwoPass + 0 + VideoTwoPass + 0 + h264Level + 3.1 + h264Profile + main + lavcOption + + x264Option + + x264OptionExtra + + x264Preset + medium + x264Tune + + x264UseAdvancedOptions + 0 + Default 0 Folder PresetBuildNumber - 2013030401 + 2013061301 PresetName Devices Type @@ -1569,7 +1702,7 @@ Folder PresetBuildNumber - 2013030401 + 2013061301 PresetName Regular Type diff --git a/libhb/common.c b/libhb/common.c index c59f063cc..5766066ac 100644 --- a/libhb/common.c +++ b/libhb/common.c @@ -21,164 +21,585 @@ *********************************************************************/ static hb_error_handler_t *error_handler = NULL; -hb_rate_t hb_video_rates[] = -{ - { "5", 5400000 }, - { "10", 2700000 }, - { "12", 2250000 }, - { "15", 1800000 }, - { "23.976", 1126125 }, - { "24", 1125000 }, - { "25", 1080000 }, - { "29.97", 900900 }, - { "30", 900000 }, - { "50", 540000 }, - { "59.94", 450450 }, - { "60", 450000 }, +/* Generic IDs for encoders, containers, etc. */ +enum +{ + HB_GID_NONE = -1, // encoders must NEVER use it + HB_GID_VCODEC_H264, + HB_GID_VCODEC_MPEG2, + HB_GID_VCODEC_MPEG4, + HB_GID_VCODEC_THEORA, + HB_GID_ACODEC_AAC, + HB_GID_ACODEC_AAC_HE, + HB_GID_ACODEC_AAC_PASS, + HB_GID_ACODEC_AC3, + HB_GID_ACODEC_AC3_PASS, + HB_GID_ACODEC_AUTO_PASS, + HB_GID_ACODEC_DTS_PASS, + HB_GID_ACODEC_DTSHD_PASS, + HB_GID_ACODEC_FLAC, + HB_GID_ACODEC_MP3, + HB_GID_ACODEC_MP3_PASS, + HB_GID_ACODEC_VORBIS, + HB_GID_MUX_MKV, + HB_GID_MUX_MP4, }; -int hb_video_rates_count = sizeof(hb_video_rates) / sizeof(hb_rate_t); - -hb_rate_t hb_audio_rates[] = -{ - { "8", 8000 }, - { "11.025", 11025 }, - { "12", 12000 }, - { "16", 16000 }, - { "22.05", 22050 }, - { "24", 24000 }, - { "32", 32000 }, - { "44.1", 44100 }, - { "48", 48000 }, + +typedef struct +{ + hb_rate_t item; + hb_rate_t *next; + int enabled; +} hb_rate_internal_t; +hb_rate_t *hb_video_rates_first_item = NULL; +hb_rate_t *hb_video_rates_last_item = NULL; +hb_rate_internal_t hb_video_rates[] = +{ + // legacy framerates (disabled) + { { "23.976 (NTSC Film)", 1126125, }, NULL, 0, }, + { { "25 (PAL Film/Video)", 1080000, }, NULL, 0, }, + { { "29.97 (NTSC Video)", 900900, }, NULL, 0, }, + // actual framerates + { { "5", 5400000, }, NULL, 1, }, + { { "10", 2700000, }, NULL, 1, }, + { { "12", 2250000, }, NULL, 1, }, + { { "15", 1800000, }, NULL, 1, }, + { { "23.976", 1126125, }, NULL, 1, }, + { { "24", 1125000, }, NULL, 1, }, + { { "25", 1080000, }, NULL, 1, }, + { { "29.97", 900900, }, NULL, 1, }, + { { "30", 900000, }, NULL, 1, }, + { { "50", 540000, }, NULL, 1, }, + { { "59.94", 450450, }, NULL, 1, }, + { { "60", 450000, }, NULL, 1, }, +}; +int hb_video_rates_count = sizeof(hb_video_rates) / sizeof(hb_video_rates[0]); + +hb_rate_t *hb_audio_rates_first_item = NULL; +hb_rate_t *hb_audio_rates_last_item = NULL; +hb_rate_internal_t hb_audio_rates[] = +{ + { { "8", 8000, }, NULL, 1, }, + { { "11.025", 11025, }, NULL, 1, }, + { { "12", 12000, }, NULL, 1, }, + { { "16", 16000, }, NULL, 1, }, + { { "22.05", 22050, }, NULL, 1, }, + { { "24", 24000, }, NULL, 1, }, + { { "32", 32000, }, NULL, 1, }, + { { "44.1", 44100, }, NULL, 1, }, + { { "48", 48000, }, NULL, 1, }, }; -int hb_audio_rates_count = sizeof(hb_audio_rates) / sizeof(hb_rate_t); +int hb_audio_rates_count = sizeof(hb_audio_rates) / sizeof(hb_audio_rates[0]); -hb_rate_t hb_audio_bitrates[] = +hb_rate_t *hb_audio_bitrates_first_item = NULL; +hb_rate_t *hb_audio_bitrates_last_item = NULL; +hb_rate_internal_t hb_audio_bitrates[] = { // AC3-compatible bitrates - { "32", 32 }, - { "40", 40 }, - { "48", 48 }, - { "56", 56 }, - { "64", 64 }, - { "80", 80 }, - { "96", 96 }, - { "112", 112 }, - { "128", 128 }, - { "160", 160 }, - { "192", 192 }, - { "224", 224 }, - { "256", 256 }, - { "320", 320 }, - { "384", 384 }, - { "448", 448 }, - { "512", 512 }, - { "576", 576 }, - { "640", 640 }, + { { "32", 32, }, NULL, 1, }, + { { "40", 40, }, NULL, 1, }, + { { "48", 48, }, NULL, 1, }, + { { "56", 56, }, NULL, 1, }, + { { "64", 64, }, NULL, 1, }, + { { "80", 80, }, NULL, 1, }, + { { "96", 96, }, NULL, 1, }, + { { "112", 112, }, NULL, 1, }, + { { "128", 128, }, NULL, 1, }, + { { "160", 160, }, NULL, 1, }, + { { "192", 192, }, NULL, 1, }, + { { "224", 224, }, NULL, 1, }, + { { "256", 256, }, NULL, 1, }, + { { "320", 320, }, NULL, 1, }, + { { "384", 384, }, NULL, 1, }, + { { "448", 448, }, NULL, 1, }, + { { "512", 512, }, NULL, 1, }, + { { "576", 576, }, NULL, 1, }, + { { "640", 640, }, NULL, 1, }, // additional bitrates - { "768", 768 }, - { "960", 960 }, - { "1152", 1152 }, - { "1344", 1344 }, - { "1536", 1536 }, + { { "768", 768, }, NULL, 1, }, + { { "960", 960, }, NULL, 1, }, + { { "1152", 1152, }, NULL, 1, }, + { { "1344", 1344, }, NULL, 1, }, + { { "1536", 1536, }, NULL, 1, }, }; -int hb_audio_bitrates_count = sizeof(hb_audio_bitrates) / sizeof(hb_rate_t); - -hb_dither_t hb_audio_dithers[] = -{ - { "default", "auto", AV_RESAMPLE_DITHER_NONE - 1, }, - { "none", "none", AV_RESAMPLE_DITHER_NONE, }, - { "rectangular", "rectangular", AV_RESAMPLE_DITHER_RECTANGULAR, }, - { "triangular", "triangular", AV_RESAMPLE_DITHER_TRIANGULAR, }, - { "triangular with high pass", "triangular_hp", AV_RESAMPLE_DITHER_TRIANGULAR_HP, }, - { "triangular with noise shaping", "triangular_ns", AV_RESAMPLE_DITHER_TRIANGULAR_NS, }, +int hb_audio_bitrates_count = sizeof(hb_audio_bitrates) / sizeof(hb_audio_bitrates[0]); + +typedef struct +{ + hb_dither_t item; + hb_dither_t *next; + int enabled; +} hb_dither_internal_t; +hb_dither_t *hb_audio_dithers_first_item = NULL; +hb_dither_t *hb_audio_dithers_last_item = NULL; +hb_dither_internal_t hb_audio_dithers[] = +{ + { { "default", "auto", AV_RESAMPLE_DITHER_NONE - 1, }, NULL, 1, }, + { { "none", "none", AV_RESAMPLE_DITHER_NONE, }, NULL, 1, }, + { { "rectangular", "rectangular", AV_RESAMPLE_DITHER_RECTANGULAR, }, NULL, 1, }, + { { "triangular", "triangular", AV_RESAMPLE_DITHER_TRIANGULAR, }, NULL, 1, }, + { { "triangular with high pass", "triangular_hp", AV_RESAMPLE_DITHER_TRIANGULAR_HP, }, NULL, 1, }, + { { "triangular with noise shaping", "triangular_ns", AV_RESAMPLE_DITHER_TRIANGULAR_NS, }, NULL, 1, }, }; -int hb_audio_dithers_count = sizeof(hb_audio_dithers) / sizeof(hb_dither_t); - -hb_mixdown_t hb_audio_mixdowns[] = -{ - { "None", "HB_AMIXDOWN_NONE", "none", HB_AMIXDOWN_NONE }, - { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO }, - { "Mono (Left Only)", "HB_AMIXDOWN_LEFT", "left_only", HB_AMIXDOWN_LEFT }, - { "Mono (Right Only)", "HB_AMIXDOWN_RIGHT", "right_only", HB_AMIXDOWN_RIGHT }, - { "Stereo", "HB_AMIXDOWN_STEREO", "stereo", HB_AMIXDOWN_STEREO }, - { "Dolby Surround", "HB_AMIXDOWN_DOLBY", "dpl1", HB_AMIXDOWN_DOLBY }, - { "Dolby Pro Logic II", "HB_AMIXDOWN_DOLBYPLII", "dpl2", HB_AMIXDOWN_DOLBYPLII }, - { "5.1 Channels", "HB_AMIXDOWN_5POINT1", "5point1", HB_AMIXDOWN_5POINT1 }, - { "6.1 Channels", "HB_AMIXDOWN_6POINT1", "6point1", HB_AMIXDOWN_6POINT1 }, - { "7.1 Channels", "HB_AMIXDOWN_7POINT1", "7point1", HB_AMIXDOWN_7POINT1 }, - { "7.1 (5F/2R/LFE)", "HB_AMIXDOWN_5_2_LFE", "5_2_lfe", HB_AMIXDOWN_5_2_LFE }, +int hb_audio_dithers_count = sizeof(hb_audio_dithers) / sizeof(hb_audio_dithers[0]); + +typedef struct +{ + hb_mixdown_t item; + hb_mixdown_t *next; + int enabled; +} hb_mixdown_internal_t; +hb_mixdown_t *hb_audio_mixdowns_first_item = NULL; +hb_mixdown_t *hb_audio_mixdowns_last_item = NULL; +hb_mixdown_internal_t hb_audio_mixdowns[] = +{ + // legacy mixdowns (disabled) + { { "AC3 Passthru", "ac3pass", HB_AMIXDOWN_NONE, }, NULL, 0, }, + { { "DTS Passthru", "dtspass", HB_AMIXDOWN_NONE, }, NULL, 0, }, + { { "DTS-HD Passthru", "dtshdpass", HB_AMIXDOWN_NONE, }, NULL, 0, }, + { { "6-channel discrete", "6ch", HB_AMIXDOWN_5POINT1, }, NULL, 0, }, + // actual mixdowns + { { "None", "none", HB_AMIXDOWN_NONE, }, NULL, 1, }, + { { "Mono", "mono", HB_AMIXDOWN_MONO, }, NULL, 1, }, + { { "Mono (Left Only)", "left_only", HB_AMIXDOWN_LEFT, }, NULL, 1, }, + { { "Mono (Right Only)", "right_only", HB_AMIXDOWN_RIGHT, }, NULL, 1, }, + { { "Stereo", "stereo", HB_AMIXDOWN_STEREO, }, NULL, 1, }, + { { "Dolby Surround", "dpl1", HB_AMIXDOWN_DOLBY, }, NULL, 1, }, + { { "Dolby Pro Logic II", "dpl2", HB_AMIXDOWN_DOLBYPLII, }, NULL, 1, }, + { { "5.1 Channels", "5point1", HB_AMIXDOWN_5POINT1, }, NULL, 1, }, + { { "6.1 Channels", "6point1", HB_AMIXDOWN_6POINT1, }, NULL, 1, }, + { { "7.1 Channels", "7point1", HB_AMIXDOWN_7POINT1, }, NULL, 1, }, + { { "7.1 (5F/2R/LFE)", "5_2_lfe", HB_AMIXDOWN_5_2_LFE, }, NULL, 1, }, }; -int hb_audio_mixdowns_count = sizeof(hb_audio_mixdowns) / sizeof(hb_mixdown_t); - -hb_encoder_t hb_video_encoders[] = -{ - { "H.264 (x264)", "x264", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MASK_MKV }, +int hb_audio_mixdowns_count = sizeof(hb_audio_mixdowns) / sizeof(hb_audio_mixdowns[0]); + +typedef struct +{ + hb_encoder_t item; + hb_encoder_t *next; + int enabled; + int gid; +} hb_encoder_internal_t; +hb_encoder_t *hb_video_encoders_first_item = NULL; +hb_encoder_t *hb_video_encoders_last_item = NULL; +hb_encoder_internal_t hb_video_encoders[] = +{ + // legacy encoders, all the way back to HB 0.7.1 (disabled) + { { "x264 (Main profile)", "", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_H264, }, + { { "x264 (Baseline profile)", "", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_H264, }, + { { "x264 (h.264 Main)", "", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_H264, }, + { { "x264 (h.264 iPod)", "", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_H264, }, + { { "", "x264b13", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_H264, }, + { { "", "x264b30", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_H264, }, + { { "XviD", "xvid", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, + { { "MPEG-4 (XviD)", "", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, + { { "FFmpeg", "ffmpeg", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_VCODEC_MPEG4, }, + // actual encoders + { { "H.264 (x264)", "x264", HB_VCODEC_X264, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_H264, }, + { { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG4, }, + { { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_MPEG2, }, + { { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_VCODEC_THEORA, }, }; -int hb_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_encoder_t); +int hb_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_video_encoders[0]); +static int hb_video_encoder_is_enabled(int encoder) +{ + switch (encoder) + { + // the following encoders are always enabled + case HB_VCODEC_X264: + case HB_VCODEC_THEORA: + case HB_VCODEC_FFMPEG_MPEG4: + case HB_VCODEC_FFMPEG_MPEG2: + return 1; + + default: + return 0; + } +} -// note: the first encoder in the list must be AAC -hb_encoder_t hb_audio_encoders[] = +hb_encoder_t *hb_audio_encoders_first_item = NULL; +hb_encoder_t *hb_audio_encoders_last_item = NULL; +hb_encoder_internal_t hb_audio_encoders[] = +{ + // legacy encoders (disabled) + { { "AC3", "ac3", HB_ACODEC_AC3, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_ACODEC_AC3, }, + { { "AC3 (pass-thru)", "ac3pass", HB_ACODEC_AC3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_ACODEC_AC3_PASS, }, + { { "DTS (pass-thru)", "dtspass", HB_ACODEC_DCA_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_ACODEC_DTS_PASS, }, + { { "", "dts", HB_ACODEC_DCA_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 0, HB_GID_ACODEC_DTS_PASS, }, + // actual encoders + { { "AAC (CoreAudio)", "ca_aac", HB_ACODEC_CA_AAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC, }, + { { "HE-AAC (CoreAudio)", "ca_haac", HB_ACODEC_CA_HAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC_HE, }, + { { "AAC (FDK)", "fdk_aac", HB_ACODEC_FDK_AAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC, }, + { { "HE-AAC (FDK)", "fdk_haac", HB_ACODEC_FDK_HAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC_HE, }, + { { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC, }, + { { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC, }, + { { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AAC_PASS, }, + { { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AC3, }, + { { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AC3_PASS, }, + { { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_DTS_PASS, }, + { { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_DTSHD_PASS, }, + { { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_MP3, }, + { { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_MP3_PASS, }, + { { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_VORBIS, }, + { { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_FLAC, }, + { { "FLAC (24-bit)", "ffflac24", HB_ACODEC_FFFLAC24, HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_FLAC, }, + { { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV, }, NULL, 1, HB_GID_ACODEC_AUTO_PASS, }, +}; +int hb_audio_encoders_count = sizeof(hb_audio_encoders) / sizeof(hb_audio_encoders[0]); +static int hb_audio_encoder_is_enabled(int encoder) { + if (encoder & HB_ACODEC_PASS_FLAG) + { + // Passthru encoders are always enabled + return 1; + } + switch (encoder) + { #ifdef __APPLE__ - { "AAC (CoreAudio)", "ca_aac", HB_ACODEC_CA_AAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "HE-AAC (CoreAudio)", "ca_haac", HB_ACODEC_CA_HAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, + case HB_ACODEC_CA_AAC: + case HB_ACODEC_CA_HAAC: + return 1; +#endif + +#if 1 //#ifdef USE_FAAC + case HB_ACODEC_FAAC: + return 1; #endif - { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, + +#if 1 //#ifdef USE_LIBAV_AAC + case HB_ACODEC_FFAAC: + return 1; +#endif + #ifdef USE_FDK_AAC - { "AAC (FDK)", "fdk_aac", HB_ACODEC_FDK_AAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "HE-AAC (FDK)", "fdk_haac", HB_ACODEC_FDK_HAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, + case HB_ACODEC_FDK_AAC: + case HB_ACODEC_FDK_HAAC: + return 1; #endif - { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, - { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MASK_MKV }, - { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MASK_MKV }, - { "FLAC (24-bit)", "ffflac24", HB_ACODEC_FFFLAC24, HB_MUX_MASK_MKV }, - { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV }, -}; -int hb_audio_encoders_count = sizeof(hb_audio_encoders) / sizeof(hb_encoder_t); -// note: for each container, the muxer nearer the top is the default -hb_container_t hb_containers[] = + // the following encoders are always enabled + case HB_ACODEC_LAME: + case HB_ACODEC_VORBIS: + case HB_ACODEC_AC3: + case HB_ACODEC_FFFLAC: + case HB_ACODEC_FFFLAC24: + return 1; + + default: + return 0; + } +} + +typedef struct +{ + hb_container_t item; + hb_container_t *next; + int enabled; + int gid; +} hb_container_internal_t; +hb_container_t *hb_containers_first_item = NULL; +hb_container_t *hb_containers_last_item = NULL; +hb_container_internal_t hb_containers[] = { - { "MPEG-4 (mp4v2)", "mp4v2", "mp4", HB_MUX_MP4V2, }, - { "Matroska (libmkv)", "libmkv", "mkv", HB_MUX_LIBMKV, }, + // legacy muxers (disabled) + { { "AVI file", "avi", "avi", 0, }, NULL, 0, HB_GID_MUX_MP4, }, + { { "M4V file", "m4v", "m4v", 0, }, NULL, 0, HB_GID_MUX_MP4, }, + { { "MP4 file", "mp4", "mp4", 0, }, NULL, 0, HB_GID_MUX_MP4, }, + { { "OGM file", "ogm", "ogm", 0, }, NULL, 0, HB_GID_MUX_MKV, }, + { { "MKV file", "mkv", "mkv", 0, }, NULL, 0, HB_GID_MUX_MKV, }, + // actual muxers + { { "MPEG-4 (mp4v2)", "mp4v2", "mp4", HB_MUX_MP4V2, }, NULL, 1, HB_GID_MUX_MP4, }, + { { "Matroska (libmkv)", "libmkv", "mkv", HB_MUX_LIBMKV, }, NULL, 1, HB_GID_MUX_MKV, }, }; -int hb_containers_count = sizeof(hb_containers) / sizeof(hb_container_t); +int hb_containers_count = sizeof(hb_containers) / sizeof(hb_containers[0]); +static int hb_container_is_enabled(int format) +{ + switch (format) + { +#if 1 //#ifdef USE_MP4V2 + case HB_MUX_MP4V2: + return 1; +#endif -int hb_video_framerate_get_from_name(const char *name) + // the following muxers are always enabled + case HB_MUX_LIBMKV: + return 1; + + default: + return 0; + } +} + +void hb_common_global_init() { - if (name == NULL || *name == '\0') - goto fail; + static int common_init_done = 0; + if (common_init_done) + return; + + int i, j; - // TODO: implement something more flexible - if (!strcasecmp(name, "23.976 (NTSC Film)")) + // video framerates + for (i = 0; i < hb_video_rates_count; i++) { - return 1126125; + if (hb_video_rates[i].enabled) + { + if (hb_video_rates_first_item == NULL) + { + hb_video_rates_first_item = &hb_video_rates[i].item; + } + else + { + ((hb_rate_internal_t*)hb_video_rates_last_item)->next = + &hb_video_rates[i].item; + } + hb_video_rates_last_item = &hb_video_rates[i].item; + } } - if (!strcasecmp(name, "25 (PAL Film/Video)")) + // fallbacks are static for now (no setup required) + + // audio samplerates + for (i = 0; i < hb_audio_rates_count; i++) { - return 1080000; + if (hb_audio_rates[i].enabled) + { + if (hb_audio_rates_first_item == NULL) + { + hb_audio_rates_first_item = &hb_audio_rates[i].item; + } + else + { + ((hb_rate_internal_t*)hb_audio_rates_last_item)->next = + &hb_audio_rates[i].item; + } + hb_audio_rates_last_item = &hb_audio_rates[i].item; + } } - if (!strcasecmp(name, "29.97 (NTSC Video)")) + // fallbacks are static for now (no setup required) + + // audio bitrates + for (i = 0; i < hb_audio_bitrates_count; i++) { - return 900900; + if (hb_audio_bitrates[i].enabled) + { + if (hb_audio_bitrates_first_item == NULL) + { + hb_audio_bitrates_first_item = &hb_audio_bitrates[i].item; + } + else + { + ((hb_rate_internal_t*)hb_audio_bitrates_last_item)->next = + &hb_audio_bitrates[i].item; + } + hb_audio_bitrates_last_item = &hb_audio_bitrates[i].item; + } } + // fallbacks are static for now (no setup required) + + // audio dithers + for (i = 0; i < hb_audio_dithers_count; i++) + { + if (hb_audio_dithers[i].enabled) + { + if (hb_audio_dithers_first_item == NULL) + { + hb_audio_dithers_first_item = &hb_audio_dithers[i].item; + } + else + { + ((hb_dither_internal_t*)hb_audio_dithers_last_item)->next = + &hb_audio_dithers[i].item; + } + hb_audio_dithers_last_item = &hb_audio_dithers[i].item; + } + } + // fallbacks are static for now (no setup required) + + // audio mixdowns + for (i = 0; i < hb_audio_mixdowns_count; i++) + { + if (hb_audio_mixdowns[i].enabled) + { + if (hb_audio_mixdowns_first_item == NULL) + { + hb_audio_mixdowns_first_item = &hb_audio_mixdowns[i].item; + } + else + { + ((hb_mixdown_internal_t*)hb_audio_mixdowns_last_item)->next = + &hb_audio_mixdowns[i].item; + } + hb_audio_mixdowns_last_item = &hb_audio_mixdowns[i].item; + } + } + // fallbacks are static for now (no setup required) + + // video encoders + for (i = 0; i < hb_video_encoders_count; i++) + { + if (hb_video_encoders[i].enabled) + { + // we still need to check + hb_video_encoders[i].enabled = + hb_video_encoder_is_enabled(hb_video_encoders[i].item.codec); + } + if (hb_video_encoders[i].enabled) + { + if (hb_video_encoders_first_item == NULL) + { + hb_video_encoders_first_item = &hb_video_encoders[i].item; + } + else + { + ((hb_encoder_internal_t*)hb_video_encoders_last_item)->next = + &hb_video_encoders[i].item; + } + hb_video_encoders_last_item = &hb_video_encoders[i].item; + } + } + // setup fallbacks + for (i = 0; i < hb_video_encoders_count; i++) + { + if (!hb_video_encoders[i].enabled) + { + if ((hb_video_encoders[i].item.codec & HB_VCODEC_MASK) && + (hb_video_encoder_is_enabled(hb_video_encoders[i].item.codec))) + { + // we have a specific fallback and it's enabled + continue; + } + for (j = 0; j < hb_video_encoders_count; j++) + { + if (hb_video_encoders[j].enabled && + hb_video_encoders[j].gid == hb_video_encoders[i].gid) + { + hb_video_encoders[i].item.codec = hb_video_encoders[j].item.codec; + break; + } + } + } + } + + // audio encoders + for (i = 0; i < hb_audio_encoders_count; i++) + { + if (hb_audio_encoders[i].enabled) + { + // we still need to check + hb_audio_encoders[i].enabled = + hb_audio_encoder_is_enabled(hb_audio_encoders[i].item.codec); + } + if (hb_audio_encoders[i].enabled) + { + if (hb_audio_encoders_first_item == NULL) + { + hb_audio_encoders_first_item = &hb_audio_encoders[i].item; + } + else + { + ((hb_encoder_internal_t*)hb_audio_encoders_last_item)->next = + &hb_audio_encoders[i].item; + } + hb_audio_encoders_last_item = &hb_audio_encoders[i].item; + } + } + // setup fallbacks + for (i = 0; i < hb_audio_encoders_count; i++) + { + if (!hb_audio_encoders[i].enabled) + { + if ((hb_audio_encoders[i].item.codec & HB_ACODEC_MASK) && + (hb_audio_encoder_is_enabled(hb_audio_encoders[i].item.codec))) + { + // we have a specific fallback and it's enabled + continue; + } + for (j = 0; j < hb_audio_encoders_count; j++) + { + if (hb_audio_encoders[j].enabled && + hb_audio_encoders[j].gid == hb_audio_encoders[i].gid) + { + hb_audio_encoders[i].item.codec = hb_audio_encoders[j].item.codec; + break; + } + } + if ((hb_audio_encoders[i].item.codec & HB_ACODEC_MASK) == 0 && + (hb_audio_encoders[i].gid == HB_GID_ACODEC_AAC_HE)) + { + // try to find an AAC fallback if no HE-AAC encoder is available + for (j = 0; j < hb_audio_encoders_count; j++) + { + if (hb_audio_encoders[j].enabled && + hb_audio_encoders[j].gid == HB_GID_ACODEC_AAC) + { + hb_audio_encoders[i].item.codec = hb_audio_encoders[j].item.codec; + break; + } + } + } + } + } + + // video containers + for (i = 0; i < hb_containers_count; i++) + { + if (hb_containers[i].enabled) + { + // we still need to check + hb_containers[i].enabled = + hb_container_is_enabled(hb_containers[i].item.format); + } + if (hb_containers[i].enabled) + { + if (hb_containers_first_item == NULL) + { + hb_containers_first_item = &hb_containers[i].item; + } + else + { + ((hb_container_internal_t*)hb_containers_last_item)->next = + &hb_containers[i].item; + } + hb_containers_last_item = &hb_containers[i].item; + } + } + // setup fallbacks + for (i = 0; i < hb_containers_count; i++) + { + if (!hb_containers[i].enabled) + { + if ((hb_containers[i].item.format & HB_MUX_MASK) && + (hb_container_is_enabled(hb_containers[i].item.format))) + { + // we have a specific fallback and it's enabled + continue; + } + for (j = 0; j < hb_containers_count; j++) + { + if (hb_containers[j].enabled && + hb_containers[j].gid == hb_containers[i].gid) + { + hb_containers[i].item.format = hb_containers[j].item.format; + break; + } + } + } + } + + // we're done, yay! + common_init_done = 1; +} + +int hb_video_framerate_get_from_name(const char *name) +{ + if (name == NULL || *name == '\0') + goto fail; int i; for (i = 0; i < hb_video_rates_count; i++) { - if (!strcasecmp(hb_video_rates[i].name, name)) + if (!strcasecmp(hb_video_rates[i].item.name, name)) { - return hb_video_rates[i].rate; + return hb_video_rates[i].item.rate; } } @@ -188,16 +609,16 @@ fail: const char* hb_video_framerate_get_name(int framerate) { - if (framerate > hb_video_rates[0].rate || - framerate < hb_video_rates[hb_video_rates_count - 1].rate) + if (framerate > hb_video_rates_first_item->rate || + framerate < hb_video_rates_last_item ->rate) goto fail; - int i; - for (i = 0; i < hb_video_rates_count; i++) + const hb_rate_t *video_framerate = NULL; + while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL) { - if (hb_video_rates[i].rate == framerate) + if (video_framerate->rate == framerate) { - return hb_video_rates[i].name; + return video_framerate->name; } } @@ -214,50 +635,47 @@ const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last) { if (last == NULL) { - return &hb_video_rates[0]; + return hb_video_rates_first_item; } - if (last < &hb_video_rates[0] || - last >= &hb_video_rates[hb_video_rates_count - 1]) - { - return NULL; - } - return last + 1; + return ((hb_rate_internal_t*)last)->next; } int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift) { - int ii, best_samplerate, samplerate_shift; - if ((samplerate < 32000) && - (codec == HB_ACODEC_CA_HAAC || codec == HB_ACODEC_AC3)) + int best_samplerate; + if (samplerate < 32000 && (codec == HB_ACODEC_AC3 || + codec == HB_ACODEC_CA_HAAC)) { // ca_haac can't do samplerates < 32 kHz // AC-3 < 32 kHz suffers from poor hardware compatibility - best_samplerate = 32000; - samplerate_shift = 0; + best_samplerate = 32000; } else if (samplerate < 16000 && codec == HB_ACODEC_FDK_HAAC) { // fdk_haac can't do samplerates < 16 kHz - best_samplerate = 16000; - samplerate_shift = 1; + best_samplerate = 16000; } else { - best_samplerate = samplerate; - for (ii = hb_audio_rates_count - 1; ii >= 0; ii--) + best_samplerate = hb_audio_rates_first_item->rate; + const hb_rate_t *audio_samplerate = NULL; + while ((audio_samplerate = hb_audio_samplerate_get_next(audio_samplerate)) != NULL) { - // valid samplerate - if (best_samplerate == hb_audio_rates[ii].rate) - break; - - // samplerate is higher than the next valid samplerate, - // or lower than the lowest valid samplerate - if (best_samplerate > hb_audio_rates[ii].rate || ii == 0) + if (samplerate == audio_samplerate->rate) { - best_samplerate = hb_audio_rates[ii].rate; + // valid samplerate + best_samplerate = audio_samplerate->rate; break; } + if (samplerate > audio_samplerate->rate) + { + // samplerates are sanitized downwards + best_samplerate = audio_samplerate->rate; + } } + } + if (sr_shift != NULL) + { /* sr_shift: 0 -> 48000, 44100, 32000 Hz * 1 -> 24000, 22050, 16000 Hz * 2 -> 12000, 11025, 8000 Hz @@ -266,12 +684,8 @@ int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift) * * (samplerate < 32000) implies (samplerate <= 24000) */ - samplerate_shift = ((best_samplerate < 16000) ? 2 : - (best_samplerate < 32000) ? 1 : 0); - } - if (sr_shift != NULL) - { - *sr_shift = samplerate_shift; + *sr_shift = ((best_samplerate < 16000) ? 2 : + (best_samplerate < 32000) ? 1 : 0); } return best_samplerate; } @@ -281,38 +695,39 @@ int hb_audio_samplerate_get_from_name(const char *name) if (name == NULL || *name == '\0') goto fail; - // TODO: implement something more flexible - int i = atoi(name); - if (i >= hb_audio_rates[0].rate && - i <= hb_audio_rates[hb_audio_rates_count - 1].rate) - { - return i; - } - + int i; for (i = 0; i < hb_audio_rates_count; i++) { - if (!strcasecmp(hb_audio_rates[i].name, name)) + if (!strcasecmp(hb_audio_rates[i].item.name, name)) { - return hb_audio_rates[i].rate; + return hb_audio_rates[i].item.rate; } } + // maybe the samplerate was specified in Hz + i = atoi(name); + if (i >= hb_audio_rates_first_item->rate && + i <= hb_audio_rates_last_item ->rate) + { + return hb_audio_samplerate_get_best(0, i, NULL); + } + fail: return -1; } const char* hb_audio_samplerate_get_name(int samplerate) { - if (samplerate < hb_audio_rates[0].rate || - samplerate > hb_audio_rates[hb_audio_rates_count - 1].rate) + if (samplerate < hb_audio_rates_first_item->rate || + samplerate > hb_audio_rates_last_item ->rate) goto fail; - int i; - for (i = 0; i < hb_audio_rates_count; i++) + const hb_rate_t *audio_samplerate = NULL; + while ((audio_samplerate = hb_audio_samplerate_get_next(audio_samplerate)) != NULL) { - if (hb_audio_rates[i].rate == samplerate) + if (audio_samplerate->rate == samplerate) { - return hb_audio_rates[i].name; + return audio_samplerate->name; } } @@ -324,14 +739,9 @@ const hb_rate_t* hb_audio_samplerate_get_next(const hb_rate_t *last) { if (last == NULL) { - return &hb_audio_rates[0]; + return hb_audio_rates_first_item; } - if (last < &hb_audio_rates[0] || - last >= &hb_audio_rates[hb_audio_rates_count - 1]) - { - return NULL; - } - return last + 1; + return ((hb_rate_internal_t*)last)->next; } // Given an input bitrate, find closest match in the set of allowed bitrates @@ -341,18 +751,23 @@ static int hb_audio_bitrate_find_closest(int bitrate) if (bitrate <= 0) return bitrate; - // result is highest rate if none found during search. - // rate returned will always be <= rate asked for. - int i, result = hb_audio_bitrates[0].rate; - for (i = hb_audio_bitrates_count - 1; i > 0; i--) + int closest_bitrate = hb_audio_bitrates_first_item->rate; + const hb_rate_t *audio_bitrate = NULL; + while ((audio_bitrate = hb_audio_bitrate_get_next(audio_bitrate)) != NULL) { - if (bitrate >= hb_audio_bitrates[i].rate) + if (bitrate == audio_bitrate->rate) { - result = hb_audio_bitrates[i].rate; + // valid bitrate + closest_bitrate = audio_bitrate->rate; break; } + if (bitrate > audio_bitrate->rate) + { + // bitrates are sanitized downwards + closest_bitrate = audio_bitrate->rate; + } } - return result; + return closest_bitrate; } // Given an input bitrate, sanitize it. @@ -643,30 +1058,25 @@ void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown, // Bitrates don't apply to passthrough audio, but may apply if we // fall back to an encoder when the source can't be passed through. default: - *low = hb_audio_bitrates[0].rate; - *high = hb_audio_bitrates[hb_audio_bitrates_count - 1].rate; + *low = hb_audio_bitrates_first_item->rate; + *high = hb_audio_bitrates_last_item ->rate; break; } // sanitize max. bitrate - if (*high < hb_audio_bitrates[0].rate) - *high = hb_audio_bitrates[0].rate; - if (*high > hb_audio_bitrates[hb_audio_bitrates_count - 1].rate) - *high = hb_audio_bitrates[hb_audio_bitrates_count - 1].rate; + if (*high < hb_audio_bitrates_first_item->rate) + *high = hb_audio_bitrates_first_item->rate; + if (*high > hb_audio_bitrates_last_item ->rate) + *high = hb_audio_bitrates_last_item ->rate; } const hb_rate_t* hb_audio_bitrate_get_next(const hb_rate_t *last) { if (last == NULL) { - return &hb_audio_bitrates[0]; - } - if (last < &hb_audio_bitrates[0] || - last >= &hb_audio_bitrates[hb_audio_bitrates_count - 1]) - { - return NULL; + return hb_audio_bitrates_first_item; } - return last + 1; + return ((hb_rate_internal_t*)last)->next; } // Get limits and hints for the UIs. @@ -806,7 +1216,7 @@ float hb_audio_compression_get_default(uint32_t codec) int hb_audio_dither_get_default() { // "auto" - return hb_audio_dithers[0].method; + return hb_audio_dithers_first_item->method; } int hb_audio_dither_get_default_method() @@ -841,9 +1251,10 @@ int hb_audio_dither_get_from_name(const char *name) int i; for ( i = 0; i < hb_audio_dithers_count; i++) { - if (!strcasecmp(hb_audio_dithers[i].short_name, name)) + if (!strcasecmp(hb_audio_dithers[i].item.short_name, name) || + !strcasecmp(hb_audio_dithers[i].item.description, name)) { - return hb_audio_dithers[i].method; + return hb_audio_dithers[i].item.method; } } @@ -853,16 +1264,16 @@ fail: const char* hb_audio_dither_get_description(int method) { - if (method < hb_audio_dithers[0].method || - method > hb_audio_dithers[hb_audio_dithers_count - 1].method) + if (method < hb_audio_dithers_first_item->method || + method > hb_audio_dithers_last_item ->method) goto fail; - int i; - for (i = 0; i < hb_audio_dithers_count; i++) + const hb_dither_t *audio_dither = NULL; + while ((audio_dither = hb_audio_dither_get_next(audio_dither)) != NULL) { - if (hb_audio_dithers[i].method == method) + if (audio_dither->method == method) { - return hb_audio_dithers[i].description; + return audio_dither->description; } } @@ -874,14 +1285,9 @@ const hb_dither_t* hb_audio_dither_get_next(const hb_dither_t *last) { if (last == NULL) { - return &hb_audio_dithers[0]; + return hb_audio_dithers_first_item; } - if (last < &hb_audio_dithers[0] || - last >= &hb_audio_dithers[hb_audio_dithers_count - 1]) - { - return NULL; - } - return last + 1; + return ((hb_dither_internal_t*)last)->next; } int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout) @@ -1028,18 +1434,19 @@ int hb_mixdown_get_best(uint32_t codec, uint64_t layout, int mixdown) if (codec & HB_ACODEC_PASS_FLAG) return HB_AMIXDOWN_NONE; - // caller requested the best available mixdown - if (mixdown == HB_INVALID_AMIXDOWN) - mixdown = hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown; - - // test all mixdowns until an authorized, supported mixdown is found - // stop before we reach the "worst" non-None mixdown (index == 1) - int i; - for (i = hb_audio_mixdowns_count - 1; i > 1; i--) - if (hb_audio_mixdowns[i].amixdown <= mixdown && - hb_mixdown_is_supported(hb_audio_mixdowns[i].amixdown, codec, layout)) - break; - return hb_audio_mixdowns[i].amixdown; + int best_mixdown = HB_INVALID_AMIXDOWN; + const hb_mixdown_t *audio_mixdown = hb_mixdown_get_next(NULL); + // test all non-None mixdowns while the value is <= the requested mixdown + // HB_INVALID_AMIXDOWN means the highest supported mixdown was requested + while ((audio_mixdown = hb_mixdown_get_next(audio_mixdown)) != NULL) + { + if ((mixdown == HB_INVALID_AMIXDOWN || audio_mixdown->amixdown <= mixdown) && + (hb_mixdown_is_supported(audio_mixdown->amixdown, codec, layout))) + { + best_mixdown = audio_mixdown->amixdown; + } + } + return best_mixdown; } int hb_mixdown_get_default(uint32_t codec, uint64_t layout) @@ -1073,44 +1480,32 @@ int hb_mixdown_get_from_name(const char *name) if (name == NULL || *name == '\0') goto fail; - // TODO: implement something more flexible - if (!strcasecmp(name, "AC3 Passthru") || - !strcasecmp(name, "DTS Passthru") || - !strcasecmp(name, "DTS-HD Passthru")) - { - return HB_AMIXDOWN_NONE; - } - if (!strcasecmp(name, "6-channel discrete")) - { - return HB_AMIXDOWN_5POINT1; - } - int i; for (i = 0; i < hb_audio_mixdowns_count; i++) { - if (!strcasecmp(hb_audio_mixdowns[i].name, name) || - !strcasecmp(hb_audio_mixdowns[i].short_name, name)) + if (!strcasecmp(hb_audio_mixdowns[i].item.name, name) || + !strcasecmp(hb_audio_mixdowns[i].item.short_name, name)) { - return hb_audio_mixdowns[i].amixdown; + return hb_audio_mixdowns[i].item.amixdown; } } fail: - return -1; + return HB_INVALID_AMIXDOWN; } const char* hb_mixdown_get_name(int mixdown) { - if (mixdown < hb_audio_mixdowns[0].amixdown || - mixdown > hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown) + if (mixdown < hb_audio_mixdowns_first_item->amixdown || + mixdown > hb_audio_mixdowns_last_item ->amixdown) goto fail; - int i; - for (i = 0; i < hb_audio_mixdowns_count; i++) + const hb_mixdown_t *audio_mixdown = NULL; + while ((audio_mixdown = hb_mixdown_get_next(audio_mixdown)) != NULL) { - if (hb_audio_mixdowns[i].amixdown == mixdown) + if (audio_mixdown->amixdown == mixdown) { - return hb_audio_mixdowns[i].name; + return audio_mixdown->name; } } @@ -1120,16 +1515,16 @@ fail: const char* hb_mixdown_get_short_name(int mixdown) { - if (mixdown < hb_audio_mixdowns[0].amixdown || - mixdown > hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown) + if (mixdown < hb_audio_mixdowns_first_item->amixdown || + mixdown > hb_audio_mixdowns_last_item ->amixdown) goto fail; - int i; - for (i = 0; i < hb_audio_mixdowns_count; i++) + const hb_mixdown_t *audio_mixdown = NULL; + while ((audio_mixdown = hb_mixdown_get_next(audio_mixdown)) != NULL) { - if (hb_audio_mixdowns[i].amixdown == mixdown) + if (audio_mixdown->amixdown == mixdown) { - return hb_audio_mixdowns[i].short_name; + return audio_mixdown->short_name; } } @@ -1146,14 +1541,9 @@ const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last) { if (last == NULL) { - return &hb_audio_mixdowns[0]; + return hb_audio_mixdowns_first_item; } - if (last < &hb_audio_mixdowns[0] || - last >= &hb_audio_mixdowns[hb_audio_mixdowns_count - 1]) - { - return NULL; - } - return last + 1; + return ((hb_mixdown_internal_t*)last)->next; } int hb_video_encoder_get_default(int muxer) @@ -1161,17 +1551,17 @@ int hb_video_encoder_get_default(int muxer) if (!(muxer & HB_MUX_MASK)) goto fail; - int i; - for (i = 0; i < hb_video_encoders_count; i++) + const hb_encoder_t *video_encoder = NULL; + while ((video_encoder = hb_video_encoder_get_next(video_encoder)) != NULL) { - if (hb_video_encoders[i].muxers & muxer) + if (video_encoder->muxers & muxer) { - return hb_video_encoders[i].codec; + return video_encoder->codec; } } fail: - return -1; + return 0; } int hb_video_encoder_get_from_name(const char *name) @@ -1179,25 +1569,18 @@ int hb_video_encoder_get_from_name(const char *name) if (name == NULL || *name == '\0') goto fail; - // TODO: implement something more flexible - if (!strcasecmp(name, "XviD") || - !strcasecmp(name, "FFmpeg")) - { - return HB_VCODEC_FFMPEG_MPEG4; - } - int i; for (i = 0; i < hb_video_encoders_count; i++) { - if (!strcasecmp(hb_video_encoders[i].name, name) || - !strcasecmp(hb_video_encoders[i].short_name, name)) + if (!strcasecmp(hb_video_encoders[i].item.name, name) || + !strcasecmp(hb_video_encoders[i].item.short_name, name)) { - return hb_video_encoders[i].codec; + return hb_video_encoders[i].item.codec; } } fail: - return -1; + return 0; } const char* hb_video_encoder_get_name(int encoder) @@ -1205,12 +1588,12 @@ const char* hb_video_encoder_get_name(int encoder) if (!(encoder & HB_VCODEC_MASK)) goto fail; - int i; - for (i = 0; i < hb_video_encoders_count; i++) + const hb_encoder_t *video_encoder = NULL; + while ((video_encoder = hb_video_encoder_get_next(video_encoder)) != NULL) { - if (hb_video_encoders[i].codec == encoder) + if (video_encoder->codec == encoder) { - return hb_video_encoders[i].name; + return video_encoder->name; } } @@ -1223,12 +1606,12 @@ const char* hb_video_encoder_get_short_name(int encoder) if (!(encoder & HB_VCODEC_MASK)) goto fail; - int i; - for (i = 0; i < hb_video_encoders_count; i++) + const hb_encoder_t *video_encoder = NULL; + while ((video_encoder = hb_video_encoder_get_next(video_encoder)) != NULL) { - if (hb_video_encoders[i].codec == encoder) + if (video_encoder->codec == encoder) { - return hb_video_encoders[i].short_name; + return video_encoder->short_name; } } @@ -1245,43 +1628,48 @@ const hb_encoder_t* hb_video_encoder_get_next(const hb_encoder_t *last) { if (last == NULL) { - return &hb_video_encoders[0]; - } - if (last < &hb_video_encoders[0] || - last >= &hb_video_encoders[hb_video_encoders_count - 1]) - { - return NULL; + return hb_video_encoders_first_item; } - return last + 1; + return ((hb_encoder_internal_t*)last)->next; } // for a valid passthru, return the matching encoder for that codec (if any), // else return -1 (i.e. drop the track) int hb_audio_encoder_get_fallback_for_passthru(int passthru) { - // TODO: implement something more flexible + int gid; + const hb_encoder_t *audio_encoder = NULL; switch (passthru) { case HB_ACODEC_AAC_PASS: -#ifdef __APPLE__ - return HB_ACODEC_CA_AAC; -#else - return HB_ACODEC_FAAC; -#endif + gid = HB_GID_ACODEC_AAC; + break; case HB_ACODEC_AC3_PASS: - return HB_ACODEC_AC3; + gid = HB_GID_ACODEC_AC3; + break; case HB_ACODEC_MP3_PASS: - return HB_ACODEC_LAME; + gid = HB_GID_ACODEC_MP3; + break; - // passthru tracks are often the second audio from the same source track - // if we don't have an encoder matching the passthru codec, return -1 - // dropping the track, as well as ensuring that there is at least one - // audio track in the output is then up to the UIs default: - return -1; + gid = HB_GID_NONE; // will never match an enabled encoder + break; + } + while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL) + { + if (((hb_encoder_internal_t*)audio_encoder)->gid == gid) + { + return audio_encoder->codec; + } } + + // passthru tracks are often the second audio from the same source track + // if we don't have an encoder matching the passthru codec, return 0 + // dropping the track, as well as ensuring that there is at least one + // audio track in the output is then up to the UIs + return 0; } int hb_audio_encoder_get_default(int muxer) @@ -1289,26 +1677,34 @@ int hb_audio_encoder_get_default(int muxer) if (!(muxer & HB_MUX_MASK)) goto fail; -#ifndef __APPLE__ - if (muxer == HB_MUX_MKV) - { - return HB_ACODEC_LAME; - } -#endif - - int i; - for (i = 0; i < hb_audio_encoders_count; i++) + int codec = 0; + const hb_encoder_t *audio_encoder = NULL; + while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL) { // default encoder should not be passthru - if ((hb_audio_encoders[i].muxers & muxer) && - (hb_audio_encoders[i].codec & HB_ACODEC_PASS_FLAG) == 0) + if ((audio_encoder->muxers & muxer) && + (audio_encoder->codec & HB_ACODEC_PASS_FLAG) == 0) { - return hb_audio_encoders[i].codec; + codec = audio_encoder->codec; + break; } } + // Lame is better than our low-end AAC encoders + // if the container is MKV, use the former + // AAC is still used when the container is MP4 (for better compatibility) + if ((codec == HB_ACODEC_FAAC || + codec == HB_ACODEC_FFAAC) && (muxer & HB_MUX_MASK_MKV) == muxer) + { + return HB_ACODEC_LAME; + } + else + { + return codec; + } + fail: - return -1; + return 0; } int hb_audio_encoder_get_from_name(const char *name) @@ -1316,44 +1712,18 @@ int hb_audio_encoder_get_from_name(const char *name) if (name == NULL || *name == '\0') goto fail; - // TODO: implement something more flexible - if (!strcasecmp(name, "AC3")) - { - return HB_ACODEC_AC3; - } - // libfdk fallback, use Core Audio if available, else FAAC -#ifndef USE_FDK_AAC -#ifdef __APPLE__ -#define AAC_ENC HB_ACODEC_CA_AAC -#define HAAC_ENC HB_ACODEC_CA_HAAC -#else -#define AAC_ENC HB_ACODEC_FAAC -#define HAAC_ENC HB_ACODEC_FAAC -#endif - if (!strcasecmp(name, "AAC (FDK)") || !strcasecmp(name, "fdk_aac")) - { - return AAC_ENC; - } - if (!strcasecmp(name, "HE-AAC (FDK)") || !strcasecmp(name, "fdk_haac")) - { - return HAAC_ENC; - } -#undef AAC_ENC -#undef HAAC_ENC -#endif - int i; for (i = 0; i < hb_audio_encoders_count; i++) { - if (!strcasecmp(hb_audio_encoders[i].name, name) || - !strcasecmp(hb_audio_encoders[i].short_name, name)) + if (!strcasecmp(hb_audio_encoders[i].item.name, name) || + !strcasecmp(hb_audio_encoders[i].item.short_name, name)) { - return hb_audio_encoders[i].codec; + return hb_audio_encoders[i].item.codec; } } fail: - return -1; + return 0; } const char* hb_audio_encoder_get_name(int encoder) @@ -1361,12 +1731,12 @@ const char* hb_audio_encoder_get_name(int encoder) if (!(encoder & HB_ACODEC_ANY)) goto fail; - int i; - for (i = 0; i < hb_audio_encoders_count; i++) + const hb_encoder_t *audio_encoder = NULL; + while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL) { - if (hb_audio_encoders[i].codec == encoder) + if (audio_encoder->codec == encoder) { - return hb_audio_encoders[i].name; + return audio_encoder->name; } } @@ -1379,12 +1749,12 @@ const char* hb_audio_encoder_get_short_name(int encoder) if (!(encoder & HB_ACODEC_ANY)) goto fail; - int i; - for (i = 0; i < hb_audio_encoders_count; i++) + const hb_encoder_t *audio_encoder = NULL; + while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL) { - if (hb_audio_encoders[i].codec == encoder) + if (audio_encoder->codec == encoder) { - return hb_audio_encoders[i].short_name; + return audio_encoder->short_name; } } @@ -1401,14 +1771,9 @@ const hb_encoder_t* hb_audio_encoder_get_next(const hb_encoder_t *last) { if (last == NULL) { - return &hb_audio_encoders[0]; + return hb_audio_encoders_first_item; } - if (last < &hb_audio_encoders[0] || - last >= &hb_audio_encoders[hb_audio_encoders_count - 1]) - { - return NULL; - } - return last + 1; + return ((hb_encoder_internal_t*)last)->next; } void hb_autopassthru_apply_settings(hb_job_t *job) @@ -1455,7 +1820,7 @@ void hb_autopassthru_apply_settings(hb_job_t *job) audio->config.out.bitrate = hb_audio_bitrate_get_default(audio->config.out.codec, audio->config.out.samplerate, - audio->config.out.mixdown ); + audio->config.out.mixdown); audio->config.out.compression_level = hb_audio_compression_get_default(audio->config.out.codec); } @@ -1561,34 +1926,18 @@ int hb_container_get_from_name(const char *name) if (name == NULL || *name == '\0') goto fail; - // TODO: implement something more flexible - if (!strcasecmp(name, "m4v")) - { - // old CLI alternate short name for "mp4" - return HB_MUX_MP4; - } - if (!strcasecmp(name, "MP4 file")) - { - return HB_MUX_MP4; - } - if (!strcasecmp(name, "MKV file")) - { - return HB_MUX_MKV; - } - int i; for (i = 0; i < hb_containers_count; i++) { - if (!strcasecmp(hb_containers[i].name, name) || - !strcasecmp(hb_containers[i].short_name, name) || - !strcasecmp(hb_containers[i].default_extension, name)) + if (!strcasecmp(hb_containers[i].item.name, name) || + !strcasecmp(hb_containers[i].item.short_name, name)) { - return hb_containers[i].format; + return hb_containers[i].item.format; } } fail: - return -1; + return 0; } int hb_container_get_from_extension(const char *extension) @@ -1596,23 +1945,17 @@ int hb_container_get_from_extension(const char *extension) if (extension == NULL || *extension == '\0') goto fail; - // TODO: implement something more flexible - if (!strcasecmp(extension, "m4v")) - { - return HB_MUX_MP4; - } - int i; for (i = 0; i < hb_containers_count; i++) { - if (!strcasecmp(hb_containers[i].default_extension, extension)) + if (!strcasecmp(hb_containers[i].item.default_extension, extension)) { - return hb_containers[i].format; + return hb_containers[i].item.format; } } fail: - return -1; + return 0; } const char* hb_container_get_name(int format) @@ -1620,14 +1963,13 @@ const char* hb_container_get_name(int format) if (!(format & HB_MUX_MASK)) goto fail; - int i; - for (i = 0; i < hb_containers_count; i++) + const hb_container_t *container = NULL; + while ((container = hb_container_get_next(container)) != NULL) { - if (hb_containers[i].format == format) + if (container->format == format) { - return hb_containers[i].name; + return container->name; } - } fail: @@ -1639,12 +1981,12 @@ const char* hb_container_get_short_name(int format) if (!(format & HB_MUX_MASK)) goto fail; - int i; - for (i = 0; i < hb_containers_count; i++) + const hb_container_t *container = NULL; + while ((container = hb_container_get_next(container)) != NULL) { - if (hb_containers[i].format == format) + if (container->format == format) { - return hb_containers[i].short_name; + return container->short_name; } } @@ -1657,12 +1999,12 @@ const char* hb_container_get_default_extension(int format) if (!(format & HB_MUX_MASK)) goto fail; - int i; - for (i = 0; i < hb_containers_count; i++) + const hb_container_t *container = NULL; + while ((container = hb_container_get_next(container)) != NULL) { - if (hb_containers[i].format == format) + if (container->format == format) { - return hb_containers[i].default_extension; + return container->default_extension; } } @@ -1679,14 +2021,9 @@ const hb_container_t* hb_container_get_next(const hb_container_t *last) { if (last == NULL) { - return &hb_containers[0]; - } - if (last < &hb_containers[0] || - last >= &hb_containers[hb_containers_count - 1]) - { - return NULL; + return hb_containers_first_item; } - return last + 1; + return ((hb_container_internal_t*)last)->next; } /********************************************************************** @@ -2945,7 +3282,7 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg) /* Initalize some sensible defaults */ audiocfg->in.track = audiocfg->out.track = 0; - audiocfg->out.codec = hb_audio_encoders[0].codec; + audiocfg->out.codec = hb_audio_encoder_get_default(HB_MUX_MP4); // default container audiocfg->out.samplerate = -1; audiocfg->out.samples_per_frame = -1; audiocfg->out.bitrate = -1; diff --git a/libhb/common.h b/libhb/common.h index ee56219a9..231cdb777 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -193,7 +193,6 @@ struct hb_dither_s struct hb_mixdown_s { const char *name; - const char *internal_name; const char *short_name; int amixdown; }; @@ -235,7 +234,7 @@ struct hb_subtitle_config_s * Use hb_*_get_from_name() to get the value corresponding to a name. * The name can be either the short or full name. * Legacy names are sanitized to currently-supported values whenever possible. - * Returns -1 if no value could be found. + * Returns 0 or -1 if no value could be found. * * Use hb_*_get_name() and hb_*_get_short_name() to get the corresponding value. * Returns NULL if the value is invalid. @@ -255,6 +254,8 @@ struct hb_subtitle_config_s * */ +void hb_common_global_init(); + int hb_video_framerate_get_from_name(const char *name); const char* hb_video_framerate_get_name(int framerate); const char* hb_video_framerate_sanitize_name(const char *name); @@ -474,7 +475,7 @@ struct hb_job_s #define HB_MUX_MASK_MP4 0x0F0000 #define HB_MUX_LIBMKV 0x100000 #define HB_MUX_MASK_MKV 0xF00000 -// default MP4 and MKV muxers +/* default muxer for each container */ #define HB_MUX_MP4 HB_MUX_MP4V2 #define HB_MUX_MKV HB_MUX_LIBMKV diff --git a/libhb/hb.c b/libhb/hb.c index e5114f9a7..a55575f8e 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -70,7 +70,6 @@ struct hb_handle_s hb_work_object_t * hb_objects = NULL; int hb_instance_counter = 0; -int hb_process_initialized = 0; static void thread_func( void * ); @@ -355,26 +354,6 @@ void hb_register( hb_work_object_t * w ) hb_objects = w; } -/** - * Ensures that the process has been initialized. - */ -static void process_init() -{ - if (!hb_process_initialized) - { -#if defined( SYS_MINGW ) && defined( PTW32_STATIC_LIB ) - pthread_win32_process_attach_np(); -#endif - -#if defined( _WIN32 ) || defined( __MINGW32__ ) - setvbuf( stdout, NULL, _IONBF, 0 ); - setvbuf( stderr, NULL, _IONBF, 0 ); -#endif - hb_process_initialized = 1; - } - -} - void (*hb_log_callback)(const char* message); static void redirect_thread_func(void *); @@ -388,8 +367,6 @@ static void redirect_thread_func(void *); */ void hb_register_logger( void (*log_cb)(const char* message) ) { - process_init(); - hb_log_callback = log_cb; hb_thread_init("ioredirect", redirect_thread_func, NULL, HB_NORMAL_PRIORITY); } @@ -402,8 +379,6 @@ void hb_register_logger( void (*log_cb)(const char* message) ) */ hb_handle_t * hb_init( int verbose, int update_check ) { - process_init(); - hb_handle_t * h = calloc( sizeof( hb_handle_t ), 1 ); uint64_t date; @@ -461,42 +436,11 @@ hb_handle_t * hb_init( int verbose, int update_check ) h->interjob = calloc( sizeof( hb_interjob_t ), 1 ); - /* libavcodec */ - hb_avcodec_init(); - /* Start library thread */ hb_log( "hb_init: starting libhb thread" ); h->die = 0; h->main_thread = hb_thread_init( "libhb", thread_func, h, HB_NORMAL_PRIORITY ); - hb_register( &hb_sync_video ); - hb_register( &hb_sync_audio ); - hb_register( &hb_decmpeg2 ); - hb_register( &hb_decvobsub ); - hb_register( &hb_encvobsub ); - hb_register( &hb_deccc608 ); - hb_register( &hb_decsrtsub ); - hb_register( &hb_decutf8sub ); - hb_register( &hb_dectx3gsub ); - hb_register( &hb_decssasub ); - hb_register( &hb_decpgssub ); - hb_register( &hb_encavcodec ); - hb_register( &hb_encx264 ); - hb_register( &hb_enctheora ); - hb_register( &hb_deca52 ); - hb_register( &hb_decavcodeca ); - hb_register( &hb_decavcodecv ); - hb_register( &hb_declpcm ); - hb_register( &hb_encfaac ); - hb_register( &hb_enclame ); - hb_register( &hb_encvorbis ); - hb_register( &hb_muxer ); -#ifdef __APPLE__ - hb_register( &hb_encca_aac ); - hb_register( &hb_encca_haac ); -#endif - hb_register( &hb_encavcodeca ); - hb_register( &hb_reader ); return h; } @@ -562,42 +506,12 @@ hb_handle_t * hb_init_dl( int verbose, int update_check ) h->pause_lock = hb_lock_init(); - /* libavcodec */ - hb_avcodec_init(); - /* Start library thread */ hb_log( "hb_init: starting libhb thread" ); h->die = 0; h->main_thread = hb_thread_init( "libhb", thread_func, h, HB_NORMAL_PRIORITY ); - hb_register( &hb_sync_video ); - hb_register( &hb_sync_audio ); - hb_register( &hb_decmpeg2 ); - hb_register( &hb_decvobsub ); - hb_register( &hb_encvobsub ); - hb_register( &hb_deccc608 ); - hb_register( &hb_decsrtsub ); - hb_register( &hb_decutf8sub ); - hb_register( &hb_dectx3gsub ); - hb_register( &hb_decssasub ); - hb_register( &hb_encavcodec ); - hb_register( &hb_encx264 ); - hb_register( &hb_enctheora ); - hb_register( &hb_deca52 ); - hb_register( &hb_decavcodeca ); - hb_register( &hb_decavcodecv ); - hb_register( &hb_declpcm ); - hb_register( &hb_encfaac ); - hb_register( &hb_enclame ); - hb_register( &hb_encvorbis ); - hb_register( &hb_muxer ); -#ifdef __APPLE__ - hb_register( &hb_encca_aac ); - hb_register( &hb_encca_haac ); -#endif - hb_register( &hb_encavcodeca ); - hb_register( &hb_reader ); return h; } @@ -1693,6 +1607,55 @@ void hb_close( hb_handle_t ** _h ) *_h = NULL; } +int hb_global_init() +{ + int result = 0; + + result = hb_platform_init(); + if (result < 0) + { + hb_error("Platform specific initialization failed!"); + return -1; + } + + /* libavcodec */ + hb_avcodec_init(); + + /* HB work objects */ + hb_register(&hb_muxer); + hb_register(&hb_reader); + hb_register(&hb_sync_video); + hb_register(&hb_sync_audio); + hb_register(&hb_deca52); + hb_register(&hb_decavcodecv); + hb_register(&hb_decavcodeca); + hb_register(&hb_declpcm); + hb_register(&hb_deccc608); + hb_register(&hb_decmpeg2); + hb_register(&hb_decpgssub); + hb_register(&hb_decsrtsub); + hb_register(&hb_decssasub); + hb_register(&hb_dectx3gsub); + hb_register(&hb_decutf8sub); + hb_register(&hb_decvobsub); + hb_register(&hb_encvobsub); + hb_register(&hb_encavcodec); + hb_register(&hb_encavcodeca); +#ifdef __APPLE__ + hb_register(&hb_encca_aac); + hb_register(&hb_encca_haac); +#endif + hb_register(&hb_encfaac); + hb_register(&hb_enclame); + hb_register(&hb_enctheora); + hb_register(&hb_encvorbis); + hb_register(&hb_encx264); + + hb_common_global_init(); + + return result; +} + /** * Cleans up libhb at a process level. Call before the app closes. Removes preview directory. */ diff --git a/libhb/hb.h b/libhb/hb.h index e4c81a4e4..768a66feb 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -126,6 +126,9 @@ int hb_get_scancount( hb_handle_t * ); Aborts all current jobs if any, frees memory. */ void hb_close( hb_handle_t ** ); +/* hb_global_init() + Performs process initialization. */ +int hb_global_init(); /* hb_global_close() Performs final cleanup for the process. */ void hb_global_close(); diff --git a/libhb/ports.c b/libhb/ports.c index 98945fec0..64b68bcb4 100644 --- a/libhb/ports.c +++ b/libhb/ports.c @@ -231,6 +231,41 @@ int hb_get_cpu_count() return cpu_count; } +int hb_platform_init() +{ + int result = 0; + +#if defined(SYS_MINGW) && defined(PTW32_STATIC_LIB) + result = !pthread_win32_process_attach_np(); + if (result) + { + hb_error("pthread_win32_process_attach_np() failed!"); + return -1; + } +#endif + +#if defined(_WIN32) || defined(__MINGW32__) + /* + * win32 _IOLBF (line-buffering) is the same as _IOFBF (full-buffering). + * force it to unbuffered otherwise informative output is not easily parsed. + */ + result = setvbuf(stdout, NULL, _IONBF, 0); + if (result) + { + hb_error("setvbuf(stdout, NULL, _IONBF, 0) failed!"); + return -1; + } + result = setvbuf(stderr, NULL, _IONBF, 0); + if (result) + { + hb_error("setvbuf(stderr, NULL, _IONBF, 0) failed!"); + return -1; + } +#endif + + return result; +} + /************************************************************************ * Get a temporary directory for HB ***********************************************************************/ diff --git a/libhb/ports.h b/libhb/ports.h index 2c0aeb1ee..10d01935b 100644 --- a/libhb/ports.h +++ b/libhb/ports.h @@ -22,6 +22,7 @@ uint64_t hb_get_date(); void hb_snooze( int delay ); int hb_get_cpu_count(); +int hb_platform_init(); #ifdef SYS_MINGW char *strtok_r(char *s, const char *delim, char **save_ptr); #endif diff --git a/macosx/Controller.m b/macosx/Controller.m index e92f7393a..d5dd32bff 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -701,7 +701,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It menuItem = [[fVidRatePopUp menu] addItemWithTitle:@"Same as source" action:nil keyEquivalent:@""]; - [menuItem setTag:-1]; // hb_video_framerate_get_from_name(NULL) + [menuItem setTag:hb_video_framerate_get_from_name("Same as source")]; for (const hb_rate_t *video_framerate = hb_video_framerate_get_next(NULL); video_framerate != NULL; video_framerate = hb_video_framerate_get_next(video_framerate)) @@ -1757,10 +1757,11 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* we open up the browse sources sheet here and call for browseSourcesDone after the sheet is closed * to evaluate whether we want to specify a title, we pass the sender in the contextInfo variable */ - [panel beginSheetForDirectory: sourceDirectory file: nil types: nil - modalForWindow: fWindow modalDelegate: self - didEndSelector: @selector( browseSourcesDone:returnCode:contextInfo: ) - contextInfo: sender]; + [panel setDirectoryURL:[NSURL fileURLWithPath:sourceDirectory]]; + [panel beginSheetModalForWindow:fWindow completionHandler: + ^(NSInteger result) { + [self browseSourcesDone:panel returnCode:(int)result contextInfo:sender]; + }]; } - (void) browseSourcesDone: (NSOpenPanel *) sheet @@ -2226,10 +2227,12 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Open a panel to let the user choose and update the text field */ NSSavePanel * panel = [NSSavePanel savePanel]; /* We get the current file name and path from the destination field here */ - [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent] - modalForWindow: fWindow modalDelegate: self - didEndSelector: @selector( browseFileDone:returnCode:contextInfo: ) - contextInfo: NULL]; + NSString* destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; + [panel setDirectoryURL:[NSURL fileURLWithPath:destinationDirectory]]; + [panel setNameFieldStringValue:[[fDstFile2Field stringValue] lastPathComponent]]; + [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [self browseFileDone:panel returnCode:(int)result contextInfo:sender]; + }]; } - (void) browseFileDone: (NSSavePanel *) sheet @@ -5972,13 +5975,14 @@ the user is using "Custom" settings by determining the sender*/ } /* we open up the browse srt sheet here and call for browseImportSrtFileDone after the sheet is closed */ NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"srt", nil]; - [panel beginSheetForDirectory: sourceDirectory file: nil types: fileTypes - modalForWindow: fWindow modalDelegate: self - didEndSelector: @selector( browseImportSrtFileDone:returnCode:contextInfo: ) - contextInfo: sender]; + [panel setDirectoryURL:[NSURL fileURLWithPath:sourceDirectory]]; + [panel setAllowedFileTypes:fileTypes]; + [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [self browseImportSrtFileDone:panel returnCode:(int)result contextInfo:sender]; + }]; } -- (void) browseImportSrtFileDone: (NSSavePanel *) sheet +- (void) browseImportSrtFileDone: (NSOpenPanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo { if( returnCode == NSOKButton ) @@ -7318,11 +7322,11 @@ return YES; NSSavePanel * panel = [NSSavePanel savePanel]; /* We get the current file name and path from the destination field here */ NSString *defaultExportDirectory = [NSString stringWithFormat: @"%@/Desktop/", NSHomeDirectory()]; - - [panel beginSheetForDirectory: defaultExportDirectory file: @"HB_Export.plist" - modalForWindow: fWindow modalDelegate: self - didEndSelector: @selector( browseExportPresetFileDone:returnCode:contextInfo: ) - contextInfo: NULL]; + [panel setDirectoryURL:[NSURL fileURLWithPath:defaultExportDirectory]]; + [panel setNameFieldStringValue:@"HB_Export.plist"]; + [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [self browseExportPresetFileDone:panel returnCode: (int)result contextInfo:sender]; + }]; } - (void) browseExportPresetFileDone: (NSSavePanel *) sheet @@ -7381,10 +7385,11 @@ return YES; */ /* set this for allowed file types, not sure if we should allow xml or not */ NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"xml", nil]; - [panel beginSheetForDirectory: sourceDirectory file: nil types: fileTypes - modalForWindow: fWindow modalDelegate: self - didEndSelector: @selector( browseImportPresetDone:returnCode:contextInfo: ) - contextInfo: sender]; + [panel setDirectoryURL:[NSURL fileURLWithPath:sourceDirectory]]; + [panel setAllowedFileTypes:fileTypes]; + [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [self browseImportPresetDone:panel returnCode:(int)result contextInfo:sender]; + }]; } - (void) browseImportPresetDone: (NSSavePanel *) sheet @@ -7719,13 +7724,13 @@ return YES; /* Open a panel to let the user choose the file */ NSOpenPanel * panel = [NSOpenPanel openPanel]; /* We get the current file name and path from the destination field here */ - [panel beginSheetForDirectory: [NSString stringWithFormat:@"%@/", - [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]] - file: NULL - types: [NSArray arrayWithObjects:@"csv",nil] - modalForWindow: fWindow modalDelegate: self - didEndSelector: @selector( browseForChapterFileDone:returnCode:contextInfo: ) - contextInfo: NULL]; + NSString* sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]; + NSArray* fileTypes = [NSArray arrayWithObjects:@"csv",nil]; + [panel setDirectoryURL:[NSURL fileURLWithPath:sourceDirectory]]; + [panel setAllowedFileTypes:fileTypes]; + [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [self browseForChapterFileDone:panel returnCode:(int)result contextInfo:sender]; + }]; } - (void) browseForChapterFileDone: (NSOpenPanel *) sheet @@ -7800,13 +7805,12 @@ return YES; NSSavePanel *panel = [NSSavePanel savePanel]; /* Open a panel to let the user save to a file */ [panel setAllowedFileTypes:[NSArray arrayWithObjects:@"csv",nil]]; - [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] - file: [[[[fDstFile2Field stringValue] lastPathComponent] stringByDeletingPathExtension] - stringByAppendingString:@"-chapters.csv"] - modalForWindow: fWindow - modalDelegate: self - didEndSelector: @selector( browseForChapterFileSaveDone:returnCode:contextInfo: ) - contextInfo: NULL]; + NSString* destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; + [panel setDirectoryURL:[NSURL fileURLWithPath:destinationDirectory]]; + [panel setNameFieldStringValue:[[[fDstFile2Field stringValue] lastPathComponent] stringByDeletingPathExtension]]; + [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [self browseForChapterFileSaveDone:panel returnCode:(int)result contextInfo:sender]; + }]; } - (void) browseForChapterFileSaveDone: (NSSavePanel *) sheet diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m index 999aa9434..b6a987f31 100644 --- a/macosx/HBAudio.m +++ b/macosx/HBAudio.m @@ -64,7 +64,7 @@ static NSMutableArray *masterBitRateArray = nil; #pragma mark - #pragma mark Object Setup -+ (void) load ++ (void) initialize { if ([HBAudio class] == self) diff --git a/macosx/HBPreferencesController.m b/macosx/HBPreferencesController.m index 4e5baccd1..d7d52d2c2 100644 --- a/macosx/HBPreferencesController.m +++ b/macosx/HBPreferencesController.m @@ -170,10 +170,10 @@ { sendToAppDirectory = @"/Applications"; } - [panel beginSheetForDirectory: sendToAppDirectory file: nil types: nil - modalForWindow: [self window] modalDelegate: self - didEndSelector: @selector( browseSendToAppDone:returnCode:contextInfo: ) - contextInfo: sender]; + [panel setDirectoryURL:[NSURL fileURLWithPath:sendToAppDirectory]]; + [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) { + [self browseSendToAppDone:panel returnCode:(int)result contextInfo:sender]; + }]; } - (void) browseSendToAppDone: (NSOpenPanel *) sheet diff --git a/macosx/HBPresets.m b/macosx/HBPresets.m index 0281a4365..a97284b11 100644 --- a/macosx/HBPresets.m +++ b/macosx/HBPresets.m @@ -60,6 +60,7 @@ [childrenArray addObject:[self createAppleTV3Preset]]; [childrenArray addObject:[self createAndroidPreset]]; [childrenArray addObject:[self createAndroidTabletPreset]]; + [childrenArray addObject:[self createW8PhonePreset]]; /* Add the individual presets to the folder */ [preset setObject:[NSMutableArray arrayWithArray:childrenArray] @@ -1081,6 +1082,110 @@ return preset; } +- (NSDictionary *)createW8PhonePreset +{ + NSMutableDictionary *preset = [[NSMutableDictionary alloc] init]; + + /* Preset properties (name, type: factory/user, default, folder, tooltip) */ + [preset setObject:@"Windows Phone 8" forKey:@"PresetName"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"]; //factory + [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"]; + [preset setObject:[NSNumber numberWithBool:NO] forKey:@"Folder"]; + [preset setObject:@"HandBrake's preset for Windows Phone 8 devices" + forKey:@"PresetDescription"]; + + /* Container format and related settings */ + [preset setObject:@"MP4 file" forKey:@"FileFormat"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"Mp4LargeFile"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"Mp4HttpOptimize"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"Mp4iPodCompatible"]; + + /* Chapter markers */ + [preset setObject:[NSNumber numberWithInt:0] forKey:@"ChapterMarkers"]; + + /* Video encoder and advanced options */ + [preset setObject:@"H.264 (x264)" forKey:@"VideoEncoder"]; + [preset setObject:@"" forKey:@"lavcOption"]; + [preset setObject:@"" forKey:@"x264Option"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"x264UseAdvancedOptions"]; + [preset setObject:@"medium" forKey:@"x264Preset"]; + [preset setObject:@"" forKey:@"x264Tune"]; + [preset setObject:@"" forKey:@"x264OptionExtra"]; + [preset setObject:@"main" forKey:@"h264Profile"]; + [preset setObject:@"3.1" forKey:@"h264Level"]; + + /* Video rate control */ + [preset setObject:@"2500" forKey:@"VideoAvgBitrate"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTurboTwoPass"]; + [preset setObject:[NSNumber numberWithInt:2] forKey:@"VideoQualityType"]; //cq + [preset setObject:[NSNumber numberWithFloat:22.0] forKey:@"VideoQualitySlider"]; + + /* Video frame rate */ + [preset setObject:@"30" forKey:@"VideoFramerate"]; + [preset setObject:@"pfr" forKey:@"VideoFramerateMode"]; + + /* Picture size */ + [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"]; + [preset setObject:[NSNumber numberWithInt:1280] forKey:@"PictureWidth"]; + [preset setObject:[NSNumber numberWithInt:720] forKey:@"PictureHeight"]; + [preset setObject:[NSNumber numberWithInt:2] forKey:@"PicturePAR"]; //loose + [preset setObject:[NSNumber numberWithInt:2] forKey:@"PictureModulus"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"]; //set to 0 for Loose (FIXME: why?) + + /* Picture filters */ + [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureFilters"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDecomb"]; //off + [preset setObject:@"" forKey:@"PictureDecombCustom"]; + [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureDecombDeinterlace"]; //decomb + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"]; + [preset setObject:@"" forKey:@"PictureDeinterlaceCustom"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDetelecine"]; + [preset setObject:@"" forKey:@"PictureDetelecineCustom"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDenoise"]; + [preset setObject:@"" forKey:@"PictureDenoiseCustom"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeblock"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"]; + + /* Picture crop */ + [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureAutoCrop"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"]; + [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"]; + + /* Auto Passthru */ + [preset setObject:@"AC3 (ffmpeg)" forKey:@"AudioEncoderFallback"]; + [preset setObject:[NSNumber numberWithInt:1] forKey:@"AudioAllowAACPass"]; + [preset setObject:[NSNumber numberWithInt:1] forKey:@"AudioAllowAC3Pass"]; + [preset setObject:[NSNumber numberWithInt:1] forKey:@"AudioAllowDTSHDPass"]; + [preset setObject:[NSNumber numberWithInt:1] forKey:@"AudioAllowDTSPass"]; + [preset setObject:[NSNumber numberWithInt:1] forKey:@"AudioAllowMP3Pass"]; + + /* Audio track list - no need to add "None" at the end */ + NSMutableArray *audioListArray = [[NSMutableArray alloc] init]; + /* Track 1 */ + NSMutableDictionary *audioTrack1Array = [[NSMutableDictionary alloc] init]; + [audioTrack1Array setObject:[NSNumber numberWithInt:1] forKey:@"AudioTrack"]; + [audioTrack1Array setObject:@"AAC (faac)" forKey:@"AudioEncoder"]; + [audioTrack1Array setObject:@"Dolby Pro Logic II" forKey:@"AudioMixdown"]; + [audioTrack1Array setObject:@"Auto" forKey:@"AudioSamplerate"]; + [audioTrack1Array setObject:@"128" forKey:@"AudioBitrate"]; + [audioTrack1Array setObject:[NSNumber numberWithFloat:0.0] forKey:@"AudioTrackGainSlider"]; + [audioTrack1Array setObject:[NSNumber numberWithFloat:0.0] forKey:@"AudioTrackDRCSlider"]; + [audioTrack1Array autorelease]; + [audioListArray addObject:audioTrack1Array]; + /* Add the audio track(s) to the preset's audio list */ + [preset setObject:[NSMutableArray arrayWithArray:audioListArray] forKey:@"AudioList"]; + + /* Subtitles (note: currently ignored) */ + [preset setObject:@"None" forKey:@"Subtitles"]; + + /* Clean up and return the preset */ + [preset autorelease]; + return preset; +} + - (NSDictionary *)createNormalPreset { NSMutableDictionary *preset = [[NSMutableDictionary alloc] init]; diff --git a/macosx/main.mm b/macosx/main.mm index 24cd7547f..bc5159fae 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -64,9 +64,10 @@ char * str_printf(const char *fmt, ...) } } -int main( int argc, const char ** argv ) +int main(int argc, const char **argv) { - signal( SIGINT, SigHandler ); + signal(SIGINT, SigHandler); + hb_global_init(); hb_register_error_handler(&hb_error_handler); - return NSApplicationMain( argc, argv ); + return NSApplicationMain(argc, argv); } diff --git a/scripts/manicure.rb b/scripts/manicure.rb index c6d2cdc3f..b8be37432 100755 --- a/scripts/manicure.rb +++ b/scripts/manicure.rb @@ -377,6 +377,10 @@ class Display #Mixdowns case audioTrack["AudioMixdown"] + when "Mono (Left Only)" + audioMixdowns << "left_only" + when "Mono (Right Only)" + audioMixdowns << "right_only" when /Mono/ audioMixdowns << "mono" when /Stereo/ @@ -385,10 +389,16 @@ class Display audioMixdowns << "dpl1" when /Dolby Pro Logic II/ audioMixdowns << "dpl2" - when /discrete/ - audioMixdowns << "6ch" + when /5.1/, /discrete/ + audioMixdowns << "5point1" + when /6.1/ + audioMixdowns << "6point1" + when "7.1 (5F/2R/LFE)" + audioMixdowns << "5_2_lfe" + when /7.1/ + audioMixdowns << "7point1" when /None/ - audioMixdowns << "auto" + audioMixdowns << "none" end #Samplerates @@ -765,6 +775,10 @@ class Display #Mixdowns case audioTrack["AudioMixdown"] + when "Mono (Left Only)" + audioMixdowns << "left_only" + when "Mono (Right Only)" + audioMixdowns << "right_only" when /Mono/ audioMixdowns << "mono" when /Stereo/ @@ -773,10 +787,16 @@ class Display audioMixdowns << "dpl1" when /Dolby Pro Logic II/ audioMixdowns << "dpl2" - when /discrete/ - audioMixdowns << "6ch" + when /5.1/, /discrete/ + audioMixdowns << "5point1" + when /6.1/ + audioMixdowns << "6point1" + when "7.1 (5F/2R/LFE)" + audioMixdowns << "5_2_lfe" + when /7.1/ + audioMixdowns << "7point1" when /None/ - audioMixdowns << "auto" + audioMixdowns << "none" end #Samplerates @@ -1159,6 +1179,10 @@ class Display #Mixdowns case audioTrack["AudioMixdown"] + when "Mono (Left Only)" + audioMixdowns << "left_only" + when "Mono (Right Only)" + audioMixdowns << "right_only" when /Mono/ audioMixdowns << "mono" when /Stereo/ @@ -1167,10 +1191,16 @@ class Display audioMixdowns << "dpl1" when /Dolby Pro Logic II/ audioMixdowns << "dpl2" - when /discrete/ - audioMixdowns << "6ch" + when /5.1/, /discrete/ + audioMixdowns << "5point1" + when /6.1/ + audioMixdowns << "6point1" + when "7.1 (5F/2R/LFE)" + audioMixdowns << "5_2_lfe" + when /7.1/ + audioMixdowns << "7point1" when /None/ - audioMixdowns << "auto" + audioMixdowns << "none" end #Samplerates @@ -1605,6 +1635,10 @@ class Display #Mixdowns case audioTrack["AudioMixdown"] + when "Mono (Left Only)" + audioMixdowns << "left_only" + when "Mono (Right Only)" + audioMixdowns << "right_only" when /Mono/ audioMixdowns << "mono" when /Stereo/ @@ -1613,10 +1647,16 @@ class Display audioMixdowns << "dpl1" when /Dolby Pro Logic II/ audioMixdowns << "dpl2" - when /discrete/ - audioMixdowns << "6ch" + when /5.1/, /discrete/ + audioMixdowns << "5point1" + when /6.1/ + audioMixdowns << "6point1" + when "7.1 (5F/2R/LFE)" + audioMixdowns << "5_2_lfe" + when /7.1/ + audioMixdowns << "7point1" when /None/ - audioMixdowns << "auto" + audioMixdowns << "none" end #Samplerates diff --git a/test/test.c b/test/test.c index 957861545..e3a226e54 100644 --- a/test/test.c +++ b/test/test.c @@ -187,13 +187,7 @@ 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 + hb_global_init(); audios = hb_list_init(); @@ -747,7 +741,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !mixdowns ) { - mixdowns = strdup("dpl2,auto"); + mixdowns = strdup("dpl2,none"); } if( !arates ) { @@ -1023,7 +1017,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !mixdowns ) { - mixdowns = strdup("dpl2,auto"); + mixdowns = strdup("dpl2,none"); } if( !arates ) { @@ -1097,7 +1091,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !mixdowns ) { - mixdowns = strdup("dpl2,auto"); + mixdowns = strdup("dpl2,none"); } if( !arates ) { @@ -1167,7 +1161,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !mixdowns ) { - mixdowns = strdup("dpl2,auto"); + mixdowns = strdup("dpl2,none"); } if( !arates ) { @@ -1350,6 +1344,74 @@ static int HandleEvents( hb_handle_t * h ) } modulus = 2; } + if (!strcasecmp(preset_name, "Windows Phone 8")) + { + if( !mux ) + { + mux = HB_MUX_MP4; + } + vcodec = HB_VCODEC_X264; + job->vquality = 22.0; + filter_vrate_base = 900000; + filter_cfr = 2; + if( !atracks ) + { + atracks = strdup("1"); + } + if( !acodecs ) + { + acodecs = strdup("faac"); + } + if( !abitrates ) + { + abitrates = str_split("128", ','); + } + if( !mixdowns ) + { + mixdowns = strdup("dpl2"); + } + if( !arates ) + { + arates = strdup("Auto"); + } + if( !dynamic_range_compression ) + { + dynamic_range_compression = strdup("0.0"); + } + if( allowed_audio_copy == -1 ) + { + allowed_audio_copy = 0; + allowed_audio_copy |= HB_ACODEC_AAC_PASS; + allowed_audio_copy |= HB_ACODEC_AC3_PASS; + allowed_audio_copy |= HB_ACODEC_DCA_HD_PASS; + allowed_audio_copy |= HB_ACODEC_DCA_PASS; + allowed_audio_copy |= HB_ACODEC_MP3_PASS; + allowed_audio_copy &= HB_ACODEC_PASS_MASK; + } + if( acodec_fallback == NULL ) + { + acodec_fallback = "ffac3"; + } + maxWidth = 1280; + maxHeight = 720; + if (x264_preset == NULL) + { + x264_preset = strdup("medium"); + } + if (h264_profile == NULL) + { + h264_profile = strdup("main"); + } + if (h264_level == NULL) + { + h264_level = strdup("3.1"); + } + if( !anamorphic_mode ) + { + anamorphic_mode = 2; + } + modulus = 2; + } if (!strcasecmp(preset_name, "Normal")) { if( !mux ) @@ -1438,7 +1500,7 @@ static int HandleEvents( hb_handle_t * h ) } if( !mixdowns ) { - mixdowns = strdup("dpl2,auto"); + mixdowns = strdup("dpl2,none"); } if( !arates ) { @@ -1984,7 +2046,7 @@ static int HandleEvents( hb_handle_t * h ) token = acodecs; while ( token != NULL ) { - if ((acodec = hb_audio_encoder_get_from_name(token)) == -1) + if ((acodec = hb_audio_encoder_get_from_name(token)) <= 0) { fprintf(stderr, "Invalid codec %s, using default for container.\n", token); acodec = hb_audio_encoder_get_default(job->mux); @@ -2057,7 +2119,7 @@ static int HandleEvents( hb_handle_t * h ) { arate = hb_audio_samplerate_get_from_name(token); } - if (arate == -1) + if (arate <= 0) { fprintf(stderr, "Invalid sample rate %s, using input rate %d\n", @@ -2436,9 +2498,6 @@ static int HandleEvents( hb_handle_t * h ) // Auto Passthru job->acodec_copy_mask = allowed_audio_copy == -1 ? HB_ACODEC_PASS_MASK : allowed_audio_copy; job->acodec_fallback = hb_audio_encoder_get_from_name(acodec_fallback); - // sanitize the fallback; -1 isn't a valid HB_ACODEC_* value - if (job->acodec_fallback == -1) - job->acodec_fallback = 0; } else if( ( audio->out.codec & HB_ACODEC_PASS_FLAG ) && !( audio->out.codec & audio->in.codec & HB_ACODEC_PASS_MASK ) ) @@ -2983,6 +3042,7 @@ static void ShowHelp() "### Video Options------------------------------------------------------------\n\n" " -e, --encoder Set video library encoder\n" " Options: " ); + name = NULL; encoder = NULL; while ((encoder = hb_video_encoder_get_next(encoder)) != NULL) { @@ -3398,19 +3458,20 @@ static void ShowPresets() fprintf( stderr, "%s - %s - %s\n", HB_PROJECT_TITLE, HB_PROJECT_BUILD_TITLE, HB_PROJECT_URL_WEBSITE ); printf("\n< Devices\n"); - printf("\n + Universal: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -X 720 -Y 576 --loose-anamorphic --modulus 2 -m --x264-preset fast --h264-profile baseline --h264-level 3.0\n"); + printf("\n + Universal: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -X 720 -Y 576 --loose-anamorphic --modulus 2 -m --x264-preset fast --h264-profile baseline --h264-level 3.0\n"); printf("\n + iPod: -e x264 -q 22.0 -r 30 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -I -X 320 -Y 240 --modulus 2 -m --x264-preset medium --h264-profile baseline --h264-level 1.3\n"); printf("\n + iPhone & iPod touch: -e x264 -q 22.0 -r 30 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 960 -Y 640 --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 3.1\n"); printf("\n + iPad: -e x264 -q 20.0 -r 30 --pfr -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 1280 -Y 720 --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 3.1\n"); - printf("\n + AppleTV: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 960 -Y 720 --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 3.1 -x qpmin=4:cabac=0:ref=2:b-pyramid=none:weightb=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500\n"); - printf("\n + AppleTV 2: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 1280 -Y 720 --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 3.1\n"); - printf("\n + AppleTV 3: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 1920 -Y 1080 --decomb=fast --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.0\n"); + printf("\n + AppleTV: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 960 -Y 720 --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 3.1 -x qpmin=4:cabac=0:ref=2:b-pyramid=none:weightb=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500\n"); + printf("\n + AppleTV 2: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 1280 -Y 720 --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 3.1\n"); + printf("\n + AppleTV 3: -e x264 -q 20.0 -r 30 --pfr -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 -X 1920 -Y 1080 --decomb=fast --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.0\n"); printf("\n + Android: -e x264 -q 22.0 -r 30 --pfr -a 1 -E faac -B 128 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -X 720 -Y 576 --loose-anamorphic --modulus 2 --x264-preset medium --h264-profile main --h264-level 3.0\n"); printf("\n + Android Tablet: -e x264 -q 22.0 -r 30 --pfr -a 1 -E faac -B 128 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -X 1280 -Y 720 --loose-anamorphic --modulus 2 --x264-preset medium --h264-profile main --h264-level 3.1\n"); - printf("\n>\n"); + printf("\n + Windows Phone 8: -e x264 -q 22.0 -r 30 --pfr -a 1 -E faac -B 128 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -X 1280 -Y 720 --loose-anamorphic --modulus 2 --x264-preset medium --h264-profile main --h264-level 3.1\n"); + printf("\n>\n"); printf("\n< Regular\n"); printf("\n + Normal: -e x264 -q 20.0 -a 1 -E faac -B 160 -6 dpl2 -R Auto -D 0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 --loose-anamorphic --modulus 2 -m --x264-preset veryfast --h264-profile main --h264-level 4.0\n"); - printf("\n + High Profile: -e x264 -q 20.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,auto -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 --decomb --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.1\n"); + printf("\n + High Profile: -e x264 -q 20.0 -a 1,1 -E faac,copy:ac3 -B 160,160 -6 dpl2,none -R Auto,Auto -D 0.0,0.0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback ffac3 -f mp4 -4 --decomb --loose-anamorphic --modulus 2 -m --x264-preset medium --h264-profile high --h264-level 4.1\n"); printf("\n>\n"); } diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj index 85ee06fb7..83535814b 100644 --- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj +++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj @@ -157,6 +157,7 @@ + @@ -432,6 +433,7 @@ Always + Designer diff --git a/win/CS/HandBrakeWPF/Helpers/AppStyleHelper.cs b/win/CS/HandBrakeWPF/Helpers/AppStyleHelper.cs new file mode 100644 index 000000000..9b67f97e2 --- /dev/null +++ b/win/CS/HandBrakeWPF/Helpers/AppStyleHelper.cs @@ -0,0 +1,37 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Defines the AppStyleHelper type. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Helpers +{ + using System.Windows; + + using Caliburn.Micro; + + using HandBrake.ApplicationServices.Services.Interfaces; + + /// + /// The AppStyle Helper. + /// + public class AppStyleHelper + { + /// + /// Gets a value indicating whether use system colours. + /// + public static bool UseSystemColours + { + get + { + IUserSettingService userSettingService = IoC.Get(); + bool useSystemColours = userSettingService.GetUserSetting(UserSettingConstants.UseSystemColours); + + return useSystemColours || SystemParameters.HighContrast; + } + } + } +} diff --git a/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs b/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs index 2298eb4ab..407748027 100644 --- a/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs +++ b/win/CS/HandBrakeWPF/Helpers/AutoNameHelper.cs @@ -47,7 +47,7 @@ namespace HandBrakeWPF.Helpers } string autoNamePath = string.Empty; - if (task.Title != 0) // TODO check. + if (task.Title != 0) { // Get the Source Name and remove any invalid characters string sourceName = Path.GetInvalidFileNameChars().Aggregate(sourceOrLabelName, (current, character) => current.Replace(character.ToString(), string.Empty)); @@ -56,6 +56,13 @@ namespace HandBrakeWPF.Helpers if (userSettingService.GetUserSetting(UserSettingConstants.AutoNameRemoveUnderscore)) sourceName = sourceName.Replace("_", " "); + if (userSettingService.GetUserSetting(UserSettingConstants.RemovePunctuation)) + { + sourceName = sourceName.Replace("-", string.Empty); + sourceName = sourceName.Replace(",", string.Empty); + sourceName = sourceName.Replace(".", string.Empty); + } + // Switch to "Title Case" if (userSettingService.GetUserSetting(UserSettingConstants.AutoNameTitleCase)) sourceName = sourceName.ToTitleCase(); @@ -170,21 +177,16 @@ namespace HandBrakeWPF.Helpers public static bool IsAutonamingEnabled() { IUserSettingService userSettingService = IoC.Get(); - // If there is an auto name path, use it... - if (userSettingService.GetUserSetting(UserSettingConstants.AutoNamePath).Trim().StartsWith("{source_path}")) - { - return true; - } - else if (userSettingService.GetUserSetting(UserSettingConstants.AutoNamePath).Contains("{source_folder_name}")) - { - return true; - } - else + + if (!userSettingService.GetUserSetting(UserSettingConstants.AutoNaming)) { - return - Directory.Exists( - userSettingService.GetUserSetting(UserSettingConstants.AutoNamePath).Trim()); + return false; } + + // If there is an auto name path, use it... + return userSettingService.GetUserSetting(UserSettingConstants.AutoNamePath).Trim().StartsWith("{source_path}") || + (userSettingService.GetUserSetting(UserSettingConstants.AutoNamePath).Contains("{source_folder_name}") || + Directory.Exists(userSettingService.GetUserSetting(UserSettingConstants.AutoNamePath).Trim())); } } } diff --git a/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs b/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs index f0b809849..4be52964e 100644 --- a/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs +++ b/win/CS/HandBrakeWPF/Model/SourceMenuItem.cs @@ -55,5 +55,10 @@ namespace HandBrakeWPF.Model /// Gets or sets the tag. /// public object Tag { get; set; } + + /// + /// Gets or sets the input gesture text. + /// + public string InputGestureText { get; set; } } } diff --git a/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs b/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs index bef7d7030..05ecfba15 100644 --- a/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs +++ b/win/CS/HandBrakeWPF/Properties/Resources.Designer.cs @@ -347,6 +347,24 @@ namespace HandBrakeWPF.Properties { } } + /// + /// Looks up a localized string similar to The Built-in presets have been reset.. + /// + public static string Presets_ResetComplete { + get { + return ResourceManager.GetString("Presets_ResetComplete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Complete. + /// + public static string Presets_ResetHeader { + get { + return ResourceManager.GetString("Presets_ResetHeader", resourceCulture); + } + } + /// /// Looks up a localized string similar to WARNING: You do not have automatic file naming turned on. Please enable this in options.. /// @@ -365,6 +383,15 @@ namespace HandBrakeWPF.Properties { } } + /// + /// Looks up a localized string similar to Higher Quality |. + /// + public static string Video_HigherQuality { + get { + return ResourceManager.GetString("Video_HigherQuality", resourceCulture); + } + } + /// /// Looks up a localized string similar to Warning: RF 0 is Lossless!. /// @@ -390,6 +417,24 @@ namespace HandBrakeWPF.Properties { } } + /// + /// Looks up a localized string similar to | Lower Quality. + /// + public static string Video_LowQuality { + get { + return ResourceManager.GetString("Video_LowQuality", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Placebo Quality |. + /// + public static string Video_PlaceboQuality { + get { + return ResourceManager.GetString("Video_PlaceboQuality", resourceCulture); + } + } + /// /// Looks up a localized string similar to Set the desired quality factor. The encoder targets a certain quality. ///The scale used by each video encoder is different. diff --git a/win/CS/HandBrakeWPF/Properties/Resources.resx b/win/CS/HandBrakeWPF/Properties/Resources.resx index 180d0abc5..2b08ae332 100644 --- a/win/CS/HandBrakeWPF/Properties/Resources.resx +++ b/win/CS/HandBrakeWPF/Properties/Resources.resx @@ -337,4 +337,19 @@ If you do not use this tab, it can be hidden from: Tools Menu > Options > WARNING: You do not currently have automatic audio and subtitle track selection setup. You can setup the default track selection behaviour in options. + + The Built-in presets have been reset. + + + Reset Complete + + + Higher Quality | + + + | Lower Quality + + + Placebo Quality | + \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/UserSettingConstants.cs b/win/CS/HandBrakeWPF/UserSettingConstants.cs index b70d88654..b9ce40b0c 100644 --- a/win/CS/HandBrakeWPF/UserSettingConstants.cs +++ b/win/CS/HandBrakeWPF/UserSettingConstants.cs @@ -226,6 +226,21 @@ namespace HandBrakeWPF /// public const string PreventSleep = "PreventSleep"; + /// + /// The remove punctuation. + /// + public const string RemovePunctuation = "RemovePunctuation"; + + /// + /// The Show Preset Panel + /// + public const string ShowPresetPanel = "ShowPresetPanel"; + + /// + /// The use system colours. + /// + public const string UseSystemColours = "UseSystemColours"; + #endregion } } \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index e9bb292d1..4978ae1ed 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -33,6 +33,7 @@ namespace HandBrakeWPF.ViewModels using HandBrakeWPF.Commands; using HandBrakeWPF.Helpers; using HandBrakeWPF.Model; + using HandBrakeWPF.Properties; using HandBrakeWPF.Services.Interfaces; using HandBrakeWPF.ViewModels.Interfaces; using HandBrakeWPF.Views; @@ -179,6 +180,12 @@ namespace HandBrakeWPF.ViewModels /// The last percentage complete value. /// private int lastEncodePercentage; + + /// + /// The is preset panel showing. + /// + private bool isPresetPanelShowing; + #endregion /// @@ -736,7 +743,7 @@ namespace HandBrakeWPF.ViewModels if (this.UserSettingService.GetUserSetting(UserSettingConstants.AutoNaming)) { - if (this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat) != null ) + if (this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameFormat) != null) { this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName); } @@ -936,6 +943,33 @@ namespace HandBrakeWPF.ViewModels } } + /// + /// Gets or sets a value indicating whether is preset panel showing. + /// + public bool IsPresetPanelShowing + { + get + { + return this.isPresetPanelShowing; + } + set + { + if (!object.Equals(this.isPresetPanelShowing, value)) + { + this.isPresetPanelShowing = value; + this.NotifyOfPropertyChange(() => this.IsPresetPanelShowing); + + // Save the setting if it has changed. + if (this.userSettingService.GetUserSetting(UserSettingConstants.ShowPresetPanel) != value) + { + this.userSettingService.SetUserSetting(UserSettingConstants.ShowPresetPanel, value); + } + } + } + } + + public int ProgressPercentage { get; set; } + #endregion #region Load and Shutdown Handling @@ -965,6 +999,9 @@ namespace HandBrakeWPF.ViewModels // Populate the Source menu with drives. this.SourceMenu = new BindingList(this.GenerateSourceMenu()); + // Show or Hide the Preset Panel. + this.IsPresetPanelShowing = this.userSettingService.GetUserSetting(UserSettingConstants.ShowPresetPanel); + // Log Cleaning if (userSettingService.GetUserSetting(UserSettingConstants.ClearOldLogs)) { @@ -1607,6 +1644,22 @@ namespace HandBrakeWPF.ViewModels this.presetService.UpdateBuiltInPresets(); this.NotifyOfPropertyChange("Presets"); this.SelectedPreset = this.presetService.DefaultPreset; + this.errorService.ShowMessageBox(Resources.Presets_ResetComplete, Resources.Presets_ResetHeader, MessageBoxButton.OK, MessageBoxImage.Information); + } + + /// + /// The preset select. + /// + /// + /// The tag. + /// + public void PresetSelect(object tag) + { + Preset preset = tag as Preset; + if (preset != null) + { + this.SelectedPreset = preset; + } } /// @@ -1924,6 +1977,8 @@ namespace HandBrakeWPF.ViewModels } lastEncodePercentage = percent; + this.ProgressPercentage = percent; + this.NotifyOfPropertyChange(() => ProgressPercentage); } else { @@ -2030,14 +2085,16 @@ namespace HandBrakeWPF.ViewModels Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/folder.png")), Width = 16, Height = 16 }, Text = "Open Folder", Command = new SourceMenuCommand(this.FolderScan), - IsDrive = false + IsDrive = false, + InputGestureText = "Ctrl + R" }; SourceMenuItem fileScan = new SourceMenuItem { Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/Movies.png")), Width = 16, Height = 16 }, Text = "Open File", Command = new SourceMenuCommand(this.FileScan), - IsDrive = false + IsDrive = false, + InputGestureText = "Ctrl + F" }; SourceMenuItem titleSpecific = new SourceMenuItem { Text = "Title Specific Scan" }; diff --git a/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs index ad012db4f..e1376363a 100644 --- a/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/OptionsViewModel.cs @@ -353,6 +353,16 @@ namespace HandBrakeWPF.ViewModels /// private bool showAdvancedTab; + /// + /// The remove punctuation. + /// + private bool removePunctuation; + + /// + /// The use system colours for styles. + /// + private bool useSystemColoursForStyles; + #endregion #region Constructors and Destructors @@ -599,6 +609,23 @@ namespace HandBrakeWPF.ViewModels this.NotifyOfPropertyChange("WhenDoneOptions"); } } + + /// + /// Gets or sets a value indicating whether use system colours. + /// + public bool UseSystemColoursForStylesForStyles + { + get + { + return this.useSystemColoursForStyles; + } + set + { + this.useSystemColoursForStyles = value; + this.NotifyOfPropertyChange(() => UseSystemColoursForStylesForStyles); + } + } + #endregion #region Output Files @@ -722,6 +749,22 @@ namespace HandBrakeWPF.ViewModels } } + /// + /// Gets or sets a value indicating whether remove punctuation. + /// + public bool RemovePunctuation + { + get + { + return this.removePunctuation; + } + set + { + this.removePunctuation = value; + this.NotifyOfPropertyChange(() => RemovePunctuation); + } + } + #endregion #region Preview @@ -1493,6 +1536,7 @@ namespace HandBrakeWPF.ViewModels this.SendFileTo = Path.GetFileNameWithoutExtension(this.userSettingService.GetUserSetting(UserSettingConstants.SendFileTo)) ?? string.Empty; this.SendFileToPath = this.userSettingService.GetUserSetting(UserSettingConstants.SendFileTo) ?? string.Empty; this.Arguments = this.userSettingService.GetUserSetting(UserSettingConstants.SendFileToArgs) ?? string.Empty; + this.UseSystemColoursForStylesForStyles = this.userSettingService.GetUserSetting(UserSettingConstants.UseSystemColours); // ############################# // Output Settings @@ -1521,6 +1565,7 @@ namespace HandBrakeWPF.ViewModels // Title case this.ChangeToTitleCase = this.userSettingService.GetUserSetting(UserSettingConstants.AutoNameTitleCase); + this.RemovePunctuation = this.userSettingService.GetUserSetting(UserSettingConstants.RemovePunctuation); // ############################# // Picture Tab @@ -1828,6 +1873,7 @@ namespace HandBrakeWPF.ViewModels this.userSettingService.SetUserSetting(UserSettingConstants.SendFileTo, this.SendFileToPath); this.userSettingService.SetUserSetting(UserSettingConstants.SendFile, this.SendFileAfterEncode); this.userSettingService.SetUserSetting(UserSettingConstants.SendFileToArgs, this.Arguments); + this.userSettingService.SetUserSetting(UserSettingConstants.UseSystemColours, this.UseSystemColoursForStylesForStyles); /* Output Files */ this.userSettingService.SetUserSetting(UserSettingConstants.AutoNaming, this.AutomaticallyNameFiles); @@ -1836,6 +1882,7 @@ namespace HandBrakeWPF.ViewModels this.userSettingService.SetUserSetting(UserSettingConstants.UseM4v, this.SelectedMp4Extension); this.userSettingService.SetUserSetting(UserSettingConstants.AutoNameRemoveUnderscore, this.RemoveUnderscores); this.userSettingService.SetUserSetting(UserSettingConstants.AutoNameTitleCase, this.ChangeToTitleCase); + this.userSettingService.SetUserSetting(UserSettingConstants.RemovePunctuation, this.RemovePunctuation); /* Previews */ this.userSettingService.SetUserSetting(UserSettingConstants.VLC_Path, this.VLCPath); diff --git a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs index 972af2910..87d0bb0c9 100644 --- a/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/PictureSettingsViewModel.cs @@ -736,24 +736,6 @@ namespace HandBrakeWPF.ViewModels this.MaxHeight = preset.Task.MaxHeight ?? this.sourceResolution.Height; } - // Update the cropping values, preffering those in the presets. - if (!preset.Task.HasCropping) - { - this.CropTop = title.AutoCropDimensions.Top; - this.CropBottom = title.AutoCropDimensions.Bottom; - this.CropLeft = title.AutoCropDimensions.Left; - this.CropRight = title.AutoCropDimensions.Right; - this.IsCustomCrop = false; - } - else - { - this.CropLeft = preset.Task.Cropping.Left; - this.CropRight = preset.Task.Cropping.Right; - this.CropTop = preset.Task.Cropping.Top; - this.CropBottom = preset.Task.Cropping.Bottom; - this.IsCustomCrop = true; - } - // Set the Width, and Maintain Aspect ratio. That should calc the Height for us. this.Width = preset.Task.Width ?? this.MaxWidth; // Note: This will be auto-corrected in the property if it's too large. @@ -769,6 +751,24 @@ namespace HandBrakeWPF.ViewModels } } + // Update the cropping values, preffering those in the presets. + if (!preset.Task.HasCropping) + { + this.CropTop = title.AutoCropDimensions.Top; + this.CropBottom = title.AutoCropDimensions.Bottom; + this.CropLeft = title.AutoCropDimensions.Left; + this.CropRight = title.AutoCropDimensions.Right; + this.IsCustomCrop = false; + } + else + { + this.CropLeft = preset.Task.Cropping.Left; + this.CropRight = preset.Task.Cropping.Right; + this.CropTop = preset.Task.Cropping.Top; + this.CropBottom = preset.Task.Cropping.Bottom; + this.IsCustomCrop = true; + } + // Set Screen Controls this.SourceInfo = string.Format( "{0}x{1}, Aspect Ratio: {2:0.00}", diff --git a/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs index a64378a49..39fee77fd 100644 --- a/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs @@ -15,6 +15,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Services.Interfaces; + using HandBrakeWPF.Helpers; using HandBrakeWPF.Model; using HandBrakeWPF.Services.Interfaces; using HandBrakeWPF.ViewModels.Interfaces; diff --git a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs index e5a8d6159..a59c9c32f 100644 --- a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs @@ -393,6 +393,18 @@ namespace HandBrakeWPF.ViewModels } } + /// + /// Gets the high quality label. + /// + public string HighQualityLabel + { + get + { + return this.SelectedVideoEncoder == VideoEncoder.X264 ? Resources.Video_PlaceboQuality : Resources.Video_HigherQuality; + } + } + + /// /// Gets or sets SelectedFramerate. /// @@ -459,6 +471,7 @@ namespace HandBrakeWPF.ViewModels this.DisplayX264Options = value == VideoEncoder.X264; this.NotifyOfPropertyChange(() => this.Rfqp); + this.NotifyOfPropertyChange(() => this.HighQualityLabel); } } @@ -938,7 +951,6 @@ namespace HandBrakeWPF.ViewModels width = 720; } - // TODO figure out what is wrong with this?? return HandBrakeUtils.CreateX264OptionsString(preset, tunes, this.ExtraArguments, profile, this.H264Level, width, height); } diff --git a/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs b/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs index f1766741e..7a13881dc 100644 --- a/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs +++ b/win/CS/HandBrakeWPF/ViewModels/ViewModelBase.cs @@ -13,6 +13,7 @@ namespace HandBrakeWPF.ViewModels using HandBrake.ApplicationServices.Services.Interfaces; + using HandBrakeWPF.Helpers; using HandBrakeWPF.ViewModels.Interfaces; /// @@ -64,6 +65,17 @@ namespace HandBrakeWPF.ViewModels } } + /// + /// Gets a value indicating whether use system colours. + /// + public bool UseSystemColours + { + get + { + return AppStyleHelper.UseSystemColours; + } + } + /// /// Gets or sets WindowManager. /// diff --git a/win/CS/HandBrakeWPF/Views/AudioView.xaml b/win/CS/HandBrakeWPF/Views/AudioView.xaml index 28d17d776..99e0da02c 100644 --- a/win/CS/HandBrakeWPF/Views/AudioView.xaml +++ b/win/CS/HandBrakeWPF/Views/AudioView.xaml @@ -105,17 +105,30 @@ + + + + diff --git a/win/CS/HandBrakeWPF/Views/ChaptersView.xaml b/win/CS/HandBrakeWPF/Views/ChaptersView.xaml index 0895579f5..583e2c41d 100644 --- a/win/CS/HandBrakeWPF/Views/ChaptersView.xaml +++ b/win/CS/HandBrakeWPF/Views/ChaptersView.xaml @@ -3,6 +3,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:cal="http://www.caliburnproject.org" + d:DesignHeight="170" + d:DesignWidth="616" mc:Ignorable="d" > @@ -26,7 +28,7 @@ diff --git a/win/CS/HandBrakeWPF/Views/MainView.xaml b/win/CS/HandBrakeWPF/Views/MainView.xaml index 70ee6c63c..cf7858859 100644 --- a/win/CS/HandBrakeWPF/Views/MainView.xaml +++ b/win/CS/HandBrakeWPF/Views/MainView.xaml @@ -7,7 +7,6 @@ xmlns:Micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro" xmlns:attachedProperties="clr-namespace:HandBrakeWPF.AttachedProperties" AllowDrop="True" - Background="#FFF0F0F0" FontSize="11" Micro:Message.Attach="[Event Loaded] = [Action Load]" SnapsToDevicePixels="True" @@ -22,8 +21,7 @@ - - + + + + + + + + + + + + + + + + + + + - + - + - - - + + + @@ -168,6 +212,7 @@ + @@ -323,8 +368,8 @@ - - + + @@ -379,7 +424,7 @@ Converter={StaticResource boolToVisConverter}, ConverterParameter=false}" /> - + - - + + diff --git a/win/CS/HandBrakeWPF/defaultsettings.xml b/win/CS/HandBrakeWPF/defaultsettings.xml index 10480d486..30eebc778 100644 --- a/win/CS/HandBrakeWPF/defaultsettings.xml +++ b/win/CS/HandBrakeWPF/defaultsettings.xml @@ -448,4 +448,28 @@ false + + + RemovePunctuation + + + false + + + + + ShowPresetPanel + + + true + + + + + UseSystemColours + + + false + + \ No newline at end of file -- 2.49.0