Improved synchronization for AAudio rerouting. This should fix the crash observed in ma_device_init__aaudio (when re-routing).

This commit is contained in:
znakeeye
2025-02-20 02:17:13 +01:00
committed by David Reid
parent a497466f75
commit 9f9fc2333e
+54 -27
View File
@@ -7985,7 +7985,7 @@ struct ma_device
{ {
/*AAudioStream**/ ma_ptr pStreamPlayback; /*AAudioStream**/ ma_ptr pStreamPlayback;
/*AAudioStream**/ ma_ptr pStreamCapture; /*AAudioStream**/ ma_ptr pStreamCapture;
ma_mutex closeLock; ma_mutex rerouteLock;
ma_aaudio_usage usage; ma_aaudio_usage usage;
ma_aaudio_content_type contentType; ma_aaudio_content_type contentType;
ma_aaudio_input_preset inputPreset; ma_aaudio_input_preset inputPreset;
@@ -38162,19 +38162,15 @@ static ma_result ma_close_streams__aaudio(ma_device* pDevice)
{ {
MA_ASSERT(pDevice != NULL); MA_ASSERT(pDevice != NULL);
ma_mutex_lock(&pDevice->aaudio.closeLock); /* When re-routing, streams may have been closed and never re-opened. Hence the extra checks below. */
{ if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
/* When re-routing, streams may have been closed and never re-opened. Hence the extra checks below. */ ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) { pDevice->aaudio.pStreamCapture = NULL;
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture); }
pDevice->aaudio.pStreamCapture = NULL; if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
} ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { pDevice->aaudio.pStreamPlayback = NULL;
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
pDevice->aaudio.pStreamPlayback = NULL;
}
} }
ma_mutex_unlock(&pDevice->aaudio.closeLock);
return MA_SUCCESS; return MA_SUCCESS;
} }
@@ -38183,8 +38179,15 @@ static ma_result ma_device_uninit__aaudio(ma_device* pDevice)
{ {
MA_ASSERT(pDevice != NULL); MA_ASSERT(pDevice != NULL);
ma_close_streams__aaudio(pDevice); /* Wait for any rerouting to finish before attempting to close the streams. */
ma_mutex_uninit(&pDevice->aaudio.closeLock); ma_mutex_lock(&pDevice->aaudio.rerouteLock);
{
ma_close_streams__aaudio(pDevice);
}
ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
/* Destroy re-routing lock. */
ma_mutex_uninit(&pDevice->aaudio.rerouteLock);
return MA_SUCCESS; return MA_SUCCESS;
} }
@@ -38236,7 +38239,7 @@ static ma_result ma_device_init_by_type__aaudio(ma_device* pDevice, const ma_dev
return MA_SUCCESS; return MA_SUCCESS;
} }
static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture) static ma_result ma_device_init_streams__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
{ {
ma_result result; ma_result result;
@@ -38266,7 +38269,21 @@ static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_conf
} }
} }
result = ma_mutex_init(&pDevice->aaudio.closeLock); return MA_SUCCESS;
}
static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
{
ma_result result;
MA_ASSERT(pDevice != NULL);
result = ma_device_init_streams__aaudio(pDevice, pConfig, pDescriptorPlayback, pDescriptorCapture);
if (result != MA_SUCCESS) {
return result;
}
result = ma_mutex_init(&pDevice->aaudio.rerouteLock);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
@@ -38410,12 +38427,16 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev
MA_ASSERT(pDevice != NULL); MA_ASSERT(pDevice != NULL);
error_disconnected: /*
/* The first thing to do is close the streams. */ TODO: Stop retrying if main thread is about to uninit device.
ma_close_streams__aaudio(pDevice); */
ma_mutex_lock(&pDevice->aaudio.rerouteLock);
/* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */
{ {
error_disconnected:
/* The first thing to do is close the streams. */
ma_close_streams__aaudio(pDevice);
/* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */
ma_device_config deviceConfig; ma_device_config deviceConfig;
ma_device_descriptor descriptorPlayback; ma_device_descriptor descriptorPlayback;
ma_device_descriptor descriptorCapture; ma_device_descriptor descriptorCapture;
@@ -38464,17 +38485,17 @@ error_disconnected:
descriptorPlayback.periodCount = deviceConfig.periods; descriptorPlayback.periodCount = deviceConfig.periods;
} }
result = ma_device_init__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture); result = ma_device_init_streams__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to create stream after route change."); ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to create stream after route change.");
return result; goto done;
} }
result = ma_device_post_init(pDevice, deviceType, &descriptorPlayback, &descriptorCapture); result = ma_device_post_init(pDevice, deviceType, &descriptorPlayback, &descriptorCapture);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change."); ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change.");
ma_close_streams__aaudio(pDevice); ma_close_streams__aaudio(pDevice);
return result; goto done;
} }
/* We'll only ever do this in response to a reroute. */ /* We'll only ever do this in response to a reroute. */
@@ -38492,15 +38513,21 @@ error_disconnected:
goto error_disconnected; goto error_disconnected;
} }
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change."); ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change.");
return result; goto done;
} }
} else { } else {
ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */ ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */
} }
} }
result = MA_SUCCESS;
return MA_SUCCESS; done:
/* Re-routing done */
} }
ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
return result;
} }
static ma_result ma_device_get_info__aaudio(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo) static ma_result ma_device_get_info__aaudio(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo)