Advertisement
Guest User

Untitled

a guest
Mar 9th, 2012
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 14.26 KB | None | 0 0
  1. diff --git a/xbmc/cores/AudioRenderers/Win32WASAPI.cpp b/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
  2. index d5b383a..5560f9a 100644
  3. --- a/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
  4. +++ b/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
  5. @@ -64,6 +64,7 @@ const enum PCMChannels wasapi_channel_order[] = {PCM_FRONT_LEFT, PCM_FRONT_RIGHT
  6.  #define WASAPI_TOTAL_CHANNELS 11
  7.  
  8.  #define EXIT_ON_FAILURE(hr, reason, ...) if(FAILED(hr)) {CLog::Log(LOGERROR, reason, __VA_ARGS__); goto failed;}
  9. +#define CHECK_LOST_DEV(hr) if(
  10.  
  11.  //This needs to be static since only one exclusive stream can exist at one time.
  12.  bool CWin32WASAPI::m_bIsAllocated = false;
  13. @@ -83,33 +84,56 @@ CWin32WASAPI::CWin32WASAPI() :
  14.    m_LastCacheCheck(0),
  15.    m_pAudioClient(NULL),
  16.    m_pRenderClient(NULL),
  17. -  m_pDevice(NULL)
  18. +  m_pDevice(NULL),
  19. +  m_Initialized(false),
  20. +  m_Recover(false)
  21.  {
  22.  }
  23.  
  24. +//***********************************************************************************************
  25.  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)
  26.  {
  27. -  CLog::Log(LOGDEBUG, __FUNCTION__": endpoint device %s", device.c_str());
  28. -
  29. -  //First check if the version of Windows we are running on even supports WASAPI.
  30. -  if (!g_sysinfo.IsVistaOrHigher())
  31. +  //Only one exclusive stream may be initialized at one time.
  32. +  if(m_bIsAllocated)
  33.    {
  34. -    CLog::Log(LOGERROR, __FUNCTION__": WASAPI output requires Vista or higher.");
  35. +    CLog::Log(LOGERROR, __FUNCTION__": Cannot create more then one WASAPI stream at one time.");
  36.      return false;
  37.    }
  38.  
  39. -  //Only one exclusive stream may be initialized at one time.
  40. -  if(m_bIsAllocated)
  41. +  // Save parameters to restore after device loss
  42. +  m_pCallback         = pCallback;
  43. +  m_device            = device;
  44. +  m_iChannels         = iChannels;
  45. +  m_channelMap        = channelMap;
  46. +  m_uiSamplesPerSec   = uiSamplesPerSec;
  47. +  m_uiBitsPerSample   = uiBitsPerSample;
  48. +  m_bResample         = bResample;
  49. +  m_bIsMusic          = bIsMusic;
  50. +  m_bAudioPassthrough = bAudioPassthrough;
  51. +  
  52. +  bool rc = Initialize();
  53. +  if (rc)
  54. +    m_bIsAllocated = true;
  55. +  return rc;
  56. +}
  57. +
  58. +//***********************************************************************************************
  59. +bool CWin32WASAPI::Initialize()
  60. +{
  61. +  CLog::Log(LOGDEBUG, __FUNCTION__": endpoint device %s", m_device.c_str());
  62. +
  63. +  //First check if the version of Windows we are running on even supports WASAPI.
  64. +  if (!g_sysinfo.IsVistaOrHigher())
  65.    {
  66. -    CLog::Log(LOGERROR, __FUNCTION__": Cannot create more then one WASAPI stream at one time.");
  67. +    CLog::Log(LOGERROR, __FUNCTION__": WASAPI output requires Vista or higher.");
  68.      return false;
  69.    }
  70.  
  71.    int layoutChannels = 0;
  72.  
  73. -  if(!bAudioPassthrough && channelMap)
  74. +  if(!m_bAudioPassthrough && m_channelMap)
  75.    {
  76. -    PCMChannels *outLayout = m_remap.SetInputFormat(iChannels, channelMap, uiBitsPerSample / 8, uiSamplesPerSec);
  77. +    PCMChannels *outLayout = m_remap.SetInputFormat(m_iChannels, m_channelMap, m_uiBitsPerSample / 8, m_uiSamplesPerSec);
  78.  
  79.      for(PCMChannels *channel = outLayout; *channel != PCM_INVALID; channel++)
  80.          ++layoutChannels;
  81. @@ -117,7 +141,7 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  82.      //Expand monural to stereo as most devices don't seem to like 1 channel PCM streams.
  83.      //Stereo sources should be sent explicitly as two channels so that the external hardware
  84.      //can apply ProLogic/5CH Stereo/etc processing on it.
  85. -    if(iChannels <= 2)
  86. +    if(m_iChannels <= 2)
  87.      {
  88.        BuildChannelMapping(2, (PCMChannels *)wasapi_default_channel_layout[1]);
  89.  
  90. @@ -134,9 +158,8 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  91.    m_bPlaying = false;
  92.    m_bPause = false;
  93.    m_bMuting = false;
  94. -  m_uiChannels = iChannels;
  95. -  m_uiBitsPerSample = uiBitsPerSample;
  96. -  m_bPassthrough = (bAudioPassthrough != ENCODED_NONE);
  97. +  m_uiChannels = m_iChannels;
  98. +  m_bPassthrough = (m_bAudioPassthrough != ENCODED_NONE);
  99.  
  100.    m_nCurrentVolume = g_settings.m_nVolumeLevel;
  101.    m_pcmAmplifier.SetVolume(m_nCurrentVolume);
  102. @@ -148,8 +171,8 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  103.    ZeroMemory(&wfxex, sizeof(WAVEFORMATEXTENSIBLE));
  104.    wfxex.Format.cbSize          =  sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
  105.    wfxex.Format.nChannels       = layoutChannels;
  106. -  wfxex.Format.nSamplesPerSec  = uiSamplesPerSec;
  107. -  if (bAudioPassthrough)
  108. +  wfxex.Format.nSamplesPerSec  = m_uiSamplesPerSec;
  109. +  if (m_bAudioPassthrough)
  110.    {
  111.      wfxex.dwChannelMask          = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
  112.      wfxex.Format.wFormatTag      = WAVE_FORMAT_DOLBY_AC3_SPDIF;
  113. @@ -162,17 +185,17 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  114.      wfxex.dwChannelMask          = m_uiSpeakerMask;
  115.      wfxex.Format.wFormatTag      = WAVE_FORMAT_EXTENSIBLE;
  116.      wfxex.SubFormat              = KSDATAFORMAT_SUBTYPE_PCM;
  117. -    wfxex.Format.wBitsPerSample  = uiBitsPerSample;
  118. +    wfxex.Format.wBitsPerSample  = m_uiBitsPerSample;
  119.    }
  120.  
  121. -  wfxex.Samples.wValidBitsPerSample = uiBitsPerSample == 32 ? 24 : uiBitsPerSample;
  122. +  wfxex.Samples.wValidBitsPerSample = m_uiBitsPerSample == 32 ? 24 : m_uiBitsPerSample;
  123.    wfxex.Format.nBlockAlign       = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
  124.    wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
  125.  
  126.    m_uiAvgBytesPerSec = wfxex.Format.nAvgBytesPerSec;
  127.  
  128.    m_uiBytesPerFrame = wfxex.Format.nBlockAlign;
  129. -  m_uiBytesPerSrcFrame = bAudioPassthrough ? m_uiBytesPerFrame : iChannels * wfxex.Format.wBitsPerSample >> 3;
  130. +  m_uiBytesPerSrcFrame = m_bAudioPassthrough ? m_uiBytesPerFrame : m_iChannels * wfxex.Format.wBitsPerSample >> 3;
  131.  
  132.    IMMDeviceEnumerator* pEnumerator = NULL;
  133.    IMMDeviceCollection* pEnumDevices = NULL;
  134. @@ -216,7 +239,7 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  135.      CStdString strDevName;
  136.      g_charsetConverter.wToUTF8(strRawDevName, strDevName);
  137.  
  138. -    if(device == strDevName)
  139. +    if(m_device == strDevName)
  140.        i = uiCount;
  141.      else
  142.        SAFE_RELEASE(m_pDevice);
  143. @@ -229,7 +252,10 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  144.  
  145.    if(!m_pDevice)
  146.    {
  147. -    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());
  148. +    if (m_Recover)
  149. +      goto failed;
  150. +
  151. +    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());
  152.      hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
  153.      EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")
  154.    }
  155. @@ -241,7 +267,7 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  156.    EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")
  157.  
  158.    hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
  159. -  EXIT_ON_FAILURE(hr, __FUNCTION__": Audio format not supported by the WASAPI device.  Channels: %i, Rate: %i, Bits/sample: %i.", iChannels, uiSamplesPerSec, uiBitsPerSample)
  160. +  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)
  161.  
  162.    REFERENCE_TIME hnsRequestedDuration, hnsPeriodicity;
  163.    hr = m_pAudioClient->GetDevicePeriod(&hnsPeriodicity, NULL);
  164. @@ -272,11 +298,12 @@ bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& devic
  165.    hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
  166.    EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")
  167.  
  168. -  m_bIsAllocated = true;
  169. +  m_Initialized = true;
  170. +  m_Recover = false;
  171.    m_CacheLen = 0;
  172.    m_LastCacheCheck = XbmcThreads::SystemClockMillis();
  173. -  
  174. -  return m_bIsAllocated;
  175. +
  176. +  return true;
  177.  
  178.  failed:
  179.    CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
  180. @@ -287,7 +314,10 @@ failed:
  181.    SAFE_RELEASE(m_pDevice);
  182.  
  183.    //Restart Directsound
  184. -  g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  185. +  if (!m_Recover)
  186. +    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  187. +  else
  188. +    Sleep(100);
  189.  
  190.    return false;
  191.  }
  192. @@ -305,16 +335,7 @@ bool CWin32WASAPI::Deinitialize()
  193.    {
  194.      CLog::Log(LOGDEBUG, __FUNCTION__": Cleaning up");
  195.  
  196. -    m_pAudioClient->Stop();
  197. -
  198. -    SAFE_RELEASE(m_pRenderClient);
  199. -    SAFE_RELEASE(m_pAudioClient);
  200. -    SAFE_RELEASE(m_pDevice);
  201. -
  202. -    m_CacheLen = 0;
  203. -    m_uiChunkSize = 0;
  204. -    m_uiBufferLen = 0;
  205. -
  206. +    Close();
  207.      m_bIsAllocated = false;
  208.  
  209.      //Restart Directsound for the interface sounds.
  210. @@ -324,11 +345,29 @@ bool CWin32WASAPI::Deinitialize()
  211.  }
  212.  
  213.  //***********************************************************************************************
  214. +bool CWin32WASAPI::Close()
  215. +{
  216. +  m_pAudioClient->Stop();
  217. +
  218. +  SAFE_RELEASE(m_pRenderClient);
  219. +  SAFE_RELEASE(m_pAudioClient);
  220. +  SAFE_RELEASE(m_pDevice);
  221. +
  222. +  m_CacheLen = 0;
  223. +  m_uiChunkSize = 0;
  224. +  m_uiBufferLen = 0;
  225. +
  226. +  m_Initialized = false;
  227. +
  228. +  return true;
  229. +}
  230. +
  231. +//***********************************************************************************************
  232.  bool CWin32WASAPI::Pause()
  233.  {
  234.    CSingleLock lock (m_critSection);
  235.  
  236. -  if (!m_bIsAllocated)
  237. +  if (!m_bIsAllocated || !m_Initialized)
  238.      return false;
  239.  
  240.    if (m_bPause) // Already paused
  241. @@ -345,7 +384,7 @@ bool CWin32WASAPI::Resume()
  242.  {
  243.    CSingleLock lock (m_critSection);
  244.  
  245. -  if (!m_bIsAllocated)
  246. +  if (!m_bIsAllocated || !m_Initialized)
  247.      return false;
  248.  
  249.    if(!m_bPause) // Already playing
  250. @@ -367,7 +406,7 @@ bool CWin32WASAPI::Stop()
  251.  {
  252.    CSingleLock lock (m_critSection);
  253.  
  254. -  if (!m_bIsAllocated)
  255. +  if (!m_bIsAllocated || !m_Initialized)
  256.      return false;
  257.  
  258.    // Stop and reset WASAPI buffer
  259. @@ -401,7 +440,7 @@ bool CWin32WASAPI::SetCurrentVolume(long nVolume)
  260.  {
  261.    CSingleLock lock (m_critSection);
  262.  
  263. -  if (!m_bIsAllocated)
  264. +  if (!m_bIsAllocated || !m_Initialized)
  265.      return false;
  266.  
  267.    m_nCurrentVolume = nVolume;
  268. @@ -417,6 +456,9 @@ unsigned int CWin32WASAPI::AddPackets(const void* data, unsigned int len)
  269.    if (!m_bIsAllocated || m_bPause)
  270.      return 0;
  271.  
  272. +  if (!m_Initialized && !Initialize())
  273. +    return 0;
  274. +
  275.    DWORD dwFlags = m_bMuting || m_nCurrentVolume == VOLUME_MINIMUM ? AUDCLNT_BUFFERFLAGS_SILENT : 0;
  276.  
  277.    unsigned int uiBytesToWrite, uiSrcBytesToWrite;
  278. @@ -447,11 +489,26 @@ unsigned int CWin32WASAPI::AddPackets(const void* data, unsigned int len)
  279.  
  280.      // Release the buffer
  281.      if (FAILED(hr=m_pRenderClient->ReleaseBuffer(uiBytesToWrite/m_uiBytesPerFrame, dwFlags)))
  282. +    {
  283.        CLog::Log(LOGERROR, __FUNCTION__": ReleaseBuffer failed (%i)", hr);
  284. +      if (hr == AUDCLNT_E_DEVICE_INVALIDATED)
  285. +      {
  286. +        m_Recover = true;
  287. +        Close();
  288. +        Sleep(5000);
  289. +      }
  290. +      return 0;
  291. +    }
  292.    }
  293.    else
  294.    {
  295.      CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed (%i)", hr);
  296. +    if (hr == AUDCLNT_E_DEVICE_INVALIDATED)
  297. +    {
  298. +      m_Recover = true;
  299. +      Close();
  300. +    }
  301. +    return 0;
  302.    }
  303.    m_CacheLen += uiBytesToWrite;
  304.  
  305. @@ -485,7 +542,7 @@ unsigned int CWin32WASAPI::GetSpace()
  306.  {
  307.    CSingleLock lock (m_critSection);
  308.  
  309. -  if (!m_bIsAllocated)
  310. +  if (!m_bIsAllocated || !m_Initialized)
  311.      return 0;
  312.  
  313.    // Make sure we know how much data is in the cache
  314. @@ -499,7 +556,7 @@ float CWin32WASAPI::GetDelay()
  315.  {
  316.    CSingleLock lock (m_critSection);
  317.  
  318. -  if (!m_bIsAllocated)
  319. +  if (!m_bIsAllocated || !m_Initialized)
  320.      return 0.0f;
  321.  
  322.    // Make sure we know how much data is in the cache
  323. @@ -513,7 +570,7 @@ float CWin32WASAPI::GetCacheTime()
  324.  {
  325.    CSingleLock lock (m_critSection);
  326.  
  327. -  if (!m_bIsAllocated)
  328. +  if (!m_bIsAllocated || !m_Initialized)
  329.      return 0.0f;
  330.  
  331.    // Make sure we know how much data is in the cache
  332. @@ -527,7 +584,7 @@ float CWin32WASAPI::GetCacheTotal()
  333.  {
  334.    CSingleLock lock (m_critSection);
  335.  
  336. -  if (!m_bIsAllocated)
  337. +  if (!m_bIsAllocated || !m_Initialized)
  338.      return 0.0f;
  339.  
  340.    return (float)m_uiBufferLen / (float)m_uiAvgBytesPerSec;
  341. @@ -642,7 +699,7 @@ void CWin32WASAPI::WaitCompletion()
  342.  {
  343.    CSingleLock lock (m_critSection);
  344.  
  345. -  if (!m_bIsAllocated)
  346. +  if (!m_bIsAllocated || !m_Initialized)
  347.      return;
  348.  
  349.    DWORD dwTimeRemaining;
  350. diff --git a/xbmc/cores/AudioRenderers/Win32WASAPI.h b/xbmc/cores/AudioRenderers/Win32WASAPI.h
  351. index 7fd8287..6bb785c 100644
  352. --- a/xbmc/cores/AudioRenderers/Win32WASAPI.h
  353. +++ b/xbmc/cores/AudioRenderers/Win32WASAPI.h
  354. @@ -67,6 +67,8 @@ public:
  355.    static void EnumerateAudioSinks(AudioSinkList& vAudioSinks, bool passthrough);
  356.  
  357.  private:
  358. +  bool Initialize();
  359. +  bool Close();
  360.    void AddDataToBuffer(unsigned char* pData, unsigned int len, unsigned char* pOut);
  361.    void UpdateCacheStatus();
  362.    void CheckPlayStatus();
  363. @@ -76,8 +78,6 @@ private:
  364.    IAudioClient* m_pAudioClient;
  365.    IAudioRenderClient* m_pRenderClient;
  366.  
  367. -  IAudioCallback* m_pCallback;
  368. -
  369.    long m_nCurrentVolume;
  370.    long m_drc;
  371.    float m_fVolAdjustFactor;
  372. @@ -87,7 +87,6 @@ private:
  373.    unsigned int m_uiBufferLen;
  374.    unsigned int m_uiBytesPerFrame;
  375.    unsigned int m_uiBytesPerSrcFrame;
  376. -  unsigned int m_uiBitsPerSample;
  377.    unsigned int m_uiChannels;
  378.    unsigned int m_uiAvgBytesPerSec;
  379.    unsigned int m_uiSpeakerMask;
  380. @@ -105,6 +104,21 @@ private:
  381.  
  382.    CPCMAmplifier m_pcmAmplifier;
  383.    CCriticalSection m_critSection;
  384. +
  385. +  // Initialization parameters
  386. +  bool              m_Initialized;
  387. +  bool              m_Recover;
  388. +  IAudioCallback*   m_pCallback;
  389. +  CStdString        m_device;
  390. +  int               m_iChannels;
  391. +  enum PCMChannels *m_channelMap;
  392. +  unsigned int      m_uiSamplesPerSec;
  393. +  unsigned int      m_uiBitsPerSample;
  394. +  bool              m_bResample;
  395. +  bool              m_bIsMusic;
  396. +  EEncoded          m_bAudioPassthrough;
  397. +
  398. +
  399.  };
  400.  
  401.  #endif //__WIN32WASAPI_H__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement