PipeWire: Optimization to multi-threaded mode.

This commit is contained in:
David Reid
2026-01-01 09:38:21 +10:00
parent 1d0a598485
commit edc44cbcaa
+34 -3
View File
@@ -1355,7 +1355,7 @@ typedef struct
ma_uint32 bufferSizeInFrames; ma_uint32 bufferSizeInFrames;
ma_uint32 bufferCount; ma_uint32 bufferCount;
ma_uint32 rbSizeInFrames; ma_uint32 rbSizeInFrames;
ma_pcm_rb rb; /* For playback, PipeWire will read from this ring buffer. For capture, it'll write to it. */ ma_pcm_rb rb; /* Only used in single-threaded mode. Acts as an intermediary buffer for step(). For playback, PipeWire will read from this ring buffer. For capture, it'll write to it. */
ma_device_descriptor* pDescriptor; /* This is only used for setting up internal format. It's needed here because it looks like the only way to get the internal format is via a stupid callback. Will be set to NULL after initialization of the PipeWire stream. */ ma_device_descriptor* pDescriptor; /* This is only used for setting up internal format. It's needed here because it looks like the only way to get the internal format is via a stupid callback. Will be set to NULL after initialization of the PipeWire stream. */
} ma_pipewire_stream_state; } ma_pipewire_stream_state;
@@ -2353,11 +2353,16 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
pContextStatePipeWire->pw_stream_get_time_n(pStreamState->pStream, &time, sizeof(time)); pContextStatePipeWire->pw_stream_get_time_n(pStreamState->pStream, &time, sizeof(time));
if (pStreamState->rbSizeInFrames > 0) { if (pStreamState->rbSizeInFrames > 0) {
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_SINGLE_THREADED) {
ma_pcm_rb_uninit(&pStreamState->rb); ma_pcm_rb_uninit(&pStreamState->rb);
} }
}
pStreamState->rbSizeInFrames = (ma_uint32)time.size; pStreamState->rbSizeInFrames = (ma_uint32)time.size;
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_SINGLE_THREADED) {
ma_pcm_rb_init(pStreamState->format, pStreamState->channels, pStreamState->rbSizeInFrames, NULL, ma_device_get_allocation_callbacks(pDeviceStatePipeWire->pDevice), &pStreamState->rb); ma_pcm_rb_init(pStreamState->format, pStreamState->channels, pStreamState->rbSizeInFrames, NULL, ma_device_get_allocation_callbacks(pDeviceStatePipeWire->pDevice), &pStreamState->rb);
}
pStreamState->initStatus |= MA_PIPEWIRE_INIT_STATUS_HAS_LATENCY; pStreamState->initStatus |= MA_PIPEWIRE_INIT_STATUS_HAS_LATENCY;
return; return;
@@ -2383,9 +2388,11 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
MA_PIPEWIRE_ASSERT(pBuffer->buffer->datas[0].data != NULL); MA_PIPEWIRE_ASSERT(pBuffer->buffer->datas[0].data != NULL);
if (frameCount > 0) { if (frameCount > 0) {
ma_uint32 framesRemaining = frameCount;
if (deviceType == ma_device_type_playback) { if (deviceType == ma_device_type_playback) {
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_MULTI_THREADED) {
ma_device_handle_backend_data_callback(pDeviceStatePipeWire->pDevice, pBuffer->buffer->datas[0].data, NULL, frameCount);
} else {
ma_uint32 framesRemaining = frameCount;
ma_uint32 framesAvailable = ma_pcm_rb_available_read(&pStreamState->rb); ma_uint32 framesAvailable = ma_pcm_rb_available_read(&pStreamState->rb);
/* Copy data in. Read from the ring buffer, output to the PipeWire buffer. */ /* Copy data in. Read from the ring buffer, output to the PipeWire buffer. */
@@ -2393,6 +2400,11 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
/* Underflow. Just write silence. */ /* Underflow. Just write silence. */
MA_PIPEWIRE_ZERO_MEMORY((char*)pBuffer->buffer->datas[0].data + (frameCount - framesRemaining) * bytesPerFrame, framesRemaining * bytesPerFrame); MA_PIPEWIRE_ZERO_MEMORY((char*)pBuffer->buffer->datas[0].data + (frameCount - framesRemaining) * bytesPerFrame, framesRemaining * bytesPerFrame);
} else { } else {
/*
Two ways of handling this. In multi-threaded mode, it doesn't really matter which thread does the data
processing so we can just do it directly from here and bypass the ring buffer entirely.
*/
while (framesRemaining > 0) { while (framesRemaining > 0) {
ma_uint32 framesToProcess = (ma_uint32)ma_min(framesRemaining, framesAvailable); ma_uint32 framesToProcess = (ma_uint32)ma_min(framesRemaining, framesAvailable);
void* pMappedBuffer; void* pMappedBuffer;
@@ -2413,9 +2425,14 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
} }
} }
} }
}
/*printf("(Playback) Processing %d frames... %d %d\n", (int)frameCount, (int)pBuffer->requested, pBuffer->buffer->datas[0].maxsize / bytesPerFrame);*/ /*printf("(Playback) Processing %d frames... %d %d\n", (int)frameCount, (int)pBuffer->requested, pBuffer->buffer->datas[0].maxsize / bytesPerFrame);*/
} else { } else {
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_MULTI_THREADED) {
ma_device_handle_backend_data_callback(pDeviceStatePipeWire->pDevice, NULL, pBuffer->buffer->datas[0].data, frameCount);
} else {
ma_uint32 framesRemaining = frameCount;
ma_uint32 framesAvailable = ma_pcm_rb_available_write(&pStreamState->rb); ma_uint32 framesAvailable = ma_pcm_rb_available_write(&pStreamState->rb);
/* Copy data out. Write from the PipeWire buffer to the ring buffer. */ /* Copy data out. Write from the PipeWire buffer to the ring buffer. */
@@ -2438,6 +2455,7 @@ static void ma_stream_event_process__pipewire(void* pUserData, ma_device_type de
break; break;
} }
} }
}
/*printf("(Capture) Processing %d frames...\n", (int)frameCount);*/ /*printf("(Capture) Processing %d frames...\n", (int)frameCount);*/
} }
@@ -2722,6 +2740,7 @@ static void ma_device_uninit__pipewire(ma_device* pDevice)
{ {
ma_device_state_pipewire* pDeviceStatePipeWire = ma_device_get_backend_state__pipewire(pDevice); ma_device_state_pipewire* pDeviceStatePipeWire = ma_device_get_backend_state__pipewire(pDevice);
ma_context_state_pipewire* pContextStatePipeWire = ma_context_get_backend_state__pipewire(ma_device_get_context(pDevice)); ma_context_state_pipewire* pContextStatePipeWire = ma_context_get_backend_state__pipewire(ma_device_get_context(pDevice));
ma_device_type deviceType = ma_device_get_type(pDevice);
if (pDeviceStatePipeWire->capture.pStream != NULL) { if (pDeviceStatePipeWire->capture.pStream != NULL) {
pContextStatePipeWire->pw_stream_destroy(pDeviceStatePipeWire->capture.pStream); pContextStatePipeWire->pw_stream_destroy(pDeviceStatePipeWire->capture.pStream);
@@ -2740,6 +2759,15 @@ static void ma_device_uninit__pipewire(ma_device* pDevice)
pContextStatePipeWire->pw_context_destroy(pDeviceStatePipeWire->pContext); pContextStatePipeWire->pw_context_destroy(pDeviceStatePipeWire->pContext);
pContextStatePipeWire->pw_loop_destroy(pDeviceStatePipeWire->pLoop); pContextStatePipeWire->pw_loop_destroy(pDeviceStatePipeWire->pLoop);
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_SINGLE_THREADED) {
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) {
ma_pcm_rb_uninit(&pDeviceStatePipeWire->capture.rb);
}
if (deviceType == ma_device_type_playback || deviceType == ma_device_type_duplex) {
ma_pcm_rb_uninit(&pDeviceStatePipeWire->playback.rb);
}
}
ma_free(pDeviceStatePipeWire, ma_device_get_allocation_callbacks(pDevice)); ma_free(pDeviceStatePipeWire, ma_device_get_allocation_callbacks(pDevice));
} }
@@ -2801,6 +2829,8 @@ static ma_result ma_device_step__pipewire(ma_device* pDevice, ma_blocking_mode b
return MA_DEVICE_NOT_STARTED; return MA_DEVICE_NOT_STARTED;
} }
/* We need only process data here in single-threaded mode. */
if (ma_device_get_threading_mode(pDeviceStatePipeWire->pDevice) == MA_THREADING_MODE_SINGLE_THREADED) {
/* We want to handle both playback and capture in a single iteration for duplex mode. */ /* We want to handle both playback and capture in a single iteration for duplex mode. */
if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) { if (deviceType == ma_device_type_capture || deviceType == ma_device_type_duplex) {
ma_uint32 framesAvailable; ma_uint32 framesAvailable;
@@ -2847,6 +2877,7 @@ static ma_result ma_device_step__pipewire(ma_device* pDevice, ma_blocking_mode b
} }
} }
} }
}
if (hasProcessedData || blockingMode == MA_BLOCKING_MODE_NON_BLOCKING) { if (hasProcessedData || blockingMode == MA_BLOCKING_MODE_NON_BLOCKING) {
break; break;