WASAPI: try other channels layouts on init if requested one is not supported
authorRainer Hochecker <fernetmenta@online.de>
Fri, 6 Dec 2013 08:36:58 +0000 (09:36 +0100)
committerRainer Hochecker <fernetmenta@online.de>
Sun, 8 Dec 2013 09:01:43 +0000 (10:01 +0100)
xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp

index 2e774b4..007983c 100644 (file)
@@ -1060,51 +1060,72 @@ bool CAESinkWASAPI::InitializeExclusive(AEAudioFormat &format)
   CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s) - trying to find a compatible format", WASAPIErrToStr(hr));
 
   int closestMatch;
+  unsigned int requestedChannels = wfxex.Format.nChannels;
+  unsigned int noOfCh;
 
   /* The requested format is not supported by the device.  Find something that works */
-  for (int j = 0; j < sizeof(testFormats)/sizeof(sampleFormat); j++)
+  for (int layout = -1; layout <= (int)ARRAYSIZE(layoutsList); layout++)
   {
-    closestMatch = -1;
-
-    wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
-    wfxex.SubFormat                   = testFormats[j].subFormat;
-    wfxex.Format.wBitsPerSample       = testFormats[j].bitsPerSample;
-    wfxex.Samples.wValidBitsPerSample = testFormats[j].validBitsPerSample;
-    wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
+    // if requested layout is not suppported, try standard layouts with at least
+    // the number of channels as requested
+    // as the last resort try stereo
+    if (layout == ARRAYSIZE(layoutsList))
+    {
+      wfxex.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
+      wfxex.Format.nChannels = 2;
+    }
+    else if (layout >= 0)
+    {
+      wfxex.dwChannelMask = ChLayoutToChMask(layoutsList[layout], &noOfCh);
+      wfxex.Format.nChannels = noOfCh;
+      if (noOfCh < requestedChannels)
+        continue;
+    }
 
-    for (int i = 0 ; i < WASAPISampleRateCount; i++)
+    for (int j = 0; j < sizeof(testFormats)/sizeof(sampleFormat); j++)
     {
-      wfxex.Format.nSamplesPerSec    = WASAPISampleRates[i];
-      wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
-
-      /* Trace format match iteration loop via log */
-      #if 0
-      CLog::Log(LOGDEBUG, "WASAPI: Trying Format: %s, %d, %d, %d", CAEUtil::DataFormatToStr(testFormats[j].subFormatType),
-                                                                   wfxex.Format.nSamplesPerSec,
-                                                                   wfxex.Format.wBitsPerSample,
-                                                                   wfxex.Samples.wValidBitsPerSample);
-      #endif
+      closestMatch = -1;
 
-      hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
+      wfxex.Format.wFormatTag           = WAVE_FORMAT_EXTENSIBLE;
+      wfxex.SubFormat                   = testFormats[j].subFormat;
+      wfxex.Format.wBitsPerSample       = testFormats[j].bitsPerSample;
+      wfxex.Samples.wValidBitsPerSample = testFormats[j].validBitsPerSample;
+      wfxex.Format.nBlockAlign          = wfxex.Format.nChannels * (wfxex.Format.wBitsPerSample >> 3);
 
-      if (SUCCEEDED(hr))
+      for (int i = 0 ; i < WASAPISampleRateCount; i++)
       {
-        /* If the current sample rate matches the source then stop looking and use it */
-        if ((WASAPISampleRates[i] == format.m_sampleRate) && (testFormats[j].subFormatType <= format.m_dataFormat))
-          goto initialize;
-        /* If this rate is closer to the source then the previous one, save it */
-        else if (closestMatch < 0 || abs((int)WASAPISampleRates[i] - (int)format.m_sampleRate) < abs((int)WASAPISampleRates[closestMatch] - (int)format.m_sampleRate))
-          closestMatch = i;
-      }
-      else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
+        wfxex.Format.nSamplesPerSec    = WASAPISampleRates[i];
+        wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
+
+        /* Trace format match iteration loop via log */
+#if 0
+        CLog::Log(LOGDEBUG, "WASAPI: Trying Format: %s, %d, %d, %d", CAEUtil::DataFormatToStr(testFormats[j].subFormatType),
+          wfxex.Format.nSamplesPerSec,
+          wfxex.Format.wBitsPerSample,
+          wfxex.Samples.wValidBitsPerSample);
+#endif
+
+        hr = m_pAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &wfxex.Format, NULL);
+
+        if (SUCCEEDED(hr))
+        {
+          /* If the current sample rate matches the source then stop looking and use it */
+          if ((WASAPISampleRates[i] == format.m_sampleRate) && (testFormats[j].subFormatType <= format.m_dataFormat))
+            goto initialize;
+          /* If this rate is closer to the source then the previous one, save it */
+          else if (closestMatch < 0 || abs((int)WASAPISampleRates[i] - (int)format.m_sampleRate) < abs((int)WASAPISampleRates[closestMatch] - (int)format.m_sampleRate))
+            closestMatch = i;
+        }
+        else if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
           CLog::Log(LOGERROR, __FUNCTION__": IsFormatSupported failed (%s)", WASAPIErrToStr(hr));
-    }
+      }
 
-    if (closestMatch >= 0)
-    {
-      wfxex.Format.nSamplesPerSec    = WASAPISampleRates[closestMatch];
-      wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
-      goto initialize;
+      if (closestMatch >= 0)
+      {
+        wfxex.Format.nSamplesPerSec    = WASAPISampleRates[closestMatch];
+        wfxex.Format.nAvgBytesPerSec   = wfxex.Format.nSamplesPerSec * wfxex.Format.nBlockAlign;
+        goto initialize;
+      }
     }
   }