vlc | branch: master | Thomas Guillem <[email protected]> | 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) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
