[vlc-commits] aout: handle DTSHD->DTS fallback
Thomas Guillem
git at videolan.org
Tue Oct 8 08:49:54 CEST 2019
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Oct 3 16:00:34 2019 +0200| [d69bae284b419545c401cada0703d13247371faa] | committer: Thomas Guillem
aout: handle DTSHD->DTS fallback
Use the DTSHD fourcc instead of the hacked "dtshd" variable.
The DTSHD -> DTS fallback is now handled in aout core, the same code path will
be used for EAC3 -> AC3 fallback. Therefore, aout modules don't have to handle
the DTSHD -> DTS fallback anymore. If a module can't handle DTSHD, it should
return an error and the DTS fourcc will be tried right after.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=d69bae284b419545c401cada0703d13247371faa
---
modules/audio_filter/converter/tospdif.c | 13 ++++++------
modules/audio_output/audiotrack.c | 34 +++++++++++++-------------------
modules/audio_output/mmdevice.c | 2 --
modules/audio_output/wasapi.c | 22 +--------------------
src/audio_output/aout_internal.h | 11 +++++++++++
src/audio_output/dec.c | 15 +++++---------
src/audio_output/output.c | 30 +++++++++++++++++++++++++++-
7 files changed, 66 insertions(+), 61 deletions(-)
diff --git a/modules/audio_filter/converter/tospdif.c b/modules/audio_filter/converter/tospdif.c
index 60f3e66544..239deae26f 100644
--- a/modules/audio_filter/converter/tospdif.c
+++ b/modules/audio_filter/converter/tospdif.c
@@ -96,6 +96,7 @@ static bool is_big_endian( filter_t *p_filter, block_t *p_in_buf )
case VLC_CODEC_TRUEHD:
return true;
case VLC_CODEC_DTS:
+ case VLC_CODEC_DTSHD:
return p_in_buf->p_buffer[0] == 0x1F
|| p_in_buf->p_buffer[0] == 0x7F;
default:
@@ -569,14 +570,11 @@ static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
case VLC_CODEC_TRUEHD:
i_ret = write_buffer_truehd( p_filter, p_in_buf );
break;
+ case VLC_CODEC_DTSHD:
+ i_ret = write_buffer_dtshd( p_filter, p_in_buf );
+ break;
case VLC_CODEC_DTS:
- /* if the fmt_out is configured for a higher rate than 48kHz
- * (IEC958 rate), use the DTS-HD framing to pass the DTS Core and
- * or DTS substreams (like DTS-HD MA). */
- if( p_filter->fmt_out.audio.i_rate > 48000 )
- i_ret = write_buffer_dtshd( p_filter, p_in_buf );
- else
- i_ret = write_buffer_dts( p_filter, p_in_buf );
+ i_ret = write_buffer_dts( p_filter, p_in_buf );
break;
default:
vlc_assert_unreachable();
@@ -606,6 +604,7 @@ static int Open( vlc_object_t *p_this )
filter_sys_t *p_sys;
if( ( p_filter->fmt_in.audio.i_format != VLC_CODEC_DTS &&
+ p_filter->fmt_in.audio.i_format != VLC_CODEC_DTSHD &&
p_filter->fmt_in.audio.i_format != VLC_CODEC_A52 &&
p_filter->fmt_in.audio.i_format != VLC_CODEC_EAC3 &&
p_filter->fmt_in.audio.i_format != VLC_CODEC_MLP &&
diff --git a/modules/audio_output/audiotrack.c b/modules/audio_output/audiotrack.c
index a5351c80e5..8b153e0ad0 100644
--- a/modules/audio_output/audiotrack.c
+++ b/modules/audio_output/audiotrack.c
@@ -1075,24 +1075,18 @@ AudioTrack_Create( JNIEnv *env, audio_output_t *p_aout,
}
static bool
-AudioTrack_HasEncoding( audio_output_t *p_aout, vlc_fourcc_t i_format,
- bool *p_dtshd )
+AudioTrack_HasEncoding( audio_output_t *p_aout, vlc_fourcc_t i_format )
{
aout_sys_t *p_sys = p_aout->sys;
#define MATCH_ENCODING_FLAG(x) jfields.AudioFormat.has_##x && \
( p_sys->i_encoding_flags == 0 || p_sys->i_encoding_flags & (1 << jfields.AudioFormat.x) )
- *p_dtshd = false;
switch( i_format )
{
+ case VLC_CODEC_DTSHD:
+ return MATCH_ENCODING_FLAG( ENCODING_DTS_HD );
case VLC_CODEC_DTS:
- if( MATCH_ENCODING_FLAG( ENCODING_DTS_HD )
- && var_GetBool( p_aout, "dtshd" ) )
- {
- *p_dtshd = true;
- return true;
- }
return MATCH_ENCODING_FLAG( ENCODING_DTS );
case VLC_CODEC_A52:
return MATCH_ENCODING_FLAG( ENCODING_AC3 );
@@ -1112,8 +1106,7 @@ StartPassthrough( JNIEnv *env, audio_output_t *p_aout )
aout_sys_t *p_sys = p_aout->sys;
int i_at_format;
- bool b_dtshd;
- if( !AudioTrack_HasEncoding( p_aout, p_sys->fmt.i_format, &b_dtshd ) )
+ if( !AudioTrack_HasEncoding( p_aout, p_sys->fmt.i_format ) )
return VLC_EGENERIC;
if( jfields.AudioFormat.has_ENCODING_IEC61937 )
@@ -1134,11 +1127,12 @@ StartPassthrough( JNIEnv *env, audio_output_t *p_aout )
case VLC_CODEC_DTS:
p_sys->fmt.i_bytes_per_frame = 4;
p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
- if( b_dtshd )
- {
- p_sys->fmt.i_rate = 192000;
- p_sys->fmt.i_bytes_per_frame = 16;
- }
+ break;
+ case VLC_CODEC_DTSHD:
+ p_sys->fmt.i_bytes_per_frame = 4;
+ p_sys->fmt.i_physical_channels = AOUT_CHANS_STEREO;
+ p_sys->fmt.i_rate = 192000;
+ p_sys->fmt.i_bytes_per_frame = 16;
break;
case VLC_CODEC_EAC3:
p_sys->fmt.i_rate = 192000;
@@ -2190,15 +2184,15 @@ static int DeviceSelect(audio_output_t *p_aout, const char *p_id)
if( at_dev == AT_DEV_ENCODED )
{
static const vlc_fourcc_t enc_fourccs[] = {
- VLC_CODEC_DTS, VLC_CODEC_A52, VLC_CODEC_EAC3, VLC_CODEC_TRUEHD,
+ VLC_CODEC_DTS, VLC_CODEC_DTSHD, VLC_CODEC_A52, VLC_CODEC_EAC3,
+ VLC_CODEC_TRUEHD,
};
for( size_t i = 0;
i < sizeof( enc_fourccs ) / sizeof( enc_fourccs[0] ); ++i )
{
- bool b_dtshd;
- if( AudioTrack_HasEncoding( p_aout, enc_fourccs[i], &b_dtshd ) )
+ if( AudioTrack_HasEncoding( p_aout, enc_fourccs[i] ) )
msg_Dbg( p_aout, "device has %4.4s passthrough support",
- b_dtshd ? "dtsh" : (const char *)&enc_fourccs[i] );
+ (const char *)&enc_fourccs[i] );
}
}
}
diff --git a/modules/audio_output/mmdevice.c b/modules/audio_output/mmdevice.c
index 07381c7ae2..bf1d2958bd 100644
--- a/modules/audio_output/mmdevice.c
+++ b/modules/audio_output/mmdevice.c
@@ -1119,8 +1119,6 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
case MM_PASSTHROUGH_ENABLED:
if (b_hdmi)
return -1;
- else if (fmt->i_format == VLC_CODEC_DTS)
- var_SetBool(aout, "dtshd", false );
/* falltrough */
case MM_PASSTHROUGH_ENABLED_HD:
break;
diff --git a/modules/audio_output/wasapi.c b/modules/audio_output/wasapi.c
index 113d0df1e6..66cfee466c 100644
--- a/modules/audio_output/wasapi.c
+++ b/modules/audio_output/wasapi.c
@@ -362,7 +362,7 @@ static void vlc_HdmiToWave(WAVEFORMATEXTENSIBLE_IEC61937 *restrict wf_iec61937,
switch (audio->i_format)
{
- case VLC_CODEC_DTS:
+ case VLC_CODEC_DTSHD:
wf->SubFormat = _KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
wf->Format.nChannels = 8;
wf->dwChannelMask = KSAUDIO_SPEAKER_7POINT1;
@@ -591,17 +591,6 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict pfmt,
audio_sample_format_t fmt = *pfmt;
bool b_spdif = AOUT_FMT_SPDIF(&fmt);
bool b_hdmi = AOUT_FMT_HDMI(&fmt);
- bool b_dtshd = false;
-
- if (fmt.i_format == VLC_CODEC_DTS)
- {
- b_dtshd = var_GetBool(vlc_object_parent(s), "dtshd");
- if (b_dtshd)
- {
- b_hdmi = true;
- b_spdif = false;
- }
- }
void *pv;
HRESULT hr = aout_stream_Activate(s, &IID_IAudioClient, NULL, &pv);
@@ -662,15 +651,6 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict pfmt,
if (FAILED(hr))
{
- if (pfmt->i_format == VLC_CODEC_DTS && b_hdmi)
- {
- msg_Warn(s, "cannot negotiate DTS at 768khz IEC958 rate (HDMI), "
- "fallback to 48kHz (S/PDIF) (error 0x%lX)", hr);
- IAudioClient_Release(sys->client);
- free(sys);
- var_SetBool(vlc_object_parent(s), "dtshd", false);
- return Start(s, pfmt, sid);
- }
msg_Err(s, "cannot negotiate audio format (error 0x%lX)%s", hr,
hr == AUDCLNT_E_UNSUPPORTED_FORMAT
&& fmt.i_format == VLC_CODEC_SPDIFL ?
diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h
index adb242eef6..a94d086410 100644
--- a/src/audio_output/aout_internal.h
+++ b/src/audio_output/aout_internal.h
@@ -76,7 +76,18 @@ typedef struct
int requested_stereo_mode; /**< Requested stereo mode set by the user */
+ /* Original input format and profile, won't change for the lifetime of a
+ * stream (between aout_DecNew() and aout_DecDelete()). */
+ int input_profile;
audio_sample_format_t input_format;
+
+ /* Format used to configure the conversion filters. It is based on the
+ * input_format but its fourcc can be different when the module is handling
+ * codec passthrough. Indeed, in case of DTSHD->DTS or EAC3->AC3 fallback,
+ * the filter need to know which codec is handled by the output. */
+ audio_sample_format_t filter_format;
+
+ /* Output format used and modified by the module. */
audio_sample_format_t mixer_format;
aout_filters_cfg_t filters_cfg;
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 07161bba2f..d89fedbf62 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -92,14 +92,9 @@ int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
owner->volume = aout_volume_New (p_aout, p_replay_gain);
atomic_store_explicit(&owner->restart, 0, memory_order_relaxed);
- owner->input_format = *p_format;
+ owner->input_profile = profile;
+ owner->filter_format = owner->mixer_format = owner->input_format = *p_format;
- /* TODO: 3.0 HACK: we need to put i_profile inside audio_format_t for 4.0
- * */
- if( owner->input_format.i_format == VLC_CODEC_DTS )
- var_SetBool( p_aout, "dtshd", profile > 0 );
-
- owner->mixer_format = owner->input_format;
owner->sync.clock = clock;
owner->filters_cfg = AOUT_FILTERS_CFG_INIT;
@@ -109,7 +104,7 @@ int aout_DecNew(audio_output_t *p_aout, const audio_sample_format_t *p_format,
/* Create the audio filtering "input" pipeline */
owner->filters = aout_FiltersNewWithClock(VLC_OBJECT(p_aout), clock,
- &owner->input_format,
+ &owner->filter_format,
&owner->mixer_format,
&owner->filters_cfg);
if (owner->filters == NULL)
@@ -167,7 +162,7 @@ static int aout_CheckReady (audio_output_t *aout)
msg_Dbg (aout, "restarting output...");
if (owner->mixer_format.i_format)
aout_OutputDelete (aout);
- owner->mixer_format = owner->input_format;
+ owner->filter_format = owner->mixer_format = owner->input_format;
owner->filters_cfg = AOUT_FILTERS_CFG_INIT;
if (aout_OutputNew (aout))
owner->mixer_format.i_format = 0;
@@ -189,7 +184,7 @@ static int aout_CheckReady (audio_output_t *aout)
{
owner->filters = aout_FiltersNewWithClock(VLC_OBJECT(aout),
owner->sync.clock,
- &owner->input_format,
+ &owner->filter_format,
&owner->mixer_format,
&owner->filters_cfg);
if (owner->filters == NULL)
diff --git a/src/audio_output/output.c b/src/audio_output/output.c
index 327b6268ce..93eb56fe05 100644
--- a/src/audio_output/output.c
+++ b/src/audio_output/output.c
@@ -517,16 +517,22 @@ static void aout_PrepareStereoMode (audio_output_t *aout,
/**
* Starts an audio output stream.
+ * \param output_codec codec accepted by the module, it can be different than
+ * the codec from the mixer_format in case of DTSHD/DTS or EAC3/AC3 fallback
* \warning The caller must NOT hold the audio output lock.
*/
int aout_OutputNew (audio_output_t *aout)
{
aout_owner_t *owner = aout_owner (aout);
audio_sample_format_t *fmt = &owner->mixer_format;
+ audio_sample_format_t *filter_fmt = &owner->filter_format;
aout_filters_cfg_t *filters_cfg = &owner->filters_cfg;
audio_channel_type_t input_chan_type = fmt->channel_type;
unsigned i_nb_input_channels = fmt->i_channels;
+ vlc_fourcc_t formats[] = {
+ fmt->i_format, 0, 0
+ };
/* Ideally, the audio filters would be created before the audio output,
* and the ideal audio format would be the output of the filters chain.
@@ -561,11 +567,33 @@ int aout_OutputNew (audio_output_t *aout)
aout_FormatPrepare (fmt);
assert (aout_FormatNbChannels(fmt) > 0);
}
+ else
+ {
+ switch (fmt->i_format)
+ {
+ case VLC_CODEC_DTS:
+ if (owner->input_profile > 0)
+ {
+ assert(ARRAY_SIZE(formats) >= 3);
+ /* DTSHD can be played as DTSHD or as DTS */
+ formats[0] = VLC_CODEC_DTSHD;
+ formats[1] = VLC_CODEC_DTS;
+ }
+ break;
+ default:
+ break;
+ }
+ }
aout->current_sink_info.headphones = false;
vlc_mutex_lock(&owner->lock);
- int ret = aout->start(aout, fmt);
+ int ret = VLC_EGENERIC;
+ for (size_t i = 0; formats[i] != 0 && ret != VLC_SUCCESS; ++i)
+ {
+ filter_fmt->i_format = fmt->i_format = formats[i];
+ ret = aout->start(aout, fmt);
+ }
assert(aout->flush && aout->play && aout->time_get && aout->pause);
vlc_mutex_unlock(&owner->lock);
if (ret)
More information about the vlc-commits
mailing list