Skip to content

Commit c7b54de

Browse files
committed
Refactor render and capture buffer notification flows to avoid more deadlocks
1 parent 3e81a10 commit c7b54de

6 files changed

+65
-21
lines changed

RS_ASIO/RSAsioAudioCaptureClient.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,23 @@ HRESULT STDMETHODCALLTYPE RSAsioAudioCaptureClient::GetBuffer(BYTE **ppData, UIN
2424
// put the newest input data on the backbuffer
2525
m_AsioAudioClient.SwapBuffers();
2626

27-
std::vector<BYTE>& buffer = m_AsioAudioClient.GetBackBuffer();
27+
bool isDiscontinuity = true;
28+
UINT64 backbufferTimestamp = 0;
29+
BYTE* backbuffer = GetBackbufferIfPending(true, &backbufferTimestamp, &isDiscontinuity);
2830

29-
*ppData = buffer.data();
30-
*pNumFramesToRead = m_NewBufferWaiting ? m_AsioAudioClient.GetBufferNumFrames() : 0;
31+
*ppData = backbuffer;
32+
*pNumFramesToRead = backbuffer ? m_AsioAudioClient.GetBufferNumFrames() : 0;
3133

3234
DWORD dwOutFlags = 0;
33-
if (m_NewBufferPerfCounter == 0)
35+
if (backbufferTimestamp == 0)
3436
{
3537
dwOutFlags |= AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR;
3638
}
37-
if (!m_NewBufferWaiting)
39+
if (!backbuffer)
3840
{
3941
dwOutFlags |= AUDCLNT_BUFFERFLAGS_SILENT;
4042
}
41-
if (m_DataDiscontinuityFlag)
43+
if (isDiscontinuity)
4244
{
4345
dwOutFlags |= AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY;
4446
}
@@ -52,11 +54,10 @@ HRESULT STDMETHODCALLTYPE RSAsioAudioCaptureClient::GetBuffer(BYTE **ppData, UIN
5254

5355
if (pu64QPCPosition)
5456
{
55-
*pu64QPCPosition = m_NewBufferPerfCounter;
57+
*pu64QPCPosition = backbufferTimestamp;
5658
}
5759

5860
m_WaitingForBufferRelease = true;
59-
m_NewBufferWaiting = false;
6061

6162
return S_OK;
6263
}
@@ -69,7 +70,6 @@ HRESULT STDMETHODCALLTYPE RSAsioAudioCaptureClient::ReleaseBuffer(UINT32 NumFram
6970
return AUDCLNT_E_OUT_OF_ORDER;
7071

7172
m_WaitingForBufferRelease = false;
72-
m_DataDiscontinuityFlag = false;
7373

7474
return S_OK;
7575
}

RS_ASIO/RSAsioAudioCaptureClient.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ class RSAsioAudioCaptureClient : public RSAsioAudioClientServiceBase<IAudioCaptu
1515

1616
private:
1717
bool m_WaitingForBufferRelease = false;
18+
19+
std::mutex m_mutex;
1820
};

