diff options
author | thexai <58434170+thexai@users.noreply.github.com> | 2024-07-20 12:10:14 +0200 |
---|---|---|
committer | thexai <58434170+thexai@users.noreply.github.com> | 2024-07-21 11:28:30 +0200 |
commit | 295473458b343f8366aa4d2c6da094af82e221c9 (patch) | |
tree | ced6654428fb33a9887bdca575aa57b483dcb156 | |
parent | 3178ecd804556f22e6a24387eef61afc06480cd3 (diff) |
[DirectSound] Fix buffer underrun for Bluetooth audio devices
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) |