Filter-centric processing

If a filter uses filter-centric processing, then by default AVStream calls the minidriver-supplied AVStrMiniFilterProcess callback routine when there are data frames available on each pin instance. Minidrivers can modify this default behavior by setting the Flags member of the KSPIN_DESCRIPTOR_EX structure.

To implement filter-centric processing, provide a pointer to a minidriver-supplied AVStrMiniFilterProcess callback routine in the Process member of the KSFILTER_DISPATCH structure. Set the Process member of KSPIN_DISPATCH to NULL.

AVStream calls AVStrMiniFilterProcess only when all of the following conditions are met:

  • Frames are available on pins that require frames for processing to occur. Minidrivers can modify processing behavior by setting flags in the Flags member of KSPIN_DESCRIPTOR_EX. Pay particular attention to combinations of the mutually exclusive flags KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING and KSPIN_FLAG_SOME_FRAMES_REQUIRED_FOR_PROCESSING. The minidriver can also modify the set of pins that require frames through the use of the KsPinAttachAndGate or KsPinAttachOrGate routines.

  • The number of pin instances is equal to or greater than the InstancesNecessary member of the KSPIN_DESCRIPTOR_EX structure. The ClientState member of the KSPIN structure specifies the particular KSSTATE enumerator at which the pin is currently set. After InstancesNecessary has been met, additional pins in the KSSTATE_STOP state will not prevent filter processing.

  • The required number of pin instances is met (as specified by the InstancesNecessary member of the KSPIN_DESCRIPTOR_EX structure.

  • The minidriver has not closed the process control gate of the filter by using the KSGATEXxx functions.

In the AVStrMiniFilterProcess callback routine, the minidriver receives a pointer to an array of KSPROCESSPIN_INDEXENTRY structures. AVStream orders the array of KSPROCESSPIN_INDEXENTRY structures by pin ID.

The following code examples illustrate how to use the process pin structures. The code is taken from the AVStream Filter-Centric Simulated Capture Driver (Avssamp) sample, which demonstrates how to write a filter-centric capture driver. Source code and a description of this sample are included in the Windows Driver Kit samples download.

The minidriver receives an array of KSPROCESSPIN_INDEXENTRY structures in its filter process dispatch. In this example, the minidriver extracts the first KSPROCESSPIN structure from the KSPROCESSPIN_INDEXENTRY structure of index VIDEO_PIN_ID:

NTSTATUS
CCaptureFilter::
Process (
    IN PKSPROCESSPIN_INDEXENTRY ProcessPinsIndex
    )
{
PKSPROCESSPIN VideoPin = NULL;
...
VideoPin = ProcessPinsIndex [VIDEO_PIN_ID].Pins [0];
...
}

The minidriver should not reference ProcessPinsIndex [n].Pins [0] before it has verified that the Count member of ProcessPinsIndex [n] is at least one, or that the InstancesNecessary member of the KSPIN_DESCRIPTOR_EX structure contained within Pins [0] is at least one. (If the latter is true, the pin is guaranteed to exist.)

Then, to specify the pin on which to capture frames, the AVStrMiniFilterProcess callback routine passes a pointer to a KSPROCESSPIN structure to CaptureFrame, a vendor-supplied capture routine:

VidCapPin -> CaptureFrame (VideoPin, m_Tick);

The capture routine can then copy to or from the Data member of the KSPROCESSPIN structure. It might also update the BytesUsed and Terminate members of this structure, as in the following example:

RtlCopyMemory ( ProcessPin -> Data,
                m_SynthesisBuffer,
                m_VideoInfoHeader -> bmiHeader.biSizeImage
               );
ProcessPin -> BytesUsed = m_VideoInfoHeader -> bmiHeader.biSizeImage;
ProcessPin -> Terminate = TRUE;

The minidriver can also access the stream header structure corresponding to the current stream pointer and pin:

PKSSTREAM_HEADER StreamHeader = ProcessPin -> StreamPointer -> StreamHeader;

Most minidrivers that use filter-centric processing use the stream pointer only for stream header access. In the filter-centric model, AVStream manipulates the stream pointer internally. As a result, minidrivers should proceed with caution if they manipulate the stream pointer in a filter-centric driver.