aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthexai <58434170+thexai@users.noreply.github.com>2024-07-23 08:43:40 +0200
committerGitHub <noreply@github.com>2024-07-23 08:43:40 +0200
commitfd79f9bfa2d41822d976636923cb0fa7b3135ab0 (patch)
treee557da07f69f0c852e7ca5350411d7c6dd5faaae
parent3e8215d6414df5e5d3b375e717bb830ec8edf658 (diff)
parent295473458b343f8366aa4d2c6da094af82e221c9 (diff)
Merge pull request #25511 from thexai/fix-DirectSound-BT-Omega
[Backport][DirectSound] Fix buffer underrun for Bluetooth audio devices
-rw-r--r--xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp23
-rw-r--r--xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin.h1
-rw-r--r--xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin32.cpp11
3 files changed, 33 insertions, 2 deletions
diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp
index 4b450ec5cb..4321679687 100644
--- a/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp
@@ -124,6 +124,7 @@ bool CAESinkDirectSound::Initialize(AEAudioFormat &format, std::string &device)
if (m_initialized)
return false;
+ bool deviceIsBluetooth = false;
LPGUID deviceGUID = nullptr;
RPC_WSTR wszUuid = nullptr;
HRESULT hr = E_FAIL;
@@ -152,6 +153,21 @@ bool CAESinkDirectSound::Initialize(AEAudioFormat &format, std::string &device)
if (hr == RPC_S_OK) RpcStringFree(&wszUuid);
}
+ // Detect a Bluetooth device
+ for (const auto& device : CAESinkFactoryWin::GetRendererDetails())
+ {
+ if (StringUtils::CompareNoCase(device.strDeviceId, strDeviceGUID) != 0)
+ continue;
+
+ if (device.strDeviceEnumerator == "BTHENUM")
+ {
+ deviceIsBluetooth = true;
+ CLog::LogF(LOGDEBUG, "Audio device '{}' is detected as Bluetooth device", deviceFriendlyName);
+ }
+
+ break;
+ }
+
hr = DirectSoundCreate(deviceGUID, m_pDSound.ReleaseAndGetAddressOf(), nullptr);
if (FAILED(hr))
@@ -218,10 +234,13 @@ bool CAESinkDirectSound::Initialize(AEAudioFormat &format, std::string &device)
m_AvgBytesPerSec = wfxex.Format.nAvgBytesPerSec;
- unsigned int uiFrameCount = (int)(format.m_sampleRate * 0.015); //default to 15ms chunks
+ const unsigned int chunkDurationMs = deviceIsBluetooth ? 50 : 20;
+ const unsigned int uiFrameCount = format.m_sampleRate * chunkDurationMs / 1000U;
m_dwFrameSize = wfxex.Format.nBlockAlign;
m_dwChunkSize = m_dwFrameSize * uiFrameCount;
- m_dwBufferLen = m_dwChunkSize * 12; //180ms total buffer
+
+ // BT: 500ms total buffer (50 * 10); non-BT: 200ms total buffer (20 * 10)
+ m_dwBufferLen = m_dwChunkSize * 10;
// fill in the secondary sound buffer descriptor
DSBUFFERDESC dsbdesc = {};
diff --git a/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin.h b/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin.h
index dbe53f3203..61db03f5c4 100644
--- a/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin.h
+++ b/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin.h
@@ -178,6 +178,7 @@ struct RendererDetail
std::string strDeviceId;
std::string strDescription;
std::string strWinDevType;
+ std::string strDeviceEnumerator;
AEDeviceType eDeviceType;
unsigned int nChannels;
unsigned int uiChannelMask;
diff --git a/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin32.cpp b/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin32.cpp
index c728155c56..3b6abaae90 100644
--- a/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin32.cpp
+++ b/xbmc/cores/AudioEngine/Sinks/windows/AESinkFactoryWin32.cpp
@@ -129,6 +129,17 @@ std::vector<RendererDetail> CAESinkFactoryWin::GetRendererDetails()
details.uiChannelMask = std::max(varName.uintVal, (unsigned int)KSAUDIO_SPEAKER_STEREO);
PropVariantClear(&varName);
+ hr = pProperty->GetValue(PKEY_Device_EnumeratorName, &varName);
+ if (FAILED(hr))
+ {
+ CLog::LogF(LOGERROR, "Retrieval of endpoint enumerator name failed.");
+ goto failed;
+ }
+
+ details.strDeviceEnumerator = KODI::PLATFORM::WINDOWS::FromW(varName.pwszVal);
+ StringUtils::ToUpper(details.strDeviceEnumerator);
+ PropVariantClear(&varName);
+
if (pDevice->GetId(&pwszID) == S_OK)
{
if (wstrDDID.compare(pwszID) == 0)