[wdmaudiodev] Re: [EXTERNAL] Understanding IMiniportWaveRtStreamNotification::RegisterNotificationEvent

  • From: "Matthew van Eerde" <dmarc-noreply@xxxxxxxxxxxxx> (Redacted sender "Matthew.van.Eerde" for DMARC)
  • To: "wdmaudiodev@xxxxxxxxxxxxx" <wdmaudiodev@xxxxxxxxxxxxx>
  • Date: Mon, 2 Nov 2020 16:47:39 +0000

Okay, so you are both a virtual speaker and a virtual microphone, and your 
virtual microphone gets its data from the virtual speaker?

________________________________
From: wdmaudiodev-bounce@xxxxxxxxxxxxx <wdmaudiodev-bounce@xxxxxxxxxxxxx> on 
behalf of wdmaudiodev@xxxxxxxxxxxxxx <wdmaudiodev@xxxxxxxxxxxxxx>
Sent: Saturday, October 31, 2020 6:25:52 AM
To: wdmaudiodev@xxxxxxxxxxxxx <wdmaudiodev@xxxxxxxxxxxxx>
Subject: [wdmaudiodev] Re: [EXTERNAL] Understanding 
IMiniportWaveRtStreamNotification::RegisterNotificationEvent


This driver creates a virtual capture endpoint ("microphone") that third-party 
chat apps like Zoom or Skype will consume.

So whenever the capture stream requests data, if there is a new packet 
available from the render stream, I copy it across. If the render stream isn't 
in RUN mode, then I silence-fill the capture buffer.

-S

On 10/30/20 9:45 AM, Matthew van Eerde (Redacted sender Matthew.van.Eerde for 
DMARC) wrote:

Who consumes the data that Windows writes to you? Do they have a clock?



From: wdmaudiodev@xxxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxxx>
Sent: Friday, October 30, 2020 9:26 AM
To: wdmaudiodev@xxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxx>
Subject: [wdmaudiodev] Re: [EXTERNAL] Understanding 
IMiniportWaveRtStreamNotification::RegisterNotificationEvent



Please don’t do this.

I'd rather go with the prevailing wisdom and do it 'properly', vs. produce 
another crappy, battery-draining Windows driver. So, OK, no timer.

SYSVAD is the only example of this that I have, and it says (paraphrasing) "in 
a real driver, you wouldn't use a timer like we show here; your DMA hardware 
and position registers would handle ...".

My driver is virtual, though, so there is no hardware. It just copies packets 
from RENDER[1] to CAPTURE, without buffering.

I could create a worker thread that waits on both render-data-ready and 
capture-buffer-available events. I don't have any driver-specific examples of 
this, but I've done this in desktop apps in the past.

Any suggestions/advice? Any insight on the SetWritePacket/SetReadPacket 
question?

--S



[1] Or, if I can get a custom interface working, copy data 
passed-from-app-to-driver via backchannel

On 10/30/20 8:44 AM, Matthew van Eerde (Redacted sender Matthew.van.Eerde for 
DMARC) wrote:

  *   I have a timer function that monitors this



Please don’t do this.



From: wdmaudiodev@xxxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxxx>
Sent: Friday, October 30, 2020 6:31 AM
To: wdmaudiodev@xxxxxxxxxxxxx<mailto:wdmaudiodev@xxxxxxxxxxxxx>
Subject: [EXTERNAL] [wdmaudiodev] Understanding 
IMiniportWaveRtStreamNotification::RegisterNotificationEvent



Hi,

I was a bit confused by the function of the 
IMiniportWaveRtOutputStream::SetWritePacket and 
IMiniportWaveRtInputStream::SetReadPacket methods, and the KEVENT passed into 
RegisterNotificationEvent.

If I understand it correctly, AllocateBufferWithNotification gets called with 
notificationCount=2, and a buffer large enough for two 'packets'. Packets seem 
to be sized to contain about 1/100 sec worth of audio frames. 
RegisterNotificationEvent gets called with a single (in my case) event.

In the RENDER case, SetWritePacket(n, ...) is called when the OS has finished 
copying packet <n> into whichever half of the buffer. I have a timer function 
that monitors this, and transfers the packet to hardware (let's say). To let 
the OS know that packet <n> has been processed (i.e., that packet in the buffer 
is available), I call KeSetEvent(pNotificationEvent, 0, FALSE).

So this part isn't clear to me:

...kernel event that must be notified as DMA progresses. Depending on the 
notification count parameter used with 
AllocateBufferWithNotification<https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fwindows-hardware%2Fdrivers%2Fddi%2Fhdaudio%2Fnc-hdaudio-pallocate_dma_buffer_with_notification&data=04%7C01%7CMatthew.van.Eerde%40microsoft.com%7Ce86354349b8f42d73f9208d87da0df32%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637397477231502141%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=2hBMswlt1IWsY6psSwMo74HF7BZKkUdev5W4IqZcWfc%3D&reserved=0>,
 the registered event is signaled __one or two times__ for every time that the 
DMA passes through the audio buffer.

I expected there to be two calls to RegisterNotificationEvent, and thus two 
KEVENT objects at any given time (one for each packet in the buffer). Instead, 
I only see one getting added. The doc quote above seems to suggest that a 
single event has to be set TWICE (or maybe set once, then the OS clears, then 
set again)? I've looked at the KEVENT struct and related APIs, but I'm still 
confused. Is this event supposed to signify "Buffer Complete" or "Packet 
Complete"?

In the CAPTURE case, it looks like things are reversed. The OS calls 
SetReadPacket to query the driver about which packet is available for reading 
(transferring to client). RegisterNotificationEvent is getting called, so I 
think the same (single) event is SET/CLEARED? by the OS to signal ME that it 
has finished transferring data out of a packet, and that packet is available 
for DMA again.

Thanks in advance for any and all help. :-)




Other related posts: