summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/audiohandler.c164
-rw-r--r--gtk/src/audiohandler.h4
-rw-r--r--gtk/src/hb-backend.c283
-rw-r--r--gtk/src/presets.c10
-rw-r--r--libhb/common.c150
-rw-r--r--libhb/common.h19
-rw-r--r--libhb/work.c107
-rw-r--r--macosx/Controller.m111
-rw-r--r--macosx/HBAudio.m133
-rw-r--r--macosx/HBAudioController.m8
-rw-r--r--test/test.c351
11 files changed, 731 insertions, 609 deletions
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c
index 9729f1b33..90256d6cf 100644
--- a/gtk/src/audiohandler.c
+++ b/gtk/src/audiohandler.c
@@ -26,127 +26,69 @@ static GValue* get_selected_asettings(signal_user_data_t *ud);
static gboolean block_updates = FALSE;
gint
-ghb_select_audio_codec(int mux, hb_audio_config_t *aconfig, gint acodec, gint fallback)
+ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint fallback, gint copy_mask)
{
guint32 in_codec = aconfig ? aconfig->in.codec : HB_ACODEC_MASK;
- if (mux == HB_MUX_MP4)
+ if (acodec == HB_ACODEC_AUTO_PASS)
{
- if (acodec & HB_ACODEC_PASS_FLAG)
- {
- if ((acodec & in_codec & HB_ACODEC_PASS_MASK & ~HB_ACODEC_VORBIS))
- {
- return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
- }
- else if (fallback)
- {
- return fallback;
- }
- else
- {
- return HB_ACODEC_FAAC;
- }
- }
- else if (acodec & HB_ACODEC_AC3)
- {
- return HB_ACODEC_AC3;
- }
- else if (acodec & HB_ACODEC_LAME)
- {
- return HB_ACODEC_LAME;
- }
- else if (acodec & HB_ACODEC_FAAC)
- {
- return HB_ACODEC_FAAC;
- }
- else if (acodec & HB_ACODEC_FFAAC)
- {
- return HB_ACODEC_FFAAC;
- }
- else if (fallback)
- {
- return fallback;
- }
- else
- {
- return HB_ACODEC_FAAC;
- }
+ return hb_autopassthru_get_encoder(in_codec, copy_mask, fallback, mux);
}
- else
+
+ gint ii;
+ // Sanitize fallback
+ for (ii = 0; ii < hb_audio_encoders_count; ii++)
{
- if (acodec & HB_ACODEC_PASS_FLAG)
+ if (hb_audio_encoders[ii].encoder == fallback &&
+ !(hb_audio_encoders[ii].muxers & mux))
{
- if ((acodec & in_codec & HB_ACODEC_PASS_MASK))
- {
- return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
- }
- else if (fallback)
- {
- return fallback;
- }
+ if ( mux == HB_MUX_MKV )
+ fallback = HB_ACODEC_LAME;
else
- {
- return HB_ACODEC_FAAC;
- }
+ fallback = HB_ACODEC_FAAC;
+ break;
}
- else if (acodec & HB_ACODEC_AC3)
- {
- return HB_ACODEC_AC3;
- }
- else if (acodec & HB_ACODEC_LAME)
- {
- return HB_ACODEC_LAME;
- }
- else if (acodec & HB_ACODEC_VORBIS)
- {
- return HB_ACODEC_VORBIS;
- }
- else if (acodec & HB_ACODEC_FAAC)
- {
- return HB_ACODEC_FAAC;
- }
- else if (acodec & HB_ACODEC_FFAAC)
- {
- return HB_ACODEC_FFAAC;
- }
- else if (fallback )
+ }
+ if ((acodec & HB_ACODEC_PASS_FLAG) &&
+ !(acodec & in_codec & HB_ACODEC_PASS_MASK))
+ {
+ return fallback;
+ }
+ for (ii = 0; ii < hb_audio_encoders_count; ii++)
+ {
+ if (hb_audio_encoders[ii].encoder == acodec &&
+ !(hb_audio_encoders[ii].muxers & mux))
{
return fallback;
}
- else
- {
- return HB_ACODEC_LAME;
- }
}
+ return acodec;
}
-int ghb_allowed_passthru_mask(GValue *settings, int acodec)
+int ghb_get_copy_mask(GValue *settings)
{
- gint ret = acodec;
-
- if (acodec == HB_ACODEC_ANY)
- {
- if (!ghb_settings_get_boolean(settings, "AudioAllowMP3Pass"))
- {
- ret &= ~HB_ACODEC_MP3;
- }
- if (!ghb_settings_get_boolean(settings, "AudioAllowAACPass"))
- {
- ret &= ~HB_ACODEC_FFAAC;
- }
- if (!ghb_settings_get_boolean(settings, "AudioAllowAC3Pass"))
- {
- ret &= ~HB_ACODEC_AC3;
- }
- if (!ghb_settings_get_boolean(settings, "AudioAllowDTSPass"))
- {
- ret &= ~HB_ACODEC_DCA;
- }
- if (!ghb_settings_get_boolean(settings, "AudioAllowDTSHDPass"))
- {
- ret &= ~HB_ACODEC_DCA_HD;
- }
- }
- return ret;
+ gint mask = 0;
+
+ if (ghb_settings_get_boolean(settings, "AudioAllowMP3Pass"))
+ {
+ mask |= HB_ACODEC_MP3;
+ }
+ if (ghb_settings_get_boolean(settings, "AudioAllowAACPass"))
+ {
+ mask |= HB_ACODEC_FFAAC;
+ }
+ if (ghb_settings_get_boolean(settings, "AudioAllowAC3Pass"))
+ {
+ mask |= HB_ACODEC_AC3;
+ }
+ if (ghb_settings_get_boolean(settings, "AudioAllowDTSPass"))
+ {
+ mask |= HB_ACODEC_DCA;
+ }
+ if (ghb_settings_get_boolean(settings, "AudioAllowDTSHDPass"))
+ {
+ mask |= HB_ACODEC_DCA_HD;
+ }
+ return mask;
}
static int ghb_select_fallback( GValue *settings, int mux, int acodec )
@@ -223,8 +165,8 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
sr = aconfig ? aconfig->in.samplerate : 48000;
}
gint fallback = ghb_select_fallback( ud->settings, mux, acodec );
- select_acodec = ghb_allowed_passthru_mask(ud->settings, acodec);
- select_acodec = ghb_select_audio_codec(mux, aconfig, select_acodec, fallback);
+ gint copy_mask = ghb_get_copy_mask(ud->settings);
+ select_acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback, copy_mask);
gboolean codec_defined_bitrate = FALSE;
if (ghb_audio_is_passthru (select_acodec))
{
@@ -339,8 +281,8 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud)
audio = ghb_array_get_nth(pref_audio, ii);
acodec = ghb_settings_combo_int(audio, "AudioEncoder");
fallback = ghb_select_fallback( ud->settings, mux, acodec );
- select_acodec = ghb_allowed_passthru_mask(ud->settings, acodec);
- select_acodec = ghb_select_audio_codec(mux, NULL, select_acodec, fallback);
+ gint copy_mask = ghb_get_copy_mask(ud->settings);
+ select_acodec = ghb_select_audio_codec(mux, NULL, acodec, fallback, copy_mask);
bitrate = ghb_settings_combo_int(audio, "AudioBitrate");
rate = ghb_settings_combo_double(audio, "AudioSamplerate");
mix = ghb_settings_combo_int(audio, "AudioMixdown");
@@ -361,7 +303,7 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud)
// HB_ACODEC_* are bit fields. Treat acodec as mask
if (!(aconfig->in.codec & select_acodec & HB_ACODEC_PASS_MASK))
{
- if (acodec != HB_ACODEC_ANY)
+ if (acodec != HB_ACODEC_AUTO_PASS)
acodec = fallback;
// If we can't substitute the passthru with a suitable
// encoder and
diff --git a/gtk/src/audiohandler.h b/gtk/src/audiohandler.h
index 74df87a3d..88ee306ae 100644
--- a/gtk/src/audiohandler.h
+++ b/gtk/src/audiohandler.h
@@ -34,7 +34,7 @@ void ghb_set_audio(signal_user_data_t *ud, GValue *settings);
gchar* ghb_get_user_audio_lang(
signal_user_data_t *ud, gint titleindex, gint track);
void ghb_audio_list_refresh_selected(signal_user_data_t *ud);
-int ghb_allowed_passthru_mask(GValue *settings, int acodec);
-gint ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, int fallback_acodec);
+gint ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec, gint fallback_acodec, gint copy_mask);
+int ghb_get_copy_mask(GValue *settings);
#endif // _AUDIOHANDLER_H_
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c
index 400246f5f..733340784 100644
--- a/gtk/src/hb-backend.c
+++ b/gtk/src/hb-backend.c
@@ -236,53 +236,6 @@ combo_opts_t denoise_opts =
d_denoise_opts
};
-static options_map_t d_vcodec_opts[] =
-{
- {"H.264 (x264)", "x264", HB_VCODEC_X264, ""},
- {"MPEG-4 (FFmpeg)", "ffmpeg", HB_VCODEC_FFMPEG_MPEG4, ""},
- {"MPEG-2 (FFmpeg)", "ffmpeg2",HB_VCODEC_FFMPEG_MPEG2, ""},
- {"VP3 (Theora)", "theora", HB_VCODEC_THEORA, ""},
-};
-combo_opts_t vcodec_opts =
-{
- sizeof(d_vcodec_opts)/sizeof(options_map_t),
- d_vcodec_opts
-};
-
-static options_map_t d_acodec_opts[] =
-{
- {"AAC (faac)", "faac", HB_ACODEC_FAAC, "faac"},
- {"AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, "ffaac"},
- {"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"},
- {"Vorbis", "vorbis", HB_ACODEC_VORBIS, "vorbis"},
- {"AC3 (ffmpeg)", "ac3", HB_ACODEC_AC3, "ac3"},
- {"MP3 Passthru", "mp3pass", HB_ACODEC_MP3_PASS, "mp3pass"},
- {"AAC Passthru", "aacpass", HB_ACODEC_AAC_PASS, "aacpass"},
- {"AC3 Passthru", "ac3pass", HB_ACODEC_AC3_PASS, "ac3pass"},
- {"DTS Passthru", "dtspass", HB_ACODEC_DCA_PASS, "dtspass"},
- {"DTS-HD Passthru", "dtshdpass", HB_ACODEC_DCA_HD_PASS, "dtshdpass"},
- {"Auto Passthru", "auto", HB_ACODEC_ANY, "auto"},
-};
-combo_opts_t acodec_opts =
-{
- sizeof(d_acodec_opts)/sizeof(options_map_t),
- d_acodec_opts
-};
-
-static options_map_t d_acodec_fallback_opts[] =
-{
- {"AAC (faac)", "faac", HB_ACODEC_FAAC, "faac"},
- {"AAC (ffmpeg)", "ffaac", HB_ACODEC_FFAAC, "ffaac"},
- {"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"},
- {"Vorbis", "vorbis", HB_ACODEC_VORBIS, "vorbis"},
- {"AC3 (ffmpeg)", "ac3", HB_ACODEC_AC3, "ac3"},
-};
-combo_opts_t acodec_fallback_opts =
-{
- sizeof(d_acodec_fallback_opts)/sizeof(options_map_t),
- d_acodec_fallback_opts
-};
-
static options_map_t d_direct_opts[] =
{
{"None", "none", 0, "none"},
@@ -432,10 +385,6 @@ combo_name_map_t combo_name_map[] =
{"PictureDecomb", &decomb_opts},
{"PictureDetelecine", &detel_opts},
{"PictureDenoise", &denoise_opts},
- {"VideoEncoder", &vcodec_opts},
- {"AudioEncoder", &acodec_opts},
- {"AudioEncoderActual", &acodec_opts},
- {"AudioEncoderFallback", &acodec_fallback_opts},
{"x264_direct", &direct_opts},
{"x264_b_adapt", &badapt_opts},
{"x264_bpyramid", &bpyramid_opts},
@@ -1229,6 +1178,111 @@ lookup_audio_bitrate_option(const GValue *rate)
}
static gint
+lookup_hb_encoder_int(const GValue *enc, hb_encoder_t *encoders, int len)
+{
+ gint ii;
+
+ if (G_VALUE_TYPE(enc) == G_TYPE_STRING)
+ {
+ gchar *str = ghb_value_string(enc);
+ for (ii = 0; ii < len; ii++)
+ {
+ if (strcmp(encoders[ii].human_readable_name, str) == 0 ||
+ strcmp(encoders[ii].short_name, str) == 0)
+ {
+ g_free(str);
+ return encoders[ii].encoder;
+ }
+ }
+ 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].encoder;
+ }
+ }
+ }
+ return 0;
+}
+
+static const gchar*
+lookup_hb_encoder_option(const GValue *enc, hb_encoder_t *encoders, int len)
+{
+ gint ii;
+
+ if (G_VALUE_TYPE(enc) == G_TYPE_STRING)
+ {
+ gchar *str = ghb_value_string(enc);
+ for (ii = 0; ii < len; ii++)
+ {
+ 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;
+ }
+ }
+ 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;
+}
+
+static const gchar*
+lookup_hb_encoder_string(const GValue *enc, hb_encoder_t *encoders, int len)
+{
+ gint ii;
+
+ if (G_VALUE_TYPE(enc) == G_TYPE_STRING)
+ {
+ gchar *str = ghb_value_string(enc);
+ for (ii = 0; ii < len; ii++)
+ {
+ if (strcmp(encoders[ii].human_readable_name, str) == 0 ||
+ strcmp(encoders[ii].short_name, str) == 0)
+ {
+ g_free(str);
+ return encoders[ii].short_name;
+ }
+ }
+ 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].short_name;
+ }
+ }
+ }
+ return 0;
+}
+
+static gint
lookup_audio_lang_int(const GValue *rate)
{
gint ii;
@@ -1281,15 +1335,15 @@ ghb_lookup_acodec_value(gint val)
GValue *value = NULL;
gint ii;
- for (ii = 0; ii < acodec_opts.count; ii++)
+ for (ii = 0; ii < hb_audio_encoders_count; ii++)
{
- if ((int)acodec_opts.map[ii].ivalue == val)
+ if ((int)hb_audio_encoders[ii].encoder == val)
{
- value = ghb_string_value_new(acodec_opts.map[ii].shortOpt);
+ value = ghb_string_value_new(hb_audio_encoders[ii].short_name);
return value;
}
}
- value = ghb_string_value_new("auto");
+ value = ghb_string_value_new("copy");
return value;
}
@@ -1644,9 +1698,9 @@ ghb_grey_combo_options(signal_user_data_t *ud)
allow_6ch = acodec & ~HB_ACODEC_LAME;
if (aconfig)
{
- acodec = ghb_allowed_passthru_mask(ud->settings, acodec);
fallback = ghb_settings_combo_int(ud->settings, "AudioEncoderFallback");
- acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback);
+ gint copy_mask = ghb_get_copy_mask(ud->settings);
+ acodec = ghb_select_audio_codec(mux, aconfig, acodec, fallback, copy_mask);
gint best = hb_get_best_mixdown(acodec, aconfig->in.channel_layout, 0);
allow_stereo = best >= HB_AMIXDOWN_STEREO;
@@ -1792,6 +1846,60 @@ video_rate_opts_set(GtkBuilder *builder, const gchar *name, hb_rate_t *rates, gi
}
static void
+hb_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");
+ store = get_combo_box_store(builder, name);
+ gtk_list_store_clear(store);
+ for (ii = 0; ii < len; ii++)
+ {
+ if ((mask & encoders[ii].encoder) &&
+ !(neg_mask & encoders[ii].encoder))
+ {
+ gtk_list_store_append(store, &iter);
+ str = g_strdup_printf("<small>%s</small>",
+ encoders[ii].human_readable_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,
+ -1);
+ g_free(str);
+ }
+ }
+}
+
+static void
+hb_encoder_opts_set(
+ GtkBuilder *builder,
+ const gchar *name,
+ hb_encoder_t *encoders,
+ int len)
+{
+ hb_encoder_opts_set_with_mask(builder, name, encoders, len, ~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);
+}
+
+static void
mix_opts_set(GtkBuilder *builder, const gchar *name)
{
GtkTreeIter iter;
@@ -1802,14 +1910,6 @@ mix_opts_set(GtkBuilder *builder, const gchar *name)
g_debug("mix_opts_set ()\n");
store = get_combo_box_store(builder, name);
gtk_list_store_clear(store);
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter,
- 0, "<small>None</small>",
- 1, TRUE,
- 2, "none",
- 3, 0.0,
- 4, "none",
- -1);
for (ii = 0; ii < hb_audio_mixdowns_count; ii++)
{
gtk_list_store_append(store, &iter);
@@ -2689,6 +2789,14 @@ ghb_lookup_combo_int(const gchar *name, const GValue *gval)
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);
+ else if (strcmp(name, "AudioEncoder") == 0)
+ return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderFallback") == 0)
+ return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderActual") == 0)
+ return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
else
{
return lookup_generic_int(find_combo_table(name), gval);
@@ -2714,6 +2822,14 @@ ghb_lookup_combo_double(const gchar *name, const GValue *gval)
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);
+ else if (strcmp(name, "AudioEncoder") == 0)
+ return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderFallback") == 0)
+ return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderActual") == 0)
+ return lookup_hb_encoder_int(gval, hb_audio_encoders, hb_audio_encoders_count);
else
{
return lookup_generic_double(find_combo_table(name), gval);
@@ -2739,6 +2855,14 @@ ghb_lookup_combo_option(const gchar *name, const GValue *gval)
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);
+ else if (strcmp(name, "AudioEncoder") == 0)
+ return lookup_hb_encoder_option(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderFallback") == 0)
+ return lookup_hb_encoder_option(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderActual") == 0)
+ return lookup_hb_encoder_option(gval, hb_audio_encoders, hb_audio_encoders_count);
else
{
return lookup_generic_option(find_combo_table(name), gval);
@@ -2764,6 +2888,14 @@ ghb_lookup_combo_string(const gchar *name, const GValue *gval)
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);
+ else if (strcmp(name, "AudioEncoder") == 0)
+ return lookup_hb_encoder_string(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderFallback") == 0)
+ return lookup_hb_encoder_string(gval, hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderActual") == 0)
+ return lookup_hb_encoder_string(gval, hb_audio_encoders, hb_audio_encoders_count);
else
{
return lookup_generic_string(find_combo_table(name), gval);
@@ -2809,6 +2941,9 @@ ghb_update_ui_combo_box(
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);
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);
+ acodec_fallback_opts_set(ud->builder, "AudioEncoderFallback");
language_opts_set(ud->builder, "SrtLanguage");
language_opts_set(ud->builder, "PreferredLanguage");
srt_codeset_opts_set(ud->builder, "SrtCodeset");
@@ -2828,9 +2963,6 @@ ghb_update_ui_combo_box(
generic_opts_set(ud->builder, "PictureDetelecine", &detel_opts);
generic_opts_set(ud->builder, "PictureDecomb", &decomb_opts);
generic_opts_set(ud->builder, "PictureDenoise", &denoise_opts);
- generic_opts_set(ud->builder, "VideoEncoder", &vcodec_opts);
- small_opts_set(ud->builder, "AudioEncoder", &acodec_opts);
- small_opts_set(ud->builder, "AudioEncoderFallback", &acodec_fallback_opts);
small_opts_set(ud->builder, "x264_direct", &direct_opts);
small_opts_set(ud->builder, "x264_b_adapt", &badapt_opts);
small_opts_set(ud->builder, "x264_bpyramid", &bpyramid_opts);
@@ -2850,6 +2982,12 @@ ghb_update_ui_combo_box(
video_rate_opts_set(ud->builder, "VideoFramerate", hb_video_rates, hb_video_rates_count);
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);
+ else if (strcmp(name, "AudioEncoder") == 0)
+ hb_encoder_opts_set(ud->builder, "AudioEncoder", hb_audio_encoders, hb_audio_encoders_count);
+ else if (strcmp(name, "AudioEncoderFallback") == 0)
+ acodec_fallback_opts_set(ud->builder, "AudioEncoderFallback");
else if (strcmp(name, "SrtLanguage") == 0)
language_opts_set(ud->builder, "SrtLanguage");
else if (strcmp(name, "PreferredLanguage") == 0)
@@ -2885,6 +3023,9 @@ init_ui_combo_boxes(GtkBuilder *builder)
init_combo_box(builder, "SrtCodeset");
init_combo_box(builder, "title");
init_combo_box(builder, "AudioTrack");
+ init_combo_box(builder, "VideoEncoder");
+ init_combo_box(builder, "AudioEncoder");
+ init_combo_box(builder, "AudioEncoderFallback");
for (ii = 0; combo_name_map[ii].name != NULL; ii++)
{
init_combo_box(builder, combo_name_map[ii].name);
@@ -4236,7 +4377,7 @@ ghb_validate_audio(signal_user_data_t *ud)
asettings = ghb_array_get_nth(audio_list, ii);
gint track = ghb_settings_combo_int(asettings, "AudioTrack");
gint codec = ghb_settings_combo_int(asettings, "AudioEncoder");
- if (codec == HB_ACODEC_ANY)
+ if (codec == HB_ACODEC_AUTO_PASS)
continue;
aconfig = (hb_audio_config_t *) hb_list_audio_config_item(
@@ -4730,9 +4871,9 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
- acodec = ghb_allowed_passthru_mask(js, acodec);
fallback = ghb_settings_combo_int(js, "AudioEncoderFallback");
- audio.out.codec = ghb_select_audio_codec(job->mux, aconfig, acodec, fallback);
+ gint copy_mask = ghb_get_copy_mask(js);
+ audio.out.codec = ghb_select_audio_codec(job->mux, aconfig, acodec, fallback, copy_mask);
audio.out.gain =
ghb_settings_get_double(asettings, "AudioTrackGain");
diff --git a/gtk/src/presets.c b/gtk/src/presets.c
index bc87e9a14..8305c4ae3 100644
--- a/gtk/src/presets.c
+++ b/gtk/src/presets.c
@@ -1989,8 +1989,9 @@ typedef struct
static value_map_t vcodec_xlat[] =
{
{"MPEG-2 (FFmpeg)", "ffmpeg2"},
+ {"MPEG-4 (FFmpeg)", "ffmpeg4"},
{"MPEG-4 (FFmpeg)", "ffmpeg"},
- {"MPEG-4 (XviD)", "ffmpeg"},
+ {"MPEG-4 (XviD)", "ffmpeg4"},
{"H.264 (x264)", "x264"},
{"VP3 (Theora)", "theora"},
{NULL,NULL}
@@ -2002,13 +2003,20 @@ static value_map_t acodec_xlat[] =
{"AAC (faac)", "faac"},
{"AAC (CoreAudio)", "faac"},
{"HE-AAC (CoreAudio)", "faac"},
+ {"AC3 (ffmpeg)", "ffac3"},
{"AC3 (ffmpeg)", "ac3"},
{"AC3", "ac3"}, // Backwards compatibility with mac ui
+ {"MP3 Passthru", "copy:mp3"},
{"MP3 Passthru", "mp3pass"},
+ {"AAC Passthru", "copy:aac"},
{"AAC Passthru", "aacpass"},
+ {"AC3 Passthru", "copy:ac3"},
{"AC3 Passthru", "ac3pass"},
+ {"DTS Passthru", "copy:dts"},
{"DTS Passthru", "dtspass"},
+ {"DTS-HD Passthru", "copy:dtshd"},
{"DTS-HD Passthru", "dtshdpass"},
+ {"Auto Passthru", "copy"},
{"Auto Passthru", "auto"},
{"MP3 (lame)", "lame"},
{"Vorbis (vorbis)", "vorbis"},
diff --git a/libhb/common.c b/libhb/common.c
index db2fac551..f320ff2c1 100644
--- a/libhb/common.c
+++ b/libhb/common.c
@@ -41,15 +41,43 @@ int hb_audio_bitrates_count = sizeof( hb_audio_bitrates ) /
static hb_error_handler_t *error_handler = NULL;
hb_mixdown_t hb_audio_mixdowns[] =
-{ { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO },
+{ { "None", "HB_AMIXDOWN_NONE", "none", HB_AMIXDOWN_NONE },
+ { "Mono", "HB_AMIXDOWN_MONO", "mono", HB_AMIXDOWN_MONO },
{ "Stereo", "HB_AMIXDOWN_STEREO", "stereo", HB_AMIXDOWN_STEREO },
{ "Dolby Surround", "HB_AMIXDOWN_DOLBY", "dpl1", HB_AMIXDOWN_DOLBY },
{ "Dolby Pro Logic II", "HB_AMIXDOWN_DOLBYPLII", "dpl2", HB_AMIXDOWN_DOLBYPLII },
- { "6-channel discrete", "HB_AMIXDOWN_6CH", "6ch", HB_AMIXDOWN_6CH }
-};
+ { "6-channel discrete", "HB_AMIXDOWN_6CH", "6ch", HB_AMIXDOWN_6CH } };
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 } };
+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 },
+#endif
+ { "AAC (faac)", "faac", HB_ACODEC_FAAC, HB_MUX_MP4|HB_MUX_MKV },
+ { "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 },
+ { "Auto Passthru", "copy", HB_ACODEC_AUTO_PASS, HB_MUX_MP4|HB_MUX_MKV } };
+int hb_audio_encoders_count = sizeof( hb_audio_encoders ) /
+ sizeof( hb_encoder_t );
+
int hb_mixdown_get_mixdown_from_short_name( const char * short_name )
{
int i;
@@ -76,6 +104,106 @@ const char * hb_mixdown_get_short_name_from_mixdown( int amixdown )
return "";
}
+void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title )
+{
+ int i, j;
+ hb_audio_t * audio;
+ for( i = 0; i < hb_list_count( title->list_audio ); )
+ {
+ audio = hb_list_item( title->list_audio, i );
+ if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
+ {
+ 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( title->list_audio, audio );
+ free( 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 );
+ }
+ else
+ {
+ 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;
+ }
+ }
+ }
+ }
+ /* 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;
+ }
+}
+
+int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer )
+{
+ 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 work.c
+ for( i = 0; i < hb_audio_encoders_count; i++ )
+ {
+ if( ( hb_audio_encoders[i].encoder == fallback ) &&
+ !( hb_audio_encoders[i].muxers & muxer ) )
+ {
+ // fallback not possible with current muxer
+ // use the default audio encoder instead
+#ifndef __APPLE__
+ if( muxer == HB_MUX_MKV )
+ // Lame is the default for MKV
+ fallback = HB_ACODEC_LAME;
+ else
+#endif // Core Audio or faac
+ fallback = hb_audio_encoders[0].encoder;
+ break;
+ }
+ }
+ 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;
+}
+
// Given an input bitrate, find closest match in the set of allowed bitrates
int hb_find_closest_audio_bitrate(int bitrate)
{
@@ -338,7 +466,7 @@ int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown )
if (codec & HB_ACODEC_PASS_FLAG)
{
// Audio pass-thru. No mixdown.
- return 0;
+ return HB_AMIXDOWN_NONE;
}
switch (layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK)
{
@@ -1226,24 +1354,24 @@ int hb_audio_add(const hb_job_t * job, const hb_audio_config_t * audiocfg)
if( (audiocfg->in.bitrate != -1) && (audiocfg->in.codec != 0xDEADBEEF) )
{
/* This most likely means the client didn't call hb_audio_config_init
- * so bail.
- */
+ * so bail. */
return 0;
}
/* Really shouldn't ignore the passed out track, but there is currently no
- * way to handle duplicates or out-of-order track numbers.
- */
+ * way to handle duplicates or out-of-order track numbers. */
audio->config.out.track = hb_list_count(job->list_audio) + 1;
audio->config.out.codec = audiocfg->out.codec;
- if( (audiocfg->out.codec & HB_ACODEC_MASK) == (audio->config.in.codec & HB_ACODEC_MASK) &&
- (audiocfg->out.codec & HB_ACODEC_PASS_FLAG ) )
+ if((audiocfg->out.codec & HB_ACODEC_PASS_FLAG) &&
+ ((audiocfg->out.codec == HB_ACODEC_AUTO_PASS) ||
+ (audiocfg->out.codec & audio->config.in.codec & HB_ACODEC_PASS_MASK)))
{
/* Pass-through, copy from input. */
audio->config.out.samplerate = audio->config.in.samplerate;
audio->config.out.bitrate = audio->config.in.bitrate;
- audio->config.out.dynamic_range_compression = 0;
audio->config.out.mixdown = 0;
+ audio->config.out.dynamic_range_compression = 0;
+ audio->config.out.gain = 0;
}
else
{
diff --git a/libhb/common.h b/libhb/common.h
index d6024aac5..41272b93f 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -56,6 +56,7 @@ typedef struct hb_handle_s hb_handle_t;
typedef struct hb_list_s hb_list_t;
typedef struct hb_rate_s hb_rate_t;
typedef struct hb_mixdown_s hb_mixdown_t;
+typedef struct hb_encoder_s hb_encoder_t;
typedef struct hb_job_s hb_job_t;
typedef struct hb_title_s hb_title_t;
typedef struct hb_chapter_s hb_chapter_t;
@@ -126,6 +127,14 @@ struct hb_mixdown_s
int amixdown;
};
+struct hb_encoder_s
+{
+ char * human_readable_name; // note: used in presets
+ char * short_name; // note: used in CLI
+ int encoder; // HB_*CODEC_* define
+ int muxers; // supported muxers
+};
+
struct hb_subtitle_config_s
{
enum subdest { RENDERSUB, PASSTHRUSUB } dest;
@@ -149,8 +158,14 @@ extern hb_rate_t hb_audio_bitrates[];
extern int hb_audio_bitrates_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;
int hb_mixdown_get_mixdown_from_short_name( const char * short_name );
const char * hb_mixdown_get_short_name_from_mixdown( int amixdown );
+void hb_autopassthru_apply_settings( hb_job_t * job, hb_title_t * title );
+int hb_autopassthru_get_encoder( int in_codec, int copy_mask, int fallback, int muxer );
int hb_get_best_mixdown( uint32_t codec, int layout, int mixdown );
int hb_get_default_mixdown( uint32_t codec, int layout );
int hb_find_closest_audio_bitrate(int bitrate);
@@ -250,6 +265,8 @@ struct hb_job_s
/* List of audio settings. */
hb_list_t * list_audio;
+ int acodec_copy_mask; // Auto Passthru allowed codecs
+ int acodec_fallback; // Auto Passthru fallback encoder
/* Subtitles */
hb_list_t * list_subtitle;
@@ -328,6 +345,7 @@ struct hb_job_s
#define HB_ACODEC_FF_MASK 0x000f0000
#define HB_ACODEC_PASS_FLAG 0x40000000
#define HB_ACODEC_PASS_MASK (HB_ACODEC_MP3 | HB_ACODEC_FFAAC | HB_ACODEC_DCA_HD | HB_ACODEC_AC3 | HB_ACODEC_DCA)
+#define HB_ACODEC_AUTO_PASS (HB_ACODEC_PASS_MASK | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_MP3_PASS (HB_ACODEC_MP3 | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_AAC_PASS (HB_ACODEC_FFAAC | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_AC3_PASS (HB_ACODEC_AC3 | HB_ACODEC_PASS_FLAG)
@@ -346,6 +364,7 @@ struct hb_job_s
#define HB_AMIXDOWN_A52_FORMAT_MASK 0x00000FF0
#define HB_AMIXDOWN_DISCRETE_CHANNEL_COUNT_MASK 0x0000000F
/* define the HB_AMIXDOWN_XXXX values */
+#define HB_AMIXDOWN_NONE 0x00000000
#define HB_AMIXDOWN_MONO 0x01000001
// DCA_FORMAT of DCA_MONO = 0 = 0x000
// A52_FORMAT of A52_MONO = 1 = 0x01
diff --git a/libhb/work.c b/libhb/work.c
index 86f453ef1..c9e5ee205 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -279,28 +279,18 @@ void hb_display_job_info( hb_job_t * job )
if( !job->indepth_scan )
{
/* Video encoder */
- switch( job->vcodec )
+ for( i = 0; i < hb_video_encoders_count; i++ )
{
- case HB_VCODEC_FFMPEG_MPEG4:
- hb_log( " + encoder: FFmpeg MPEG-4" );
- break;
-
- case HB_VCODEC_FFMPEG_MPEG2:
- hb_log( " + encoder: FFmpeg MPEG-2" );
- break;
-
- case HB_VCODEC_X264:
- hb_log( " + encoder: x264" );
- break;
-
- case HB_VCODEC_THEORA:
- hb_log( " + encoder: Theora" );
+ if( hb_video_encoders[i].encoder == job->vcodec )
+ {
+ hb_log( " + encoder: %s", hb_video_encoders[i].human_readable_name );
break;
+ }
}
- if ( job->advanced_opts && *job->advanced_opts &&
- ( ( job->vcodec & HB_VCODEC_FFMPEG_MASK ) ||
- job->vcodec == HB_VCODEC_X264 ) )
+ if( job->advanced_opts && *job->advanced_opts &&
+ ( ( job->vcodec & HB_VCODEC_FFMPEG_MASK ) ||
+ ( job->vcodec == HB_VCODEC_X264 ) ) )
{
hb_log( " + options: %s", job->advanced_opts);
}
@@ -360,46 +350,44 @@ void hb_display_job_info( hb_job_t * job )
hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.in.bitrate / 1000, audio->config.in.samplerate );
}
- if( !(audio->config.out.codec & HB_ACODEC_PASS_FLAG) )
+ if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
{
- for (j = 0; j < hb_audio_mixdowns_count; j++)
+ for( j = 0; j < hb_audio_encoders_count; j++ )
{
- if (hb_audio_mixdowns[j].amixdown == audio->config.out.mixdown) {
+ if( hb_audio_encoders[j].encoder == audio->config.out.codec )
+ {
+ hb_log( " + %s", hb_audio_encoders[j].human_readable_name );
+ break;
+ }
+ }
+ }
+ 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;
}
}
- if ( audio->config.out.gain != 0.0 )
+ if( audio->config.out.gain != 0.0 )
{
hb_log( " + gain: %.fdB", audio->config.out.gain );
}
- }
-
- if ( audio->config.out.dynamic_range_compression && (audio->config.in.codec == HB_ACODEC_AC3) && (audio->config.out.codec != HB_ACODEC_AC3_PASS) )
- {
- hb_log(" + dynamic range compression: %f", audio->config.out.dynamic_range_compression);
- }
-
- if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
- {
- hb_log( " + %s passthrough",
- (audio->config.out.codec == HB_ACODEC_MP3_PASS) ? "MP3" :
- (audio->config.out.codec == HB_ACODEC_AAC_PASS) ? "AAC" :
- (audio->config.out.codec == HB_ACODEC_AC3_PASS) ? "AC3" :
- (audio->config.out.codec == HB_ACODEC_DCA_PASS) ? "DTS" :
- "DTS-HD");
- }
- else
- {
- hb_log( " + encoder: %s",
- ( audio->config.out.codec == HB_ACODEC_FAAC ) ? "faac" :
- ( ( audio->config.out.codec == HB_ACODEC_LAME ) ? "lame" :
- ( ( audio->config.out.codec == HB_ACODEC_CA_AAC ) ? "ca_aac" :
- ( ( audio->config.out.codec == HB_ACODEC_CA_HAAC ) ? "ca_haac" :
- ( ( audio->config.out.codec == HB_ACODEC_FFAAC ) ? "ffaac" :
- ( ( audio->config.out.codec == HB_ACODEC_AC3 ) ? "ffac3" :
- "vorbis" ) ) ) ) ) );
- hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );
+ if( ( audio->config.out.dynamic_range_compression != 0.0 ) && ( audio->config.in.codec == HB_ACODEC_AC3 ) )
+ {
+ hb_log( " + dynamic range compression: %f", audio->config.out.dynamic_range_compression );
+ }
+ for( j = 0; j < hb_audio_encoders_count; j++ )
+ {
+ if( hb_audio_encoders[j].encoder == audio->config.out.codec )
+ {
+ hb_log( " + encoder: %s", hb_audio_encoders[j].human_readable_name );
+ hb_log( " + bitrate: %d kbps, samplerate: %d Hz", audio->config.out.bitrate, audio->config.out.samplerate );
+ break;
+ }
+ }
}
}
}
@@ -530,16 +518,23 @@ static void do_job( hb_job_t * job )
*/
if( !job->indepth_scan )
{
- // if we are doing passthru, and the input codec is not the same as the output
- // codec, then remove this audio from the job. If we're not doing passthru and
- // the input codec is the 'internal' ffmpeg codec, make sure that only one
- // audio references that audio stream since the codec context is specific to
- // the audio id & multiple copies of the same stream will garble the audio
- // or cause aborts.
+ // apply Auto Passthru settings
+ hb_autopassthru_apply_settings( job, title );
+ // sanitize audio settings
for( i = 0; i < hb_list_count( title->list_audio ); )
{
audio = hb_list_item( title->list_audio, i );
- if( ( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) &&
+ if( audio->config.out.codec == HB_ACODEC_AUTO_PASS )
+ {
+ // Auto Passthru should have been handled above
+ // remove track to avoid a crash
+ hb_log( "Auto Passthru error, dropping track %d",
+ audio->config.out.track );
+ hb_list_rem( title->list_audio, audio );
+ free( audio );
+ continue;
+ }
+ if( ( audio->config.out.codec & HB_ACODEC_PASS_FLAG ) &&
!( audio->config.in.codec & audio->config.out.codec & HB_ACODEC_PASS_MASK ) )
{
hb_log( "Passthru requested and input codec is not the same as output codec for track %d, dropping track",
diff --git a/macosx/Controller.m b/macosx/Controller.m
index 865cc7f60..57ea2cc3b 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -2415,12 +2415,25 @@ fWorkingCount = 0;
[queueFileJob setObject:[NSString stringWithFormat:@"%d",[fPictureController deblock]] forKey:@"PictureDeblock"];
[queueFileJob setObject:[NSNumber numberWithInt:[fPictureController grayscale]] forKey:@"VideoGrayScale"];
+
+ /* Auto Passthru */
+ /* For the time being, values are hardcoded. */
+ [queueFileJob setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowAACPass"];
+ [queueFileJob setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowAC3Pass"];
+ [queueFileJob setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowDTSHDPass"];
+ [queueFileJob setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowDTSPass"];
+ [queueFileJob setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowMP3Pass"];
+ // just in case we need it for display purposes
+ [queueFileJob setObject: @"AC3 (ffmpeg)" forKey: @"AudioEncoderFallback"];
+ // actual fallback encoder
+ [queueFileJob setObject: [NSNumber numberWithInt: HB_ACODEC_AC3] forKey: @"JobAudioEncoderFallback"];
+
+ /* Audio */
[self writeToActivityLog: "createQueueFileItem: Getting Audio from prepareAudioForQueueFileJob ..."];
- /*Audio*/
- [fAudioDelegate prepareAudioForQueueFileJob: queueFileJob];
- [self writeToActivityLog: "createQueueFileItem: Returned getting audio from prepareAudioForQueueFileJob"];
+ [fAudioDelegate prepareAudioForQueueFileJob: queueFileJob];
+ [self writeToActivityLog: "createQueueFileItem: Returned getting audio from prepareAudioForQueueFileJob"];
- /* Subtitles*/
+ /* Subtitles */
NSMutableArray *subtitlesArray = [[NSMutableArray alloc] initWithArray:[fSubtitlesDelegate getSubtitleArray] copyItems:YES];
[queueFileJob setObject:[NSArray arrayWithArray: subtitlesArray] forKey:@"SubtitleList"];
[subtitlesArray autorelease];
@@ -2815,11 +2828,13 @@ fWorkingCount = 0;
/* Turbo 1st pass for 2 Pass Encoding */
[fVidTurboPassCheck setState:[[queueToApply objectForKey:@"VideoTurboTwoPass"] intValue]];
- /*Audio*/
-
+ /* Auto Passthru */
+ /* For the time being, there are no GUI elements for this;
+ * everything is hardcoded. */
+ /* Audio */
/* Now lets add our new tracks to the audio list here */
- [fAudioDelegate addTracksFromQueue: queueToApply];
+ [fAudioDelegate addTracksFromQueue: queueToApply];
/*Subtitles*/
/* Crashy crashy right now, working on it */
@@ -3220,8 +3235,13 @@ bool one_burned = FALSE;
-[subtitlesArray autorelease];
+[subtitlesArray autorelease];
+
+ /* Auto Passthru */
+ /* For the time being, values are hardcoded. */
+ job->acodec_copy_mask = HB_ACODEC_PASS_MASK;
+ job->acodec_fallback = HB_ACODEC_AC3;
/* Audio tracks and mixdowns */
[fAudioDelegate prepareAudioForJob: job];
@@ -3716,11 +3736,34 @@ bool one_burned = FALSE;
#pragma mark -
-
+ /* Auto Passthru */
+ job->acodec_copy_mask = 0;
+ if( [[queueToApply objectForKey: @"AudioAllowAACPass"] intValue] == 1 )
+ {
+ job->acodec_copy_mask |= HB_ACODEC_FFAAC;
+ }
+ if( [[queueToApply objectForKey: @"AudioAllowAC3Pass"] intValue] == 1 )
+ {
+ job->acodec_copy_mask |= HB_ACODEC_AC3;
+ }
+ if( [[queueToApply objectForKey: @"AudioAllowDTSHDPass"] intValue] == 1 )
+ {
+ job->acodec_copy_mask |= HB_ACODEC_DCA_HD;
+ }
+ if( [[queueToApply objectForKey: @"AudioAllowDTSPass"] intValue] == 1 )
+ {
+ job->acodec_copy_mask |= HB_ACODEC_DCA;
+ }
+ if( [[queueToApply objectForKey: @"AudioAllowMP3Pass"] intValue] == 1 )
+ {
+ job->acodec_copy_mask |= HB_ACODEC_MP3;
+ }
+ job->acodec_fallback = [[queueToApply objectForKey: @"JobAudioEncoderFallback"] intValue];
+
/* Audio tracks and mixdowns */
- /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/
+ /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty */
int audiotrack_count = hb_list_count(job->list_audio);
- for( int i = 0; i < audiotrack_count;i++)
+ for( int i = 0; i < audiotrack_count; i++ )
{
hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 );
hb_list_rem(job->list_audio, temp_audio);
@@ -4059,8 +4102,8 @@ bool one_burned = FALSE;
{
/* Let libhb do the job */
hb_start( fQueueEncodeLibhb );
- /*set the fEncodeState State */
- fEncodeState = 1;
+ /* set the fEncodeState State */
+ fEncodeState = 1;
}
@@ -4500,13 +4543,17 @@ bool one_burned = FALSE;
/* Note: we now store the video encoder int values from common.c in the tags of each popup for easy retrieval later */
[fVidEncoderPopUp removeAllItems];
NSMenuItem *menuItem;
- /* These video encoders are available to all of our current muxers, so lets list them once here */
- menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"MPEG-4 (FFmpeg)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_VCODEC_FFMPEG_MPEG4];
- menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"MPEG-2 (FFmpeg)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_VCODEC_FFMPEG_MPEG2];
- menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"H.264 (x264)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_VCODEC_X264];
+ int i;
+ for( i = 0; i < hb_video_encoders_count; i++ )
+ {
+ if( ( ( format == 0 ) && ( hb_video_encoders[i].muxers & HB_MUX_MP4 ) ) ||
+ ( ( format == 1 ) && ( hb_video_encoders[i].muxers & HB_MUX_MKV ) ) )
+ {
+ menuItem = [[fVidEncoderPopUp menu] addItemWithTitle: [NSString stringWithUTF8String: hb_video_encoders[i].human_readable_name]
+ action: NULL keyEquivalent: @""];
+ [menuItem setTag: hb_video_encoders[i].encoder];
+ }
+ }
switch( format )
{
@@ -4519,11 +4566,8 @@ bool one_burned = FALSE;
[fDstMp4iPodFileCheck setHidden: NO];
break;
- case 1:
+ case 1:
ext = "mkv";
- /* Add additional video encoders here */
- menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"VP3 (Theora)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_VCODEC_THEORA];
/* We enable the create chapters checkbox here */
[fCreateChapterMarkers setEnabled: YES];
break;
@@ -5592,8 +5636,12 @@ return YES;
/* Turbo 1st pass for 2 Pass Encoding */
[fVidTurboPassCheck setState:[[chosenPreset objectForKey:@"VideoTurboTwoPass"] intValue]];
- /*Audio*/
- [fAudioDelegate addTracksFromPreset: chosenPreset];
+ /* Auto Passthru */
+ /* For the time being, there are no GUI elements for this;
+ * everything is hardcoded. */
+
+ /* Audio */
+ [fAudioDelegate addTracksFromPreset: chosenPreset];
/*Subtitles*/
[fSubPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Subtitles"]];
@@ -6112,7 +6160,16 @@ return YES;
[preset setObject:[fPictureController decombCustomString] forKey:@"PictureDecombCustom"];
[preset setObject:[NSNumber numberWithInt:[fPictureController grayscale]] forKey:@"VideoGrayScale"];
- /*Audio*/
+ /* Auto Pasthru */
+ /* For the time being, values are hardcoded. */
+ [preset setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowAACPass"];
+ [preset setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowAC3Pass"];
+ [preset setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowDTSHDPass"];
+ [preset setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowDTSPass"];
+ [preset setObject: [NSNumber numberWithInt: 1] forKey: @"AudioAllowMP3Pass"];
+ [preset setObject: @"AC3 (ffmpeg)" forKey: @"AudioEncoderFallback"];
+
+ /* Audio */
NSMutableArray *audioListArray = [[NSMutableArray alloc] init];
[fAudioDelegate prepareAudioForPreset: audioListArray];
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m
index b7fdbcc85..10522b3d3 100644
--- a/macosx/HBAudio.m
+++ b/macosx/HBAudio.m
@@ -70,104 +70,51 @@ static NSMutableArray *masterBitRateArray = nil;
{
if ([HBAudio class] == self)
{
- int i;
+ int i, audioMustMatch, shouldAdd;
+ BOOL muxMKV, muxMP4;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *dict;
masterCodecArray = [[NSMutableArray alloc] init]; // knowingly leaked
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AAC (CoreAudio)", @"AAC (CoreAudio)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_CA_AAC], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
- if (encca_haac_available())
+ for( i = 0; i < hb_audio_encoders_count; i++ )
{
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"HE-AAC (CoreAudio)", @"HE-AAC (CoreAudio)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_CA_HAAC], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
+ if( ( hb_audio_encoders[i].encoder & HB_ACODEC_PASS_FLAG ) &&
+ ( hb_audio_encoders[i].encoder != HB_ACODEC_AUTO_PASS ) )
+ {
+ audioMustMatch = ( hb_audio_encoders[i].encoder & ~HB_ACODEC_PASS_FLAG );
+ }
+ else
+ {
+ audioMustMatch = 0;
+ }
+ // Auto Passthru disabled until we have GUI widgets for it
+ shouldAdd = ( hb_audio_encoders[i].encoder != HB_ACODEC_AUTO_PASS ) &&
+ ( ( hb_audio_encoders[i].encoder != HB_ACODEC_CA_HAAC ) || encca_haac_available() );
+ muxMKV = ( hb_audio_encoders[i].muxers & HB_MUX_MKV ) ? YES : NO;
+ muxMP4 = ( hb_audio_encoders[i].muxers & HB_MUX_MP4 ) ? YES : NO;
+ if( shouldAdd && 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 if( shouldAdd )
+ {
+ [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]];
+ }
}
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AAC (ffmpeg)", @"AAC (ffmpeg)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_FFAAC], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AAC (faac)", @"AAC (faac)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_FAAC], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AAC Passthru", @"AAC Passthru"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_AAC_PASS], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithInt: HB_ACODEC_FFAAC], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AC3 (ffmpeg)", @"AC3 (ffmpeg)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_AC3_PASS], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"DTS Passthru", @"DTS Passthru"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_DCA_PASS], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithInt: HB_ACODEC_DCA], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"DTS-HD Passthru", @"DTS-HD Passthru"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_DCA_HD_PASS], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithInt: HB_ACODEC_DCA_HD], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"MP3 (lame)", @"MP3 (lame)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_LAME], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"MP3 Passthru", @"MP3 Passthru"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_MP3_PASS], keyAudioCodec,
- [NSNumber numberWithBool: YES], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithInt: HB_ACODEC_MP3], keyAudioMustMatchTrack,
- nil]];
- [masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"Vorbis (vorbis)", @"Vorbis (vorbis)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_VORBIS], keyAudioCodec,
- [NSNumber numberWithBool: NO], keyAudioMP4,
- [NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
- nil]];
masterMixdownArray = [[NSMutableArray alloc] init]; // knowingly leaked
- [masterMixdownArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"None", @"None"), keyAudioMixdownName,
- [NSNumber numberWithInt: 0], keyAudioMixdown,
- nil]];
for (i = 0; i < hb_audio_mixdowns_count; i++)
{
[masterMixdownArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
@@ -296,11 +243,11 @@ static NSMutableArray *masterBitRateArray = nil;
// Basically with the way the mixdowns are stored, the assumption from the libhb point of view
// currently is that all mixdowns from the best down to mono are supported.
- if (currentMixdown && currentMixdown <= theBestMixdown)
+ if ((currentMixdown != HB_AMIXDOWN_NONE) && (currentMixdown <= theBestMixdown))
{
shouldAdd = YES;
}
- else if (0 == currentMixdown && (codecCodec & HB_ACODEC_PASS_FLAG))
+ else if ((currentMixdown == HB_AMIXDOWN_NONE) && (codecCodec & HB_ACODEC_PASS_FLAG))
{
// "None" mixdown (passthru)
shouldAdd = YES;
@@ -638,7 +585,7 @@ static NSMutableArray *masterBitRateArray = nil;
if (retval)
{
int myMixdown = [[[self mixdown] objectForKey: keyAudioMixdown] intValue];
- if (0 == myMixdown)
+ if (myMixdown == HB_AMIXDOWN_NONE)
{
// "None" mixdown (passthru)
retval = NO;
diff --git a/macosx/HBAudioController.m b/macosx/HBAudioController.m
index 16538c2ff..b275f7a82 100644
--- a/macosx/HBAudioController.m
+++ b/macosx/HBAudioController.m
@@ -302,14 +302,6 @@ NSString *HBMixdownChangedNotification = @"HBMixdownChangedNotification";
[dict setObject: @"AAC (CoreAudio)" forKey: @"AudioEncoder"];
}
- // Auto Passthru not yet implemented - fallback to AC3 Passthru as it is
- // compatible with all source codecs (via the AC3 encoder fallback)
- if ([key isEqualToString: @"Auto Passthru"])
- {
- [dict setObject: @"AC3 Passthru" forKey: @"AudioEncoder"];
- key = @"AC3 Passthru";
- }
-
// passthru fallbacks
if ([key isEqualToString: @"AAC Passthru"])
{
diff --git a/test/test.c b/test/test.c
index 9074064cd..ff94c1c5b 100644
--- a/test/test.c
+++ b/test/test.c
@@ -1969,107 +1969,53 @@ static int HandleEvents( hb_handle_t * h )
for( i = 0; i < hb_list_count( job->list_audio ); )
{
audio = hb_list_audio_config_item( job->list_audio, i );
- // check whether we're doing passthru
- if( audio->out.codec & HB_ACODEC_PASS_FLAG )
- {
- // compute the output passthru codec
- // required to make 'copy' work
- // doesn't break codec-specific passthru
- int out_codec = ( audio->out.codec & ( audio->in.codec | HB_ACODEC_PASS_FLAG ) );
- // check whether passthru is possible or not
- if( !( out_codec & audio->in.codec & HB_ACODEC_PASS_MASK ) )
- {
- // first, check whether we're doing a codec-specific passthru
- // for which we have a corresponding encoder
- // note: Auto Passthru with a single codec in the passthru
- // mask is assimilated to codec-specific passthru
- 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 );
-#ifdef __APPLE_CC__
- audio->out.codec = HB_ACODEC_CA_AAC;
-#else
- audio->out.codec = HB_ACODEC_FAAC;
-#endif
- }
- 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;
- }
- // we're doing either DTS, DTS-HD or Auto Passthru
- else if( ( audio->out.codec != HB_ACODEC_DCA_PASS ) &&
- ( audio->out.codec != HB_ACODEC_DCA_HD_PASS ) )
- {
- // we're doing Auto Passthru, check if there's a fallback
- if( acodec_fallback )
- {
- fprintf( stderr, "Auto passthru requested and input codec is not compatible for track %d, using fallback\n",
- audio->out.track );
- audio->out.codec = get_acodec_for_string( acodec_fallback );
- }
- // we didn't find a suitable fallback
- // check whether we have an encoder for
- // one of the allowed passthru codecs
- else if( audio->out.codec & HB_ACODEC_AAC_PASS )
- {
- fprintf( stderr, "Auto passthru requested and input codec is not compatible for track %d, AAC Passthru allowed: using AAC encoder\n",
- audio->out.track );
+ if( audio->out.codec == HB_ACODEC_AUTO_PASS )
+ {
+ // Auto Passthru
+ job->acodec_copy_mask = allowed_audio_copy;
+ job->acodec_fallback = acodec_fallback ? get_acodec_for_string( acodec_fallback ) : 0;
+ // sanitize the fallback; -1 isn't a valid HB_ACODEC_* value
+ if( job->acodec_fallback == -1 )
+ job->acodec_fallback = 0;
+ }
+ else if( ( audio->out.codec & HB_ACODEC_PASS_FLAG ) &&
+ !( audio->out.codec & audio->in.codec & HB_ACODEC_PASS_MASK ) )
+ {
+ 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 );
#ifdef __APPLE_CC__
- audio->out.codec = HB_ACODEC_CA_AAC;
+ audio->out.codec = HB_ACODEC_CA_AAC;
#else
- audio->out.codec = HB_ACODEC_FAAC;
+ audio->out.codec = HB_ACODEC_FAAC;
#endif
- }
- else if( audio->out.codec & HB_ACODEC_AC3_PASS )
- {
- fprintf( stderr, "Auto passthru requested and input codec is not compatible for track %d, AC3 Passthru allowed: using AC3 encoder\n",
- audio->out.track );
- audio->out.codec = HB_ACODEC_AC3;
- }
- else if( audio->out.codec & HB_ACODEC_MP3_PASS )
- {
- fprintf( stderr, "Auto passthru requested and input codec is not compatible for track %d, MP3 Passthru allowed: using MP3 encoder\n",
- audio->out.track );
- audio->out.codec = HB_ACODEC_LAME;
- }
- else
- {
- // Passthru not possible, drop audio.
- fprintf( stderr, "Auto passthru requested, input codec is not compatible for track %d and no valid fallback specified: dropping track\n",
- audio->out.track );
- hb_audio_t * item = hb_list_item( job->list_audio, i );
- hb_list_rem( job->list_audio, item );
- continue;
- }
- }
- else
- {
- // 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 );
- continue;
- }
- // 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 );
+ }
+ 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 is possible
- audio->out.codec = out_codec;
+ // 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 );
+ continue;
}
+ // 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 );
}
// we didn't drop the track
i++;
@@ -2541,7 +2487,7 @@ void SigHandler( int i_signal )
****************************************************************************/
static void ShowHelp()
{
- int i;
+ int i, j;
FILE* const out = stdout;
fprintf( out,
@@ -2595,8 +2541,25 @@ static void ShowHelp()
"### Video Options------------------------------------------------------------\n\n"
" -e, --encoder <string> Set video library encoder\n"
- " Options: ffmpeg4,ffmpeg2,x264,theora\n"
- " (default: ffmpeg4)\n"
+ " Options: " );
+ for( i = 0; i < hb_video_encoders_count; i++ )
+ {
+ fprintf( out, "%s", hb_video_encoders[i].short_name );
+ if( i != hb_video_encoders_count - 1 )
+ 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,
" -x, --encopts <string> Specify advanced encoder options in the\n"
" same style as mencoder (x264 and ffmpeg only):\n"
" option1=value1:option2=value2\n"
@@ -2632,58 +2595,42 @@ static void ShowHelp()
"\n"
"### Audio Options-----------------------------------------------------------\n\n"
" -a, --audio <string> Select audio track(s), separated by commas\n"
- " More than one output track can be used for one\n"
- " input.\n"
" (\"none\" for no audio, \"1,2,3\" for multiple\n"
- " tracks, default: first one)\n" );
-
-#ifdef __APPLE_CC__
+ " 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++ )
+ {
+ fprintf( out, " %s\n",
+ hb_audio_encoders[i].short_name );
+ }
fprintf( out,
- " -E, --aencoder <string> Audio encoder(s)\n"
- " ca_aac\n"
- " ca_haac\n"
- " faac\n"
- " lame\n"
- " vorbis\n"
- " ac3\n"
- " copy\n"
- " copy:aac\n"
- " copy:ac3\n"
- " copy:dts\n"
- " copy:dtshd\n"
- " copy:mp3\n"
- " copy* will passthrough the corresponding\n"
+ " 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: ca_aac)\n" );
+#ifdef __APPLE_CC__
+ " (default: ca_aac)\n"
#else
- fprintf( out,
- " -E, --aencoder <string> Audio encoder(s):\n"
- " faac\n"
- " lame\n"
- " vorbis\n"
- " ac3\n"
- " copy\n"
- " copy:aac\n"
- " copy:ac3\n"
- " copy:dts\n"
- " copy:dtshd\n"
- " copy:mp3\n"
- " 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: faac for mp4, lame for mkv)\n" );
+ " (default: faac for mp4, lame for mkv)\n"
#endif
- fprintf( out,
- " --audio-copy-mask Set audio codecs that are permitted when\n"
- " <string> \"copy\" audio encoder option is specified.\n"
- " Separated by commas for multiple allowed options.\n");
- fprintf( out,
+ " --audio-copy-mask Set audio codecs that are permitted when the\n"
+ " <string> \"copy\" audio encoder option is specified\n"
+ " (" );
+ for( i = 0, j = 0; i < hb_audio_encoders_count; i++ )
+ {
+ if( !strncmp( hb_audio_encoders[i].short_name, "copy:", 5 ) )
+ {
+ if( j != 0 )
+ fprintf( out, "/" );
+ fprintf( out, "%s", hb_audio_encoders[i].short_name + 5 );
+ j = 1;
+ }
+ }
+ fprintf( out, ", default: all).\n"
+ " Separated by commas for multiple allowed options.\n"
" --audio-fallback Set audio codec to use when it is not possible\n"
- " <string> to copy an audio track without re-encoding.\n");
- fprintf( out,
+ " <string> to copy an audio track without re-encoding.\n"
" -B, --ab <kb/s> Set audio bitrate(s) (default: depends on the\n"
" selected codec, mixdown and samplerate)\n"
" Separated by commas for more than one audio track.\n"
@@ -3357,32 +3304,23 @@ static int ParseOptions( int argc, char ** argv )
}
break;
case 'e':
- if( !strcasecmp( optarg, "ffmpeg" ) )
- {
- vcodec = HB_VCODEC_FFMPEG_MPEG4;
- }
- else if( !strcasecmp( optarg, "ffmpeg4" ) )
- {
- vcodec = HB_VCODEC_FFMPEG_MPEG4;
- }
- else if( !strcasecmp( optarg, "ffmpeg2" ) )
- {
- vcodec = HB_VCODEC_FFMPEG_MPEG2;
- }
- else if( !strcasecmp( optarg, "x264" ) )
- {
- vcodec = HB_VCODEC_X264;
- }
- else if( !strcasecmp( optarg, "theora" ) )
+ {
+ int i;
+ for( i = 0, vcodec = 0; i < hb_video_encoders_count; i++ )
{
- vcodec = HB_VCODEC_THEORA;
+ if( !strcasecmp( hb_video_encoders[i].short_name, optarg ) )
+ {
+ vcodec = hb_video_encoders[i].encoder;
+ break;
+ }
}
- else
+ if( !vcodec )
{
fprintf( stderr, "invalid codec (%s)\n", optarg );
return -1;
}
break;
+ }
case 'E':
if( optarg != NULL )
{
@@ -3514,23 +3452,26 @@ static int ParseOptions( int argc, char ** argv )
break;
case ALLOWED_AUDIO_COPY:
{
- int i;
+ int i, j;
char **allowed = str_split( optarg, ',' );
allowed_audio_copy = 0;
- for ( i = 0; allowed[i]; i++ )
- {
- if ( !strcmp( allowed[i], "ac3" ) )
- allowed_audio_copy |= HB_ACODEC_AC3;
- if ( !strcmp( allowed[i], "dts" ) )
- allowed_audio_copy |= HB_ACODEC_DCA;
- if ( !strcmp( allowed[i], "dtshd" ) )
- allowed_audio_copy |= HB_ACODEC_DCA_HD;
- if ( !strcmp( allowed[i], "mp3" ) )
- allowed_audio_copy |= HB_ACODEC_MP3;
- if ( !strcmp( allowed[i], "aac" ) )
- allowed_audio_copy |= HB_ACODEC_FFAAC;
+ for( i = 0; allowed[i]; i++ )
+ {
+ for( j = 0; j < hb_audio_encoders_count; j++ )
+ {
+ char * encoder = hb_audio_encoders[j].short_name;
+ // skip "copy:"
+ if( strlen( encoder ) > 5 )
+ encoder += 5;
+ if( !strcmp( allowed[i], encoder ) )
+ {
+ allowed_audio_copy |= hb_audio_encoders[j].encoder;
+ break;
+ }
+ }
}
+ allowed_audio_copy &= HB_ACODEC_PASS_MASK;
str_vfree( allowed );
} break;
case AUDIO_FALLBACK:
@@ -3695,64 +3636,16 @@ static int CheckOptions( int argc, char ** argv )
static int get_acodec_for_string( char *codec )
{
- if( !strcasecmp( codec, "ac3" ) )
- {
- return HB_ACODEC_AC3;
- }
- else if( !strcasecmp( codec, "copy" ) )
- {
- return (HB_ACODEC_PASS_MASK & allowed_audio_copy) | HB_ACODEC_PASS_FLAG;
- }
- else if( !strcasecmp( codec, "copy:aac" ) )
- {
- return HB_ACODEC_AAC_PASS;
- }
- else if( !strcasecmp( codec, "copy:ac3" ) )
- {
- return HB_ACODEC_AC3_PASS;
- }
- else if( !strcasecmp( codec, "copy:dts" ) || !strcasecmp( codec, "copy:dca" ) )
- {
- return HB_ACODEC_DCA_PASS;
- }
- else if( !strcasecmp( codec, "copy:dtshd" ) )
- {
- return HB_ACODEC_DCA_HD_PASS;
- }
- else if( !strcasecmp( codec, "copy:mp3" ) )
- {
- return HB_ACODEC_MP3_PASS;
- }
- else if( !strcasecmp( codec, "lame" ) )
- {
- return HB_ACODEC_LAME;
- }
- else if( !strcasecmp( codec, "faac" ) )
+ int i, acodec;
+ for( i = 0, acodec = 0; i < hb_audio_encoders_count; i++ )
{
- return HB_ACODEC_FAAC;
- }
- else if( !strcasecmp( codec, "ffaac" ) )
- {
- return HB_ACODEC_FFAAC;
- }
- else if( !strcasecmp( codec, "vorbis") )
- {
- return HB_ACODEC_VORBIS;
- }
-#ifdef __APPLE__
- else if( !strcasecmp( codec, "ca_aac") )
- {
- return HB_ACODEC_CA_AAC;
- }
- else if( !strcasecmp( codec, "ca_haac") )
- {
- return HB_ACODEC_CA_HAAC;
- }
-#endif
- else
- {
- return -1;
+ if( !strcasecmp( hb_audio_encoders[i].short_name, codec ) )
+ {
+ acodec = hb_audio_encoders[i].encoder;
+ break;
+ }
}
+ return acodec ? acodec : -1;
}
static int is_sample_rate_valid(int rate)