summaryrefslogtreecommitdiff
path: root/avstream/avssamp/video.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'avstream/avssamp/video.cpp')
-rw-r--r--avstream/avssamp/video.cpp1433
1 files changed, 0 insertions, 1433 deletions
diff --git a/avstream/avssamp/video.cpp b/avstream/avssamp/video.cpp
deleted file mode 100644
index d2291a24..00000000
--- a/avstream/avssamp/video.cpp
+++ /dev/null
@@ -1,1433 +0,0 @@
-/**************************************************************************
-
- AVStream Filter-Centric Sample
-
- Copyright (c) 1999 - 2001, Microsoft Corporation
-
- File:
-
- video.cpp
-
- Abstract:
-
- This file contains the video capture pin implementation.
-
- History:
-
- created 6/11/01
-
-**************************************************************************/
-
-#include "avssamp.h"
-
-/**************************************************************************
-
- PAGEABLE CODE
-
-**************************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma code_seg("PAGE")
-#endif // ALLOC_PRAGMA
-
-NTSTATUS
-CVideoCapturePin::
-DispatchCreate (
- IN PKSPIN Pin,
- IN PIRP Irp
- )
-
-/*++
-
-Routine Description:
-
- Create a new video capture pin. This is the creation dispatch for
- the video capture pin.
-
-Arguments:
-
- Pin -
- The pin being created
-
- Irp -
- The creation Irp
-
-Return Value:
-
- Success / Failure
-
---*/
-
-{
-
- PAGED_CODE();
-
- NTSTATUS Status = STATUS_SUCCESS;
-
- CVideoCapturePin *CapPin = new (NonPagedPool) CVideoCapturePin (Pin);
- CCapturePin *BasePin = static_cast <CCapturePin *> (CapPin);
-
- if (!CapPin) {
- //
- // Return failure if we couldn't create the pin.
- //
- Status = STATUS_INSUFFICIENT_RESOURCES;
-
- } else {
- //
- // Add the item to the object bag if we we were successful.
- // Whenever the pin closes, the bag is cleaned up and we will be
- // freed.
- //
- Status = KsAddItemToObjectBag (
- Pin -> Bag,
- reinterpret_cast <PVOID> (BasePin),
- reinterpret_cast <PFNKSFREE> (CCapturePin::BagCleanup)
- );
-
- if (!NT_SUCCESS (Status)) {
- delete CapPin;
- } else {
- Pin -> Context = reinterpret_cast <PVOID> (BasePin);
- }
-
- }
-
- //
- // If we succeeded so far, stash the video info header away and change
- // our allocator framing to reflect the fact that only now do we know
- // the framing requirements based on the connection format.
- //
- PKS_VIDEOINFOHEADER VideoInfoHeader = NULL;
-
- if (NT_SUCCESS (Status)) {
-
- VideoInfoHeader = CapPin -> CaptureVideoInfoHeader ();
- if (!VideoInfoHeader) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- }
-
- if (NT_SUCCESS (Status)) {
-
- //
- // We need to edit the descriptor to ensure we don't mess up any other
- // pins using the descriptor or touch read-only memory.
- //
- Status = KsEdit (Pin, &Pin -> Descriptor, 'aChS');
-
- if (NT_SUCCESS (Status)) {
- Status = KsEdit (
- Pin,
- &(Pin -> Descriptor -> AllocatorFraming),
- 'aChS'
- );
- }
-
- //
- // If the edits proceeded without running out of memory, adjust
- // the framing based on the video info header.
- //
- if (NT_SUCCESS (Status)) {
-
- //
- // We've KsEdit'ed this... I'm safe to cast away constness as
- // long as the edit succeeded.
- //
- PKSALLOCATOR_FRAMING_EX Framing =
- const_cast <PKSALLOCATOR_FRAMING_EX> (
- Pin -> Descriptor -> AllocatorFraming
- );
-
- Framing -> FramingItem [0].Frames = 2;
-
- //
- // The physical and optimal ranges must be biSizeImage. We only
- // support one frame size, precisely the size of each capture
- // image.
- //
- Framing -> FramingItem [0].PhysicalRange.MinFrameSize =
- Framing -> FramingItem [0].PhysicalRange.MaxFrameSize =
- Framing -> FramingItem [0].FramingRange.Range.MinFrameSize =
- Framing -> FramingItem [0].FramingRange.Range.MaxFrameSize =
- VideoInfoHeader -> bmiHeader.biSizeImage;
-
- Framing -> FramingItem [0].PhysicalRange.Stepping =
- Framing -> FramingItem [0].FramingRange.Range.Stepping =
- 0;
-
- }
-
- }
-
- if (NT_SUCCESS (Status)) {
- //
- // Adjust the stream header size. The video packets have extended
- // header info (KS_FRAME_INFO).
- //
- Pin -> StreamHeaderSize = sizeof (KSSTREAM_HEADER) +
- sizeof (KS_FRAME_INFO);
-
- }
-
- return Status;
-
-}
-
-/*************************************************/
-
-
-PKS_VIDEOINFOHEADER
-CVideoCapturePin::
-CaptureVideoInfoHeader (
- )
-
-/*++
-
-Routine Description:
-
- Capture the video info header out of the connection format. This
- is what we use to base synthesized images off.
-
-Arguments:
-
- None
-
-Return Value:
-
- The captured video info header or NULL if there is insufficient
- memory.
-
---*/
-
-{
-
- PAGED_CODE();
-
- PKS_VIDEOINFOHEADER ConnectionHeader =
- &((reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER>
- (m_Pin -> ConnectionFormat)) ->
- VideoInfoHeader);
-
- m_VideoInfoHeader = reinterpret_cast <PKS_VIDEOINFOHEADER> (
- ExAllocatePoolWithTag (
- NonPagedPool,
- KS_SIZE_VIDEOHEADER (ConnectionHeader),
- AVSSMP_POOLTAG
- )
- );
-
- if (!m_VideoInfoHeader)
- return NULL;
-
- //
- // Bag the newly allocated header space. This will get cleaned up
- // automatically when the pin closes.
- //
- NTSTATUS Status =
- KsAddItemToObjectBag (
- m_Pin -> Bag,
- reinterpret_cast <PVOID> (m_VideoInfoHeader),
- NULL
- );
-
- if (!NT_SUCCESS (Status)) {
-
- ExFreePool (m_VideoInfoHeader);
- return NULL;
-
- } else {
-
- //
- // Copy the connection format video info header into the newly
- // allocated "captured" video info header.
- //
- RtlCopyMemory (
- m_VideoInfoHeader,
- ConnectionHeader,
- KS_SIZE_VIDEOHEADER (ConnectionHeader)
- );
-
- }
-
- return m_VideoInfoHeader;
-
-}
-
-/*************************************************/
-
-
-NTSTATUS
-CVideoCapturePin::
-IntersectHandler (
- IN PKSFILTER Filter,
- IN PIRP Irp,
- IN PKSP_PIN PinInstance,
- IN PKSDATARANGE CallerDataRange,
- IN PKSDATARANGE DescriptorDataRange,
- IN ULONG BufferSize,
- OUT PVOID Data OPTIONAL,
- OUT PULONG DataSize
- )
-
-/*++
-
-Routine Description:
-
- This routine handles video pin intersection queries by determining the
- intersection between two data ranges.
-
-Arguments:
-
- Filter -
- Contains a void pointer to the filter structure.
-
- Irp -
- Contains a pointer to the data intersection property request.
-
- PinInstance -
- Contains a pointer to a structure indicating the pin in question.
-
- CallerDataRange -
- Contains a pointer to one of the data ranges supplied by the client
- in the data intersection request. The format type, subtype and
- specifier are compatible with the DescriptorDataRange.
-
- DescriptorDataRange -
- Contains a pointer to one of the data ranges from the pin descriptor
- for the pin in question. The format type, subtype and specifier are
- compatible with the CallerDataRange.
-
- BufferSize -
- Contains the size in bytes of the buffer pointed to by the Data
- argument. For size queries, this value will be zero.
-
- Data -
- Optionally contains a pointer to the buffer to contain the data
- format structure representing the best format in the intersection
- of the two data ranges. For size queries, this pointer will be
- NULL.
-
- DataSize -
- Contains a pointer to the location at which to deposit the size
- of the data format. This information is supplied by the function
- when the format is actually delivered and in response to size
- queries.
-
-Return Value:
-
- STATUS_SUCCESS if there is an intersection and it fits in the supplied
- buffer, STATUS_BUFFER_OVERFLOW for successful size queries,
- STATUS_NO_MATCH if the intersection is empty, or
- STATUS_BUFFER_TOO_SMALL if the supplied buffer is too small.
-
---*/
-
-{
- PAGED_CODE();
-
- const GUID VideoInfoSpecifier =
- {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
-
- NT_ASSERT(Filter);
- NT_ASSERT(Irp);
- NT_ASSERT(PinInstance);
- NT_ASSERT(CallerDataRange);
- NT_ASSERT(DescriptorDataRange);
- NT_ASSERT(DataSize);
-
- ULONG DataFormatSize;
-
- //
- // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
- //
- if (IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier) &&
- CallerDataRange->FormatSize >= sizeof (KS_DATARANGE_VIDEO)) {
-
- PKS_DATARANGE_VIDEO callerDataRange =
- reinterpret_cast <PKS_DATARANGE_VIDEO> (CallerDataRange);
-
- PKS_DATARANGE_VIDEO descriptorDataRange =
- reinterpret_cast <PKS_DATARANGE_VIDEO> (DescriptorDataRange);
-
- PKS_DATAFORMAT_VIDEOINFOHEADER FormatVideoInfoHeader;
-
- //
- // Check that the other fields match
- //
- if ((callerDataRange->bFixedSizeSamples !=
- descriptorDataRange->bFixedSizeSamples) ||
- (callerDataRange->bTemporalCompression !=
- descriptorDataRange->bTemporalCompression) ||
- (callerDataRange->StreamDescriptionFlags !=
- descriptorDataRange->StreamDescriptionFlags) ||
- (callerDataRange->MemoryAllocationFlags !=
- descriptorDataRange->MemoryAllocationFlags) ||
- (RtlCompareMemory (&callerDataRange->ConfigCaps,
- &descriptorDataRange->ConfigCaps,
- sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
- sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
- {
- return STATUS_NO_MATCH;
- }
-
- //
- // KS_SIZE_VIDEOHEADER() below is relying on bmiHeader.biSize from
- // the caller's data range. This **MUST** be validated; the
- // extended bmiHeader size (biSize) must not extend past the end
- // of the range buffer. Possible arithmetic overflow is also
- // checked for.
- //
- {
- ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
- &callerDataRange->VideoInfoHeader
- );
-
- ULONG DataRangeSize =
- FIELD_OFFSET (KS_DATARANGE_VIDEO, VideoInfoHeader) +
- VideoHeaderSize;
-
- //
- // Check that biSize does not extend past the buffer. The
- // first two checks are for arithmetic overflow on the
- // operations to compute the alleged size. (On unsigned
- // math, a+b < a iff an arithmetic overflow occurred).
- //
- if (
- VideoHeaderSize < callerDataRange->
- VideoInfoHeader.bmiHeader.biSize ||
- DataRangeSize < VideoHeaderSize ||
- DataRangeSize > callerDataRange -> DataRange.FormatSize
- ) {
-
- return STATUS_INVALID_PARAMETER;
-
- }
-
- }
-
- DataFormatSize =
- sizeof (KSDATAFORMAT) +
- KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader);
-
- //
- // If the passed buffer size is 0, it indicates that this is a size
- // only query. Return the size of the intersecting data format and
- // pass back STATUS_BUFFER_OVERFLOW.
- //
- if (BufferSize == 0) {
-
- *DataSize = DataFormatSize;
- return STATUS_BUFFER_OVERFLOW;
-
- }
-
- //
- // Verify that the provided structure is large enough to
- // accept the result.
- //
- if (BufferSize < DataFormatSize)
- {
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- //
- // Copy over the KSDATAFORMAT, followed by the actual VideoInfoHeader
- //
- *DataSize = DataFormatSize;
-
- FormatVideoInfoHeader = PKS_DATAFORMAT_VIDEOINFOHEADER( Data );
-
- //
- // Copy over the KSDATAFORMAT. This is precisely the same as the
- // KSDATARANGE (it's just the GUIDs, etc... not the format information
- // following any data format.
- //
- RtlCopyMemory (
- &FormatVideoInfoHeader->DataFormat,
- DescriptorDataRange,
- sizeof (KSDATAFORMAT));
-
- FormatVideoInfoHeader->DataFormat.FormatSize = DataFormatSize;
-
- //
- // Copy over the callers requested VIDEOINFOHEADER
- //
-
- RtlCopyMemory (
- &FormatVideoInfoHeader->VideoInfoHeader,
- &callerDataRange->VideoInfoHeader,
- KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader)
- );
-
- //
- // 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
- //
- FormatVideoInfoHeader->VideoInfoHeader.bmiHeader.biSizeImage =
- FormatVideoInfoHeader->DataFormat.SampleSize =
- KS_DIBSIZE (FormatVideoInfoHeader->VideoInfoHeader.bmiHeader);
-
- //
- // REVIEW - Perform other validation such as cropping and scaling checks
- //
-
- return STATUS_SUCCESS;
-
- } // End of VIDEOINFOHEADER specifier
-
- return STATUS_NO_MATCH;
-}
-
-/*************************************************/
-
-BOOL
-MultiplyCheckOverflow (
- ULONG a,
- ULONG b,
- ULONG *pab
- )
-
-/*++
-
-Routine Description:
-
- Perform a 32 bit unsigned multiplication and check for arithmetic overflow.
-
-Arguments:
-
- a -
- First operand
-
- b -
- Second operand
-
- pab -
- Result
-
-Return Value:
-
- TRUE -
- no overflow
-
- FALSE -
- overflow occurred
-
---*/
-
-{
- PAGED_CODE();
-
- *pab = a * b;
- if ((a == 0) || (((*pab) / a) == b)) {
- return TRUE;
- }
- return FALSE;
-}
-
-/*************************************************/
-
-
-NTSTATUS
-CVideoCapturePin::
-DispatchSetFormat (
- IN PKSPIN Pin,
- IN PKSDATAFORMAT OldFormat OPTIONAL,
- IN PKSMULTIPLE_ITEM OldAttributeList OPTIONAL,
- IN const KSDATARANGE *DataRange,
- IN const KSATTRIBUTE_LIST *AttributeRange OPTIONAL
- )
-
-/*++
-
-Routine Description:
-
- This is the set data format dispatch for the capture pin. It is called
- in two circumstances.
-
- 1: before Pin's creation dispatch has been made to verify that
- Pin -> ConnectionFormat is an acceptable format for the range
- DataRange. In this case OldFormat is NULL.
-
- 2: after Pin's creation dispatch has been made and an initial format
- selected in order to change the format for the pin. In this case,
- OldFormat will not be NULL.
-
- Validate that the format is acceptible and perform the actions necessary
- to change format if appropriate.
-
-Arguments:
-
- Pin -
- The pin this format is being set on. The format itself will be in
- Pin -> ConnectionFormat.
-
- OldFormat -
- The previous format used on this pin. If this is NULL, it is an
- indication that Pin's creation dispatch has not yet been made and
- that this is a request to validate the initial format and not to
- change formats.
-
- OldAttributeList -
- The old attribute list for the prior format
-
- DataRange -
- A range out of our list of data ranges which was determined to be
- at least a partial match for Pin -> ConnectionFormat. If the format
- there is unacceptable for the range, STATUS_NO_MATCH should be
- returned.
-
- AttributeRange -
- The attribute range
-
-Return Value:
-
- Success / Failure
-
- STATUS_SUCCESS -
- The format is acceptable / the format has been changed
-
- STATUS_NO_MATCH -
- The format is not-acceptable / the format has not been changed
-
---*/
-
-{
-
- PAGED_CODE();
-
- NTSTATUS Status = STATUS_NO_MATCH;
-
- const GUID VideoInfoSpecifier =
- {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
-
- CCapturePin *CapPin = NULL;
- CVideoCapturePin *VidCapPin = NULL;
-
- //
- // Find the pin, if it exists yet. OldFormat will be an indication of
- // this. If we're changing formats, OldFormat will be non-NULL.
- //
- // You cannot use Pin -> Context to make the determination. AVStream
- // preinitializes this to the filter's context.
- //
- if (OldFormat) {
- CapPin = reinterpret_cast <CCapturePin *> (Pin -> Context);
-
- //
- // We know this pin happens to be the video capture pin. Downcast it.
- //
- VidCapPin = static_cast <CVideoCapturePin *> (CapPin);
- }
-
- if (IsEqualGUID (Pin -> ConnectionFormat -> Specifier,
- VideoInfoSpecifier) &&
- Pin -> ConnectionFormat -> FormatSize >=
- sizeof (KS_DATAFORMAT_VIDEOINFOHEADER)
- ) {
-
- PKS_DATAFORMAT_VIDEOINFOHEADER ConnectionFormat =
- reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER>
- (Pin -> ConnectionFormat);
-
- //
- // DataRange comes out of OUR data range list. I know the range
- // is valid as such.
- //
- const KS_DATARANGE_VIDEO *VIRange =
- reinterpret_cast <const KS_DATARANGE_VIDEO *>
- (DataRange);
-
- //
- // Check that bmiHeader.biSize is valid since we use it later.
- //
- ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
- &ConnectionFormat -> VideoInfoHeader
- );
-
- ULONG DataFormatSize = FIELD_OFFSET (
- KS_DATAFORMAT_VIDEOINFOHEADER, VideoInfoHeader
- ) + VideoHeaderSize;
-
- if (
- VideoHeaderSize < ConnectionFormat->
- VideoInfoHeader.bmiHeader.biSize ||
- DataFormatSize < VideoHeaderSize ||
- DataFormatSize > ConnectionFormat -> DataFormat.FormatSize
- ) {
-
- Status = STATUS_INVALID_PARAMETER;
-
- }
-
- //
- // Check that the format is a match for the selected range.
- //
- else if (
- (ConnectionFormat -> VideoInfoHeader.bmiHeader.biWidth !=
- VIRange -> VideoInfoHeader.bmiHeader.biWidth) ||
-
- (ConnectionFormat -> VideoInfoHeader.bmiHeader.biHeight !=
- VIRange -> VideoInfoHeader.bmiHeader.biHeight) ||
-
- (ConnectionFormat -> VideoInfoHeader.bmiHeader.biCompression !=
- VIRange -> VideoInfoHeader.bmiHeader.biCompression)
- ) {
-
- Status = STATUS_NO_MATCH;
-
- } else {
-
- //
- // Compute the minimum size of our buffers to validate against.
- // The image synthesis routines synthesize |biHeight| rows of
- // biWidth pixels in either RGB24 or UYVY. In order to ensure
- // safe synthesis into the buffer, we need to know how large an
- // image this will produce.
- //
- // I do this explicitly because of the method that the data is
- // synthesized. A variation of this may or may not be necessary
- // depending on the mechanism the driver in question fills the
- // capture buffers. The important thing is to ensure that they
- // aren't overrun during capture.
- //
- ULONG ImageSize;
-
- if (!MultiplyCheckOverflow (
- (ULONG)ConnectionFormat->VideoInfoHeader.bmiHeader.biWidth,
- (ULONG)abs (ConnectionFormat->
- VideoInfoHeader.bmiHeader.biHeight),
- &ImageSize
- )) {
-
- Status = STATUS_INVALID_PARAMETER;
- }
-
- //
- // We only support KS_BI_RGB (24) and KS_BI_YUV422 (16), so
- // this is valid for those formats.
- //
- else if (!MultiplyCheckOverflow (
- ImageSize,
- (ULONG)(ConnectionFormat->
- VideoInfoHeader.bmiHeader.biBitCount / 8),
- &ImageSize
- )) {
-
- Status = STATUS_INVALID_PARAMETER;
-
- }
-
- //
- // Valid for the formats we use. Otherwise, this would be
- // checked later.
- //
- else if (ConnectionFormat->VideoInfoHeader.bmiHeader.biSizeImage <
- ImageSize) {
-
- Status = STATUS_INVALID_PARAMETER;
-
- } else {
-
- //
- // We can accept the format.
- //
- Status = STATUS_SUCCESS;
-
- //
- // OldFormat is an indication that this is a format change.
- // Since I do not implement the
- // KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT, by default, I do
- // not handle dynamic format changes.
- //
- // If something changes while we're in the stop state, we're
- // fine to handle it since we haven't "configured the hardware"
- // yet.
- //
- if (OldFormat) {
- //
- // If we're in the stop state, we can handle just about any
- // change. We don't support dynamic format changes.
- //
- if (Pin -> DeviceState == KSSTATE_STOP) {
- if (!VidCapPin -> CaptureVideoInfoHeader ()) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
- } else {
- //
- // Because we don't accept dynamic format changes, we
- // should never get here. Just being over-protective.
- //
- Status = STATUS_INVALID_DEVICE_STATE;
- }
-
- }
-
- }
-
- }
-
- }
-
- return Status;
-
-}
-
-/*************************************************/
-
-
-NTSTATUS
-CVideoCapturePin::
-Pause (
- IN KSSTATE FromState
- )
-
-/*++
-
-Routine Description:
-
- Called when the pin transitions into the pause state. If we're in an
- upward transition, start the capture DPC. Note that we do not actually
- trigger capture in the pause state, but we start up our DPC.
-
-Arguments:
-
- FromState -
- The state that the pin is transitioning away from. This is either
- KSSTATE_ACQUIRE, indicating an upward transition, or KSSTATE_RUN,
- indicating a downward transition.
-
-Return Value:
-
- STATUS_SUCCESS
-
---*/
-
-{
-
- PAGED_CODE();
-
- //
- // On the transition from acquire -> pause, start the timer DPC running.
- //
- if (FromState == KSSTATE_ACQUIRE) {
- m_ParentFilter -> StartDPC (m_VideoInfoHeader -> AvgTimePerFrame);
- }
-
- return STATUS_SUCCESS;
-
-}
-
-/*************************************************/
-
-
-NTSTATUS
-CVideoCapturePin::
-Acquire (
- IN KSSTATE FromState
- )
-
-/*++
-
-Routine Description:
-
- This is called from the base class when the video capture pin transitions
- into the acquire state (from either Stop or Pause). The state the pin
- transitioned from is passed in.
-
- During this phase, the video capture pin creates the image synthesizer
- and initializes it.
-
-Arguments:
-
- FromState -
- The state transitioning from (KSSTATE_STOP or KSSTATE_PAUSE)
-
-Return Value:
-
- Success / Failure
-
---*/
-
-{
-
- PAGED_CODE();
-
- NT_ASSERT (m_VideoInfoHeader);
-
- NTSTATUS Status = STATUS_SUCCESS;
-
- if (FromState == KSSTATE_STOP) {
-
- m_SynthesisBuffer = reinterpret_cast <PUCHAR> (
- ExAllocatePoolWithTag (
- NonPagedPool,
- m_VideoInfoHeader -> bmiHeader.biSizeImage,
- AVSSMP_POOLTAG
- )
- );
-
- if (!m_SynthesisBuffer) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- } else {
- //
- // Determine the necessary type of image synthesizer to create
- // based on the format that has been set on this pin.
- //
- if (m_VideoInfoHeader -> bmiHeader.biBitCount == 24 &&
- m_VideoInfoHeader -> bmiHeader.biCompression == KS_BI_RGB) {
-
- //
- // If we're RGB24, create a new RGB24 synth. RGB24 surfaces
- // can be in either orientation. The origin is lower left if
- // height < 0. Otherwise, it's upper left.
- //
- m_ImageSynth = new (NonPagedPool, 'RysI')
- CRGB24Synthesizer (
- m_VideoInfoHeader -> bmiHeader.biHeight >= 0,
- m_VideoInfoHeader -> bmiHeader.biWidth,
- ABS (m_VideoInfoHeader -> bmiHeader.biHeight)
- );
-
- } else
- if (m_VideoInfoHeader -> bmiHeader.biBitCount == 16 &&
- m_VideoInfoHeader -> bmiHeader.biCompression == FOURCC_YUV422) {
-
- //
- // If we're UYVY, create the YUV synth.
- //
- m_ImageSynth = new (NonPagedPool, 'YysI') CYUVSynthesizer (
- m_VideoInfoHeader -> bmiHeader.biWidth,
- m_VideoInfoHeader -> bmiHeader.biHeight
- );
-
- } else
- //
- // We don't synthesize anything but RGB 24 and UYVY.
- //
- Status = STATUS_INVALID_PARAMETER;
-
- if (NT_SUCCESS (Status) && !m_ImageSynth) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- }
-
- }
-
- //
- // Bag the image synthesizer.
- //
- if (NT_SUCCESS (Status)) {
-
- Status = KsAddItemToObjectBag (
- m_Pin -> Bag,
- m_ImageSynth,
- reinterpret_cast <PFNKSFREE> (CVideoCapturePin::CleanupSynth)
- );
-
- }
-
- //
- // If everything is okay at this point, inform the synthesizer of
- // the scratch buffer.
- //
- if (NT_SUCCESS (Status)) {
- m_ImageSynth -> SetBuffer (m_SynthesisBuffer);
- }
-
- } else {
-
- //
- // The only other state we can come from is pause. If we're in a
- // downward state transition below pause, tell the filter to stop the
- // capture DPC.
- //
- m_ParentFilter -> StopDPC ();
-
- }
-
- return Status;
-
-}
-
-/*************************************************/
-
-
-NTSTATUS
-CVideoCapturePin::
-Stop (
- IN KSSTATE FromState
- )
-
-/*++
-
-Routine Description:
-
- Called when the video capture pin transitions from acquire to stop.
- This function will clean up the image synth and any data structures
- that we need to clean up on stop.
-
-Arguments:
-
- FromState -
- The state the pin is transitioning away from. This should
- always be KSSTATE_ACQUIRE for this call.
-
-Return Value:
-
- STATUS_SUCCESS
-
---*/
-
-{
- PAGED_CODE();
-
- NT_ASSERT (FromState == KSSTATE_ACQUIRE);
-
- //
- // Remove the image synthesizer from the object bag and free it.
- //
- KsRemoveItemFromObjectBag (
- m_Pin -> Bag,
- m_ImageSynth,
- TRUE
- );
-
- m_ImageSynth = NULL;
-
- if (m_SynthesisBuffer) {
- ExFreePool (m_SynthesisBuffer);
- m_SynthesisBuffer = NULL;
- }
-
- return STATUS_SUCCESS;
-
-}
-
-/**************************************************************************
-
- LOCKED CODE
-
-**************************************************************************/
-
-#ifdef ALLOC_PRAGMA
-#pragma code_seg()
-#endif // ALLOC_PRAGMA
-
-
-NTSTATUS
-CVideoCapturePin::
-CaptureFrame (
- IN PKSPROCESSPIN ProcessPin,
- IN ULONG Tick
- )
-
-/*++
-
-Routine Description:
-
- This routine is called from the filter processing function to capture
- a frame for the video capture pin. The process pin to capture to is
- passed.
-
-Arguments:
-
- ProcessPin -
- The process pin associated with this pin.
-
- Tick -
- The tick count on the filter. This is the number of timer DPC's that
- have fired since the timer DPC started.
-
-Return Value:
-
- STATUS_SUCCESS
-
---*/
-
-{
-
- NT_ASSERT (ProcessPin -> Pin == m_Pin);
-
- //
- // Increment the frame number. This is the total count of frames which
- // have attempted capture.
- //
- m_FrameNumber++;
-
- //
- // Since this pin is KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING, it
- // means that we do not require frames available in order to process.
- // This means that this routine can get called from our DPC with no
- // buffers available to capture into. In this case, we increment our
- // dropped frame counter and do nothing.
- //
- if (ProcessPin -> BytesAvailable) {
-
- //
- // Because we adjusted the allocator framing, each frame should be
- // sufficient to trigger capture of the appropriate buffer size.
- //
- NT_ASSERT (ProcessPin -> BytesAvailable >=
- m_VideoInfoHeader -> bmiHeader.biSizeImage);
-
- //
- // If we get an invalid buffer, kick it out.
- //
- if (ProcessPin -> BytesAvailable <
- m_VideoInfoHeader -> bmiHeader.biSizeImage) {
-
- ProcessPin -> BytesUsed = 0;
- ProcessPin -> Terminate = TRUE;
- m_DroppedFrames++;
- return STATUS_SUCCESS;
- }
-
- //
- // Generate a synthesized image.
- //
- m_ImageSynth -> SynthesizeBars ();
-
- //
- // Overlay some activity onto the bars.
- //
- ULONG DropLength = (Tick * 2) %
- (ABS (m_VideoInfoHeader -> bmiHeader.biHeight));
-
- //
- // Create a drop flowing down DropLength lines from the top of the
- // image.
- //
- m_ImageSynth -> Fill (
- 0, 0,
- m_VideoInfoHeader -> bmiHeader.biWidth - 1, DropLength,
- GREEN
- );
-
- //
- // Overlay the dropped frame count over the image.
- //
- char Text [256];
- Text[0] = '\0';
- RtlStringCbPrintfA(Text, sizeof(Text), "Video Skipped: %ld", m_DroppedFrames);
-
- m_ImageSynth -> OverlayText (
- 10,
- 10,
- 1,
- Text,
- TRANSPARENT,
- BLUE
- );
-
- //
- // This is used to indicate that there is no audio pin.
- //
- if (m_NotifyAudDrop != (ULONG)-1) {
- RtlStringCbPrintfA(Text, sizeof(Text), "Audio Skipped: %ld", m_NotifyAudDrop);
-
- m_ImageSynth -> OverlayText (
- 10,
- 20,
- 1,
- Text,
- TRANSPARENT,
- BLUE
- );
- }
-
- //
- // Copy the synthesized image into the buffer.
- //
- RtlCopyMemory (
- ProcessPin -> Data,
- m_SynthesisBuffer,
- m_VideoInfoHeader -> bmiHeader.biSizeImage
- );
-
- ProcessPin -> BytesUsed = m_VideoInfoHeader -> bmiHeader.biSizeImage;
- ProcessPin -> Terminate = TRUE;
-
-
- PKSSTREAM_HEADER StreamHeader =
- ProcessPin -> StreamPointer -> StreamHeader;
-
- //
- // If there is a clock assigned to the pin, time stamp the sample.
- //
- if (m_Clock) {
-
- StreamHeader -> PresentationTime.Time = GetTime ();
- StreamHeader -> Duration = m_VideoInfoHeader -> AvgTimePerFrame;
-
- StreamHeader -> OptionsFlags =
- KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
- KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
-
- }
-
- //
- // Update the extended header info.
- //
- NT_ASSERT (StreamHeader -> Size >= sizeof (KSSTREAM_HEADER) +
- sizeof (KS_FRAME_INFO));
-
- //
- // Double check the Stream Header size. AVStream makes no guarantee
- // that because StreamHeaderSize is set to a specific size that you
- // will get that size. If the proper data type handlers are not
- // installed, the stream header will be of default size.
- //
- if (StreamHeader -> Size >= sizeof (KSSTREAM_HEADER) +
- sizeof (KS_FRAME_INFO)) {
-
- PKS_FRAME_INFO FrameInfo = reinterpret_cast <PKS_FRAME_INFO> (
- StreamHeader + 1
- );
-
- FrameInfo -> ExtendedHeaderSize = sizeof (KS_FRAME_INFO);
- FrameInfo -> PictureNumber = (LONGLONG)m_FrameNumber;
- FrameInfo -> DropCount = (LONGLONG)m_DroppedFrames;
-
- }
-
- } else {
- m_DroppedFrames++;
- }
-
- return STATUS_SUCCESS;
-
-}
-
-/**************************************************************************
-
- DESCRIPTOR AND DISPATCH LAYOUT
-
-**************************************************************************/
-
-#define D_X 320
-#define D_Y 240
-
-//
-// FormatRGB24Bpp_Capture:
-//
-// This is the data range description of the RGB24 capture format we support.
-//
-const
-KS_DATARANGE_VIDEO
-FormatRGB24Bpp_Capture = {
-
- //
- // KSDATARANGE
- //
- {
- sizeof (KS_DATARANGE_VIDEO), // FormatSize
- 0, // Flags
- D_X * D_Y * 3, // SampleSize
- 0, // Reserved
-
- STATICGUIDOF (KSDATAFORMAT_TYPE_VIDEO), // aka. MEDIATYPE_Video
- 0xe436eb7d, 0x524f, 0x11ce, 0x9f, 0x53, 0x00, 0x20,
- 0xaf, 0x0b, 0xa7, 0x70, // aka. MEDIASUBTYPE_RGB24,
- STATICGUIDOF (KSDATAFORMAT_SPECIFIER_VIDEOINFO) // aka. FORMAT_VideoInfo
- },
-
- TRUE, // BOOL, bFixedSizeSamples (all samples same size?)
- TRUE, // BOOL, bTemporalCompression (all I frames?)
- 0, // Reserved (was StreamDescriptionFlags)
- 0, // Reserved (was MemoryAllocationFlags
- // (KS_VIDEO_ALLOC_*))
-
- //
- // _KS_VIDEO_STREAM_CONFIG_CAPS
- //
- {
- STATICGUIDOF( KSDATAFORMAT_SPECIFIER_VIDEOINFO ), // GUID
- KS_AnalogVideo_NTSC_M |
- KS_AnalogVideo_PAL_B, // AnalogVideoStandard
- 720,480, // InputSize, (the inherent size of the incoming signal
- // with every digitized pixel unique)
- 160,120, // MinCroppingSize, smallest rcSrc cropping rect allowed
- 720,480, // MaxCroppingSize, largest rcSrc cropping rect allowed
- 8, // CropGranularityX, granularity of cropping size
- 1, // CropGranularityY
- 8, // CropAlignX, alignment of cropping rect
- 1, // CropAlignY;
- 160, 120, // MinOutputSize, smallest bitmap stream can produce
- 720, 480, // MaxOutputSize, largest bitmap stream can produce
- 8, // OutputGranularityX, granularity of output bitmap size
- 1, // OutputGranularityY;
- 0, // StretchTapsX (0 no stretch, 1 pix dup, 2 interp...)
- 0, // StretchTapsY
- 0, // ShrinkTapsX
- 0, // ShrinkTapsY
- 333667, // MinFrameInterval, 100 nS units
- 640000000, // MaxFrameInterval, 100 nS units
- 8 * 3 * 30 * 160 * 120, // MinBitsPerSecond;
- 8 * 3 * 30 * 720 * 480 // MaxBitsPerSecond;
- },
-
- //
- // KS_VIDEOINFOHEADER (default format)
- //
- {
- 0,0,0,0, // RECT rcSource;
- 0,0,0,0, // RECT rcTarget;
- D_X * D_Y * 3 * 30, // DWORD dwBitRate;
- 0L, // DWORD dwBitErrorRate;
- 333667, // REFERENCE_TIME AvgTimePerFrame;
- sizeof (KS_BITMAPINFOHEADER), // DWORD biSize;
- D_X, // LONG biWidth;
- -D_Y, // LONG biHeight;
- 1, // WORD biPlanes;
- 24, // WORD biBitCount;
- KS_BI_RGB, // DWORD biCompression;
- D_X * D_Y * 3, // DWORD biSizeImage;
- 0, // LONG biXPelsPerMeter;
- 0, // LONG biYPelsPerMeter;
- 0, // DWORD biClrUsed;
- 0 // DWORD biClrImportant;
- }
-};
-
-#undef D_X
-#undef D_Y
-
-#define D_X 320
-#define D_Y 240
-
-//
-// FormatUYU2_Capture:
-//
-// This is the data range description of the UYVY format we support.
-//
-const
-KS_DATARANGE_VIDEO
-FormatUYU2_Capture = {
-
- //
- // KSDATARANGE
- //
- {
- sizeof (KS_DATARANGE_VIDEO), // FormatSize
- 0, // Flags
- D_X * D_Y * 2, // SampleSize
- 0, // Reserved
- STATICGUIDOF (KSDATAFORMAT_TYPE_VIDEO), // aka. MEDIATYPE_Video
- 0x59565955, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa,
- 0x00, 0x38, 0x9b, 0x71, // aka. MEDIASUBTYPE_UYVY,
- STATICGUIDOF (KSDATAFORMAT_SPECIFIER_VIDEOINFO) // aka. FORMAT_VideoInfo
- },
-
- TRUE, // BOOL, bFixedSizeSamples (all samples same size?)
- TRUE, // BOOL, bTemporalCompression (all I frames?)
- 0, // Reserved (was StreamDescriptionFlags)
- 0, // Reserved (was MemoryAllocationFlags
- // (KS_VIDEO_ALLOC_*))
-
- //
- // _KS_VIDEO_STREAM_CONFIG_CAPS
- //
- {
- STATICGUIDOF( KSDATAFORMAT_SPECIFIER_VIDEOINFO ), // GUID
- KS_AnalogVideo_NTSC_M |
- KS_AnalogVideo_PAL_B, // AnalogVideoStandard
- 720,480, // InputSize, (the inherent size of the incoming signal
- // with every digitized pixel unique)
- 160,120, // MinCroppingSize, smallest rcSrc cropping rect allowed
- 720,480, // MaxCroppingSize, largest rcSrc cropping rect allowed
- 8, // CropGranularityX, granularity of cropping size
- 1, // CropGranularityY
- 8, // CropAlignX, alignment of cropping rect
- 1, // CropAlignY;
- 160, 120, // MinOutputSize, smallest bitmap stream can produce
- 720, 480, // MaxOutputSize, largest bitmap stream can produce
- 8, // OutputGranularityX, granularity of output bitmap size
- 1, // OutputGranularityY;
- 0, // StretchTapsX (0 no stretch, 1 pix dup, 2 interp...)
- 0, // StretchTapsY
- 0, // ShrinkTapsX
- 0, // ShrinkTapsY
- 333667, // MinFrameInterval, 100 nS units
- 640000000, // MaxFrameInterval, 100 nS units
- 8 * 2 * 30 * 160 * 120, // MinBitsPerSecond;
- 8 * 2 * 30 * 720 * 480 // MaxBitsPerSecond;
- },
-
- //
- // KS_VIDEOINFOHEADER (default format)
- //
- {
- 0,0,0,0, // RECT rcSource;
- 0,0,0,0, // RECT rcTarget;
- D_X * D_Y * 2 * 30, // DWORD dwBitRate;
- 0L, // DWORD dwBitErrorRate;
- 333667, // REFERENCE_TIME AvgTimePerFrame;
- sizeof (KS_BITMAPINFOHEADER), // DWORD biSize;
- D_X, // LONG biWidth;
- D_Y, // LONG biHeight;
- 1, // WORD biPlanes;
- 16, // WORD biBitCount;
- FOURCC_YUV422, // DWORD biCompression;
- D_X * D_Y * 2, // DWORD biSizeImage;
- 0, // LONG biXPelsPerMeter;
- 0, // LONG biYPelsPerMeter;
- 0, // DWORD biClrUsed;
- 0 // DWORD biClrImportant;
- }
-};
-
-//
-// VideoCapturePinDispatch:
-//
-// This is the dispatch table for the capture pin. It provides notifications
-// about creation, closure, processing, data formats, etc...
-//
-const
-KSPIN_DISPATCH
-VideoCapturePinDispatch = {
- CVideoCapturePin::DispatchCreate, // Pin Create
- NULL, // Pin Close
- NULL, // Pin Process
- NULL, // Pin Reset
- CVideoCapturePin::DispatchSetFormat, // Pin Set Data Format
- CCapturePin::DispatchSetState, // Pin Set Device State
- NULL, // Pin Connect
- NULL, // Pin Disconnect
- NULL, // Clock Dispatch
- NULL // Allocator Dispatch
-};
-
-//
-// VideoCapturePinAllocatorFraming:
-//
-// This is the simple framing structure for the capture pin. Note that this
-// will be modified via KsEdit when the actual capture format is determined.
-//
-DECLARE_SIMPLE_FRAMING_EX (
- VideoCapturePinAllocatorFraming,
- STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED),
- KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
- KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY,
- 2,
- 0,
- 2 * PAGE_SIZE,
- 2 * PAGE_SIZE
- );
-
-//
-// VideoCapturePinDataRanges:
-//
-// This is the list of data ranges supported on the capture pin. We support
-// two: one RGB24, and one UYVY.
-//
-const
-PKSDATARANGE
-VideoCapturePinDataRanges [CAPTURE_PIN_DATA_RANGE_COUNT] = {
- (PKSDATARANGE) &FormatRGB24Bpp_Capture,
- (PKSDATARANGE) &FormatUYU2_Capture
- };
-