AVStream

AVStream is a class driver for video streaming miniport drivers, supported in Windows XP and later systems, with downloads for some earlier systems. Microsoft recommends it for use with video and combined video/audio drivers. Your device driver calls into AVStream in the initial entrypoint and is then called back via a table of callback functions when service is needed. Unlike the NDIS model, your driver still has full access to all the facilities of WDM.

The documentation for AVStream is quite extensive, but the samples are very limited. I've noted below a number of issues with AVStream.

AVSHWS Sample and Stream Format dialog

If you install the avshws sample driver and view it in Graphedt, you cannot access the Stream Format dialog. This is because of a mismatch of video standard declarations in the sample. The property page code gets the current video standard using IAMAnalogVideoDecoder::get_TVFormat and compares that to the standard listed in the pin's format structures. The sample does not support the TVFormat property, which will thus default to 0, and this does not correspond to the KS_AnalogVideo_NSTC_M in the pin's format structures.

Change this value to 0 in the pin's format structures and the Stream Format dialog will work correctly.

Handling Flush: Hangs in CKSQueue or CKSOutputPin

There are a couple of bugs in AVStream that will affect your driver if you create something like a hardware video decoder in AVStream. Fortunately, there are workarounds for both.

The first bug is that if you delete a stream pointer during a cancellation callback, it may not be properly deleted. When there is a seek request on the graph, the BeginFlush method will be called on your input pin. AVStream will translate this to a cancellation callback on the cloned stream pointers. Depending on your device, you may have to handle this by aborting all i/o, which would cause you to call KsStreamPointerDelete on all the queued pointers. If you call KsStreamPointerDelete during a cancellation callback, only the stream pointer that is being cancelled is deleted. Other deletes are ignored. So you will get cancellation callbacks on all the other outstanding pointers. To work around this, you should always delete a pointer if you get a cancellation callback, but must be careful with your own state since you may already have completed or cancelled the i/o operation.

The second bug relates to propagation: when a BeginFlush is received by the input pin, AVStream translates this to a cancellation of all the input pin's stream pointers. It does not propagate to the output pin or downstream. So if your filter has stream pointers outstanding on the output pin, you will need to register cancellation handlers on the input pin and in the handler, delete all the output pin's cloned pointers.

Dynamic Type Change

Decoders for DVD or Blu-Ray systems will sometimes need to change the output image dimensions dynamically. DirectShow supports this using the ReceiveConnection protocol. However, the KSProxy filter does not support this, so this is not possible for any WDM Streaming device; it's also not possible to change the output buffer size dynamically from the decoder. The only workaround I've found is to have a user-mode DirectShow filter between the decoder and the renderer. A private signal as part of the data indicates to the post-processing filter that a type change is required. This introduces a copy of the decompressed image, but allows type changes and also simplifies the handling of renderer-originated stride and orientation changes.