I'm trying to read raw PCM data from a microphone stream. To do this, I'm using KsCreatePin
to create a connection to a microphone pin and start reading from it. Before reading, I'm setting the pin state to KSSTATE_RUN
using IOCTL_KS_PROPERTY
.
Reading data in the loop works for a few seconds (I can read a few KB) but then suddenly, ZwWaitForSingleObject
never returns after the IOCTL_KS_READ_STREAM
call. I'm not sure what I'm doing wrong to trigger this behavior. The current test code looks as follows:
// Start the reading loop
while (Stream != NULL)
{
// Clear wait event
ZwClearEvent(Event);
// Zero the stream header
memset(&StreamHdr, 0, sizeof(KSSTREAM_HEADER));
// Initialize the stream header
StreamHdr.Size = sizeof(KSSTREAM_HEADER);
StreamHdr.Data = MediaBuffer;
StreamHdr.FrameExtent = MediaBufferSize;
StreamHdr.DataUsed = 0;
StreamHdr.OptionsFlags = 0 /* KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID */;
// Initialize time and duration
StreamHdr.PresentationTime.Numerator = 8 * 10000000; // Bits per byte * nanoseconds
StreamHdr.PresentationTime.Denominator = BitsPerSample * NoChannels * SampleFreq;
StreamHdr.PresentationTime.Time = ByteOffset;
StreamHdr.Duration = MediaBufferSize;
// Request new block of media data
Status = NtDeviceIoControlFile(
PinHandle,
Event,
NULL,
NULL,
&IoStatus,
IOCTL_KS_READ_STREAM,
&StreamHdr,
sizeof(KSSTREAM_HEADER),
&StreamHdr,
sizeof(KSSTREAM_HEADER)
);
// Check and wait if pending
if (Status == STATUS_PENDING)
{
Status = ZwWaitForSingleObject(Event, FALSE, NULL); // Stalls here
Status = IoStatus.Status;
}
// Check success
if (!NT_SUCCESS(Status))
break;
DbgPrintEx(0, 0, "Received data: %d\n", StreamHdr.DataUsed); // Works for a few KB
}
Note: I've tried setting KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID
as OptionsFlags in the stream header as well, as described by the docs, but this results in NtDeviceIoControlFile
instantly returning with 0 bytes read.
I appricate any attempts to explain this behavior!