[release] version bump to 13.0 beta1
[vuplus_xbmc] / xbmc / cores / AudioEngine / Sinks / AESinkWASAPI.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "AESinkWASAPI.h"
22 #include <Audioclient.h>
23 #include <avrt.h>
24 #include <initguid.h>
25 #include <Mmreg.h>
26 #include <stdint.h>
27
28 #include "../Utils/AEUtil.h"
29 #include "settings/AdvancedSettings.h"
30 #include "utils/StdString.h"
31 #include "utils/log.h"
32 #include "threads/SingleLock.h"
33 #include "utils/CharsetConverter.h"
34 #include "../Utils/AEDeviceInfo.h"
35 #include <Mmreg.h>
36 #include <mmdeviceapi.h>
37 #include "utils/StringUtils.h"
38
39 #pragma comment(lib, "Avrt.lib")
40
41 const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
42 const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
43 const IID IID_IAudioClient = __uuidof(IAudioClient);
44 const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
45
46 static const unsigned int WASAPISampleRateCount = 10;
47 static const unsigned int WASAPISampleRates[] = {384000, 192000, 176400, 96000, 88200, 48000, 44100, 32000, 22050, 11025};
48
49 #define WASAPI_SPEAKER_COUNT 21
50 static const unsigned int WASAPIChannelOrder[] = {AE_CH_RAW,
51                                                   SPEAKER_FRONT_LEFT,           SPEAKER_FRONT_RIGHT,           SPEAKER_FRONT_CENTER,
52                                                   SPEAKER_LOW_FREQUENCY,        SPEAKER_BACK_LEFT,             SPEAKER_BACK_RIGHT,
53                                                   SPEAKER_FRONT_LEFT_OF_CENTER, SPEAKER_FRONT_RIGHT_OF_CENTER,
54                                                   SPEAKER_BACK_CENTER,          SPEAKER_SIDE_LEFT,             SPEAKER_SIDE_RIGHT,
55                                                   SPEAKER_TOP_FRONT_LEFT,       SPEAKER_TOP_FRONT_RIGHT,       SPEAKER_TOP_FRONT_CENTER,
56                                                   SPEAKER_TOP_CENTER,           SPEAKER_TOP_BACK_LEFT,         SPEAKER_TOP_BACK_RIGHT,
57                                                   SPEAKER_TOP_BACK_CENTER,      SPEAKER_RESERVED,              SPEAKER_RESERVED};
58
59 static const enum AEChannel AEChannelNames[]   = {AE_CH_RAW,
60                                                   AE_CH_FL,                     AE_CH_FR,                      AE_CH_FC,
61                                                   AE_CH_LFE,                    AE_CH_BL,                      AE_CH_BR,
62                                                   AE_CH_FLOC,                   AE_CH_FROC,
63                                                   AE_CH_BC,                     AE_CH_SL,                      AE_CH_SR,
64                                                   AE_CH_TFL,                    AE_CH_TFR,                     AE_CH_TFC ,
65                                                   AE_CH_TC  ,                   AE_CH_TBL,                     AE_CH_TBR,
66                                                   AE_CH_TBC,                    AE_CH_BLOC,                    AE_CH_BROC};
67
68 static const enum AEChannel layoutsList[][16] = 
69 {
70   /* Most common configurations */
71   {AE_CH_FC,  AE_CH_NULL}, // Mono
72   {AE_CH_FL,  AE_CH_FR,  AE_CH_NULL}, // Stereo
73   {AE_CH_FL,  AE_CH_FR,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // Quad
74   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BC,  AE_CH_NULL}, // Surround
75   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_NULL}, // Standard 5.1
76   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // Standard 7.1
77   /* Less common configurations */
78   {AE_CH_FL,  AE_CH_FR,  AE_CH_LFE, AE_CH_NULL}, // 2.1
79   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // 5.1 wide (obsolete)
80   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_BL,  AE_CH_BR,  AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // 7.1 wide (obsolete)
81   /* Exotic configurations */
82   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_NULL}, // 3 front speakers
83   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_NULL}, // 3 front speakers + LFE
84   {AE_CH_FL,  AE_CH_FR,  AE_CH_BL,  AE_CH_BR,  AE_CH_LFE, AE_CH_NULL}, // Quad + LFE
85   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BC,  AE_CH_LFE, AE_CH_NULL}, // Surround + LFE
86   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_SL,  AE_CH_SR,  AE_CH_NULL}, // Standard 5.1 w/o LFE
87   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // 5.1 wide w/o LFE
88   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_SL,  AE_CH_SR,  AE_CH_BC,  AE_CH_NULL}, // Standard 5.1 w/o LFE + Back Center
89   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BC,  AE_CH_BR,  AE_CH_NULL}, // 5.1 wide w/o LFE + Back Center
90   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_BL,  AE_CH_BR,  AE_CH_TC,  AE_CH_NULL}, // DVD speakers
91   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BR,  AE_CH_BC,  AE_CH_LFE, AE_CH_NULL}, // 5.1 wide + Back Center
92   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_NULL}, // Standard 7.1 w/o LFE
93   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_BL,  AE_CH_BR,  AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // 7.1 wide w/o LFE
94   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BC,  AE_CH_BR,  AE_CH_NULL}, // Standard 7.1 + Back Center
95   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_FLOC,AE_CH_FROC,AE_CH_NULL}, // Standard 7.1 + front wide
96   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_NULL}, // Standard 7.1 + 2 front top
97   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_NULL}, // Standard 7.1 + 3 front top
98   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TBL, AE_CH_TBR, AE_CH_NULL}, // Standard 7.1 + 2 front top + 2 back top
99   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_TBL, AE_CH_TBR, AE_CH_NULL}, // Standard 7.1 + 3 front top + 2 back top
100   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_TBL, AE_CH_TBR, AE_CH_TBC, AE_CH_NULL}, // Standard 7.1 + 3 front top + 3 back top
101   {AE_CH_FL,  AE_CH_FR,  AE_CH_FC,  AE_CH_LFE, AE_CH_SL,  AE_CH_SR,  AE_CH_BL,  AE_CH_BR,  AE_CH_TFL, AE_CH_TFR, AE_CH_TFC, AE_CH_TBL, AE_CH_TBR, AE_CH_TBC, AE_CH_TC,  AE_CH_NULL} // Standard 7.1 + 3 front top + 3 back top + Top Center
102 };
103
104 struct sampleFormat
105 {
106   GUID subFormat;
107   unsigned int bitsPerSample;
108   unsigned int validBitsPerSample;
109   AEDataFormat subFormatType;
110 };
111
112 /* Sample formats go from float -> 32 bit int -> 24 bit int (packed in 32) -> -> 24 bit int -> 16 bit int */
113 static const sampleFormat testFormats[] = { {KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 32, 32, AE_FMT_FLOAT},
114                                             {KSDATAFORMAT_SUBTYPE_PCM, 32, 32, AE_FMT_S32NE},
115                                             {KSDATAFORMAT_SUBTYPE_PCM, 32, 24, AE_FMT_S24NE4},
116                                             {KSDATAFORMAT_SUBTYPE_PCM, 24, 24, AE_FMT_S24NE3},
117                                             {KSDATAFORMAT_SUBTYPE_PCM, 16, 16, AE_FMT_S16NE} };
118
119 struct winEndpointsToAEDeviceType
120 {
121   std::string winEndpointType;
122   AEDeviceType aeDeviceType;
123 };
124
125 static const winEndpointsToAEDeviceType winEndpoints[EndpointFormFactor_enum_count] =
126 {
127   {"Network Device - ",         AE_DEVTYPE_PCM},
128   {"Speakers - ",               AE_DEVTYPE_PCM},
129   {"LineLevel - ",              AE_DEVTYPE_PCM},
130   {"Headphones - ",             AE_DEVTYPE_PCM},
131   {"Microphone - ",             AE_DEVTYPE_PCM},
132   {"Headset - ",                AE_DEVTYPE_PCM},
133   {"Handset - ",                AE_DEVTYPE_PCM},
134   {"Digital Passthrough - ", AE_DEVTYPE_IEC958},
135   {"SPDIF - ",               AE_DEVTYPE_IEC958},
136   {"HDMI - ",                  AE_DEVTYPE_HDMI},
137   {"Unknown - ",                AE_DEVTYPE_PCM},
138 };
139
140 AEDeviceInfoList DeviceInfoList;
141
142 #define EXIT_ON_FAILURE(hr, reason, ...) if(FAILED(hr)) {CLog::Log(LOGERROR, reason " - %s", __VA_ARGS__, WASAPIErrToStr(hr)); goto failed;}
143
144 #define ERRTOSTR(err) case err: return #err
145
146 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
147
148 DWORD ChLayoutToChMask(const enum AEChannel * layout, unsigned int * numberOfChannels = NULL)
149 {
150   if (numberOfChannels)
151     *numberOfChannels = 0;
152   if (!layout)
153     return 0;
154   
155   DWORD mask = 0;
156   unsigned int i;
157   for (i = 0; layout[i] != AE_CH_NULL; i++)
158     mask |= WASAPIChannelOrder[layout[i]];
159   
160   if (numberOfChannels)
161     *numberOfChannels = i;
162
163   return mask;
164 }
165
166 CStdStringA localWideToUtf(LPCWSTR wstr)
167 {
168   if (wstr == NULL)
169     return "";
170   int bufSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
171   CStdStringA strA ("", bufSize);
172   if ( bufSize == 0 || WideCharToMultiByte(CP_UTF8, 0, wstr, -1, strA.GetBuf(bufSize), bufSize, NULL, NULL) != bufSize )
173     strA.clear();
174   strA.RelBuf();
175   return strA;
176 }
177
178 CAESinkWASAPI::CAESinkWASAPI() :
179   m_needDataEvent(0),
180   m_pDevice(NULL),
181   m_pAudioClient(NULL),
182   m_pRenderClient(NULL),
183   m_encodedFormat(AE_FMT_INVALID),
184   m_encodedChannels(0),
185   m_encodedSampleRate(0),
186   sinkReqFormat(AE_FMT_INVALID),
187   sinkRetFormat(AE_FMT_INVALID),
188   m_running(false),
189   m_initialized(false),
190   m_isSuspended(false),
191   m_isDirty(false),
192   m_uiBufferLen(0),
193   m_avgTimeWaiting(50),
194   m_sinkLatency(0.0),
195   m_lastWriteToBuffer(0),
196   m_pBuffer(NULL),
197   m_bufferPtr(0)
198 {
199   m_channelLayout.Reset();
200 }
201
202 CAESinkWASAPI::~CAESinkWASAPI()
203 {
204
205 }
206
207 bool CAESinkWASAPI::Initialize(AEAudioFormat &format, std::string &device)
208 {
209   if (m_initialized)
210     return false;
211
212   m_device = device;
213   bool bdefault = false;
214
215   /* Save requested format */
216   /* Clear returned format */
217   sinkReqFormat = format.m_dataFormat;
218   sinkRetFormat = AE_FMT_INVALID;
219
220   IMMDeviceEnumerator* pEnumerator = NULL;
221   IMMDeviceCollection* pEnumDevices = NULL;
222
223   HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
224   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr)
225
226   /* Get our device. First try to find the named device. */
227   UINT uiCount = 0;
228
229   hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices);
230   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.")
231
232   hr = pEnumDevices->GetCount(&uiCount);
233   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.")
234
235   if(StringUtils::EndsWithNoCase(device, std::string("default")))
236     bdefault = true;
237
238   if(!bdefault)
239   {
240     for (UINT i = 0; i < uiCount; i++)
241     {
242       IPropertyStore *pProperty = NULL;
243       PROPVARIANT varName;
244
245       hr = pEnumDevices->Item(i, &m_pDevice);
246       EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint failed.")
247
248       hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
249       EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")
250
251       hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
252       if (FAILED(hr))
253       {
254         CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed.");
255         SAFE_RELEASE(pProperty);
256         goto failed;
257       }
258
259       std::string strDevName = localWideToUtf(varName.pwszVal);
260
261       if (device == strDevName)
262         i = uiCount;
263       else
264         SAFE_RELEASE(m_pDevice);
265
266       PropVariantClear(&varName);
267       SAFE_RELEASE(pProperty);
268     }
269   }
270   SAFE_RELEASE(pEnumDevices);
271
272   if (!m_pDevice)
273   {
274     if(!bdefault)
275       CLog::Log(LOGINFO, __FUNCTION__": Could not locate the device named \"%s\" in the list of WASAPI endpoint devices.  Trying the default device...", device.c_str());
276     hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &m_pDevice);
277     EXIT_ON_FAILURE(hr, __FUNCTION__": Could not retrieve the default WASAPI audio endpoint.")
278
279     IPropertyStore *pProperty = NULL;
280     PROPVARIANT varName;
281
282     hr = m_pDevice->OpenPropertyStore(STGM_READ, &pProperty);
283     EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.")
284
285     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
286
287     device = localWideToUtf(varName.pwszVal);
288     PropVariantClear(&varName);
289     SAFE_RELEASE(pProperty);
290   }
291
292   SAFE_RELEASE(pEnumerator);
293
294   hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
295   EXIT_ON_FAILURE(hr, __FUNCTION__": Activating the WASAPI endpoint device failed.")
296
297   if (!InitializeExclusive(format))
298   {
299     CLog::Log(LOGINFO, __FUNCTION__": Could not Initialize Exclusive with that format");
300     goto failed;
301   }
302
303   /* get the buffer size and calculate the frames for AE */
304   m_pAudioClient->GetBufferSize(&m_uiBufferLen);
305
306   format.m_frames       = m_uiBufferLen;
307   format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
308   m_format              = format;
309   sinkRetFormat         = format.m_dataFormat;
310
311   hr = m_pAudioClient->GetService(IID_IAudioRenderClient, (void**)&m_pRenderClient);
312   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not initialize the WASAPI render client interface.")
313
314   m_needDataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
315   hr = m_pAudioClient->SetEventHandle(m_needDataEvent);
316   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not set the WASAPI event handler.");
317
318   m_initialized = true;
319   m_isDirty     = false;
320
321   // allow feeding less samples than buffer size
322   // if the device is opened exclusive and event driven, provided samples must match buffersize
323   // ActiveAE tries to align provided samples with buffer size but cannot guarantee (e.g. transcoding)
324   // this can be avoided by dropping the event mode which has not much benefit; SoftAE polls anyway
325   delete [] m_pBuffer;
326   m_pBuffer = new uint8_t[format.m_frames * format.m_frameSize];
327   m_bufferPtr = 0;
328
329   return true;
330
331 failed:
332   CLog::Log(LOGERROR, __FUNCTION__": WASAPI initialization failed.");
333   SAFE_RELEASE(pEnumDevices);
334   SAFE_RELEASE(pEnumerator);
335   SAFE_RELEASE(m_pRenderClient);
336   SAFE_RELEASE(m_pAudioClient);
337   SAFE_RELEASE(m_pDevice);
338   if(m_needDataEvent)
339   {
340     CloseHandle(m_needDataEvent);
341     m_needDataEvent = 0;
342   }
343
344   return false;
345 }
346
347 void CAESinkWASAPI::Deinitialize()
348 {
349   if (!m_initialized && !m_isDirty)
350     return;
351
352   if (m_running)
353   {
354     try
355     {
356     m_pAudioClient->Stop();  //stop the audio output
357     m_pAudioClient->Reset(); //flush buffer and reset audio clock stream position
358     }
359     catch (...)
360     {
361       CLog::Log(LOGDEBUG, __FUNCTION__, "Invalidated AudioClient - Releasing");
362     }
363   }
364   m_running = false;
365
366   CloseHandle(m_needDataEvent);
367
368   SAFE_RELEASE(m_pRenderClient);
369   SAFE_RELEASE(m_pAudioClient);
370   SAFE_RELEASE(m_pDevice);
371
372   m_initialized = false;
373
374   delete [] m_pBuffer;
375   m_bufferPtr = 0;
376 }
377
378 double CAESinkWASAPI::GetDelay()
379 {
380   if (!m_initialized)
381     return 0.0;
382
383   double time_played = 0.0;
384   if (m_running)
385   {
386     unsigned int now = XbmcThreads::SystemClockMillis();
387     time_played = (double)(now-m_lastWriteToBuffer) / 1000;
388   }
389
390   double delay = m_sinkLatency - time_played + (double)m_bufferPtr / (double)m_format.m_sampleRate;
391
392   if (delay < 0)
393     delay = 0.0;
394
395   return delay;
396 }
397
398 double CAESinkWASAPI::GetCacheTotal()
399 {
400   if (!m_initialized)
401     return 0.0;
402
403   return m_sinkLatency;
404 }
405
406 unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
407 {
408   if (!m_initialized)
409     return 0;
410
411   HRESULT hr;
412   BYTE *buf;
413   DWORD flags = 0;
414
415 #ifndef _DEBUG
416   LARGE_INTEGER timerStart;
417   LARGE_INTEGER timerStop;
418   LARGE_INTEGER timerFreq;
419 #endif
420
421   unsigned int NumFramesRequested = m_format.m_frames;
422   unsigned int FramesToCopy = std::min(m_format.m_frames - m_bufferPtr, frames);
423   if (m_bufferPtr != 0 || frames != m_format.m_frames)
424   {
425     memcpy(m_pBuffer+m_bufferPtr*m_format.m_frameSize, data, FramesToCopy*m_format.m_frameSize);
426     m_bufferPtr += FramesToCopy;
427     if (m_bufferPtr != m_format.m_frames)
428       return frames;
429   }
430
431   if (!m_running) //first time called, pre-fill buffer then start audio client
432   {
433     hr = m_pAudioClient->Reset();
434     if (FAILED(hr))
435     {
436       CLog::Log(LOGERROR, __FUNCTION__ " AudioClient reset failed due to %s", WASAPIErrToStr(hr));
437       return 0;
438     }
439     hr = m_pRenderClient->GetBuffer(NumFramesRequested, &buf);
440     if (FAILED(hr))
441     {
442       #ifdef _DEBUG
443       CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed due to %s", WASAPIErrToStr(hr));
444       #endif
445       m_isDirty = true; //flag new device or re-init needed
446       return INT_MAX;
447     }
448
449     memset(buf, 0, NumFramesRequested * m_format.m_frameSize); //fill buffer with silence
450
451     hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
452     if (FAILED(hr))
453     {
454       #ifdef _DEBUG
455       CLog::Log(LOGDEBUG, __FUNCTION__": ReleaseBuffer failed due to %s.", WASAPIErrToStr(hr));
456       #endif
457       m_isDirty = true; //flag new device or re-init needed
458       return INT_MAX;
459     }
460     hr = m_pAudioClient->Start(); //start the audio driver running
461     if (FAILED(hr))
462       CLog::Log(LOGERROR, __FUNCTION__": AudioClient Start Failed");
463     m_running = true; //signal that we're processing frames
464     return 0U;
465   }
466
467 #ifndef _DEBUG
468   /* Get clock time for latency checks */
469   QueryPerformanceFrequency(&timerFreq);
470   QueryPerformanceCounter(&timerStart);
471 #endif
472
473   /* Wait for Audio Driver to tell us it's got a buffer available */
474   DWORD eventAudioCallback;
475   if(!blocking)
476     eventAudioCallback = WaitForSingleObject(m_needDataEvent, 0);
477   else
478     eventAudioCallback = WaitForSingleObject(m_needDataEvent, 1100);
479
480   if (!blocking)
481   {
482     if(eventAudioCallback != WAIT_OBJECT_0)
483           return 0;
484   }
485   else
486   {
487     if(eventAudioCallback != WAIT_OBJECT_0 || !&buf)
488     {
489       CLog::Log(LOGERROR, __FUNCTION__": Endpoint Buffer timed out");
490       return INT_MAX;
491     }
492   }
493
494
495   if (!m_running)
496     return 0;
497
498 #ifndef _DEBUG
499   QueryPerformanceCounter(&timerStop);
500   LONGLONG timerDiff = timerStop.QuadPart - timerStart.QuadPart;
501   double timerElapsed = (double) timerDiff * 1000.0 / (double) timerFreq.QuadPart;
502   m_avgTimeWaiting += (timerElapsed - m_avgTimeWaiting) * 0.5;
503
504   if (m_avgTimeWaiting < 3.0)
505   {
506     CLog::Log(LOGDEBUG, __FUNCTION__": Possible AQ Loss: Avg. Time Waiting for Audio Driver callback : %dmsec", (int)m_avgTimeWaiting);
507   }
508 #endif
509
510   hr = m_pRenderClient->GetBuffer(NumFramesRequested, &buf);
511   if (FAILED(hr))
512   {
513     #ifdef _DEBUG
514       CLog::Log(LOGERROR, __FUNCTION__": GetBuffer failed due to %s", WASAPIErrToStr(hr));
515     #endif
516     return INT_MAX;
517   }
518   memcpy(buf, m_bufferPtr == 0 ? data : m_pBuffer, NumFramesRequested * m_format.m_frameSize); //fill buffer
519   m_bufferPtr = 0;
520   hr = m_pRenderClient->ReleaseBuffer(NumFramesRequested, flags); //pass back to audio driver
521   if (FAILED(hr))
522   {
523     #ifdef _DEBUG
524     CLog::Log(LOGDEBUG, __FUNCTION__": ReleaseBuffer failed due to %s.", WASAPIErrToStr(hr));
525     #endif
526     return INT_MAX;
527   }
528   m_lastWriteToBuffer = XbmcThreads::SystemClockMillis();
529
530   if (FramesToCopy != frames)
531   {
532     m_bufferPtr = frames-FramesToCopy;
533     memcpy(m_pBuffer, data+FramesToCopy*m_format.m_frameSize, m_bufferPtr*m_format.m_frameSize);
534   }
535
536   return frames;
537 }
538
539 void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force)
540 {
541   IMMDeviceEnumerator* pEnumerator = NULL;
542   IMMDeviceCollection* pEnumDevices = NULL;
543   IMMDevice*           pDefaultDevice = NULL;
544   CAEDeviceInfo        deviceInfo;
545   CAEChannelInfo       deviceChannels;
546   LPWSTR               pwszID = NULL;
547   std::wstring         wstrDDID;
548
549   WAVEFORMATEXTENSIBLE wfxex = {0};
550   HRESULT              hr;
551
552   hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
553   EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %li", hr)
554
555   UINT uiCount = 0;
556
557   // get the default audio endpoint
558   if(pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDefaultDevice) == S_OK)
559   {
560     if(pDefaultDevice->GetId(&pwszID) == S_OK)
561     {
562       wstrDDID = pwszID;
563       CoTaskMemFree(pwszID);
564     }
565     SAFE_RELEASE(pDefaultDevice);
566   }
567
568   // enumerate over all audio endpoints
569   hr = pEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pEnumDevices);
570   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint enumeration failed.")
571
572   hr = pEnumDevices->GetCount(&uiCount);
573   EXIT_ON_FAILURE(hr, __FUNCTION__": Retrieval of audio endpoint count failed.")
574
575   for (UINT i = 0; i < uiCount; i++)
576   {
577     IMMDevice *pDevice = NULL;
578     IPropertyStore *pProperty = NULL;
579     PROPVARIANT varName;
580     PropVariantInit(&varName);
581
582     deviceInfo.m_channels.Reset();
583     deviceInfo.m_dataFormats.clear();
584     deviceInfo.m_sampleRates.clear();
585
586     hr = pEnumDevices->Item(i, &pDevice);
587     if (FAILED(hr))
588     {
589       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint failed.");
590       goto failed;
591     }
592
593     hr = pDevice->OpenPropertyStore(STGM_READ, &pProperty);
594     if (FAILED(hr))
595     {
596       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint properties failed.");
597       SAFE_RELEASE(pDevice);
598       goto failed;
599     }
600
601     hr = pProperty->GetValue(PKEY_Device_FriendlyName, &varName);
602     if (FAILED(hr))
603     {
604       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint device name failed.");
605       SAFE_RELEASE(pDevice);
606       SAFE_RELEASE(pProperty);
607       goto failed;
608     }
609
610     std::string strFriendlyName = localWideToUtf(varName.pwszVal);
611     PropVariantClear(&varName);
612
613     hr = pProperty->GetValue(PKEY_AudioEndpoint_GUID, &varName);
614     if(FAILED(hr))
615     {
616       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint GUID failed.");
617       SAFE_RELEASE(pDevice);
618       SAFE_RELEASE(pProperty);
619       goto failed;
620     }
621
622     std::string strDevName = localWideToUtf(varName.pwszVal);
623     PropVariantClear(&varName);
624
625     hr = pProperty->GetValue(PKEY_AudioEndpoint_FormFactor, &varName);
626     if (FAILED(hr))
627     {
628       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint form factor failed.");
629       SAFE_RELEASE(pDevice);
630       SAFE_RELEASE(pProperty);
631       goto failed;
632     }
633     std::string strWinDevType = winEndpoints[(EndpointFormFactor)varName.uiVal].winEndpointType;
634     AEDeviceType aeDeviceType = winEndpoints[(EndpointFormFactor)varName.uiVal].aeDeviceType;
635
636     PropVariantClear(&varName);
637
638     hr = pProperty->GetValue(PKEY_AudioEndpoint_PhysicalSpeakers, &varName);
639     if (FAILED(hr))
640     {
641       CLog::Log(LOGERROR, __FUNCTION__": Retrieval of WASAPI endpoint speaker layout failed.");
642       SAFE_RELEASE(pDevice);
643       SAFE_RELEASE(pProperty);
644       goto failed;
645     }
646     unsigned int uiChannelMask = std::max(varName.uintVal, (unsigned int) KSAUDIO_SPEAKER_STEREO);
647
648     deviceChannels.Reset();
649
650     for (unsigned int c = 0; c < WASAPI_SPEAKER_COUNT; c++)
651     {
652       if (uiChannelMask & WASAPIChannelOrder[c])
653         deviceChannels += AEChannelNames[c];
654     }
655
656     PropVariantClear(&varName);
657
658     IAudioClient *pClient;
659     hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pClient);
660     if (SUCCEEDED(hr))
661     {
662       /* Test format DTS-HD */
663       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
664       wfxex.Format.nSamplesPerSec       = 192000;
665       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_7POINT1_SURROUND;
666       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
667       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
668       wfxex.Format.wBitsPerSample       = 16;
669       wfxex.Samples.wValidBitsPerSample = 16;
670       wfxex.Format.nChannels            = 8;
671       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
672       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
673       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
674       if (SUCCEEDED(hr))
675         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTSHD));
676
677       /* Test format Dolby TrueHD */
678       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP;
679       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
680       if (SUCCEEDED(hr))
681         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_TRUEHD));
682
683       /* Test format Dolby EAC3 */
684       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS;
685       wfxex.Format.nChannels            = 2;
686       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
687       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
688       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
689       if (SUCCEEDED(hr))
690         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_EAC3));
691
692       /* Test format DTS */
693       wfxex.Format.nSamplesPerSec       = 48000;
694       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_5POINT1;
695       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DTS;
696       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
697       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
698       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
699       if (SUCCEEDED(hr))
700         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_DTS));
701
702       /* Test format Dolby AC3 */
703       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL;
704       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
705       if (SUCCEEDED(hr))
706         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AC3));
707
708       /* Test format AAC */
709       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_AAC;
710       hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
711       if (SUCCEEDED(hr))
712         deviceInfo.m_dataFormats.push_back(AEDataFormat(AE_FMT_AAC));
713
714       /* Test format for PCM format iteration */
715       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
716       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_STEREO;
717       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
718       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
719
720       for (int p = AE_FMT_FLOAT; p > AE_FMT_INVALID; p--)
721       {
722         if (p < AE_FMT_FLOAT)
723           wfxex.SubFormat               = KSDATAFORMAT_SUBTYPE_PCM;
724         wfxex.Format.wBitsPerSample     = CAEUtil::DataFormatToBits((AEDataFormat) p);
725         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
726         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
727         if (p <= AE_FMT_S24NE4 && p >= AE_FMT_S24BE4)
728         {
729           wfxex.Samples.wValidBitsPerSample = 24;
730         }
731         else
732         {
733           wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample;
734         }
735
736         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
737         if (SUCCEEDED(hr))
738           deviceInfo.m_dataFormats.push_back((AEDataFormat) p);
739       }
740
741       /* Test format for sample rate iteration */
742       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
743       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_STEREO;
744       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
745       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
746       wfxex.Format.wBitsPerSample       = 16;
747       wfxex.Samples.wValidBitsPerSample = 16;
748       wfxex.Format.nChannels            = 2;
749       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
750       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
751
752       for (int j = 0; j < WASAPISampleRateCount; j++)
753       {
754         wfxex.Format.nSamplesPerSec     = WASAPISampleRates[j];
755         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
756         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
757         if (SUCCEEDED(hr))
758           deviceInfo.m_sampleRates.push_back(WASAPISampleRates[j]);
759       }
760
761       /* Test format for channels iteration */
762       wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
763       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_STEREO;
764       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
765       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
766       wfxex.Format.nSamplesPerSec       = 48000;
767       wfxex.Format.wBitsPerSample       = 16;
768       wfxex.Samples.wValidBitsPerSample = 16;
769       wfxex.Format.nChannels            = 2;
770       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
771       wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
772
773       bool hasLpcm = false;
774
775       // Try with KSAUDIO_SPEAKER_DIRECTOUT
776       for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--)
777       {
778         wfxex.dwChannelMask             = KSAUDIO_SPEAKER_DIRECTOUT;
779         wfxex.Format.nChannels          = k;
780         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
781         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
782         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
783         if (SUCCEEDED(hr))
784         {
785           if (k > 3) // Add only multichannel LPCM
786           {
787             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
788             hasLpcm = true;
789           }
790           break;
791         }
792       }
793
794       /* Try with reported channel mask */
795       for (unsigned int k = WASAPI_SPEAKER_COUNT; k > 0; k--)
796       {
797         wfxex.dwChannelMask             = uiChannelMask;
798         wfxex.Format.nChannels          = k;
799         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
800         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
801         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
802         if (SUCCEEDED(hr))
803         {
804           if ( !hasLpcm && k > 3) // Add only multichannel LPCM
805           {
806             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
807             hasLpcm = true;
808           }
809           break;
810         }
811       }
812
813       /* Try with specific speakers configurations */
814       for (unsigned int i = 0; i < ARRAYSIZE(layoutsList); i++)
815       {
816         unsigned int nmbOfCh;
817         wfxex.dwChannelMask             = ChLayoutToChMask(layoutsList[i], &nmbOfCh);
818         wfxex.Format.nChannels          = nmbOfCh;
819         wfxex.Format.nBlockAlign        = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
820         wfxex.Format.nAvgBytesPerSec    = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
821         hr = pClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
822         if (SUCCEEDED(hr))
823         {
824           if ( deviceChannels.Count() < nmbOfCh)
825             deviceChannels = layoutsList[i];
826           if ( !hasLpcm && nmbOfCh > 3) // Add only multichannel LPCM
827           {
828             deviceInfo.m_dataFormats.push_back(AE_FMT_LPCM);
829             hasLpcm = true;
830           }
831         }
832       }
833       pClient->Release();
834     }
835     else
836     {
837       CLog::Log(LOGDEBUG, __FUNCTION__": Failed to activate device for passthrough capability testing.");
838     }
839
840     deviceInfo.m_deviceName       = strDevName;
841     deviceInfo.m_displayName      = strWinDevType.append(strFriendlyName);
842     deviceInfo.m_displayNameExtra = std::string("WASAPI: ").append(strFriendlyName);
843     deviceInfo.m_deviceType       = aeDeviceType;
844     deviceInfo.m_channels         = deviceChannels;
845
846     /* Store the device info */
847     deviceInfoList.push_back(deviceInfo);
848
849     if(pDevice->GetId(&pwszID) == S_OK)
850     {
851       if(wstrDDID.compare(pwszID) == 0)
852       {
853         deviceInfo.m_deviceName = std::string("default");
854         deviceInfo.m_displayName = std::string("default");
855         deviceInfo.m_displayNameExtra = std::string("");
856         deviceInfoList.push_back(deviceInfo);
857       }
858       CoTaskMemFree(pwszID);
859     }
860
861     SAFE_RELEASE(pDevice);
862     SAFE_RELEASE(pProperty);
863   }
864   return;
865
866 failed:
867
868   if (FAILED(hr))
869     CLog::Log(LOGERROR, __FUNCTION__": Failed to enumerate WASAPI endpoint devices (%s).", WASAPIErrToStr(hr));
870
871   SAFE_RELEASE(pEnumDevices);
872   SAFE_RELEASE(pEnumerator);
873 }
874
875 //Private utility functions////////////////////////////////////////////////////
876
877 void CAESinkWASAPI::BuildWaveFormatExtensible(AEAudioFormat &format, WAVEFORMATEXTENSIBLE &wfxex)
878 {
879   wfxex.Format.wFormatTag        = WAVE_FORMAT_EXTENSIBLE;
880   wfxex.Format.cbSize            = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
881
882
883   if (!AE_IS_RAW(format.m_dataFormat)) // PCM data
884   {
885     wfxex.dwChannelMask          = SpeakerMaskFromAEChannels(format.m_channelLayout);
886     wfxex.Format.nChannels       = (WORD)format.m_channelLayout.Count();
887     wfxex.Format.nSamplesPerSec  = format.m_sampleRate;
888     wfxex.Format.wBitsPerSample  = CAEUtil::DataFormatToBits((AEDataFormat) format.m_dataFormat);
889     wfxex.SubFormat              = format.m_dataFormat <= AE_FMT_FLOAT ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
890   }
891   else //Raw bitstream
892   {
893     wfxex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
894     if (format.m_dataFormat == AE_FMT_AC3 || format.m_dataFormat == AE_FMT_DTS)
895     {
896       wfxex.dwChannelMask               = bool (format.m_channelLayout.Count() == 2) ? KSAUDIO_SPEAKER_STEREO : KSAUDIO_SPEAKER_5POINT1;
897       wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL;
898       wfxex.Format.wBitsPerSample       = 16;
899       wfxex.Samples.wValidBitsPerSample = 16;
900       wfxex.Format.nChannels            = (WORD)format.m_channelLayout.Count();
901       wfxex.Format.nSamplesPerSec       = format.m_sampleRate;
902     }
903     else if (format.m_dataFormat == AE_FMT_EAC3 || format.m_dataFormat == AE_FMT_TRUEHD || format.m_dataFormat == AE_FMT_DTSHD)
904     {
905       /* IEC 61937 transmissions over HDMI */            
906       wfxex.Format.nSamplesPerSec       = 192000L;
907       wfxex.Format.wBitsPerSample       = 16;
908       wfxex.Samples.wValidBitsPerSample = 16;
909       wfxex.dwChannelMask               = KSAUDIO_SPEAKER_7POINT1_SURROUND;
910
911       switch (format.m_dataFormat)
912       {
913         case AE_FMT_EAC3:
914           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL_PLUS;
915           wfxex.Format.nChannels      = 2; // One IEC 60958 Line.
916           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_5POINT1;
917           break;
918         case AE_FMT_TRUEHD:
919           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_MLP;
920           wfxex.Format.nChannels      = 8; // Four IEC 60958 Lines.
921           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
922           break;
923         case AE_FMT_DTSHD:
924           wfxex.SubFormat             = KSDATAFORMAT_SUBTYPE_IEC61937_DTS_HD;
925           wfxex.Format.nChannels      = 8; // Four IEC 60958 Lines.
926           wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
927           break;
928       }
929
930       if (format.m_channelLayout.Count() == 8)
931         wfxex.dwChannelMask         = KSAUDIO_SPEAKER_7POINT1_SURROUND;
932       else
933         wfxex.dwChannelMask         = KSAUDIO_SPEAKER_5POINT1;
934     }
935   }
936
937   if (wfxex.Format.wBitsPerSample == 32 && wfxex.SubFormat != KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
938     wfxex.Samples.wValidBitsPerSample = 24;
939   else
940     wfxex.Samples.wValidBitsPerSample = wfxex.Format.wBitsPerSample;
941
942   wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
943   wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
944 }
945
946 void CAESinkWASAPI::BuildWaveFormatExtensibleIEC61397(AEAudioFormat &format, WAVEFORMATEXTENSIBLE_IEC61937 &wfxex)
947 {
948   /* Fill the common structure */
949   BuildWaveFormatExtensible(format, wfxex.FormatExt);
950
951   /* Code below kept for future use - preferred for later Windows versions */
952   /* but can cause problems on older Windows versions and drivers          */
953   /*
954   wfxex.FormatExt.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE_IEC61937)-sizeof(WAVEFORMATEX);
955   wfxex.dwEncodedChannelCount   = format.m_channelLayout.Count();
956   wfxex.dwEncodedSamplesPerSec  = bool(format.m_dataFormat == AE_FMT_TRUEHD ||
957                                        format.m_dataFormat == AE_FMT_DTSHD  ||
958                                        format.m_dataFormat == AE_FMT_EAC3) ? 96000L : 48000L;
959   wfxex.dwAverageBytesPerSec    = 0; //Ignored */
960 }
961
962 bool CAESinkWASAPI::InitializeExclusive(AEAudioFormat &format)
963 {
964   WAVEFORMATEXTENSIBLE_IEC61937 wfxex_iec61937;
965   WAVEFORMATEXTENSIBLE &wfxex = wfxex_iec61937.FormatExt;
966
967   if (format.m_dataFormat <= AE_FMT_FLOAT)
968     BuildWaveFormatExtensible(format, wfxex);
969   else
970     BuildWaveFormatExtensibleIEC61397(format, wfxex_iec61937);
971
972   /* Test for incomplete format and provide defaults */
973   if (format.m_sampleRate == 0 ||
974       format.m_channelLayout == NULL ||
975       format.m_dataFormat <= AE_FMT_INVALID ||
976       format.m_dataFormat >= AE_FMT_MAX ||
977       format.m_channelLayout.Count() == 0)
978   {
979     wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
980     wfxex.Format.nChannels            = 2;
981     wfxex.Format.nSamplesPerSec       = 44100L;
982     wfxex.Format.wBitsPerSample       = 16;
983     wfxex.Format.nBlockAlign          = 4;
984     wfxex.Samples.wValidBitsPerSample = 16;
985     wfxex.Format.cbSize               = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
986     wfxex.Format.nAvgBytesPerSec      = wfxex.Format.nBlockAlign * wfxex.Format.nSamplesPerSec;
987     wfxex.dwChannelMask               = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
988     wfxex.SubFormat                   = KSDATAFORMAT_SUBTYPE_PCM;
989   }
990
991   HRESULT hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
992
993   if (SUCCEEDED(hr))
994   {
995     CLog::Log(LOGINFO, __FUNCTION__": Format is Supported - will attempt to Initialize");
996     goto initialize;
997   }
998   else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT) //It failed for a reason unrelated to an unsupported format.
999   {
1000     CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
1001     return false;
1002   }
1003   else if (AE_IS_RAW(format.m_dataFormat)) //No sense in trying other formats for passthrough.
1004     return false;
1005
1006   CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s) - trying to find a compatible format", WASAPIErrToStr(hr));
1007
1008   int closestMatch;
1009   unsigned int requestedChannels = wfxex.Format.nChannels;
1010   unsigned int noOfCh;
1011
1012   /* The requested format is not supported by the device.  Find something that works */
1013   for (int layout = -1; layout <= (int)ARRAYSIZE(layoutsList); layout++)
1014   {
1015     // if requested layout is not suppported, try standard layouts with at least
1016     // the number of channels as requested
1017     // as the last resort try stereo
1018     if (layout == ARRAYSIZE(layoutsList))
1019     {
1020       wfxex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
1021       wfxex.Format.nChannels = 2;
1022     }
1023     else if (layout >= 0)
1024     {
1025       wfxex.dwChannelMask = ChLayoutToChMask(layoutsList[layout], &noOfCh);
1026       wfxex.Format.nChannels = noOfCh;
1027       if (noOfCh < requestedChannels)
1028         continue;
1029     }
1030
1031     for (int j = 0; j < sizeof(testFormats)/sizeof(sampleFormat); j++)
1032     {
1033       closestMatch = -1;
1034
1035       wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
1036       wfxex.SubFormat                   = testFormats[j].subFormat;
1037       wfxex.Format.wBitsPerSample       = testFormats[j].bitsPerSample;
1038       wfxex.Samples.wValidBitsPerSample = testFormats[j].validBitsPerSample;
1039       wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
1040
1041       for (int i = 0 ; i < WASAPISampleRateCount; i++)
1042       {
1043         wfxex.Format.nSamplesPerSec    = WASAPISampleRates[i];
1044         wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
1045
1046         /* Trace format match iteration loop via log */
1047 #if 0
1048         CLog::Log(LOGDEBUG, "WASAPI: Trying Format: %s, %d, %d, %d", CAEUtil::DataFormatToStr(testFormats[j].subFormatType),
1049           wfxex.Format.nSamplesPerSec,
1050           wfxex.Format.wBitsPerSample,
1051           wfxex.Samples.wValidBitsPerSample);
1052 #endif
1053
1054         hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
1055
1056         if (SUCCEEDED(hr))
1057         {
1058           /* If the current sample rate matches the source then stop looking and use it */
1059           if ((WASAPISampleRates[i] == format.m_sampleRate) && (testFormats[j].subFormatType <= format.m_dataFormat))
1060             goto initialize;
1061           /* If this rate is closer to the source then the previous one, save it */
1062           else if (closestMatch < 0 || abs((int)WASAPISampleRates[i] - (int)format.m_sampleRate) < abs((int)WASAPISampleRates[closestMatch] - (int)format.m_sampleRate))
1063             closestMatch = i;
1064         }
1065         else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
1066           CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
1067       }
1068
1069       if (closestMatch >= 0)
1070       {
1071         wfxex.Format.nSamplesPerSec    = WASAPISampleRates[closestMatch];
1072         wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
1073         goto initialize;
1074       }
1075     }
1076   }
1077
1078   CLog::Log(LOGERROR, __FUNCTION__": Unable to locate a supported output format for the device.  Check the speaker settings in the control panel.");
1079
1080   /* We couldn't find anything supported. This should never happen      */
1081   /* unless the user set the wrong speaker setting in the control panel */
1082   return false;
1083
1084 initialize:
1085
1086   AEChannelsFromSpeakerMask(wfxex.dwChannelMask);
1087   format.m_channelLayout = m_channelLayout;
1088
1089   /* When the stream is raw, the values in the format structure are set to the link    */
1090   /* parameters, so store the encoded stream values here for the IsCompatible function */
1091   m_encodedFormat     = format.m_dataFormat;
1092   m_encodedChannels   = wfxex.Format.nChannels;
1093   m_encodedSampleRate = format.m_encodedRate;
1094   wfxex_iec61937.dwEncodedChannelCount = wfxex.Format.nChannels;
1095   wfxex_iec61937.dwEncodedSamplesPerSec = m_encodedSampleRate;
1096
1097   /* Set up returned sink format for engine */
1098   if (!AE_IS_RAW(format.m_dataFormat))
1099   {
1100     if (wfxex.Format.wBitsPerSample == 32)
1101     {
1102       if (wfxex.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
1103         format.m_dataFormat = AE_FMT_FLOAT;
1104       else if (wfxex.Samples.wValidBitsPerSample == 32)
1105         format.m_dataFormat = AE_FMT_S32NE;
1106       else
1107         format.m_dataFormat = AE_FMT_S24NE4;
1108     }
1109     else if (wfxex.Format.wBitsPerSample == 24)
1110       format.m_dataFormat = AE_FMT_S24NE3;
1111     else
1112       format.m_dataFormat = AE_FMT_S16NE;
1113   }
1114
1115   format.m_sampleRate    = wfxex.Format.nSamplesPerSec; //PCM: Sample rate.  RAW: Link speed
1116   format.m_frameSize     = (wfxex.Format.wBitsPerSample >> 3) * wfxex.Format.nChannels;
1117
1118   REFERENCE_TIME audioSinkBufferDurationMsec, hnsLatency;
1119
1120   audioSinkBufferDurationMsec = (REFERENCE_TIME)500000;
1121   audioSinkBufferDurationMsec = (REFERENCE_TIME)((audioSinkBufferDurationMsec / format.m_frameSize) * format.m_frameSize); //even number of frames
1122
1123   if (AE_IS_RAW(format.m_dataFormat))
1124     format.m_dataFormat = AE_FMT_S16NE;
1125
1126   hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
1127                                     audioSinkBufferDurationMsec, audioSinkBufferDurationMsec, &wfxex.Format, NULL);
1128
1129   if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED)
1130   {
1131     /* WASAPI requires aligned buffer */
1132     /* Get the next aligned frame     */
1133     hr = m_pAudioClient->GetBufferSize(&m_uiBufferLen);
1134     if (FAILED(hr))
1135     {
1136       CLog::Log(LOGERROR, __FUNCTION__": GetBufferSize Failed : %s", WASAPIErrToStr(hr));
1137       return false;
1138     }
1139
1140     audioSinkBufferDurationMsec = (REFERENCE_TIME) ((10000.0 * 1000 / wfxex.Format.nSamplesPerSec * m_uiBufferLen) + 0.5);
1141
1142     /* Release the previous allocations */
1143     SAFE_RELEASE(m_pAudioClient);
1144
1145     /* Create a new audio client */
1146     hr = m_pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&m_pAudioClient);
1147     if (FAILED(hr))
1148     {
1149       CLog::Log(LOGERROR, __FUNCTION__": Device Activation Failed : %s", WASAPIErrToStr(hr));
1150       return false;
1151     }
1152
1153     /* Open the stream and associate it with an audio session */
1154     hr = m_pAudioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
1155                                       audioSinkBufferDurationMsec, audioSinkBufferDurationMsec, &wfxex.Format, NULL);
1156   }
1157   if (FAILED(hr))
1158   {
1159     CLog::Log(LOGERROR, __FUNCTION__": Failed to initialize WASAPI in exclusive mode %d - (%s).", HRESULT(hr), WASAPIErrToStr(hr));
1160     CLog::Log(LOGDEBUG, "  Sample Rate     : %d", wfxex.Format.nSamplesPerSec);
1161     CLog::Log(LOGDEBUG, "  Sample Format   : %s", CAEUtil::DataFormatToStr(format.m_dataFormat));
1162     CLog::Log(LOGDEBUG, "  Bits Per Sample : %d", wfxex.Format.wBitsPerSample);
1163     CLog::Log(LOGDEBUG, "  Valid Bits/Samp : %d", wfxex.Samples.wValidBitsPerSample);
1164     CLog::Log(LOGDEBUG, "  Channel Count   : %d", wfxex.Format.nChannels);
1165     CLog::Log(LOGDEBUG, "  Block Align     : %d", wfxex.Format.nBlockAlign);
1166     CLog::Log(LOGDEBUG, "  Avg. Bytes Sec  : %d", wfxex.Format.nAvgBytesPerSec);
1167     CLog::Log(LOGDEBUG, "  Samples/Block   : %d", wfxex.Samples.wSamplesPerBlock);
1168     CLog::Log(LOGDEBUG, "  Format cBSize   : %d", wfxex.Format.cbSize);
1169     CLog::Log(LOGDEBUG, "  Channel Layout  : %s", ((std::string)format.m_channelLayout).c_str());
1170     CLog::Log(LOGDEBUG, "  Enc. Channels   : %d", wfxex_iec61937.dwEncodedChannelCount);
1171     CLog::Log(LOGDEBUG, "  Enc. Samples/Sec: %d", wfxex_iec61937.dwEncodedSamplesPerSec);
1172     CLog::Log(LOGDEBUG, "  Channel Mask    : %d", wfxex.dwChannelMask);
1173     CLog::Log(LOGDEBUG, "  Periodicty      : %d", audioSinkBufferDurationMsec);
1174     return false;
1175   }
1176
1177   /* Latency of WASAPI buffers in event-driven mode is equal to the returned value  */
1178   /* of GetStreamLatency converted from 100ns intervals to seconds then multiplied  */
1179   /* by two as there are two equally-sized buffers and playback starts when the     */
1180   /* second buffer is filled. Multiplying the returned 100ns intervals by 0.0000002 */
1181   /* is handles both the unit conversion and twin buffers.                          */
1182   hr = m_pAudioClient->GetStreamLatency(&hnsLatency);
1183   if (FAILED(hr))
1184   {
1185     CLog::Log(LOGERROR, __FUNCTION__": GetStreamLatency Failed : %s", WASAPIErrToStr(hr));
1186     return false;
1187   }
1188
1189   m_sinkLatency = hnsLatency * 0.0000002;
1190
1191   CLog::Log(LOGINFO, __FUNCTION__": WASAPI Exclusive Mode Sink Initialized using: %s, %d, %d",
1192                                      CAEUtil::DataFormatToStr(format.m_dataFormat),
1193                                      wfxex.Format.nSamplesPerSec,
1194                                      wfxex.Format.nChannels);
1195   return true;
1196 }
1197
1198 void CAESinkWASAPI::AEChannelsFromSpeakerMask(DWORD speakers)
1199 {
1200   m_channelLayout.Reset();
1201
1202   for (int i = 0; i < WASAPI_SPEAKER_COUNT; i++)
1203   {
1204     if (speakers & WASAPIChannelOrder[i])
1205       m_channelLayout += AEChannelNames[i];
1206   }
1207 }
1208
1209 DWORD CAESinkWASAPI::SpeakerMaskFromAEChannels(const CAEChannelInfo &channels)
1210 {
1211   DWORD mask = 0;
1212
1213   for (unsigned int i = 0; i < channels.Count(); i++)
1214   {
1215     for (unsigned int j = 0; j < WASAPI_SPEAKER_COUNT; j++)
1216       if (channels[i] == AEChannelNames[j])
1217         mask |= WASAPIChannelOrder[j];
1218   }
1219   return mask;
1220 }
1221
1222 const char *CAESinkWASAPI::WASAPIErrToStr(HRESULT err)
1223 {
1224   switch(err)
1225   {
1226     ERRTOSTR(AUDCLNT_E_NOT_INITIALIZED);
1227     ERRTOSTR(AUDCLNT_E_ALREADY_INITIALIZED);
1228     ERRTOSTR(AUDCLNT_E_WRONG_ENDPOINT_TYPE);
1229     ERRTOSTR(AUDCLNT_E_DEVICE_INVALIDATED);
1230     ERRTOSTR(AUDCLNT_E_NOT_STOPPED);
1231     ERRTOSTR(AUDCLNT_E_BUFFER_TOO_LARGE);
1232     ERRTOSTR(AUDCLNT_E_OUT_OF_ORDER);
1233     ERRTOSTR(AUDCLNT_E_UNSUPPORTED_FORMAT);
1234     ERRTOSTR(AUDCLNT_E_INVALID_SIZE);
1235     ERRTOSTR(AUDCLNT_E_DEVICE_IN_USE);
1236     ERRTOSTR(AUDCLNT_E_BUFFER_OPERATION_PENDING);
1237     ERRTOSTR(AUDCLNT_E_THREAD_NOT_REGISTERED);
1238     ERRTOSTR(AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED);
1239     ERRTOSTR(AUDCLNT_E_ENDPOINT_CREATE_FAILED);
1240     ERRTOSTR(AUDCLNT_E_SERVICE_NOT_RUNNING);
1241     ERRTOSTR(AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED);
1242     ERRTOSTR(AUDCLNT_E_EXCLUSIVE_MODE_ONLY);
1243     ERRTOSTR(AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL);
1244     ERRTOSTR(AUDCLNT_E_EVENTHANDLE_NOT_SET);
1245     ERRTOSTR(AUDCLNT_E_INCORRECT_BUFFER_SIZE);
1246     ERRTOSTR(AUDCLNT_E_BUFFER_SIZE_ERROR);
1247     ERRTOSTR(AUDCLNT_E_CPUUSAGE_EXCEEDED);
1248     ERRTOSTR(AUDCLNT_E_BUFFER_ERROR);
1249     ERRTOSTR(AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED);
1250     ERRTOSTR(AUDCLNT_E_INVALID_DEVICE_PERIOD);
1251     ERRTOSTR(E_POINTER);
1252     ERRTOSTR(E_INVALIDARG);
1253     ERRTOSTR(E_OUTOFMEMORY);
1254     default: break;
1255   }
1256   return NULL;
1257 }
1258
1259 void CAESinkWASAPI::Drain()
1260 {
1261   if(!m_pAudioClient)
1262     return;
1263
1264   Sleep( (DWORD)(GetDelay()*500) );
1265
1266   if (m_running)
1267   {
1268     try
1269     {
1270       m_pAudioClient->Stop();  //stop the audio output
1271       m_pAudioClient->Reset(); //flush buffer and reset audio clock stream position
1272     }
1273     catch (...)
1274     {
1275       CLog::Log(LOGDEBUG, __FUNCTION__, "Invalidated AudioClient - Releasing");
1276     }
1277   }
1278   m_running = false;
1279 }