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);
1, TRUE,
2, mix->short_name,
3, (gdouble)mix->amixdown,
- 4, mix->internal_name,
+ 4, mix->short_name,
-1);
g_free(str);
}
GError *error = NULL;
GOptionContext *context;
+ hb_global_init();
+
#ifdef ENABLE_NLS
bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
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"},
}
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);
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";
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);
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);
}
}
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);
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";
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);
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);
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)
{
<key>x264UseAdvancedOptions</key>
<integer>0</integer>
</dict>
+ <dict>
+ <key>AudioAllowAACPass</key>
+ <integer>1</integer>
+ <key>AudioAllowAC3Pass</key>
+ <integer>1</integer>
+ <key>AudioAllowDTSHDPass</key>
+ <integer>1</integer>
+ <key>AudioAllowDTSPass</key>
+ <integer>1</integer>
+ <key>AudioAllowMP3Pass</key>
+ <integer>1</integer>
+ <key>AudioEncoderFallback</key>
+ <string>AC3 (ffmpeg)</string>
+ <key>AudioList</key>
+ <array>
+ <dict>
+ <key>AudioBitrate</key>
+ <string>128</string>
+ <key>AudioEncoder</key>
+ <string>AAC (faac)</string>
+ <key>AudioMixdown</key>
+ <string>Dolby Pro Logic II</string>
+ <key>AudioSamplerate</key>
+ <string>Auto</string>
+ <key>AudioTrack</key>
+ <integer>1</integer>
+ <key>AudioTrackDRCSlider</key>
+ <real>0.0</real>
+ <key>AudioTrackGainSlider</key>
+ <real>0.0</real>
+ </dict>
+ </array>
+ <key>ChapterMarkers</key>
+ <integer>0</integer>
+ <key>Default</key>
+ <integer>0</integer>
+ <key>FileFormat</key>
+ <string>MP4 file</string>
+ <key>Folder</key>
+ <false/>
+ <key>Mp4HttpOptimize</key>
+ <integer>0</integer>
+ <key>Mp4LargeFile</key>
+ <integer>0</integer>
+ <key>Mp4iPodCompatible</key>
+ <integer>0</integer>
+ <key>PictureAutoCrop</key>
+ <integer>1</integer>
+ <key>PictureBottomCrop</key>
+ <integer>0</integer>
+ <key>PictureDeblock</key>
+ <integer>0</integer>
+ <key>PictureDecomb</key>
+ <integer>0</integer>
+ <key>PictureDecombCustom</key>
+ <string></string>
+ <key>PictureDecombDeinterlace</key>
+ <integer>1</integer>
+ <key>PictureDeinterlace</key>
+ <integer>0</integer>
+ <key>PictureDeinterlaceCustom</key>
+ <string></string>
+ <key>PictureDenoise</key>
+ <integer>0</integer>
+ <key>PictureDenoiseCustom</key>
+ <string></string>
+ <key>PictureDetelecine</key>
+ <integer>0</integer>
+ <key>PictureDetelecineCustom</key>
+ <string></string>
+ <key>PictureHeight</key>
+ <integer>720</integer>
+ <key>PictureKeepRatio</key>
+ <integer>0</integer>
+ <key>PictureLeftCrop</key>
+ <integer>0</integer>
+ <key>PictureModulus</key>
+ <integer>2</integer>
+ <key>PicturePAR</key>
+ <integer>2</integer>
+ <key>PictureRightCrop</key>
+ <integer>0</integer>
+ <key>PictureTopCrop</key>
+ <integer>0</integer>
+ <key>PictureWidth</key>
+ <integer>1280</integer>
+ <key>PresetDescription</key>
+ <string>HandBrake's preset for Windows Phone 8 devices</string>
+ <key>PresetName</key>
+ <string>Windows Phone 8</string>
+ <key>Subtitles</key>
+ <string>None</string>
+ <key>Type</key>
+ <integer>0</integer>
+ <key>UsesPictureFilters</key>
+ <integer>1</integer>
+ <key>UsesPictureSettings</key>
+ <integer>1</integer>
+ <key>VideoAvgBitrate</key>
+ <string>2500</string>
+ <key>VideoEncoder</key>
+ <string>H.264 (x264)</string>
+ <key>VideoFramerate</key>
+ <string>30</string>
+ <key>VideoFramerateMode</key>
+ <string>pfr</string>
+ <key>VideoGrayScale</key>
+ <integer>0</integer>
+ <key>VideoQualitySlider</key>
+ <real>22</real>
+ <key>VideoQualityType</key>
+ <integer>2</integer>
+ <key>VideoTurboTwoPass</key>
+ <integer>0</integer>
+ <key>VideoTwoPass</key>
+ <integer>0</integer>
+ <key>h264Level</key>
+ <string>3.1</string>
+ <key>h264Profile</key>
+ <string>main</string>
+ <key>lavcOption</key>
+ <string></string>
+ <key>x264Option</key>
+ <string></string>
+ <key>x264OptionExtra</key>
+ <string></string>
+ <key>x264Preset</key>
+ <string>medium</string>
+ <key>x264Tune</key>
+ <string></string>
+ <key>x264UseAdvancedOptions</key>
+ <integer>0</integer>
+ </dict>
</array>
<key>Default</key>
<integer>0</integer>
<key>Folder</key>
<true/>
<key>PresetBuildNumber</key>
- <integer>2013030401</integer>
+ <integer>2013061301</integer>
<key>PresetName</key>
<string>Devices</string>
<key>Type</key>
<key>Folder</key>
<true/>
<key>PresetBuildNumber</key>
- <integer>2013030401</integer>
+ <integer>2013061301</integer>
<key>PresetName</key>
<string>Regular</string>
<key>Type</key>
*********************************************************************/
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;
}
}
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;
}
}
{
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
*
* (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;
}
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;
}
}
{
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
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.
// 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.
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()
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;
}
}
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;
}
}
{
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)
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)
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;
}
}
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;
}
}
{
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)
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)
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)
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;
}
}
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;
}
}
{
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)
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)
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)
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;
}
}
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;
}
}
{
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)
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);
}
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)
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)
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:
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;
}
}
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;
}
}
{
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;
}
/**********************************************************************
/* 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;
struct hb_mixdown_s
{
const char *name;
- const char *internal_name;
const char *short_name;
int amixdown;
};
* 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.
*
*/
+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);
#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
hb_work_object_t * hb_objects = NULL;
int hb_instance_counter = 0;
-int hb_process_initialized = 0;
static void thread_func( void * );
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 *);
*/
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);
}
*/
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;
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;
}
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;
}
*_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.
*/
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();
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
***********************************************************************/
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
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))
/* 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
/* 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
}
/* 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 )
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
*/
/* 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
/* 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
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
#pragma mark -
#pragma mark Object Setup
-+ (void) load
++ (void) initialize
{
if ([HBAudio class] == self)
{
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
[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]
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];
}
}
-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);
}
#Mixdowns
case audioTrack["AudioMixdown"]
+ when "Mono (Left Only)"
+ audioMixdowns << "left_only"
+ when "Mono (Right Only)"
+ audioMixdowns << "right_only"
when /Mono/
audioMixdowns << "mono"
when /Stereo/
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
#Mixdowns
case audioTrack["AudioMixdown"]
+ when "Mono (Left Only)"
+ audioMixdowns << "left_only"
+ when "Mono (Right Only)"
+ audioMixdowns << "right_only"
when /Mono/
audioMixdowns << "mono"
when /Stereo/
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
#Mixdowns
case audioTrack["AudioMixdown"]
+ when "Mono (Left Only)"
+ audioMixdowns << "left_only"
+ when "Mono (Right Only)"
+ audioMixdowns << "right_only"
when /Mono/
audioMixdowns << "mono"
when /Stereo/
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
#Mixdowns
case audioTrack["AudioMixdown"]
+ when "Mono (Left Only)"
+ audioMixdowns << "left_only"
+ when "Mono (Right Only)"
+ audioMixdowns << "right_only"
when /Mono/
audioMixdowns << "mono"
when /Stereo/
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
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();
}
if( !mixdowns )
{
- mixdowns = strdup("dpl2,auto");
+ mixdowns = strdup("dpl2,none");
}
if( !arates )
{
}
if( !mixdowns )
{
- mixdowns = strdup("dpl2,auto");
+ mixdowns = strdup("dpl2,none");
}
if( !arates )
{
}
if( !mixdowns )
{
- mixdowns = strdup("dpl2,auto");
+ mixdowns = strdup("dpl2,none");
}
if( !arates )
{
}
if( !mixdowns )
{
- mixdowns = strdup("dpl2,auto");
+ mixdowns = strdup("dpl2,none");
}
if( !arates )
{
}
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 )
}
if( !mixdowns )
{
- mixdowns = strdup("dpl2,auto");
+ mixdowns = strdup("dpl2,none");
}
if( !arates )
{
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);
{
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",
// 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 ) )
"### Video Options------------------------------------------------------------\n\n"
" -e, --encoder <string> Set video library encoder\n"
" Options: " );
+ name = NULL;
encoder = NULL;
while ((encoder = hb_video_encoder_get_next(encoder)) != NULL)
{
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");
}
<Compile Include="Converters\Video\VideoEncoderConverter.cs" />\r
<Compile Include="Helpers\GrayscaleImage.cs" />\r
<Compile Include="Helpers\GrowlCommunicator.cs" />\r
+ <Compile Include="Helpers\AppStyleHelper.cs" />\r
<Compile Include="Model\OptionsTab.cs" />\r
<Compile Include="Model\SelectionTitle.cs" />\r
<Compile Include="Services\EncodeServiceWrapper.cs" />\r
<ItemGroup>\r
<Content Include="defaultsettings.xml">\r
<CopyToOutputDirectory>Always</CopyToOutputDirectory>\r
+ <SubType>Designer</SubType>\r
</Content>\r
<Resource Include="Views\Images\add40.png" />\r
<Resource Include="Views\Images\add.png" />\r
--- /dev/null
+// --------------------------------------------------------------------------------------------------------------------\r
+// <copyright file="AppStyleHelper.cs" company="HandBrake Project (http://handbrake.fr)">\r
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.\r
+// </copyright>\r
+// <summary>\r
+// Defines the AppStyleHelper type.\r
+// </summary>\r
+// --------------------------------------------------------------------------------------------------------------------\r
+\r
+namespace HandBrakeWPF.Helpers\r
+{\r
+ using System.Windows;\r
+\r
+ using Caliburn.Micro;\r
+\r
+ using HandBrake.ApplicationServices.Services.Interfaces;\r
+\r
+ /// <summary>\r
+ /// The AppStyle Helper.\r
+ /// </summary>\r
+ public class AppStyleHelper\r
+ {\r
+ /// <summary>\r
+ /// Gets a value indicating whether use system colours.\r
+ /// </summary>\r
+ public static bool UseSystemColours\r
+ {\r
+ get\r
+ {\r
+ IUserSettingService userSettingService = IoC.Get<IUserSettingService>();\r
+ bool useSystemColours = userSettingService.GetUserSetting<bool>(UserSettingConstants.UseSystemColours);\r
+\r
+ return useSystemColours || SystemParameters.HighContrast;\r
+ }\r
+ }\r
+ }\r
+}\r
}\r
\r
string autoNamePath = string.Empty;\r
- if (task.Title != 0) // TODO check.\r
+ if (task.Title != 0)\r
{\r
// Get the Source Name and remove any invalid characters\r
string sourceName = Path.GetInvalidFileNameChars().Aggregate(sourceOrLabelName, (current, character) => current.Replace(character.ToString(), string.Empty));\r
if (userSettingService.GetUserSetting<bool>(UserSettingConstants.AutoNameRemoveUnderscore))\r
sourceName = sourceName.Replace("_", " ");\r
\r
+ if (userSettingService.GetUserSetting<bool>(UserSettingConstants.RemovePunctuation))\r
+ {\r
+ sourceName = sourceName.Replace("-", string.Empty);\r
+ sourceName = sourceName.Replace(",", string.Empty);\r
+ sourceName = sourceName.Replace(".", string.Empty); \r
+ }\r
+ \r
// Switch to "Title Case"\r
if (userSettingService.GetUserSetting<bool>(UserSettingConstants.AutoNameTitleCase))\r
sourceName = sourceName.ToTitleCase();\r
public static bool IsAutonamingEnabled()\r
{\r
IUserSettingService userSettingService = IoC.Get<IUserSettingService>();\r
- // If there is an auto name path, use it...\r
- if (userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNamePath).Trim().StartsWith("{source_path}"))\r
- {\r
- return true;\r
- }\r
- else if (userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNamePath).Contains("{source_folder_name}"))\r
- {\r
- return true;\r
- }\r
- else\r
+\r
+ if (!userSettingService.GetUserSetting<bool>(UserSettingConstants.AutoNaming))\r
{\r
- return\r
- Directory.Exists(\r
- userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNamePath).Trim());\r
+ return false;\r
}\r
+\r
+ // If there is an auto name path, use it...\r
+ return userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNamePath).Trim().StartsWith("{source_path}") ||\r
+ (userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNamePath).Contains("{source_folder_name}") ||\r
+ Directory.Exists(userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNamePath).Trim()));\r
}\r
}\r
}\r
/// Gets or sets the tag.\r
/// </summary>\r
public object Tag { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets the input gesture text.\r
+ /// </summary>\r
+ public string InputGestureText { get; set; }\r
}\r
}\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Looks up a localized string similar to The Built-in presets have been reset..\r
+ /// </summary>\r
+ public static string Presets_ResetComplete {\r
+ get {\r
+ return ResourceManager.GetString("Presets_ResetComplete", resourceCulture);\r
+ }\r
+ }\r
+ \r
+ /// <summary>\r
+ /// Looks up a localized string similar to Reset Complete.\r
+ /// </summary>\r
+ public static string Presets_ResetHeader {\r
+ get {\r
+ return ResourceManager.GetString("Presets_ResetHeader", resourceCulture);\r
+ }\r
+ }\r
+ \r
/// <summary>\r
/// Looks up a localized string similar to WARNING: You do not have automatic file naming turned on. Please enable this in options..\r
/// </summary>\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Looks up a localized string similar to Higher Quality |.\r
+ /// </summary>\r
+ public static string Video_HigherQuality {\r
+ get {\r
+ return ResourceManager.GetString("Video_HigherQuality", resourceCulture);\r
+ }\r
+ }\r
+ \r
/// <summary>\r
/// Looks up a localized string similar to Warning: RF 0 is Lossless!.\r
/// </summary>\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Looks up a localized string similar to | Lower Quality.\r
+ /// </summary>\r
+ public static string Video_LowQuality {\r
+ get {\r
+ return ResourceManager.GetString("Video_LowQuality", resourceCulture);\r
+ }\r
+ }\r
+ \r
+ /// <summary>\r
+ /// Looks up a localized string similar to Placebo Quality |.\r
+ /// </summary>\r
+ public static string Video_PlaceboQuality {\r
+ get {\r
+ return ResourceManager.GetString("Video_PlaceboQuality", resourceCulture);\r
+ }\r
+ }\r
+ \r
/// <summary>\r
/// Looks up a localized string similar to Set the desired quality factor. The encoder targets a certain quality. \r
///The scale used by each video encoder is different.\r
<data name="QueueSelection_AutoTrackSelectionWarning" xml:space="preserve">\r
<value>WARNING: You do not currently have automatic audio and subtitle track selection setup. You can setup the default track selection behaviour in options.</value>\r
</data>\r
+ <data name="Presets_ResetComplete" xml:space="preserve">\r
+ <value>The Built-in presets have been reset.</value>\r
+ </data>\r
+ <data name="Presets_ResetHeader" xml:space="preserve">\r
+ <value>Reset Complete</value>\r
+ </data>\r
+ <data name="Video_HigherQuality" xml:space="preserve">\r
+ <value>Higher Quality |</value>\r
+ </data>\r
+ <data name="Video_LowQuality" xml:space="preserve">\r
+ <value>| Lower Quality</value>\r
+ </data>\r
+ <data name="Video_PlaceboQuality" xml:space="preserve">\r
+ <value>Placebo Quality |</value>\r
+ </data>\r
</root>
\ No newline at end of file
/// </summary>\r
public const string PreventSleep = "PreventSleep";\r
\r
+ /// <summary>\r
+ /// The remove punctuation.\r
+ /// </summary>\r
+ public const string RemovePunctuation = "RemovePunctuation";\r
+\r
+ /// <summary>\r
+ /// The Show Preset Panel\r
+ /// </summary>\r
+ public const string ShowPresetPanel = "ShowPresetPanel";\r
+\r
+ /// <summary>\r
+ /// The use system colours.\r
+ /// </summary>\r
+ public const string UseSystemColours = "UseSystemColours";\r
+\r
#endregion\r
}\r
}
\ No newline at end of file
using HandBrakeWPF.Commands;\r
using HandBrakeWPF.Helpers;\r
using HandBrakeWPF.Model;\r
+ using HandBrakeWPF.Properties;\r
using HandBrakeWPF.Services.Interfaces;\r
using HandBrakeWPF.ViewModels.Interfaces;\r
using HandBrakeWPF.Views;\r
/// The last percentage complete value.\r
/// </summary>\r
private int lastEncodePercentage;\r
+\r
+ /// <summary>\r
+ /// The is preset panel showing.\r
+ /// </summary>\r
+ private bool isPresetPanelShowing;\r
+\r
#endregion\r
\r
/// <summary>\r
\r
if (this.UserSettingService.GetUserSetting<bool>(UserSettingConstants.AutoNaming))\r
{\r
- if (this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat) != null )\r
+ if (this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat) != null)\r
{\r
this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName);\r
}\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Gets or sets a value indicating whether is preset panel showing.\r
+ /// </summary>\r
+ public bool IsPresetPanelShowing\r
+ {\r
+ get\r
+ {\r
+ return this.isPresetPanelShowing;\r
+ }\r
+ set\r
+ {\r
+ if (!object.Equals(this.isPresetPanelShowing, value))\r
+ {\r
+ this.isPresetPanelShowing = value;\r
+ this.NotifyOfPropertyChange(() => this.IsPresetPanelShowing);\r
+\r
+ // Save the setting if it has changed.\r
+ if (this.userSettingService.GetUserSetting<bool>(UserSettingConstants.ShowPresetPanel) != value)\r
+ {\r
+ this.userSettingService.SetUserSetting(UserSettingConstants.ShowPresetPanel, value);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public int ProgressPercentage { get; set; }\r
+\r
#endregion\r
\r
#region Load and Shutdown Handling\r
// Populate the Source menu with drives.\r
this.SourceMenu = new BindingList<SourceMenuItem>(this.GenerateSourceMenu());\r
\r
+ // Show or Hide the Preset Panel.\r
+ this.IsPresetPanelShowing = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.ShowPresetPanel);\r
+\r
// Log Cleaning\r
if (userSettingService.GetUserSetting<bool>(UserSettingConstants.ClearOldLogs))\r
{\r
this.presetService.UpdateBuiltInPresets();\r
this.NotifyOfPropertyChange("Presets");\r
this.SelectedPreset = this.presetService.DefaultPreset;\r
+ this.errorService.ShowMessageBox(Resources.Presets_ResetComplete, Resources.Presets_ResetHeader, MessageBoxButton.OK, MessageBoxImage.Information);\r
+ }\r
+\r
+ /// <summary>\r
+ /// The preset select.\r
+ /// </summary>\r
+ /// <param name="tag">\r
+ /// The tag.\r
+ /// </param>\r
+ public void PresetSelect(object tag)\r
+ {\r
+ Preset preset = tag as Preset;\r
+ if (preset != null)\r
+ {\r
+ this.SelectedPreset = preset;\r
+ }\r
}\r
\r
/// <summary>\r
}\r
\r
lastEncodePercentage = percent;\r
+ this.ProgressPercentage = percent;\r
+ this.NotifyOfPropertyChange(() => ProgressPercentage);\r
}\r
else\r
{\r
Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/folder.png")), Width = 16, Height = 16 },\r
Text = "Open Folder",\r
Command = new SourceMenuCommand(this.FolderScan),\r
- IsDrive = false\r
+ IsDrive = false,\r
+ InputGestureText = "Ctrl + R"\r
};\r
SourceMenuItem fileScan = new SourceMenuItem\r
{\r
Image = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/HandBrake;component/Views/Images/Movies.png")), Width = 16, Height = 16 },\r
Text = "Open File",\r
Command = new SourceMenuCommand(this.FileScan),\r
- IsDrive = false\r
+ IsDrive = false,\r
+ InputGestureText = "Ctrl + F"\r
};\r
\r
SourceMenuItem titleSpecific = new SourceMenuItem { Text = "Title Specific Scan" };\r
/// </summary>\r
private bool showAdvancedTab;\r
\r
+ /// <summary>\r
+ /// The remove punctuation.\r
+ /// </summary>\r
+ private bool removePunctuation;\r
+\r
+ /// <summary>\r
+ /// The use system colours for styles.\r
+ /// </summary>\r
+ private bool useSystemColoursForStyles;\r
+\r
#endregion\r
\r
#region Constructors and Destructors\r
this.NotifyOfPropertyChange("WhenDoneOptions");\r
}\r
}\r
+\r
+ /// <summary>\r
+ /// Gets or sets a value indicating whether use system colours.\r
+ /// </summary>\r
+ public bool UseSystemColoursForStylesForStyles\r
+ {\r
+ get\r
+ {\r
+ return this.useSystemColoursForStyles;\r
+ }\r
+ set\r
+ {\r
+ this.useSystemColoursForStyles = value;\r
+ this.NotifyOfPropertyChange(() => UseSystemColoursForStylesForStyles);\r
+ }\r
+ }\r
+\r
#endregion\r
\r
#region Output Files\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Gets or sets a value indicating whether remove punctuation.\r
+ /// </summary>\r
+ public bool RemovePunctuation\r
+ {\r
+ get\r
+ {\r
+ return this.removePunctuation;\r
+ }\r
+ set\r
+ {\r
+ this.removePunctuation = value;\r
+ this.NotifyOfPropertyChange(() => RemovePunctuation);\r
+ }\r
+ }\r
+\r
#endregion\r
\r
#region Preview\r
this.SendFileTo = Path.GetFileNameWithoutExtension(this.userSettingService.GetUserSetting<string>(UserSettingConstants.SendFileTo)) ?? string.Empty;\r
this.SendFileToPath = this.userSettingService.GetUserSetting<string>(UserSettingConstants.SendFileTo) ?? string.Empty;\r
this.Arguments = this.userSettingService.GetUserSetting<string>(UserSettingConstants.SendFileToArgs) ?? string.Empty;\r
+ this.UseSystemColoursForStylesForStyles = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.UseSystemColours);\r
\r
// #############################\r
// Output Settings\r
\r
// Title case\r
this.ChangeToTitleCase = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.AutoNameTitleCase);\r
+ this.RemovePunctuation = this.userSettingService.GetUserSetting<bool>(UserSettingConstants.RemovePunctuation);\r
\r
// #############################\r
// Picture Tab\r
this.userSettingService.SetUserSetting(UserSettingConstants.SendFileTo, this.SendFileToPath);\r
this.userSettingService.SetUserSetting(UserSettingConstants.SendFile, this.SendFileAfterEncode);\r
this.userSettingService.SetUserSetting(UserSettingConstants.SendFileToArgs, this.Arguments);\r
+ this.userSettingService.SetUserSetting(UserSettingConstants.UseSystemColours, this.UseSystemColoursForStylesForStyles);\r
\r
/* Output Files */\r
this.userSettingService.SetUserSetting(UserSettingConstants.AutoNaming, this.AutomaticallyNameFiles);\r
this.userSettingService.SetUserSetting(UserSettingConstants.UseM4v, this.SelectedMp4Extension);\r
this.userSettingService.SetUserSetting(UserSettingConstants.AutoNameRemoveUnderscore, this.RemoveUnderscores);\r
this.userSettingService.SetUserSetting(UserSettingConstants.AutoNameTitleCase, this.ChangeToTitleCase);\r
+ this.userSettingService.SetUserSetting(UserSettingConstants.RemovePunctuation, this.RemovePunctuation);\r
\r
/* Previews */\r
this.userSettingService.SetUserSetting(UserSettingConstants.VLC_Path, this.VLCPath);\r
this.MaxHeight = preset.Task.MaxHeight ?? this.sourceResolution.Height;\r
}\r
\r
- // Update the cropping values, preffering those in the presets.\r
- if (!preset.Task.HasCropping)\r
- {\r
- this.CropTop = title.AutoCropDimensions.Top;\r
- this.CropBottom = title.AutoCropDimensions.Bottom;\r
- this.CropLeft = title.AutoCropDimensions.Left;\r
- this.CropRight = title.AutoCropDimensions.Right;\r
- this.IsCustomCrop = false;\r
- }\r
- else\r
- {\r
- this.CropLeft = preset.Task.Cropping.Left;\r
- this.CropRight = preset.Task.Cropping.Right;\r
- this.CropTop = preset.Task.Cropping.Top;\r
- this.CropBottom = preset.Task.Cropping.Bottom;\r
- this.IsCustomCrop = true;\r
- }\r
-\r
// Set the Width, and Maintain Aspect ratio. That should calc the Height for us.\r
this.Width = preset.Task.Width ?? this.MaxWidth; // Note: This will be auto-corrected in the property if it's too large.\r
\r
}\r
}\r
\r
+ // Update the cropping values, preffering those in the presets.\r
+ if (!preset.Task.HasCropping)\r
+ {\r
+ this.CropTop = title.AutoCropDimensions.Top;\r
+ this.CropBottom = title.AutoCropDimensions.Bottom;\r
+ this.CropLeft = title.AutoCropDimensions.Left;\r
+ this.CropRight = title.AutoCropDimensions.Right;\r
+ this.IsCustomCrop = false;\r
+ }\r
+ else\r
+ {\r
+ this.CropLeft = preset.Task.Cropping.Left;\r
+ this.CropRight = preset.Task.Cropping.Right;\r
+ this.CropTop = preset.Task.Cropping.Top;\r
+ this.CropBottom = preset.Task.Cropping.Bottom;\r
+ this.IsCustomCrop = true;\r
+ }\r
+\r
// Set Screen Controls\r
this.SourceInfo = string.Format(\r
"{0}x{1}, Aspect Ratio: {2:0.00}",\r
\r
using HandBrake.ApplicationServices.Services.Interfaces;\r
\r
+ using HandBrakeWPF.Helpers;\r
using HandBrakeWPF.Model;\r
using HandBrakeWPF.Services.Interfaces;\r
using HandBrakeWPF.ViewModels.Interfaces;\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Gets the high quality label.\r
+ /// </summary>\r
+ public string HighQualityLabel\r
+ {\r
+ get\r
+ {\r
+ return this.SelectedVideoEncoder == VideoEncoder.X264 ? Resources.Video_PlaceboQuality : Resources.Video_HigherQuality;\r
+ }\r
+ }\r
+\r
+\r
/// <summary>\r
/// Gets or sets SelectedFramerate.\r
/// </summary>\r
this.DisplayX264Options = value == VideoEncoder.X264;\r
\r
this.NotifyOfPropertyChange(() => this.Rfqp);\r
+ this.NotifyOfPropertyChange(() => this.HighQualityLabel);\r
}\r
}\r
\r
width = 720;\r
}\r
\r
- // TODO figure out what is wrong with this??\r
return HandBrakeUtils.CreateX264OptionsString(preset, tunes, this.ExtraArguments, profile, this.H264Level, width, height);\r
}\r
\r
\r
using HandBrake.ApplicationServices.Services.Interfaces;\r
\r
+ using HandBrakeWPF.Helpers;\r
using HandBrakeWPF.ViewModels.Interfaces;\r
\r
/// <summary>\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Gets a value indicating whether use system colours.\r
+ /// </summary>\r
+ public bool UseSystemColours\r
+ {\r
+ get\r
+ {\r
+ return AppStyleHelper.UseSystemColours;\r
+ }\r
+ }\r
+\r
/// <summary>\r
/// Gets or sets WindowManager.\r
/// </summary>\r
\r
<ListBox Grid.Row="2"\r
Margin="10,10,10,10"\r
- Background="LightGray"\r
dd:DragDrop.DropHandler="{Binding}"\r
dd:DragDrop.IsDragSource="True"\r
dd:DragDrop.IsDropTarget="True"\r
ItemsSource="{Binding Task.AudioTracks}"\r
SelectionMode="Extended">\r
+ <ListBox.Style>\r
+ <Style TargetType="ListBox">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="LightGray" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+ </ListBox.Style>\r
+ \r
<ListBox.ItemContainerStyle>\r
<Style TargetType="ListBoxItem">\r
<Setter Property="HorizontalContentAlignment" Value="Stretch" />\r
- <Setter Property="Background" Value="WhiteSmoke" />\r
<Setter Property="Margin" Value="0,0,0,1" />\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="WhiteSmoke" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
</Style>\r
</ListBox.ItemContainerStyle>\r
\r
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" \r
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:cal="http://www.caliburnproject.org"\r
+ d:DesignHeight="170"\r
+ d:DesignWidth="616"\r
mc:Ignorable="d" >\r
<Grid>\r
<Grid.RowDefinitions>\r
</Grid>\r
\r
<DataGrid Grid.Row="2" Margin="10" ItemsSource="{Binding Task.ChapterNames}" \r
- VerticalAlignment="Stretch" HorizontalAlignment="Stretch" AutoGenerateColumns="False"\r
+ VerticalAlignment="Stretch" AutoGenerateColumns="False"\r
CanUserSortColumns="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False"\r
CanUserAddRows="False" CanUserDeleteRows="False">\r
<DataGrid.CellStyle>\r
xmlns:Micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"\r
xmlns:attachedProperties="clr-namespace:HandBrakeWPF.AttachedProperties"\r
AllowDrop="True"\r
- Background="#FFF0F0F0"\r
FontSize="11"\r
Micro:Message.Attach="[Event Loaded] = [Action Load]"\r
SnapsToDevicePixels="True"\r
</i:EventTrigger>\r
</i:Interaction.Triggers>\r
\r
- <UserControl.Resources>\r
-\r
+ <UserControl.Resources> \r
<Style TargetType="Button">\r
<Setter Property="FontWeight" Value="Bold" />\r
<Setter Property="Padding" Value="5,1" />\r
<Style TargetType="ListBoxItem">\r
<Setter Property="Padding" Value="0,2,0,2" />\r
<Style.Triggers>\r
- <DataTrigger Binding="{Binding IsBuildIn}" Value="True">\r
+ <MultiDataTrigger>\r
+ <MultiDataTrigger.Conditions>\r
+ <Condition Binding="{Binding IsBuildIn}" Value="True" />\r
+ <Condition Binding="{Binding DataContext.UseSystemColours, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Value="False" />\r
+ </MultiDataTrigger.Conditions>\r
<Setter Property="Foreground" Value="DarkBlue" />\r
- </DataTrigger>\r
+ </MultiDataTrigger>\r
+ <!--<DataTrigger Binding="{Binding IsBuildIn}" Value="True">\r
+ <Setter Property="Foreground" Value="DarkBlue" />\r
+ </DataTrigger>-->\r
<Trigger Property="IsSelected" Value="True">\r
<Setter Property="FontWeight" Value="Bold"/>\r
<Setter Property="Background" Value="Transparent"/>\r
HorizontalAlignment="Stretch"\r
VerticalAlignment="Top"\r
>\r
- <MenuItem Header="File">\r
- <MenuItem Header="Cancel Scan" Command="{Binding CancelScanCommand}" />\r
+ <MenuItem Header="_File">\r
+ <MenuItem Header="_Cancel Scan" Command="{Binding CancelScanCommand}" />\r
<Separator />\r
- <MenuItem Header="Exit" Micro:Message.Attach="[Event Click] = [Action ExitApplication]" />\r
+ <MenuItem Header="_Exit" Micro:Message.Attach="[Event Click] = [Action ExitApplication]" InputGestureText="Alt + F4" />\r
</MenuItem>\r
\r
- <MenuItem Header="Tools">\r
- <MenuItem Header="Show Queue" Micro:Message.Attach="[Event Click] = [Action OpenQueueWindow]">\r
+ <MenuItem Header="_Tools">\r
+ <MenuItem Header="_Show Queue" Micro:Message.Attach="[Event Click] = [Action OpenQueueWindow]" InputGestureText="Ctrl + Q">\r
<MenuItem.Icon>\r
<Image Width="16" Source="Images/Queue_Small.png" />\r
</MenuItem.Icon>\r
</MenuItem>\r
- <MenuItem Header="Activity Log" Micro:Message.Attach="[Event Click] = [Action OpenLogWindow]">\r
+ <MenuItem Header="_Activity Log" Micro:Message.Attach="[Event Click] = [Action OpenLogWindow]" InputGestureText="Ctrl + L">\r
<MenuItem.Icon>\r
<Image Width="16" Source="Images/Output_Small.png" />\r
</MenuItem.Icon>\r
</MenuItem>\r
<Separator />\r
- <MenuItem Header="Options" Micro:Message.Attach="[Event Click] = [Action OpenOptionsWindow]">\r
+ <MenuItem Header="_Options" Micro:Message.Attach="[Event Click] = [Action OpenOptionsWindow]">\r
<MenuItem.Icon>\r
<Image Width="16" Source="Images/Pref_Small.png" />\r
</MenuItem.Icon>\r
</MenuItem>\r
</MenuItem>\r
\r
- <MenuItem Header="Help">\r
- <MenuItem Header="HandBrake User Guide (HTTP)" Micro:Message.Attach="[Event Click] = [Action LaunchHelp]">\r
+\r
+ <MenuItem Header="_Presets" x:Name="presetMenu">\r
+ <MenuItem Header="_Presets" ItemsSource="{Binding Presets}">\r
+ <MenuItem.ItemContainerStyle>\r
+ <Style TargetType="MenuItem">\r
+ <Setter Property="Tag" Value="{Binding}" />\r
+ <Setter Property="Micro:Action.TargetWithoutContext" Value="{Binding DataContext, ElementName=presetMenu}"/>\r
+ <Setter Property="Micro:Message.Attach" Value="[Event Click] = [Action PresetSelect($this.Tag)]"/>\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding IsDefault}" Value="True">\r
+ <Setter Property="FontStyle" Value="Italic" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+ </MenuItem.ItemContainerStyle>\r
+ </MenuItem>\r
+ <Separator />\r
+ <MenuItem Header="_Import" Micro:Message.Attach="[Event Click] = [Action PresetImport]" />\r
+ <MenuItem Header="_Export" Micro:Message.Attach="[Event Click] = [Action PresetExport]" />\r
+ <Separator />\r
+ <MenuItem Header="_Set Current as Default" Micro:Message.Attach="[Event Click] = [Action PresetSetDefault]" />\r
+ <MenuItem Header="_Reset Built-In Presets" Micro:Message.Attach="[Event Click] = [Action PresetReset]" />\r
+ <Separator />\r
+ <MenuItem IsCheckable="True" x:Name="showPresetPanelMenuItem" IsChecked="{Binding IsPresetPanelShowing}">\r
+ <MenuItem.Style>\r
+ <Style TargetType="MenuItem">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding IsChecked, ElementName=showPresetPanelMenuItem}" Value="True">\r
+ <Setter Property="Header" Value="_Hide Preset Panel"/>\r
+ </DataTrigger>\r
+ <DataTrigger Binding="{Binding IsChecked, ElementName=showPresetPanelMenuItem}" Value="False">\r
+ <Setter Property="Header" Value="S_how Preset Panel"/>\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+ </MenuItem.Style>\r
+ </MenuItem>\r
+ </MenuItem>\r
+\r
+ <MenuItem Header="_Help">\r
+ <MenuItem Header="_HandBrake User Guide (HTTP)" Micro:Message.Attach="[Event Click] = [Action LaunchHelp]">\r
<MenuItem.Icon>\r
<Image Width="16" Height="16" Source="Images/information.png" />\r
</MenuItem.Icon>\r
</MenuItem>\r
<Separator />\r
- <MenuItem Header="Check for Updates" Micro:Message.Attach="[Event Click] = [Action CheckForUpdates]" />\r
+ <MenuItem Header="_Check for Updates" Micro:Message.Attach="[Event Click] = [Action CheckForUpdates]" />\r
<Separator />\r
- <MenuItem Header="About..." Micro:Message.Attach="[Event Click] = [Action OpenAboutApplication]" />\r
+ <MenuItem Header="_About..." Micro:Message.Attach="[Event Click] = [Action OpenAboutApplication]" />\r
</MenuItem>\r
\r
- <MenuItem Header="Debug" Visibility="{Binding ShowDebugMenu, Converter={StaticResource boolToVisConverter}}" >\r
- <MenuItem Header="Show CLI Equiv" Micro:Message.Attach="[Event Click] = [Action ShowCliQuery]" />\r
- <MenuItem Header="Debug Scan Log" Micro:Message.Attach="[Event Click] = [Action DebugScanLog]" />\r
+ <MenuItem Header="_Debug" Visibility="{Binding ShowDebugMenu, Converter={StaticResource boolToVisConverter}}" >\r
+ <MenuItem Header="_Show CLI Equiv" Micro:Message.Attach="[Event Click] = [Action ShowCliQuery]" />\r
+ <MenuItem Header="_Debug Scan Log" Micro:Message.Attach="[Event Click] = [Action DebugScanLog]" />\r
</MenuItem>\r
</Menu>\r
\r
<Setter Property="MenuItem.CommandParameter" Value="123"/>\r
<Setter Property="ItemsSource" Value="{Binding Children}" />\r
<Setter Property="Icon" Value="{Binding Image}" />\r
+ <Setter Property="InputGestureText" Value="{Binding InputGestureText}" />\r
</Style>\r
</MenuItem.ItemContainerStyle>\r
</MenuItem>\r
<!-- Main Body -->\r
<Grid Grid.Row="1">\r
<Grid.ColumnDefinitions>\r
- <ColumnDefinition Width="*" />\r
- <ColumnDefinition Width="270" />\r
+ <ColumnDefinition Width="*" MinWidth="700"/>\r
+ <ColumnDefinition Width="Auto" />\r
</Grid.ColumnDefinitions>\r
<Grid.RowDefinitions>\r
<RowDefinition Height="Auto" />\r
Converter={StaticResource boolToVisConverter},\r
ConverterParameter=false}"\r
/>\r
- \r
+\r
<Label Margin="8,0,0,0" Content="through" />\r
<ComboBox Name="EndPoint"\r
MinWidth="60"\r
Converter={StaticResource boolToVisConverter},\r
ConverterParameter=false}"\r
/>\r
- \r
+\r
<Label Margin="8,0,0,0" Content="Duration" />\r
<Label Margin="8,0,0,0" Content="{Binding Duration}" />\r
</StackPanel>\r
VerticalAlignment="Stretch"\r
Header="Presets"\r
Margin="0,0,0,5"\r
- Background="White"\r
- >\r
+ Visibility="{Binding IsPresetPanelShowing, Converter={StaticResource boolToVisConverter}}">\r
+ \r
<Grid>\r
<Grid.RowDefinitions>\r
<RowDefinition Height="*" />\r
/>\r
\r
<!-- Status Bar -->\r
- <StatusBar Grid.Row="2"\r
- Grid.ColumnSpan="2"\r
- Height="32"\r
- Margin="0"\r
- VerticalAlignment="Bottom"\r
- Padding="0"\r
- >\r
+ <StatusBar Grid.Row="2" Grid.ColumnSpan="2" MinHeight="32" >\r
+\r
+ <ProgressBar Value="{Binding ProgressPercentage}" Visibility="{Binding IsEncoding, Converter={StaticResource boolToVisConverter}}"\r
+ Width="100" Height="18" VerticalAlignment="Center"/>\r
<Label VerticalAlignment="Center"\r
- Content="{Binding Path=ProgramStatusLabel}"\r
- FontSize="11"\r
- Padding="0,0,0,5"\r
- />\r
+ Content="{Binding Path=ProgramStatusLabel}" />\r
\r
</StatusBar>\r
</Grid>\r
xmlns:Options="clr-namespace:HandBrakeWPF.Converters.Options"\r
xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"\r
xmlns:Converters="clr-namespace:HandBrakeWPF.Converters" xmlns:local="clr-namespace:HandBrakeWPF.Model"\r
- Background="White">\r
+ Style="{StaticResource whiteUserControlStyle}">\r
\r
<UserControl.Resources>\r
<Style TargetType="Button">\r
\r
</StackPanel>\r
</StackPanel>\r
+\r
+\r
+ <StackPanel Orientation="Vertical" Margin="0,0,0,20">\r
+\r
+ <TextBlock Text="User Interface" Grid.Column="0" FontSize="14" Margin="0,0,0,10"/>\r
+\r
+ <StackPanel Orientation="Vertical" Grid.Column="1" Margin="20,0,0,0">\r
+\r
+ <CheckBox Content="Always use System Colours (Requires Restart)"\r
+ ToolTip="Note: This option will always be on for systems with a High Contrast Theme selected." IsChecked="{Binding UseSystemColoursForStylesForStyles}" />\r
+\r
+ </StackPanel>\r
+ </StackPanel>\r
</StackPanel>\r
\r
<StackPanel Name="Output" Orientation="Vertical" Margin="10,10,0,0"\r
<TextBlock Text="Available Options: {source} {title} {chapters} {date}" />\r
\r
<StackPanel Orientation="Horizontal" Margin="0,15,0,0">\r
- <CheckBox Content="Remove underscores from name" IsChecked="{Binding RemoveUnderscores}"/>\r
+ <CheckBox Content="Replace underscores with a space" IsChecked="{Binding RemoveUnderscores}"/>\r
+ <CheckBox Content="Remove common punctuation" ToolTip="Dash (-), Period (.) and Comma (,) " IsChecked="{Binding RemovePunctuation}" Margin="5,0,0,0"/>\r
<CheckBox Content="Change case to Title Case" IsChecked="{Binding ChangeToTitleCase}" Margin="5,0,0,0" />\r
</StackPanel>\r
\r
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"\r
xmlns:Data="clr-namespace:System.Windows.Data;assembly=PresentationFramework"\r
- xmlns:Converters="clr-namespace:HandBrakeWPF.Converters" Title="{Data:Binding Path=WindowTitle}"\r
+ xmlns:Converters="clr-namespace:HandBrakeWPF.Converters"\r
+ Title="{Data:Binding Path=WindowTitle}"\r
Width="1015"\r
- Height="680"\r
- MinWidth="1015"\r
+ Height="670"\r
+ MinWidth="750"\r
MinHeight="670"\r
AllowDrop="True"\r
- Background="#FFF0F0F0"\r
- FontSize="11"\r
SnapsToDevicePixels="True"\r
UseLayoutRounding="True"\r
WindowStartupLocation="CenterScreen"\r
TextOptions.TextFormattingMode="Display"\r
+ Style="{StaticResource mainWindowStyle}"\r
>\r
<Window.Resources>\r
<Converters:BooleanToVisibilityConverter x:Key="boolToVisConverter" />\r
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"\r
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">\r
\r
+ <Style x:Key="mainWindowStyle" TargetType="Window">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="#FFF0F0F0" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+\r
+ <Style x:Key="whiteUserControlStyle" TargetType="UserControl">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="White" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+\r
<Style x:Key="{x:Type StatusBar}" TargetType="{x:Type StatusBar}">\r
<Setter Property="SnapsToDevicePixels" Value="True"/>\r
<Setter Property="Template">\r
<Setter.Value>\r
<ControlTemplate TargetType="{x:Type StatusBar}">\r
- <Border Background="#FAFAFA" Padding="1">\r
+ <Border Padding="1">\r
+ <Border.Style>\r
+ <Style TargetType="Border">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="#FAFAFA" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+ </Border.Style>\r
<ItemsPresenter Margin="0" />\r
</Border>\r
</ControlTemplate>\r
</Setter>\r
</Style>\r
\r
+ <Style TargetType="{x:Type GroupBox}">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="White" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+\r
<Style TargetType="{x:Type ComboBox}">\r
<Setter Property="MinHeight" Value="22"/>\r
<Setter Property="Margin" Value="0,2,0,2" />\r
\r
<ListBox Grid.Row="2"\r
Margin="10,10,10,10"\r
- Background="LightGray"\r
dd:DragDrop.DropHandler="{Binding}"\r
dd:DragDrop.IsDragSource="True"\r
dd:DragDrop.IsDropTarget="True"\r
ItemsSource="{Binding Task.SubtitleTracks}"\r
SelectionMode="Extended">\r
+ <ListBox.Style>\r
+ <Style TargetType="ListBox">\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="LightGray" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
+ </Style>\r
+ </ListBox.Style>\r
+ \r
<ListBox.ItemContainerStyle>\r
<Style TargetType="ListBoxItem">\r
<Setter Property="HorizontalContentAlignment" Value="Stretch" />\r
- <Setter Property="Background" Value="WhiteSmoke" />\r
<Setter Property="Margin" Value="0,0,0,1" />\r
+ <Style.Triggers>\r
+ <DataTrigger Binding="{Binding UseSystemColours}" Value="False">\r
+ <Setter Property="Background" Value="WhiteSmoke" />\r
+ </DataTrigger>\r
+ </Style.Triggers>\r
</Style>\r
</ListBox.ItemContainerStyle>\r
\r
<Converters:EnumComboConverter x:Key="enumComboConverter" />\r
<Converters:InverseBooleanConverter x:Key="inverseConverter" />\r
<Video:VideoEncoderConverter x:Key="videoEncoderConverter" />\r
- \r
+\r
<Style x:Key="LongToolTipHolder" TargetType="FrameworkElement">\r
<Setter Property="ToolTipService.ShowDuration" Value="20000" />\r
</Style>\r
</Setter>\r
</Style>\r
</UserControl.Resources>\r
- \r
+\r
<Grid Margin="10,5,0,0">\r
<Grid.RowDefinitions>\r
<RowDefinition Height="Auto" />\r
<ColumnDefinition Width="*" />\r
<ColumnDefinition Width="*" />\r
</Grid.ColumnDefinitions>\r
- \r
+\r
<Grid.RowDefinitions>\r
<RowDefinition Height="Auto" />\r
<RowDefinition Height="Auto" />\r
</MultiBinding>\r
</ComboBox.ItemsSource>\r
</ComboBox>\r
- \r
+\r
</StackPanel>\r
\r
<StackPanel Orientation="Horizontal">\r
</StackPanel>\r
\r
\r
- <StackPanel Orientation="Vertical" Grid.Column="1" >\r
+ <StackPanel Orientation="Vertical" Grid.Column="1" Grid.RowSpan="2">\r
<TextBlock Text="Quality" FontWeight="Bold" Margin="0,0,0,10"/>\r
\r
<StackPanel Orientation="Horizontal" Margin="0,0,0,10" >\r
</StackPanel>\r
\r
<Slider Width="280" Value="{Binding RF}" HorizontalAlignment="Left" Maximum="{Binding QualityMax}" Minimum="{Binding QualityMin}"\r
- IsEnabled="{Binding IsConstantQuantity}" Margin="20,0,0,20"\r
+ IsEnabled="{Binding IsConstantQuantity}" Margin="20,0,0,10"\r
ToolTip="{x:Static Properties:Resources.Video_QualitySlider}" Style="{StaticResource LongToolTipHolder}" \r
IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight" />\r
\r
+ <Grid Margin="20,0,0,20" Width="280" HorizontalAlignment="Left">\r
+ <Grid.ColumnDefinitions>\r
+ <ColumnDefinition Width="Auto" />\r
+ <ColumnDefinition Width="*" />\r
+ </Grid.ColumnDefinitions>\r
+ <TextBlock Text="{x:Static Properties:Resources.Video_LowQuality}" />\r
+ <TextBlock Text="{Binding HighQualityLabel}" HorizontalAlignment="Right" Grid.Column="1" />\r
+ </Grid>\r
+\r
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">\r
<RadioButton Content="Avg Bitrate (kbps):" IsChecked="{Binding IsConstantQuantity, Converter={StaticResource boolConverter}, ConverterParameter=true}" Margin="0,0,10,0"/>\r
<TextBox Width="75" Text="{Binding Task.VideoBitrate, UpdateSourceTrigger=PropertyChanged}" \r
\r
</Grid>\r
</Grid>\r
- \r
- \r
+\r
+\r
</Grid>\r
\r
</Grid>\r
<anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" d4p1:type="q1:boolean" xmlns:d4p1="http://www.w3.org/2001/XMLSchema-instance">false</anyType>\r
</value>\r
</item>\r
+ <item>\r
+ <key>\r
+ <string>RemovePunctuation</string>\r
+ </key>\r
+ <value>\r
+ <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" d4p1:type="q1:boolean" xmlns:d4p1="http://www.w3.org/2001/XMLSchema-instance">false</anyType>\r
+ </value>\r
+ </item>\r
+ <item>\r
+ <key>\r
+ <string>ShowPresetPanel</string>\r
+ </key>\r
+ <value>\r
+ <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" d4p1:type="q1:boolean" xmlns:d4p1="http://www.w3.org/2001/XMLSchema-instance">true</anyType>\r
+ </value>\r
+ </item>\r
+ <item>\r
+ <key>\r
+ <string>UseSystemColours</string>\r
+ </key>\r
+ <value>\r
+ <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" d4p1:type="q1:boolean" xmlns:d4p1="http://www.w3.org/2001/XMLSchema-instance">false</anyType>\r
+ </value>\r
+ </item>\r
</dictionary>
\ No newline at end of file