summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/ffmpeg/A04-dca-frame-size.patch12
-rw-r--r--gtk/src/audiohandler.c239
-rw-r--r--gtk/src/audiohandler.h2
-rw-r--r--gtk/src/callbacks.c7
-rw-r--r--gtk/src/ghb.ui144
-rw-r--r--gtk/src/hb-backend.c189
-rw-r--r--gtk/src/hb-backend.h3
-rw-r--r--gtk/src/internal_defaults.xml12
-rw-r--r--gtk/src/makedeps.py19
-rw-r--r--gtk/src/presets.c8
-rw-r--r--libhb/common.h10
-rw-r--r--libhb/deca52.c1
-rw-r--r--libhb/decavcodec.c6
-rw-r--r--libhb/decdca.c1
-rw-r--r--libhb/declpcm.c2
-rw-r--r--libhb/encavcodecaudio.c2
-rw-r--r--libhb/encfaac.c1
-rw-r--r--libhb/enclame.c1
-rw-r--r--libhb/encvorbis.c1
-rw-r--r--libhb/muxmkv.c9
-rw-r--r--libhb/muxmp4.c376
-rw-r--r--libhb/platform/macosx/encca_aac.c2
-rw-r--r--libhb/scan.c1
-rw-r--r--libhb/stream.c18
-rw-r--r--libhb/sync.c174
-rw-r--r--libhb/work.c2
-rw-r--r--macosx/HBAudio.m36
-rw-r--r--macosx/HBAudioController.m7
-rw-r--r--test/test.c46
29 files changed, 830 insertions, 501 deletions
diff --git a/contrib/ffmpeg/A04-dca-frame-size.patch b/contrib/ffmpeg/A04-dca-frame-size.patch
new file mode 100644
index 000000000..5af1040b2
--- /dev/null
+++ b/contrib/ffmpeg/A04-dca-frame-size.patch
@@ -0,0 +1,12 @@
+diff --git a/libavcodec/dca.c b/libavcodec/dca.c
+index 68731c9..cf62c48 100644
+--- a/libavcodec/dca.c
++++ b/libavcodec/dca.c
+@@ -1650,6 +1650,7 @@ static int dca_decode_frame(AVCodecContext * avctx,
+ //set AVCodec values with parsed data
+ avctx->sample_rate = s->sample_rate;
+ avctx->bit_rate = s->bit_rate;
++ avctx->frame_size = s->sample_blocks * 32;
+
+ s->profile = FF_PROFILE_DTS;
+
diff --git a/gtk/src/audiohandler.c b/gtk/src/audiohandler.c
index 54cd1a496..ee84a798f 100644
--- a/gtk/src/audiohandler.c
+++ b/gtk/src/audiohandler.c
@@ -25,6 +25,130 @@ 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)
+{
+ guint32 in_codec = aconfig ? aconfig->in.codec : HB_ACODEC_MASK;
+ if (mux == HB_MUX_MP4)
+ {
+ if (acodec & HB_ACODEC_PASS_FLAG)
+ {
+ if ((acodec & in_codec & HB_ACODEC_MASK & ~HB_ACODEC_VORBIS))
+ {
+ return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
+ }
+ else if (fallback & (HB_ACODEC_AC3 | HB_ACODEC_LAME | HB_ACODEC_FAAC | HB_ACODEC_FFAAC))
+ {
+ 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 & (HB_ACODEC_AC3 | HB_ACODEC_LAME | HB_ACODEC_FAAC | HB_ACODEC_FFAAC))
+ {
+ return fallback;
+ }
+ else
+ {
+ return HB_ACODEC_FAAC;
+ }
+ }
+ else
+ {
+ if (acodec & HB_ACODEC_PASS_FLAG)
+ {
+ if ((acodec & in_codec & HB_ACODEC_PASS_MASK))
+ {
+ 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_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 )
+ {
+ return fallback;
+ }
+ else
+ {
+ return HB_ACODEC_LAME;
+ }
+ }
+}
+
+int ghb_allowed_passthru_mask(GValue *settings, int acodec)
+{
+ 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;
+}
+
void
ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
{
@@ -32,7 +156,7 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
hb_audio_config_t *aconfig;
GtkWidget *widget;
GValue *gval;
- int mux;
+ gint mux;
gint bitrate;
gint sr = 48000;
@@ -62,25 +186,15 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
gval = ghb_widget_value(widget);
sr = ghb_lookup_combo_int("AudioSamplerate", gval);
- select_acodec = acodec;
- if (mux == HB_MUX_MP4)
- {
- select_acodec &= ~HB_ACODEC_DCA;
- }
- if ((select_acodec & HB_ACODEC_MASK) == 0)
- {
- // Unsuported codec in this container.
- select_acodec |= HB_ACODEC_AC3;
- acodec = select_acodec;
- }
aconfig = ghb_get_scan_audio_info(titleindex, track);
if (sr == 0)
{
sr = aconfig ? aconfig->in.samplerate : 48000;
}
- if (aconfig)
- select_acodec = ghb_select_audio_codec(mux, aconfig, select_acodec);
+ gint fallback = ghb_settings_combo_int(ud->settings, "AudioEncoderFallback");
+ select_acodec = ghb_allowed_passthru_mask(ud->settings, acodec);
+ select_acodec = ghb_select_audio_codec(mux, aconfig, select_acodec, fallback);
gboolean codec_defined_bitrate = FALSE;
if (ghb_audio_is_passthru (select_acodec))
{
@@ -89,44 +203,33 @@ ghb_adjust_audio_rate_combos(signal_user_data_t *ud)
bitrate = aconfig->in.bitrate / 1000;
// Set the values for bitrate and samplerate to the input rates
- if (aconfig->in.codec & select_acodec & HB_ACODEC_PASS_MASK)
- {
- ghb_set_passthru_bitrate_opts (ud->builder, bitrate);
- ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(0));
- select_acodec &= aconfig->in.codec | HB_ACODEC_PASS_FLAG;
- codec_defined_bitrate = TRUE;
- }
- else
- {
- gint mux = ghb_settings_get_int(ud->settings, "FileFormat");
- select_acodec = ghb_select_audio_codec(mux, aconfig, acodec);
- if (acodec != HB_ACODEC_ANY)
- {
- ghb_ui_update(ud, "AudioEncoder", ghb_int64_value(select_acodec));
- }
-
- mix = ghb_get_best_mix( aconfig, select_acodec, mix);
- bitrate = hb_get_default_audio_bitrate(select_acodec, sr, mix);
- ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix));
- }
+ ghb_set_passthru_bitrate_opts (ud->builder, bitrate);
+ mix = 0;
+ ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix));
+ select_acodec &= aconfig->in.codec | HB_ACODEC_PASS_FLAG;
+ codec_defined_bitrate = TRUE;
ghb_ui_update(ud, "AudioSamplerate", ghb_int64_value(0));
}
else
{
ghb_ui_update(ud, "AudioSamplerate", ghb_int64_value(0));
- ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(0));
+ mix = 0;
+ ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix));
bitrate = 448;
- mix = ghb_get_best_mix( aconfig, select_acodec, 0);
}
ghb_ui_update(ud, "AudioTrackDRCSlider", ghb_double_value(0));
}
else
{
+ if (mix == 0)
+ mix = ghb_get_best_mix( aconfig, select_acodec, 0);
bitrate = hb_get_best_audio_bitrate(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);
ghb_set_default_bitrate_opts (ud->builder, low, high);
}
@@ -182,14 +285,7 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud)
g_debug("set_pref_audio");
mux = ghb_settings_combo_int(ud->settings, "FileFormat");
- if (mux == HB_MUX_MP4)
- {
- fallback_acodec = HB_ACODEC_FAAC;
- }
- else
- {
- fallback_acodec = HB_ACODEC_LAME;
- }
+ fallback_acodec = ghb_settings_combo_int(ud->settings, "AudioEncoderFallback");
track_indices = g_hash_table_new_full(g_int_hash, g_int_equal,
free_audio_hash_key_value, free_audio_hash_key_value);
// Clear the audio list
@@ -208,24 +304,12 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud)
count = ghb_array_len(pref_audio);
for (ii = 0; ii < count; ii++)
{
- int select_acodec;
+ gint select_acodec;
audio = ghb_array_get_nth(pref_audio, ii);
- select_acodec = acodec = ghb_settings_combo_int(audio, "AudioEncoder");
- if (mux == HB_MUX_MP4)
- {
- select_acodec &= ~HB_ACODEC_DCA;
- }
- if ((select_acodec & HB_ACODEC_MASK) == 0)
- {
- // Unsuported codec in this container.
- select_acodec |= HB_ACODEC_AC3;
- acodec = select_acodec;
- }
- if ( ghb_audio_can_passthru( select_acodec ) )
- {
- fallback_acodec = HB_ACODEC_AC3;
- }
+ acodec = ghb_settings_combo_int(audio, "AudioEncoder");
+ select_acodec = ghb_allowed_passthru_mask(ud->settings, acodec);
+ select_acodec = ghb_select_audio_codec(mux, NULL, select_acodec, fallback_acodec);
bitrate = ghb_settings_combo_int(audio, "AudioBitrate");
rate = ghb_settings_combo_double(audio, "AudioSamplerate");
mix = ghb_settings_combo_int(audio, "AudioMixdown");
@@ -260,17 +344,13 @@ ghb_set_pref_audio(gint titleindex, signal_user_data_t *ud)
}
else
{
- int channels, min_rate, max_rate;
+ int channels;
select_acodec = fallback_acodec;
mix = ghb_get_best_mix(aconfig, select_acodec, mix);
channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(mix);
bitrate = aconfig->in.bitrate / 1000;
- min_rate = channels * 64;
- max_rate = channels * 160;
- if (bitrate < min_rate)
- bitrate = min_rate;
- if (bitrate > max_rate)
- bitrate = max_rate;
+ bitrate = hb_get_best_audio_bitrate(select_acodec, bitrate,
+ aconfig->in.samplerate, mix);
rate = 0;
}
}
@@ -417,7 +497,7 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
if (block_updates)
{
prev_acodec = acodec_code;
- ghb_grey_combo_options (ud->builder);
+ ghb_grey_combo_options (ud);
return;
}
@@ -469,7 +549,7 @@ audio_codec_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
ghb_ui_update(ud, "AudioMixdown", ghb_int64_value(mix_code));
}
ghb_adjust_audio_rate_combos(ud);
- ghb_grey_combo_options (ud->builder);
+ ghb_grey_combo_options (ud);
ghb_check_dependency(ud, widget, NULL);
prev_acodec = acodec_code;
if (asettings != NULL)
@@ -488,11 +568,15 @@ audio_track_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
GValue *asettings;
g_debug("audio_track_changed_cb ()");
- if (block_updates) return;
+ if (block_updates)
+ {
+ ghb_grey_combo_options (ud);
+ return;
+ }
ghb_adjust_audio_rate_combos(ud);
ghb_check_dependency(ud, widget, NULL);
- ghb_grey_combo_options(ud->builder);
+ ghb_grey_combo_options(ud);
asettings = get_selected_asettings(ud);
if (asettings != NULL)
{
@@ -544,6 +628,19 @@ audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
ghb_live_reset(ud);
}
+G_MODULE_EXPORT void
+global_audio_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
+{
+ g_debug("global_audio_widget_changed_cb ()");
+ if (block_updates) return;
+
+ ghb_check_dependency(ud, widget, NULL);
+ ghb_widget_to_setting(ud->settings, widget);
+ ghb_adjust_audio_rate_combos(ud);
+ ghb_audio_list_refresh_selected(ud);
+ ghb_live_reset(ud);
+}
+
G_MODULE_EXPORT gchar*
format_drc_cb(GtkScale *scale, gdouble val, signal_user_data_t *ud)
{
diff --git a/gtk/src/audiohandler.h b/gtk/src/audiohandler.h
index 87b9612f7..74df87a3d 100644
--- a/gtk/src/audiohandler.h
+++ b/gtk/src/audiohandler.h
@@ -34,5 +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);
#endif // _AUDIOHANDLER_H_
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c
index 0fd92a9e6..03d576603 100644
--- a/gtk/src/callbacks.c
+++ b/gtk/src/callbacks.c
@@ -1250,7 +1250,8 @@ window_delete_event_cb(GtkWidget *widget, GdkEvent *event, signal_user_data_t *u
static void
update_acodec_combo(signal_user_data_t *ud)
{
- ghb_grey_combo_options (ud->builder);
+ ghb_adjust_audio_rate_combos(ud);
+ ghb_grey_combo_options (ud);
}
G_MODULE_EXPORT void
@@ -1507,7 +1508,7 @@ title_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
update_chapter_list (ud);
ghb_adjust_audio_rate_combos(ud);
ghb_set_pref_audio(titleindex, ud);
- ghb_grey_combo_options (ud->builder);
+ ghb_grey_combo_options (ud);
ghb_set_pref_subtitle(titleindex, ud);
// Unfortunately, there is no way to query how many frames were
@@ -1662,7 +1663,7 @@ http_opt_changed_cb(GtkWidget *widget, signal_user_data_t *ud)
ghb_clear_presets_selection(ud);
ghb_live_reset(ud);
// AC3 is not allowed when Web optimized
- ghb_grey_combo_options (ud->builder);
+ ghb_grey_combo_options (ud);
}
G_MODULE_EXPORT void
diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui
index 999f3c621..7d037434b 100644
--- a/gtk/src/ghb.ui
+++ b/gtk/src/ghb.ui
@@ -1716,7 +1716,7 @@
<object class="GtkLabel" id="label46">
<property name="visible">True</property>
<property name="xalign">0</property>
- <property name="label" translatable="yes">Video Codec:</property>
+ <property name="label" translatable="yes">Video Encoder:</property>
<property name="width_chars">11</property>
</object>
<packing>
@@ -2113,9 +2113,10 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle
<object class="GtkTable" id="table14">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="n_rows">2</property>
+ <property name="n_rows">4</property>
<property name="n_columns">5</property>
<property name="row_spacing">5</property>
+ <property name="column_spacing">5</property>
<child>
<object class="GtkLabel" id="audio_name_label">
<property name="visible">True</property>
@@ -2228,7 +2229,7 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle
<child>
<object class="GtkHScale" id="AudioTrackGain">
<property name="visible">True</property>
- <property name="width-request">200</property>
+ <property name="width-request">150</property>
<property name="orientation">horizontal</property>
<property name="adjustment">adjustment35</property>
<property name="value_pos">right</property>
@@ -2282,6 +2283,141 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle
<property name="x_options">GTK_FILL</property>
</packing>
</child>
+ <child>
+ <object class="GtkHBox" id="hbox40">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="labela3">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Auto Passthru:</property>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="AudioAllowMP3Pass">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AAC. This permits AAC passthru to be selected when automatic passthru selection is enabled.</property>
+ <property name="label" translatable="yes">MP3</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="global_audio_widget_changed_cb" name="toggled"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="AudioAllowAACPass">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AAC. This permits AAC passthru to be selected when automatic passthru selection is enabled.</property>
+ <property name="label" translatable="yes">AAC</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="global_audio_widget_changed_cb" name="toggled"/>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="AudioAllowAC3Pass">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="tooltip-text" translatable="yes">Enable this if your playback device supports AC-3. This permits AC-3 passthru to be selected when automatic passthru selection is enabled.</property>
+ <property name="label" translatable="yes">AC-3</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="global_audio_widget_changed_cb" name="toggled"/>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="AudioAllowDTSPass">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="tooltip-text" translatable="yes">Enable this if your playback device supports DTS. This permits DTS passthru to be selected when automatic passthru selection is enabled.</property>
+ <property name="label" translatable="yes">DTS</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="global_audio_widget_changed_cb" name="toggled"/>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="AudioAllowDTSHDPass">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="tooltip-text" translatable="yes">Enable this if your playback device supports DTS-HD. This permits DTS-HD passthru to be selected when automatic passthru selection is enabled.</property>
+ <property name="label" translatable="yes">DTS-HD</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="global_audio_widget_changed_cb" name="toggled"/>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="labela4">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="xalign">1</property>
+ <property name="label" translatable="yes">Passthru Fallback:</property>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="AudioEncoderFallback">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="tooltip-text" translatable="yes">Set the audio codec to encode with when a suitable track can not be found for audio passthru.</property>
+ <signal handler="global_audio_widget_changed_cb" name="changed"/>
+ </object>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
</object>
</child>
</object>
@@ -2323,7 +2459,7 @@ FFMpeg's and Theora's scale is more linear. These encoders do not have a lossle
<object class="GtkLabel" id="label68">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="label" translatable="yes">Codec</property>
+ <property name="label" translatable="yes">Encoder</property>
</object>
<packing>
<property name="top_attach">0</property>
diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c
index 8a90d4ece..a3b9e5106 100644
--- a/gtk/src/hb-backend.c
+++ b/gtk/src/hb-backend.c
@@ -57,7 +57,7 @@ static gint index_str_size = 0;
static void
index_str_init(gint max_index)
{
- int ii;
+ gint ii;
if (max_index+1 > index_str_size)
{
@@ -256,10 +256,12 @@ static options_map_t d_acodec_opts[] =
{"MP3 (lame)", "lame", HB_ACODEC_LAME, "lame"},
{"Vorbis", "vorbis", HB_ACODEC_VORBIS, "vorbis"},
{"AC3 (ffmpeg)", "ac3", HB_ACODEC_AC3, "ac3"},
- {"AC3 (pass-thru)", "ac3pass", HB_ACODEC_AC3_PASS, "ac3pass"},
- {"DTS (pass-thru)", "dtspass", HB_ACODEC_DCA_PASS, "dtspass"},
- {"DTS-HD (pass-thru)", "dtshdpass", HB_ACODEC_DCA_HD_PASS, "dtshdpass"},
- {"Choose For Me", "auto", HB_ACODEC_ANY, "auto"},
+ {"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 =
{
@@ -267,6 +269,20 @@ combo_opts_t acodec_opts =
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"},
@@ -418,6 +434,7 @@ combo_name_map_t combo_name_map[] =
{"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},
@@ -1535,71 +1552,75 @@ grey_combo_box_item(GtkBuilder *builder, const gchar *name, gint value, gboolean
}
void
-ghb_grey_combo_options(GtkBuilder *builder)
+ghb_grey_combo_options(signal_user_data_t *ud)
{
GtkWidget *widget;
- gint mux, track, titleindex, acodec;
- hb_audio_config_t *aconfig = NULL;
+ gint mux, track, titleindex, acodec, fallback;
+ hb_audio_config_t *aconfig = NULL;
GValue *gval;
- widget = GHB_WIDGET (builder, "title");
+ widget = GHB_WIDGET (ud->builder, "title");
gval = ghb_widget_value(widget);
titleindex = ghb_lookup_combo_int("title", gval);
ghb_value_free(gval);
- widget = GHB_WIDGET (builder, "AudioTrack");
+ widget = GHB_WIDGET (ud->builder, "AudioTrack");
gval = ghb_widget_value(widget);
track = ghb_lookup_combo_int("AudioTrack", gval);
ghb_value_free(gval);
aconfig = get_hb_audio(h_scan, titleindex, track);
- widget = GHB_WIDGET (builder, "FileFormat");
+ widget = GHB_WIDGET (ud->builder, "FileFormat");
gval = ghb_widget_value(widget);
mux = ghb_lookup_combo_int("FileFormat", gval);
ghb_value_free(gval);
- grey_combo_box_item(builder, "x264_analyse", 4, TRUE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FFAAC, FALSE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_FAAC, FALSE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_LAME, FALSE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, FALSE);
-
- gboolean allow_dca = TRUE;
- allow_dca = (mux != HB_MUX_MP4);
+ grey_combo_box_item(ud->builder, "x264_analyse", 4, TRUE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_FFAAC, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_FAAC, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_LAME, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_VORBIS, FALSE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_AC3_PASS, FALSE);
- if (allow_dca)
- {
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_PASS, FALSE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, FALSE);
- }
- else
- {
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE);
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, TRUE);
- }
+ grey_combo_box_item(ud->builder, "AudioEncoderFallback", HB_ACODEC_FFAAC, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoderFallback", HB_ACODEC_FAAC, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoderFallback", HB_ACODEC_LAME, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoderFallback", HB_ACODEC_VORBIS, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_MP3_PASS, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AAC_PASS, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AC3_PASS, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_PASS, FALSE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, FALSE);
+ if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_MP3)
+ {
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_MP3_PASS, TRUE);
+ }
+ if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_FFAAC)
+ {
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AAC_PASS, TRUE);
+ }
if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_AC3)
{
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_AC3_PASS, TRUE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_AC3_PASS, TRUE);
}
if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_DCA)
{
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_PASS, TRUE);
}
if (aconfig && (aconfig->in.codec & HB_ACODEC_MASK) != HB_ACODEC_DCA_HD)
{
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, TRUE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_DCA_HD_PASS, TRUE);
}
- grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, FALSE);
+ grey_combo_box_item(ud->builder, "VideoEncoder", HB_VCODEC_THEORA, FALSE);
- widget = GHB_WIDGET (builder, "AudioEncoder");
+ widget = GHB_WIDGET (ud->builder, "AudioEncoder");
gval = ghb_widget_value(widget);
acodec = ghb_lookup_combo_int("AudioEncoder", gval);
ghb_value_free(gval);
- grey_combo_box_item(builder, "AudioMixdown", 0, TRUE);
+ grey_combo_box_item(ud->builder, "AudioMixdown", 0, TRUE);
if (mux == HB_MUX_MP4)
{
- grey_combo_box_item(builder, "AudioEncoder", HB_ACODEC_VORBIS, TRUE);
- grey_combo_box_item(builder, "VideoEncoder", HB_VCODEC_THEORA, TRUE);
+ grey_combo_box_item(ud->builder, "AudioEncoder", HB_ACODEC_VORBIS, TRUE);
+ grey_combo_box_item(ud->builder, "AudioEncoderFallback", HB_ACODEC_VORBIS, TRUE);
+ grey_combo_box_item(ud->builder, "VideoEncoder", HB_VCODEC_THEORA, TRUE);
}
gboolean allow_mono = TRUE;
@@ -1610,7 +1631,9 @@ ghb_grey_combo_options(GtkBuilder *builder)
allow_6ch = acodec & ~HB_ACODEC_LAME;
if (aconfig)
{
- acodec = ghb_select_audio_codec(mux, aconfig, acodec);
+ 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 best = hb_get_best_mixdown(acodec, aconfig->in.channel_layout, 0);
allow_stereo = best >= HB_AMIXDOWN_STEREO;
@@ -1619,17 +1642,17 @@ ghb_grey_combo_options(GtkBuilder *builder)
allow_6ch = best >= HB_AMIXDOWN_6CH;
allow_mono = best >= HB_AMIXDOWN_MONO;
}
- grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_MONO, !allow_mono);
- grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_STEREO, !allow_stereo);
- grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_DOLBY, !allow_dolby);
- grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_DOLBYPLII, !allow_dpl2);
- grey_combo_box_item(builder, "AudioMixdown", HB_AMIXDOWN_6CH, !allow_6ch);
+ grey_combo_box_item(ud->builder, "AudioMixdown", HB_AMIXDOWN_MONO, !allow_mono);
+ grey_combo_box_item(ud->builder, "AudioMixdown", HB_AMIXDOWN_STEREO, !allow_stereo);
+ grey_combo_box_item(ud->builder, "AudioMixdown", HB_AMIXDOWN_DOLBY, !allow_dolby);
+ grey_combo_box_item(ud->builder, "AudioMixdown", HB_AMIXDOWN_DOLBYPLII, !allow_dpl2);
+ grey_combo_box_item(ud->builder, "AudioMixdown", HB_AMIXDOWN_6CH, !allow_6ch);
}
gint
ghb_get_best_mix(hb_audio_config_t *aconfig, gint acodec, gint mix)
{
- int layout;
+ gint layout;
layout = aconfig ? aconfig->in.channel_layout :
HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE;
return hb_get_best_mixdown( acodec, layout, mix );
@@ -2780,6 +2803,7 @@ ghb_update_ui_combo_box(
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);
@@ -4135,70 +4159,6 @@ ghb_validate_subtitles(signal_user_data_t *ud)
return TRUE;
}
-gint
-ghb_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec)
-{
- guint32 in_codec = aconfig ? aconfig->in.codec : HB_ACODEC_MASK;
- if (mux == HB_MUX_MP4)
- {
- if ((acodec & in_codec & HB_ACODEC_AC3))
- {
- return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
- }
- 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
- {
- return HB_ACODEC_FAAC;
- }
- }
- else
- {
- if ((acodec & in_codec & HB_ACODEC_PASS_MASK))
- {
- return acodec & (in_codec | HB_ACODEC_PASS_FLAG);
- }
- else if (acodec & HB_ACODEC_AC3)
- {
- return HB_ACODEC_AC3;
- }
- else if (acodec & HB_ACODEC_VORBIS)
- {
- return HB_ACODEC_VORBIS;
- }
- 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
- {
- return HB_ACODEC_LAME;
- }
- }
-}
-
gboolean
ghb_validate_audio(signal_user_data_t *ud)
{
@@ -4283,11 +4243,6 @@ ghb_validate_audio(signal_user_data_t *ud)
a_unsup = "Vorbis";
codec = HB_ACODEC_FAAC;
}
- if (codec == HB_ACODEC_DCA)
- {
- a_unsup = "DTS";
- codec = HB_ACODEC_AC3;
- }
}
if (a_unsup)
{
@@ -4711,7 +4666,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
GValue *asettings;
hb_audio_config_t audio;
hb_audio_config_t *aconfig;
- gint acodec;
+ gint acodec, fallback;
hb_audio_config_init(&audio);
asettings = ghb_array_get_nth(audio_list, ii);
@@ -4735,7 +4690,9 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex)
acodec = ghb_settings_combo_int(asettings, "AudioEncoder");
- audio.out.codec = ghb_select_audio_codec(job->mux, aconfig, acodec);
+ 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);
audio.out.gain =
ghb_settings_get_double(asettings, "AudioTrackGain");
diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h
index 6733ad306..f59d821a6 100644
--- a/gtk/src/hb-backend.h
+++ b/gtk/src/hb-backend.h
@@ -137,7 +137,7 @@ hb_audio_config_t* ghb_get_scan_audio_info(gint titleindex, gint audioindex);
void ghb_set_passthru_bitrate_opts(GtkBuilder *builder, gint bitrate);
void ghb_set_default_bitrate_opts(
GtkBuilder *builder, gint first_rate, gint last_rate);
-void ghb_grey_combo_options(GtkBuilder *builder);
+void ghb_grey_combo_options(signal_user_data_t *ud);
void ghb_update_ui_combo_box(
signal_user_data_t *ud, const gchar *name, gint user_data, gboolean all);
gchar* ghb_get_source_audio_lang(gint titleindex, gint track);
@@ -175,7 +175,6 @@ 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_select_audio_codec(gint mux, hb_audio_config_t *aconfig, gint acodec);
gint ghb_find_closest_audio_rate(gint rate);
GValue* ghb_lookup_acodec_value(gint val);
diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml
index e4a4a72b6..b4d06694d 100644
--- a/gtk/src/internal_defaults.xml
+++ b/gtk/src/internal_defaults.xml
@@ -295,6 +295,18 @@
<true />
<key>Mp4LargeFile</key>
<false />
+ <key>AudioAllowMP3Pass</key>
+ <true />
+ <key>AudioAllowAACPass</key>
+ <true />
+ <key>AudioAllowAC3Pass</key>
+ <true />
+ <key>AudioAllowDTSPass</key>
+ <true />
+ <key>AudioAllowDTSHDPass</key>
+ <true />
+ <key>AudioEncoderFallback</key>
+ <string>ac3</string>
<key>AudioList</key>
<array>
<dict>
diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py
index a16b28ca5..65d398eca 100644
--- a/gtk/src/makedeps.py
+++ b/gtk/src/makedeps.py
@@ -49,13 +49,18 @@ dep_map = (
DepEntry("VideoEncoder", "x264_tab", "x264", False, True),
DepEntry("VideoEncoder", "lavc_mpeg4_tab", "ffmpeg|ffmpeg2", False, True),
DepEntry("VideoEncoder", "Mp4iPodCompatible", "x264", False, False),
- DepEntry("AudioEncoderActual", "AudioBitrate", "ac3pass|dtspass", True, False),
- DepEntry("AudioEncoderActual", "AudioSamplerate", "ac3pass|dtspass", True, False),
- DepEntry("AudioEncoderActual", "AudioMixdown", "ac3pass|dtspass", True, False),
- DepEntry("AudioEncoderActual", "AudioTrackDRCSlider", "ac3pass|dtspass", True, False),
- DepEntry("AudioEncoderActual", "drc_label", "ac3pass|dtspass", True, False),
- DepEntry("AudioEncoderActual", "AudioTrackGain", "ac3pass|dtspass", True, False),
- DepEntry("AudioEncoderActual", "gain_label", "ac3pass|dtspass", True, False),
+ DepEntry("AudioEncoderActual", "AudioBitrate", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoderActual", "AudioSamplerate", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoderActual", "AudioMixdown", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoderActual", "AudioTrackDRCSlider", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoderActual", "drc_label", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoderActual", "AudioTrackGain", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoderActual", "gain_label", "mp3pass|aacpass|ac3pass|dtspass|dtshdpass", True, False),
+ DepEntry("AudioEncoder", "AudioAllowMP3Pass", "auto", False, False),
+ DepEntry("AudioEncoder", "AudioAllowAACPass", "auto", False, False),
+ DepEntry("AudioEncoder", "AudioAllowAC3Pass", "auto", False, False),
+ DepEntry("AudioEncoder", "AudioAllowDTSPass", "auto", False, False),
+ DepEntry("AudioEncoder", "AudioAllowDTSHDPass", "auto", False, False),
DepEntry("x264_bframes", "x264_bpyramid", "<2", True, False),
DepEntry("x264_bframes", "x264_direct", "0", True, False),
DepEntry("x264_bframes", "x264_b_adapt", "0", True, False),
diff --git a/gtk/src/presets.c b/gtk/src/presets.c
index 064d27323..0a4d46745 100644
--- a/gtk/src/presets.c
+++ b/gtk/src/presets.c
@@ -2004,6 +2004,8 @@ static value_map_t acodec_xlat[] =
{"HE-AAC (CoreAudio)", "faac"},
{"AC3", "ac3"}, // Backwards compatibility with mac ui
{"AC3 (ffmpeg)", "ac3"},
+ {"MP3 Passthru", "mp3pass"},
+ {"AAC Passthru", "aacpass"},
{"AC3 Passthru", "ac3pass"},
{"DTS Passthru", "dtspass"},
{"DTS-HD Passthru", "dtshdpass"},
@@ -2055,10 +2057,10 @@ value_map_t mix_xlat[] =
{"Dolby Surround", "dpl1"},
{"Dolby Pro Logic II", "dpl2"},
{"6-channel discrete", "6ch"},
- {"AC3 Passthru", "none"},
- {"DTS Passthru", "none"},
- {"DTS-HD Passthru", "none"},
{"None", "none"},
+ {"AC3 Passthru", "none"}, // Backwards compatibility with mac ui
+ {"DTS Passthru", "none"}, // Backwards compatibility with mac ui
+ {"DTS-HD Passthru", "none"}, // Backwards compatibility with mac ui
{NULL, NULL}
};
diff --git a/libhb/common.h b/libhb/common.h
index 48a4812bb..88bb8389d 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -321,9 +321,12 @@ struct hb_job_s
#define HB_ACODEC_FFAAC 0x00010000
#define HB_ACODEC_FFMPEG 0x00020000
#define HB_ACODEC_DCA_HD 0x00040000
-#define HB_ACODEC_FF_MASK 0x00060000
+#define HB_ACODEC_MP3 0x00080000
+#define HB_ACODEC_FF_MASK 0x000f0000
#define HB_ACODEC_PASS_FLAG 0x40000000
-#define HB_ACODEC_PASS_MASK (HB_ACODEC_DCA_HD | HB_ACODEC_AC3 | HB_ACODEC_DCA)
+#define HB_ACODEC_PASS_MASK (HB_ACODEC_MP3 | HB_ACODEC_FFAAC | HB_ACODEC_DCA_HD | HB_ACODEC_AC3 | HB_ACODEC_DCA)
+#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)
#define HB_ACODEC_DCA_PASS (HB_ACODEC_DCA | HB_ACODEC_PASS_FLAG)
#define HB_ACODEC_DCA_HD_PASS (HB_ACODEC_DCA_HD | HB_ACODEC_PASS_FLAG)
@@ -404,6 +407,7 @@ struct hb_audio_config_s
* are ignored.
*/
int samplerate; /* Output sample rate (Hz) */
+ int samples_per_frame; /* Number of samples per frame */
int bitrate; /* Output bitrate (kbps) */
int mixdown; /* The mixdown format to be used for this audio track (see HB_AMIXDOWN_*) */
double dynamic_range_compression; /* Amount of DRC that gets applied to this track */
@@ -423,6 +427,7 @@ struct hb_audio_config_s
PRIVATE uint32_t version; /* Bitsream version */
PRIVATE uint32_t mode; /* Bitstream mode, codec dependent encoding */
PRIVATE int samplerate; /* Input sample rate (Hz) */
+ PRIVATE int samples_per_frame; /* Number of samples per frame */
PRIVATE int bitrate; /* Input bitrate (kbps) */
PRIVATE int channel_layout; /* channel_layout is the channel layout of this audio this is used to
* provide a common way of describing the source audio */
@@ -714,6 +719,7 @@ typedef struct hb_work_info_s
struct { // info only valid for audio decoders
int channel_layout;
hb_chan_map_t * channel_map;
+ int samples_per_frame;
};
};
} hb_work_info_t;
diff --git a/libhb/deca52.c b/libhb/deca52.c
index 2771eda55..a8d537d52 100644
--- a/libhb/deca52.c
+++ b/libhb/deca52.c
@@ -414,6 +414,7 @@ static int deca52BSInfo( hb_work_object_t *w, const hb_buffer_t *b,
info->flags = flags;
info->version = raw >> 3; /* bsid is the first 5 bits */
info->mode = raw & 0x7; /* bsmod is the following 3 bits */
+ info->samples_per_frame = 1536;
if ( (flags & A52_CHANNEL_MASK) == A52_DOLBY )
{
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index e52021655..f67850d86 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -439,6 +439,7 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
&out_size, &avp );
if ( len > 0 && context->sample_rate > 0 )
{
+ int isamp = av_get_bytes_per_sample( context->sample_fmt );
info->bitrate = context->bit_rate;
info->rate = context->sample_rate;
info->rate_base = 1;
@@ -446,6 +447,11 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
hb_ff_layout_xlat(context->channel_layout,
context->channels);
ret = 1;
+ if ( context->channels && isamp )
+ {
+ info->samples_per_frame = out_size /
+ (isamp * context->channels);
+ }
break;
}
}
diff --git a/libhb/decdca.c b/libhb/decdca.c
index 138024a6d..4f5ee3929 100644
--- a/libhb/decdca.c
+++ b/libhb/decdca.c
@@ -311,6 +311,7 @@ static int decdcaBSInfo( hb_work_object_t *w, const hb_buffer_t *b,
info->rate_base = 1;
info->bitrate = bitrate;
info->flags = flags;
+ info->samples_per_frame = frame_length;
if ( ( flags & DCA_CHANNEL_MASK) == DCA_DOLBY )
{
diff --git a/libhb/declpcm.c b/libhb/declpcm.c
index 3dd1f7366..62eb563e8 100644
--- a/libhb/declpcm.c
+++ b/libhb/declpcm.c
@@ -259,6 +259,7 @@ static int declpcmBSInfo( hb_work_object_t *w, const hb_buffer_t *b,
int rate = hdr2samplerate[ ( b->data[4] >> 4 ) & 0x3 ];
int bitrate = rate * sample_size * nchannels;
+ int64_t duration = b->data[0] * 150;
memset( info, 0, sizeof(*info) );
@@ -269,6 +270,7 @@ static int declpcmBSInfo( hb_work_object_t *w, const hb_buffer_t *b,
info->flags = ( b->data[3] << 16 ) | ( b->data[4] << 8 ) | b->data[5];
info->channel_layout = hdr2layout[nchannels - 1];
info->channel_map = &hb_qt_chan_map;
+ info->samples_per_frame = ( duration * rate ) / 90000;
return 1;
}
diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c
index 9239c519a..ebf2fd8f2 100644
--- a/libhb/encavcodecaudio.c
+++ b/libhb/encavcodecaudio.c
@@ -103,7 +103,7 @@ static int encavcodecaInit( hb_work_object_t * w, hb_job_t * job )
}
pv->context = context;
- pv->samples_per_frame = context->frame_size;
+ audio->config.out.samples_per_frame = pv->samples_per_frame = context->frame_size;
pv->input_samples = pv->samples_per_frame * pv->out_discrete_channels;
// Set a reasonable maximum output size
diff --git a/libhb/encfaac.c b/libhb/encfaac.c
index fe1a1f55b..0ab9124c8 100644
--- a/libhb/encfaac.c
+++ b/libhb/encfaac.c
@@ -99,6 +99,7 @@ int encfaacInit( hb_work_object_t * w, hb_job_t * job )
pv->obuf = malloc( pv->output_bytes );
pv->framedur = 90000.0 * pv->input_samples /
( audio->config.out.samplerate * pv->out_discrete_channels );
+ audio->config.out.samples_per_frame = pv->input_samples / pv->out_discrete_channels;
cfg = faacEncGetCurrentConfiguration( pv->faac );
cfg->mpegVersion = MPEG4;
diff --git a/libhb/enclame.c b/libhb/enclame.c
index ba05e1fc0..434aa185e 100644
--- a/libhb/enclame.c
+++ b/libhb/enclame.c
@@ -76,6 +76,7 @@ int enclameInit( hb_work_object_t * w, hb_job_t * job )
pv->input_samples = 1152 * pv->out_discrete_channels;
pv->output_bytes = LAME_MAXMP3BUFFER;
pv->buf = malloc( pv->input_samples * sizeof( float ) );
+ audio->config.out.samples_per_frame = 1152;
pv->list = hb_list_init();
pv->pts = -1;
diff --git a/libhb/encvorbis.c b/libhb/encvorbis.c
index 01bd216e8..fc186e089 100644
--- a/libhb/encvorbis.c
+++ b/libhb/encvorbis.c
@@ -111,6 +111,7 @@ int encvorbisInit( hb_work_object_t * w, hb_job_t * job )
}
pv->input_samples = pv->out_discrete_channels * OGGVORBIS_FRAME_SIZE;
+ audio->config.out.samples_per_frame = OGGVORBIS_FRAME_SIZE;
pv->buf = malloc( pv->input_samples * sizeof( float ) );
pv->list = hb_list_init();
diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c
index f73139b98..2ec32139d 100644
--- a/libhb/muxmkv.c
+++ b/libhb/muxmkv.c
@@ -187,23 +187,21 @@ static int MKVInit( hb_mux_object_t * m )
mux_data->codec = audio->config.out.codec;
- switch (audio->config.out.codec)
+ switch (audio->config.out.codec & HB_ACODEC_MASK)
{
case HB_ACODEC_DCA:
- case HB_ACODEC_DCA_PASS:
case HB_ACODEC_DCA_HD:
- case HB_ACODEC_DCA_HD_PASS:
track->codecPrivate = NULL;
track->codecPrivateSize = 0;
track->codecID = MK_ACODEC_DTS;
break;
case HB_ACODEC_AC3:
- case HB_ACODEC_AC3_PASS:
track->codecPrivate = NULL;
track->codecPrivateSize = 0;
track->codecID = MK_ACODEC_AC3;
break;
case HB_ACODEC_LAME:
+ case HB_ACODEC_MP3:
track->codecPrivate = NULL;
track->codecPrivateSize = 0;
track->codecID = MK_ACODEC_MP3;
@@ -259,8 +257,7 @@ static int MKVInit( hb_mux_object_t * m )
lang = lang_for_code2( audio->config.lang.iso639_2 );
track->language = lang->iso639_2b ? lang->iso639_2b : lang->iso639_2;
track->extra.audio.samplingFreq = (float)audio->config.out.samplerate;
- if (audio->config.out.codec == HB_ACODEC_AC3_PASS ||
- audio->config.out.codec == HB_ACODEC_DCA_PASS)
+ if (audio->config.out.codec & HB_ACODEC_PASS_FLAG)
{
track->extra.audio.channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(audio->config.in.channel_layout);
}
diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c
index b9c7637e8..05bce561a 100644
--- a/libhb/muxmp4.c
+++ b/libhb/muxmp4.c
@@ -257,228 +257,206 @@ static int MP4Init( hb_mux_object_t * m )
MP4SetTrackFloatProperty(m->file, mux_data->track, "tkhd.width", job->width * (width / height));
}
- /* add the audio tracks */
+ /* add the audio tracks */
for( i = 0; i < hb_list_count( title->list_audio ); i++ )
{
audio = hb_list_item( title->list_audio, i );
mux_data = calloc(1, sizeof( hb_mux_data_t ) );
audio->priv.mux_data = mux_data;
- if( audio->config.out.codec == HB_ACODEC_AC3_PASS )
+ switch ( audio->config.out.codec & HB_ACODEC_MASK )
{
- uint8_t bsid = audio->config.in.version;
- uint8_t bsmod = audio->config.in.mode;
- uint8_t acmod = audio->config.flags.ac3 & 0x7;
- uint8_t lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0;
- uint8_t bit_rate_code = 0;
- int ii, jj;
- int freq = audio->config.in.samplerate;
- int bitrate = audio->config.in.bitrate;
- int sr_shift, sr_code;
-
- for (ii = 0; ii < 3; ii++)
+ case HB_ACODEC_AC3:
{
- for (jj = 0; jj < 3; jj++)
+ uint8_t bsid;
+ uint8_t bsmod;
+ uint8_t acmod;
+ uint8_t lfeon;
+ uint8_t bit_rate_code = 0;
+ int ii, jj;
+ int freq;
+ int bitrate;
+ int sr_shift, sr_code;
+
+ if ( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
{
- if ((ac3_sample_rate_tab[jj] >> ii) == freq)
+ bsmod = audio->config.in.mode;
+ acmod = audio->config.flags.ac3 & 0x7;
+ lfeon = (audio->config.flags.ac3 & A52_LFE) ? 1 : 0;
+ freq = audio->config.in.samplerate;
+ bitrate = audio->config.in.bitrate;
+ }
+ else
+ {
+ bsmod = 0;
+ freq = audio->config.out.samplerate;
+ bitrate = audio->config.out.bitrate * 1000;
+ switch( audio->config.out.mixdown )
{
- goto rate_found1;
+ case HB_AMIXDOWN_MONO:
+ acmod = 1;
+ lfeon = 0;
+ break;
+
+ case HB_AMIXDOWN_STEREO:
+ case HB_AMIXDOWN_DOLBY:
+ case HB_AMIXDOWN_DOLBYPLII:
+ acmod = 2;
+ lfeon = 0;
+ break;
+
+ case HB_AMIXDOWN_6CH:
+ acmod = 7;
+ lfeon = 1;
+ break;
+
+ default:
+ hb_log(" MP4Init: bad mixdown" );
+ acmod = 2;
+ lfeon = 0;
+ break;
}
}
- }
- hb_error("Unknown AC3 samplerate");
- ii = jj = 0;
-rate_found1:
- sr_shift = ii;
- sr_code = jj;
- for (ii = 0; ii < 19; ii++)
- {
- if ((ac3_bitrate_tab[ii] >> sr_shift)*1000 == bitrate)
- break;
- }
- if ( ii >= 19 )
- {
- hb_error("Unknown AC3 bitrate");
- ii = 0;
- }
- bit_rate_code = ii;
-
- mux_data->track = MP4AddAC3AudioTrack(
- m->file,
- audio->config.in.samplerate,
- sr_code,
- bsid,
- bsmod,
- acmod,
- lfeon,
- bit_rate_code);
- /* Tune track chunk duration */
- MP4TuneTrackDurationPerChunk( m, mux_data->track );
-
- if (audio->config.out.name == NULL) {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)"Surround", strlen("Surround"));
- }
- else {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)(audio->config.out.name),
- strlen(audio->config.out.name));
- }
- }
- else if( audio->config.out.codec == HB_ACODEC_AC3 )
- {
- uint8_t bsid = 8;
- uint8_t bsmod = 0;
- uint8_t acmod = 2;
- uint8_t lfeon = 0;
- uint8_t bit_rate_code = 0;
- int ii, jj;
- int freq = audio->config.out.samplerate;
- int bitrate = audio->config.out.bitrate;
- int sr_shift, sr_code;
-
- for (ii = 0; ii < 3; ii++)
- {
- for (jj = 0; jj < 3; jj++)
+ for (ii = 0; ii < 3; ii++)
{
- if ((ac3_sample_rate_tab[jj] >> ii) == freq)
+ for (jj = 0; jj < 3; jj++)
{
- goto rate_found2;
+ if ((ac3_sample_rate_tab[jj] >> ii) == freq)
+ {
+ goto rate_found1;
+ }
}
}
- }
- hb_error("Unknown AC3 samplerate");
- ii = jj = 0;
-rate_found2:
- sr_shift = ii;
- sr_code = jj;
- bsid = 8 + ii;
- for (ii = 0; ii < 19; ii++)
- {
- if ((ac3_bitrate_tab[ii] >> sr_shift) == bitrate)
- break;
- }
- if ( ii >= 19 )
- {
- hb_error("Unknown AC3 bitrate");
- ii = 0;
- }
- bit_rate_code = ii;
-
- switch( audio->config.out.mixdown )
+ hb_error("Unknown AC3 samplerate");
+ ii = jj = 0;
+ rate_found1:
+ sr_shift = ii;
+ sr_code = jj;
+ bsid = 8 + ii;
+ for (ii = 0; ii < 19; ii++)
+ {
+ if ((ac3_bitrate_tab[ii] >> sr_shift)*1000 == bitrate)
+ break;
+ }
+ if ( ii >= 19 )
+ {
+ hb_error("Unknown AC3 bitrate");
+ ii = 0;
+ }
+ bit_rate_code = ii;
+
+ mux_data->track = MP4AddAC3AudioTrack(
+ m->file,
+ freq,
+ sr_code,
+ bsid,
+ bsmod,
+ acmod,
+ lfeon,
+ bit_rate_code);
+
+ /* Tune track chunk duration */
+ MP4TuneTrackDurationPerChunk( m, mux_data->track );
+
+ if (audio->config.out.name == NULL) {
+ MP4SetTrackBytesProperty(
+ m->file, mux_data->track,
+ "udta.name.value",
+ (const uint8_t*)"Surround", strlen("Surround"));
+ }
+ else {
+ MP4SetTrackBytesProperty(
+ m->file, mux_data->track,
+ "udta.name.value",
+ (const uint8_t*)(audio->config.out.name),
+ strlen(audio->config.out.name));
+ }
+ } break;
+
+ case HB_ACODEC_FAAC:
+ case HB_ACODEC_FFAAC:
+ case HB_ACODEC_CA_AAC:
+ case HB_ACODEC_CA_HAAC:
+ case HB_ACODEC_LAME:
+ case HB_ACODEC_MP3:
+ case HB_ACODEC_DCA_HD:
+ case HB_ACODEC_DCA:
{
- case HB_AMIXDOWN_MONO:
- acmod = 1;
- break;
-
- case HB_AMIXDOWN_STEREO:
- case HB_AMIXDOWN_DOLBY:
- case HB_AMIXDOWN_DOLBYPLII:
- acmod = 2;
- break;
+ uint8_t audio_type;
+ int samplerate, samples_per_frame, channels, config_len;
+ uint8_t *config_bytes = NULL;
- case HB_AMIXDOWN_6CH:
- acmod = 7;
- lfeon = 1;
- break;
-
- default:
- hb_log(" MP4Init: bad mixdown" );
- break;
- }
-
- mux_data->track = MP4AddAC3AudioTrack(
- m->file,
- audio->config.out.samplerate,
- sr_code,
- bsid,
- bsmod,
- acmod,
- lfeon,
- bit_rate_code);
-
- /* Tune track chunk duration */
- MP4TuneTrackDurationPerChunk( m, mux_data->track );
-
- if (audio->config.out.name == NULL) {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)"Surround", strlen("Surround"));
- }
- else {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)(audio->config.out.name),
- strlen(audio->config.out.name));
- }
- }
- else if( audio->config.out.codec == HB_ACODEC_FAAC ||
- audio->config.out.codec == HB_ACODEC_FFAAC ||
- audio->config.out.codec == HB_ACODEC_CA_AAC ||
- audio->config.out.codec == HB_ACODEC_CA_HAAC )
- {
- int samples_per_frame = ( audio->config.out.codec == HB_ACODEC_CA_HAAC ) ? 2048 : 1024;
- mux_data->track = MP4AddAudioTrack(
- m->file,
- audio->config.out.samplerate, samples_per_frame, MP4_MPEG4_AUDIO_TYPE );
-
- /* Tune track chunk duration */
- MP4TuneTrackDurationPerChunk( m, mux_data->track );
-
- if (audio->config.out.name == NULL) {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)"Stereo", strlen("Stereo"));
- }
- else {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)(audio->config.out.name),
- strlen(audio->config.out.name));
- }
-
- MP4SetAudioProfileLevel( m->file, 0x0F );
- MP4SetTrackESConfiguration(
- m->file, mux_data->track,
- audio->priv.config.aac.bytes, audio->priv.config.aac.length );
-
- /* Set the correct number of channels for this track */
- MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (uint16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown));
- } else if( audio->config.out.codec == HB_ACODEC_LAME ) {
- mux_data->track = MP4AddAudioTrack(
- m->file,
- audio->config.out.samplerate, 1152, MP4_MPEG2_AUDIO_TYPE );
+ switch ( audio->config.out.codec & HB_ACODEC_MASK )
+ {
+ case HB_ACODEC_FAAC:
+ case HB_ACODEC_FFAAC:
+ case HB_ACODEC_CA_AAC:
+ case HB_ACODEC_CA_HAAC:
+ {
+ audio_type = MP4_MPEG4_AUDIO_TYPE;
+ config_bytes = audio->priv.config.aac.bytes;
+ config_len = audio->priv.config.aac.length;
+ } break;
+ case HB_ACODEC_LAME:
+ case HB_ACODEC_MP3:
+ {
+ audio_type = MP4_MPEG2_AUDIO_TYPE;
+ } break;
+ case HB_ACODEC_DCA:
+ case HB_ACODEC_DCA_HD:
+ {
+ audio_type = 0xA9;
+ } break;
+ }
+ if( audio->config.out.codec & HB_ACODEC_PASS_FLAG )
+ {
+ samplerate = audio->config.in.samplerate;
+ samples_per_frame = audio->config.in.samples_per_frame;
+ channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT(
+ audio->config.in.channel_layout );
+ }
+ else
+ {
+ samplerate = audio->config.out.samplerate;
+ samples_per_frame = audio->config.out.samples_per_frame;
+ channels = HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
+ audio->config.out.mixdown );
+ }
+ mux_data->track = MP4AddAudioTrack( m->file, samplerate,
+ samples_per_frame, audio_type );
- /* Tune track chunk duration */
- MP4TuneTrackDurationPerChunk( m, mux_data->track );
+ /* Tune track chunk duration */
+ MP4TuneTrackDurationPerChunk( m, mux_data->track );
- if (audio->config.out.name == NULL) {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)"Stereo", strlen("Stereo"));
- }
- else {
- MP4SetTrackBytesProperty(
- m->file, mux_data->track,
- "udta.name.value",
- (const uint8_t*)(audio->config.out.name),
- strlen(audio->config.out.name));
- }
+ if (audio->config.out.name == NULL) {
+ MP4SetTrackBytesProperty(
+ m->file, mux_data->track,
+ "udta.name.value",
+ (const uint8_t*)"Stereo", strlen("Stereo"));
+ }
+ else {
+ MP4SetTrackBytesProperty(
+ m->file, mux_data->track,
+ "udta.name.value",
+ (const uint8_t*)(audio->config.out.name),
+ strlen(audio->config.out.name));
+ }
- MP4SetAudioProfileLevel( m->file, 0x0F );
+ MP4SetAudioProfileLevel( m->file, 0x0F );
+ if ( config_bytes )
+ {
+ MP4SetTrackESConfiguration( m->file, mux_data->track,
+ config_bytes, config_len );
+ }
+ /* Set the correct number of channels for this track */
+ MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.*.channels", channels);
+ } break;
- /* Set the correct number of channels for this track */
- MP4SetTrackIntegerProperty(m->file, mux_data->track, "mdia.minf.stbl.stsd.mp4a.channels", (uint16_t)HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(audio->config.out.mixdown));
+ default:
+ {
+ hb_log("MP4Mux: Unsupported audio codec %x", audio->config.out.codec);
+ } break;
}
/* Set the language for this track */
diff --git a/libhb/platform/macosx/encca_aac.c b/libhb/platform/macosx/encca_aac.c
index 1bca23910..35b737e79 100644
--- a/libhb/platform/macosx/encca_aac.c
+++ b/libhb/platform/macosx/encca_aac.c
@@ -241,7 +241,7 @@ int encCoreAudioInit( hb_work_object_t * w, hb_job_t * job, enum AAC_MODE mode )
// set sizes
pv->isamplesiz = input.mBytesPerPacket;
- pv->isamples = output.mFramesPerPacket;
+ pv->isamples = audio->config.out.samples_per_frame = output.mFramesPerPacket;
pv->osamplerate = output.mSampleRate;
// set channel map and layout (for remapping)
diff --git a/libhb/scan.c b/libhb/scan.c
index 8999dc15c..43b4825bc 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -1030,6 +1030,7 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
hb_fifo_close( &audio->priv.scan_cache );
audio->config.in.samplerate = info.rate;
+ audio->config.in.samples_per_frame = info.samples_per_frame;
audio->config.in.bitrate = info.bitrate;
audio->config.in.channel_layout = info.channel_layout;
audio->config.in.channel_map = info.channel_map;
diff --git a/libhb/stream.c b/libhb/stream.c
index 84d31fe0b..d4f810c99 100644
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -57,7 +57,7 @@ static const stream2codec_t st2codec[256] = {
st(0x0c, N, 0, 0, "ISO 13818-6 Stream descriptors"),
st(0x0d, N, 0, 0, "ISO 13818-6 Sections"),
st(0x0e, N, 0, 0, "ISO 13818-1 auxiliary"),
- st(0x0f, A, HB_ACODEC_FFMPEG, CODEC_ID_AAC, "AAC"),
+ st(0x0f, A, HB_ACODEC_FFAAC, CODEC_ID_AAC, "AAC"),
st(0x10, V, WORK_DECAVCODECV, CODEC_ID_MPEG4, "MPEG4"),
st(0x11, A, HB_ACODEC_FFMPEG, CODEC_ID_AAC_LATM, "LATM AAC"),
st(0x12, U, 0, 0, "MPEG4 generic"),
@@ -1984,7 +1984,7 @@ static void add_audio_to_title(hb_title_t *title, int id)
switch ( id >> 12 )
{
case 0x0:
- audio->config.in.codec = HB_ACODEC_FFMPEG;
+ audio->config.in.codec = HB_ACODEC_MP3;
hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id);
break;
case 0x2:
@@ -3204,6 +3204,17 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id )
{
audio->config.in.codec = HB_ACODEC_DCA_HD;
}
+ else if ( codec->codec_id == CODEC_ID_AAC )
+ {
+ int len = MIN(codec->extradata_size, HB_CONFIG_MAX_SIZE);
+ memcpy(audio->priv.config.aac.bytes, codec->extradata, len);
+ audio->priv.config.aac.length = len;
+ audio->config.in.codec = HB_ACODEC_FFAAC;
+ }
+ else if ( codec->codec_id == CODEC_ID_MP3 )
+ {
+ audio->config.in.codec = HB_ACODEC_MP3;
+ }
else
{
audio->config.in.codec = HB_ACODEC_FFMPEG;
@@ -3212,6 +3223,7 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id )
audio->config.in.bitrate = codec->bit_rate? codec->bit_rate : 1;
audio->config.in.samplerate = codec->sample_rate;
+ audio->config.in.samples_per_frame = codec->frame_size;
audio->config.in.channel_layout = layout;
audio->config.in.channel_map = &hb_smpte_chan_map;
}
@@ -3698,7 +3710,7 @@ hb_buffer_t * hb_ffmpeg_read( hb_stream_t *stream )
{
buf->renderOffset = buf->start;
}
-
+
/*
* Fill out buf->stop for subtitle packets
*
diff --git a/libhb/sync.c b/libhb/sync.c
index b754a54cc..b1ec99619 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -14,8 +14,6 @@
#endif
#define INT64_MIN (-9223372036854775807LL-1)
-#define AC3_SAMPLES_PER_FRAME 1536
-
typedef struct
{
hb_lock_t * mutex;
@@ -44,9 +42,10 @@ typedef struct
SRC_STATE * state;
SRC_DATA data;
- /* AC-3 */
- int ac3_size;
- uint8_t * ac3_buf;
+ int silence_size;
+ uint8_t * silence_buf;
+
+ int drop_video_to_sync;
double gain_factor;
} hb_sync_audio_t;
@@ -261,7 +260,7 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
hb_subtitle_t * subtitle;
hb_sync_video_t * sync = &pv->type.video;
int i;
- int64_t start, next_start;
+ int64_t next_start;
*buf_out = NULL;
next = *buf_in;
@@ -456,16 +455,12 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
return HB_WORK_DONE;
}
- hb_lock( pv->common->mutex );
- start = cur->start - pv->common->video_pts_slip;
- hb_unlock( pv->common->mutex );
-
/* Check for end of point-to-point pts encoding */
if( job->pts_to_stop && sync->next_start >= job->pts_to_stop )
{
// Drop an empty buffer into our output to ensure that things
// get flushed all the way out.
- hb_log( "sync: reached pts %"PRId64", exiting early", start );
+ hb_log( "sync: reached pts %"PRId64", exiting early", cur->start );
hb_buffer_close( &sync->cur );
hb_buffer_close( &next );
*buf_out = hb_buffer_init( 0 );
@@ -487,7 +482,7 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
if( sync->first_frame )
{
/* This is our first frame */
- if ( start > 0 )
+ if ( cur->start > 0 )
{
/*
* The first pts from a dvd should always be zero but
@@ -497,8 +492,8 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
* as if it started at zero so that our audio timing will
* be in sync.
*/
- hb_log( "sync: first pts is %"PRId64, start );
- start = 0;
+ hb_log( "sync: first pts is %"PRId64, cur->start );
+ cur->start = 0;
}
sync->first_frame = 0;
}
@@ -514,7 +509,7 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
* can deal with overlaps of up to a frame time but anything larger
* we handle by dropping frames here.
*/
- if ( next_start - start <= 0 )
+ if ( next_start - cur->start <= 0 )
{
if ( sync->first_drop == 0 )
{
@@ -533,8 +528,8 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
{
hb_log( "sync: video time didn't advance - dropped %d frames "
"(delta %d ms, current %"PRId64", next %"PRId64", dur %d)",
- sync->drop_count, (int)( start - sync->first_drop ) / 90,
- start, next_start, (int)( next_start - start ) );
+ sync->drop_count, (int)( cur->start - sync->first_drop ) / 90,
+ cur->start, next_start, (int)( next_start - cur->start ) );
sync->first_drop = 0;
sync->drop_count = 0;
}
@@ -766,14 +761,16 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
* explicit stop time from the start time of the next frame.
*/
*buf_out = cur;
+ int64_t duration = next_start - cur->start;
sync->cur = cur = next;
cur->sub = NULL;
- int64_t duration = next_start - start;
+ cur->start -= pv->common->video_pts_slip;
+ cur->stop -= pv->common->video_pts_slip;
sync->pts_skip = 0;
if ( duration <= 0 )
{
hb_log( "sync: invalid video duration %"PRId64", start %"PRId64", next %"PRId64"",
- duration, start, next_start );
+ duration, cur->start, next_start );
}
(*buf_out)->start = sync->next_start;
@@ -837,11 +834,11 @@ void syncAudioClose( hb_work_object_t * w )
hb_work_private_t * pv = w->private_data;
hb_sync_audio_t * sync = &pv->type.audio;
- if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
+ if( sync->silence_buf )
{
- free( sync->ac3_buf );
+ free( sync->silence_buf );
}
- else
+ if ( sync->state )
{
src_delete( sync->state );
}
@@ -985,29 +982,26 @@ static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
return HB_WORK_DONE;
}
- if ( start - sync->next_start < 0 )
+ // audio time went backwards.
+ // If our output clock is more than a half frame ahead of the
+ // input clock drop this frame to move closer to sync.
+ // Otherwise drop frames until the input clock matches the output clock.
+ if ( sync->next_start - start > 90*15 )
{
- // audio time went backwards.
- // If our output clock is more than a half frame ahead of the
- // input clock drop this frame to move closer to sync.
- // Otherwise drop frames until the input clock matches the output clock.
- if ( sync->first_drop || sync->next_start - start > 90*15 )
+ // Discard data that's in the past.
+ if ( sync->first_drop == 0 )
{
- // Discard data that's in the past.
- if ( sync->first_drop == 0 )
- {
- sync->first_drop = sync->next_start;
- }
- ++sync->drop_count;
- hb_buffer_close( &buf );
- return HB_WORK_OK;
+ sync->first_drop = start;
}
+ ++sync->drop_count;
+ hb_buffer_close( &buf );
+ return HB_WORK_OK;
}
if ( sync->first_drop )
{
// we were dropping old data but input buf time is now current
hb_log( "sync: audio 0x%x time went backwards %d ms, dropped %d frames "
- "(next %"PRId64", current %"PRId64")", w->audio->id,
+ "(start %"PRId64", next %"PRId64")", w->audio->id,
(int)( sync->next_start - sync->first_drop ) / 90,
sync->drop_count, sync->first_drop, (int64_t)sync->next_start );
sync->first_drop = 0;
@@ -1033,8 +1027,7 @@ static int syncAudioWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
* Or in the case of DCA, skip some frames from the
* other streams.
*/
- if( w->audio->config.out.codec == HB_ACODEC_DCA_PASS ||
- w->audio->config.out.codec == HB_ACODEC_DCA_HD_PASS )
+ if ( sync->drop_video_to_sync )
{
hb_log( "sync: audio gap %d ms. Skipping frames. Audio 0x%x"
" start %"PRId64", next %"PRId64,
@@ -1103,21 +1096,41 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
w->fifo_out = w->audio->priv.fifo_sync;
}
- if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
+ if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS ||
+ w->audio->config.out.codec == HB_ACODEC_AAC_PASS )
{
- /* Have a silent AC-3 frame ready in case we have to fill a
+ /* Have a silent AC-3/AAC frame ready in case we have to fill a
gap */
AVCodec * codec;
AVCodecContext * c;
short * zeros;
- codec = avcodec_find_encoder( CODEC_ID_AC3 );
+ switch ( w->audio->config.out.codec )
+ {
+ case HB_ACODEC_AC3_PASS:
+ {
+ codec = avcodec_find_encoder( CODEC_ID_AC3 );
+ } break;
+ case HB_ACODEC_AAC_PASS:
+ {
+ codec = avcodec_find_encoder( CODEC_ID_AAC );
+ } break;
+ case HB_ACODEC_MP3_PASS:
+ {
+ codec = avcodec_find_encoder( CODEC_ID_MP3 );
+ } break;
+ default:
+ {
+ // Never gets here
+ } break;
+ }
+
c = avcodec_alloc_context3( codec );
c->bit_rate = w->audio->config.in.bitrate;
c->sample_rate = w->audio->config.in.samplerate;
c->channels = HB_INPUT_CH_LAYOUT_GET_DISCRETE_COUNT( w->audio->config.in.channel_layout );
- c->sample_fmt = AV_SAMPLE_FMT_FLT;
+ hb_ff_set_sample_fmt( c, codec );
switch( w->audio->config.in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK )
{
@@ -1167,14 +1180,26 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
return;
}
- zeros = calloc( AC3_SAMPLES_PER_FRAME *
- sizeof( float ) * c->channels, 1 );
- sync->ac3_size = w->audio->config.in.bitrate * AC3_SAMPLES_PER_FRAME /
- w->audio->config.in.samplerate / 8;
- sync->ac3_buf = malloc( sync->ac3_size );
+ int input_size = c->frame_size * av_get_bytes_per_sample( c->sample_fmt ) * c->channels;
+ zeros = calloc( 1, input_size );
+ // Allocate enough space for the encoded silence
+ // The output should be < the input
+ sync->silence_buf = malloc( input_size );
+
+ // There is some delay in getting output from some audio encoders.
+ // So encode a few packets till we get output.
+ int ii;
+ for ( ii = 0; ii < 10; ii++ )
+ {
+ sync->silence_size = avcodec_encode_audio( c, sync->silence_buf,
+ input_size, zeros );
- if( avcodec_encode_audio( c, sync->ac3_buf, sync->ac3_size,
- zeros ) != sync->ac3_size )
+ if (sync->silence_size)
+ {
+ break;
+ }
+ }
+ if (!sync->silence_size)
{
hb_log( "sync: avcodec_encode_audio failed" );
}
@@ -1185,12 +1210,19 @@ static void InitAudio( hb_job_t * job, hb_sync_common_t * common, int i )
}
else
{
- /* Initialize libsamplerate */
- int error;
- sync->state = src_new( SRC_SINC_MEDIUM_QUALITY,
- HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
- w->audio->config.out.mixdown), &error );
- sync->data.end_of_input = 0;
+ if( w->audio->config.out.codec & HB_ACODEC_PASS_FLAG )
+ {
+ sync->drop_video_to_sync = 1;
+ }
+ else
+ {
+ /* Not passthru, Initialize libsamplerate */
+ int error;
+ sync->state = src_new( SRC_SINC_MEDIUM_QUALITY,
+ HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
+ w->audio->config.out.mixdown), &error );
+ sync->data.end_of_input = 0;
+ }
}
sync->gain_factor = pow(LVL_PLUS1DB, w->audio->config.out.gain);
@@ -1293,29 +1325,39 @@ static void InsertSilence( hb_work_object_t * w, int64_t duration )
hb_sync_audio_t *sync = &pv->type.audio;
hb_buffer_t *buf;
hb_fifo_t *fifo;
+ int frame_dur, frame_count;
// to keep pass-thru and regular audio in sync we generate silence in
- // AC3 frame-sized units. If the silence duration isn't an integer multiple
- // of the AC3 frame duration we will truncate or round up depending on
+ // frame-sized units. If the silence duration isn't an integer multiple
+ // of the frame duration we will truncate or round up depending on
// which minimizes the timing error.
- const int frame_dur = ( 90000 * AC3_SAMPLES_PER_FRAME ) /
- w->audio->config.in.samplerate;
- int frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
+ if( w->audio->config.out.codec & HB_ACODEC_PASS_FLAG )
+ {
+ frame_dur = ( 90000 * w->audio->config.in.samples_per_frame ) /
+ w->audio->config.in.samplerate;
+ }
+ else
+ {
+ frame_dur = ( 90000 * w->audio->config.out.samples_per_frame ) /
+ w->audio->config.in.samplerate;
+ }
+ frame_count = ( duration + (frame_dur >> 1) ) / frame_dur;
while ( --frame_count >= 0 )
{
- if( w->audio->config.out.codec == HB_ACODEC_AC3_PASS )
+ if( w->audio->config.out.codec & HB_ACODEC_PASS_FLAG )
{
- buf = hb_buffer_init( sync->ac3_size );
+ buf = hb_buffer_init( sync->silence_size );
buf->start = sync->next_start;
buf->stop = buf->start + frame_dur;
- memcpy( buf->data, sync->ac3_buf, buf->size );
+ memcpy( buf->data, sync->silence_buf, buf->size );
fifo = w->audio->priv.fifo_out;
}
else
{
- buf = hb_buffer_init( AC3_SAMPLES_PER_FRAME * sizeof( float ) *
- HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
+ buf = hb_buffer_init( w->audio->config.out.samples_per_frame *
+ sizeof( float ) *
+ HB_AMIXDOWN_GET_DISCRETE_CHANNEL_COUNT(
w->audio->config.out.mixdown) );
buf->start = sync->next_start;
buf->stop = buf->start + frame_dur;
diff --git a/libhb/work.c b/libhb/work.c
index ffd48ec4b..222ae240f 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -378,6 +378,8 @@ void hb_display_job_info( hb_job_t * job )
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");
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m
index e92e578e4..b7fdbcc85 100644
--- a/macosx/HBAudio.m
+++ b/macosx/HBAudio.m
@@ -107,41 +107,55 @@ static NSMutableArray *masterBitRateArray = nil;
[NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
nil]];
[masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"MP3 (lame)", @"MP3 (lame)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_LAME], keyAudioCodec,
+ NSLocalizedString(@"AAC Passthru", @"AAC Passthru"), keyAudioCodecName,
+ [NSNumber numberWithInt: HB_ACODEC_AAC_PASS], keyAudioCodec,
[NSNumber numberWithBool: YES], keyAudioMP4,
[NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
+ [NSNumber numberWithInt: HB_ACODEC_FFAAC], keyAudioMustMatchTrack,
nil]];
[masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_AC3_PASS], keyAudioCodec,
+ NSLocalizedString(@"AC3 (ffmpeg)", @"AC3 (ffmpeg)"), keyAudioCodecName,
+ [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioCodec,
[NSNumber numberWithBool: YES], keyAudioMP4,
[NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioMustMatchTrack,
+ [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
nil]];
[masterCodecArray addObject: [NSDictionary dictionaryWithObjectsAndKeys:
- NSLocalizedString(@"AC3 (ffmpeg)", @"AC3 (ffmpeg)"), keyAudioCodecName,
- [NSNumber numberWithInt: HB_ACODEC_AC3], keyAudioCodec,
+ NSLocalizedString(@"AC3 Passthru", @"AC3 Passthru"), keyAudioCodecName,
+ [NSNumber numberWithInt: HB_ACODEC_AC3_PASS], keyAudioCodec,
[NSNumber numberWithBool: YES], keyAudioMP4,
[NSNumber numberWithBool: YES], keyAudioMKV,
- [NSNumber numberWithBool: NO], keyAudioMustMatchTrack,
+ [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: NO], keyAudioMP4,
+ [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: NO], keyAudioMP4,
+ [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,
diff --git a/macosx/HBAudioController.m b/macosx/HBAudioController.m
index ec9314697..b2de10c98 100644
--- a/macosx/HBAudioController.m
+++ b/macosx/HBAudioController.m
@@ -299,6 +299,13 @@ 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";
+ }
if ([[NSUserDefaults standardUserDefaults] boolForKey: @"AC3PassthruDefaultsToAC3"] &&
[key isEqualToString: @"AC3 Passthru"])
{
diff --git a/test/test.c b/test/test.c
index d9f360dec..4fd728537 100644
--- a/test/test.c
+++ b/test/test.c
@@ -2563,17 +2563,39 @@ static void ShowHelp()
#ifdef __APPLE_CC__
fprintf( out,
" -E, --aencoder <string> Audio encoder(s)\n"
- " (ca_aac/ca_haac/faac/lame/vorbis/ac3/copy/copy:ac3/copy:dts)\n"
- " copy, copy:ac3 and copy:dts meaning passthrough.\n"
- " copy will passthrough either ac3 or dts.\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"
+ " 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" );
#else
fprintf( out,
" -E, --aencoder <string> Audio encoder(s):\n"
- " (faac/lame/vorbis/ac3/copy/copy:ac3/copy:dts)\n"
- " copy, copy:ac3 and copy:dts meaning passthrough.\n"
- " copy will passthrough either ac3 or dts.\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" );
#endif
@@ -3427,6 +3449,10 @@ static int ParseOptions( int argc, char ** argv )
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;
}
str_vfree( allowed );
} break;
@@ -3600,6 +3626,10 @@ static int get_acodec_for_string( char *codec )
{
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;
@@ -3612,6 +3642,10 @@ static int get_acodec_for_string( char *codec )
{
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;