[idd] audio: discipline playback clock from client

Forward coalesced feedback through the broker to the render clock.

Keep capture independent and apply the rate to WaveRT timing.

Bound and slew targets, then restore unity when feedback stalls.

Withdraw feedback after the watchdog makes fallback safe.
This commit is contained in:
Geoffrey McRae
2026-09-05 06:32:14 +10:00
parent f7b1133785
commit 5681dcdbe7
10 changed files with 679 additions and 60 deletions

View File

@@ -860,7 +860,8 @@ namespace
caps->maximumVersion = LGAUDIO_BROKER_ABI_VERSION;
caps->capabilities = LGAUDIO_BROKER_CAP_CONTROL |
LGAUDIO_BROKER_CAP_RENDER_READ |
LGAUDIO_BROKER_CAP_CAPTURE_WRITE;
LGAUDIO_BROKER_CAP_CAPTURE_WRITE |
LGAUDIO_BROKER_CAP_CLOCK_CONTROL;
caps->maximumRenderTransfer = LGAUDIO_BROKER_MAX_PAYLOAD_BYTES;
caps->maximumCaptureTransfer = LGAUDIO_BROKER_MAX_PAYLOAD_BYTES;
return CompleteIrp(irp, STATUS_SUCCESS, sizeof(*caps));
@@ -1028,6 +1029,48 @@ namespace
return CompleteIrp(irp, status);
}
NTSTATUS SetClockControl(
_In_ BrokerControlExtension *extension,
_In_ PFILE_OBJECT fileObject,
_Inout_ PIRP irp,
_In_ ULONG inputLength)
{
const void *input = irp->AssociatedIrp.SystemBuffer;
if (!ValidateVersionedInput(input, inputLength,
sizeof(LGAudioBrokerClockControl)))
return CompleteIrp(irp, STATUS_INVALID_PARAMETER);
const auto *control =
static_cast<const LGAudioBrokerClockControl *>(input);
if (control->flags || control->reserved0 ||
control->reserved[0] || control->reserved[1] ||
!control->adapterGeneration || !control->bindingGeneration ||
!control->streamGeneration || !control->targetRateQ32)
{
return CompleteIrp(irp, STATUS_INVALID_PARAMETER);
}
BindingSnapshot binding{};
NTSTATUS status = AcquireBinding(extension, fileObject, &binding);
if (NT_SUCCESS(status) &&
(control->adapterGeneration != binding.adapterGeneration ||
control->bindingGeneration != binding.bindingGeneration))
{
status = STATUS_RETRY;
}
if (NT_SUCCESS(status) && !IsCurrentAdapter(binding))
status = STATUS_DEVICE_NOT_CONNECTED;
if (NT_SUCCESS(status))
{
status = binding.adapter->SetRenderClockRate(
control->streamGeneration, control->targetRateQ32);
}
if (binding.adapter)
ExReleaseRundownProtection(&extension->bindingRundown);
return CompleteIrp(irp, status);
}
NTSTATUS QueryStats(
_Inout_ PIRP irp,
_In_ ULONG outputLength)
@@ -1492,6 +1535,10 @@ namespace
status = QueryStats(irp, outputLength);
break;
case IOCTL_LGAUDIO_BROKER_SET_CLOCK_CONTROL:
status = SetClockControl(extension, fileObject, irp, inputLength);
break;
default:
status = CompleteIrp(irp, STATUS_INVALID_DEVICE_REQUEST);
break;