RS_ASIO/RSAsioAudioClientServiceBase.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RSAsioAudioClientServiceBase<TBaseClientService>::~RSAsioAudioClientServiceBase(
2020
template<typename TBaseClientService>
2121
void RSAsioAudioClientServiceBase<TBaseClientService>::NotifyNewBuffer()
2222
{
23-
std::lock_guard<std::mutex> g(m_mutex);
23+
std::lock_guard<std::mutex> g(m_bufferMutex);
2424

2525
LARGE_INTEGER li;
2626

@@ -66,11 +66,46 @@ void RSAsioAudioClientServiceBase<TBaseClientService>::NotifyNewBuffer()
6666
template<typename TBaseClientService>
6767
bool RSAsioAudioClientServiceBase<TBaseClientService>::HasNewBufferWaiting() const
6868
{
69-
std::lock_guard<std::mutex> g(m_mutex);
69+
std::lock_guard<std::mutex> g(m_bufferMutex);
7070

7171
return m_NewBufferWaiting;
7272
}
7373

74+
template<typename TBaseClientService>
75+
BYTE* RSAsioAudioClientServiceBase<TBaseClientService>::GetBackbufferIfPending(bool resetPendingFlag, UINT64* outOptionalPerfCounter, bool* outOptionalIsDiscontinuity)
76+
{
77+
std::lock_guard<std::mutex> g(m_bufferMutex);
78+
if (!m_NewBufferWaiting)
79+
{
80+
if (outOptionalPerfCounter)
81+
{
82+
*outOptionalPerfCounter = 0;
83+
}
84+
if (outOptionalIsDiscontinuity)
85+
{
86+
*outOptionalIsDiscontinuity = true;
87+
}
88+
89+
return nullptr;
90+
}
91+
92+
std::vector<BYTE>& buffer = m_AsioAudioClient.GetBackBuffer();
93+
if (outOptionalPerfCounter)
94+
{
95+
*outOptionalPerfCounter = m_NewBufferPerfCounter;
96+
}
97+
if (outOptionalIsDiscontinuity)
98+
{
99+
*outOptionalIsDiscontinuity = m_DataDiscontinuityFlag;
100+
}
101+
if (resetPendingFlag)
102+
{
103+
m_NewBufferWaiting = false;
104+
m_DataDiscontinuityFlag = false;
105+
}
106+
return buffer.data();
107+
}
108+
74109

75110

76111
template class RSAsioAudioClientServiceBase<IAudioCaptureClient>;

RS_ASIO/RSAsioAudioClientServiceBase.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ class RSAsioAudioClientServiceBase : public ComBaseUnknown<TBaseClientService>
1818

1919
protected:
2020
RSAsioAudioClient& m_AsioAudioClient;
21+
22+
BYTE* GetBackbufferIfPending(bool resetPendingFlag, UINT64* outOptionalPerfCounter, bool* outOptionalIsDiscontinuity);
23+
24+
private:
25+
mutable std::mutex m_bufferMutex;
26+
2127
bool m_NewBufferWaiting; // set in ctor
2228
UINT64 m_NewBufferPerfCounter = 0;
2329

2430
bool m_DataDiscontinuityFlag = false;
2531

2632
unsigned m_NumSequentialDiscontinuities = 0;
2733
unsigned m_IgnoreDiscontinuityLoggingCountdown = 0;
28-
29-
mutable std::mutex m_mutex;
3034
};

RS_ASIO/RSAsioAudioRenderClient.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,21 @@ HRESULT STDMETHODCALLTYPE RSAsioAudioRenderClient::GetBuffer(UINT32 NumFramesReq
2121
if (m_WaitingForBufferRelease)
2222
return AUDCLNT_E_OUT_OF_ORDER;
2323

24-
if (!m_NewBufferWaiting)
24+
if (NumFramesRequested != m_AsioAudioClient.GetBufferNumFrames())
25+
return AUDCLNT_E_BUFFER_SIZE_ERROR;
26+
27+
bool isDiscontinuity = true;
28+
UINT64 backbufferTimestamp = 0;
29+
BYTE* backbuffer = GetBackbufferIfPending(true, &backbufferTimestamp, &isDiscontinuity);
30+
31+
if (!backbuffer)
2532
{
2633
*ppData = nullptr;
2734
return AUDCLNT_E_BUFFER_ERROR;
2835
}
2936

30-
std::vector<BYTE>& buffer = m_AsioAudioClient.GetBackBuffer();
31-
if (NumFramesRequested != m_AsioAudioClient.GetBufferNumFrames())
32-
return AUDCLNT_E_BUFFER_SIZE_ERROR;
33-
34-
*ppData = buffer.data();
37+
*ppData = backbuffer;
3538
m_WaitingForBufferRelease = true;
36-
m_NewBufferWaiting = false;
3739

3840
return S_OK;
3941
}
@@ -56,7 +58,6 @@ HRESULT STDMETHODCALLTYPE RSAsioAudioRenderClient::ReleaseBuffer(UINT32 NumFrame
5658
return AUDCLNT_E_BUFFER_SIZE_ERROR;
5759

5860
m_WaitingForBufferRelease = false;
59-
m_DataDiscontinuityFlag = false;
6061

6162
// move the data we've put in the backbuffer to the frontbuffer for output
6263
m_AsioAudioClient.SwapBuffers();

RS_ASIO/RSAsioAudioRenderClient.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ class RSAsioAudioRenderClient : public RSAsioAudioClientServiceBase<IAudioRender
1414

1515
private:
1616
bool m_WaitingForBufferRelease = false;
17+
18+
std::mutex m_mutex;
1719
};

0 commit comments

Comments
 (0)