**************************************************************************/ GUID g_PINNAME_VIDEO_CAPTURE = {STATIC_PINNAME_VIDEO_CAPTURE}; GUID g_PINNAME_VIDEO_PREVIEW = {STATIC_PINNAME_VIDEO_PREVIEW}; GUID g_PINNAME_IMAGE_CAPTURE = {STATIC_PINNAME_IMAGE}; // // CaptureFilterCategories: // // The list of category GUIDs for the capture filter. // const GUID FilterCategories [CAPTURE_FILTER_CATEGORIES_COUNT] = { STATICGUIDOF (KSCATEGORY_VIDEO_CAMERA), STATICGUIDOF (KSCATEGORY_VIDEO), STATICGUIDOF (KSCATEGORY_CAPTURE) }; DEFINE_KSPROPERTY_TABLE(FocusPropertyItems) { DEFINE_PROP_ITEM( CCaptureFilter, KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_PROPERTY_ID, KSPROPERTY_CAMERACONTROL_REGION_OF_INTEREST_S, FocusRect ) }; DEFINE_KSPROPERTY_TABLE(VideoStabPropertyItems) { DEFINE_PROP_ITEM( CCaptureFilter, 0, KSPROPERTY_CAMERACONTROL_VIDEOSTABILIZATION_MODE_S, VideoStabMode ) }; DEFINE_KSPROPERTY_TABLE(FlashPropertyItems)
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(); DBGU_TRACE("Enter CStillPin::DispatchSetFormat\n"); NTSTATUS Status = STATUS_NO_MATCH; const GUID VideoInfoSpecifier = {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)}; CStillPin *StiPin = 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) { StiPin = reinterpret_cast <CStillPin *> (Pin -> Context); } if (IsEqualGUID (Pin -> ConnectionFormat -> Specifier, VideoInfoSpecifier) &&
NTSTATUS CStillPin:: 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(); DBGU_TRACE("Enter CStillPin::IntersectHandler\n"); const GUID VideoInfoSpecifier = {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)}; ASSERT(Filter); ASSERT(Irp); ASSERT(PinInstance); ASSERT(CallerDataRange); ASSERT(DescriptorDataRange); ASSERT(DataSize); ULONG DataFormatSize; // // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER2 // 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))) { DBGU_TRACE("Check that the other fields match, return STATUS_NO_MATCH\n"); 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; DBGU_TRACE("X=%d, Y=%d, BI=%d\n",callerDataRange->VideoInfoHeader.bmiHeader.biWidth, callerDataRange->VideoInfoHeader.bmiHeader.biHeight, callerDataRange->VideoInfoHeader.bmiHeader.biBitCount); // // 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 ) { DBGU_TRACE("Check that biSize, return STATUS_INVALID_PARAMETER\n"); 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; DBGU_TRACE("the passed buffer size is 0, return STATUS_BUFFER_OVERFLOW\n"); return STATUS_BUFFER_OVERFLOW; } // // Verify that the provided structure is large enough to // accept the result. // if (BufferSize < DataFormatSize) { DBGU_TRACE("Verify buffer large enough, return STATUS_BUFFER_TOO_SMALL\n"); 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 // DBGU_TRACE("REVIEW - Perform other validation such as cropping and scaling checks\n"); return STATUS_SUCCESS; } // End of VIDEOINFOHEADER specifier DBGU_TRACE("End of VIDEOINFOHEADER specifier, return STATUS_NO_MATCH\n"); return STATUS_NO_MATCH; }
#define WAVE_FORMAT_WMA_SPDIF 0x164 #define STATIC_KSDATAFORMAT_SUBTYPE_WMA_SPDIF DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_WMA_SPDIF) DEFINE_GUIDSTRUCT("00000164-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_WMA_SPDIF); #define KSDATAFORMAT_SUBTYPE_WMA_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_WMA_SPDIF) static KSDATARANGE_AUDIO WavePinDataRangesPCMStream[] = { { { { sizeof(KSDATARANGE_AUDIO), 0, 0, 0, {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM)}, {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)} } }, MAX_CHANNELS_PCM, MIN_BITS_PER_SAMPLE_PCM, MAX_BITS_PER_SAMPLE_PCM, MIN_SAMPLE_RATE, MAX_SAMPLE_RATE } }; static KSDATARANGE_AUDIO WavePinDataRangesAC3Stream[] = { {
void CEncoderPin:: CompleteMappings ( IN ULONG NumMappings ) /*++ Routine Description: Called to notify the pin that a given number of scatter / gather mappings have completed. Let the buffers go if possible. We're called at DPC. Arguments: NumMappings - The number of mappings that have completed. Return Value: None --*/ { ULONG MappingsRemaining = NumMappings; // // Walk through the clones list and delete clones whose time has come. // The list is guaranteed to be kept in the order they were cloned. // PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin); while (MappingsRemaining && Clone) { PKSSTREAM_POINTER NextClone = KsStreamPointerGetNextClone (Clone); #if defined(_BUILD_SW_TUNER_ON_X64) #else // // Count up the number of bytes we've completed and mark this // in the Stream Header. In mapped queues // (KSPIN_FLAG_GENERATE_MAPPINGS), this is the responsibility of // the minidriver. In non-mapped queues, AVStream performs this. // ULONG MappingsToCount = (MappingsRemaining > Clone -> OffsetOut.Remaining) ? Clone -> OffsetOut.Remaining : MappingsRemaining; // // Update DataUsed according to the mappings. // for (ULONG CurMapping = 0; CurMapping < MappingsToCount; CurMapping++) { Clone -> StreamHeader -> DataUsed += Clone -> OffsetOut.Mappings [CurMapping].ByteCount; } #endif // // If we have completed all remaining mappings in this clone, it // is an indication that the clone is ready to be deleted and the // buffer released. Set anything required in the stream header which // has not yet been set. If we have a clock, we can timestamp the // sample. // #if defined(_BUILD_SW_TUNER_ON_X64) if (Clone -> StreamHeader -> DataUsed >= Clone -> OffsetOut.Remaining) { #else if (MappingsRemaining >= Clone -> OffsetOut.Remaining) { #endif Clone -> StreamHeader -> Duration = m_TransportInfo -> AvgTimePerFrame; Clone -> StreamHeader -> PresentationTime.Numerator = Clone -> StreamHeader -> PresentationTime.Denominator = 1; // // If a clock has been assigned, timestamp the packets with the // time shown on the clock. // if (m_Clock) { LONGLONG ClockTime = m_Clock -> GetTime (); Clone -> StreamHeader -> PresentationTime.Time = ClockTime; Clone -> StreamHeader -> OptionsFlags = KSSTREAM_HEADER_OPTIONSF_TIMEVALID | KSSTREAM_HEADER_OPTIONSF_DURATIONVALID; } else { // // If there is no clock, don't time stamp the packets. // Clone -> StreamHeader -> PresentationTime.Time = 0; } // // If all of the mappings in this clone have been completed, // delete the clone. We've already updated DataUsed above. // #if defined(_BUILD_SW_TUNER_ON_X64) MappingsRemaining--; #else MappingsRemaining -= Clone -> OffsetOut.Remaining; #endif KsStreamPointerDelete (Clone); } else { // // If only part of the mappings in this clone have been completed, // update the pointers. Since we're guaranteed this won't advance // to a new frame by the check above, it won't fail. // #if defined(_BUILD_SW_TUNER_ON_X64) KsStreamPointerAdvanceOffsets ( Clone, 0, Clone -> StreamHeader -> DataUsed, FALSE ); #else KsStreamPointerAdvanceOffsets ( Clone, 0, MappingsRemaining, FALSE ); #endif MappingsRemaining = 0; } // // Go to the next clone. // Clone = NextClone; } // // If we've used all the mappings in hardware and pended, we can kick // processing to happen again if we've completed mappings. // if (m_PendIo) { m_PendIo = TRUE; KsPinAttemptProcessing (m_Pin, TRUE); } } /************************************************************************** DISPATCH AND DESCRIPTOR LAYOUT **************************************************************************/ // // This is the data range description of the capture output pin. // // MEDIASUBTYPE_None #define MEDIASUBTYPE_MPEG2_PROGRAM\ 0xe06d8022, 0xdb46, 0x11cf, 0xb4, 0xd1, 0x00, 0x80, 0x05f, 0x6c, 0xbb, 0xea const KSDATARANGE FormatEncoderOut = { // insert the KSDATARANGE and KSDATAFORMAT here { sizeof( KSDATARANGE), // FormatSize 0, // Flags - (N/A) PS_SAMPLE_SIZE, // SampleSize 0, // Reserved { STATIC_KSDATAFORMAT_TYPE_STREAM }, // MajorFormat { MEDIASUBTYPE_MPEG2_PROGRAM}, // SubFormat { STATIC_KSDATAFORMAT_SPECIFIER_NONE } // Specifier } }; // // This is the data range description of the capture input pin. // const KS_DATARANGE_BDA_TRANSPORT FormatEncoderIn = { // insert the KSDATARANGE and KSDATAFORMAT here { sizeof( KS_DATARANGE_BDA_TRANSPORT), // FormatSize 0, // Flags - (N/A) 0, // SampleSize - (N/A) 0, // Reserved { STATIC_KSDATAFORMAT_TYPE_STREAM }, // MajorFormat { STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT }, // SubFormat { STATIC_KSDATAFORMAT_SPECIFIER_BDA_TRANSPORT } // Specifier }, // insert the BDA_TRANSPORT_INFO here { PS_PACKET_SIZE, // ulcbPhyiscalPacket PS_SAMPLE_SIZE, // ulcbPhyiscalFrame 0, // ulcbPhyiscalFrameAlignment (no requirement) 0 // AvgTimePerFrame (not known) } }; // // EncoderPinDispatch: // // This is the dispatch table for the capture pin. It provides notifications // about creation, closure, processing, data formats, etc... // extern const KSPIN_DISPATCH EncoderPinDispatch = { CEncoderPin::DispatchCreate, // Pin Create NULL, // Pin Close CEncoderPin::DispatchProcess, // Pin Process NULL, // Pin Reset NULL, // Pin Set Data Format CEncoderPin::DispatchSetState, // Pin Set Device State NULL, // Pin Connect NULL, // Pin Disconnect NULL, // Clock Dispatch NULL // Allocator Dispatch }; // // InputPinDispatch: // // This is the dispatch table for the capture pin. It provides notifications // about creation, closure, processing, data formats, etc... // extern const KSPIN_DISPATCH InputPinDispatch = { CEncoderPin::DispatchCreate, // Pin Create NULL, // Pin Close NULL, // Pin Process NULL, // Pin Reset NULL, // Pin Set Data Format NULL, // Pin Set Device State NULL, // Pin Connect NULL, // Pin Disconnect NULL, // Clock Dispatch NULL // Allocator Dispatch }; // // EncoderPinAllocatorFraming: // // 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. // extern DECLARE_SIMPLE_FRAMING_EX ( EncoderPinAllocatorFraming, // FramingExName STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED), // MemoryType KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY, // Flags 8, // Frames 0, // Alignment PS_SAMPLE_SIZE, // MinFrameSize PS_SAMPLE_SIZE // MaxFrameSize ); // // EncoderOutPinDataRanges: // // This is the list of data ranges supported on the capture output pin. // extern const PKSDATARANGE EncoderOutPinDataRanges [ENCODER_OUT_PIN_DATA_RANGE_COUNT] = { (PKSDATARANGE) &FormatEncoderOut }; // // EncoderInPinDataRanges: // // This is the list of data ranges supported on the capture input pin. // extern const PKSDATARANGE EncoderInPinDataRanges [ENCODER_IN_PIN_DATA_RANGE_COUNT] = { (PKSDATARANGE) &FormatEncoderIn };
#define STATIC_KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF\ DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_DOLBY_AC3_SPDIF) DEFINE_GUIDSTRUCT("00000092-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF); #define KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) #endif static KSDATARANGE PinDataRangesBridge[] = { { { sizeof(KSDATARANGE), 0, 0, 0, {STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO)}, {STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG)}, {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)} } } }; static PKSDATARANGE PinDataRangePointersBridge[] = { &PinDataRangesBridge[0] }; static KSDATARANGE WavePinDataRangesAC3Bridge[] = { { {
DBG_LEAVE("(Pin=%d)=0x%08X", Pin->Id, Status); return Status; } // // CapturePinDispatch: // // This is the dispatch table for the capture pin. It provides notifications // about creation, closure, processing, data formats, etc... // DEFINE_CAMERA_KSPIN_DISPATCH( VideoCapturePinDispatch, CVideoCapturePin ); // // CapturePinAllocatorFraming: // // 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 );
**************************************************************************/ //=====================首先是Pin相关的描述符 // 输入/输出Pin所支持的数据格式,这其实是一个格式范围(Range) // 在这个范围里面,可以设置最大、最小采用,最大最小采样深度 // // 下面的结构体所表示的格式范围是: // 双声道、24位采样、44.1或者48K采样率 KSDATARANGE_AUDIO gPinDataFormatRange = { { sizeof(KSDATARANGE_AUDIO), 0, 6, 0, STATIC_KSDATAFORMAT_TYPE_AUDIO, STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) }, 2, // channels 16, // min. bits per sample 24, // max. bits per sample 44100, // min. sample rate 48000 // max. sample rate }; const PKSDATARANGE gPinDataFormatRanges[] = { PKSDATARANGE(&gPinDataFormatRange) }; const KSPIN_DISPATCH gPinDispatch =
////////////////////////////////////////////////////////////////////////////// // // Description: // This is the intersect handler for comparison of a data range. // of the analog VBI out pin.(Needs no class environment to intersect // the format, because the format that is supported is already // given in the filter descriptor). // // Settings: // A match occurs under three conditions: // (1) if the major format of the range passed matches a pin factory range, // (2) if the sub-format matches, // (3) if the specifier is KSDATAFORMAT_SPECIFIER_VBI. // Since the data range size may be variable, it is not validated beyond // checking that it is at least the size of a data range structure. // (KSDATAFORMAT_SPECIFIER_VBI) // // Remarks: // There is a bug so we always get all formats from the descriptor // even if they do not match with the current video standard detected // in the decoder property (see correct handling in the video classes). // To set up the right format, we ask the decoder for the current format // and if it does not match to the pCallerDataRange, we return // STATUS_NO_MATCH to get called again with the next format from the // descriptor. // If it matches our decoder setting, we write it to the target format // pData. // // Return Value: // STATUS_SUCCESS If a matching range is found and it fits // in the supplied buffer. // STATUS_UNSUCCESSFUL Operation failed, // the function parameters are zero. // STATUS_BUFFER_OVERFLOW For successful size queries. (in that case // the buffer size is zero and has to be set // to the right value before return) // STATUS_BUFFER_TOO_SMALL If the supplied buffer is too small. // STATUS_NO_MATCH (a) if the intersection is empty, or // (b) if no matching range was found // ////////////////////////////////////////////////////////////////////////////// static NTSTATUS AnlgVBIOutIntersectDataFormat ( IN PVOID pvKSFilter, //Pointer to KS filter structure. IN PIRP pIrp, //Pointer to data intersection //property request. IN PKSP_PIN pPinInstance, //Pointer to structure indicating //pin in question. IN PKSDATARANGE pCallerDataRange, //Pointer to the caller data //structure that should be //intersected. IN PKSDATARANGE pDescriptorDataRange, //Pointer to the descriptor data //structure, see AnlgVbiFormats.h. IN ULONG dwBufferSize, //Size in bytes of the target //buffer structure. For size //queries, this value is zero. OUT OPTIONAL PVOID pData, //Pointer to the target data //structure representing the best //format in the intersection. OUT PULONG pdwDataSize //Pointer to size of target data //format structure. ) { PKSFILTER pKSFilter; pKSFilter = (PKSFILTER) pvKSFilter; DbgPrint("AnlgVBIOutIntersectDataFormat"); //invalid parameters? if( !pKSFilter || !pIrp || !pPinInstance || !pCallerDataRange || !pDescriptorDataRange || !pdwDataSize ) { DbgPrint("SWTANALOG-Capture VBIOut UNSUCCESSFUL"); return STATUS_UNSUCCESSFUL; } //set output data size *pdwDataSize = sizeof(KS_DATAFORMAT_VBIINFOHEADER); //check for size only query if( dwBufferSize == 0 ) { //BUGBUG: we have to return "buffer overflow", //because this is what is expected on the other side, //any other return value will cause a wrong handling of //the size parameter DbgPrint("SWTANALOG-Capture VBIOut BUFFER_OVERFLOW"); return STATUS_BUFFER_OVERFLOW; } //check if output buffer size is sufficient if( dwBufferSize < *pdwDataSize ) { DbgPrint("SWTANALOG-Capture VBIOut TOO_SMALL"); return STATUS_BUFFER_TOO_SMALL; } //*** start intersection ***// //check if given datarange GUID matches to VBI const GUID VBIInfoSpecifier = {STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VBI)}; if( !IsEqualGUID(pCallerDataRange->Specifier, VBIInfoSpecifier) || pCallerDataRange->FormatSize != sizeof(KS_DATARANGE_VIDEO_VBI) ) { DbgPrint("SWTANALOG-Capture VBIOut NO_MATCH 1"); return STATUS_NO_MATCH; } PKS_DATARANGE_VIDEO_VBI pCallerVbiDataRange = reinterpret_cast <PKS_DATARANGE_VIDEO_VBI> (pCallerDataRange); PKS_DATARANGE_VIDEO_VBI pDescriptorVbiDataRange = reinterpret_cast <PKS_DATARANGE_VIDEO_VBI> (pDescriptorDataRange); PKS_DATAFORMAT_VBIINFOHEADER pTargetVbiDataRange = reinterpret_cast <PKS_DATAFORMAT_VBIINFOHEADER> (pData); //check if all other important fields match if( (pCallerVbiDataRange->bFixedSizeSamples != pDescriptorVbiDataRange->bFixedSizeSamples) || (pCallerVbiDataRange->bTemporalCompression != pDescriptorVbiDataRange->bTemporalCompression) || (pCallerVbiDataRange->StreamDescriptionFlags != pDescriptorVbiDataRange->StreamDescriptionFlags) || (pCallerVbiDataRange->MemoryAllocationFlags != pDescriptorVbiDataRange->MemoryAllocationFlags) ) { DbgPrint("SWTANALOG-Capture VBIOut NO_MATCH 2"); return STATUS_NO_MATCH; } pTargetVbiDataRange->DataFormat = static_cast <KSDATAFORMAT> (pDescriptorVbiDataRange->DataRange); pTargetVbiDataRange->DataFormat.FormatSize = *pdwDataSize; pTargetVbiDataRange->VBIInfoHeader = pDescriptorVbiDataRange->VBIInfoHeader; DbgPrint("SWTANALOG-Capture VBIOut DataSize %d",*pdwDataSize); DbgPrint("SWTANALOG-Capture VBIOut success"); return STATUS_SUCCESS; }
#include "ntintsafe.h" #ifdef ALLOC_PRAGMA #pragma code_seg("PAGE") #endif // ALLOC_PRAGMA /************************************************************************** DISPATCH AND DESCRIPTOR LAYOUT **************************************************************************/ DEFINE_DATARANGE_VIDEO( FormatNV12_CaptureVGA, STATICGUIDOF(KSDATAFORMAT_SUBTYPE_NV12), DMAX_X, DMAX_Y, 30, 1, 12, FOURCC_NV12) DEFINE_DATARANGE_VIDEO( FormatYUY2_CaptureQVGA, STATICGUIDOF(KSDATAFORMAT_SUBTYPE_YUY2), D_X, D_Y, 30, 1, 16, FOURCC_YUY2)