Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/xbmc/cores/AudioRenderers/Win32WASAPI.cpp b/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
- index d5b383a..5560f9a 100644
- --- a/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
- +++ b/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
- @@ -64,6 +64,7 @@ const enum PCMChannels wasapi_channel_order[] = {PCM_FRONT_LEFT, PCM_FRONT_RIGHT
- #define WASAPI_TOTAL_CHANNELS 11
- #define EXIT_ON_FAILURE(hr, reason, ...) if(FAILED(hr)) {CLog::Log(LOGERROR, reason, __VA_ARGS__); goto failed;}
- +#define CHECK_LOST_DEV(hr) if(
- //This needs to be static since only one exclusive stream can exist at one time.
- bool CWin32WASAPI::m_bIsAllocated = false;
- @@ -83,33 +84,56 @@ CWin32WASAPI::CWin32WASAPI() :
- m_LastCacheCheck(0),
- m_pAudioClient(NULL),
- m_pRenderClient(NULL),
- - m_pDevice(NULL)
- + m_pDevice(NULL),
- + m_Initialized(false),
- + m_Recover(false)
- {
- }
- +//***********************************************************************************************
- bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, EEncoded bAudioPassthrough)
- {
- - CLog::Log(LOGDEBUG, __FUNCTION__": endpoint device %s", device.c_str());
- -
- - //First check if the version of Windows we are running on even supports WASAPI.
- - if (!g_sysinfo.IsVistaOrHigher())
- + //Only one exclusive stream may be initialized at one time.
- + if(m_bIsAllocated)
- {
- - CLog::Log(LOGERROR, __FUNCTION__": WASAPI output requires Vista or higher.");
- + CLog::Log(LOGERROR, __FUNCTION__": Cannot create more then one WASAPI stream at one time.");
- return false;
- }
- - //Only one exclusive stream may be initialized at one time.
- - if(m_bIsAllocated)
- + // Save parameters to restore after device loss
- + m_pCallback = pCallback;
- + m_device = device;
- + m_iChannels = iChannels;
- + m_channelMap = channelMap;
- + m_uiSamplesPerSec = uiSamplesPerSec;
- + m_uiBitsPerSample = uiBitsPerSample;
- + m_bResample = bResample;
- + m_bIsMusic = bIsMusic;
- + m_bAudioPassthrough = bAudioPassthrough;
- +
- + bool rc = Initialize();
- + if (rc)
- + m_bIsAllocated = true;
- + return rc;
- +}
- +
- +//***********************************************************************************************
- +bool CWin32WASAPI::Initialize()
- +{
- + CLog::Log(LOGDEBUG, __FUNCTION__": endpoint device %s", m_device.c_str());
- +
- + //First check if the version of Windows we are running on even supports WASAPI.
- + if (!g_sysinfo.IsVistaOrHigher())
- {
- - CLog::Log(LOGERROR, __FUNCTION__": Cannot create more then one WASAPI stream at one time.");
- + CLog::Log(LOGERROR, __FUNCTION__": WASAPI output requires Vista or higher.");
- return false;
- }
- int layoutChannels = 0;
- - if(!bAudioPassthrough && channelMap)
- + if(!m_bAudioPassthrough && m_channelMap)
- {
- - PCMChannels *outLayout = m_remap.SetInputFormat(iChannels, channelMap, uiBitsPerSample / 8, uiSamplesPerSec);
- + PCMChannels *outLayout = m_remap.SetInputFormat(m_iChannels, m_channelMap, m_uiBitsPerSample / 8, m_uiSamplesPerSec);
- for(PCMChannels *channel = outLayout; *channel != PCM_INVALID; channel++)
- ++layoutChannels;
- @@ -117,7 +141,7 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- //Expand monural to stereo as most devices don't seem to like 1 channel PCM streams.
- //Stereo sources should be sent explicitly as two channels so that the external hardware
- //can apply ProLogic/5CH Stereo/etc processing on it.
- - if(iChannels <= 2)
- + if(m_iChannels <= 2)
- {
- BuildChannelMapping(2, (PCMChannels *)wasapi_default_channel_layout[1]);
- @@ -134,9 +158,8 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- m_bPlaying = false;
- m_bPause = false;
- m_bMuting = false;
- - m_uiChannels = iChannels;
- - m_uiBitsPerSample = uiBitsPerSample;
- - m_bPassthrough = (bAudioPassthrough != ENCODED_NONE);
- + m_uiChannels = m_iChannels;
- + m_bPassthrough = (m_bAudioPassthrough != ENCODED_NONE);
- m_nCurrentVolume = g_settings.m_nVolumeLevel;
- m_pcmAmplifier.SetVolume(m_nCurrentVolume);
- @@ -148,8 +171,8 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- ZeroMemory(&wfxex, sizeof(WAVEFORMATEXTENSIBLE));
- wfxex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
- wfxex.Format.nChannels = layoutChannels;
- - wfxex.Format.nSamplesPerSec = uiSamplesPerSec;
- - if (bAudioPassthrough)
- + wfxex.Format.nSamplesPerSec = m_uiSamplesPerSec;
- + if (m_bAudioPassthrough)
- {
- wfxex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
- wfxex.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF;
- @@ -162,17 +185,17 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- wfxex.dwChannelMask = m_uiSpeakerMask;
- wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- wfxex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- - wfxex.Format.wBitsPerSample = uiBitsPerSample;
- + wfxex.Format.wBitsPerSample = m_uiBitsPerSample;
- }
- - wfxex.Samples.wValidBitsPerSample = uiBitsPerSample == 32 ? 24 : uiBitsPerSample;
- + wfxex.Samples.wValidBitsPerSample = m_uiBitsPerSample == 32 ? 24 : m_uiBitsPerSample;
- wfxex.Format.nBlockAlign = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
- wfxex.Format.nAvgBytesPerSec = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
- m_uiAvgBytesPerSec = wfxex.Format.nAvgBytesPerSec;
- m_uiBytesPerFrame = wfxex.Format.nBlockAlign;
- - m_uiBytesPerSrcFrame = bAudioPassthrough ? m_uiBytesPerFrame : iChannels * wfxex.Format.wBitsPerSample >> 3;
- + m_uiBytesPerSrcFrame = m_bAudioPassthrough ? m_uiBytesPerFrame : m_iChannels * wfxex.Format.wBitsPerSample >> 3;
- IMMDeviceEnumerator* pEnumerator = NULL;
- IMMDeviceCollection* pEnumDevices = NULL;
- @@ -216,7 +239,7 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- CStdString strDevName;
- g_charsetConverter.wToUTF8(strRawDevName, strDevName);
- - if(device == strDevName)
- + if(m_device == strDevName)
- i = uiCount;
- else
- SAFE_RELEASE(m_pDevice);
- @@ -229,7 +252,10 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- if(!m_pDevice)
- {
- - CLog::Log(LOGDEBUG, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices. Trying the default device...", device.c_str());
- + if (m_Recover)
- + goto failed;
- +
- + CLog::Log(LOGDEBUG, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices. Trying the default device...", m_device.c_str());
- hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
- EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")
- }
- @@ -241,7 +267,7 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")
- hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
- - EXIT_ON_FAILURE(hr, __FUNCTION__": Audio format not supported by the WASAPI device. Channels: %i, Rate: %i, Bits/sample: %i.", iChannels, uiSamplesPerSec, uiBitsPerSample)
- + EXIT_ON_FAILURE(hr, __FUNCTION__": Audio format not supported by the WASAPI device. Channels: %i, Rate: %i, Bits/sample: %i.", m_iChannels, m_uiSamplesPerSec, m_uiBitsPerSample)
- REFERENCE_TIME hnsRequestedDuration, hnsPeriodicity;
- hr = m_pAudioClient->GetDevicePeriod(&hnsPeriodicity, NULL);
- @@ -272,11 +298,12 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
- hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
- EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")
- - m_bIsAllocated = true;
- + m_Initialized = true;
- + m_Recover = false;
- m_CacheLen = 0;
- m_LastCacheCheck = XbmcThreads::SystemClockMillis();
- -
- - return m_bIsAllocated;
- +
- + return true;
- failed:
- CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
- @@ -287,7 +314,10 @@ failed:
- SAFE_RELEASE(m_pDevice);
- //Restart Directsound
- - g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
- + if (!m_Recover)
- + g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
- + else
- + Sleep(100);
- return false;
- }
- @@ -305,16 +335,7 @@ bool CWin32WASAPI::Deinitialize()
- {
- CLog::Log(LOGDEBUG, __FUNCTION__": Cleaning up");
- - m_pAudioClient->Stop();
- -
- - SAFE_RELEASE(m_pRenderClient);
- - SAFE_RELEASE(m_pAudioClient);
- - SAFE_RELEASE(m_pDevice);
- -
- - m_CacheLen = 0;
- - m_uiChunkSize = 0;
- - m_uiBufferLen = 0;
- -
- + Close();
- m_bIsAllocated = false;
- //Restart Directsound for the interface sounds.
- @@ -324,11 +345,29 @@ bool CWin32WASAPI::Deinitialize()
- }
- //***********************************************************************************************
- +bool CWin32WASAPI::Close()
- +{
- + m_pAudioClient->Stop();
- +
- + SAFE_RELEASE(m_pRenderClient);
- + SAFE_RELEASE(m_pAudioClient);
- + SAFE_RELEASE(m_pDevice);
- +
- + m_CacheLen = 0;
- + m_uiChunkSize = 0;
- + m_uiBufferLen = 0;
- +
- + m_Initialized = false;
- +
- + return true;
- +}
- +
- +//***********************************************************************************************
- bool CWin32WASAPI::Pause()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return false;
- if (m_bPause) // Already paused
- @@ -345,7 +384,7 @@ bool CWin32WASAPI::Resume()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return false;
- if(!m_bPause) // Already playing
- @@ -367,7 +406,7 @@ bool CWin32WASAPI::Stop()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return false;
- // Stop and reset WASAPI buffer
- @@ -401,7 +440,7 @@ bool CWin32WASAPI::SetCurrentVolume(long nVolume)
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return false;
- m_nCurrentVolume = nVolume;
- @@ -417,6 +456,9 @@ unsigned int CWin32WASAPI::AddPackets(const void* data, unsigned int len)
- if (!m_bIsAllocated || m_bPause)
- return 0;
- + if (!m_Initialized && !Initialize())
- + return 0;
- +
- DWORD dwFlags = m_bMuting || m_nCurrentVolume == VOLUME_MINIMUM ? AUDCLNT_BUFFERFLAGS_SILENT : 0;
- unsigned int uiBytesToWrite, uiSrcBytesToWrite;
- @@ -447,11 +489,26 @@ unsigned int CWin32WASAPI::AddPackets(const void* data, unsigned int len)
- // Release the buffer
- if (FAILED(hr=m_pRenderClient->ReleaseBuffer(uiBytesToWrite/m_uiBytesPerFrame, dwFlags)))
- + {
- CLog::Log(LOGERROR, __FUNCTION__": ReleaseBuffer failed (%i)", hr);
- + if (hr == AUDCLNT_E_DEVICE_INVALIDATED)
- + {
- + m_Recover = true;
- + Close();
- + Sleep(5000);
- + }
- + return 0;
- + }
- }
- else
- {
- CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed (%i)", hr);
- + if (hr == AUDCLNT_E_DEVICE_INVALIDATED)
- + {
- + m_Recover = true;
- + Close();
- + }
- + return 0;
- }
- m_CacheLen += uiBytesToWrite;
- @@ -485,7 +542,7 @@ unsigned int CWin32WASAPI::GetSpace()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return 0;
- // Make sure we know how much data is in the cache
- @@ -499,7 +556,7 @@ float CWin32WASAPI::GetDelay()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return 0.0f;
- // Make sure we know how much data is in the cache
- @@ -513,7 +570,7 @@ float CWin32WASAPI::GetCacheTime()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return 0.0f;
- // Make sure we know how much data is in the cache
- @@ -527,7 +584,7 @@ float CWin32WASAPI::GetCacheTotal()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return 0.0f;
- return (float)m_uiBufferLen / (float)m_uiAvgBytesPerSec;
- @@ -642,7 +699,7 @@ void CWin32WASAPI::WaitCompletion()
- {
- CSingleLock lock (m_critSection);
- - if (!m_bIsAllocated)
- + if (!m_bIsAllocated || !m_Initialized)
- return;
- DWORD dwTimeRemaining;
- diff --git a/xbmc/cores/AudioRenderers/Win32WASAPI.h b/xbmc/cores/AudioRenderers/Win32WASAPI.h
- index 7fd8287..6bb785c 100644
- --- a/xbmc/cores/AudioRenderers/Win32WASAPI.h
- +++ b/xbmc/cores/AudioRenderers/Win32WASAPI.h
- @@ -67,6 +67,8 @@ public:
- static void EnumerateAudioSinks(AudioSinkList& vAudioSinks, bool passthrough);
- private:
- + bool Initialize();
- + bool Close();
- void AddDataToBuffer(unsigned char* pData, unsigned int len, unsigned char* pOut);
- void UpdateCacheStatus();
- void CheckPlayStatus();
- @@ -76,8 +78,6 @@ private:
- IAudioClient* m_pAudioClient;
- IAudioRenderClient* m_pRenderClient;
- - IAudioCallback* m_pCallback;
- -
- long m_nCurrentVolume;
- long m_drc;
- float m_fVolAdjustFactor;
- @@ -87,7 +87,6 @@ private:
- unsigned int m_uiBufferLen;
- unsigned int m_uiBytesPerFrame;
- unsigned int m_uiBytesPerSrcFrame;
- - unsigned int m_uiBitsPerSample;
- unsigned int m_uiChannels;
- unsigned int m_uiAvgBytesPerSec;
- unsigned int m_uiSpeakerMask;
- @@ -105,6 +104,21 @@ private:
- CPCMAmplifier m_pcmAmplifier;
- CCriticalSection m_critSection;
- +
- + // Initialization parameters
- + bool m_Initialized;
- + bool m_Recover;
- + IAudioCallback* m_pCallback;
- + CStdString m_device;
- + int m_iChannels;
- + enum PCMChannels *m_channelMap;
- + unsigned int m_uiSamplesPerSec;
- + unsigned int m_uiBitsPerSample;
- + bool m_bResample;
- + bool m_bIsMusic;
- + EEncoded m_bAudioPassthrough;
- +
- +
- };
- #endif //__WIN32WASAPI_H__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement