summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/audiohandler.c42
-rw-r--r--gtk/src/hb-backend.c1029
-rw-r--r--gtk/src/hb-backend.h4
-rw-r--r--gtk/src/presets.c126
-rw-r--r--libhb/common.c1850
-rw-r--r--libhb/common.h210
-rw-r--r--libhb/encavcodec.c8
-rw-r--r--libhb/scan.c7
-rw-r--r--libhb/work.c205
-rw-r--r--macosx/Controller.m360
-rw-r--r--macosx/HBAudio.m134
-rw-r--r--macosx/HBAudioController.m64
-rw-r--r--macosx/HBPreviewController.m4
-rw-r--r--macosx/HBSubtitles.m2
-rwxr-xr-xscripts/manicure.rb22
-rw-r--r--test/test.c440
16 files changed, 2631 insertions, 1876 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c
index 2a7b619e4..72f58bfa7 100644
--- a/gtk/src/audiohandler.c
+++ b/gtk/src/audiohandler.c
@@ -63,12 +63,13 @@ ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint f
return hb_autopassthru_get_encoder(in_codec, copy_mask, fallback, mux);
}
- gint ii;
// Sanitize fallback
- for (ii = 0; ii < hb_audio_encoders_count; ii++)
+ const hb_encoder_t *enc;
+ for (enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ enc = hb_audio_encoder_get_next(enc))
{
- if (hb_audio_encoders[ii].encoder == fallback &&
- !(hb_audio_encoders[ii].muxers & mux))
+ if (enc->codec == fallback &&
+ !(enc->muxers & mux))
{
if ( mux == HB_MUX_MKV )
fallback = HB_ACODEC_LAME;
@@ -82,10 +83,11 @@ ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint f
{
return fallback;
}
- for (ii = 0; ii < hb_audio_encoders_count; ii++)
+ for (enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ enc = hb_audio_encoder_get_next(enc))
{
- if (hb_audio_encoders[ii].encoder == acodec &&
- !(hb_audio_encoders[ii].muxers & mux))
+ if (enc->codec == acodec &&
+ !(enc->muxers & mux))
{
return fallback;
}
@@ -198,7 +200,7 @@ ghb_sanitize_audio(GValue *settings, GValue *asettings)
{
if (mix == 0)
mix = ghb_get_best_mix( aconfig, select_acodec, 0);
- bitrate = hb_get_best_audio_bitrate(select_acodec, bitrate, sr, mix);
+ bitrate = hb_audio_bitrate_get_best(select_acodec, bitrate, sr, mix);
ghb_settings_set_string(asettings, "AudioMixdown",
ghb_lookup_combo_string("AudioMixdown", ghb_int_value(mix)));
}
@@ -206,7 +208,7 @@ ghb_sanitize_audio(GValue *settings, GValue *asettings)
ghb_lookup_combo_string("AudioBitrate", ghb_int_value(bitrate)));
ghb_settings_take_value(asettings, "AudioEncoderActual",
- ghb_lookup_acodec_value(select_acodec));
+ ghb_lookup_audio_encoder_value(select_acodec));
}
void
@@ -283,25 +285,25 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
{
if (mix == 0)
mix = ghb_get_best_mix( aconfig, select_acodec, 0);
- bitrate = hb_get_best_audio_bitrate(select_acodec, bitrate, sr, mix);
+ bitrate = hb_audio_bitrate_get_best(select_acodec, bitrate, sr, mix);
ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix));
}
if (!codec_defined_bitrate)
{
int low, high;
mix = ghb_get_best_mix( aconfig, select_acodec, mix);
- hb_get_audio_bitrate_limits(select_acodec, sr, mix, &low, &high);
+ hb_audio_bitrate_get_limits(select_acodec, sr, mix, &low, &high);
ghb_set_bitrate_opts (ud->builder, low, high, -1);
}
ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(bitrate));
ghb_settings_take_value(ud->settings, "AudioEncoderActual",
- ghb_lookup_acodec_value(select_acodec));
+ ghb_lookup_audio_encoder_value(select_acodec));
GValue *asettings = get_selected_asettings(ud);
if (asettings)
{
ghb_settings_take_value(asettings, "AudioEncoderActual",
- ghb_lookup_acodec_value(select_acodec));
+ ghb_lookup_audio_encoder_value(select_acodec));
}
ghb_audio_list_refresh_selected(ud);
ghb_check_dependency(ud, NULL, "AudioEncoderActual");
@@ -423,7 +425,7 @@ ghb_set_pref_audio_settings(gint titleindex, GValue *settings)
ghb_settings_set_string(asettings, "AudioEncoder",
ghb_lookup_combo_string("AudioEncoder", ghb_int_value(acodec)));
ghb_settings_set_value(asettings, "AudioEncoderActual",
- ghb_lookup_acodec_value(select_acodec));
+ ghb_lookup_audio_encoder_value(select_acodec));
ghb_settings_set_value(asettings, "AudioTrackQualityEnable", enable_qual);
ghb_settings_set_double(asettings, "AudioTrackQuality", quality);
@@ -687,7 +689,7 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
track = ghb_settings_combo_int(ud->settings, "AudioTrack");
if (sr)
{
- sr = ghb_find_closest_audio_rate(sr);
+ sr = ghb_find_closest_audio_samplerate(sr);
}
ghb_ui_update(ud, "AudioSamplerate", ghb_int64_value(sr));
@@ -698,7 +700,7 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
sr = aconfig ? aconfig->in.samplerate : 48000;
}
mix_code = ghb_get_best_mix( aconfig, acodec_code, mix_code);
- br = hb_get_best_audio_bitrate(acodec_code, br, sr, mix_code);
+ br = hb_audio_bitrate_get_best(acodec_code, br, sr, mix_code);
ghb_ui_update(ud, "AudioBitrate", ghb_int64_value(br));
ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix_code));
@@ -717,8 +719,8 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
float low, high, gran, defval;
int dir;
- hb_get_audio_quality_limits(acodec_code, &low, &high, &gran, &dir);
- defval = hb_get_default_audio_quality(acodec_code);
+ hb_audio_quality_get_limits(acodec_code, &low, &high, &gran, &dir);
+ defval = hb_audio_quality_get_default(acodec_code);
GtkScaleButton *sb;
GtkAdjustment *adj;
sb = GTK_SCALE_BUTTON(GHB_WIDGET(ud->builder, "AudioTrackQuality"));
@@ -843,7 +845,7 @@ char * ghb_format_quality( const char *prefix, int codec, double quality )
{
float low, high, gran;
int dir;
- hb_get_audio_quality_limits(codec, &low, &high, &gran, &dir);
+ hb_audio_quality_get_limits(codec, &low, &high, &gran, &dir);
int digits = 0;
float tmp = gran;
@@ -868,7 +870,7 @@ quality_widget_changed_cb(GtkWidget *widget, gdouble quality, signal_user_data_t
float low, high, gran;
int dir;
int codec = ghb_settings_combo_int(ud->settings, "AudioEncoderActual");
- hb_get_audio_quality_limits(codec, &low, &high, &gran, &dir);
+ hb_audio_quality_get_limits(codec, &low, &high, &gran, &dir);
if (dir)
{
// Quality values are inverted
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c
index 689c3b7e0..b3f82067c 100644
--- a/gtk/src/hb-backend.c
+++ b/gtk/src/hb-backend.c
@@ -173,17 +173,6 @@ combo_opts_t vqual_granularity_opts =
d_vqual_granularity_opts
};
-static options_map_t d_container_opts[] =
-{
- {"MKV", "mkv", HB_MUX_MKV, "mkv"},
- {"MP4", "mp4", HB_MUX_MP4, "mp4"},
-};
-combo_opts_t container_opts =
-{
- sizeof(d_container_opts)/sizeof(options_map_t),
- d_container_opts
-};
-
static options_map_t d_detel_opts[] =
{
{"Off", "off", 0, ""},
@@ -383,7 +372,6 @@ combo_name_map_t combo_name_map[] =
{"LogLongevity", &log_longevity_opts},
{"check_updates", &appcast_update_opts},
{"VideoQualityGranularity", &vqual_granularity_opts},
- {"FileFormat", &container_opts},
{"PictureDeinterlace", &deint_opts},
{"PictureDecomb", &decomb_opts},
{"PictureDetelecine", &detel_opts},
@@ -842,529 +830,532 @@ lookup_generic_option(combo_opts_t *opts, const GValue *gval)
return result;
}
-static gint
-lookup_mix_int(const GValue *mix)
+static const hb_mixdown_t *
+lookup_mixdown_by_int(int imix)
{
- gint ii;
- gint result = 0;
-
-
- if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
+ const hb_mixdown_t *mix;
+ for (mix = hb_mixdown_get_next(NULL); mix != NULL;
+ mix = hb_mixdown_get_next(mix))
{
- gchar * str = ghb_value_string(mix);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+ if (mix->amixdown == imix)
{
- if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
- {
- result = hb_audio_mixdowns[ii].amixdown;
- break;
- }
- }
- g_free(str);
- }
- else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
- G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
- G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
- {
- gint val = ghb_value_int(mix);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
- {
- if (hb_audio_mixdowns[ii].amixdown == val)
- {
- result = hb_audio_mixdowns[ii].amixdown;
- break;
- }
+ return mix;
}
}
- return result;
+ return NULL;
}
-static const gchar*
-lookup_mix_option(const GValue *mix)
+static const hb_mixdown_t *
+lookup_mixdown(const GValue *gmix)
{
- gint ii;
- const gchar *result = "None";
+ const hb_mixdown_t *mix;
-
- if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
+ if (G_VALUE_TYPE(gmix) == G_TYPE_STRING)
{
- gchar *str = ghb_value_string(mix);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+ gchar * str = ghb_value_string(gmix);
+ for (mix = hb_mixdown_get_next(NULL); mix != NULL;
+ mix = hb_mixdown_get_next(mix))
{
- if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
+ if (strcmp(mix->short_name, str) == 0)
{
- result = hb_audio_mixdowns[ii].human_readable_name;
- break;
+ g_free(str);
+ return mix;
}
}
g_free(str);
}
- else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
- G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
- G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
+ else if (G_VALUE_TYPE(gmix) == G_TYPE_INT ||
+ G_VALUE_TYPE(gmix) == G_TYPE_INT64 ||
+ G_VALUE_TYPE(gmix) == G_TYPE_DOUBLE)
{
- gint val = ghb_value_int(mix);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
- {
- if (hb_audio_mixdowns[ii].amixdown == val)
- {
- result = hb_audio_mixdowns[ii].human_readable_name;
- break;
- }
- }
+ return lookup_mixdown_by_int(ghb_value_int(gmix));
}
- return result;
+ return NULL;
}
-static const gchar*
-lookup_mix_string(const GValue *mix)
+static gint
+lookup_mixdown_int(const GValue *gmix)
{
- gint ii;
- const gchar *result = "none";
+ const hb_mixdown_t *mix = lookup_mixdown(gmix);
+ if (mix != NULL)
+ return mix->amixdown;
+ return 0;
+}
+static const gchar*
+lookup_mixdown_option(const GValue *gmix)
+{
+ const hb_mixdown_t *mix = lookup_mixdown(gmix);
+ if (mix != NULL)
+ return mix->name;
+ return "None";
+}
- if (G_VALUE_TYPE(mix) == G_TYPE_STRING)
- {
- gchar *str = ghb_value_string(mix);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
- {
- if (strcmp(hb_audio_mixdowns[ii].short_name, str) == 0)
- {
- result = hb_audio_mixdowns[ii].short_name;
- break;
- }
- }
- g_free(str);
- }
- else if (G_VALUE_TYPE(mix) == G_TYPE_INT ||
- G_VALUE_TYPE(mix) == G_TYPE_INT64 ||
- G_VALUE_TYPE(mix) == G_TYPE_DOUBLE)
- {
- gint val = ghb_value_int(mix);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
- {
- if (hb_audio_mixdowns[ii].amixdown == val)
- {
- result = hb_audio_mixdowns[ii].short_name;
- break;
- }
- }
- }
- return result;
+static const gchar*
+lookup_mixdown_string(const GValue *gmix)
+{
+ const hb_mixdown_t *mix = lookup_mixdown(gmix);
+ if (mix != NULL)
+ return mix->short_name;
+ return "none";
}
-static gint
-lookup_video_rate_int(const GValue *vrate)
+static const hb_rate_t *
+lookup_video_framerate(const GValue *grate)
{
- gint ii;
gchar *str;
- gint result = 0;
+ const hb_rate_t *rate;
- str = ghb_value_string(vrate);
- for (ii = 0; ii < hb_video_rates_count; ii++)
+ str = ghb_value_string(grate);
+ for (rate = hb_video_framerate_get_next(NULL); rate != NULL;
+ rate = hb_video_framerate_get_next(rate))
{
- if (strcmp(hb_video_rates[ii].string, str) == 0)
+ if (strcmp(rate->name, str) == 0)
{
- result = hb_video_rates[ii].rate;
- break;
+ g_free(str);
+ return rate;
}
}
g_free(str);
// Default to "same as source"
- return result;
+ return NULL;
}
-static const gchar*
-lookup_video_rate_option(const GValue *vrate)
+static gint
+lookup_video_framerate_int(const GValue *grate)
{
- gint ii;
- gchar *str;
- const gchar *result = "Same as source";
+ const hb_rate_t *rate = lookup_video_framerate(grate);
+ if (rate != NULL)
+ return rate->rate;
+ return 0;
+}
- str = ghb_value_string(vrate);
- for (ii = 0; ii < hb_video_rates_count; ii++)
- {
- if (strcmp(hb_video_rates[ii].string, str) == 0)
- {
- result = hb_video_rates[ii].string;
- break;
- }
- }
- g_free(str);
- // Default to "same as source"
- return result;
+static const gchar*
+lookup_video_framerate_option(const GValue *grate)
+{
+ const hb_rate_t *rate = lookup_video_framerate(grate);
+ if (rate != NULL)
+ return rate->name;
+ return "Same as source";
}
-static gint
-lookup_audio_rate_int(const GValue *rate)
+static const hb_rate_t *
+lookup_audio_samplerate(const GValue *grate)
{
- gint ii;
- gint result = 0;
+ const hb_rate_t *rate;
- if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
+ if (G_VALUE_TYPE(grate) == G_TYPE_STRING)
{
// Coincidentally, the string "source" will return 0
// which is our flag to use "same as source"
- gchar * str = ghb_value_string(rate);
- for (ii = 0; ii < hb_audio_rates_count; ii++)
+ gchar * str = ghb_value_string(grate);
+ for (rate = hb_audio_samplerate_get_next(NULL); rate != NULL;
+ rate = hb_audio_samplerate_get_next(rate))
{
- if (strcmp(hb_audio_rates[ii].string, str) == 0)
+ if (strcmp(rate->name, str) == 0)
{
- result = hb_audio_rates[ii].rate;
- break;
+ g_free(str);
+ return rate;
}
}
g_free(str);
}
- else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
- G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
- G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+ else if (G_VALUE_TYPE(grate) == G_TYPE_INT ||
+ G_VALUE_TYPE(grate) == G_TYPE_INT64 ||
+ G_VALUE_TYPE(grate) == G_TYPE_DOUBLE)
{
- for (ii = 0; ii < hb_audio_rates_count; ii++)
+ gint val = ghb_value_int(grate);
+ for (rate = hb_audio_samplerate_get_next(NULL); rate != NULL;
+ rate = hb_audio_samplerate_get_next(rate))
{
- gint val = ghb_value_int(rate);
- if (val == hb_audio_rates[ii].rate)
+ if (val == rate->rate)
{
- result = hb_audio_rates[ii].rate;
- break;
+ return rate;
}
}
}
- return result;
+ return NULL;
+}
+
+static gint
+lookup_audio_samplerate_int(const GValue *grate)
+{
+ const hb_rate_t *rate = lookup_audio_samplerate(grate);
+ if (rate != NULL)
+ return rate->rate;
+ return 0;
}
static const gchar*
-lookup_audio_rate(const GValue *rate, const char *def)
+lookup_audio_samplerate_def(const GValue *grate, const char *def)
{
- gint ii;
const gchar *result = def;
-
- if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
- {
- // Coincidentally, the string "source" will return 0
- // which is our flag to use "same as source"
- gchar *str = ghb_value_string(rate);
- for (ii = 0; ii < hb_audio_rates_count; ii++)
- {
- if (strcmp(hb_audio_rates[ii].string, str) == 0)
- {
- result = hb_audio_rates[ii].string;
- break;
- }
- }
- g_free(str);
- }
- else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
- G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
- G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
- {
- for (ii = 0; ii < hb_audio_rates_count; ii++)
- {
- gint val = ghb_value_int(rate);
- if (val == hb_audio_rates[ii].rate)
- {
- result = hb_audio_rates[ii].string;
- break;
- }
- }
- }
+ const hb_rate_t *rate = lookup_audio_samplerate(grate);
+ if (rate != NULL)
+ return rate->name;
return result;
}
static const gchar*
-lookup_audio_rate_option(const GValue *rate)
+lookup_audio_samplerate_option(const GValue *grate)
{
- return lookup_audio_rate(rate, "Same as Source");
+ return lookup_audio_samplerate_def(grate, "Same as Source");
}
static const gchar*
-lookup_audio_rate_string(const GValue *rate)
+lookup_audio_samplerate_string(const GValue *grate)
{
- return lookup_audio_rate(rate, "source");
+ return lookup_audio_samplerate_def(grate, "source");
}
gint
-ghb_find_closest_audio_rate(gint rate)
+ghb_find_closest_audio_samplerate(gint irate)
{
- gint ii;
gint result;
+ const hb_rate_t *rate;
result = 0;
- for (ii = 0; ii < hb_audio_rates_count; ii++)
+ for (rate = hb_audio_samplerate_get_next(NULL); rate != NULL;
+ rate = hb_audio_samplerate_get_next(rate))
{
- if (rate <= hb_audio_rates[ii].rate)
+ if (irate <= rate->rate)
{
- result = hb_audio_rates[ii].rate;
+ result = rate->rate;
break;
}
}
return result;
}
-hb_rate_t *ghb_audio_bitrates;
-int ghb_audio_bitrates_count;
+hb_rate_t *ghb_audio_bitrates = NULL;
+int ghb_audio_bitrates_count = 0;
+int ghb_abr_count = 0;
-static gint
-lookup_audio_bitrate_int(const GValue *rate)
+static const hb_rate_t *
+lookup_audio_bitrate(const GValue *grate)
{
gint ii;
- gint result = 160;
+ const hb_rate_t *result = NULL;
- if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
+ if (G_VALUE_TYPE(grate) == G_TYPE_STRING)
{
// Coincidentally, the string "source" will return 0
// which is our flag to use "same as source"
- gchar *str = ghb_value_string(rate);
+ gchar *str = ghb_value_string(grate);
for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
{
- if (strcmp(ghb_audio_bitrates[ii].string, str) == 0)
+ if (strcmp(ghb_audio_bitrates[ii].name, str) == 0)
{
- result = ghb_audio_bitrates[ii].rate;
- break;
+ g_free(str);
+ return &ghb_audio_bitrates[ii];
}
}
g_free(str);
}
- else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
- G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
- G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+ else if (G_VALUE_TYPE(grate) == G_TYPE_INT ||
+ G_VALUE_TYPE(grate) == G_TYPE_INT64 ||
+ G_VALUE_TYPE(grate) == G_TYPE_DOUBLE)
{
- gint val = ghb_value_int(rate);
+ gint val = ghb_value_int(grate);
for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
{
if (ghb_audio_bitrates[ii].rate == val)
{
- result = ghb_audio_bitrates[ii].rate;
- break;
+ return &ghb_audio_bitrates[ii];
}
}
}
return result;
}
+static gint
+lookup_audio_bitrate_int(const GValue *grate)
+{
+ const hb_rate_t *rate = lookup_audio_bitrate(grate);
+ if (rate != NULL)
+ return rate->rate;
+ return 160;
+}
+
static const gchar*
-lookup_audio_bitrate_option(const GValue *rate)
+lookup_audio_bitrate_option(const GValue *grate)
{
- gint ii;
- const gchar *result = "160";
+ const hb_rate_t *rate = lookup_audio_bitrate(grate);
+ if (rate != NULL)
+ return rate->name;
+ return "160";
+}
- if (G_VALUE_TYPE(rate) == G_TYPE_STRING)
- {
- // Coincidentally, the string "source" will return 0
- // which is our flag to use "same as source"
- gchar *str = ghb_value_string(rate);
- for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
- {
- if (strcmp(ghb_audio_bitrates[ii].string, str) == 0)
- {
- result = ghb_audio_bitrates[ii].string;
- break;
- }
- }
- g_free(str);
- }
- else if (G_VALUE_TYPE(rate) == G_TYPE_INT ||
- G_VALUE_TYPE(rate) == G_TYPE_INT64 ||
- G_VALUE_TYPE(rate) == G_TYPE_DOUBLE)
+static const hb_encoder_t *
+lookup_audio_encoder_by_int(int ienc)
+{
+ const hb_encoder_t *enc;
+ for (enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ enc = hb_audio_encoder_get_next(enc))
{
- gint val = ghb_value_int(rate);
- for (ii = 0; ii < ghb_audio_bitrates_count; ii++)
+ if (enc->codec == ienc)
{
- if (ghb_audio_bitrates[ii].rate == val)
- {
- result = ghb_audio_bitrates[ii].string;
- break;
- }
+ return enc;
}
}
- return result;
+ return NULL;
}
-static gint
-lookup_hb_encoder_int(const GValue *enc, hb_encoder_t *encoders, int len)
+static const hb_encoder_t *
+lookup_audio_encoder(const GValue *genc)
{
- gint ii;
+ const hb_encoder_t *enc;
- if (G_VALUE_TYPE(enc) == G_TYPE_STRING)
+ if (G_VALUE_TYPE(genc) == G_TYPE_STRING)
{
- gchar *str = ghb_value_string(enc);
- for (ii = 0; ii < len; ii++)
+ gchar *str = ghb_value_string(genc);
+ for (enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ enc = hb_audio_encoder_get_next(enc))
{
- if (strcmp(encoders[ii].human_readable_name, str) == 0 ||
- strcmp(encoders[ii].short_name, str) == 0)
+ if (strcmp(enc->name, str) == 0 ||
+ strcmp(enc->short_name, str) == 0)
{
g_free(str);
- return encoders[ii].encoder;
+ return enc;
}
}
g_free(str);
}
- else if (G_VALUE_TYPE(enc) == G_TYPE_INT ||
- G_VALUE_TYPE(enc) == G_TYPE_INT64 ||
- G_VALUE_TYPE(enc) == G_TYPE_DOUBLE)
+ else if (G_VALUE_TYPE(genc) == G_TYPE_INT ||
+ G_VALUE_TYPE(genc) == G_TYPE_INT64 ||
+ G_VALUE_TYPE(genc) == G_TYPE_DOUBLE)
{
- int val = ghb_value_int(enc);
- for (ii = 0; ii < len; ii++)
- {
- if (encoders[ii].encoder == val)
- {
- return encoders[ii].encoder;
- }
- }
+ return lookup_audio_encoder_by_int(ghb_value_int(genc));
}
- return 0;
+ return NULL;
}
-static const gchar*
-lookup_hb_encoder_option(const GValue *enc, hb_encoder_t *encoders, int len)
+static const hb_encoder_t *
+lookup_video_encoder_by_int(int ienc)
{
- gint ii;
-
- if (G_VALUE_TYPE(enc) == G_TYPE_STRING)
+ const hb_encoder_t *enc;
+ for (enc = hb_video_encoder_get_next(NULL); enc != NULL;
+ enc = hb_video_encoder_get_next(enc))
{
- gchar *str = ghb_value_string(enc);
- for (ii = 0; ii < len; ii++)
+ if (enc->codec == ienc)
{
- if (strcmp(encoders[ii].human_readable_name, str) == 0 ||
- strcmp(encoders[ii].short_name, str) == 0)
- {
- g_free(str);
- return encoders[ii].human_readable_name;
- }
+ return enc;
}
- g_free(str);
}
- else if (G_VALUE_TYPE(enc) == G_TYPE_INT ||
- G_VALUE_TYPE(enc) == G_TYPE_INT64 ||
- G_VALUE_TYPE(enc) == G_TYPE_DOUBLE)
- {
- int val = ghb_value_int(enc);
- for (ii = 0; ii < len; ii++)
- {
- if (encoders[ii].encoder == val)
- {
- return encoders[ii].human_readable_name;
- }
- }
- }
- return 0;
+ return NULL;
}
-static const gchar*
-lookup_hb_encoder_string(const GValue *enc, hb_encoder_t *encoders, int len)
+static const hb_encoder_t *
+lookup_video_encoder(const GValue *genc)
{
- gint ii;
+ const hb_encoder_t *enc;
- if (G_VALUE_TYPE(enc) == G_TYPE_STRING)
+ if (G_VALUE_TYPE(genc) == G_TYPE_STRING)
{
- gchar *str = ghb_value_string(enc);
- for (ii = 0; ii < len; ii++)
+ gchar *str = ghb_value_string(genc);
+ for (enc = hb_video_encoder_get_next(NULL); enc != NULL;
+ enc = hb_video_encoder_get_next(enc))
{
- if (strcmp(encoders[ii].human_readable_name, str) == 0 ||
- strcmp(encoders[ii].short_name, str) == 0)
+ if (strcmp(enc->name, str) == 0 ||
+ strcmp(enc->short_name, str) == 0)
{
g_free(str);
- return encoders[ii].short_name;
+ return enc;
}
}
g_free(str);
}
- else if (G_VALUE_TYPE(enc) == G_TYPE_INT ||
- G_VALUE_TYPE(enc) == G_TYPE_INT64 ||
- G_VALUE_TYPE(enc) == G_TYPE_DOUBLE)
+ else if (G_VALUE_TYPE(genc) == G_TYPE_INT ||
+ G_VALUE_TYPE(genc) == G_TYPE_INT64 ||
+ G_VALUE_TYPE(genc) == G_TYPE_DOUBLE)
{
- int val = ghb_value_int(enc);
- for (ii = 0; ii < len; ii++)
- {
- if (encoders[ii].encoder == val)
- {
- return encoders[ii].short_name;
- }
- }
+ return lookup_video_encoder_by_int(ghb_value_int(genc));
}
+ return NULL;
+}
+
+static gint
+lookup_audio_encoder_int(const GValue *genc)
+{
+ const hb_encoder_t *enc = lookup_audio_encoder(genc);
+ if (enc != NULL)
+ return enc->codec;
return 0;
}
static gint
-lookup_audio_lang_int(const GValue *rate)
+lookup_video_encoder_int(const GValue *genc)
+{
+ const hb_encoder_t *enc = lookup_video_encoder(genc);
+ if (enc != NULL)
+ return enc->codec;
+ return 0;
+}
+
+static const gchar*
+lookup_audio_encoder_option(const GValue *genc)
+{
+ const hb_encoder_t *enc = lookup_audio_encoder(genc);
+ if (enc != NULL)
+ return enc->name;
+ return NULL;
+}
+
+static const gchar*
+lookup_video_encoder_option(const GValue *genc)
+{
+ const hb_encoder_t *enc = lookup_video_encoder(genc);
+ if (enc != NULL)
+ return enc->name;
+ return NULL;
+}
+
+static const gchar*
+lookup_audio_encoder_string(const GValue *genc)
+{
+ const hb_encoder_t *enc = lookup_audio_encoder(genc);
+ if (enc != NULL)
+ return enc->short_name;
+ return NULL;
+}
+
+static const gchar*
+lookup_video_encoder_string(const GValue *genc)
+{
+ const hb_encoder_t *enc = lookup_video_encoder(genc);
+ if (enc != NULL)
+ return enc->short_name;
+ return NULL;
+}
+
+static int
+lookup_audio_lang(const GValue *glang)
{
gint ii;
gchar *str;
- gint result = 0;
- // Coincidentally, the string "source" will return 0
- // which is our flag to use "same as source"
- str = ghb_value_string(rate);
+ str = ghb_value_string(glang);
for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
{
if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
{
- result = ii;
- break;
+ g_free(str);
+ return ii;
}
}
g_free(str);
- return result;
+ return -1;
}
-static const gchar*
-lookup_audio_lang_option(const GValue *rate)
+static int
+lookup_audio_lang_int(const GValue *glang)
{
- gint ii;
- gchar *str;
- const gchar *result = "Same as source";
+ gint ii = lookup_audio_lang(glang);
+ if (ii >= 0)
+ return ii;
+ return 0;
+}
- // Coincidentally, the string "source" will return 0
- // which is our flag to use "same as source"
- str = ghb_value_string(rate);
- for (ii = 0; ii < LANG_TABLE_SIZE; ii++)
+static const gchar*
+lookup_audio_lang_option(const GValue *glang)
+{
+ gint ii = lookup_audio_lang(glang);
+ if (ii >= 0)
{
- if (strcmp(ghb_language_table[ii].iso639_2, str) == 0)
- {
- if (ghb_language_table[ii].native_name[0] != 0)
- result = ghb_language_table[ii].native_name;
- else
- result = ghb_language_table[ii].eng_name;
- break;
- }
+ if (ghb_language_table[ii].native_name[0] != 0)
+ return ghb_language_table[ii].native_name;
+ else
+ return ghb_language_table[ii].eng_name;
}
- g_free(str);
- return result;
+ return "Same as source";
}
GValue*
-ghb_lookup_acodec_value(gint val)
+ghb_lookup_audio_encoder_value(gint ienc)
{
- GValue *value = NULL;
- gint ii;
+ const hb_encoder_t *enc = lookup_audio_encoder_by_int(ienc);
+ if (enc != NULL)
+ return ghb_string_value_new(enc->short_name);
+ return ghb_string_value_new("copy");
+}
- for (ii = 0; ii < hb_audio_encoders_count; ii++)
+static GValue*
+lookup_mixdown_value(gint imix)
+{
+ const hb_mixdown_t *mix = lookup_mixdown_by_int(imix);
+ if (mix != NULL)
+ return ghb_string_value_new(mix->short_name);
+ return NULL;
+}
+static const hb_container_t *
+lookup_container_by_int(int imux)
+{
+ const hb_container_t *mux;
+ for (mux = hb_container_get_next(NULL); mux != NULL;
+ mux = hb_container_get_next(mux))
{
- if ((int)hb_audio_encoders[ii].encoder == val)
+ if (mux->format == imux)
{
- value = ghb_string_value_new(hb_audio_encoders[ii].short_name);
- return value;
+ return mux;
}
}
- value = ghb_string_value_new("copy");
- return value;
+ return NULL;
}
-static GValue*
-get_amix_value(gint val)
+static const hb_container_t *
+lookup_container(const GValue *gmux)
{
- GValue *value = NULL;
- gint ii;
+ const hb_container_t *mux;
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+ if (G_VALUE_TYPE(gmux) == G_TYPE_STRING)
{
- if (hb_audio_mixdowns[ii].amixdown == val)
+ gchar *str = ghb_value_string(gmux);
+ for (mux = hb_container_get_next(NULL); mux != NULL;
+ mux = hb_container_get_next(mux))
{
- value = ghb_string_value_new(hb_audio_mixdowns[ii].short_name);
- break;
+ if (strcmp(mux->name, str) == 0 ||
+ strcmp(mux->short_name, str) == 0)
+ {
+ g_free(str);
+ return mux;
+ }
}
+ g_free(str);
+ }
+ else if (G_VALUE_TYPE(gmux) == G_TYPE_INT ||
+ G_VALUE_TYPE(gmux) == G_TYPE_INT64 ||
+ G_VALUE_TYPE(gmux) == G_TYPE_DOUBLE)
+ {
+ return lookup_container_by_int(ghb_value_int(gmux));
}
- return value;
+ return NULL;
+}
+
+static gint
+lookup_container_int(const GValue *gmux)
+{
+ const hb_container_t *mux = lookup_container(gmux);
+ if (mux != NULL)
+ return mux->format;
+ return 0;
+}
+
+static const gchar*
+lookup_container_option(const GValue *gmux)
+{
+ const hb_container_t *mux = lookup_container(gmux);
+ if (mux != NULL)
+ return mux->name;
+ return 0;
+}
+
+static const gchar*
+lookup_container_string(const GValue *gmux)
+{
+ const hb_container_t *mux = lookup_container(gmux);
+ if (mux != NULL)
+ return mux->short_name;
+ return 0;
}
// Handle for libhb. Gets set by ghb_backend_init()
@@ -1561,15 +1552,14 @@ grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean
static void
grey_mix_opts(signal_user_data_t *ud, gint acodec, gint64 layout)
{
- gint ii;
-
g_debug("grey_mix_opts()\n");
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+
+ const hb_mixdown_t *mix;
+ for (mix = hb_mixdown_get_next(NULL); mix != NULL;
+ mix = hb_mixdown_get_next(mix))
{
- grey_combo_box_item(ud->builder, "AudioMixdown",
- hb_audio_mixdowns[ii].amixdown,
- !hb_mixdown_is_supported(hb_audio_mixdowns[ii].amixdown,
- acodec, layout));
+ grey_combo_box_item(ud->builder, "AudioMixdown", mix->amixdown,
+ !hb_mixdown_is_supported(mix->amixdown, acodec, layout));
}
}
@@ -1580,7 +1570,6 @@ ghb_grey_combo_options(signal_user_data_t *ud)
gint mux, track, titleindex, acodec, fallback;
hb_audio_config_t *aconfig = NULL;
GValue *gval;
- int ii;
widget = GHB_WIDGET (ud->builder, "title");
gval = ghb_widget_value(widget);
@@ -1597,34 +1586,38 @@ ghb_grey_combo_options(signal_user_data_t *ud)
ghb_value_free(gval);
grey_combo_box_item(ud->builder, "x264_analyse", 4, TRUE);
- for (ii = 0; ii < hb_audio_encoders_count; ii++)
+
+ const hb_encoder_t *enc;
+ for (enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ enc = hb_audio_encoder_get_next(enc))
{
- if (!(mux & hb_audio_encoders[ii].muxers))
+ if (!(mux & enc->muxers))
{
grey_combo_box_item(ud->builder, "AudioEncoder",
- hb_audio_encoders[ii].encoder, TRUE);
+ enc->codec, TRUE);
grey_combo_box_item(ud->builder, "AudioEncoderFallback",
- hb_audio_encoders[ii].encoder, TRUE);
+ enc->codec, TRUE);
}
else
{
grey_combo_box_item(ud->builder, "AudioEncoder",
- hb_audio_encoders[ii].encoder, FALSE);
+ enc->codec, FALSE);
grey_combo_box_item(ud->builder, "AudioEncoderFallback",
- hb_audio_encoders[ii].encoder, FALSE);
+ enc->codec, FALSE);
}
}
- for (ii = 0; ii < hb_video_encoders_count; ii++)
+ for (enc = hb_video_encoder_get_next(NULL); enc != NULL;
+ enc = hb_video_encoder_get_next(enc))
{
- if (!(mux & hb_video_encoders[ii].muxers))
+ if (!(mux & enc->muxers))
{
grey_combo_box_item(ud->builder, "VideoEncoder",
- hb_video_encoders[ii].encoder, TRUE);
+ enc->codec, TRUE);
}
else
{
grey_combo_box_item(ud->builder, "VideoEncoder",
- hb_video_encoders[ii].encoder, FALSE);
+ enc->codec, FALSE);
}
}
@@ -1668,9 +1661,9 @@ ghb_get_best_mix(hb_audio_config_t *aconfig, gint acodec, gint mix)
layout = aconfig ? aconfig->in.channel_layout : AV_CH_LAYOUT_5POINT1;
if (mix == HB_AMIXDOWN_NONE)
- mix = hb_audio_mixdowns[hb_audio_mixdowns_count-1].amixdown;
+ mix = HB_INVALID_AMIXDOWN;
- return hb_get_best_mixdown( acodec, layout, mix );
+ return hb_mixdown_get_best( acodec, layout, mix );
}
// Set up the model for the combo box
@@ -1711,11 +1704,10 @@ init_combo_box(GtkBuilder *builder, const gchar *name)
}
static void
-audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
+audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name)
{
GtkTreeIter iter;
GtkListStore *store;
- gint ii;
gchar *str;
g_debug("audio_samplerate_opts_set ()\n");
@@ -1730,29 +1722,31 @@ audio_samplerate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rat
3, 0.0,
4, "source",
-1);
- for (ii = 0; ii < count; ii++)
+
+ const hb_rate_t *rate;
+ for (rate = hb_audio_samplerate_get_next(NULL); rate != NULL;
+ rate = hb_audio_samplerate_get_next(rate))
{
gtk_list_store_append(store, &iter);
- str = g_strdup_printf("<small>%s</small>", rates[ii].string);
+ str = g_strdup_printf("<small>%s</small>", rate->name);
gtk_list_store_set(store, &iter,
0, str,
1, TRUE,
- 2, rates[ii].string,
- 3, (gdouble)rates[ii].rate,
- 4, rates[ii].string,
+ 2, rate->name,
+ 3, (gdouble)rate->rate,
+ 4, rate->name,
-1);
g_free(str);
}
}
static void
-video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gint count)
+video_framerate_opts_set(GtkBuilder *builder, const gchar *name)
{
GtkTreeIter iter;
GtkListStore *store;
- gint ii;
- g_debug("video_rate_opts_set ()\n");
+ g_debug("video_framerate_opts_set ()\n");
store = get_combo_box_store(builder, name);
gtk_list_store_clear(store);
// Add an item for "Same As Source"
@@ -1764,66 +1758,97 @@ video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gi
3, 0.0,
4, "source",
-1);
- for (ii = 0; ii < count; ii++)
+
+ const hb_rate_t *rate;
+ for (rate = hb_video_framerate_get_next(NULL); rate != NULL;
+ rate = hb_video_framerate_get_next(rate))
{
gchar *desc = "";
gchar *option;
- if (strcmp(rates[ii].string, "23.976") == 0)
+ if (strcmp(rate->name, "23.976") == 0)
{
desc = "(NTSC Film)";
}
- else if (strcmp(rates[ii].string, "25") == 0)
+ else if (strcmp(rate->name, "25") == 0)
{
desc = "(PAL Film/Video)";
}
- else if (strcmp(rates[ii].string, "29.97") == 0)
+ else if (strcmp(rate->name, "29.97") == 0)
{
desc = "(NTSC Video)";
}
- option = g_strdup_printf ("%s %s", rates[ii].string, desc);
+ option = g_strdup_printf ("%s %s", rate->name, desc);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
0, option,
1, TRUE,
- 2, rates[ii].string,
- 3, (gdouble)rates[ii].rate,
- 4, rates[ii].string,
+ 2, rate->name,
+ 3, (gdouble)rate->rate,
+ 4, rate->name,
-1);
g_free(option);
}
}
static void
-hb_encoder_opts_set_with_mask(
+video_encoder_opts_set(
+ GtkBuilder *builder,
+ const gchar *name)
+{
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gchar *str;
+
+ g_debug("video_encoder_opts_set ()\n");
+ store = get_combo_box_store(builder, name);
+ gtk_list_store_clear(store);
+
+ const hb_encoder_t *enc;
+ for (enc = hb_video_encoder_get_next(NULL); enc != NULL;
+ enc = hb_video_encoder_get_next(enc))
+ {
+ gtk_list_store_append(store, &iter);
+ str = g_strdup_printf("<small>%s</small>", enc->name);
+ gtk_list_store_set(store, &iter,
+ 0, str,
+ 1, TRUE,
+ 2, enc->short_name,
+ 3, (gdouble)enc->codec,
+ 4, enc->short_name,
+ -1);
+ g_free(str);
+ }
+}
+
+static void
+audio_encoder_opts_set_with_mask(
GtkBuilder *builder,
const gchar *name,
- hb_encoder_t *encoders,
- int len,
int mask,
int neg_mask)
{
GtkTreeIter iter;
GtkListStore *store;
- gint ii;
gchar *str;
- g_debug("hb_encoder_opts_set ()\n");
+ g_debug("audio_encoder_opts_set ()\n");
store = get_combo_box_store(builder, name);
gtk_list_store_clear(store);
- for (ii = 0; ii < len; ii++)
+
+ const hb_encoder_t *enc;
+ for (enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ enc = hb_audio_encoder_get_next(enc))
{
- if ((mask & encoders[ii].encoder) &&
- !(neg_mask & encoders[ii].encoder))
+ if ((mask & enc->codec) && !(neg_mask & enc->codec))
{
gtk_list_store_append(store, &iter);
- str = g_strdup_printf("<small>%s</small>",
- encoders[ii].human_readable_name);
+ str = g_strdup_printf("<small>%s</small>", enc->name);
gtk_list_store_set(store, &iter,
0, str,
1, TRUE,
- 2, encoders[ii].short_name,
- 3, (gdouble)encoders[ii].encoder,
- 4, encoders[ii].short_name,
+ 2, enc->short_name,
+ 3, (gdouble)enc->codec,
+ 4, enc->short_name,
-1);
g_free(str);
}
@@ -1831,20 +1856,17 @@ hb_encoder_opts_set_with_mask(
}
static void
-hb_encoder_opts_set(
+audio_encoder_opts_set(
GtkBuilder *builder,
- const gchar *name,
- hb_encoder_t *encoders,
- int len)
+ const gchar *name)
{
- hb_encoder_opts_set_with_mask(builder, name, encoders, len, ~0, 0);
+ audio_encoder_opts_set_with_mask(builder, name, ~0, 0);
}
static void
acodec_fallback_opts_set(GtkBuilder *builder, const gchar *name)
{
- hb_encoder_opts_set_with_mask(builder, name, hb_audio_encoders,
- hb_audio_encoders_count, ~0, HB_ACODEC_PASS_FLAG);
+ audio_encoder_opts_set_with_mask(builder, name, ~0, HB_ACODEC_PASS_FLAG);
}
static void
@@ -1852,23 +1874,54 @@ mix_opts_set(GtkBuilder *builder, const gchar *name)
{
GtkTreeIter iter;
GtkListStore *store;
- gint ii;
gchar *str;
g_debug("mix_opts_set ()\n");
store = get_combo_box_store(builder, name);
gtk_list_store_clear(store);
- for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
+
+ const hb_mixdown_t *mix;
+ for (mix = hb_mixdown_get_next(NULL); mix != NULL;
+ mix = hb_mixdown_get_next(mix))
{
gtk_list_store_append(store, &iter);
- str = g_strdup_printf("<small>%s</small>",
- hb_audio_mixdowns[ii].human_readable_name);
+ str = g_strdup_printf("<small>%s</small>", mix->name);
gtk_list_store_set(store, &iter,
0, str,
1, TRUE,
- 2, hb_audio_mixdowns[ii].short_name,
- 3, (gdouble)hb_audio_mixdowns[ii].amixdown,
- 4, hb_audio_mixdowns[ii].internal_name,
+ 2, mix->short_name,
+ 3, (gdouble)mix->amixdown,
+ 4, mix->internal_name,
+ -1);
+ g_free(str);
+ }
+}
+
+static void
+container_opts_set(
+ GtkBuilder *builder,
+ const gchar *name)
+{
+ GtkTreeIter iter;
+ GtkListStore *store;
+ gchar *str;
+
+ g_debug("hb_container_opts_set ()\n");
+ store = get_combo_box_store(builder, name);
+ gtk_list_store_clear(store);
+
+ const hb_container_t *mux;
+ for (mux = hb_container_get_next(NULL); mux != NULL;
+ mux = hb_container_get_next(mux))
+ {
+ gtk_list_store_append(store, &iter);
+ str = g_strdup_printf("<small>%s</small>", mux->name);
+ gtk_list_store_set(store, &iter,
+ 0, str,
+ 1, TRUE,
+ 2, mux->short_name,
+ 3, (gdouble)mux->format,
+ 4, mux->short_name,
-1);
g_free(str);
}
@@ -2821,23 +2874,25 @@ ghb_lookup_combo_int(const gchar *name, const GValue *gval)
if (strcmp(name, "AudioBitrate") == 0)
return lookup_audio_bitrate_int(gval);
else if (strcmp(name, "AudioSamplerate") == 0)
- return lookup_audio_rate_int(gval);
+ return lookup_audio_samplerate_int(gval);
else if (strcmp(name, "VideoFramerate") == 0)
- return lookup_video_rate_int(gval);
+ return lookup_video_framerate_int(gval);
else if (strcmp(name, "AudioMixdown") == 0)
- return lookup_mix_int(gval);
+ return lookup_mixdown_int(gval);
else if (strcmp(name, "SrtLanguage") == 0)
return lookup_audio_lang_int(gval);
else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_int(gval);
else if (strcmp(name, "VideoEncoder") == 0)
- return lookup_hb_encoder_int(gval, hb_video_encoders, hb_video_encoders_count);
+ return lookup_video_encoder_int(gval);
else if (strcmp(name, "AudioEncoder") == 0)
- return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_int(gval);
else if (strcmp(name, "AudioEncoderFallback") == 0)
- return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_int(gval);
else if (strcmp(name, "AudioEncoderActual") == 0)
- return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_int(gval);
+ else if (strcmp(name, "FileFormat") == 0)
+ return lookup_container_int(gval);
else
{
return lookup_generic_int(find_combo_table(name), gval);
@@ -2854,23 +2909,25 @@ ghb_lookup_combo_double(const gchar *name, const GValue *gval)
if (strcmp(name, "AudioBitrate") == 0)
return lookup_audio_bitrate_int(gval);
else if (strcmp(name, "AudioSamplerate") == 0)
- return lookup_audio_rate_int(gval);
+ return lookup_audio_samplerate_int(gval);
else if (strcmp(name, "VideoFramerate") == 0)
- return lookup_video_rate_int(gval);
+ return lookup_video_framerate_int(gval);
else if (strcmp(name, "AudioMixdown") == 0)
- return lookup_mix_int(gval);
+ return lookup_mixdown_int(gval);
else if (strcmp(name, "SrtLanguage") == 0)
return lookup_audio_lang_int(gval);
else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_int(gval);
else if (strcmp(name, "VideoEncoder") == 0)
- return lookup_hb_encoder_int(gval, hb_video_encoders, hb_video_encoders_count);
+ return lookup_video_encoder_int(gval);
else if (strcmp(name, "AudioEncoder") == 0)
- return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_int(gval);
else if (strcmp(name, "AudioEncoderFallback") == 0)
- return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_int(gval);
else if (strcmp(name, "AudioEncoderActual") == 0)
- return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_int(gval);
+ else if (strcmp(name, "FileFormat") == 0)
+ return lookup_container_int(gval);
else
{
return lookup_generic_double(find_combo_table(name), gval);
@@ -2887,23 +2944,25 @@ ghb_lookup_combo_option(const gchar *name, const GValue *gval)
if (strcmp(name, "AudioBitrate") == 0)
return lookup_audio_bitrate_option(gval);
else if (strcmp(name, "AudioSamplerate") == 0)
- return lookup_audio_rate_option(gval);
+ return lookup_audio_samplerate_option(gval);
else if (strcmp(name, "VideoFramerate") == 0)
- return lookup_video_rate_option(gval);
+ return lookup_video_framerate_option(gval);
else if (strcmp(name, "AudioMixdown") == 0)
- return lookup_mix_option(gval);
+ return lookup_mixdown_option(gval);
else if (strcmp(name, "SrtLanguage") == 0)
return lookup_audio_lang_option(gval);
else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_option(gval);
else if (strcmp(name, "VideoEncoder") == 0)
- return lookup_hb_encoder_option(gval, hb_video_encoders, hb_video_encoders_count);
+ return lookup_video_encoder_option(gval);
else if (strcmp(name, "AudioEncoder") == 0)
- return lookup_hb_encoder_option(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_option(gval);
else if (strcmp(name, "AudioEncoderFallback") == 0)
- return lookup_hb_encoder_option(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_option(gval);
else if (strcmp(name, "AudioEncoderActual") == 0)
- return lookup_hb_encoder_option(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_option(gval);
+ else if (strcmp(name, "FileFormat") == 0)
+ return lookup_container_option(gval);
else
{
return lookup_generic_option(find_combo_table(name), gval);
@@ -2920,23 +2979,25 @@ ghb_lookup_combo_string(const gchar *name, const GValue *gval)
if (strcmp(name, "AudioBitrate") == 0)
return lookup_audio_bitrate_option(gval);
else if (strcmp(name, "AudioSamplerate") == 0)
- return lookup_audio_rate_string(gval);
+ return lookup_audio_samplerate_string(gval);
else if (strcmp(name, "VideoFramerate") == 0)
- return lookup_video_rate_option(gval);
+ return lookup_video_framerate_option(gval);
else if (strcmp(name, "AudioMixdown") == 0)
- return lookup_mix_string(gval);
+ return lookup_mixdown_string(gval);
else if (strcmp(name, "SrtLanguage") == 0)
return lookup_audio_lang_option(gval);
else if (strcmp(name, "PreferredLanguage") == 0)
return lookup_audio_lang_option(gval);
else if (strcmp(name, "VideoEncoder") == 0)
- return lookup_hb_encoder_string(gval, hb_video_encoders, hb_video_encoders_count);
+ return lookup_video_encoder_string(gval);
else if (strcmp(name, "AudioEncoder") == 0)
- return lookup_hb_encoder_string(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_string(gval);
else if (strcmp(name, "AudioEncoderFallback") == 0)
- return lookup_hb_encoder_string(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_string(gval);
else if (strcmp(name, "AudioEncoderActual") == 0)
- return lookup_hb_encoder_string(gval, hb_audio_encoders, hb_audio_encoders_count);
+ return lookup_audio_encoder_string(gval);
+ else if (strcmp(name, "FileFormat") == 0)
+ return lookup_container_string(gval);
else
{
return lookup_generic_string(find_combo_table(name), gval);
@@ -2979,11 +3040,11 @@ ghb_update_ui_combo_box(
if (all)
{
audio_bitrate_opts_set(ud->builder, "AudioBitrate");
- audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
- video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
+ audio_samplerate_opts_set(ud->builder, "AudioSamplerate");
+ video_framerate_opts_set(ud->builder, "VideoFramerate");
mix_opts_set(ud->builder, "AudioMixdown");
- hb_encoder_opts_set(ud->builder, "VideoEncoder", hb_video_encoders, hb_video_encoders_count);
- hb_encoder_opts_set(ud->builder, "AudioEncoder", hb_audio_encoders, hb_audio_encoders_count);
+ video_encoder_opts_set(ud->builder, "VideoEncoder");
+ audio_encoder_opts_set(ud->builder, "AudioEncoder");
acodec_fallback_opts_set(ud->builder, "AudioEncoderFallback");
language_opts_set(ud->builder, "SrtLanguage");
language_opts_set(ud->builder, "PreferredLanguage");
@@ -2999,7 +3060,6 @@ ghb_update_ui_combo_box(
generic_opts_set(ud->builder, "LoggingLevel", &logging_opts);
generic_opts_set(ud->builder, "LogLongevity", &log_longevity_opts);
generic_opts_set(ud->builder, "check_updates", &appcast_update_opts);
- generic_opts_set(ud->builder, "FileFormat", &container_opts);
generic_opts_set(ud->builder, "PictureDeinterlace", &deint_opts);
generic_opts_set(ud->builder, "PictureDetelecine", &detel_opts);
generic_opts_set(ud->builder, "PictureDecomb", &decomb_opts);
@@ -3015,21 +3075,22 @@ ghb_update_ui_combo_box(
x264_tune_opts_set(ud->builder, "x264Tune");
h264_profile_opts_set(ud->builder, "h264Profile");
h264_level_opts_set(ud->builder, "h264Level");
+ container_opts_set(ud->builder, "FileFormat");
}
else
{
if (strcmp(name, "AudioBitrate") == 0)
audio_bitrate_opts_set(ud->builder, "AudioBitrate");
else if (strcmp(name, "AudioSamplerate") == 0)
- audio_samplerate_opts_set(ud->builder, "AudioSamplerate", hb_audio_rates, hb_audio_rates_count);
+ audio_samplerate_opts_set(ud->builder, "AudioSamplerate");
else if (strcmp(name, "VideoFramerate") == 0)
- video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
+ video_framerate_opts_set(ud->builder, "VideoFramerate");
else if (strcmp(name, "AudioMixdown") == 0)
mix_opts_set(ud->builder, "AudioMixdown");
else if (strcmp(name, "VideoEncoder") == 0)
- hb_encoder_opts_set(ud->builder, "VideoEncoder", hb_video_encoders, hb_video_encoders_count);
+ video_encoder_opts_set(ud->builder, "VideoEncoder");
else if (strcmp(name, "AudioEncoder") == 0)
- hb_encoder_opts_set(ud->builder, "AudioEncoder", hb_audio_encoders, hb_audio_encoders_count);
+ audio_encoder_opts_set(ud->builder, "AudioEncoder");
else if (strcmp(name, "AudioEncoderFallback") == 0)
acodec_fallback_opts_set(ud->builder, "AudioEncoderFallback");
else if (strcmp(name, "SrtLanguage") == 0)
@@ -3050,6 +3111,8 @@ ghb_update_ui_combo_box(
h264_profile_opts_set(ud->builder, "h264Profile");
else if (strcmp(name, "h264Level") == 0)
h264_level_opts_set(ud->builder, "h264Level");
+ else if (strcmp(name, "FileFormat") == 0)
+ container_opts_set(ud->builder, "FileFormat");
else
generic_opts_set(ud->builder, name, find_combo_table(name));
}
@@ -3079,6 +3142,7 @@ init_ui_combo_boxes(GtkBuilder *builder)
init_combo_box(builder, "x264Tune");
init_combo_box(builder, "h264Profile");
init_combo_box(builder, "h264Level");
+ init_combo_box(builder, "FileFormat");
for (ii = 0; combo_name_map[ii].name != NULL; ii++)
{
init_combo_box(builder, combo_name_map[ii].name);
@@ -3325,35 +3389,33 @@ audio_bitrate_opts_add(GtkBuilder *builder, const gchar *name, gint rate)
if (rate >= 0 && rate < 8) return;
- if (ghb_audio_bitrates[hb_audio_bitrates_count].string)
+ if (ghb_audio_bitrates[ghb_abr_count].name)
{
- g_free((char*)ghb_audio_bitrates[hb_audio_bitrates_count].string);
+ g_free((char*)ghb_audio_bitrates[ghb_abr_count].name);
}
- ghb_audio_bitrates[hb_audio_bitrates_count].rate = rate;
+ ghb_audio_bitrates[ghb_abr_count].rate = rate;
if (rate < 0)
{
- ghb_audio_bitrates[hb_audio_bitrates_count].string =
- g_strdup_printf("N/A");
+ ghb_audio_bitrates[ghb_abr_count].name = g_strdup_printf("N/A");
}
else
{
- ghb_audio_bitrates[hb_audio_bitrates_count].string =
- g_strdup_printf("%d", rate);
+ ghb_audio_bitrates[ghb_abr_count].name = g_strdup_printf("%d", rate);
}
- ghb_audio_bitrates_count = hb_audio_bitrates_count + 1;
+ ghb_audio_bitrates_count = ghb_abr_count + 1;
store = get_combo_box_store(builder, name);
if (!find_combo_item_by_int(GTK_TREE_MODEL(store), rate, &iter))
{
str = g_strdup_printf ("<small>%s</small>",
- ghb_audio_bitrates[hb_audio_bitrates_count].string);
+ ghb_audio_bitrates[ghb_abr_count].name);
gtk_list_store_append(store, &iter);
gtk_list_store_set(store, &iter,
0, str,
1, TRUE,
- 2, ghb_audio_bitrates[hb_audio_bitrates_count].string,
+ 2, ghb_audio_bitrates[ghb_abr_count].name,
3, (gdouble)rate,
- 4, ghb_audio_bitrates[hb_audio_bitrates_count].string,
+ 4, ghb_audio_bitrates[ghb_abr_count].name,
-1);
g_free(str);
}
@@ -3375,7 +3437,7 @@ audio_bitrate_opts_update(
guint last = (guint)last_rate;
guint first = (guint)first_rate;
- ghb_audio_bitrates_count = hb_audio_bitrates_count;
+ ghb_audio_bitrates_count = ghb_abr_count;
g_debug("audio_bitrate_opts_clean ()\n");
store = get_combo_box_store(builder, name);
@@ -3414,15 +3476,29 @@ audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name)
{
GtkTreeIter iter;
GtkListStore *store;
- gint ii;
+ gint count = 0;
gchar *str;
+ int ii;
- ghb_audio_bitrates_count = hb_audio_bitrates_count;
- ghb_audio_bitrates = calloc(hb_audio_bitrates_count+1, sizeof(hb_rate_t));
+ const hb_rate_t *rate;
- for (ii = 0; ii < hb_audio_bitrates_count; ii++)
+ if (ghb_audio_bitrates == NULL)
{
- ghb_audio_bitrates[ii] = hb_audio_bitrates[ii];
+ // Count rates
+ for (rate = hb_audio_bitrate_get_next(NULL); rate != NULL;
+ rate = hb_audio_bitrate_get_next(rate))
+ {
+ count++;
+ }
+
+ ghb_audio_bitrates_count = ghb_abr_count = count;
+ ghb_audio_bitrates = calloc(count+1, sizeof(hb_rate_t));
+
+ for (ii = 0, rate = hb_audio_bitrate_get_next(NULL); rate != NULL;
+ ii++, rate = hb_audio_bitrate_get_next(rate))
+ {
+ ghb_audio_bitrates[ii] = *rate;
+ }
}
g_debug("audio_bitrate_opts_set ()\n");
@@ -3432,13 +3508,13 @@ audio_bitrate_opts_set(GtkBuilder *builder, const gchar *name)
{
gtk_list_store_append(store, &iter);
str = g_strdup_printf ("<small>%s</small>",
- ghb_audio_bitrates[ii].string);
+ ghb_audio_bitrates[ii].name);
gtk_list_store_set(store, &iter,
0, str,
1, TRUE,
- 2, ghb_audio_bitrates[ii].string,
+ 2, ghb_audio_bitrates[ii].name,
3, (gdouble)ghb_audio_bitrates[ii].rate,
- 4, ghb_audio_bitrates[ii].string,
+ 4, ghb_audio_bitrates[ii].name,
-1);
g_free(str);
}
@@ -4513,7 +4589,7 @@ ghb_validate_audio(GValue *settings)
{
codec = HB_ACODEC_FAAC;
}
- value = ghb_lookup_acodec_value(codec);
+ value = ghb_lookup_audio_encoder_value(codec);
ghb_settings_take_value(asettings, "AudioEncoder", value);
}
gchar *a_unsup = NULL;
@@ -4540,25 +4616,18 @@ ghb_validate_audio(GValue *settings)
return FALSE;
}
g_free(message);
- value = ghb_lookup_acodec_value(codec);
+ value = ghb_lookup_audio_encoder_value(codec);
ghb_settings_take_value(asettings, "AudioEncoder", value);
}
gint mix = ghb_settings_combo_int (asettings, "AudioMixdown");
- gint jj;
const gchar *mix_unsup = NULL;
if (!hb_mixdown_is_supported(mix, codec, aconfig->in.channel_layout))
{
- for (jj = 0; jj < hb_audio_mixdowns_count; jj++)
- {
- if (mix == hb_audio_mixdowns[jj].amixdown)
- {
- {
- mix_unsup = hb_audio_mixdowns[jj].human_readable_name;
- }
- }
- }
+ const hb_mixdown_t *hb_mix = lookup_mixdown_by_int(mix);
+ if (hb_mix != NULL)
+ mix_unsup = hb_mix->name;
}
if (mix_unsup)
{
@@ -4573,7 +4642,7 @@ ghb_validate_audio(GValue *settings)
}
g_free(message);
mix = ghb_get_best_mix(aconfig, codec, mix);
- value = get_amix_value(mix);
+ value = lookup_mixdown_value(mix);
ghb_settings_take_value(asettings, "AudioMixdown", value);
}
}
@@ -5017,7 +5086,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
audio.out.bitrate =
ghb_settings_combo_int(asettings, "AudioBitrate");
- audio.out.bitrate = hb_get_best_audio_bitrate(
+ audio.out.bitrate = hb_audio_bitrate_get_best(
audio.out.codec, audio.out.bitrate,
audio.out.samplerate, audio.out.mixdown);
}
diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h
index 242a3e3b7..03d0ce4ed 100644
--- a/gtk/src/hb-backend.h
+++ b/gtk/src/hb-backend.h
@@ -156,7 +156,7 @@ gdouble ghb_lookup_combo_double(const gchar *name, const GValue *gval);
const gchar* ghb_lookup_combo_option(const gchar *name, const GValue *gval);
const gchar* ghb_lookup_combo_string(const gchar *name, const GValue *gval);
gchar* ghb_get_tmp_dir();
-gint ghb_find_closest_audio_rate(gint rate);
-GValue* ghb_lookup_acodec_value(gint val);
+gint ghb_find_closest_audio_samplerate(gint rate);
+GValue* ghb_lookup_audio_encoder_value(gint val);
#endif // _HBBACKEND_H_
diff --git a/gtk/src/presets.c b/gtk/src/presets.c
index d76d5d280..12fdfbd67 100644
--- a/gtk/src/presets.c
+++ b/gtk/src/presets.c
@@ -2044,19 +2044,26 @@ static value_map_t acodec_xlat_compat[] =
static value_map_t *acodec_xlat;
-static value_map_t * create_encoder_xlat_tbl(value_map_t *compat, hb_encoder_t *enc, int size)
+static value_map_t * create_video_encoder_xlat_tbl(value_map_t *compat)
{
value_map_t *out;
- int cc, ii;
+ 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; ii < size; ii++)
+ 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[ii].human_readable_name;
- out[ii].lin_val = enc[ii].short_name;
+ out[ii].mac_val = enc->name;
+ out[ii].lin_val = enc->short_name;
}
for (ii = 0; ii < cc; ii++)
@@ -2065,19 +2072,26 @@ static value_map_t * create_encoder_xlat_tbl(value_map_t *compat, hb_encoder_t *
return out;
}
-static value_map_t * create_mix_xlat_tbl(value_map_t *compat, hb_mixdown_t * mix, int size)
+static value_map_t * create_audio_encoder_xlat_tbl(value_map_t *compat)
{
value_map_t *out;
- int cc, ii;
+ 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; ii < size; ii++)
+ for (ii = 0, enc = hb_audio_encoder_get_next(NULL); enc != NULL;
+ ii++, enc = hb_audio_encoder_get_next(enc))
{
- out[ii].mac_val = mix[ii].human_readable_name;
- out[ii].lin_val = mix[ii].short_name;
+ out[ii].mac_val = enc->name;
+ out[ii].lin_val = enc->short_name;
}
for (ii = 0; ii < cc; ii++)
@@ -2086,15 +2100,33 @@ static value_map_t * create_mix_xlat_tbl(value_map_t *compat, hb_mixdown_t * mix
return out;
}
-value_map_t container_xlat[] =
+static value_map_t * create_mix_xlat_tbl(value_map_t *compat)
{
- {"MP4 file", "mp4"},
- {"M4V file", "mp4"},
- {"MKV file", "mkv"},
- {"AVI file", "mkv"},
- {"OGM file", "mkv"},
- {NULL, NULL}
-};
+ 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[] =
{
@@ -2361,6 +2393,24 @@ export_value_xlat2(value_map_t *value_map, GValue *lin_val, GType mac_type)
return NULL;
}
+static GValue*
+export_value_xlat_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);
+ g_free(str);
+ mux = hb_container_get_name(imux);
+ if (mux != NULL)
+ sval = ghb_string_value_new(mux);
+
+ return sval;
+}
+
static void
export_value_xlat(GValue *dict)
{
@@ -2374,7 +2424,7 @@ export_value_xlat(GValue *dict)
ghb_dict_insert(dict, g_strdup(key), gval);
key = "FileFormat";
lin_val = ghb_dict_lookup(dict, key);
- gval = export_value_xlat2(container_xlat, lin_val, G_TYPE_STRING);
+ gval = export_value_xlat_container(lin_val);
if (gval)
ghb_dict_insert(dict, g_strdup(key), gval);
key = "VideoFramerate";
@@ -2528,6 +2578,34 @@ import_value_xlat2(
return NULL;
}
+static GValue*
+import_value_xlat_container(GValue *mac_val)
+{
+ GValue *sval = NULL;
+ gchar *str;
+ const gchar *mux;
+ int imux;
+
+ str = ghb_value_string(mac_val);
+ mux = hb_container_sanitize_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 (mux != NULL)
+ sval = ghb_string_value_new(mux);
+
+ return sval;
+}
+
static void
import_value_xlat(GValue *dict)
{
@@ -2542,7 +2620,7 @@ import_value_xlat(GValue *dict)
ghb_dict_insert(dict, g_strdup(key), gval);
key = "FileFormat";
mac_val = ghb_dict_lookup(dict, key);
- gval = import_value_xlat2(defaults, container_xlat, key, mac_val);
+ gval = import_value_xlat_container(mac_val);
if (gval)
ghb_dict_insert(dict, g_strdup(key), gval);
key = "VideoFramerate";
@@ -3304,9 +3382,9 @@ void
ghb_presets_load(signal_user_data_t *ud)
{
// Create translation tables from libhb tables
- mix_xlat = create_mix_xlat_tbl(mix_xlat_compat, hb_audio_mixdowns, hb_audio_mixdowns_count);
- acodec_xlat = create_encoder_xlat_tbl(acodec_xlat_compat, hb_audio_encoders, hb_audio_encoders_count);
- vcodec_xlat = create_encoder_xlat_tbl(vcodec_xlat_compat, hb_video_encoders, hb_video_encoders_count);
+ mix_xlat = create_mix_xlat_tbl(mix_xlat_compat);
+ acodec_xlat = create_audio_encoder_xlat_tbl(acodec_xlat_compat);
+ vcodec_xlat = create_video_encoder_xlat_tbl(vcodec_xlat_compat);
presetsPlist = load_plist("presets");
if (presetsPlist == NULL)
diff --git a/libhb/common.c b/libhb/common.c
index 95c9f921d..1d02af536 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -19,6 +19,8 @@
/**********************************************************************
* Global variables
*********************************************************************/
+static hb_error_handler_t *error_handler = NULL;
+
hb_rate_t hb_video_rates[] =
{
{ "5", 5400000 },
@@ -81,8 +83,6 @@ hb_rate_t hb_audio_bitrates[] =
};
int hb_audio_bitrates_count = sizeof(hb_audio_bitrates) / sizeof(hb_rate_t);
-static hb_error_handler_t *error_handler = NULL;
-
hb_dither_t hb_audio_dithers[] =
{
{ "default", "auto", AV_RESAMPLE_DITHER_NONE - 1, },
@@ -112,10 +112,10 @@ 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_MP4|HB_MUX_MKV },
- { "MPEG-4 (FFmpeg)", "ffmpeg4", HB_VCODEC_FFMPEG_MPEG4, HB_MUX_MP4|HB_MUX_MKV },
- { "MPEG-2 (FFmpeg)", "ffmpeg2", HB_VCODEC_FFMPEG_MPEG2, HB_MUX_MP4|HB_MUX_MKV },
- { "VP3 (Theora)", "theora", HB_VCODEC_THEORA, HB_MUX_MKV },
+ { "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_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_encoder_t);
@@ -123,566 +123,420 @@ int hb_video_encoders_count = sizeof(hb_video_encoders) / sizeof(hb_encoder_t);
hb_encoder_t hb_audio_encoders[] =
{
#ifdef __APPLE__
- { "AAC (CoreAudio)", "ca_aac", HB_ACODEC_CA_AAC, HB_MUX_MP4|HB_MUX_MKV },
- { "HE-AAC (CoreAudio)", "ca_haac", HB_ACODEC_CA_HAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "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 },
#endif
- { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MASK_MP4|HB_MUX_MASK_MKV },
#ifdef USE_FDK_AAC
- { "AAC (FDK)", "fdk_aac", HB_ACODEC_FDK_AAC, HB_MUX_MP4|HB_MUX_MKV },
- { "HE-AAC (FDK)", "fdk_haac", HB_ACODEC_FDK_HAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "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 },
#endif
- { "AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, HB_MUX_MP4|HB_MUX_MKV },
- { "AAC Passthru", "copy:aac", HB_ACODEC_AAC_PASS, HB_MUX_MP4|HB_MUX_MKV },
- { "AC3 (ffmpeg)", "ffac3", HB_ACODEC_AC3, HB_MUX_MP4|HB_MUX_MKV },
- { "AC3 Passthru", "copy:ac3", HB_ACODEC_AC3_PASS, HB_MUX_MP4|HB_MUX_MKV },
- { "DTS Passthru", "copy:dts", HB_ACODEC_DCA_PASS, HB_MUX_MP4|HB_MUX_MKV },
- { "DTS-HD Passthru", "copy:dtshd", HB_ACODEC_DCA_HD_PASS, HB_MUX_MP4|HB_MUX_MKV },
- { "MP3 (lame)", "lame", HB_ACODEC_LAME, HB_MUX_MP4|HB_MUX_MKV },
- { "MP3 Passthru", "copy:mp3", HB_ACODEC_MP3_PASS, HB_MUX_MP4|HB_MUX_MKV },
- { "Vorbis (vorbis)", "vorbis", HB_ACODEC_VORBIS, HB_MUX_MKV },
- { "FLAC (ffmpeg)", "ffflac", HB_ACODEC_FFFLAC, HB_MUX_MKV },
- { "FLAC (24-bit)", "ffflac24", HB_ACODEC_FFFLAC24, HB_MUX_MKV },
- { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV },
+ { "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);
-/* Expose values for PInvoke */
-hb_rate_t* hb_get_video_rates() { return hb_video_rates; }
-int hb_get_video_rates_count() { return hb_video_rates_count; }
-hb_rate_t* hb_get_audio_rates() { return hb_audio_rates; }
-int hb_get_audio_rates_count() { return hb_audio_rates_count; }
-hb_rate_t* hb_get_audio_bitrates() { return hb_audio_bitrates; }
-int hb_get_audio_bitrates_count() { return hb_audio_bitrates_count; }
-hb_dither_t* hb_get_audio_dithers() { return hb_audio_dithers; }
-int hb_get_audio_dithers_count() { return hb_audio_dithers_count; }
-hb_mixdown_t* hb_get_audio_mixdowns() { return hb_audio_mixdowns; }
-int hb_get_audio_mixdowns_count() { return hb_audio_mixdowns_count; }
-hb_encoder_t* hb_get_video_encoders() { return hb_video_encoders; }
-int hb_get_video_encoders_count() { return hb_video_encoders_count; }
-hb_encoder_t* hb_get_audio_encoders() { return hb_audio_encoders; }
-int hb_get_audio_encoders_count() { return hb_audio_encoders_count; }
-
-int hb_audio_dither_get_default()
+// note: for each container, the muxer nearer the top is the default
+hb_container_t hb_containers[] =
{
- // "auto"
- return hb_audio_dithers[0].method;
-}
+ { "MPEG-4 (mp4v2)", "mp4v2", "mp4", HB_MUX_MP4V2, },
+ { "Matroska (libmkv)", "libmkv", "mkv", HB_MUX_LIBMKV, },
+};
+int hb_containers_count = sizeof(hb_containers) / sizeof(hb_container_t);
-int hb_audio_dither_get_default_method()
+int hb_video_framerate_get_from_name(const char *name)
{
- /*
- * input could be s16 (possibly already dithered) converted to flt, so
- * let's use a "low-risk" dither algorithm (standard triangular).
- */
- return AV_RESAMPLE_DITHER_TRIANGULAR;
-}
+ if (name == NULL || *name == '\0')
+ goto fail;
-int hb_audio_dither_is_supported(uint32_t codec)
-{
- // encoder's input sample format must be s16(p)
- switch (codec)
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "23.976 (NTSC Film)"))
{
- case HB_ACODEC_FFFLAC:
- case HB_ACODEC_FDK_AAC:
- case HB_ACODEC_FDK_HAAC:
- return 1;
- default:
- return 0;
+ return 1126125;
+ }
+ if (!strcasecmp(name, "25 (PAL Film/Video)"))
+ {
+ return 1080000;
+ }
+ if (!strcasecmp(name, "29.97 (NTSC Video)"))
+ {
+ return 900900;
}
-}
-const char* hb_audio_dither_get_description(int method)
-{
int i;
- for (i = 0; i < hb_audio_dithers_count; i++)
+ for (i = 0; i < hb_video_rates_count; i++)
{
- if (hb_audio_dithers[i].method == method)
+ if (!strcasecmp(hb_video_rates[i].name, name))
{
- return hb_audio_dithers[i].description;
+ return hb_video_rates[i].rate;
}
}
- return "";
-}
-
-int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout)
-{
- return (hb_mixdown_has_codec_support(mixdown, codec) &&
- hb_mixdown_has_remix_support(mixdown, layout));
+fail:
+ return -1;
}
-int hb_mixdown_has_codec_support(int mixdown, uint32_t codec)
+const char* hb_video_framerate_get_name(int framerate)
{
- // Passthru, only "None" mixdown is supported
- if (codec & HB_ACODEC_PASS_FLAG)
- return (mixdown == HB_AMIXDOWN_NONE);
-
- // Not passthru, "None" mixdown never supported
- if (mixdown == HB_AMIXDOWN_NONE)
- return 0;
+ if (framerate > hb_video_rates[0].rate ||
+ framerate < hb_video_rates[hb_video_rates_count - 1].rate)
+ goto fail;
- switch (codec)
+ int i;
+ for (i = 0; i < hb_video_rates_count; i++)
{
- case HB_ACODEC_VORBIS:
- case HB_ACODEC_FFFLAC:
- case HB_ACODEC_FFFLAC24:
- return (mixdown <= HB_AMIXDOWN_7POINT1);
-
- case HB_ACODEC_LAME:
- case HB_ACODEC_FFAAC:
- return (mixdown <= HB_AMIXDOWN_DOLBYPLII);
-
- case HB_ACODEC_FAAC:
- case HB_ACODEC_CA_AAC:
- case HB_ACODEC_CA_HAAC:
- return ((mixdown <= HB_AMIXDOWN_5POINT1) ||
- (mixdown == HB_AMIXDOWN_5_2_LFE));
-
- default:
- return (mixdown <= HB_AMIXDOWN_5POINT1);
+ if (hb_video_rates[i].rate == framerate)
+ {
+ return hb_video_rates[i].name;
+ }
}
+
+fail:
+ return NULL;
}
-int hb_mixdown_has_remix_support(int mixdown, uint64_t layout)
+const char* hb_video_framerate_sanitize_name(const char *name)
{
- switch (mixdown)
- {
- // stereo + front left/right of center
- case HB_AMIXDOWN_5_2_LFE:
- return ((layout & AV_CH_FRONT_LEFT_OF_CENTER) &&
- (layout & AV_CH_FRONT_RIGHT_OF_CENTER) &&
- (layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO);
-
- // 7.0 or better
- case HB_AMIXDOWN_7POINT1:
- return ((layout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0);
-
- // 6.0 or better
- case HB_AMIXDOWN_6POINT1:
- return ((layout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0 ||
- (layout & AV_CH_LAYOUT_6POINT0) == AV_CH_LAYOUT_6POINT0 ||
- (layout & AV_CH_LAYOUT_HEXAGONAL) == AV_CH_LAYOUT_HEXAGONAL);
-
- // stereo + either of front center, side or back left/right, back center
- case HB_AMIXDOWN_5POINT1:
- return ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 ||
- (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 ||
- (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD ||
- (layout & AV_CH_LAYOUT_SURROUND) == AV_CH_LAYOUT_SURROUND);
-
- // stereo + either of side or back left/right, back center
- // also, allow Dolby Surrounbd output if the input is already Dolby
- case HB_AMIXDOWN_DOLBY:
- case HB_AMIXDOWN_DOLBYPLII:
- return ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 ||
- (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 ||
- (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD ||
- (layout == AV_CH_LAYOUT_STEREO_DOWNMIX &&
- mixdown == HB_AMIXDOWN_DOLBY));
-
- // more than 1 channel
- case HB_AMIXDOWN_STEREO:
- return (av_get_channel_layout_nb_channels(layout) > 1);
-
- // regular stereo (not Dolby)
- case HB_AMIXDOWN_LEFT:
- case HB_AMIXDOWN_RIGHT:
- return (layout == AV_CH_LAYOUT_STEREO);
-
- // mono remix always supported
- // HB_AMIXDOWN_NONE always supported (for Passthru)
- case HB_AMIXDOWN_MONO:
- case HB_AMIXDOWN_NONE:
- return 1;
-
- // unknown mixdown, should never happen
- default:
- return 0;
- }
+ return hb_video_framerate_get_name(hb_video_framerate_get_from_name(name));
}
-int hb_mixdown_get_discrete_channel_count(int amixdown)
+const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last)
{
- switch (amixdown)
+ if (last == NULL)
{
- case HB_AMIXDOWN_5_2_LFE:
- case HB_AMIXDOWN_7POINT1:
- return 8;
-
- case HB_AMIXDOWN_6POINT1:
- return 7;
-
- case HB_AMIXDOWN_5POINT1:
- return 6;
-
- case HB_AMIXDOWN_MONO:
- case HB_AMIXDOWN_LEFT:
- case HB_AMIXDOWN_RIGHT:
- return 1;
-
- case HB_AMIXDOWN_NONE:
- return 0;
-
- default:
- return 2;
+ return &hb_video_rates[0];
}
-}
-
-int hb_mixdown_get_low_freq_channel_count(int amixdown)
-{
- switch (amixdown)
+ if (last < &hb_video_rates[0] ||
+ last >= &hb_video_rates[hb_video_rates_count - 1])
{
- case HB_AMIXDOWN_5POINT1:
- case HB_AMIXDOWN_6POINT1:
- case HB_AMIXDOWN_7POINT1:
- case HB_AMIXDOWN_5_2_LFE:
- return 1;
-
- default:
- return 0;
+ return NULL;
}
+ return last + 1;
}
-int hb_mixdown_get_mixdown_from_short_name(const char *short_name)
+int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift)
{
- int i;
- for (i = 0; i < hb_audio_mixdowns_count; i++)
+ int ii, best_samplerate, samplerate_shift;
+ if ((samplerate < 32000) &&
+ (codec == HB_ACODEC_CA_HAAC || codec == HB_ACODEC_AC3))
{
- if (!strcmp(hb_audio_mixdowns[i].short_name, short_name))
- {
- return hb_audio_mixdowns[i].amixdown;
- }
+ // ca_haac can't do samplerates < 32 kHz
+ // AC-3 < 32 kHz suffers from poor hardware compatibility
+ best_samplerate = 32000;
+ samplerate_shift = 0;
}
- return 0;
-}
-
-const char* hb_mixdown_get_short_name_from_mixdown(int amixdown)
-{
- int i;
- for (i = 0; i < hb_audio_mixdowns_count; i++)
+ else if (samplerate < 16000 && codec == HB_ACODEC_FDK_HAAC)
{
- if (hb_audio_mixdowns[i].amixdown == amixdown)
- {
- return hb_audio_mixdowns[i].short_name;
- }
+ // fdk_haac can't do samplerates < 16 kHz
+ best_samplerate = 16000;
+ samplerate_shift = 1;
}
- return "";
-}
-
-void hb_autopassthru_apply_settings( hb_job_t * job )
-{
- int i, j, already_printed;
- hb_audio_t * audio;
- for( i = 0, already_printed = 0; i < hb_list_count( job->list_audio ); )
+ else
{
- audio = hb_list_item( job->list_audio, i );
- if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
+ best_samplerate = samplerate;
+ for (ii = hb_audio_rates_count - 1; ii >= 0; ii--)
{
- if( !already_printed )
- hb_autopassthru_print_settings( job );
- already_printed = 1;
- audio->config.out.codec = hb_autopassthru_get_encoder( audio->config.in.codec,
- job->acodec_copy_mask,
- job->acodec_fallback,
- job->mux );
- if( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) &&
- !( audio->config.out.codec & HB_ACODEC_MASK ) )
- {
- hb_log( "Auto Passthru: passthru not possible and no valid fallback specified, dropping track %d",
- audio->config.out.track );
- hb_list_rem( job->list_audio, audio );
- hb_audio_close( &audio );
- continue;
- }
- audio->config.out.samplerate = audio->config.in.samplerate;
- if( !( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) )
- {
- if( audio->config.out.codec == job->acodec_fallback )
- {
- hb_log( "Auto Passthru: passthru not possible for track %d, using fallback",
- audio->config.out.track );
- }
- else
- {
- hb_log( "Auto Passthru: passthru and fallback not possible for track %d, using default encoder",
- audio->config.out.track );
- }
- audio->config.out.mixdown = hb_get_default_mixdown( audio->config.out.codec,
- audio->config.in.channel_layout );
- audio->config.out.bitrate = hb_get_default_audio_bitrate( audio->config.out.codec,
- audio->config.out.samplerate,
- audio->config.out.mixdown );
- audio->config.out.compression_level = hb_get_default_audio_compression( audio->config.out.codec );
- }
- else
+ // 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)
{
- for( j = 0; j < hb_audio_encoders_count; j++ )
- {
- if( hb_audio_encoders[j].encoder == audio->config.out.codec )
- {
- hb_log( "Auto Passthru: using %s for track %d",
- hb_audio_encoders[j].human_readable_name,
- audio->config.out.track );
- break;
- }
- }
+ best_samplerate = hb_audio_rates[ii].rate;
+ break;
}
}
- /* Adjust output track number, in case we removed one.
- * Output tracks sadly still need to be in sequential order.
- * Note: out.track starts at 1, i starts at 0 */
- audio->config.out.track = ++i;
+ /* sr_shift: 0 -> 48000, 44100, 32000 Hz
+ * 1 -> 24000, 22050, 16000 Hz
+ * 2 -> 12000, 11025, 8000 Hz
+ *
+ * also, since samplerates are sanitized downwards:
+ *
+ * (samplerate < 32000) implies (samplerate <= 24000)
+ */
+ samplerate_shift = ((best_samplerate < 16000) ? 2 :
+ (best_samplerate < 32000) ? 1 : 0);
}
+ if (sr_shift != NULL)
+ {
+ *sr_shift = samplerate_shift;
+ }
+ return best_samplerate;
}
-void hb_autopassthru_print_settings( hb_job_t * job )
+int hb_audio_samplerate_get_from_name(const char *name)
{
- int i, codec_len;
- char *mask = NULL, *tmp;
- const char *fallback = NULL;
- for( i = 0; i < hb_audio_encoders_count; i++ )
+ 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)
{
- if( ( hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG ) &&
- ( hb_audio_encoders[i].encoder != HB_ACODEC_AUTO_PASS ) &&
- ( hb_audio_encoders[i].encoder & job->acodec_copy_mask ) )
- {
- if( mask )
- {
- tmp = hb_strncat_dup( mask, ", ", 2 );
- if( tmp )
- {
- free( mask );
- mask = tmp;
- }
- }
- // passthru name without " Passthru"
- codec_len = strlen( hb_audio_encoders[i].human_readable_name ) - 9;
- tmp = hb_strncat_dup( mask, hb_audio_encoders[i].human_readable_name, codec_len );
- if( tmp )
- {
- free( mask );
- mask = tmp;
- }
- }
- else if( !( hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG ) &&
- ( hb_audio_encoders[i].encoder == job->acodec_fallback ) )
+ return i;
+ }
+
+ for (i = 0; i < hb_audio_rates_count; i++)
+ {
+ if (!strcasecmp(hb_audio_rates[i].name, name))
{
- fallback = hb_audio_encoders[i].human_readable_name;
+ return hb_audio_rates[i].rate;
}
}
- if( !mask )
- hb_log( "Auto Passthru: no codecs allowed" );
- else
- hb_log( "Auto Passthru: allowed codecs are %s", mask );
- if( !fallback )
- hb_log( "Auto Passthru: no valid fallback specified" );
- else
- hb_log( "Auto Passthru: fallback is %s", fallback );
+
+fail:
+ return -1;
}
-int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer )
+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)
+ goto fail;
+
int i;
- int out_codec = ( copy_mask & in_codec ) | HB_ACODEC_PASS_FLAG;
- // sanitize fallback encoder and selected passthru
- // note: invalid fallbacks are caught in hb_autopassthru_apply_settings
- for( i = 0; i < hb_audio_encoders_count; i++ )
+ for (i = 0; i < hb_audio_rates_count; i++)
{
- if( ( hb_audio_encoders[i].encoder == fallback ) &&
- !( hb_audio_encoders[i].muxers & muxer ) )
+ if (hb_audio_rates[i].rate == samplerate)
{
- // fallback not possible with current muxer
- // use the default audio encoder instead
- fallback = hb_get_default_audio_encoder(muxer);
- break;
+ return hb_audio_rates[i].name;
}
}
- for( i = 0; i < hb_audio_encoders_count; i++ )
- {
- if( ( hb_audio_encoders[i].encoder == out_codec ) &&
- !( hb_audio_encoders[i].muxers & muxer ) )
- {
- // selected passthru not possible with current muxer
- out_codec = fallback;
- break;
- }
- }
- if( !( out_codec & HB_ACODEC_PASS_MASK ) )
- return fallback;
- return out_codec;
+
+fail:
+ return NULL;
}
-int hb_get_default_audio_encoder(int muxer)
+const hb_rate_t* hb_audio_samplerate_get_next(const hb_rate_t *last)
{
-#ifndef __APPLE__
- if (muxer == HB_MUX_MKV)
+ if (last == NULL)
{
- return HB_ACODEC_LAME;
+ return &hb_audio_rates[0];
}
-#endif
- return hb_audio_encoders[0].encoder;
+ if (last < &hb_audio_rates[0] ||
+ last >= &hb_audio_rates[hb_audio_rates_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
}
// Given an input bitrate, find closest match in the set of allowed bitrates
-int hb_find_closest_audio_bitrate(int bitrate)
+static int hb_audio_bitrate_find_closest(int bitrate)
{
// Check if bitrate mode was disabled
if (bitrate <= 0)
return bitrate;
- int ii, result;
// result is highest rate if none found during search.
// rate returned will always be <= rate asked for.
- result = hb_audio_bitrates[0].rate;
- for (ii = hb_audio_bitrates_count - 1; ii > 0; ii--)
+ int i, result = hb_audio_bitrates[0].rate;
+ for (i = hb_audio_bitrates_count - 1; i > 0; i--)
{
- if (bitrate >= hb_audio_bitrates[ii].rate)
+ if (bitrate >= hb_audio_bitrates[i].rate)
{
- result = hb_audio_bitrates[ii].rate;
+ result = hb_audio_bitrates[i].rate;
break;
}
}
return result;
}
-/* Get the bitrate low and high limits for a codec/samplerate/mixdown triplet.
+// Given an input bitrate, sanitize it.
+// Check low and high limits and make sure it is in the set of allowed bitrates.
+int hb_audio_bitrate_get_best(uint32_t codec, int bitrate, int samplerate,
+ int mixdown)
+{
+ int low, high;
+ hb_audio_bitrate_get_limits(codec, samplerate, mixdown, &low, &high);
+ if (bitrate > high)
+ bitrate = high;
+ if (bitrate < low)
+ bitrate = low;
+ return hb_audio_bitrate_find_closest(bitrate);
+}
-Encoder 1.0 channel 2.0 channels 5.1 channels 6.1 channels 7.1 channels
---------------------------------------------------------------------------------------
-
-faac
-----
-supported samplerates: 8 - 48 kHz
-libfaac/util.c defines the bitrate limits:
-MinBitrate() -> 8000 bps (per channel, incl. LFE).
-MaxBitrate() -> (6144 * samplerate / 1024) bps (per channel, incl. LFE).
-But output bitrates don't go as high as the theoretical maximums:
-12 kHz 43 (72) 87 (144) 260 (432) 303 (504) 342 (576)
-24 kHz 87 (144) 174 (288) 514 (864) 595 (1008) 669 (1152)
-48 kHz 174 (288) 347 (576) 970 (1728) 1138 (2016) 1287 (2304)
-Also, faac isn't a great encoder, so you don't want to allow too low a bitrate.
-Limits: minimum of 32 Kbps per channel
- maximum of 192 Kbps per channel at 32-48 kHz, adjusted for sr_shift
-
-
-ffaac
------
-supported samplerates: 8 - 48 kHz
-libavcodec/aacenc.c defines a maximum bitrate:
--> 6144 * samplerate / 1024 bps (per channel, incl. LFE).
-But output bitrates don't go as high as the theoretical maximums:
-12 kHz 61 (72) 123 (144)
-24 kHz 121 (144) 242 (288)
-48 kHz 236 (288) 472 (576)
-Also, ffaac isn't a great encoder, so you don't want to allow too low a bitrate.
-Limits: minimum of 32 Kbps per channel
- maximum of 192 Kbps per channel at 32 kHz, adjusted for sr_shift
- maximum of 256 Kbps per channel at 44.1-48 kHz, adjusted for sr_shift
-
-vorbis
-------
-supported samplerates: 8 - 48 kHz
-lib/modes/setup_*.h provides a range of allowed bitrates for various configurations.
-for each samplerate, the highest minimums and lowest maximums are:
- 8 kHz Minimum 8 Kbps, maximum 32 Kbps (per channel, incl. LFE).
-12 kHz Minimum 14 Kbps, maximum 44 Kbps (per channel, incl. LFE).
-16 kHz Minimum 16 Kbps, maximum 86 Kbps (per channel, incl. LFE).
-24 kHz Minimum 22 Kbps, maximum 86 Kbps (per channel, incl. LFE).
-32 kHz Minimum 26 Kbps, maximum 190 Kbps (per channel, incl. LFE).
-48 kHz Minimum 28 Kbps, maximum 240 Kbps (per channel, incl. LFE).
-Limits: minimum of 14/22/28 Kbps per channel (8-12, 16-24, 32-48 kHz)
- maximum of 32/86/190/240 Kbps per channel (8-12, 16-24, 32, 44.1-48 kHz)
-
-lame
-----
-supported samplerates: 8 - 48 kHz
-lame_init_params() allows the following bitrates:
-12 kHz Minimum 8 Kbps, maximum 64 Kbps
-24 kHz Minimum 8 Kbps, maximum 160 Kbps
-48 kHz Minimum 32 Kbps, maximum 320 Kbps
-Limits: minimum of 8/8/32 Kbps (8-12, 16-24, 32-48 kHz)
- maximum of 64/160/320 Kbps (8-12, 16-24, 32-48 kHz)
-
-ffac3
------
-supported samplerates: 32 - 48 kHz (< 32 kHz disabled for compatibility reasons)
-Dolby's encoder has a min. of 224 Kbps for 5 full-bandwidth channels (5.0, 5.1)
-The maximum AC3 bitrate is 640 Kbps
-Limits: minimum of 224/5 Kbps per full-bandwidth channel, maximum of 640 Kbps
-
-ca_aac
-------
-supported samplerates: 8 - 48 kHz
-Core Audio API provides a range of allowed bitrates:
- 8 kHz 8 - 24 16 - 48 40 - 112 48 - 144 56 - 160
-12 kHz 12 - 32 24 - 64 64 - 160 72 - 192 96 - 224
-16 kHz 12 - 48 24 - 96 64 - 224 72 - 288 96 - 320
-24 kHz 16 - 64 32 - 128 80 - 320 96 - 384 112 - 448
-32 kHz 24 - 96 48 - 192 128 - 448 144 - 576 192 - 640
-48 kHz 32 - 256 64 - 320 160 - 768 192 - 960 224 - 960
-Limits:
- 8 kHz -> minimum of 8 Kbps and maximum of 24 Kbps per full-bandwidth channel
-12 kHz -> minimum of 12 Kbps and maximum of 32 Kbps per full-bandwidth channel
-16 kHz -> minimum of 12 Kbps and maximum of 48 Kbps per full-bandwidth channel
-24 kHz -> minimum of 16 Kbps and maximum of 64 Kbps per full-bandwidth channel
-32 kHz -> minimum of 24 Kbps and maximum of 96 Kbps per full-bandwidth channel
-48 kHz -> minimum of 32 Kbps and maximum of 160 Kbps per full-bandwidth channel
-48 kHz -> maximum of +96 Kbps for Mono
-Note: encCoreAudioInit() will sanitize any mistake made here.
-
-ca_haac
--------
-supported samplerates: 32 - 48 kHz
-Core Audio API provides a range of allowed bitrates:
-32 kHz 12 - 40 24 - 80 64 - 192 N/A 96 - 256
-48 kHz 16 - 40 32 - 80 80 - 192 N/A 112 - 256
-Limits: minimum of 12 Kbps per full-bandwidth channel (<= 32 kHz)
- minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz)
- maximum of 40 Kbps per full-bandwidth channel
-Note: encCoreAudioInit() will sanitize any mistake made here.
-
-fdk_aac
--------
-supported samplerates: 8 - 48 kHz
-libfdk limits the bitrate to the following values:
- 8 kHz 48 96 240
-12 kHz 72 144 360
-16 kHz 96 192 480
-24 kHz 144 288 720
-32 kHz 192 384 960
-48 kHz 288 576 1440
-Limits: minimum of samplerate * 2/3 Kbps per full-bandwidth channel (see ca_aac)
- maximum of samplerate * 6.0 Kbps per full-bandwidth channel
-
-fdk_haac
---------
-supported samplerates: 16 - 48 kHz
-libfdk limits the bitrate to the following values:
-16 kHz 8 - 48 16 - 96 45 - 199
-24 kHz 8 - 63 16 - 127 45 - 266
-32 kHz 8 - 63 16 - 127 45 - 266
-48 kHz 12 - 63 16 - 127 50 - 266
-Limits: minimum of 12 Kbps per full-bandwidth channel (<= 32 kHz) (see ca_haac)
- minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz) (see ca_haac)
- maximum of 48, 96 or 192 Kbps (1.0, 2.0, 5.1) (<= 16 kHz)
- maximum of 64, 128 or 256 Kbps (1.0, 2.0, 5.1) ( > 16 kHz)
-*/
-
-void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown,
- int *low, int *high)
+// Get the default bitrate for a given codec/samplerate/mixdown triplet.
+int hb_audio_bitrate_get_default(uint32_t codec, int samplerate, int mixdown)
{
- if (codec & HB_ACODEC_PASS_FLAG)
+ if ((codec & HB_ACODEC_PASS_FLAG) || !(codec & HB_ACODEC_MASK))
+ goto fail;
+
+ int bitrate, nchannels, sr_shift;
+ /* full-bandwidth channels, sr_shift */
+ nchannels = (hb_mixdown_get_discrete_channel_count(mixdown) -
+ hb_mixdown_get_low_freq_channel_count(mixdown));
+ hb_audio_samplerate_get_best(codec, samplerate, &sr_shift);
+
+ switch (codec)
{
- // Bitrates don't apply to passthrough audio, but may apply if we
- // fallback to an encoder when the source can't be passed through.
- *low = hb_audio_bitrates[0].rate;
- *high = hb_audio_bitrates[hb_audio_bitrates_count-1].rate;
- return;
+ case HB_ACODEC_FFFLAC:
+ case HB_ACODEC_FFFLAC24:
+ goto fail;
+
+ // 96, 224, 640 Kbps
+ case HB_ACODEC_AC3:
+ bitrate = (nchannels * 128) - (32 * (nchannels < 5));
+ break;
+
+ case HB_ACODEC_CA_HAAC:
+ case HB_ACODEC_FDK_HAAC:
+ bitrate = nchannels * 32;
+ break;
+
+ default:
+ bitrate = nchannels * 80;
+ break;
}
+ // sample_rate adjustment
+ bitrate >>= sr_shift;
+ return hb_audio_bitrate_get_best(codec, bitrate, samplerate, mixdown);
+
+fail:
+ return -1;
+}
+/* Get the bitrate low and high limits for a codec/samplerate/mixdown triplet.
+ *
+ * Encoder 1.0 channel 2.0 channels 5.1 channels 6.1 channels 7.1 channels
+ * --------------------------------------------------------------------------------------
+ *
+ * faac
+ * ----
+ * supported samplerates: 8 - 48 kHz
+ * libfaac/util.c defines the bitrate limits:
+ * MinBitrate() -> 8000 bps (per channel, incl. LFE).
+ * MaxBitrate() -> (6144 * samplerate / 1024) bps (per channel, incl. LFE).
+ * But output bitrates don't go as high as the theoretical maximums:
+ * 12 kHz 43 (72) 87 (144) 260 (432) 303 (504) 342 (576)
+ * 24 kHz 87 (144) 174 (288) 514 (864) 595 (1008) 669 (1152)
+ * 48 kHz 174 (288) 347 (576) 970 (1728) 1138 (2016) 1287 (2304)
+ * Also, faac isn't a great encoder, so you don't want to allow too low a bitrate.
+ * Limits: minimum of 32 Kbps per channel
+ * maximum of 192 Kbps per channel at 32-48 kHz, adjusted for sr_shift
+ *
+ *
+ * ffaac
+ * -----
+ * supported samplerates: 8 - 48 kHz
+ * libavcodec/aacenc.c defines a maximum bitrate:
+ * -> 6144 * samplerate / 1024 bps (per channel, incl. LFE).
+ * But output bitrates don't go as high as the theoretical maximums:
+ * 12 kHz 61 (72) 123 (144)
+ * 24 kHz 121 (144) 242 (288)
+ * 48 kHz 236 (288) 472 (576)
+ * Also, ffaac isn't a great encoder, so you don't want to allow too low a bitrate.
+ * Limits: minimum of 32 Kbps per channel
+ * maximum of 192 Kbps per channel at 32 kHz, adjusted for sr_shift
+ * maximum of 256 Kbps per channel at 44.1-48 kHz, adjusted for sr_shift
+ *
+ * vorbis
+ * ------
+ * supported samplerates: 8 - 48 kHz
+ * lib/modes/setup_*.h provides a range of allowed bitrates for various configurations.
+ * for each samplerate, the highest minimums and lowest maximums are:
+ * 8 kHz Minimum 8 Kbps, maximum 32 Kbps (per channel, incl. LFE).
+ * 12 kHz Minimum 14 Kbps, maximum 44 Kbps (per channel, incl. LFE).
+ * 16 kHz Minimum 16 Kbps, maximum 86 Kbps (per channel, incl. LFE).
+ * 24 kHz Minimum 22 Kbps, maximum 86 Kbps (per channel, incl. LFE).
+ * 32 kHz Minimum 26 Kbps, maximum 190 Kbps (per channel, incl. LFE).
+ * 48 kHz Minimum 28 Kbps, maximum 240 Kbps (per channel, incl. LFE).
+ * Limits: minimum of 14/22/28 Kbps per channel (8-12, 16-24, 32-48 kHz)
+ * maximum of 32/86/190/240 Kbps per channel (8-12, 16-24, 32, 44.1-48 kHz)
+ *
+ * lame
+ * ----
+ * supported samplerates: 8 - 48 kHz
+ * lame_init_params() allows the following bitrates:
+ * 12 kHz Minimum 8 Kbps, maximum 64 Kbps
+ * 24 kHz Minimum 8 Kbps, maximum 160 Kbps
+ * 48 kHz Minimum 32 Kbps, maximum 320 Kbps
+ * Limits: minimum of 8/8/32 Kbps (8-12, 16-24, 32-48 kHz)
+ * maximum of 64/160/320 Kbps (8-12, 16-24, 32-48 kHz)
+ *
+ * ffac3
+ * -----
+ * supported samplerates: 32 - 48 kHz (< 32 kHz disabled for compatibility reasons)
+ * Dolby's encoder has a min. of 224 Kbps for 5 full-bandwidth channels (5.0, 5.1)
+ * The maximum AC3 bitrate is 640 Kbps
+ * Limits: minimum of 224/5 Kbps per full-bandwidth channel, maximum of 640 Kbps
+ *
+ * ca_aac
+ * ------
+ * supported samplerates: 8 - 48 kHz
+ * Core Audio API provides a range of allowed bitrates:
+ * 8 kHz 8 - 24 16 - 48 40 - 112 48 - 144 56 - 160
+ * 12 kHz 12 - 32 24 - 64 64 - 160 72 - 192 96 - 224
+ * 16 kHz 12 - 48 24 - 96 64 - 224 72 - 288 96 - 320
+ * 24 kHz 16 - 64 32 - 128 80 - 320 96 - 384 112 - 448
+ * 32 kHz 24 - 96 48 - 192 128 - 448 144 - 576 192 - 640
+ * 48 kHz 32 - 256 64 - 320 160 - 768 192 - 960 224 - 960
+ * Limits:
+ * 8 kHz -> minimum of 8 Kbps and maximum of 24 Kbps per full-bandwidth channel
+ * 12 kHz -> minimum of 12 Kbps and maximum of 32 Kbps per full-bandwidth channel
+ * 16 kHz -> minimum of 12 Kbps and maximum of 48 Kbps per full-bandwidth channel
+ * 24 kHz -> minimum of 16 Kbps and maximum of 64 Kbps per full-bandwidth channel
+ * 32 kHz -> minimum of 24 Kbps and maximum of 96 Kbps per full-bandwidth channel
+ * 48 kHz -> minimum of 32 Kbps and maximum of 160 Kbps per full-bandwidth channel
+ * 48 kHz -> maximum of +96 Kbps for Mono
+ * Note: encCoreAudioInit() will sanitize any mistake made here.
+ *
+ * ca_haac
+ * -------
+ * supported samplerates: 32 - 48 kHz
+ * Core Audio API provides a range of allowed bitrates:
+ * 32 kHz 12 - 40 24 - 80 64 - 192 N/A 96 - 256
+ * 48 kHz 16 - 40 32 - 80 80 - 192 N/A 112 - 256
+ * Limits: minimum of 12 Kbps per full-bandwidth channel (<= 32 kHz)
+ * minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz)
+ * maximum of 40 Kbps per full-bandwidth channel
+ * Note: encCoreAudioInit() will sanitize any mistake made here.
+ *
+ * fdk_aac
+ * -------
+ * supported samplerates: 8 - 48 kHz
+ * libfdk limits the bitrate to the following values:
+ * 8 kHz 48 96 240
+ * 12 kHz 72 144 360
+ * 16 kHz 96 192 480
+ * 24 kHz 144 288 720
+ * 32 kHz 192 384 960
+ * 48 kHz 288 576 1440
+ * Limits: minimum of samplerate * 2/3 Kbps per full-bandwidth channel (see ca_aac)
+ * maximum of samplerate * 6.0 Kbps per full-bandwidth channel
+ *
+ * fdk_haac
+ * --------
+ * supported samplerates: 16 - 48 kHz
+ * libfdk limits the bitrate to the following values:
+ * 16 kHz 8 - 48 16 - 96 45 - 199
+ * 24 kHz 8 - 63 16 - 127 45 - 266
+ * 32 kHz 8 - 63 16 - 127 45 - 266
+ * 48 kHz 12 - 63 16 - 127 50 - 266
+ * Limits: minimum of 12 Kbps per full-bandwidth channel (<= 32 kHz) (see ca_haac)
+ * minimum of 16 Kbps per full-bandwidth channel ( > 32 kHz) (see ca_haac)
+ * maximum of 48, 96 or 192 Kbps (1.0, 2.0, 5.1) (<= 16 kHz)
+ * maximum of 64, 128 or 256 Kbps (1.0, 2.0, 5.1) ( > 16 kHz)
+ */
+void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown,
+ int *low, int *high)
+{
/* samplerate, sr_shift */
int sr_shift;
- samplerate = hb_get_best_samplerate(codec, samplerate, &sr_shift);
+ samplerate = hb_audio_samplerate_get_best(codec, samplerate, &sr_shift);
/* LFE, full-bandwidth channels */
int lfe_count, nchannels;
@@ -710,32 +564,37 @@ void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown,
*low = nchannels * 8;
*high = nchannels * 24;
break;
+
case 11025:
case 12000:
*low = nchannels * 12;
*high = nchannels * 32;
break;
+
case 16000:
*low = nchannels * 12;
*high = nchannels * 48;
break;
+
case 22050:
case 24000:
*low = nchannels * 16;
*high = nchannels * 64;
break;
+
case 32000:
*low = nchannels * 24;
*high = nchannels * 96;
break;
+
case 44100:
case 48000:
default:
*low = nchannels * 32;
*high = nchannels * (160 + (96 * (nchannels == 1)));
break;
- }
- } break;
+ } break;
+ }
case HB_ACODEC_CA_HAAC:
*low = nchannels * (12 + (4 * (samplerate >= 44100)));
@@ -781,69 +640,33 @@ void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown,
( 50 * (samplerate >= 44100)));
break;
+ // 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;
+ *high = hb_audio_bitrates[hb_audio_bitrates_count - 1].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;
-}
-
-// Given an input bitrate, sanitize it.
-// Check low and high limits and make sure it is in the set of allowed bitrates.
-int hb_get_best_audio_bitrate(uint32_t codec, int bitrate, int samplerate,
- int mixdown)
-{
- int low, high;
- hb_get_audio_bitrate_limits(codec, samplerate, mixdown, &low, &high);
- if (bitrate > high)
- bitrate = high;
- if (bitrate < low)
- bitrate = low;
- return hb_find_closest_audio_bitrate(bitrate);
+ if (*high > hb_audio_bitrates[hb_audio_bitrates_count - 1].rate)
+ *high = hb_audio_bitrates[hb_audio_bitrates_count - 1].rate;
}
-// Get the default bitrate for a given codec/samplerate/mixdown triplet.
-int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown)
+const hb_rate_t* hb_audio_bitrate_get_next(const hb_rate_t *last)
{
- if (codec & HB_ACODEC_PASS_FLAG)
+ if (last == NULL)
{
- return -1;
+ return &hb_audio_bitrates[0];
}
-
- int bitrate, nchannels, sr_shift;
- /* full-bandwidth channels, sr_shift */
- nchannels = (hb_mixdown_get_discrete_channel_count(mixdown) -
- hb_mixdown_get_low_freq_channel_count(mixdown));
- hb_get_best_samplerate(codec, samplerate, &sr_shift);
-
- switch (codec)
+ if (last < &hb_audio_bitrates[0] ||
+ last >= &hb_audio_bitrates[hb_audio_bitrates_count - 1])
{
- case HB_ACODEC_FFFLAC:
- case HB_ACODEC_FFFLAC24:
- return -1;
-
- // 96, 224, 640 Kbps
- case HB_ACODEC_AC3:
- bitrate = (nchannels * 128) - (32 * (nchannels < 5));
- break;
-
- case HB_ACODEC_CA_HAAC:
- case HB_ACODEC_FDK_HAAC:
- bitrate = nchannels * 32;
- break;
-
- default:
- bitrate = nchannels * 80;
- break;
+ return NULL;
}
- // sample_rate adjustment
- bitrate >>= sr_shift;
- return hb_get_best_audio_bitrate(codec, bitrate, samplerate, mixdown);
+ return last + 1;
}
// Get limits and hints for the UIs.
@@ -851,47 +674,47 @@ int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown)
// granularity sets the minimum step increments that should be used
// (it's ok to round up to some nice multiple if you like)
//
-// direction says whether 'low' limit is highest or lowest
+// direction says whether 'low' limit is highest or lowest
// quality (direction 0 == lowest value is worst quality)
-void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high,
+void hb_audio_quality_get_limits(uint32_t codec, float *low, float *high,
float *granularity, int *direction)
{
switch (codec)
{
case HB_ACODEC_LAME:
- *direction = 1;
+ *direction = 1;
*granularity = 0.5;
- *low = 0.;
- *high = 10.0;
+ *low = 0.;
+ *high = 10.;
break;
case HB_ACODEC_VORBIS:
- *direction = 0;
+ *direction = 0;
*granularity = 0.5;
- *low = -2.0;
- *high = 10.0;
+ *low = -2.;
+ *high = 10.;
break;
case HB_ACODEC_CA_AAC:
- *direction = 0;
- *granularity = 9;
- *low = 1.;
- *high = 127.0;
+ *direction = 0;
+ *granularity = 9.;
+ *low = 1.;
+ *high = 127.;
break;
default:
- *direction = 0;
- *granularity = 1;
+ *direction = 0;
+ *granularity = 1.;
*low = *high = HB_INVALID_AUDIO_QUALITY;
break;
}
}
-float hb_get_best_audio_quality(uint32_t codec, float quality)
+float hb_audio_quality_get_best(uint32_t codec, float quality)
{
- float low, high, granularity;
int direction;
- hb_get_audio_quality_limits(codec, &low, &high, &granularity, &direction);
+ float low, high, granularity;
+ hb_audio_quality_get_limits(codec, &low, &high, &granularity, &direction);
if (quality > high)
quality = high;
if (quality < low)
@@ -899,28 +722,22 @@ float hb_get_best_audio_quality(uint32_t codec, float quality)
return quality;
}
-float hb_get_default_audio_quality( uint32_t codec )
+float hb_audio_quality_get_default(uint32_t codec)
{
- float quality;
- switch( codec )
+ switch (codec)
{
case HB_ACODEC_LAME:
- quality = 2.;
- break;
+ return 2.;
case HB_ACODEC_VORBIS:
- quality = 5.;
- break;
+ return 5.;
case HB_ACODEC_CA_AAC:
- quality = 91.;
- break;
+ return 91.;
default:
- quality = HB_INVALID_AUDIO_QUALITY;
- break;
+ return HB_INVALID_AUDIO_QUALITY;
}
- return quality;
}
// Get limits and hints for the UIs.
@@ -928,41 +745,41 @@ float hb_get_default_audio_quality( uint32_t codec )
// granularity sets the minimum step increments that should be used
// (it's ok to round up to some nice multiple if you like)
//
-// direction says whether 'low' limit is highest or lowest
+// direction says whether 'low' limit is highest or lowest
// compression level (direction 0 == lowest value is worst compression level)
-void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high,
+void hb_audio_compression_get_limits(uint32_t codec, float *low, float *high,
float *granularity, int *direction)
{
switch (codec)
{
case HB_ACODEC_FFFLAC:
case HB_ACODEC_FFFLAC24:
- *direction = 0;
- *granularity = 1;
- *high = 12;
- *low = 0;
+ *direction = 0;
+ *granularity = 1.;
+ *high = 12.;
+ *low = 0.;
break;
-
+
case HB_ACODEC_LAME:
- *direction = 1;
- *granularity = 1;
- *high = 9;
- *low = 0;
+ *direction = 1;
+ *granularity = 1.;
+ *high = 9.;
+ *low = 0.;
break;
-
+
default:
- *direction = 0;
- *granularity = 1;
- *low = *high = -1;
+ *direction = 0;
+ *granularity = 1.;
+ *low = *high = -1.;
break;
}
}
-float hb_get_best_audio_compression(uint32_t codec, float compression)
+float hb_audio_compression_get_best(uint32_t codec, float compression)
{
- float low, high, granularity;
int direction;
- hb_get_audio_compression_limits(codec, &low, &high, &granularity, &direction);
+ float low, high, granularity;
+ hb_audio_compression_get_limits(codec, &low, &high, &granularity, &direction);
if( compression > high )
compression = high;
if( compression < low )
@@ -970,7 +787,7 @@ float hb_get_best_audio_compression(uint32_t codec, float compression)
return compression;
}
-float hb_get_default_audio_compression(uint32_t codec)
+float hb_audio_compression_get_default(uint32_t codec)
{
switch (codec)
{
@@ -986,7 +803,226 @@ float hb_get_default_audio_compression(uint32_t codec)
}
}
-int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown)
+int hb_audio_dither_get_default()
+{
+ // "auto"
+ return hb_audio_dithers[0].method;
+}
+
+int hb_audio_dither_get_default_method()
+{
+ /*
+ * input could be s16 (possibly already dithered) converted to flt, so
+ * let's use a "low-risk" dither algorithm (standard triangular).
+ */
+ return AV_RESAMPLE_DITHER_TRIANGULAR;
+}
+
+int hb_audio_dither_is_supported(uint32_t codec)
+{
+ // encoder's input sample format must be s16(p)
+ switch (codec)
+ {
+ case HB_ACODEC_FFFLAC:
+ case HB_ACODEC_FDK_AAC:
+ case HB_ACODEC_FDK_HAAC:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+int hb_audio_dither_get_from_name(const char *name)
+{
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ int i;
+ for ( i = 0; i < hb_audio_dithers_count; i++)
+ {
+ if (!strcasecmp(hb_audio_dithers[i].short_name, name))
+ {
+ return hb_audio_dithers[i].method;
+ }
+ }
+
+fail:
+ return hb_audio_dither_get_default();
+}
+
+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)
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_dithers_count; i++)
+ {
+ if (hb_audio_dithers[i].method == method)
+ {
+ return hb_audio_dithers[i].description;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const hb_dither_t* hb_audio_dither_get_next(const hb_dither_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_audio_dithers[0];
+ }
+ if (last < &hb_audio_dithers[0] ||
+ last >= &hb_audio_dithers[hb_audio_dithers_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout)
+{
+ return (hb_mixdown_has_codec_support(mixdown, codec) &&
+ hb_mixdown_has_remix_support(mixdown, layout));
+}
+
+int hb_mixdown_has_codec_support(int mixdown, uint32_t codec)
+{
+ // Passthru, only "None" mixdown is supported
+ if (codec & HB_ACODEC_PASS_FLAG)
+ return (mixdown == HB_AMIXDOWN_NONE);
+
+ // Not passthru, "None" mixdown never supported
+ if (mixdown == HB_AMIXDOWN_NONE)
+ return 0;
+
+ switch (codec)
+ {
+ case HB_ACODEC_VORBIS:
+ case HB_ACODEC_FFFLAC:
+ case HB_ACODEC_FFFLAC24:
+ return (mixdown <= HB_AMIXDOWN_7POINT1);
+
+ case HB_ACODEC_LAME:
+ case HB_ACODEC_FFAAC:
+ return (mixdown <= HB_AMIXDOWN_DOLBYPLII);
+
+ case HB_ACODEC_FAAC:
+ case HB_ACODEC_CA_AAC:
+ case HB_ACODEC_CA_HAAC:
+ return ((mixdown <= HB_AMIXDOWN_5POINT1) ||
+ (mixdown == HB_AMIXDOWN_5_2_LFE));
+
+ default:
+ return (mixdown <= HB_AMIXDOWN_5POINT1);
+ }
+}
+
+int hb_mixdown_has_remix_support(int mixdown, uint64_t layout)
+{
+ switch (mixdown)
+ {
+ // stereo + front left/right of center
+ case HB_AMIXDOWN_5_2_LFE:
+ return ((layout & AV_CH_FRONT_LEFT_OF_CENTER) &&
+ (layout & AV_CH_FRONT_RIGHT_OF_CENTER) &&
+ (layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO);
+
+ // 7.0 or better
+ case HB_AMIXDOWN_7POINT1:
+ return ((layout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0);
+
+ // 6.0 or better
+ case HB_AMIXDOWN_6POINT1:
+ return ((layout & AV_CH_LAYOUT_7POINT0) == AV_CH_LAYOUT_7POINT0 ||
+ (layout & AV_CH_LAYOUT_6POINT0) == AV_CH_LAYOUT_6POINT0 ||
+ (layout & AV_CH_LAYOUT_HEXAGONAL) == AV_CH_LAYOUT_HEXAGONAL);
+
+ // stereo + either of front center, side or back left/right, back center
+ case HB_AMIXDOWN_5POINT1:
+ return ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 ||
+ (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 ||
+ (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD ||
+ (layout & AV_CH_LAYOUT_SURROUND) == AV_CH_LAYOUT_SURROUND);
+
+ // stereo + either of side or back left/right, back center
+ // also, allow Dolby Surrounbd output if the input is already Dolby
+ case HB_AMIXDOWN_DOLBY:
+ case HB_AMIXDOWN_DOLBYPLII:
+ return ((layout & AV_CH_LAYOUT_2_1) == AV_CH_LAYOUT_2_1 ||
+ (layout & AV_CH_LAYOUT_2_2) == AV_CH_LAYOUT_2_2 ||
+ (layout & AV_CH_LAYOUT_QUAD) == AV_CH_LAYOUT_QUAD ||
+ (layout == AV_CH_LAYOUT_STEREO_DOWNMIX &&
+ mixdown == HB_AMIXDOWN_DOLBY));
+
+ // more than 1 channel
+ case HB_AMIXDOWN_STEREO:
+ return (av_get_channel_layout_nb_channels(layout) > 1);
+
+ // regular stereo (not Dolby)
+ case HB_AMIXDOWN_LEFT:
+ case HB_AMIXDOWN_RIGHT:
+ return (layout == AV_CH_LAYOUT_STEREO);
+
+ // mono remix always supported
+ // HB_AMIXDOWN_NONE always supported (for Passthru)
+ case HB_AMIXDOWN_MONO:
+ case HB_AMIXDOWN_NONE:
+ return 1;
+
+ // unknown mixdown, should never happen
+ default:
+ return 0;
+ }
+}
+
+int hb_mixdown_get_discrete_channel_count(int amixdown)
+{
+ switch (amixdown)
+ {
+ case HB_AMIXDOWN_5_2_LFE:
+ case HB_AMIXDOWN_7POINT1:
+ return 8;
+
+ case HB_AMIXDOWN_6POINT1:
+ return 7;
+
+ case HB_AMIXDOWN_5POINT1:
+ return 6;
+
+ case HB_AMIXDOWN_MONO:
+ case HB_AMIXDOWN_LEFT:
+ case HB_AMIXDOWN_RIGHT:
+ return 1;
+
+ case HB_AMIXDOWN_NONE:
+ return 0;
+
+ default:
+ return 2;
+ }
+}
+
+int hb_mixdown_get_low_freq_channel_count(int amixdown)
+{
+ switch (amixdown)
+ {
+ case HB_AMIXDOWN_5POINT1:
+ case HB_AMIXDOWN_6POINT1:
+ case HB_AMIXDOWN_7POINT1:
+ case HB_AMIXDOWN_5_2_LFE:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+int hb_mixdown_get_best(uint32_t codec, uint64_t layout, int mixdown)
{
// Passthru, only "None" mixdown is supported
if (codec & HB_ACODEC_PASS_FLAG)
@@ -996,17 +1032,17 @@ int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown)
if (mixdown == HB_INVALID_AMIXDOWN)
mixdown = hb_audio_mixdowns[hb_audio_mixdowns_count - 1].amixdown;
- int ii;
// test all mixdowns until an authorized, supported mixdown is found
// stop before we reach the "worst" non-None mixdown (index == 1)
- for (ii = hb_audio_mixdowns_count - 1; ii > 1; ii--)
- if (hb_audio_mixdowns[ii].amixdown <= mixdown &&
- hb_mixdown_is_supported(hb_audio_mixdowns[ii].amixdown, codec, layout))
+ 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[ii].amixdown;
+ return hb_audio_mixdowns[i].amixdown;
}
-int hb_get_default_mixdown(uint32_t codec, uint64_t layout)
+int hb_mixdown_get_default(uint32_t codec, uint64_t layout)
{
int mixdown;
switch (codec)
@@ -1016,69 +1052,641 @@ int hb_get_default_mixdown(uint32_t codec, uint64_t layout)
case HB_ACODEC_FFFLAC24:
mixdown = HB_AMIXDOWN_7POINT1;
break;
+
// the AC3 encoder defaults to the best mixdown up to 5.1
case HB_ACODEC_AC3:
mixdown = HB_AMIXDOWN_5POINT1;
break;
+
// other encoders default to the best mixdown up to DPLII
default:
mixdown = HB_AMIXDOWN_DOLBYPLII;
break;
}
+
// return the best available mixdown up to the selected default
- return hb_get_best_mixdown(codec, layout, mixdown);
+ return hb_mixdown_get_best(codec, layout, mixdown);
}
-int hb_get_best_samplerate(uint32_t codec, int samplerate, int *sr_shift)
+int hb_mixdown_get_from_name(const char *name)
{
- int ii, best_samplerate, samplerate_shift;
- if ((samplerate < 32000) &&
- (codec == HB_ACODEC_CA_HAAC || codec == HB_ACODEC_AC3))
+ 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"))
{
- // ca_haac can't do samplerates < 32 kHz
- // AC-3 < 32 kHz suffers from poor hardware compatibility
- best_samplerate = 32000;
- samplerate_shift = 0;
+ return HB_AMIXDOWN_NONE;
}
- else if (samplerate < 16000 && codec == HB_ACODEC_FDK_HAAC)
+ if (!strcasecmp(name, "6-channel discrete"))
{
- // fdk_haac can't do samplerates < 16 kHz
- best_samplerate = 16000;
- samplerate_shift = 1;
+ return HB_AMIXDOWN_5POINT1;
}
- else
+
+ int i;
+ for (i = 0; i < hb_audio_mixdowns_count; i++)
{
- best_samplerate = samplerate;
- for (ii = hb_audio_rates_count - 1; ii >= 0; ii--)
+ if (!strcasecmp(hb_audio_mixdowns[i].name, name) ||
+ !strcasecmp(hb_audio_mixdowns[i].short_name, name))
{
- // valid samplerate
- if (best_samplerate == hb_audio_rates[ii].rate)
- break;
+ return hb_audio_mixdowns[i].amixdown;
+ }
+ }
- // 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)
+fail:
+ return -1;
+}
+
+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)
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_mixdowns_count; i++)
+ {
+ if (hb_audio_mixdowns[i].amixdown == mixdown)
+ {
+ return hb_audio_mixdowns[i].name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+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)
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_mixdowns_count; i++)
+ {
+ if (hb_audio_mixdowns[i].amixdown == mixdown)
+ {
+ return hb_audio_mixdowns[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_mixdown_sanitize_name(const char *name)
+{
+ return hb_mixdown_get_name(hb_mixdown_get_from_name(name));
+}
+
+const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_audio_mixdowns[0];
+ }
+ if (last < &hb_audio_mixdowns[0] ||
+ last >= &hb_audio_mixdowns[hb_audio_mixdowns_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+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++)
+ {
+ if (hb_video_encoders[i].muxers & muxer)
+ {
+ return hb_video_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+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))
+ {
+ return hb_video_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+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++)
+ {
+ if (hb_video_encoders[i].codec == encoder)
+ {
+ return hb_video_encoders[i].name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_video_encoder_get_short_name(int encoder)
+{
+ if (!(encoder & HB_VCODEC_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_video_encoders_count; i++)
+ {
+ if (hb_video_encoders[i].codec == encoder)
+ {
+ return hb_video_encoders[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_video_encoder_sanitize_name(const char *name)
+{
+ return hb_video_encoder_get_name(hb_video_encoder_get_from_name(name));
+}
+
+const hb_encoder_t* hb_video_encoder_get_next(const hb_encoder_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_video_encoders[0];
+ }
+ if (last < &hb_video_encoders[0] ||
+ last >= &hb_video_encoders[hb_video_encoders_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+// 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
+ switch (passthru)
+ {
+ case HB_ACODEC_AAC_PASS:
+#ifdef __APPLE__
+ return HB_ACODEC_CA_AAC;
+#else
+ return HB_ACODEC_FAAC;
+#endif
+
+ case HB_ACODEC_AC3_PASS:
+ return HB_ACODEC_AC3;
+
+ case HB_ACODEC_MP3_PASS:
+ return HB_ACODEC_LAME;
+
+ // 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;
+ }
+}
+
+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++)
+ {
+ // default encoder should not be passthru
+ if ((hb_audio_encoders[i].muxers & muxer) &&
+ (hb_audio_encoders[i].codec & HB_ACODEC_PASS_FLAG) == 0)
+ {
+ return hb_audio_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+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))
+ {
+ return hb_audio_encoders[i].codec;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+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++)
+ {
+ if (hb_audio_encoders[i].codec == encoder)
+ {
+ return hb_audio_encoders[i].name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_audio_encoder_get_short_name(int encoder)
+{
+ if (!(encoder & HB_ACODEC_ANY))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_audio_encoders_count; i++)
+ {
+ if (hb_audio_encoders[i].codec == encoder)
+ {
+ return hb_audio_encoders[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_audio_encoder_sanitize_name(const char *name)
+{
+ return hb_audio_encoder_get_name(hb_audio_encoder_get_from_name(name));
+}
+
+const hb_encoder_t* hb_audio_encoder_get_next(const hb_encoder_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_audio_encoders[0];
+ }
+ if (last < &hb_audio_encoders[0] ||
+ last >= &hb_audio_encoders[hb_audio_encoders_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
+}
+
+void hb_autopassthru_apply_settings(hb_job_t *job)
+{
+ hb_audio_t *audio;
+ int i, already_printed;
+ for (i = already_printed = 0; i < hb_list_count(job->list_audio);)
+ {
+ audio = hb_list_item(job->list_audio, i);
+ if (audio->config.out.codec == HB_ACODEC_AUTO_PASS)
+ {
+ if (!already_printed)
+ hb_autopassthru_print_settings(job);
+ already_printed = 1;
+ audio->config.out.codec = hb_autopassthru_get_encoder(audio->config.in.codec,
+ job->acodec_copy_mask,
+ job->acodec_fallback,
+ job->mux);
+ if (!(audio->config.out.codec & HB_ACODEC_PASS_FLAG) &&
+ !(audio->config.out.codec & HB_ACODEC_MASK))
{
- best_samplerate = hb_audio_rates[ii].rate;
- break;
+ hb_log("Auto Passthru: passthru not possible and no valid fallback specified, dropping track %d",
+ audio->config.out.track );
+ hb_list_rem(job->list_audio, audio);
+ hb_audio_close(&audio);
+ continue;
+ }
+ audio->config.out.samplerate = audio->config.in.samplerate;
+ if (!(audio->config.out.codec & HB_ACODEC_PASS_FLAG))
+ {
+ if (audio->config.out.codec == job->acodec_fallback)
+ {
+ hb_log("Auto Passthru: passthru not possible for track %d, using fallback",
+ audio->config.out.track);
+ }
+ else
+ {
+ hb_log("Auto Passthru: passthru and fallback not possible for track %d, using default encoder",
+ audio->config.out.track);
+ }
+ audio->config.out.mixdown =
+ hb_mixdown_get_default(audio->config.out.codec,
+ audio->config.in.channel_layout);
+ audio->config.out.bitrate =
+ hb_audio_bitrate_get_default(audio->config.out.codec,
+ audio->config.out.samplerate,
+ audio->config.out.mixdown );
+ audio->config.out.compression_level =
+ hb_audio_compression_get_default(audio->config.out.codec);
+ }
+ else
+ {
+ const hb_encoder_t *audio_encoder = NULL;
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
+ {
+ if (audio_encoder->codec == audio->config.out.codec)
+ {
+ hb_log("Auto Passthru: using %s for track %d",
+ audio_encoder->name,
+ audio->config.out.track);
+ break;
+ }
+ }
}
}
- /* sr_shift: 0 -> 48000, 44100, 32000 Hz
- * 1 -> 24000, 22050, 16000 Hz
- * 2 -> 12000, 11025, 8000 Hz
- *
- * also, since samplerates are sanitized downwards:
- *
- * (samplerate < 32000) implies (samplerate <= 24000)
- */
- samplerate_shift = ((best_samplerate < 16000) ? 2 :
- (best_samplerate < 32000) ? 1 : 0);
+ /* Adjust output track number, in case we removed one.
+ * Output tracks sadly still need to be in sequential order.
+ * Note: out.track starts at 1, i starts at 0 */
+ audio->config.out.track = ++i;
}
- if (sr_shift != NULL)
+}
+
+void hb_autopassthru_print_settings(hb_job_t *job)
+{
+ char *mask = NULL, *tmp;
+ const char *fallback = NULL;
+ const hb_encoder_t *audio_encoder = NULL;
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
{
- *sr_shift = samplerate_shift;
+ if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) &&
+ (audio_encoder->codec != HB_ACODEC_AUTO_PASS) &&
+ (audio_encoder->codec & job->acodec_copy_mask))
+ {
+ if (mask != NULL)
+ {
+ tmp = hb_strncat_dup(mask, ", ", 2);
+ if (tmp != NULL)
+ {
+ free(mask);
+ mask = tmp;
+ }
+ }
+ // passthru name without " Passthru"
+ tmp = hb_strncat_dup(mask, audio_encoder->name,
+ strlen(audio_encoder->name) - 9);
+ if (tmp != NULL)
+ {
+ free(mask);
+ mask = tmp;
+ }
+ }
+ else if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) == 0 &&
+ (audio_encoder->codec == job->acodec_fallback))
+ {
+ fallback = audio_encoder->name;
+ }
}
- return best_samplerate;
+ if (mask == NULL)
+ hb_log("Auto Passthru: no codecs allowed");
+ else
+ hb_log("Auto Passthru: allowed codecs are %s", mask);
+ if (fallback == NULL)
+ hb_log("Auto Passthru: no valid fallback specified");
+ else
+ hb_log("Auto Passthru: fallback is %s", fallback);
+}
+
+int hb_autopassthru_get_encoder(int in_codec, int copy_mask, int fallback,
+ int muxer)
+{
+ int i = 0;
+ const hb_encoder_t *audio_encoder = NULL;
+ int out_codec = (copy_mask & in_codec) | HB_ACODEC_PASS_FLAG;
+ // sanitize fallback encoder and selected passthru
+ // note: invalid fallbacks are caught in hb_autopassthru_apply_settings
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
+ {
+ if (audio_encoder->codec == out_codec)
+ {
+ i++;
+ if (!(audio_encoder->muxers & muxer))
+ out_codec = 0;
+ }
+ else if (audio_encoder->codec == fallback)
+ {
+ i++;
+ if (!(audio_encoder->muxers & muxer))
+ fallback = hb_audio_encoder_get_default(muxer);
+ }
+ if (i > 1)
+ {
+ break;
+ }
+ }
+ return (out_codec & HB_ACODEC_PASS_MASK) ? out_codec : fallback;
+}
+
+int hb_container_get_from_name(const char *name)
+{
+ if (name == NULL || *name == '\0')
+ goto fail;
+
+ // TODO: implement something more flexible
+ if (!strcasecmp(name, "m4v"))
+ {
+ // old CLI alternate short name for "mp4"
+ return HB_MUX_MP4;
+ }
+ if (!strcasecmp(name, "MP4 file"))
+ {
+ return HB_MUX_MP4;
+ }
+ if (!strcasecmp(name, "MKV file"))
+ {
+ return HB_MUX_MKV;
+ }
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (!strcasecmp(hb_containers[i].name, name) ||
+ !strcasecmp(hb_containers[i].short_name, name) ||
+ !strcasecmp(hb_containers[i].default_extension, name))
+ {
+ return hb_containers[i].format;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+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))
+ {
+ return hb_containers[i].format;
+ }
+ }
+
+fail:
+ return -1;
+}
+
+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++)
+ {
+ if (hb_containers[i].format == format)
+ {
+ return hb_containers[i].name;
+ }
+
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_container_get_short_name(int format)
+{
+ if (!(format & HB_MUX_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (hb_containers[i].format == format)
+ {
+ return hb_containers[i].short_name;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_container_get_default_extension(int format)
+{
+ if (!(format & HB_MUX_MASK))
+ goto fail;
+
+ int i;
+ for (i = 0; i < hb_containers_count; i++)
+ {
+ if (hb_containers[i].format == format)
+ {
+ return hb_containers[i].default_extension;
+ }
+ }
+
+fail:
+ return NULL;
+}
+
+const char* hb_container_sanitize_name(const char *name)
+{
+ return hb_container_get_name(hb_container_get_from_name(name));
+}
+
+const hb_container_t* hb_container_get_next(const hb_container_t *last)
+{
+ if (last == NULL)
+ {
+ return &hb_containers[0];
+ }
+ if (last < &hb_containers[0] ||
+ last >= &hb_containers[hb_containers_count - 1])
+ {
+ return NULL;
+ }
+ return last + 1;
}
/**********************************************************************
@@ -2336,7 +2944,7 @@ void hb_audio_config_init(hb_audio_config_t * audiocfg)
/* Initalize some sensible defaults */
audiocfg->in.track = audiocfg->out.track = 0;
- audiocfg->out.codec = hb_audio_encoders[0].encoder;
+ audiocfg->out.codec = hb_audio_encoders[0].codec;
audiocfg->out.samplerate = -1;
audiocfg->out.samples_per_frame = -1;
audiocfg->out.bitrate = -1;
@@ -2970,9 +3578,9 @@ void hb_attachment_close( hb_attachment_t **attachment )
* hb_yuv2rgb
**********************************************************************
* Converts a YCrCb pixel to an RGB pixel.
- *
+ *
* This conversion is lossy (due to rounding and clamping).
- *
+ *
* Algorithm:
* http://en.wikipedia.org/w/index.php?title=YCbCr&oldid=361987695#Technical_details
*********************************************************************/
@@ -3004,9 +3612,9 @@ int hb_yuv2rgb(int yuv)
* hb_rgb2yuv
**********************************************************************
* Converts an RGB pixel to a YCrCb pixel.
- *
+ *
* This conversion is lossy (due to rounding and clamping).
- *
+ *
* Algorithm:
* http://en.wikipedia.org/w/index.php?title=YCbCr&oldid=361987695#Technical_details
*********************************************************************/
diff --git a/libhb/common.h b/libhb/common.h
index 2951def5d..58d102c9a 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -73,6 +73,7 @@ typedef struct hb_rate_s hb_rate_t;
typedef struct hb_dither_s hb_dither_t;
typedef struct hb_mixdown_s hb_mixdown_t;
typedef struct hb_encoder_s hb_encoder_t;
+typedef struct hb_container_s hb_container_t;
typedef struct hb_job_s hb_job_t;
typedef struct hb_title_set_s hb_title_set_t;
typedef struct hb_title_s hb_title_t;
@@ -171,7 +172,7 @@ void hb_chapter_set_title(hb_chapter_t *chapter, const char *title);
struct hb_rate_s
{
- const char *string;
+ const char *name;
int rate;
};
@@ -184,7 +185,7 @@ struct hb_dither_s
struct hb_mixdown_s
{
- const char *human_readable_name;
+ const char *name;
const char *internal_name;
const char *short_name;
int amixdown;
@@ -192,10 +193,18 @@ struct hb_mixdown_s
struct hb_encoder_s
{
- const char *human_readable_name; // note: used in presets
- const char *short_name; // note: used in CLI
- int encoder; // HB_*CODEC_* define
- int muxers; // supported muxers
+ const char *name; // note: used in presets
+ const char *short_name; // note: used in CLI
+ int codec; // HB_*CODEC_* define
+ int muxers; // supported muxers
+};
+
+struct hb_container_s
+{
+ const char *name;
+ const char *short_name;
+ const char *default_extension;
+ int format;
};
struct hb_subtitle_config_s
@@ -210,77 +219,115 @@ struct hb_subtitle_config_s
int64_t offset;
};
-#define HB_VIDEO_RATE_BASE 27000000
-
-extern hb_rate_t hb_video_rates[];
-extern int hb_video_rates_count;
-extern hb_rate_t hb_audio_rates[];
-extern int hb_audio_rates_count;
-extern int hb_audio_rates_default;
-extern hb_rate_t hb_audio_bitrates[];
-extern int hb_audio_bitrates_count;
-extern hb_dither_t hb_audio_dithers[];
-extern int hb_audio_dithers_count;
-extern hb_mixdown_t hb_audio_mixdowns[];
-extern int hb_audio_mixdowns_count;
-extern hb_encoder_t hb_video_encoders[];
-extern int hb_video_encoders_count;
-extern hb_encoder_t hb_audio_encoders[];
-extern int hb_audio_encoders_count;
-
-/* Expose values for PInvoke */
-hb_rate_t* hb_get_video_rates();
-int hb_get_video_rates_count();
-hb_rate_t* hb_get_audio_rates();
-int hb_get_audio_rates_count();
-int hb_get_audio_rates_default();
-hb_rate_t* hb_get_audio_bitrates();
-int hb_get_audio_bitrates_count();
-hb_dither_t* hb_get_audio_dithers();
-int hb_get_audio_dithers_count();
-hb_mixdown_t* hb_get_audio_mixdowns();
-int hb_get_audio_mixdowns_count();
-hb_encoder_t* hb_get_video_encoders();
-int hb_get_video_encoders_count();
-hb_encoder_t* hb_get_audio_encoders();
-int hb_get_audio_encoders_count();
-
-int hb_audio_dither_get_default();
-int hb_audio_dither_get_default_method();
-int hb_audio_dither_is_supported(uint32_t codec);
-const char* hb_audio_dither_get_description(int method);
-
-int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout);
-int hb_mixdown_has_codec_support(int mixdown, uint32_t codec);
-int hb_mixdown_has_remix_support(int mixdown, uint64_t layout);
-int hb_mixdown_get_discrete_channel_count(int amixdown);
-int hb_mixdown_get_low_freq_channel_count(int amixdown);
-int hb_mixdown_get_mixdown_from_short_name(const char *short_name);
-const char* hb_mixdown_get_short_name_from_mixdown(int amixdown);
+/*******************************************************************************
+ * Lists of rates, mixdowns, encoders etc.
+ *******************************************************************************
+ *
+ * Use hb_*_get_next() to get the next list item (use NULL to get the first).
+ *
+ * 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.
+ *
+ * Use hb_*_get_name() and hb_*_get_short_name() to get the corresponding value.
+ * Returns NULL if the value is invalid.
+ *
+ * hb_*_sanitize_name() are convenience functions for use when dealing
+ * with full names (e.g. to translate legacy values while loading a preset).
+ *
+ * Names are case-insensitive; libhb will ensure that the lists do not contain
+ * more than one entry with the same name.
+ *
+ * Use hb_*_get_limits() to get the minimum/maximum for lists with numerically
+ * ordered values.
+ *
+ * Use hb_*_get_best() to sanitize a value based on other relevant parameters.
+ *
+ * Use hb_*_get_default() to get the default based on other relevant parameters.
+ *
+ */
+
+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);
+const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last);
+
+int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift);
+int hb_audio_samplerate_get_from_name(const char *name);
+const char* hb_audio_samplerate_get_name(int samplerate);
+const hb_rate_t* hb_audio_samplerate_get_next(const hb_rate_t *last);
+
+int hb_audio_bitrate_get_best(uint32_t codec, int bitrate, int samplerate, int mixdown);
+int hb_audio_bitrate_get_default(uint32_t codec, int samplerate, int mixdown);
+void hb_audio_bitrate_get_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high);
+const hb_rate_t* hb_audio_bitrate_get_next(const hb_rate_t *last);
+
+void hb_audio_quality_get_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
+float hb_audio_quality_get_best(uint32_t codec, float quality);
+float hb_audio_quality_get_default(uint32_t codec);
+
+void hb_audio_compression_get_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
+float hb_audio_compression_get_best(uint32_t codec, float compression);
+float hb_audio_compression_get_default(uint32_t codec);
+
+int hb_audio_dither_get_default();
+int hb_audio_dither_get_default_method(); // default method, if enabled && supported
+int hb_audio_dither_is_supported(uint32_t codec);
+int hb_audio_dither_get_from_name(const char *name);
+const char* hb_audio_dither_get_description(int method);
+const hb_dither_t* hb_audio_dither_get_next(const hb_dither_t *last);
+
+int hb_mixdown_is_supported(int mixdown, uint32_t codec, uint64_t layout);
+int hb_mixdown_has_codec_support(int mixdown, uint32_t codec);
+int hb_mixdown_has_remix_support(int mixdown, uint64_t layout);
+int hb_mixdown_get_discrete_channel_count(int mixdown);
+int hb_mixdown_get_low_freq_channel_count(int mixdown);
+int hb_mixdown_get_best(uint32_t codec, uint64_t layout, int mixdown);
+int hb_mixdown_get_default(uint32_t codec, uint64_t layout);
+int hb_mixdown_get_from_name(const char *name);
+const char* hb_mixdown_get_name(int mixdown);
+const char* hb_mixdown_get_short_name(int mixdown);
+const char* hb_mixdown_sanitize_name(const char *name);
+const hb_mixdown_t* hb_mixdown_get_next(const hb_mixdown_t *last);
+
+int hb_video_encoder_get_default(int muxer);
+int hb_video_encoder_get_from_name(const char *name);
+const char* hb_video_encoder_get_name(int encoder);
+const char* hb_video_encoder_get_short_name(int encoder);
+const char* hb_video_encoder_sanitize_name(const char *name);
+const hb_encoder_t* hb_video_encoder_get_next(const hb_encoder_t *last);
+
+/*
+ * hb_audio_encoder_get_fallback_for_passthru() will sanitize a passthru codec
+ * to the matching audio encoder (if any is available).
+ *
+ * hb_audio_encoder_get_from_name(), hb_audio_encoder_sanitize_name() will
+ * sanitize legacy encoder names, but won't convert passthru to an encoder.
+ */
+int hb_audio_encoder_get_fallback_for_passthru(int passthru);
+int hb_audio_encoder_get_default(int muxer);
+int hb_audio_encoder_get_from_name(const char *name);
+const char* hb_audio_encoder_get_name(int encoder);
+const char* hb_audio_encoder_get_short_name(int encoder);
+const char* hb_audio_encoder_sanitize_name(const char *name);
+const hb_encoder_t* hb_audio_encoder_get_next(const hb_encoder_t *last);
+/*
+ * Not typically used by the UIs
+ * (set hb_job_t.acodec_copy_mask, hb_job_t.acodec_fallback instead).
+ */
void hb_autopassthru_apply_settings(hb_job_t *job);
void hb_autopassthru_print_settings(hb_job_t *job);
int hb_autopassthru_get_encoder(int in_codec, int copy_mask, int fallback, int muxer);
-int hb_get_default_audio_encoder(int muxer);
-
-int hb_get_best_mixdown(uint32_t codec, uint64_t layout, int mixdown);
-int hb_get_default_mixdown(uint32_t codec, uint64_t layout);
-
-int hb_get_best_samplerate(uint32_t codec, int samplerate, int *sr_shift);
-
-int hb_find_closest_audio_bitrate(int bitrate);
-void hb_get_audio_bitrate_limits(uint32_t codec, int samplerate, int mixdown, int *low, int *high);
-int hb_get_best_audio_bitrate(uint32_t codec, int bitrate, int samplerate, int mixdown);
-int hb_get_default_audio_bitrate(uint32_t codec, int samplerate, int mixdown);
-
-void hb_get_audio_quality_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
-float hb_get_best_audio_quality(uint32_t codec, float quality);
-float hb_get_default_audio_quality(uint32_t codec);
-
-void hb_get_audio_compression_limits(uint32_t codec, float *low, float *high, float *granularity, int *direction);
-float hb_get_best_audio_compression(uint32_t codec, float compression);
-float hb_get_default_audio_compression(uint32_t codec);
+int hb_container_get_from_name(const char *name);
+int hb_container_get_from_extension(const char *extension); // not really a container name
+const char* hb_container_get_name(int format);
+const char* hb_container_get_short_name(int format);
+const char* hb_container_get_default_extension(int format);
+const char* hb_container_sanitize_name(const char *name);
+const hb_container_t* hb_container_get_next(const hb_container_t *last);
struct hb_title_set_s
{
@@ -408,12 +455,19 @@ struct hb_job_s
hb_metadata_t * metadata;
- /* Muxer settings
- mux: output file format
- file: file path */
-#define HB_MUX_MASK 0xFF0000
-#define HB_MUX_MP4 0x010000
-#define HB_MUX_MKV 0x200000
+ /*
+ * Muxer settings
+ * mux: output file format
+ * file: file path
+ */
+#define HB_MUX_MASK 0xFF0000
+#define HB_MUX_MP4V2 0x010000
+#define HB_MUX_MASK_MP4 0x0F0000
+#define HB_MUX_LIBMKV 0x100000
+#define HB_MUX_MASK_MKV 0xF00000
+// default MP4 and MKV muxers
+#define HB_MUX_MP4 HB_MUX_MP4V2
+#define HB_MUX_MKV HB_MUX_LIBMKV
int mux;
char * file;
diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c
index b232dae81..dcb19da34 100644
--- a/libhb/encavcodec.c
+++ b/libhb/encavcodec.c
@@ -117,12 +117,12 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job )
// to fps.den.
if (fps.num == 27000000)
{
- int ii;
- for (ii = 0; ii < hb_video_rates_count; ii++)
+ const hb_rate_t *video_framerate = NULL;
+ while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
{
- if (abs(fps.den - hb_video_rates[ii].rate) < 10)
+ if (abs(fps.den - video_framerate->rate) < 10)
{
- fps.den = hb_video_rates[ii].rate;
+ fps.den = video_framerate->rate;
break;
}
}
diff --git a/libhb/scan.c b/libhb/scan.c
index c83326d4d..0d7dde7ff 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -820,11 +820,12 @@ skip_preview:
// if the frame rate is very close to one of our "common" framerates,
// assume it actually is said frame rate; e.g. some 24000/1001 sources
// may have a rate_base of 1126124 (instead of 1126125)
- 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( is_close_to( vid_info.rate_base, hb_video_rates[i].rate, 100 ) )
+ if (is_close_to(vid_info.rate_base, video_framerate->rate, 100))
{
- vid_info.rate_base = hb_video_rates[i].rate;
+ vid_info.rate_base = video_framerate->rate;
break;
}
}
diff --git a/libhb/work.c b/libhb/work.c
index 72d758eed..1e05c9db7 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -149,12 +149,12 @@ hb_work_object_t* hb_codec_encoder(int codec)
* Displays job parameters in the debug log.
* @param job Handle work hb_job_t.
*/
-void hb_display_job_info( hb_job_t * job )
+void hb_display_job_info(hb_job_t *job)
{
- hb_title_t * title = job->title;
- hb_audio_t * audio;
- hb_subtitle_t * subtitle;
- int i, j;
+ int i;
+ hb_title_t *title = job->title;
+ hb_audio_t *audio;
+ hb_subtitle_t *subtitle;
hb_log("job configuration:");
hb_log( " * source");
@@ -206,26 +206,19 @@ void hb_display_job_info( hb_job_t * job )
hb_log( " + %s", job->file );
- switch( job->mux )
+ hb_log(" + container: %s", hb_container_get_name(job->mux));
+ switch (job->mux)
{
- case HB_MUX_MP4:
- hb_log(" + container: MPEG-4 (.mp4 and .m4v)");
-
- if( job->ipod_atom )
- hb_log( " + compatibility atom for iPod 5G");
-
- if( job->largeFileSize )
- hb_log( " + 64-bit formatting");
-
- if( job->mp4_optimize )
- hb_log( " + optimized for progressive web downloads");
-
- if( job->color_matrix_code )
- hb_log( " + custom color matrix: %s", job->color_matrix_code == 1 ? "ITU Bt.601 (SD)" : job->color_matrix_code == 2 ? "ITU Bt.709 (HD)" : "Custom" );
+ case HB_MUX_MP4V2:
+ if (job->largeFileSize)
+ hb_log(" + 64-bit chunk offsets");
+ if (job->mp4_optimize)
+ hb_log(" + optimized for HTTP streaming (fast start)");
+ if (job->ipod_atom)
+ hb_log(" + compatibility atom for iPod 5G");
break;
- case HB_MUX_MKV:
- hb_log(" + container: Matroska (.mkv)");
+ default:
break;
}
@@ -295,14 +288,7 @@ void hb_display_job_info( hb_job_t * job )
if( !job->indepth_scan )
{
/* Video encoder */
- for( i = 0; i < hb_video_encoders_count; i++ )
- {
- if( hb_video_encoders[i].encoder == job->vcodec )
- {
- hb_log( " + encoder: %s", hb_video_encoders[i].human_readable_name );
- break;
- }
- }
+ hb_log(" + encoder: %s", hb_video_encoder_get_name(job->vcodec));
if( job->x264_preset && *job->x264_preset &&
job->vcodec == HB_VCODEC_X264 )
@@ -346,6 +332,18 @@ void hb_display_job_info( hb_job_t * job )
hb_log( " subq=2 (if originally greater than 2, else subq unchanged)" );
}
}
+
+ if (job->color_matrix_code && (job->vcodec == HB_VCODEC_X264 ||
+ job->mux == HB_MUX_MP4V2))
+ {
+ // color matrix is set:
+ // 1) at the stream level (x264 only),
+ // 2) at the container level (mp4v2 only)
+ hb_log(" + custom color matrix: %s",
+ job->color_matrix_code == 1 ? "ITU Bt.601 (NTSC)" :
+ job->color_matrix_code == 2 ? "ITU Bt.601 (PAL)" :
+ job->color_matrix_code == 3 ? "ITU Bt.709 (HD)" : "Custom");
+ }
}
if( job->indepth_scan )
@@ -413,25 +411,13 @@ void hb_display_job_info( hb_job_t * job )
if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
{
- for( j = 0; j < hb_audio_encoders_count; j++ )
- {
- if( hb_audio_encoders[j].encoder == audio->config.out.codec )
- {
- hb_log( " + %s", hb_audio_encoders[j].human_readable_name );
- break;
- }
- }
+ hb_log(" + %s",
+ hb_audio_encoder_get_name(audio->config.out.codec));
}
else
{
- for( j = 0; j < hb_audio_mixdowns_count; j++ )
- {
- if( hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown )
- {
- hb_log( " + mixdown: %s", hb_audio_mixdowns[j].human_readable_name );
- break;
- }
- }
+ hb_log(" + mixdown: %s",
+ hb_mixdown_get_name(audio->config.out.mixdown));
if( audio->config.out.normalize_mix_level != 0 )
{
hb_log( " + normalized mixing levels" );
@@ -449,22 +435,27 @@ void hb_display_job_info( hb_job_t * job )
hb_log(" + dither: %s",
hb_audio_dither_get_description(audio->config.out.dither_method));
}
- for( j = 0; j < hb_audio_encoders_count; j++ )
+ hb_log(" + encoder: %s",
+ hb_audio_encoder_get_name(audio->config.out.codec));
+ if (audio->config.out.bitrate > 0)
{
- if( hb_audio_encoders[j].encoder == audio->config.out.codec )
- {
- hb_log( " + encoder: %s", hb_audio_encoders[j].human_readable_name );
- if( audio->config.out.bitrate > 0 )
- hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );
- else if( audio->config.out.quality != HB_INVALID_AUDIO_QUALITY )
- hb_log( " + quality: %.2f, samplerate: %d Hz", audio->config.out.quality, audio->config.out.samplerate );
- else if( audio->config.out.samplerate > 0 )
- hb_log( " + samplerate: %d Hz", audio->config.out.samplerate );
- if( audio->config.out.compression_level >= 0 )
- hb_log( " + compression level: %.2f",
- audio->config.out.compression_level );
- break;
- }
+ hb_log(" + bitrate: %d kbps, samplerate: %d Hz",
+ audio->config.out.bitrate, audio->config.out.samplerate);
+ }
+ else if (audio->config.out.quality != HB_INVALID_AUDIO_QUALITY)
+ {
+ hb_log(" + quality: %.2f, samplerate: %d Hz",
+ audio->config.out.quality, audio->config.out.samplerate);
+ }
+ else if (audio->config.out.samplerate > 0)
+ {
+ hb_log(" + samplerate: %d Hz",
+ audio->config.out.samplerate);
+ }
+ if (audio->config.out.compression_level >= 0)
+ {
+ hb_log(" + compression level: %.2f",
+ audio->config.out.compression_level);
}
}
}
@@ -494,24 +485,24 @@ void correct_framerate( hb_job_t * job )
* Closes threads and frees fifos.
* @param job Handle work hb_job_t.
*/
-static void do_job( hb_job_t * job )
+static void do_job(hb_job_t *job)
{
- hb_title_t * title;
- int i, j;
- hb_work_object_t * w;
- hb_work_object_t * sync;
- hb_work_object_t * muxer;
+ int i;
+ hb_title_t *title;
+ hb_interjob_t *interjob;
+ hb_work_object_t *w;
+ hb_work_object_t *sync;
+ hb_work_object_t *muxer;
hb_work_object_t *reader = hb_get_work(WORK_READER);
- hb_interjob_t * interjob;
-
- hb_audio_t * audio;
- hb_subtitle_t * subtitle;
- unsigned int subtitle_highest = 0;
- unsigned int subtitle_lowest = 0;
- unsigned int subtitle_lowest_id = 0;
- unsigned int subtitle_forced_id = 0;
+
+ hb_audio_t *audio;
+ hb_subtitle_t *subtitle;
+ unsigned int subtitle_highest = 0;
+ unsigned int subtitle_lowest = 0;
+ unsigned int subtitle_lowest_id = 0;
+ unsigned int subtitle_forced_id = 0;
unsigned int subtitle_forced_hits = 0;
- unsigned int subtitle_hit = 0;
+ unsigned int subtitle_hit = 0;
title = job->title;
interjob = hb_interjob_get( job->h );
@@ -797,21 +788,14 @@ static void do_job( hb_job_t * job )
audio->config.out.samplerate = audio->config.in.samplerate;
}
best_samplerate =
- hb_get_best_samplerate(audio->config.out.codec,
- audio->config.out.samplerate, NULL);
+ hb_audio_samplerate_get_best(audio->config.out.codec,
+ audio->config.out.samplerate,
+ NULL);
if (best_samplerate != audio->config.out.samplerate)
{
- int ii;
- for (ii = 0; ii < hb_audio_rates_count; ii++)
- {
- if (best_samplerate == hb_audio_rates[ii].rate)
- {
- hb_log("work: sanitizing track %d unsupported samplerate %d Hz to %s kHz",
- audio->config.out.track, audio->config.out.samplerate,
- hb_audio_rates[ii].string);
- break;
- }
- }
+ hb_log("work: sanitizing track %d unsupported samplerate %d Hz to %s kHz",
+ audio->config.out.track, audio->config.out.samplerate,
+ hb_audio_samplerate_get_name(best_samplerate));
audio->config.out.samplerate = best_samplerate;
}
@@ -820,44 +804,25 @@ static void do_job( hb_job_t * job )
{
/* Mixdown not specified, set the default mixdown */
audio->config.out.mixdown =
- hb_get_default_mixdown(audio->config.out.codec,
+ hb_mixdown_get_default(audio->config.out.codec,
audio->config.in.channel_layout);
- for (j = 0; j < hb_audio_mixdowns_count; j++)
- {
- if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown)
- {
- hb_log("work: mixdown not specified, track %d setting mixdown %s",
- audio->config.out.track,
- hb_audio_mixdowns[j].human_readable_name);
- break;
- }
- }
+ hb_log("work: mixdown not specified, track %d setting mixdown %s",
+ audio->config.out.track,
+ hb_mixdown_get_name(audio->config.out.mixdown));
}
else
{
best_mixdown =
- hb_get_best_mixdown(audio->config.out.codec,
+ hb_mixdown_get_best(audio->config.out.codec,
audio->config.in.channel_layout,
audio->config.out.mixdown);
if (audio->config.out.mixdown != best_mixdown)
{
- int prev_mix_idx = 0, best_mix_idx = 0;
- for (j = 0; j < hb_audio_mixdowns_count; j++)
- {
- if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown)
- {
- prev_mix_idx = j;
- }
- else if (hb_audio_mixdowns[j].amixdown == best_mixdown)
- {
- best_mix_idx = j;
- }
- }
/* log the output mixdown */
hb_log("work: sanitizing track %d mixdown %s to %s",
audio->config.out.track,
- hb_audio_mixdowns[prev_mix_idx].human_readable_name,
- hb_audio_mixdowns[best_mix_idx].human_readable_name);
+ hb_mixdown_get_name(audio->config.out.mixdown),
+ hb_mixdown_get_name(best_mixdown));
audio->config.out.mixdown = best_mixdown;
}
}
@@ -866,7 +831,7 @@ static void do_job( hb_job_t * job )
if (audio->config.out.compression_level < 0)
{
audio->config.out.compression_level =
- hb_get_default_audio_compression(audio->config.out.codec);
+ hb_audio_compression_get_default(audio->config.out.codec);
if (audio->config.out.compression_level >= 0)
{
hb_log("work: compression level not specified, track %d setting compression level %.2f",
@@ -877,7 +842,7 @@ static void do_job( hb_job_t * job )
else
{
float best_compression =
- hb_get_best_audio_compression(audio->config.out.codec,
+ hb_audio_compression_get_best(audio->config.out.codec,
audio->config.out.compression_level);
if (best_compression != audio->config.out.compression_level)
{
@@ -901,7 +866,7 @@ static void do_job( hb_job_t * job )
if (audio->config.out.quality != HB_INVALID_AUDIO_QUALITY)
{
float best_quality =
- hb_get_best_audio_quality(audio->config.out.codec,
+ hb_audio_quality_get_best(audio->config.out.codec,
audio->config.out.quality);
if (best_quality != audio->config.out.quality)
{
@@ -927,7 +892,7 @@ static void do_job( hb_job_t * job )
{
/* Bitrate not specified, set the default bitrate */
audio->config.out.bitrate =
- hb_get_default_audio_bitrate(audio->config.out.codec,
+ hb_audio_bitrate_get_default(audio->config.out.codec,
audio->config.out.samplerate,
audio->config.out.mixdown);
if (audio->config.out.bitrate > 0)
@@ -940,7 +905,7 @@ static void do_job( hb_job_t * job )
else
{
best_bitrate =
- hb_get_best_audio_bitrate(audio->config.out.codec,
+ hb_audio_bitrate_get_best(audio->config.out.codec,
audio->config.out.bitrate,
audio->config.out.samplerate,
audio->config.out.mixdown);
diff --git a/macosx/Controller.m b/macosx/Controller.m
index 93c61f8b5..e92f7393a 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -656,29 +656,33 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
/* Destination box*/
NSMenuItem *menuItem;
[fDstFormatPopUp removeAllItems];
- // MP4 file
- menuItem = [[fDstFormatPopUp menu] addItemWithTitle:@"MP4 file" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_MUX_MP4];
- // MKV file
- menuItem = [[fDstFormatPopUp menu] addItemWithTitle:@"MKV file" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_MUX_MKV];
-
- [fDstFormatPopUp selectItemAtIndex: 0];
-
+ for (const hb_container_t *container = hb_container_get_next(NULL);
+ container != NULL;
+ container = hb_container_get_next(container))
+ {
+ menuItem = [[fDstFormatPopUp menu] addItemWithTitle:[NSString stringWithUTF8String:container->name]
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:container->format];
+ }
+ // select the first container
+ [fDstFormatPopUp selectItemAtIndex:0];
[self formatPopUpChanged:nil];
+
+ // enable/disable chapter markers as necessary
+ if ([fCreateChapterMarkers isEnabled] &&
+ [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"])
+ {
+ [fCreateChapterMarkers setState:NSOnState];
+ }
+ else
+ {
+ [fCreateChapterMarkers setState:NSOffState];
+ }
- /* We enable the create chapters checkbox here since we are .mp4 */
- [fCreateChapterMarkers setEnabled: YES];
- if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
- {
- [fCreateChapterMarkers setState: NSOnState];
- }
-
-
-
-
- [fDstFile2Field setStringValue: [NSString stringWithFormat:
- @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
+ [fDstFile2Field setStringValue:[NSString
+ stringWithFormat:@"%@/Desktop/Movie.mp4",
+ NSHomeDirectory()]];
/* Video encoder */
[fVidEncoderPopUp removeAllItems];
@@ -694,31 +698,37 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
/* Video framerate */
[fVidRatePopUp removeAllItems];
- [fVidRatePopUp addItemWithTitle: NSLocalizedString( @"Same as source", @"" )];
- for( int i = 0; i < hb_video_rates_count; i++ )
+ menuItem = [[fVidRatePopUp menu] addItemWithTitle:@"Same as source"
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:-1]; // hb_video_framerate_get_from_name(NULL)
+ 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))
{
- if ([[NSString stringWithUTF8String: hb_video_rates[i].string] isEqualToString: [NSString stringWithFormat: @"%.3f",23.976]])
- {
- [fVidRatePopUp addItemWithTitle:[NSString stringWithFormat: @"%@%@",
- [NSString stringWithUTF8String: hb_video_rates[i].string], @" (NTSC Film)"]];
- }
- else if ([[NSString stringWithUTF8String: hb_video_rates[i].string] isEqualToString: [NSString stringWithFormat: @"%d",25]])
- {
- [fVidRatePopUp addItemWithTitle:[NSString stringWithFormat: @"%@%@",
- [NSString stringWithUTF8String: hb_video_rates[i].string], @" (PAL Film/Video)"]];
- }
- else if ([[NSString stringWithUTF8String: hb_video_rates[i].string] isEqualToString: [NSString stringWithFormat: @"%.2f",29.97]])
- {
- [fVidRatePopUp addItemWithTitle:[NSString stringWithFormat: @"%@%@",
- [NSString stringWithUTF8String: hb_video_rates[i].string], @" (NTSC Video)"]];
- }
- else
- {
- [fVidRatePopUp addItemWithTitle:
- [NSString stringWithUTF8String: hb_video_rates[i].string]];
- }
+ NSString *itemTitle;
+ if (!strcmp(video_framerate->name, "23.976"))
+ {
+ itemTitle = @"23.976 (NTSC Film)";
+ }
+ else if (!strcmp(video_framerate->name, "25"))
+ {
+ itemTitle = @"25 (PAL Film/Video)";
+ }
+ else if (!strcmp(video_framerate->name, "29.97"))
+ {
+ itemTitle = @"29.97 (NTSC Video)";
+ }
+ else
+ {
+ itemTitle = [NSString stringWithUTF8String:video_framerate->name];
+ }
+ menuItem = [[fVidRatePopUp menu] addItemWithTitle:itemTitle
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:video_framerate->rate];
}
- [fVidRatePopUp selectItemAtIndex: 0];
+ [fVidRatePopUp selectItemAtIndex:0];
/* Set Auto Crop to On at launch */
[fPictureController setAutoCrop:YES];
@@ -2114,12 +2124,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[fSrcDVD2Field setStringValue:browsedSourceDisplayName];
// use the correct extension based on the container
- int format = [fDstFormatPopUp indexOfSelectedItem];
- char *ext = "mp4";
- if (format == 1)
- {
- ext = "mkv";
- }
+ int videoContainer = [[fDstFormatPopUp selectedItem] tag];
+ const char *ext = hb_container_get_default_extension(videoContainer);
/* If its a queue rescan for edit, get the queue item output path */
/* if not, its a new source scan. */
@@ -2140,9 +2146,9 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
}
// set m4v extension if necessary - do not override user-specified .mp4 extension
- if (format == 0 && applyQueueToScan != YES)
+ if ((videoContainer & HB_MUX_MASK_MP4) && (applyQueueToScan != YES))
{
- [self autoSetM4vExtension: sender];
+ [self autoSetM4vExtension:sender];
}
/* See if this is the main feature according to libhb */
@@ -2720,8 +2726,8 @@ fWorkingCount = 0;
/* Framerate */
[queueFileJob setObject:[NSNumber numberWithInt:[fVidRatePopUp indexOfSelectedItem]] forKey:@"JobIndexVideoFramerate"];
- [queueFileJob setObject:[NSNumber numberWithInt:title->rate] forKey:@"JobVrate"];
- [queueFileJob setObject:[NSNumber numberWithInt:title->rate_base] forKey:@"JobVrateBase"];
+ [queueFileJob setObject:[NSNumber numberWithInt:title->rate] forKey:@"JobVrate"];
+ [queueFileJob setObject:[NSNumber numberWithInt:title->rate_base] forKey:@"JobVrateBase"];
/* Picture Sizing */
/* Use Max Picture settings for whatever the dvd is.*/
@@ -3313,8 +3319,6 @@ fWorkingCount = 0;
[fSrcTitlePopUp indexOfSelectedItem] );
hb_job_t * job = title->job;
hb_filter_object_t * filter;
- int vrate, vrate_base;
-
/* set job->angle for libdvdnav */
job->angle = [fSrcAnglePopUp indexOfSelectedItem] + 1;
/* Chapter selection */
@@ -3381,37 +3385,37 @@ fWorkingCount = 0;
}
/* Video settings */
-
+ int fps_mode, fps_num, fps_den;
if( [fVidRatePopUp indexOfSelectedItem] > 0 )
{
/* a specific framerate has been chosen */
- vrate = 27000000;
- vrate_base = hb_video_rates[[fVidRatePopUp indexOfSelectedItem]-1].rate;
+ fps_num = 27000000;
+ fps_den = [[fVidRatePopUp selectedItem] tag];
if ([fFramerateMatrix selectedRow] == 1)
{
// CFR
- job->cfr = 1;
+ fps_mode = 1;
}
else
{
// PFR
- job->cfr = 2;
+ fps_mode = 2;
}
}
else
{
/* same as source */
- vrate = title->rate;
- vrate_base = title->rate_base;
+ fps_num = title->rate;
+ fps_den = title->rate_base;
if ([fFramerateMatrix selectedRow] == 1)
{
// CFR
- job->cfr = 1;
+ fps_mode = 1;
}
else
{
// VFR
- job->cfr = 0;
+ fps_mode = 0;
}
}
@@ -3723,9 +3727,9 @@ bool one_burned = FALSE;
job->crop[2], job->crop[3]] UTF8String] );
/* Add framerate shaping filter */
- filter = hb_filter_init( HB_FILTER_VFR );
- hb_add_filter( job, filter, [[NSString stringWithFormat:@"%d:%d:%d",
- job->cfr, vrate, vrate_base] UTF8String] );
+ filter = hb_filter_init(HB_FILTER_VFR);
+ hb_add_filter(job, filter, [[NSString stringWithFormat:@"%d:%d:%d",
+ fps_mode, fps_num, fps_den] UTF8String]);
}
@@ -3742,8 +3746,6 @@ bool one_burned = FALSE;
hb_job_t * job = title->job;
hb_audio_config_t * audio;
hb_filter_object_t * filter;
- int vrate, vrate_base;
-
/* Title Angle for dvdnav */
job->angle = [[queueToApply objectForKey:@"TitleAngle"] intValue];
@@ -3938,37 +3940,37 @@ bool one_burned = FALSE;
/* Video settings */
/* Framerate */
-
- if( [[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue] > 0 )
+ int fps_mode, fps_num, fps_den;
+ if ([[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue] > 0)
{
/* a specific framerate has been chosen */
- vrate = 27000000;
- vrate_base = hb_video_rates[[[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue]-1].rate;
+ fps_num = 27000000;
+ fps_den = [[fVidRatePopUp itemAtIndex:[[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue]] tag];
if ([[queueToApply objectForKey:@"VideoFramerateMode"] isEqualToString:@"cfr"])
{
// CFR
- job->cfr = 1;
+ fps_mode = 1;
}
else
{
// PFR
- job->cfr = 2;
+ fps_mode = 2;
}
}
else
{
/* same as source */
- vrate = [[queueToApply objectForKey:@"JobVrate"] intValue];
- vrate_base = [[queueToApply objectForKey:@"JobVrateBase"] intValue];
+ fps_num = [[queueToApply objectForKey:@"JobVrate"] intValue];
+ fps_den = [[queueToApply objectForKey:@"JobVrateBase"] intValue];
if ([[queueToApply objectForKey:@"VideoFramerateMode"] isEqualToString:@"cfr"])
{
// CFR
- job->cfr = 1;
+ fps_mode = 1;
}
else
{
// VFR
- job->cfr = 0;
+ fps_mode = 0;
}
}
@@ -4159,7 +4161,7 @@ bool one_burned = FALSE;
/* We go ahead and assign values to our audio->out.<properties> */
audio->out.track = audio->in.track;
audio->out.codec = [[queueToApply objectForKey:[jobPrefix stringByAppendingString:@"Encoder"]] intValue];
- audio->out.compression_level = hb_get_default_audio_compression(audio->out.codec);
+ audio->out.compression_level = hb_audio_compression_get_default(audio->out.codec);
audio->out.mixdown = [[queueToApply objectForKey:[jobPrefix stringByAppendingString:@"Mixdown"]] intValue];
audio->out.normalize_mix_level = 0;
audio->out.bitrate = [[queueToApply objectForKey:[jobPrefix stringByAppendingString:@"Bitrate"]] intValue];
@@ -4284,9 +4286,9 @@ bool one_burned = FALSE;
job->crop[2], job->crop[3]] UTF8String] );
/* Add framerate shaping filter */
- filter = hb_filter_init( HB_FILTER_VFR );
- hb_add_filter( job, filter, [[NSString stringWithFormat:@"%d:%d:%d",
- job->cfr, vrate, vrate_base] UTF8String] );
+ filter = hb_filter_init(HB_FILTER_VFR);
+ hb_add_filter(job, filter, [[NSString stringWithFormat:@"%d:%d:%d",
+ fps_mode, fps_num, fps_den] UTF8String]);
[self writeToActivityLog: "prepareJob exiting"];
}
@@ -4922,31 +4924,31 @@ bool one_burned = FALSE;
- (IBAction) formatPopUpChanged: (id) sender
{
- NSString * string = [fDstFile2Field stringValue];
- int format = [fDstFormatPopUp indexOfSelectedItem];
- char * ext = NULL;
+ NSString *string = [fDstFile2Field stringValue];
+ int videoContainer = [[fDstFormatPopUp selectedItem] tag];
+ const char *ext = NULL;
NSMenuItem *menuItem;
- int i;
- /* Initially set the large file (64 bit formatting) output checkbox to hidden */
- [fDstMp4LargeFileCheck setHidden: YES];
- [fDstMp4HttpOptFileCheck setHidden: YES];
- [fDstMp4iPodFileCheck setHidden: YES];
+ /* Initially set the large file (64 bit formatting) output checkbox to hidden */
+ [fDstMp4LargeFileCheck setHidden:YES];
+ [fDstMp4HttpOptFileCheck setHidden:YES];
+ [fDstMp4iPodFileCheck setHidden:YES];
/* Update the Video Codec Popup */
/* lets get the tag of the currently selected item first so we might reset it later */
- int selectedVidEncoderTag;
- selectedVidEncoderTag = [[fVidEncoderPopUp selectedItem] tag];
+ int selectedVidEncoderTag = [[fVidEncoderPopUp selectedItem] tag];
/* Note: we now store the video encoder int values from common.c in the tags of each popup for easy retrieval later */
[fVidEncoderPopUp removeAllItems];
- for( i = 0; i < hb_video_encoders_count; i++ )
+ for (const hb_encoder_t *video_encoder = hb_video_encoder_get_next(NULL);
+ video_encoder != NULL;
+ video_encoder = hb_video_encoder_get_next(video_encoder))
{
- if( ( ( format == 0 ) && ( hb_video_encoders[i].muxers & HB_MUX_MP4 ) ) ||
- ( ( format == 1 ) && ( hb_video_encoders[i].muxers & HB_MUX_MKV ) ) )
+ if (video_encoder->muxers & videoContainer)
{
- menuItem = [[fVidEncoderPopUp menu] addItemWithTitle: [NSString stringWithUTF8String: hb_video_encoders[i].human_readable_name]
- action: NULL keyEquivalent: @""];
- [menuItem setTag: hb_video_encoders[i].encoder];
+ menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:[NSString stringWithUTF8String:video_encoder->name]
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:video_encoder->codec];
}
}
@@ -4965,70 +4967,72 @@ bool one_burned = FALSE;
/* Update the Auto Passtgru Fallback Codec Popup */
/* lets get the tag of the currently selected item first so we might reset it later */
- int selectedAutoPassthruFallbackEncoderTag;
- selectedAutoPassthruFallbackEncoderTag = [[fAudioFallbackPopUp selectedItem] tag];
+ int selectedAutoPassthruFallbackEncoderTag = [[fAudioFallbackPopUp selectedItem] tag];
[fAudioFallbackPopUp removeAllItems];
- for( i = 0; i < hb_audio_encoders_count; i++ )
+ for (const hb_encoder_t *audio_encoder = hb_audio_encoder_get_next(NULL);
+ audio_encoder != NULL;
+ audio_encoder = hb_audio_encoder_get_next(audio_encoder))
{
- if( !( hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG ) &&
- ( ( ( format == 0 ) && ( hb_audio_encoders[i].muxers & HB_MUX_MP4 ) ) ||
- ( ( format == 1 ) && ( hb_audio_encoders[i].muxers & HB_MUX_MKV ) ) ) )
+ if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) == 0 &&
+ (audio_encoder->muxers & videoContainer))
{
- menuItem = [[fAudioFallbackPopUp menu] addItemWithTitle: [NSString stringWithUTF8String: hb_audio_encoders[i].human_readable_name]
- action: NULL keyEquivalent: @""];
- [menuItem setTag: hb_audio_encoders[i].encoder];
+ menuItem = [[fAudioFallbackPopUp menu] addItemWithTitle:[NSString stringWithUTF8String:audio_encoder->name]
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:audio_encoder->codec];
}
}
/* if we have a previously selected auto passthru fallback encoder tag, then try to select it */
if (selectedAutoPassthruFallbackEncoderTag)
{
- selectedAutoPassthruFallbackEncoderTag = [fAudioFallbackPopUp selectItemWithTag: selectedAutoPassthruFallbackEncoderTag];
+ selectedAutoPassthruFallbackEncoderTag = [fAudioFallbackPopUp selectItemWithTag:selectedAutoPassthruFallbackEncoderTag];
}
/* if we had no previous fallback selected OR if selection failed
* select the default fallback encoder (AC3) */
if (!selectedAutoPassthruFallbackEncoderTag)
{
- [fAudioFallbackPopUp selectItemWithTag: HB_ACODEC_AC3];
+ [fAudioFallbackPopUp selectItemWithTag:HB_ACODEC_AC3];
}
- switch( format )
+ // enable chapter markers and hide muxer-specific options
+ [fCreateChapterMarkers setEnabled:YES];
+ [fDstMp4LargeFileCheck setHidden:YES];
+ [fDstMp4HttpOptFileCheck setHidden:YES];
+ [fDstMp4iPodFileCheck setHidden:YES];
+ switch (videoContainer)
{
- case 0:
- [self autoSetM4vExtension: nil];
- /* We show the mp4 option checkboxes here since we are mp4 */
- [fCreateChapterMarkers setEnabled: YES];
- [fDstMp4LargeFileCheck setHidden: NO];
- [fDstMp4HttpOptFileCheck setHidden: NO];
- [fDstMp4iPodFileCheck setHidden: NO];
+ case HB_MUX_MP4V2:
+ [fDstMp4LargeFileCheck setHidden:NO];
+ [fDstMp4HttpOptFileCheck setHidden:NO];
+ [fDstMp4iPodFileCheck setHidden:NO];
break;
-
- case 1:
- ext = "mkv";
- /* We enable the create chapters checkbox here */
- [fCreateChapterMarkers setEnabled: YES];
- break;
-
+ default:
+ break;
+ }
+ // set the file extension
+ ext = hb_container_get_default_extension(videoContainer);
+ [fDstFile2Field setStringValue:[NSString stringWithFormat:@"%@.%s",
+ [string stringByDeletingPathExtension],
+ ext]];
+ if (videoContainer & HB_MUX_MASK_MP4)
+ {
+ [self autoSetM4vExtension:sender];
}
- /* tell fSubtitlesDelegate we have a new video container */
- [fSubtitlesDelegate containerChanged:[[fDstFormatPopUp selectedItem] tag]];
+ /* tell fSubtitlesDelegate we have a new video container */
+ [fSubtitlesDelegate containerChanged:videoContainer];
[fSubtitlesTable reloadData];
- /* post a notification for any interested observers to indicate that our video container has changed */
- [[NSNotificationCenter defaultCenter] postNotification:
- [NSNotification notificationWithName: HBContainerChangedNotification
- object: self
- userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInt: [[fDstFormatPopUp selectedItem] tag]], keyContainerTag,
- nil]]];
-
- if( format == 0 )
- [self autoSetM4vExtension: sender];
- else
- [fDstFile2Field setStringValue: [NSString stringWithFormat:@"%@.%s", [string stringByDeletingPathExtension], ext]];
+ /* post a notification for any interested observers to indicate that our video container has changed */
+ [[NSNotificationCenter defaultCenter] postNotification:
+ [NSNotification notificationWithName:HBContainerChangedNotification
+ object:self
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:videoContainer], keyContainerTag,
+ nil]]];
if (SuccessfulScan)
{
@@ -5090,6 +5094,12 @@ the user is using "Custom" settings by determining the sender*/
- (IBAction) videoEncoderPopUpChanged: (id) sender
{
+ /* if no valid encoder is selected, use the first one */
+ if ([fVidEncoderPopUp selectedItem] == nil)
+ {
+ [fVidEncoderPopUp selectItemAtIndex:0];
+ }
+
int videoEncoder = [[fVidEncoderPopUp selectedItem] tag];
[fAdvancedOptions setHidden:YES];
@@ -5170,6 +5180,12 @@ the user is using "Custom" settings by determining the sender*/
- (IBAction ) videoFrameRateChanged: (id) sender
{
+ /* if no valid framerate is selected, use "Same as source" */
+ if ([fVidRatePopUp selectedItem] == nil)
+ {
+ [fVidRatePopUp selectItemAtIndex:0];
+ }
+
/* Hide and set the PFR Checkbox to OFF if we are set to Same as Source */
/* Depending on whether or not Same as source is selected modify the title for
* fFramerateVfrPfrCell*/
@@ -5898,21 +5914,23 @@ the user is using "Custom" settings by determining the sender*/
- (NSString*) muxerOptionsSummary
{
NSMutableString *summary = [NSMutableString stringWithString:@""];
- if (([fDstFormatPopUp selectedItem]) &&
- [[fDstFormatPopUp selectedItem] tag] == HB_MUX_MP4)
+ if ([fDstMp4LargeFileCheck isHidden] == NO &&
+ [fDstMp4LargeFileCheck isEnabled] == YES &&
+ [fDstMp4LargeFileCheck state] == NSOnState)
{
- if ([fDstMp4LargeFileCheck state])
- {
- [summary appendString:@" - Large file size"];
- }
- if ([fDstMp4HttpOptFileCheck state])
- {
- [summary appendString:@" - Web optimized"];
- }
- if ([fDstMp4iPodFileCheck state])
- {
- [summary appendString:@" - iPod 5G support"];
- }
+ [summary appendString:@" - Large file size"];
+ }
+ if ([fDstMp4HttpOptFileCheck isHidden] == NO &&
+ [fDstMp4HttpOptFileCheck isEnabled] == YES &&
+ [fDstMp4HttpOptFileCheck state] == NSOnState)
+ {
+ [summary appendString:@" - Web optimized"];
+ }
+ if ([fDstMp4iPodFileCheck isHidden] == NO &&
+ [fDstMp4iPodFileCheck isEnabled] == YES &&
+ [fDstMp4iPodFileCheck state] == NSOnState)
+ {
+ [summary appendString:@" - iPod 5G support"];
}
if ([summary hasPrefix:@" - "])
{
@@ -6397,9 +6415,11 @@ return YES;
- (IBAction)selectPreset:(id)sender
{
-
if (YES == [self hasValidPresetSelected])
{
+ // for mapping names via libhb
+ int intValue;
+ const char *strValue;
chosenPreset = [self selectedPreset];
[fPresetSelectedDisplay setStringValue:[chosenPreset objectForKey:@"PresetName"]];
@@ -6413,7 +6433,9 @@ return YES;
}
/* File Format */
- [fDstFormatPopUp selectItemWithTitle:[chosenPreset objectForKey:@"FileFormat"]];
+ /* map legacy container names via libhb */
+ strValue = hb_container_sanitize_name([[chosenPreset objectForKey:@"FileFormat"] UTF8String]);
+ [fDstFormatPopUp selectItemWithTitle:[NSString stringWithFormat:@"%s", strValue]];
[self formatPopUpChanged:nil];
/* Chapter Markers*/
@@ -6427,10 +6449,12 @@ return YES;
[fDstMp4HttpOptFileCheck setState:[[chosenPreset objectForKey:@"Mp4HttpOptimize"] intValue]];
/* Video encoder */
- [fVidEncoderPopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoEncoder"]];
+ /* map legacy encoder names via libhb */
+ strValue = hb_video_encoder_sanitize_name([[chosenPreset objectForKey:@"VideoEncoder"] UTF8String]);
+ [fVidEncoderPopUp selectItemWithTitle:[NSString stringWithFormat:@"%s", strValue]];
[self videoEncoderPopUpChanged:nil];
- if ([[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"H.264 (x264)"])
+ if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_X264)
{
if (![chosenPreset objectForKey:@"x264UseAdvancedOptions"] ||
[[chosenPreset objectForKey:@"x264UseAdvancedOptions"] intValue])
@@ -6549,7 +6573,9 @@ return YES;
[fFramerateMatrix selectCellAtRow:1 column:0]; // we want cfr
}
}
- [fVidRatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoFramerate"]];
+ /* map legacy names via libhb */
+ intValue = hb_video_framerate_get_from_name([[chosenPreset objectForKey:@"VideoFramerate"] UTF8String]);
+ [fVidRatePopUp selectItemWithTag:intValue];
[self videoFrameRateChanged:nil];
/* 2 Pass Encoding */
@@ -6604,11 +6630,13 @@ return YES;
}
if ((tempObject = [chosenPreset objectForKey:@"AudioEncoderFallback"]) != nil)
{
- [fAudioFallbackPopUp selectItemWithTitle:tempObject];
+ /* map legacy encoder names via libhb */
+ strValue = hb_audio_encoder_sanitize_name([tempObject UTF8String]);
+ [fAudioFallbackPopUp selectItemWithTitle:[NSString stringWithFormat:@"%s", strValue]];
}
else
{
- [fAudioFallbackPopUp selectItemWithTitle:@"AC3 (ffmpeg)"];
+ [fAudioFallbackPopUp selectItemWithTag:HB_ACODEC_AC3];
}
/* Audio */
@@ -7131,13 +7159,11 @@ return YES;
[preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
[preset setObject:[NSNumber numberWithFloat:[fVidQualityRFField floatValue]] forKey:@"VideoQualitySlider"];
- /* Video framerate */
- /* Set the Video Frame Rate Mode */
+ /* Video framerate and framerate mode */
if ([fFramerateMatrix selectedRow] == 1)
{
[preset setObject:@"cfr" forKey:@"VideoFramerateMode"];
}
- /* Set the actual framerate from popup overriding the cfr setting as needed */
if ([fVidRatePopUp indexOfSelectedItem] == 0) // Same as source is selected
{
[preset setObject:@"Same as source" forKey:@"VideoFramerate"];
@@ -7147,9 +7173,11 @@ return YES;
[preset setObject:@"vfr" forKey:@"VideoFramerateMode"];
}
}
- else // we can record the actual titleOfSelectedItem
+ else // translate the rate (selected item's tag) to the official libhb name
{
- [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
+ [preset setObject:[NSString stringWithFormat:@"%s",
+ hb_video_framerate_get_name([[fVidRatePopUp selectedItem] tag])]
+ forKey:@"VideoFramerate"];
if ([fFramerateMatrix selectedRow] == 0)
{
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m
index fdd7b5462..999aa9434 100644
--- a/macosx/HBAudio.m
+++ b/macosx/HBAudio.m
@@ -10,8 +10,7 @@
#import "hb.h"
NSString *keyAudioCodecName = @"keyAudioCodecName";
-NSString *keyAudioMP4 = @"keyAudioMP4";
-NSString *keyAudioMKV = @"keyAudioMKV";
+NSString *keyAudioSupportedMuxers = @"keyAudioSupportedMuxers";
NSString *keyAudioSampleRateName = @"keyAudioSampleRateName";
NSString *keyAudioBitrateName = @"keyAudioBitrateName";
NSString *keyAudioMustMatchTrack = @"keyAudioMustMatchTrack";
@@ -70,83 +69,70 @@ static NSMutableArray *masterBitRateArray = nil;
{
if ([HBAudio class] == self)
{
- int i, audioMustMatch;
- BOOL muxMKV, muxMP4;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSDictionary *dict;
-
masterCodecArray = [[NSMutableArray alloc] init]; // knowingly leaked
- for (i = 0; i < hb_audio_encoders_count; i++)
+ for (const hb_encoder_t *audio_encoder = hb_audio_encoder_get_next(NULL);
+ audio_encoder != NULL;
+ audio_encoder = hb_audio_encoder_get_next(audio_encoder))
{
- if ((hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG) &&
- (hb_audio_encoders[i].encoder != HB_ACODEC_AUTO_PASS))
+ id audioMustMatchTrack;
+ if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) &&
+ (audio_encoder->codec != HB_ACODEC_AUTO_PASS))
{
- audioMustMatch = (hb_audio_encoders[i].encoder & ~HB_ACODEC_PASS_FLAG);
+ audioMustMatchTrack = [NSNumber
+ numberWithInt:(audio_encoder->codec &
+ ~HB_ACODEC_PASS_FLAG)];
}
else
{
- audioMustMatch = 0;
- }
- muxMKV = (hb_audio_encoders[i].muxers & HB_MUX_MKV) ? YES : NO;
- muxMP4 = (hb_audio_encoders[i].muxers & HB_MUX_MP4) ? YES : NO;
- if (audioMustMatch)
- {
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithUTF8String: hb_audio_encoders[i].human_readable_name], keyAudioCodecName,
- [NSNumber numberWithInt: hb_audio_encoders[i].encoder], keyAudioCodec,
- [NSNumber numberWithBool: muxMP4], keyAudioMP4,
- [NSNumber numberWithBool: muxMKV], keyAudioMKV,
- [NSNumber numberWithInt: audioMustMatch], keyAudioMustMatchTrack,
- nil]];
- }
- else
- {
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithUTF8String: hb_audio_encoders[i].human_readable_name], keyAudioCodecName,
- [NSNumber numberWithInt: hb_audio_encoders[i].encoder], keyAudioCodec,
- [NSNumber numberWithBool: muxMP4], keyAudioMP4,
- [NSNumber numberWithBool: muxMKV], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
+ audioMustMatchTrack = [NSNumber numberWithBool:NO];
}
+ [masterCodecArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithUTF8String:audio_encoder->name], keyAudioCodecName,
+ [NSNumber numberWithInt:audio_encoder->codec], keyAudioCodec,
+ [NSNumber numberWithInt:audio_encoder->muxers], keyAudioSupportedMuxers,
+ audioMustMatchTrack, keyAudioMustMatchTrack,
+ nil]];
}
masterMixdownArray = [[NSMutableArray alloc] init]; // knowingly leaked
- for (i = 0; i < hb_audio_mixdowns_count; i++)
+ for (const hb_mixdown_t *mixdown = hb_mixdown_get_next(NULL);
+ mixdown != NULL;
+ mixdown = hb_mixdown_get_next(mixdown))
{
- [masterMixdownArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithUTF8String: hb_audio_mixdowns[i].human_readable_name], keyAudioMixdownName,
- [NSNumber numberWithInt: hb_audio_mixdowns[i].amixdown], keyAudioMixdown,
- nil]];
+ [masterMixdownArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithUTF8String:mixdown->name], keyAudioMixdownName,
+ [NSNumber numberWithInt:mixdown->amixdown], keyAudioMixdown,
+ nil]];
}
// Note that for the Auto value we use 0 for the sample rate because our controller will give back the track's
// input sample rate when it finds this 0 value as the selected sample rate. We do this because the input
// sample rate depends on the track, which means it depends on the title, so cannot be nicely set up here.
masterSampleRateArray = [[NSMutableArray alloc] init]; // knowingly leaked
- [masterSampleRateArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"Auto", @"Auto"), keyAudioSampleRateName,
- [NSNumber numberWithInt: 0], keyAudioSamplerate,
- nil]];
- for (i = 0; i < hb_audio_rates_count; i++)
+ [masterSampleRateArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithString:@"Auto"], keyAudioSampleRateName,
+ [NSNumber numberWithInt:0], keyAudioSamplerate,
+ nil]];
+ for (const hb_rate_t *audio_samplerate = hb_audio_samplerate_get_next(NULL);
+ audio_samplerate != NULL;
+ audio_samplerate = hb_audio_samplerate_get_next(audio_samplerate))
{
- [masterSampleRateArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithUTF8String: hb_audio_rates[i].string], keyAudioSampleRateName,
- [NSNumber numberWithInt: hb_audio_rates[i].rate], keyAudioSamplerate,
- nil]];
+ [masterSampleRateArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithUTF8String:audio_samplerate->name], keyAudioSampleRateName,
+ [NSNumber numberWithInt:audio_samplerate->rate], keyAudioSamplerate,
+ nil]];
}
masterBitRateArray = [[NSMutableArray alloc] init]; // knowingly leaked
- for (i = 0; i < hb_audio_bitrates_count; i++)
+ for (const hb_rate_t *audio_bitrate = hb_audio_bitrate_get_next(NULL);
+ audio_bitrate != NULL;
+ audio_bitrate = hb_audio_bitrate_get_next(audio_bitrate))
{
- dict = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSString stringWithUTF8String: hb_audio_bitrates[i].string], keyAudioBitrateName,
- [NSNumber numberWithInt: hb_audio_bitrates[i].rate], keyAudioBitrate,
- nil];
- [masterBitRateArray addObject: dict];
+ [masterBitRateArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithUTF8String:audio_bitrate->name], keyAudioBitrateName,
+ [NSNumber numberWithInt:audio_bitrate->rate], keyAudioBitrate,
+ nil]];
}
-
- [pool release];
}
}
@@ -158,21 +144,6 @@ static NSMutableArray *masterBitRateArray = nil;
NSMutableArray *permittedCodecs = [NSMutableArray array];
unsigned int count = [masterCodecArray count];
NSDictionary *dict;
- NSString *keyThatAllows = nil;
-
- // Determine which key we use to see which codecs are permitted
- switch ([videoContainerTag intValue])
- {
- case HB_MUX_MP4:
- keyThatAllows = keyAudioMP4;
- break;
- case HB_MUX_MKV:
- keyThatAllows = keyAudioMKV;
- break;
- default:
- keyThatAllows = @"error condition";
- break;
- }
// First get a list of the permitted codecs based on the internal rules
if (nil != track && [self enabled])
@@ -184,7 +155,8 @@ static NSMutableArray *masterBitRateArray = nil;
dict = [masterCodecArray objectAtIndex: i];
// First make sure only codecs permitted by the container are here
- goodToAdd = [[dict objectForKey: keyThatAllows] boolValue];
+ goodToAdd = !!([[dict objectForKey:keyAudioSupportedMuxers] intValue] &
+ [videoContainerTag intValue]);
// Now we make sure if DTS or AC3 is not available in the track it is not put in the codec list, but in a general way
if ([[dict objectForKey: keyAudioMustMatchTrack] boolValue])
@@ -227,9 +199,9 @@ static NSMutableArray *masterBitRateArray = nil;
int currentMixdown;
unsigned long long channelLayout = [[track objectForKey: keyAudioInputChannelLayout] unsignedLongLongValue];
- unsigned int count = [masterMixdownArray count];
- int codecCodec = [[codec objectForKey: keyAudioCodec] intValue];
- int theDefaultMixdown = hb_get_default_mixdown(codecCodec, channelLayout);
+ unsigned int count = [masterMixdownArray count];
+ int codecCodec = [[codec objectForKey: keyAudioCodec] intValue];
+ int theDefaultMixdown = hb_mixdown_get_default(codecCodec, channelLayout);
for (unsigned int i = 0; i < count; i++)
{
@@ -282,10 +254,10 @@ static NSMutableArray *masterBitRateArray = nil;
theSampleRate = [[[self track] objectForKey: keyAudioInputSampleRate] intValue];
}
- int ourCodec = [[codec objectForKey: keyAudioCodec] intValue];
- int ourMixdown = [[[self mixdown] objectForKey: keyAudioMixdown] intValue];
- hb_get_audio_bitrate_limits(ourCodec, theSampleRate, ourMixdown, &minBitRate, &maxBitRate);
- int theDefaultBitRate = hb_get_default_audio_bitrate(ourCodec, theSampleRate, ourMixdown);
+ int ourCodec = [[codec objectForKey:keyAudioCodec] intValue];
+ int ourMixdown = [[[self mixdown] objectForKey:keyAudioMixdown] intValue];
+ int theDefaultBitRate = hb_audio_bitrate_get_default(ourCodec, theSampleRate, ourMixdown);
+ hb_audio_bitrate_get_limits(ourCodec, theSampleRate, ourMixdown, &minBitRate, &maxBitRate);
BOOL codecIsPassthru = ([[codec objectForKey: keyAudioCodec] intValue] & HB_ACODEC_PASS_FLAG) ? YES : NO;
BOOL codecIsLossless = (theDefaultBitRate == -1) ? YES : NO;
@@ -582,8 +554,8 @@ static NSMutableArray *masterBitRateArray = nil;
if (retval)
{
- int myCodecCodec = [[[self codec] objectForKey: keyAudioCodec] intValue];
- int myCodecDefaultBitrate = hb_get_default_audio_bitrate(myCodecCodec, 0, 0);
+ int myCodecCodec = [[[self codec] objectForKey:keyAudioCodec] intValue];
+ int myCodecDefaultBitrate = hb_audio_bitrate_get_default(myCodecCodec, 0, 0);
if (myCodecDefaultBitrate < 0)
{
retval = NO;
diff --git a/macosx/HBAudioController.m b/macosx/HBAudioController.m
index 353e24f16..52cc8284b 100644
--- a/macosx/HBAudioController.m
+++ b/macosx/HBAudioController.m
@@ -163,7 +163,7 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification";
/* We go ahead and assign values to our audio->out.<properties> */
audio->out.track = audio->in.track;
audio->out.codec = [[[anAudio codec] objectForKey:keyAudioCodec] intValue];
- audio->out.compression_level = hb_get_default_audio_compression(audio->out.codec);
+ audio->out.compression_level = hb_audio_compression_get_default(audio->out.codec);
audio->out.mixdown = [[[anAudio mixdown] objectForKey:keyAudioMixdown] intValue];
audio->out.normalize_mix_level = 0;
audio->out.bitrate = [[[anAudio bitRate] objectForKey:keyAudioBitrate] intValue];
@@ -295,46 +295,38 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification";
[newAudio setVideoContainerTag: [self videoContainerTag]];
[newAudio setTrackFromIndex: trackIndex];
- key = [dict objectForKey: @"AudioEncoder"];
-
// map faac to ca_aac for built-in presets (can be disabled in preferences)
if (0 == aType &&
- [[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] &&
- [key isEqualToString: @"AAC (faac)"])
+ [[NSUserDefaults standardUserDefaults] boolForKey:@"UseCoreAudio"] &&
+ [[dict objectForKey:@"AudioEncoder"] isEqualToString:@"AAC (faac)"])
{
- [dict setObject: @"AAC (CoreAudio)" forKey: @"AudioEncoder"];
+ key = @"AAC (CoreAudio)";
}
-
- // passthru fallbacks
- if ([key isEqualToString: @"AAC Passthru"])
+ else
{
- if (![newAudio setCodecFromName: key])
- {
- [dict setObject: @"AAC (CoreAudio)" forKey: @"AudioEncoder"];
- fallenBack = YES;
- }
+ key = [dict objectForKey:@"AudioEncoder"];
}
- else if ([key isEqualToString: @"AC3 Passthru"])
+
+ // map legacy encoder names via libhb
+ if (key != nil)
{
- if (![newAudio setCodecFromName: key])
+ const char *name;
+ // passthru fallbacks
+ if ([key hasSuffix:@"Passthru"] &&
+ ![newAudio setCodecFromName:key])
{
- [dict setObject: @"AC3 (ffmpeg)" forKey: @"AudioEncoder"];
+ int passthru, fallback;
fallenBack = YES;
+ passthru = hb_audio_encoder_get_from_name([key UTF8String]);
+ fallback = hb_audio_encoder_get_fallback_for_passthru(passthru);
+ name = hb_audio_encoder_get_name(fallback);
}
- }
- else if ([key isEqualToString: @"MP3 Passthru"])
- {
- if (![newAudio setCodecFromName: key])
+ else
{
- [dict setObject: @"MP3 (lame)" forKey: @"AudioEncoder"];
- fallenBack = YES;
+ name = hb_audio_encoder_sanitize_name([key UTF8String]);
}
- }
-
- // map legacy encoder names
- if ([key isEqualToString: @"AC3"])
- {
- [dict setObject: @"AC3 (ffmpeg)" forKey: @"AudioEncoder"];
+ [dict setObject:[NSString stringWithFormat:@"%s", name]
+ forKey:@"AudioEncoder"];
}
// If our preset does not contain a drc or gain value set it to a default of 0.0
@@ -347,17 +339,13 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification";
[dict setObject:[NSNumber numberWithFloat:0.0] forKey:@"AudioTrackGainSlider"];
}
- // map legacy mixdowns
+ // map legacy mixdowns via libhb
key = [dict objectForKey: @"AudioMixdown"];
- if ([key isEqualToString: @"AC3 Passthru"] ||
- [key isEqualToString: @"DTS Passthru"] ||
- [key isEqualToString: @"DTS-HD Passthru"])
- {
- [dict setObject: @"None" forKey: @"AudioMixdown"];
- }
- else if ([key isEqualToString: @"6-channel discrete"])
+ if (key != nil)
{
- [dict setObject: @"5.1 Channels" forKey: @"AudioMixdown"];
+ [dict setObject:[NSString stringWithFormat:@"%s",
+ hb_mixdown_sanitize_name([key UTF8String])]
+ forKey:@"AudioMixdown"];
}
// If our preset wants us to support a codec that the track does not support, instead
diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m
index aaf6ec36c..5d132a12e 100644
--- a/macosx/HBPreviewController.m
+++ b/macosx/HBPreviewController.m
@@ -729,12 +729,12 @@
}
/* Destination file. We set this to our preview directory
* changing the extension appropriately.*/
- if (fTitle->job->mux == HB_MUX_MP4) // MP4 file
+ if (fTitle->job->mux & HB_MUX_MASK_MP4) // MP4 file
{
/* we use .m4v for our mp4 files so that ac3 and chapters in mp4 will play properly */
fPreviewMoviePath = [PreviewDirectory stringByAppendingString:@"/preview_temp.m4v"];
}
- else if (fTitle->job->mux == HB_MUX_MKV) // MKV file
+ else if (fTitle->job->mux & HB_MUX_MASK_MKV) // MKV file
{
fPreviewMoviePath = [PreviewDirectory stringByAppendingString:@"/preview_temp.mkv"];
}
diff --git a/macosx/HBSubtitles.m b/macosx/HBSubtitles.m
index d8b4b6989..989374e37 100644
--- a/macosx/HBSubtitles.m
+++ b/macosx/HBSubtitles.m
@@ -801,7 +801,7 @@
* by default to avoid massive confusion and anarchy. However we also want to guard against multiple burned in subtitle tracks
* as libhb would ignore all but the first one anyway. Plus it would probably be stupid.
*/
- if (container == HB_MUX_MP4 && [anObject intValue] != 0)
+ if ((container & HB_MUX_MASK_MP4) && ([anObject intValue] != 0))
{
if ([[[subtitleArray objectAtIndex:rowIndex] objectForKey:@"subtitleSourceTrackType"] intValue] == VOBSUB)
{
diff --git a/scripts/manicure.rb b/scripts/manicure.rb
index 4dc9b8db7..c6d2cdc3f 100755
--- a/scripts/manicure.rb
+++ b/scripts/manicure.rb
@@ -273,9 +273,9 @@ class Display
#Filename suffix
case hash["FileFormat"]
- when /MP4/
+ when /MPEG-4/, /MP4/
commandString << "mp4 "
- when /MKV/
+ when /Matroska/, /MKV/
commandString << "mkv "
end
@@ -477,8 +477,12 @@ class Display
#Container
commandString << " -f "
case hash["FileFormat"]
+ when "MPEG-4 (mp4v2)"
+ commandString << "mp4v2"
when /MP4/
commandString << "mp4"
+ when "Matroska (libmkv)"
+ commandString << "libmkv"
when /MKV/
commandString << "mkv"
end
@@ -861,8 +865,12 @@ class Display
#Container
commandString << " -f "
case hash["FileFormat"]
+ when "MPEG-4 (mp4v2)"
+ commandString << "mp4v2"
when /MP4/
commandString << "mp4"
+ when "Matroska (libmkv)"
+ commandString << "libmkv"
when /MKV/
commandString << "mkv"
end
@@ -1020,13 +1028,17 @@ class Display
commandString = "if (!strcasecmp(preset_name, \"" << hash["PresetName"] << "\"))\n{\n "
- #Filename suffix
+ #Container
commandString << "if( !mux )\n "
commandString << "{\n "
case hash["FileFormat"]
+ when "MPEG-4 (mp4v2)"
+ commandString << " mux = " << "HB_MUX_MP4V2;\n "
when /MP4/
commandString << " mux = " << "HB_MUX_MP4;\n "
+ when "Matroska (libmkv)"
+ commandString << " mux = " << "HB_MUX_LIBMKV;\n "
when /MKV/
commandString << " mux = " << "HB_MUX_MKV;\n "
end
@@ -1693,8 +1705,12 @@ class Display
#Container
commandString << " -f "
case hash["FileFormat"]
+ when "MPEG-4 (mp4v2)"
+ commandString << "mp4v2"
when /MP4/
commandString << "mp4"
+ when "Matroska (libmkv)"
+ commandString << "libmkv"
when /MKV/
commandString << "mkv"
end
diff --git a/test/test.c b/test/test.c
index efa7ae227..05b415043 100644
--- a/test/test.c
+++ b/test/test.c
@@ -153,11 +153,6 @@ static int ParseOptions( int argc, char ** argv );
static int CheckOptions( int argc, char ** argv );
static int HandleEvents( hb_handle_t * h );
-static int get_dither_for_string(const char *dither);
-static int get_acodec_for_string(const char *codec);
-static const char* get_string_for_acodec(int acodec);
-
-static int is_sample_rate_valid(int rate);
static void str_vfree( char **strv );
static char** str_split( char *str, char delem );
@@ -578,7 +573,7 @@ static int HandleEvents( hb_handle_t * h )
{
hb_state_t s;
int tmp_num_audio_tracks;
- int filter_vrate, filter_vrate_base, filter_cfr;
+ int filter_cfr, filter_vrate, filter_vrate_base;
hb_get_state( h, &s );
switch( s.state )
@@ -688,10 +683,10 @@ static int HandleEvents( hb_handle_t * h )
PrintTitleInfo( title, title_set->feature );
/* Set job settings */
- job = hb_job_init( title );
- filter_vrate = job->vrate;
+ job = hb_job_init(title);
+ filter_cfr = job->cfr;
+ filter_vrate = job->vrate;
filter_vrate_base = job->vrate_base;
- filter_cfr = job->cfr;
if( chapter_start && chapter_end && !stop_at_pts && !start_at_preview && !stop_at_frame && !start_at_pts && !start_at_frame )
@@ -1756,25 +1751,25 @@ static int HandleEvents( hb_handle_t * h )
free( filter_str );
// Add framerate shaping filter
- if( vrate )
+ if (vrate)
{
- filter_cfr = cfr;
- filter_vrate = 27000000;
+ filter_cfr = cfr;
+ filter_vrate = 27000000;
filter_vrate_base = vrate;
}
- else if ( cfr )
+ else if (cfr)
{
// cfr or pfr flag with no rate specified implies
// use the title rate.
- filter_cfr = cfr;
- filter_vrate = title->rate;
+ filter_cfr = cfr;
+ filter_vrate = title->rate;
filter_vrate_base = title->rate_base;
}
- filter_str = hb_strdup_printf("%d:%d:%d",
- filter_cfr, filter_vrate, filter_vrate_base );
- filter = hb_filter_init( HB_FILTER_VFR );
- hb_add_filter( job, filter, filter_str );
- free( filter_str );
+ filter = hb_filter_init(HB_FILTER_VFR);
+ filter_str = hb_strdup_printf("%d:%d:%d", filter_cfr, filter_vrate,
+ filter_vrate_base);
+ hb_add_filter(job, filter, filter_str);
+ free(filter_str);
// hb_job_init() will set a default muxer for us
// only override it if a specific muxer has been set
@@ -1966,10 +1961,10 @@ static int HandleEvents( hb_handle_t * h )
token = acodecs;
while ( token != NULL )
{
- if ((acodec = get_acodec_for_string(token)) == -1)
+ if ((acodec = hb_audio_encoder_get_from_name(token)) == -1)
{
fprintf(stderr, "Invalid codec %s, using default for container.\n", token);
- acodec = hb_get_default_audio_encoder(job->mux);
+ acodec = hb_audio_encoder_get_default(job->mux);
}
if( i < num_audio_tracks )
{
@@ -2007,7 +2002,7 @@ static int HandleEvents( hb_handle_t * h )
* then use that codec instead.
*/
if (i != 1)
- acodec = hb_get_default_audio_encoder(job->mux);
+ acodec = hb_audio_encoder_get_default(job->mux);
for ( ; i < num_audio_tracks; i++)
{
audio = hb_list_audio_config_item(job->list_audio, i);
@@ -2026,18 +2021,7 @@ static int HandleEvents( hb_handle_t * h )
token = arates;
while ( token != NULL )
{
- arate = atoi(token);
audio = hb_list_audio_config_item(job->list_audio, i);
- int j;
-
- for( j = 0; j < hb_audio_rates_count; j++ )
- {
- if( !strcmp( token, hb_audio_rates[j].string ) )
- {
- arate = hb_audio_rates[j].rate;
- break;
- }
- }
if( audio != NULL )
{
@@ -2046,9 +2030,15 @@ static int HandleEvents( hb_handle_t * h )
arate = audio->in.samplerate;
auto_sample_rate = 1;
}
- if (!is_sample_rate_valid(arate))
+ else
+ {
+ arate = hb_audio_samplerate_get_from_name(token);
+ }
+ if (arate == -1)
{
- fprintf(stderr, "Invalid sample rate %d, using input rate %d\n", arate, audio->in.samplerate);
+ fprintf(stderr,
+ "Invalid sample rate %s, using input rate %d\n",
+ token, audio->in.samplerate);
arate = audio->in.samplerate;
}
@@ -2091,8 +2081,8 @@ static int HandleEvents( hb_handle_t * h )
token = mixdowns;
while ( token != NULL )
{
- mixdown = hb_mixdown_get_mixdown_from_short_name(token);
- audio = hb_list_audio_config_item(job->list_audio, i);
+ mixdown = hb_mixdown_get_from_name(token);
+ audio = hb_list_audio_config_item(job->list_audio, i);
if( audio != NULL )
{
audio->out.mixdown = mixdown;
@@ -2299,8 +2289,8 @@ static int HandleEvents( hb_handle_t * h )
int dither_method = hb_audio_dither_get_default();
for (i = 0; audio_dither[i] != NULL; i++)
{
- dither_method = get_dither_for_string(audio_dither[i]);
- audio = hb_list_audio_config_item(job->list_audio, i);
+ dither_method = hb_audio_dither_get_from_name(audio_dither[i]);
+ audio = hb_list_audio_config_item(job->list_audio, i);
if (audio != NULL)
{
if (hb_audio_dither_is_supported(audio->out.codec))
@@ -2422,45 +2412,41 @@ static int HandleEvents( hb_handle_t * h )
{
// Auto Passthru
job->acodec_copy_mask = allowed_audio_copy == -1 ? HB_ACODEC_PASS_MASK : allowed_audio_copy;
- job->acodec_fallback = acodec_fallback ? get_acodec_for_string( acodec_fallback ) : 0;
+ 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;
+ 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 ) )
{
- if( audio->out.codec == HB_ACODEC_AAC_PASS )
- {
- fprintf( stderr, "AAC Passthru requested and input codec is not AAC for track %d, using AAC encoder\n",
- audio->out.track );
- audio->out.codec = hb_audio_encoders[0].encoder;
- }
- else if( audio->out.codec == HB_ACODEC_AC3_PASS )
- {
- fprintf( stderr, "AC3 Passthru requested and input codec is not AC3 for track %d, using AC3 encoder\n",
- audio->out.track );
- audio->out.codec = HB_ACODEC_AC3;
- }
- else if( audio->out.codec == HB_ACODEC_MP3_PASS )
- {
- fprintf( stderr, "MP3 Passthru requested and input codec is not MP3 for track %d, using MP3 encoder\n",
- audio->out.track );
- audio->out.codec = HB_ACODEC_LAME;
- }
- else
+ // passthru fallbacks
+ int requested_passthru = audio->out.codec;
+ audio->out.codec =
+ hb_audio_encoder_get_fallback_for_passthru(requested_passthru);
+ if (!(audio->out.codec & HB_ACODEC_MASK))
{
// Passthru not possible, drop audio.
- fprintf( stderr, "Passthru requested and input codec is not the same as output codec for track %d, dropping track\n",
- audio->out.track );
- hb_audio_t * item = hb_list_item( job->list_audio, i );
- hb_list_rem( job->list_audio, item );
+ fprintf(stderr,
+ "Passthru requested and input codec is not the same as output codec for track %d, dropping track\n",
+ audio->out.track);
+ hb_audio_t *item = hb_list_item(job->list_audio, i);
+ hb_list_rem(job->list_audio, item);
+ hb_audio_close(&item);
continue;
}
+ fprintf(stderr,
+ "%s requested and input codec is not compatible for track %d, using %s encoder\n",
+ hb_audio_encoder_get_name(requested_passthru), audio->out.track,
+ hb_audio_encoder_get_name(audio->out.codec));
// we didn't drop the track, set the mixdown and bitrate from libhb defaults
- audio->out.mixdown = hb_get_default_mixdown( audio->out.codec, audio->in.channel_layout );
- audio->out.bitrate = hb_get_default_audio_bitrate( audio->out.codec, audio->out.samplerate,
- audio->out.mixdown );
+ audio->out.mixdown =
+ hb_mixdown_get_default(audio->out.codec,
+ audio->in.channel_layout);
+ audio->out.bitrate =
+ hb_audio_bitrate_get_default(audio->out.codec,
+ audio->out.samplerate,
+ audio->out.mixdown);
}
// we didn't drop the track
i++;
@@ -2891,7 +2877,13 @@ void SigHandler( int i_signal )
****************************************************************************/
static void ShowHelp()
{
- int i, j, len;
+ int i, len;
+ const char *name;
+ const hb_rate_t *rate;
+ const hb_dither_t *dither;
+ const hb_mixdown_t *mixdown;
+ const hb_encoder_t *encoder;
+ const hb_container_t *container;
FILE* const out = stdout;
const char * const *x264_opts;
char tmp[80];
@@ -2934,8 +2926,22 @@ static void ShowHelp()
"### Destination Options------------------------------------------------------\n\n"
" -o, --output <string> Set output file name\n"
- " -f, --format <string> Set output format (mp4/mkv, default:\n"
- " autodetected from file name)\n"
+ " -f, --format <string> Set output container format (");
+ container = NULL;
+ while ((container = hb_container_get_next(container)) != NULL)
+ {
+ fprintf(out, "%s", container->short_name);
+ if (hb_container_get_next(container) != NULL)
+ {
+ fprintf(out, "/");
+ }
+ else
+ {
+ fprintf(out, ")\n");
+ }
+ }
+ fprintf(out,
+ " (default: autodetected from file name)\n"
" -m, --markers Add chapter markers\n"
" -4, --large-file Create 64-bit mp4 files that can hold more than 4 GB\n"
" of data. Note: breaks pre-iOS iPod compatibility.\n"
@@ -2947,23 +2953,24 @@ static void ShowHelp()
"### Video Options------------------------------------------------------------\n\n"
" -e, --encoder <string> Set video library encoder\n"
" Options: " );
- for( i = 0; i < hb_video_encoders_count; i++ )
+ encoder = NULL;
+ while ((encoder = hb_video_encoder_get_next(encoder)) != NULL)
{
- fprintf( out, "%s", hb_video_encoders[i].short_name );
- if( i != hb_video_encoders_count - 1 )
- fprintf( out, "/" );
+ fprintf(out, "%s", encoder->short_name);
+ if (hb_video_encoder_get_next(encoder) != NULL)
+ {
+ fprintf(out, "/");
+ }
else
- fprintf( out, "\n" );
- }
- for( i = 0; i < hb_video_encoders_count; i++ )
- {
- if( hb_video_encoders[i].encoder == vcodec )
{
- fprintf( out, " (default: %s)\n",
- hb_video_encoders[i].short_name );
- break;
+ fprintf(out, "\n");
+ }
+ if (encoder->codec == vcodec)
+ {
+ name = encoder->short_name;
}
}
+ fprintf(out, " (default: %s)\n", name);
fprintf( out,
" --x264-preset When using x264, selects the x264 preset:\n"
" <string> ");
@@ -3060,11 +3067,14 @@ static void ShowHelp()
" -T, --turbo When using 2-pass use \"turbo\" options on the\n"
" 1st pass to improve speed (only works with x264)\n"
" -r, --rate Set video framerate (" );
- for( i = 0; i < hb_video_rates_count; i++ )
+ rate = NULL;
+ while ((rate = hb_video_framerate_get_next(rate)) != NULL)
{
- fprintf( out, "%s", hb_video_rates[i].string );
- if( i != hb_video_rates_count - 1 )
- fprintf( out, "/" );
+ fprintf(out, "%s", rate->name);
+ if (hb_video_framerate_get_next(rate) != NULL)
+ {
+ fprintf(out, "/");
+ }
}
fprintf( out, ")\n"
" Be aware that not specifying a framerate lets\n"
@@ -3088,33 +3098,44 @@ static void ShowHelp()
" tracks, default: first one).\n"
" Multiple output tracks can be used for one input.\n"
" -E, --aencoder <string> Audio encoder(s):\n" );
- for (i = 0; i < hb_audio_encoders_count; i++)
+ encoder = NULL;
+ while ((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
{
fprintf(out, " %s\n",
- hb_audio_encoders[i].short_name);
+ encoder->short_name);
}
fprintf(out,
" copy:* will passthrough the corresponding\n"
" audio unmodified to the muxer if it is a\n"
" supported passthrough audio type.\n"
" Separated by commas for more than one audio track.\n"
- " (default: %s for mp4, %s for mkv)\n",
- get_string_for_acodec(hb_get_default_audio_encoder(HB_MUX_MP4)),
- get_string_for_acodec(hb_get_default_audio_encoder(HB_MUX_MKV)));
+ " Defaults:\n");
+ container = NULL;
+ while ((container = hb_container_get_next(container)) != NULL)
+ {
+ int audio_encoder = hb_audio_encoder_get_default(container->format);
+ fprintf(out, " %-8s %s\n",
+ container->short_name,
+ hb_audio_encoder_get_short_name(audio_encoder));
+ }
fprintf(out,
" --audio-copy-mask Set audio codecs that are permitted when the\n"
" <string> \"copy\" audio encoder option is specified\n"
" (" );
- for (i = j = 0; i < hb_audio_encoders_count; i++)
+ i = 0;
+ encoder = NULL;
+ while ((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
{
- if ((hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG) &&
- (hb_audio_encoders[i].encoder != HB_ACODEC_AUTO_PASS))
+ if ((encoder->codec & HB_ACODEC_PASS_FLAG) &&
+ (encoder->codec != HB_ACODEC_AUTO_PASS))
{
- if (j)
+ if (i)
+ {
fprintf(out, "/");
+ }
+ i = 1;
// skip "copy:"
- fprintf(out, "%s", hb_audio_encoders[i].short_name + 5);
- j = 1;
+ fprintf(out, "%s", encoder->short_name + 5);
}
}
fprintf(out, ", default: all).\n"
@@ -3132,25 +3153,25 @@ static void ShowHelp()
" Separated by commas for more than one audio track.\n"
" -6, --mixdown <string> Format(s) for audio downmixing/upmixing:\n");
// skip HB_AMIXDOWN_NONE
- for (i = 1; i < hb_audio_mixdowns_count; i++)
+ mixdown = hb_mixdown_get_next(NULL);
+ while((mixdown = hb_mixdown_get_next(mixdown)) != NULL)
{
fprintf(out, " %s\n",
- hb_audio_mixdowns[i].short_name);
+ mixdown->short_name);
}
fprintf(out,
" Separated by commas for more than one audio track.\n"
" Defaults:\n");
- for (i = 0; i < hb_audio_encoders_count; i++)
+ encoder = NULL;
+ while((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
{
- if (!(hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG))
+ if (!(encoder->codec & HB_ACODEC_PASS_FLAG))
{
// layout: UINT64_MAX (all channels) should work with any mixdown
- int mixdown = hb_get_default_mixdown(hb_audio_encoders[i].encoder,
- UINT64_MAX);
+ int mixdown = hb_mixdown_get_default(encoder->codec, UINT64_MAX);
// assumes that the encoder short name is <= 16 characters long
fprintf(out, " %-16s up to %s\n",
- hb_audio_encoders[i].short_name,
- hb_mixdown_get_short_name_from_mixdown(mixdown));
+ encoder->short_name, hb_mixdown_get_short_name(mixdown));
}
}
fprintf(out,
@@ -3159,11 +3180,14 @@ static void ShowHelp()
" 0 = Disable Normalization (default)\n"
" 1 = Enable Normalization\n"
" -R, --arate Set audio samplerate(s) (" );
- for( i = 0; i < hb_audio_rates_count; i++ )
+ rate = NULL;
+ while ((rate = hb_audio_samplerate_get_next(rate)) != NULL)
{
- fprintf( out, "%s", hb_audio_rates[i].string );
- if( i != hb_audio_rates_count - 1 )
- fprintf( out, "/" );
+ fprintf(out, "%s", rate->name);
+ if (hb_audio_samplerate_get_next(rate) != NULL)
+ {
+ fprintf(out, "/");
+ }
}
fprintf( out, " kHz)\n"
" Separated by commas for more than one audio track.\n"
@@ -3178,30 +3202,35 @@ static void ShowHelp()
" --adither <string> Apply dithering to the audio before encoding.\n"
" Separated by commas for more than one audio track.\n"
" Only supported by some encoders (");
- for (i = j = 0; i < hb_audio_encoders_count; i++)
+ i = 0;
+ encoder = NULL;
+ while ((encoder = hb_audio_encoder_get_next(encoder)) != NULL)
{
- if (hb_audio_dither_is_supported(hb_audio_encoders[i].encoder))
+ if (hb_audio_dither_is_supported(encoder->codec))
{
- if (j)
+ if (i)
+ {
fprintf(out, "/");
- fprintf(out, "%s", hb_audio_encoders[i].short_name);
- j = 1;
+ }
+ i = 1;
+ fprintf(out, "%s", encoder->short_name);
}
}
fprintf(out, ").\n");
fprintf(out,
" Options:\n");
- for (i = 0; i < hb_audio_dithers_count; i++)
+ dither = NULL;
+ while ((dither = hb_audio_dither_get_next(dither)) != NULL)
{
- if (hb_audio_dithers[i].method == hb_audio_dither_get_default())
+ if (dither->method == hb_audio_dither_get_default())
{
fprintf(out, " %s (default)\n",
- hb_audio_dithers[i].short_name);
+ dither->short_name);
}
else
{
fprintf(out, " %s\n",
- hb_audio_dithers[i].short_name);
+ dither->short_name);
}
}
fprintf(out,
@@ -3894,18 +3923,10 @@ static int ParseOptions( int argc, char ** argv )
break;
case 'e':
{
- int i;
- for( i = 0, vcodec = 0; i < hb_video_encoders_count; i++ )
- {
- if( !strcasecmp( hb_video_encoders[i].short_name, optarg ) )
- {
- vcodec = hb_video_encoders[i].encoder;
- break;
- }
- }
- if( !vcodec )
+ vcodec = hb_video_encoder_get_from_name(optarg);
+ if (vcodec <= 0)
{
- fprintf( stderr, "invalid codec (%s)\n", optarg );
+ fprintf(stderr, "invalid codec (%s)\n", optarg);
return -1;
}
break;
@@ -3940,21 +3961,13 @@ static int ParseOptions( int argc, char ** argv )
break;
case 'r':
{
- int i;
- vrate = 0;
- for( i = 0; i < hb_video_rates_count; i++ )
- {
- if( !strcmp( optarg, hb_video_rates[i].string ) )
- {
- vrate = hb_video_rates[i].rate;
- break;
- }
- }
- if( !vrate )
+ vrate = hb_video_framerate_get_from_name(optarg);
+ if (vrate <= 0)
{
- fprintf( stderr, "invalid framerate %s\n", optarg );
+ vrate = 0;
+ fprintf(stderr, "invalid framerate %s\n", optarg);
}
- else if ( cfr == 0 )
+ else if (!cfr)
{
cfr = 1;
}
@@ -4067,28 +4080,33 @@ static int ParseOptions( int argc, char ** argv )
}
case ALLOWED_AUDIO_COPY:
{
- int i, j;
- char **allowed = str_split( optarg, ',' );
+ allowed_audio_copy = 0;
+ const hb_encoder_t *audio_encoder = NULL;
+ char **allowed = str_split(optarg, ',');
- allowed_audio_copy = 0;
- for( i = 0; allowed[i]; i++ )
+ while ((audio_encoder = hb_audio_encoder_get_next(audio_encoder)) != NULL)
{
- for( j = 0; j < hb_audio_encoders_count; j++ )
+ if ((audio_encoder->codec & HB_ACODEC_PASS_FLAG) &&
+ (audio_encoder->codec != HB_ACODEC_AUTO_PASS))
{
- const char *encoder = hb_audio_encoders[j].short_name;
- // skip "copy:"
- if( strlen( encoder ) > 5 )
- encoder += 5;
- if( !strcmp( allowed[i], encoder ) )
+ int i = -1;
+ while(allowed[++i] != NULL)
{
- allowed_audio_copy |= hb_audio_encoders[j].encoder;
- break;
+ // skip "copy:"
+ if (!strcasecmp(allowed[i],
+ audio_encoder->short_name + 5))
+ {
+ allowed_audio_copy |= audio_encoder->codec;
+ break;
+ }
}
}
}
+
allowed_audio_copy &= HB_ACODEC_PASS_MASK;
- str_vfree( allowed );
- } break;
+ str_vfree(allowed);
+ break;
+ }
case AUDIO_FALLBACK:
acodec_fallback = strdup( optarg );
break;
@@ -4139,94 +4157,50 @@ static int CheckOptions( int argc, char ** argv )
return 1;
}
- if( !format )
+ if (format == NULL)
{
- char * p = strrchr( output, '.' );
-
/* autodetect */
- if( p && ( !strcasecmp( p, ".mp4" ) ||
- !strcasecmp( p, ".m4v" ) ) )
- {
- mux = HB_MUX_MP4;
- }
- else if( p && !strcasecmp(p, ".mkv" ) )
+ const char *extension = strrchr(output, '.');
+ if (extension != NULL)
{
- mux = HB_MUX_MKV;
+ // skip '.'
+ mux = hb_container_get_from_extension(extension + 1);
}
- else
+ if (mux <= 0)
{
- fprintf( stderr, "Output format couldn't be guessed "
- "from file name, using default.\n" );
+ fprintf(stderr,
+ "Output format can't be guessed from file name (%s), "
+ "using default.\n", output);
+ // reset the muxer (use default)
+ mux = 0;
return 0;
}
}
- else if( !strcasecmp( format, "mp4" ) ||
- !strcasecmp( format, "m4v" ) )
- {
- mux = HB_MUX_MP4;
- }
- else if( !strcasecmp( format, "mkv" ) )
- {
- mux = HB_MUX_MKV;
- }
else
{
- fprintf( stderr, "Invalid output format (%s). Possible "
- "choices are mp4, m4v and mkv\n.", format );
- return 1;
- }
- }
-
- return 0;
-}
-
-static int get_dither_for_string(const char *dither)
-{
- int i;
- for (i = 0; i < hb_audio_dithers_count; i++)
- {
- if (!strcasecmp(hb_audio_dithers[i].short_name, dither))
- {
- return hb_audio_dithers[i].method;
- }
- }
- return hb_audio_dither_get_default();
-}
-
-static int get_acodec_for_string(const char *codec)
-{
- int i;
- for (i = 0; i < hb_audio_encoders_count; i++)
- {
- if (!strcasecmp(hb_audio_encoders[i].short_name, codec))
- {
- return hb_audio_encoders[i].encoder;
- }
- }
- return -1;
-}
-
-static const char* get_string_for_acodec(int acodec)
-{
- int i;
- for (i = 0; i < hb_audio_encoders_count; i++)
- {
- if (hb_audio_encoders[i].encoder == acodec)
- {
- return hb_audio_encoders[i].short_name;
+ mux = hb_container_get_from_name(format);
+ if (mux <= 0)
+ {
+ fprintf(stderr, "Invalid output format (%s).", format);
+ fprintf(stderr, "Possible choices are: ");
+ const hb_container_t *container = NULL;
+ while ((container = hb_container_get_next(container)) != NULL)
+ {
+ fprintf(stderr, "%s", container->short_name);
+ if (hb_container_get_next(container) != NULL)
+ {
+ fprintf(stderr, ", ");
+ }
+ else
+ {
+ fprintf(stderr, "\n");
+ }
+ }
+ return 1;
+ }
}
}
- return NULL;
-}
-static int is_sample_rate_valid(int rate)
-{
- int i;
- for( i = 0; i < hb_audio_rates_count; i++ )
- {
- if (rate == hb_audio_rates[i].rate)
- return 1;
- }
return 0;
}