📄 filter.cpp
字号:
Status = filter->Stop(Pin, FromState);
break;
case KSSTATE_ACQUIRE:
//
// This is a KS only state, that has no correspondence in DirectShow
//
_DbgPrintF(DEBUGLVL_BLAB,("filter to KSSTATE_STOP Pin->Id:%d From:%d", Pin->Id, FromState));
break;
case KSSTATE_PAUSE:
Status = filter->Pause(Pin, FromState);
break;
case KSSTATE_RUN:
Status = filter->Run(Pin, FromState);
break;
}
return Status;
}
NTSTATUS
VideoIntersectHandler(
IN PVOID 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.
--*/
{
const GUID VideoInfoSpecifier =
{STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
PAGED_CODE();
ASSERT(Filter);
ASSERT(Irp);
ASSERT(PinInstance);
ASSERT(CallerDataRange);
ASSERT(DescriptorDataRange);
ASSERT(DataSize);
PKSFILTER FilterInstance = reinterpret_cast<PKSFILTER>( Filter );
ULONG DataFormatSize;
_DbgPrintF(DEBUGLVL_BLAB,("VideoIntersectHandler"));
//
// Walk the formats supported by the stream searching for a match
// of the three GUIDs which together define a DATARANGE
//
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
if (IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier )) {
PKS_DATARANGE_VIDEO callerDataRange = PKS_DATARANGE_VIDEO(CallerDataRange);
PKS_DATARANGE_VIDEO descriptorDataRange = 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,
&callerDataRange->ConfigCaps,
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
{
_DbgPrintF(DEBUGLVL_VERBOSE,
("PinIntersectHandler: STATUS_NO_MATCH (KSDATAFORMAT_SPECIFIER_VIDEOINFO)"));
return STATUS_NO_MATCH;
}
DataFormatSize =
sizeof( KSDATAFORMAT ) +
KS_SIZE_VIDEOHEADER( &callerDataRange->VideoInfoHeader );
if (BufferSize == 0)
{
//
// Size only query...
//
*DataSize = DataFormatSize;
_DbgPrintF(DEBUGLVL_VERBOSE,("PinIntersectHandler: STATUS_BUFFER_OVERFLOW DataFormatSize:%d", 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
RtlCopyMemory(&FormatVideoInfoHeader->DataFormat, DescriptorDataRange, sizeof( KSDATARANGE ));
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
//
_DbgPrintF(DEBUGLVL_VERBOSE, ("PinIntersectHandler: STATUS_SUCCESS (KSDATAFORMAT_SPECIFIER_VIDEOINFO)"));
return STATUS_SUCCESS;
} // End of VIDEOINFOHEADER specifier
#if 0
// Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
else if (IsEqualGUID (&DataRange->Specifier,
&KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
//
// For analog video, the DataRange and DataFormat
// are identical, so just copy the whole structure
//
PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
(PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
// MATCH FOUND!
MatchFound = TRUE;
FormatSize = sizeof (KS_DATARANGE_ANALOGVIDEO);
if (OnlyWantsSize) {
break;
}
// Caller wants the full data format
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
RtlCopyMemory(
IntersectInfo->DataFormatBuffer,
DataRangeVideo,
sizeof (KS_DATARANGE_ANALOGVIDEO));
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
} // End of KS_ANALOGVIDEOINFO specifier
#endif
_DbgPrintF(DEBUGLVL_VERBOSE,("PinIntersectHandler: STATUS_NO_MATCH"));
return STATUS_NO_MATCH;
}
NTSTATUS
AudioIntersectHandler(
IN PVOID 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 audip 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.
--*/
{
PKSDATARANGE_AUDIO descriptorDataRange;
PKSDATARANGE_AUDIO callerDataRange;
PKSDATAFORMAT_WAVEFORMATEX dataFormat;
_DbgPrintF(DEBUGLVL_BLAB,("AudioIntersectHandler"));
PAGED_CODE();
ASSERT(Filter);
ASSERT(Irp);
ASSERT(PinInstance);
ASSERT(CallerDataRange);
ASSERT(DescriptorDataRange);
ASSERT(DataSize);
//
// Descriptor data range must be WAVEFORMATEX.
//
ASSERT(IsEqualGUID(DescriptorDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
descriptorDataRange = (PKSDATARANGE_AUDIO)DescriptorDataRange;
//
// Caller data range may be wildcard or WAVEFORMATEX.
//
if (IsEqualGUID(CallerDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WILDCARD)) {
//
// Wildcard. Do not try to look at the specifier.
//
callerDataRange = NULL;
} else {
//
// WAVEFORMATEX. Validate the specifier ranges.
//
ASSERT(IsEqualGUID(CallerDataRange->Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
callerDataRange = (PKSDATARANGE_AUDIO)CallerDataRange;
if ((CallerDataRange->FormatSize != sizeof(*callerDataRange)) ||
(callerDataRange->MaximumSampleFrequency <
descriptorDataRange->MinimumSampleFrequency) ||
(descriptorDataRange->MaximumSampleFrequency <
callerDataRange->MinimumSampleFrequency) ||
(callerDataRange->MaximumBitsPerSample <
descriptorDataRange->MinimumBitsPerSample) ||
(descriptorDataRange->MaximumBitsPerSample <
callerDataRange->MinimumBitsPerSample)) {
_DbgPrintF(DEBUGLVL_VERBOSE,("[PinIntersectHandler] STATUS_NO_MATCH"));
return STATUS_NO_MATCH;
}
}
dataFormat = (PKSDATAFORMAT_WAVEFORMATEX)Data;
if (BufferSize == 0) {
//
// Size query - return the size.
//
*DataSize = sizeof(*dataFormat);
_DbgPrintF(DEBUGLVL_VERBOSE,("[PinIntersectHandler] STATUS_BUFFER_OVERFLOW"));
return STATUS_BUFFER_OVERFLOW;
}
ASSERT(dataFormat);
if (BufferSize < sizeof(*dataFormat)) {
//
// Buffer is too small.
//
_DbgPrintF(DEBUGLVL_VERBOSE,("[PinIntersectHandler] STATUS_BUFFER_TOO_SMALL"));
return STATUS_BUFFER_TOO_SMALL;
}
//
// Gotta build the format.
//
*DataSize = sizeof(*dataFormat);
//
// All the guids are in the descriptor's data range.
//
RtlCopyMemory(
&dataFormat->DataFormat,
DescriptorDataRange,
sizeof(dataFormat->DataFormat));
dataFormat->WaveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
if (callerDataRange) {
dataFormat->WaveFormatEx.nChannels = (USHORT)
min(callerDataRange->MaximumChannels,descriptorDataRange->MaximumChannels);
dataFormat->WaveFormatEx.nSamplesPerSec =
min(callerDataRange->MaximumSampleFrequency,descriptorDataRange->MaximumSampleFrequency);
dataFormat->WaveFormatEx.wBitsPerSample = (USHORT)
min(callerDataRange->MaximumBitsPerSample,descriptorDataRange->MaximumBitsPerSample);
} else {
dataFormat->WaveFormatEx.nChannels = (USHORT)
descriptorDataRange->MaximumChannels;
dataFormat->WaveFormatEx.nSamplesPerSec =
descriptorDataRange->MaximumSampleFrequency;
dataFormat->WaveFormatEx.wBitsPerSample = (USHORT)
descriptorDataRange->MaximumBitsPerSample;
}
dataFormat->WaveFormatEx.nBlockAlign =
(dataFormat->WaveFormatEx.wBitsPerSample * dataFormat->WaveFormatEx.nChannels) / 8;
dataFormat->WaveFormatEx.nAvgBytesPerSec =
dataFormat->WaveFormatEx.nBlockAlign * dataFormat->WaveFormatEx.nSamplesPerSec;
dataFormat->WaveFormatEx.cbSize = 0;
dataFormat->DataFormat.FormatSize = sizeof(*dataFormat);
dataFormat->DataFormat.SampleSize = dataFormat->WaveFormatEx.nBlockAlign;
return STATUS_SUCCESS;
}
//
// Topology
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -