diff options
Diffstat (limited to 'avstream/avssamp/video.cpp')
| -rw-r--r-- | avstream/avssamp/video.cpp | 1433 |
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 - }; - |
