Step 1: Learn about Windows architecture and drivers
AVStream:
AVStream is a Microsoft-provided multimedia class driver that supportsvideo-only streaming and integrated audio/video streaming. Microsoft providesAVStream as part of the operating system, in the export driver
Ks.sys
.Hardware vendors write minidrivers that run under
Ks.sys
.
The preferred class driver for audio drivers is the Microsoft-providedaudio
port class
driver. Audio vendors should write minidrivers that run under
Portcls.sys
.
Microsoft supports the
stream class
driver only for existing minidrivers.
AVStream drivers build on Microsoft Windows XP, Microsoft WindowsServer 2003, or any platform Windows 98 Gold or later version thathas DirectX 8.0 or later version installed.
If you build on an operating system earlier than Windows XP, make surethat you use the latest available DirectX Driver Development Kit (DDK). DirectX9.0 contains updates for AVStream, kernel streaming components, and streamclass.
AVStream offers significant advantages to the vendor by:
- Requiring minidriver writers to produce less code.
- Providing a unified kernel streaming class model for both audio and video minidrivers.
-
Providing support for vendors to write user-mode plug-ins. These are COM interfaces that provide methods to access property values. You can provide plug-ins without altering existing minidriver binaries. For more information, see
Kernel Streaming Proxy Plug-ins
.
In the AVStream driver model, vendors provide a minidriver that interactswith a Microsoft-provided class driver, as shown in the following diagram:
Relationship Between AVStream and KS Services
All kernel streaming andAVStream reference material covers structures and functions that are declaredin
ks.h
. This is the header that the minidriver must include in order toaccess the Microsoft-supplied KS and AVStream class driver support.
An AVStream minidriver describes itself and the filter types itsupports by providing nested descriptor structures in the call toKsInitializeDriver. Each key component — the device, the filter factory, andthe pin factory — has an associated descriptor.
As shown in AVStream Object Hierarchy, the highest leveldescriptor for an AVStream minidriver is the device descriptor,KSDEVICE_DESCRIPTOR.
In the device descriptor, the FilterDescriptors member points toan array of KSFILTER_DESCRIPTOR structures that describe the types of filtersthis device can create. AVStream clients can call KsCreateFilterFactory todynamically add filter factories.
A KSFILTER_DESCRIPTOR indicates how many pin types the filtersupports, the KS categories under which the filter is to be registered, and thetopology of the filter. Inside each filter descriptor, the minidriver providesa pointer to an array of KSPIN_DESCRIPTOR_EX structures. Each of these pindescriptors describes a pin type that this filter can instantiate. You cancreate additional pin factories by calling KsFilterCreatePinFactory.
Typically, AVStream minidrivers lay out static descriptor tablesin their source and call KsInitializeDriver to perform the setup work. For moreinformation about initializing your driver, see Initializing an AVStreamMinidriver.
There are other types of descriptors as well, such as the nodedescriptor KSNODE_DESCRIPTOR, which describes a given topology node.
The dispatch table is common to each of the three maindescriptor types. See AVStream Dispatch Tables.
The AVStream dispatch table,
KSDEVICE_DISPATCH
,is a set of function pointers to dispatch functions. A minidriver can extendthe behavior provided by AVStream by providing callback routines that performdriver-specific tasks.
These minidriver-provided routines receive notifications ofcertain events and may extend or modify the default event handling provided byAVStream.
Both
KSFILTER_DISPATCH
and
KSPIN_DISPATCH
structures provide a dispatch called
Process
. Use this dispatch todifferentiate a
filter-centric
filter from a
pin-centric
filter.To specify a filter-centric filter, supply a pointer to a processdispatch callback routine in the filter dispatch table. A pin-centric filterprovides a process dispatch in each of the pin descriptor tables.
You can register filters to be notified about creations,deletions, the need to process data, and resets. You can register pins to benotified of events such as creations, closure, the need to process data,resets, setting of data formats, and state changes. To register objects fornotification, supply a pointer to a vendor-supplied dispatch routine in therelevant dispatch structure.
For more information about dispatch functions, see
KSFILTER_DISPATCH
,
KSPIN_DISPATCH
,and
KSALLOCATOR_DISPATCH
.
Initializing an AVStream Minidriver
An AVStream minidriver that does not handle device initialization on itsown calls
KsInitializeDriver
from theminidriver’s
DriverEntry
routine.
KsInitializeDriver
initializes the driver object of an AVStream driver, in addition to IRPdispatching, PnP add device messages, and unloading.
In calling
KsInitializeDriver
, the minidriver passes a pointer tothe driver object to initialize a pointer to the registry path, and optionally,a device descriptor object. Note that passing the
KSDEVICE_DESCRIPTOR
object isnot required. If the minidriver does pass a device descriptor, AVStream createsa device with the specified characteristics at AddDevice time.
The device descriptor object contains a pointer to a
KSDEVICE_DISPATCH
structure as wellas an array of filter descriptors. Provide a
KSFILTER_DESCRIPTOR
for eachfilter type that your minidriver supports. When the minidriver calls
KsInitializeDriver
, AVStreamcreates a filter factory object for each type of filter exposed by theminidriver. Individual filters are then instantiated by the filter factory uponreceipt of a create IRP for the associated create item. Each filter descriptorcontains a pointer to an array of
KSPIN_DESCRIPTOR_EX
objects.AVStream creates a pin factory on the relevant filter for each type of pin theminidriver exposes through that filter.
When a connection is made to a given pi n type on a filter, the AVStreampin factory creates a pin object. Note that each filter must expose at leastone pin. The minidriver uses the
InstancesNecessary
member ofKSPIN_DESCRIPTOR_EX to identify the number of instances of this pin type thatare necessary for the filter to function correctly. Similarly, the minidrivercan impose a maximum on the number of pins that the pin factory can instantiateby using the
InstancesPossible
member of this structure.
AVStream supports two types of processing:
filter-centric processing
, and
pin-centric processing
. Whenlaying out the descriptors, decide which type of processing each filter typewill perform.
Installing an AVStream Minidriver
An AVStream minidriver must have an INF file that the system uses toinstall the driver. An AVStream INF file is based on the common INF format,which is described in
Creating an INF File
. You canalso refer to the INF files supplied with AVStream sample drivers in the WindowsDriver Kit (WDK). Keep in mind the following AVStream-specific guidelines.
If you are writing a minidriver for a parent device, the
AddReg
section of your INF file should contain:
[ParentName.AddReg]
HKR,”ENUM\[DeviceName]”,pnpid,,”[string]”
If you are writing a minidriver for a child device, the
AddReg
section should contain:
[Manufacturer]
…=ChildName
[ChildName]
…=ChildName.Device,
AVStream\
[string]
Note that “AVStream” would be “Stream” for a streamclass driver.
For all AVStream minidrivers, the filter-specific reference string in theINF file must match the
ReferenceGuid
member of the
KSFILTER_DESCRIPTOR
structure.
For more information about descriptors, see
AVStream Descriptors
.
When writing an AVStream minidriver, you provide filters that use one oftwo processing paradigms: pin-centric processing or
filter-centric processing
.
Pin-centric processing means that AVStream calls the minidriver’s pinprocess dispatch routine when new frames arrive in the pin queue.
Filter-centric processing means that AVStream calls the minidriver’sfilter process dispatch routine when there are data frames available on eachinstantiated pin. Note that these definitions specify default behavior;minidrivers can modify the default behavior by setting flags in the
KSPIN_DESCRIPTOR_EX
structure.
In general, software filters use filter-centric processing and hardwarefilters use pin-centric processing. For instance, hardware that transforms orrenders data could route data on a pin-centric filter. There are rare cases inwhich these roles may be reversed.
To supply a pin-centric filter, the minidriver provides a pointer to an
AVStrMiniPinProcess
callback routine in each
KSPIN_DISPATCH
structure; do notsupply a processing dispatch in the
KSFILTER_DISPATCH
structure.
If the minidriver does not modify flag settings in the KSPIN_DESCRIPTOR_EXstructure, AVStream calls the vendor-supplied
AVStrMiniPinProcess
callback routine in three situations:
- The pin transitions into the minimum processing state. Frames must already exist in the queue, and the pin must transition from less than the minimum processing state into at least the minimum processing state.
- New frames arrive. The pin must be in at least the minimum processing state and there must be no frames at or ahead of the leading edge.
-
Minidriver explicitly calls
KsPinAttemptProcessing
.
By default, pause is the minimum processing state.
In addition, AVStream does not call the pin process dispatch if the pin’sAND gate is closed. If you use the
KsGate
Xxx
routines to addadditional off inputs to the pin’s AND gate, for instance, your processdispatch will not be called.
When AVStream calls
AVStrMiniPinProcess
, it provides a pointer tothe pin object that has available data. The minidriver’s processing dispatchcan then acquire a
leading edge pointer
by calling
KsPinGetLeadingEdgeStreamPointer
. Minidrivers then manipulate stream data using the
stream pointer
API.
Minidrivers that use pin-centric processing can modify when AVStream callsthe
AVStrMiniPinProcess
dispatch by setting flags in the relevant
KSPIN_DESCRIPTOR_EX
structure.Flag descriptions on the KSPIN_DESCRIPTOR_EX reference page are particularlyrelevant to vendors who are implementing pin-centric filters.
Processing attempts may fail if the minidriver is holding the
processing mutex
through
KsPinAcquireProcessingMutex
. Problems may also arise if the minidriver directly manipulates a gate byusing the
KsGate
*
calls.
The
Avshws
sample in the Windows Driver Kit (WDK) is a pin-centriccapture driver for a simulated piece of hardware. The
Avshws
sampleshows how to implement
DMA through AVStream
.
If a filter uses filter-centric processing, then by default AVStream callsthe minidriver-supplied
AVStrMiniFilterProcess
callback routine when there are data frames available on each pininstance. 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 aminidriver-supplied
AVStrMiniFilterProcess
callback routine in the
Process
member of the
KSFILTER_DISPATCH
structure. Setthe
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
KsGate
Xxx
functions.
In the
AVStrMiniFilterProcess
callback routine, the minidriver receives a pointer to an array of
KSPROCESSPIN_INDEXENTRY
structures. AVStream orders the array of KSPROCESSPIN_INDEXENTRYstructures by pin ID.
The following code examples illustrate how to use the process pin structures.The code is taken from the
Avssamp
sample, which demonstrates how towrite a filter-centric capture driver. Source code for this sample is includedin the Windows Driver Kit (WDK). The code is located in a subdirectory of thedirectory tree that contains WDK samples.
The minidriver receives an array of KSPROCESSPIN_INDEXENTRY structures inits filter process dispatch. In this example, the minidriver extracts the firstKSPROCESSPIN structure from the KSPROCESSPIN_INDEXENTRY structure of indexVIDEO_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
memberof the KSPIN_DESCRIPTOR_EX structure contained within
Pins
[0] is atleast 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 theKSPROCESSPIN 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 correspondingto the current stream pointer and pin:
PKSSTREAM_HEADER StreamHeader = ProcessPin -> StreamPointer -> StreamHeader;
Most minidrivers that use filter-centric processing use the stream pointeronly for stream header access. In the filter-centric model, AVStreammanipulates the stream pointer internally. As a result, minidrivers shouldproceed with caution if they manipulate the stream pointer in a filter-centricdriver.
EventHandling in AVStream
AVStream filters and pins describe properties, events, andmethods that they support by supplying a
KSAUTOMATION_TABLE
structure in the
AutomationTable
member of either a
KSFILTER_DESCRIPTOR
structure or a
KSPIN_DESCRIPTOR_EX
structure. For more information, see
AVStreamDescriptors
.
To support events, an AVStream minidriver provides an arrayof
KSEVENT_SET
structures in an automation table. Each KSEVENT_SET structure contains an arrayof
KSEVENT_ITEM
structures. Each KSEVENT_ITEM structure describes how the minidriver supports aspecific event.
The minidriver can customize event behavior by supplying
AVStrMiniAddEvent
and
AVStrMiniRemoveEvent
handlers in the KSEVENT_ITEM structures.
When AVStream receives an event enable request, itgenerates a KSEVENT_ENTRY structure. If the minidriver has provided an
AVStrAddEvent
handler, AVStream passes a pointer to the KSEVENT_ENTRY structure in the callto
AVStrAddEvent
.
If you do not provide an
AVStrAddEvent
handler, thenby default AVStream adds the event to the object list. Your minidriver does notreceive a
KSEVENT_ENTRY
pointer. Your minidriver can trigger the event by calling
KsFilterGenerateEvents
or
KsPinGenerateEvents
.
AVStreamChild Devices
This section applies to Microsoft Windows Server 2003 and earlieroperating systems only if DirectX 9.0 or later is installed on that platform.
AVStream can function as a bus enumerator for your device,creating a child device for each key in the
Enum
branch. To do this,place an
Enum
branch in the registry under the device key.
Specifically, in the
AddReg
section of the driver’sINF file, the vendor supplies a value
pnpid
of type REG_SZ for eachentry under
Enum
. AVStream uses this string value to construct a Plugand Play (PnP) hardware ID for each individual child device.
In releases earlier than DirectX 9.0, AVStream creates achild device hardware ID of the form “AVStream\
<pnpid>
“(where <pnpid> is the value of
pnpid
for the specific device).
For example, the vendor specifies the following in the
AddReg
section of the INF file:
[MyTVDevice.AddReg]
HKR,”ENUM\CrossbarDevice”,pnpid,,”MyCrossbar”
HKR,”ENUM\TunerDevice”,pnpid,,”MyTuner”
Accordingly, AVStream creates two child devices with thefollowing device IDs:
AVStream\MyCrossbar
AVStream\MyTuner
To resolve possible ambiguity from two different childdevices specifying the same
pnpid
value, DirectX 9.0 and later changethe IDs reported for each of the child devices. For each hardware ID reportedby the parent device, AVStream creates an ID for the child device in thefollowing form:
AVStream\
<pnpid>
#
<modified parenthardware ID>
The modified parent hardware ID is the parent hardware IDwith each backslash (
\
) character replaced by the number sign (
#
).
If the resulting string is too long, AVStream terminatesthe ID string at MAX_DEVICE_ID_LEN characters, including the NULL terminator.In Windows Server 2003, this limit is set to 200 characters in
cfgmgr32.h
.
For example, a parent device reports the following hardwareIDs:
PCI\VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ&REV_VV
PCI\VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ
For a device with a
pnpid
key of
MyCrossbar
,AVStream creates the following child device hardware IDs:
AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ&REV_VV
AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY&SUBSYS_ZZZZZZZZ
AVStream uses the same process for compatible IDs reportedby the parent device. AVStream creates a compatible ID for the child device ofthe form:
AVStream\
<pnpid>
#
<modified parentcompatible ID>
The name modification and length rules for compatible IDsare identical to those for hardware IDs.
For example, if the parent device previously describedreports the following compatible IDs:
PCI\VEN_XXXX&DEV_YYYY&REV_VV
PCI\VEN_XXXX&DEV_YYYY
PCI\VEN_XXXX&CC_ZZZZZZ
PCI\VEN_XXXX&CC_ZZZZ
PCI\VEN_XXXX
PCI\CC_ZZZZZZ
PCI\CC_ZZZZ
The
MyCrossbar
child device would report throughAVStream the following compatible IDs:
AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY&REV_VV
AVStream\MyCrossbar#PCI#VEN_XXXX&DEV_YYYY
AVStream\MyCrossbar#PCI#VEN_XXXX&CC_ZZZZZZ
AVStream\MyCrossbar#PCI#VEN_XXXX&CC_ZZZZ
AVStream\MyCrossbar#PCI#VEN_XXXX
AVStream\MyCrossbar#PCI#CC_ZZZZZZ
AVStream\MyCrossbar#PCI#CC_ZZZZ
AVStream\MyCrossbar
Note:
InDirectX 9.0 and later, the legacy hardware ID, AVStream\
<pnpid>
,is still reported as the lowest rank compatible ID. As a result, legacy driverscontinue to work unmodified on these platforms.
However, as of the DirectX 9.0 release,Microsoft recommends that vendors writingnew or revised drivers thatleverage the AVStream class bus enumerator use the new hardware ID formats.Drivers can support platforms running earlier versions of AVStream by includingthe old ID in the compatible IDs list in the INF file.
Restarting Processing in AVStream
AVStream stops processing if any of the following conditions are true:
- In a pin-centric environment, no data is currently available on the pin.
-
In a filter-centric environment, at least one pin for which the
Flags
member of the
KSPIN_DESCRIPTOR_EX
structure does not set KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING, does not have data waiting to be processed. By default, this flag is not set. -
The minidriver’s processing dispatch callback routine returns STATUS_PENDING, regardless of frame availability. Note that the processing dispatch can be either
AVStrMiniFilterProcess
or
AVStrMiniPinProcess
, depending on whether the minidriver implements
pin-centric processing
or
filter-centric processing
.
AVStream initiates processing when new data arrives into a previouslyempty queue. Therefore, if the minidriver’s processing dispatch returnsSTATUS_PENDING when the associated queues are full, the minidriver will neverbe called on to resume processing. If the minidriver sets STATUS_PENDING, theminidriver must call
KsPinAttemptProcessing
or
KsFilterAttemptProcessing
to resume processing.
Do not return STATUS_SUCCESS from the processing dispatch if theminidriver does not actually process data. This causes AVStream to immediatelycall the minidriver again, resulting in an infinite loop between AVStream andthe processing dispatch.
AVStreamTesting and Debugging
In the Windows Server 2008 WDK, five tools are provided inthe
WDKPath\tools\avstream
folder hierarchy. This topic explains thepurpose and basic usage of each tool. In some cases, additional documentationis included in the folder hierarchy.
AMCap2
AMCap2.exe
(Active MovieCapture) is an application for enumerating and using audio and video capturedevices with the Microsoft DirectShow application programming interface.
AMCap2 includes one binary component:
AMCap2.exe
.
AMCap2 binaries are provided for x86-based and x64-basedarchitectures. AMCap2 runs on Microsoft Windows 2000, XP, Windows 2003 Server,and Vista.
When AMCap2 initializes, it enumerates available audio andvideo capture devices on its device menu. You can select none or one audioand/or video device. On the Settings menu, you can select specific device attributes.
For more information about DirectShow, see the DirectShowdocumentation on
MSDN
.
The
AMCap2.exe
tool has been removed from theWindows 7 WDK for both x86-based and x64-based platforms.
All the functionality of AMCap2 is still available in theexisting GraphEdt tool, which is included in the Windows 7 WDK.
GraphEdt
GraphEdt.exe
is adevelopment tool for visually building functional multimedia filter graphsusing the DirectShow application programming interface.
GraphEdt includes three binary components:
GraphEdt.exe
(the application),
GraphEdt.chm
(the help documentation), and
Proppage.dll
(a helper filter).
Proppage.dll
exposes additional property settings forfilters when registered with the operating system using the command”regsvr32 proppage.dll”. The regsvr32 command must be run at elevatedprivilege level.
GraphEdt binaries are provided for x86-based and x64-basedarchitectures. GraphEdt runs on Microsoft Windows 2000, XP, Windows 2003Server, and Vista.
KsStudio
KsStudio.exe
(KernelStreaming Development Studio) is a development tool used to examine multimediadriver properties, pins, and supported media.
KsStudio binaries are provided for Microsoft Windows Vistaon the x86-based and x64-based architectures. There is a version for Windows XPand Windows 2003 Server in the XP folder (for both x86 and x64). For Vista, thebinaries are
KsStudio.exe
(the application),
KsStudio.chm
(thehelp documentation), and
KsMon.sys
(a helper device driver). For XP andWindows 2003 Server, there is also S
ndAnlyz.dll
(a helper file).
KsStudio is a kernel development tool, and therefore shouldbe used carefully.
KsStudio.exe
must write a summary log to the startingdirectory, which must have write access for the user. KsStudio attempts to loadits helper driver
KsMon.sys
. This loading is optional and will onlysucceed if
KsMon.sys
is in the starting directory and the command is runat elevated privilege level. Typically, KsStudio will present a dialog boxtitled “KS Studio Filter Options,” which allows the user to specifyparameters, the most important of which are the Classes to enumerate. Use the
Classes
button on that dialog box to select none, any, or all classes.
This is a complex, yet elegant, and very handy developmenttool for multimedia device authors. For more information, refer to the
KsStudio.chm
help file.
MCStream
MCStream.exe
(MultiChannelStreaming Tool) is a development tool that allows the user to generate andrender multiple channel wave tones. MCStream is an older tool that uses KSdirectly, instead of DirectShow or Media Foundation.
Note
MCStreamdoes not work with all audio renderers.
MCStream includes two binary components:
MCStream.exe
(the application) and
MCStream.txt
(the help documentation).
MCStream binaries are provided for x86-based and x64-basedarchitectures. MCStream runs on Microsoft Windows 2000, XP, Windows 2003Server, and Vista.
The
MCstream.exe
tool is not included in theWindows 7 WDK for both x86-based and x64-based platforms.
This tool uses legacy technology that is no longerrecommended for driver development in Windows 7 and later operatingsystems.
UVCView
UVCView.exe
(USB Video Classdescriptor viewer) is a development tool that allows the user to examine thedescriptors on any attached USB device. UVCView is a variation on USBView,which ships in this Windows Driver Kit (WDK) as a sample in the USB section.UVCView adds descriptive descriptor information for multimedia USB Audio andVideo Class devices.
UVCView includes one binary component:
UVCView.exe
.In the Windows Server 2008 WDK, this executable is located in the
tools\avstream
folder hierarchy. For documentation, see the USBView sample in
WDKPath\src\usb\usbview
.
UVCView binaries are provided for x86-based and x64-basedarchitectures. UVCView runs on Microsoft Windows 2000, XP, Windows 2003 Server,and Vista.
VideoCapture Devices
This section describes how to create video captureminidrivers, which follow the Windows Driver Model (WDM) architecture. Itassumes familiarity with concepts discussed in
KernelStreaming
. For information on creating a minidriver for audio-only devices,the
Audiodevices Design Guide
.
With the integration of DVD, MPEG decoders, video decodersand tuners, video port extensions (VPEs), and audio codecs on single adapters,a unified driver model that supports all these devices and handles resourcecontention simplifies development efforts.
The
AVStream
and
Streamclass
interfaces both provide a framework that provide support forintegrated devices. These interfaces support data transfer between kernel-modedrivers. These data transfers do not require a thread to transition to usermode, thereby avoiding a performance hit.
Both interfaces support a uniform streaming model forstandard and custom data types. Microsoft defines property sets for moststandard devices. Vendors can provide additional property sets if needed.
Microsoft recommends that all new video capture drivers usethe AVStream interface. Microsoft provides the Stream class interface forbackwards compatibility. However, the Stream class interface is obsolete, andMicrosoft has discontinued its further development.
Note
: Thissection does not describe the obsolete Video for Windows (VfW) technology. VfWwas optimized for capturing movies to disk. Features important to videoconferencing, TV viewing, capture of video fields, and ancillary data streamsare missing from the VfW architecture. To circumvent these limitations, vendorshave added proprietary extensions to VfW. However, without standardizedinterfaces, applications that use these features must includehardware-dependent code.
To bridge the VfW and WDM driver models,Microsoft provides a VfW-to-WDM mapper as part of the operating system. Thiscomponent enables WDM drivers to appear as VfW drivers for legacy VfWapplications.
This section includes:
ImplementingVideo Capture Support
For more information about WDM video capture driverdevelopment, see the
videocapture technologies
Web site.
Video capture minidrivers interact with either the AVStream of Streamclass interfaces to control hardware devices that primarily produce streams ofvideo data, along with ancillary data such as TV audio, or AM/FM tunerfunctionality. Vendors write a video capture minidriver to:
- Capture compressed and uncompressed video streams from digital and analog video sources, such as IEEE 1394, USB, S-Video, and RCA video-in jacks.
- Capture vertical blanking interval (VBI) data.
- Capture ancillary data streams, such as TV audio or AM/FM tuner audio.
- Capture timecode.
- Control video ports and capture video from video port streams.
- Control devices associated with video streams such as TV/radio tuners, signal routing devices (crossbars), TV audio control, and video compressors.
- Control camera properties such as zoom, pan, and focus.
- Control video properties such as hue, saturation, brightness, and sharpness.
- Provide WDM streaming (for kernel mode) and DirectShow (for user mode) compatibility.
ImplementingVideo Capture Support
The following sections describe the general steps a Streamclass minidriver follows to implement video capture:
Registeringwith the Stream Class Interface
Registering with the Stream Class Interface
Stream class minidrivers use the following steps to initialize and prepareto stream data:
- The hardware adapter supported by the minidriver is detected by the Plug and Play manager.
-
The Plug and Play manager loads the minidriver and calls the minidriver’s
DriverEntry
routine. A file object is created from the information in the
DriverEntry
routine. -
The minidriver calls the Stream class interface’s
StreamClassRegisterMinidriver
function from its
DriverEntry
routine and passes a properly initialized
HW_INITIALIZATION_DATA
structure as a parameter. The HW_INITIALIZATION_DATA structure includes the addresses of minidriver functions that handle stream request block (SRB) command codes. This allows the minidriver to respond to SRB codes sent by the Stream class interface. A complete list of SRB command codes supported by the stream class is documented in the
Stream Class SRB Reference
.
Selectinga Stream Format
Video capture devices can capture video in a number ofdifferent formats. The
KSDATARANGE
structure is used to convey information about the width, height, granularity,cropping, and frame rates for a particular color space. The structures
KS_DATARANGE_VIDEO
and
KS_DATARANGE_VIDEO2
are extensions of the KSDATARANGE structure and should be used for describingvideo capture formats. Use KS_DATARANGE_VIDEO to describe video frames only.Use KS_DATARANGE_VIDEO2 to describe video fields and video frames, with orwithout bob or weave settings.
The process of selecting a stream format is called
performinga data intersection
. The Stream class interface sends an
SRB_GET_DATA_INTERSECTION
request to a Stream class minidriver to perform a data intersection. Theminidriver is responsible for determining the validity of the data rangerequested and then selecting a particular stream format from the supplied datarange, typically using
KS_DATAFORMAT_VIDEOINFOHEADER
or
KS_DATAFORMAT_VIDEOINFOHEADER2
structures.
Finally, the minidriver must set certain members of theresulting format as shown below:
.
.
.
// Calculate biSizeImage for this request, and put the result in both
// the biSizeImage field of the bmiHeader AND in the SampleSize field
// of the DataFormat.
//
// Note that for compressed sizes, this calculation will probably not
// be just width * height * bitdepth
DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);
Openingand Closing a Stream
The Stream class interface sends an
SRB_OPEN_STREAM
request to a Stream class minidriver to open a stream with the selected videoformat. Information passed in SRB_OPEN_STREAM includes the index of the streamto be open and a pointer to a pointer to a
KS_VIDEOINFOHEADER
structure. The stream index corresponds to the index of the stream in the arrayof
KS_DATARANGE_VIDEO
structures returned by the minidriver in response to an earlier
SRB_GET_STREAM_INFO
request. For more information about handling SRB_GET_STREAM_INFO, see
StreamCategories
.
The following example code obtains the stream index, kernelstreaming data format, and kernel streaming video info header.
int StreamNumber = pSrb->StreamObject->StreamNumber;
PKS_DATAFORMAT_VIDEOINFOHEADER pKSDataFormat =
(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
PKS_VIDEOINFOHEADER pVideoInfoHdrRequested =
&pKSDataFormat->VideoInfoHeader;
Minidrivers should verify that they can support therequested stream format. In particular, the contents of the
KS_BITMAPINFOHEADER
structure should be verified, along with cropping and scaling informationspecified by the
rcSource
and
rcTarget
members.
If the device hardware cannot support the capture framerate requested in the
AvgTimePerFrame
member of KS_VIDEOINFOHEADER, itshould always select the next
lower
frame rate available. For example,if a camera can support a capture frame rate of 7 frames per second (fps) and15 fps, and a client application attempts to open the stream at a capture framerate of 10 fps, the camera should create a 7-fps physical stream.
For a ten-second capture in which all 70 available physicalframes are captured, the minidriver should report 100 frames captured, 30frames of which were dropped by the
KSPROPERTY_DROPPEDFRAMES_CURRENT
property.
Special rules apply when the output buffer is a DirectDrawsurface. In this case, the
biWidth
member of the KS_BITMAPINFOHEADERstructure actually represents the stride of the destination DirectDraw surface,which typically is larger than the video image width. The stride of a surfaceis usually the width of the surface multiplied by its byte-depth. For example,for a surface that is 640 pixels wide with a color depth of 32 bits-per-pixel,the stride would be 2560 bytes.
To determine the requested image width, use the followingcode example:
if (IsRectEmpty(&pVideoInfoHdrRequested->rcTarget) {
Width = pVideoInfoHdrRequested->bmiHeader.biWidth;
Height = pVideoInfoHdrRequested->bmiHeader.biHeight;
}
else {
Width = pVideoInfoHdrRequested->rcTarget.right −
pVideoInfoHdrRequested->rcTarget.left;
Height = pVideoInfoHdrRequested->rcTarget.bottom −
pVideoInfoHdrRequested->rcTarget.top;
}
The Stream class interface sends an
SRB_CLOSE_STREAM
request to the minidriver to close a stream. The minidriver should then returnall outstanding stream SRBs to the Stream class interface.
Each stream provided by the minidriver exists in one of four states:KSSTATE_STOP, KSSTATE_ACQUIRE, KSSTATE_PAUSE, or KSSTATE_RUN. Uponinitialization, the stream is, by default, in the KSSTATE_STOP state.Transitions to the other states are made when the Stream class interface sendsan
SRB_SET_STREAM_STATE
request tothe minidriver. The following table identifies and describes the four streamstates.
|
|
KSSTATE_STOP |
When the stream state is stopped, the minidriver uses the absolute minimum of resources, and there are no outstanding data SRBs in the minidriver’s queue. |
KSSTATE_ACQUIRE |
When the stream state is acquiring resources, the minidriver allocates all needed resources, such as bandwidth on USB and IEEE 1394. |
KSSTATE_PAUSE |
When the stream state is paused, the minidriver is prepared to instantly make a transition to KSSTATE_RUN. |
KSSTATE_RUN |
When the stream state is streaming, the minidriver fills buffers and completes SRBs using |
To ensure orderly resource allocation, only a subset of the possiblekernel streaming state transitions is allowed. The following table lists theallowed transitions along with tasks that a Stream class minidriver typicallyperforms during such transitions.
|
|
Stop to pause |
Allocate resources. The read SRBs are queued after the transition to KSSTATE_PAUSE has completed. |
Pause to run |
Begin streaming. |
Run to pause |
Stop streaming. The outstanding read SRBs remain in the queue maintained by the minidriver. |
Pause to stop |
Deallocate resources and complete all outstanding read SRBs. SRBs that have not been filled with an image are completed with zero length in the |
Note
: Transitions can cycle multipletimes between the KSSTATE_PAUSE and KSSTATE_RUN states before returning to theKSSTATE_STOP state. Video capture minidrivers should expect transitions suchas:
KSSTATE_STOP -> KSSTATE_ACQUIRE -> KSSTATE_PAUSE -> KSSTATE_RUN-> KSSTATE_PAUSE -> KSSTATE_RUN -> KSSTATE_PAUSE -> KSSTATE_STOP
When a stream is in a KSSTATE_STOP state, the minidriver must immediatelycomplete all outstanding data-read SRBs.
Because a user-mode application can end unexpectedly while streaming, allStream class minidrivers must accept and process an
SRB_CLOSE_STREAM
request from theStream class interface at any time. Before the Stream class interface sends SRB_CLOSE_STREAMto a minidriver, it cancels all outstanding buffers through the minidriver’s
HwCancelPacket
routine. Note that the stream state cannot be set to KSSTATE_STOP before theapplication terminates.
Do not update the
PictureNumber
or
DropCount
members of
KS_FRAME_INFO
,
KS_VBI_FRAME_INFO
, or
KSPROPERTY_DROPPEDFRAMES_CURRENT_S
on transition from KSSTATE_PAUSE to KSSTATE_RUN or KSSTATE_RUN toKSSTATE_PAUSE. For more information, see
Capturing Video
.
CapturingVideo
Once the stream is in the KSSTATE_RUN state, the captureprocess begins. Based on the frame interval specified by the
AvgTimePerFrame
member of the
KS_VIDEOINFOHEADER
structure passed when the stream is opened, the stream transfers images intobuffers passed through SRB_READ_DATA. Additional information about the imagecaptured is returned in the
KS_FRAME_INFO
structure that is appended to the end of the
KSSTREAM_HEADER
structure.
The following example code obtains the appendedKS_FRAME_INFO structure:
PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
PKS_FRAME_INFO pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
A minidriver should set additional information fields aboutthe data captured, such as frames captured, frames dropped, and field polarity.The frame information is generally stored in a member of the driver-writerdefined stream extension.
*pFrameInfo = pStrmEx->FrameInfo; // Get the frame info from the minidriver-defined stream extension
It is optimal to update the
PictureNumber
or
DropCount
members of
KS_FRAME_INFO
,
KS_VBI_FRAME_INFO
,or
KSPROPERTY_DROPPEDFRAMES_CURRENT_S
at transition into the KSSTATE_ACQUIRE state.
It is acceptable to update these members on transition fromthe KSSTATE_ACQUIRE state into the KSSTATE_PAUSE state.
Do not update
PictureNumber
or
DropCount
ontransition from the KSSTATE_PAUSE state to the KSSTATE_RUN state or theKSSTATE_RUN state to the KSSTATE_PAUSE state.
If frames have been previously dropped, the minidrivershould set the discontinuity flag and then reset its internal flag. Thefollowing code demonstrates setting the data discontinuity flag:
if (pStrmEx->fDiscontinuity) {
pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
pStrmEx->fDiscontinuity = FALSE;
}
Finally, the minidriver should relinquish control of theSRB, completing the frame capture.
CompleteStreamSRB (pSrb);