Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/LAVFilters.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2012-07-14 12:32:57 +0400
committerHendrik Leppkes <h.leppkes@gmail.com>2012-07-14 12:32:57 +0400
commit34bbf4259fab58f19039ccfa398f5a5044956e3a (patch)
tree5d06a68aec51cdad4a0735723c8e6a811ed31987 /decoder/LAVAudio
parent1007411f99d58cf6504fc8cdb7450cd8c183ab48 (diff)
Introduce a fallback override mixer mode.
The fallback override mixer will only engage in case the channel layout changes mid-stream and the new layout is not being accepted by the audio renderer. This is typically the case with WMP/WMC, because they do not like channel re-configurations mid-stream. When the override mixer is activated, it'll mix the audio to the previous channel layout to ensure playback continues. Fixes issue 50.
Diffstat (limited to 'decoder/LAVAudio')
-rw-r--r--decoder/LAVAudio/LAVAudio.cpp60
-rw-r--r--decoder/LAVAudio/LAVAudio.h1
-rw-r--r--decoder/LAVAudio/PostProcessor.cpp22
3 files changed, 66 insertions, 17 deletions
diff --git a/decoder/LAVAudio/LAVAudio.cpp b/decoder/LAVAudio/LAVAudio.cpp
index ed36bba5..ed975428 100644
--- a/decoder/LAVAudio/LAVAudio.cpp
+++ b/decoder/LAVAudio/LAVAudio.cpp
@@ -80,6 +80,7 @@ CLAVAudio::CLAVAudio(LPUNKNOWN pUnk, HRESULT* phr)
, m_bChannelMappingRequired(FALSE)
, m_bFindDTSInPCM(FALSE)
, m_bFallback16Int(FALSE)
+ , m_dwOverrideMixer(0)
, m_bNeedSyncpoint(FALSE)
, m_dRate(1.0)
, m_bInputPadded(FALSE)
@@ -88,6 +89,7 @@ CLAVAudio::CLAVAudio(LPUNKNOWN pUnk, HRESULT* phr)
, m_bMixingSettingsChanged(FALSE)
, m_fMixingClipThreshold(0.0f)
, m_bHasVideo(TRUE)
+ , m_dwRemixLayout(0)
{
#ifdef DEBUG
DbgSetModuleLevel (LOG_CUSTOM1, DWORD_MAX); // FFMPEG messages use custom1
@@ -1260,6 +1262,8 @@ HRESULT CLAVAudio::ffmpeg_init(CodecID codec, const void *format, const GUID for
m_bFindDTSInPCM = (codec == CODEC_ID_PCM_S16LE && m_settings.bFormats[Codec_DTS]);
m_bFallback16Int = FALSE;
+ m_dwOverrideMixer = 0;
+ m_bMixingSettingsChanged = TRUE;
return S_OK;
}
@@ -2083,13 +2087,55 @@ HRESULT CLAVAudio::Deliver(BufferDetails &buffer)
if(hr == S_OK) {
hr = m_pOutput->GetConnected()->QueryAccept(&mt);
DbgLog((LOG_TRACE, 1, L"Sending new Media Type (QueryAccept: %0#.8x)", hr));
- if (hr != S_OK && buffer.sfFormat != SampleFormat_16) {
- mt = CreateMediaType(SampleFormat_16, buffer.dwSamplesPerSec, buffer.wChannels, buffer.dwChannelMask, 16);
- hr = m_pOutput->GetConnected()->QueryAccept(&mt);
- if (hr == S_OK) {
- DbgLog((LOG_TRACE, 1, L"-> 16-bit fallback type accepted"));
- ConvertSampleFormat(&buffer, SampleFormat_16);
- m_bFallback16Int = TRUE;
+ if (hr != S_OK) {
+ if (buffer.sfFormat != SampleFormat_16) {
+ mt = CreateMediaType(SampleFormat_16, buffer.dwSamplesPerSec, buffer.wChannels, buffer.dwChannelMask, 16);
+ hr = m_pOutput->GetConnected()->QueryAccept(&mt);
+ if (hr == S_OK) {
+ DbgLog((LOG_TRACE, 1, L"-> 16-bit fallback type accepted"));
+ ConvertSampleFormat(&buffer, SampleFormat_16);
+ m_bFallback16Int = TRUE;
+ }
+ }
+ // If a 16-bit fallback isn't enough, try to retain current channel layout
+ if (hr != S_OK) {
+ WAVEFORMATEX* wfeCurrent = (WAVEFORMATEX*)m_pOutput->CurrentMediaType().Format();
+ WORD wChannels = wfeCurrent->nChannels;
+ DWORD dwChannelMask = 0;
+ if (wfeCurrent->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
+ WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE *)wfeCurrent;
+ dwChannelMask = wfex->dwChannelMask;
+ } else {
+ dwChannelMask = wChannels == 2 ? (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) : SPEAKER_FRONT_CENTER;
+ }
+ mt = CreateMediaType(buffer.sfFormat, buffer.dwSamplesPerSec, wChannels, dwChannelMask, buffer.wBitsPerSample);
+ hr = m_pOutput->GetConnected()->QueryAccept(&mt);
+ if (hr == S_OK) {
+ DbgLog((LOG_TRACE, 1, L"-> Override Mixing to layout 0x%x", dwChannelMask));
+ m_dwOverrideMixer = dwChannelMask;
+ m_bMixingSettingsChanged = TRUE;
+ LAVAudioSampleFormat sf = buffer.sfFormat;
+ // Mix to the new layout
+ PerformMixing(&buffer);
+ // Convert to old sample format, if required
+ if (buffer.sfFormat != sf) {
+ ConvertSampleFormat(&buffer, sf);
+ }
+ } else {
+ // If current channel layout alone wasn't enough, also go 16-bit
+ mt = CreateMediaType(SampleFormat_16, buffer.dwSamplesPerSec, wChannels, dwChannelMask, 16);
+ hr = m_pOutput->GetConnected()->QueryAccept(&mt);
+ if (hr == S_OK) {
+ DbgLog((LOG_TRACE, 1, L"-> Override Mixing to layout 0x%x with 16-bit fallback type", dwChannelMask));
+ m_dwOverrideMixer = dwChannelMask;
+ m_bMixingSettingsChanged = TRUE;
+ // Mix to new layout
+ PerformMixing(&buffer);
+ // Convert to 16-bit
+ ConvertSampleFormat(&buffer, SampleFormat_16);
+ m_bFallback16Int = TRUE;
+ }
+ }
}
}
m_pOutput->SetMediaType(&mt);
diff --git a/decoder/LAVAudio/LAVAudio.h b/decoder/LAVAudio/LAVAudio.h
index 38b3b199..68ac5879 100644
--- a/decoder/LAVAudio/LAVAudio.h
+++ b/decoder/LAVAudio/LAVAudio.h
@@ -263,6 +263,7 @@ private:
GrowableArray<BYTE> m_buff; // Input Buffer
LAVAudioSampleFormat m_DecodeFormat; // Number of bits in the samples
BOOL m_bFallback16Int;
+ DWORD m_dwOverrideMixer;
BOOL m_bSampleSupport[SampleFormat_NB];
diff --git a/decoder/LAVAudio/PostProcessor.cpp b/decoder/LAVAudio/PostProcessor.cpp
index c3103736..87947c8b 100644
--- a/decoder/LAVAudio/PostProcessor.cpp
+++ b/decoder/LAVAudio/PostProcessor.cpp
@@ -554,8 +554,10 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer)
{
int ret = 0;
+ DWORD dwMixingLayout = m_dwOverrideMixer ? m_dwOverrideMixer : m_settings.MixingLayout;
+
// Check if we need mixing, either already in target mask or in stereo (no downmixing from stereo)
- if (buffer->dwChannelMask == m_settings.MixingLayout || (buffer->wChannels <= 2 && (m_settings.MixingFlags & LAV_MIXING_FLAG_UNTOUCHED_STEREO)))
+ if (buffer->dwChannelMask == dwMixingLayout || (buffer->wChannels <= 2 && (m_settings.MixingFlags & LAV_MIXING_FLAG_UNTOUCHED_STEREO) && !m_dwOverrideMixer))
return S_FALSE;
// Sadly, we need to convert this, avresample has no 24-bit mode
@@ -563,7 +565,7 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer)
ConvertSampleFormat(buffer, SampleFormat_32);
}
- if (buffer->dwChannelMask != m_DecodeLayoutSanified || (!m_avrContext && !m_bAVResampleFailed) || m_bMixingSettingsChanged) {
+ if (buffer->dwChannelMask != m_DecodeLayoutSanified || (!m_avrContext && !m_bAVResampleFailed) || m_bMixingSettingsChanged || m_dwRemixLayout != dwMixingLayout) {
m_bAVResampleFailed = FALSE;
m_bMixingSettingsChanged = FALSE;
if (m_avrContext) {
@@ -587,20 +589,20 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer)
av_opt_set_int(m_avrContext, "in_channel_layout", buffer->dwChannelMask, 0);
av_opt_set_int(m_avrContext, "in_sample_fmt", get_ff_sample_fmt(buffer->sfFormat), 0);
- av_opt_set_int(m_avrContext, "out_channel_layout", m_settings.MixingLayout, 0);
+ av_opt_set_int(m_avrContext, "out_channel_layout", dwMixingLayout, 0);
av_opt_set_int(m_avrContext, "out_sample_fmt", get_ff_sample_fmt(m_sfRemixFormat), 0);
// Create Matrix
int in_ch = buffer->wChannels;
- int out_ch = av_get_channel_layout_nb_channels(m_settings.MixingLayout);
+ int out_ch = av_get_channel_layout_nb_channels(dwMixingLayout);
double *matrix_dbl = (double *)av_mallocz(in_ch * out_ch * sizeof(*matrix_dbl));
const double center_mix_level = (double)m_settings.MixingCenterLevel / 10000.0 / M_SQRT1_2;
const double surround_mix_level = (double)m_settings.MixingSurroundLevel / 10000.0;
const double lfe_mix_level = (double)m_settings.MixingLFELevel / 10000.0;
- ret = avresample_build_matrix(buffer->dwChannelMask, m_settings.MixingLayout, center_mix_level, surround_mix_level, lfe_mix_level, bNormalize, matrix_dbl, in_ch, (AVMatrixEncoding)m_settings.MixingMode);
+ ret = avresample_build_matrix(buffer->dwChannelMask, dwMixingLayout, center_mix_level, surround_mix_level, lfe_mix_level, bNormalize, matrix_dbl, in_ch, (AVMatrixEncoding)m_settings.MixingMode);
if (ret < 0) {
- DbgLog((LOG_ERROR, 10, L"avresample_build_matrix failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, m_settings.MixingLayout, buffer->sfFormat, m_sfRemixFormat));
+ DbgLog((LOG_ERROR, 10, L"avresample_build_matrix failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, dwMixingLayout, buffer->sfFormat, m_sfRemixFormat));
av_free(matrix_dbl);
goto setuperr;
}
@@ -609,18 +611,18 @@ HRESULT CLAVAudio::PerformMixing(BufferDetails *buffer)
ret = avresample_set_matrix(m_avrContext, matrix_dbl, in_ch);
av_free(matrix_dbl);
if (ret < 0) {
- DbgLog((LOG_ERROR, 10, L"avresample_set_matrix failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, m_settings.MixingLayout, buffer->sfFormat, m_sfRemixFormat));
+ DbgLog((LOG_ERROR, 10, L"avresample_set_matrix failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, dwMixingLayout, buffer->sfFormat, m_sfRemixFormat));
goto setuperr;
}
// Open Resample Context
ret = avresample_open(m_avrContext);
if (ret < 0) {
- DbgLog((LOG_ERROR, 10, L"avresample_open failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, m_settings.MixingLayout, buffer->sfFormat, m_sfRemixFormat));
+ DbgLog((LOG_ERROR, 10, L"avresample_open failed, layout in: %x, out: %x, sample fmt in: %d, out: %d", buffer->dwChannelMask, dwMixingLayout, buffer->sfFormat, m_sfRemixFormat));
goto setuperr;
}
- m_dwRemixLayout = m_settings.MixingLayout;
+ m_dwRemixLayout = dwMixingLayout;
}
if (!m_avrContext)
@@ -683,7 +685,7 @@ HRESULT CLAVAudio::PostProcess(BufferDetails *buffer)
buffer->dwChannelMask = get_channel_mask(buffer->wChannels);
}
- if (m_settings.MixingEnabled) {
+ if (m_settings.MixingEnabled || m_dwOverrideMixer) {
PerformMixing(buffer);
}
// Remap to standard configurations, if requested