📄 hwcappin.cpp
字号:
// Comments:
// Static method called on format verification BEFORE the object is created.
//
NTSTATUS HwcapPin::OnSetDataFormat(
PKSPIN Pin,
const KSDATARANGE* DataRange,
const KSATTRIBUTE_LIST* AttributeRange)
{
g_Trace << "HwcapPin::OnSetDataFormat VERIFY, id=" << Pin->Id << EOL;
const GUID VideoInfoSpecifier =
{STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
if (IsEqualGUID (Pin -> ConnectionFormat -> Specifier, VideoInfoSpecifier)) {
PKS_DATAFORMAT_VIDEOINFOHEADER ConnectionFormat =
reinterpret_cast <PKS_DATAFORMAT_VIDEOINFOHEADER>
(Pin -> ConnectionFormat);
//
// DataRange comes out of OUR data range list, so it should be OK
//
const KS_DATARANGE_VIDEO *VIRange =
reinterpret_cast <const KS_DATARANGE_VIDEO *>
(DataRange);
//
// Check that the format is a match for the selected range.
//
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)
) {
return STATUS_NO_MATCH;
}
}
return STATUS_SUCCESS;
};
///////////////////////////////////////////////////////////////////////
// HwcapPin::OnSetDataFormat
//
// Parameters:
// OldFormat - The previous format used on this pin.
// 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.
// AttributeRange - The attribute range
// Returns:
// STATUS_SUCCESS if Pin's ConnectionFormat member matches the range
// that was passed to this routine.
// STATUS_NO_MATCH if ConnectionFormat does not match the passed range.
// Comments:
// Called on format change.
//
NTSTATUS HwcapPin::OnSetDataFormat(
PKSDATAFORMAT OldFormat,
PKSMULTIPLE_ITEM OldAttributeList,
const KSDATARANGE* DataRange,
const KSATTRIBUTE_LIST* AttributeRange)
{
ASSERT (OldFormat); // would be a Framework bug
g_Trace << "HwcapPin::OnSetDataFormat CHANGE, id=" << PKSPIN(*this)->Id << EOL;
PKSPIN Pin = PKSPIN(*this);
// verify if the format is acceptable
if ( OnSetDataFormat(Pin, DataRange, AttributeRange) == STATUS_SUCCESS ) {
// OK. Set the new format by caching the new video header
// Don't accept dynamic changes
if (Pin -> DeviceState == KSSTATE_STOP) {
if (m_VideoInfoHeader)
delete m_VideoInfoHeader;
m_VideoInfoHeader = new (Pin) KsVideoInfoHeader;
if (m_VideoInfoHeader==NULL)
return STATUS_INSUFFICIENT_RESOURCES;
}
else {
ASSERT(!"Should be here");
return STATUS_INVALID_DEVICE_STATE;
}
}
else
return STATUS_NO_MATCH;
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
// HwcapPin::OnIntersection
//
// Parameters:
// Irp - IRP with the request
// CallerDataRange - Ptr to one of the data ranges supplied by the client
// DescriptorDataRange - Ptr to one of the data ranges from the pin descriptor
// BufferSize - Size in bytes of the buffer pointed to by the Data
// Data - Pointer to the buffer to contain the data format
// structure representing the best format in the intersection of the
// two data ranges. Can be NULL.
// DataSize - Resulting buffer size copied
// Returns:
// 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.
// Comments:
// none
NTSTATUS HwcapPin::OnIntersection (KIrp /*Irp*/,
PKSDATARANGE CallerDataRange,
PKSDATARANGE DescriptorDataRange,
ULONG BufferSize,
PVOID Data,
PULONG DataSize)
{
g_Trace << "HwcapPin::OnIntersection, BufSize=" << BufferSize << " " << EOL;
PKS_DATAFORMAT_VIDEOINFOHEADER FormatVideoInfoHeader = PKS_DATAFORMAT_VIDEOINFOHEADER(Data);
ULONG DataFormatSize;
const GUID VideoInfoSpecifier =
{STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
// Make sure this is the videa data range
if (!IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier )) {
return STATUS_NO_MATCH;
}
PKS_DATARANGE_VIDEO callerDataRange = PKS_DATARANGE_VIDEO(CallerDataRange);
PKS_DATARANGE_VIDEO descriptorDataRange = PKS_DATARANGE_VIDEO(DescriptorDataRange);
//
// 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)))
{
g_Trace.Trace(TraceWarning, "Field mismatch OnIntersection()");
return STATUS_NO_MATCH;
}
// get required size:
DataFormatSize = sizeof( KSDATAFORMAT ) + KS_SIZE_VIDEOHEADER( &callerDataRange->VideoInfoHeader );
// for size query, return the required size
if (BufferSize == 0)
{
*DataSize = DataFormatSize;
g_Trace.Trace(TraceWarning, "Required size OnIntersection() = %d bytes\n", DataFormatSize);
return STATUS_BUFFER_OVERFLOW;
} else if (BufferSize < DataFormatSize) {
return STATUS_BUFFER_TOO_SMALL; // error
}
// Buffer is OK. Copy over the KSDATAFORMAT, followed by the actual VideoInfoHeader
*DataSize = DataFormatSize;
// Copy over the KSDATAFORMAT
memcpy(&FormatVideoInfoHeader->DataFormat, DescriptorDataRange, sizeof( KSDATARANGE ));
FormatVideoInfoHeader->DataFormat.FormatSize = DataFormatSize;
// Copy over the caller's requested VIDEOINFOHEADER
memcpy(&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.
//
// Adjust for compression if any
FormatVideoInfoHeader->VideoInfoHeader.bmiHeader.biSizeImage =
FormatVideoInfoHeader->DataFormat.SampleSize =
KS_DIBSIZE( FormatVideoInfoHeader->VideoInfoHeader.bmiHeader );
return STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////
// HwcapPin::DeleteClones
//
// Parameters:
// none
// Returns:
// none
// Comments:
// none
void HwcapPin::DeleteClones()
{
KsStreamPointer Clone = KsPin::GetFirstClone();
while (Clone.IsValid()) {
KsStreamPointer ThisClone = Clone;
Clone = Clone.GetNextClone();
ThisClone.Release();
}
}
///////////////////////////////////////////////////////////////////////
// HwcapPin::DPC
//
// Parameters:
// none
// Returns:
// none
// Comments:
// Handle the "interrupt".
// Simulate image transfer into DMA buffers and satisfy pending cloned
// stream pointers.
//
void HwcapPin::DPC()
{
// Generate image into an internal frame store & fill the dma buffers
// with the image.
ULONG MappingsRemaining = m_pHardware->CompleteDma();
// Walk over the list of clones and delete
// the ones for each the mappings have been filled
KsStreamPointer Clone = KsPin::GetFirstClone();
while (MappingsRemaining && Clone.IsValid()) {
// Update the stream header associated with given clone
ULONG MappingsCompletedInThisClone = (MappingsRemaining > Clone.OffsetOut().Remaining) ?
Clone.OffsetOut().Remaining : MappingsRemaining;
for (ULONG i=0; i<MappingsCompletedInThisClone; i++)
Clone.Header()->DataUsed += Clone.OffsetOut().Mappings[i].ByteCount;
if (MappingsRemaining >= Clone.OffsetOut().Remaining) {
// This clone is satisfied, fill the header
Clone.Header()->Duration =
PKS_VIDEOINFOHEADER(*m_VideoInfoHeader)->AvgTimePerFrame;
Clone.Header()->PresentationTime.Numerator =
Clone.Header()->PresentationTime.Denominator = 1;
PKS_VIDEOINFOHEADER(*m_VideoInfoHeader)->AvgTimePerFrame;
// Timestamp it if we got the clocks assigned
if (m_pClock) {
Clone.Header()->PresentationTime.Time = m_pClock->GetTime();
Clone.Header()->OptionsFlags = KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
}
else {
Clone.Header()->PresentationTime.Time = 0;
}
// Delete this one and goto the next clone
// g_Trace.Trace(TraceInfo, "HwcapPin::DPC() deleting clone %p\n", PKSSTREAM_POINTER(Clone));
KsStreamPointer ThisClone = Clone;
Clone = Clone.GetNextClone();
ThisClone.Release();
MappingsRemaining -= MappingsCompletedInThisClone;
} else {
// This clone has some more room to go: advance it and exit
// g_Trace.Trace(TraceInfo, "HwcapPin::DPC() advancing clone %p\n", PKSSTREAM_POINTER(Clone));
Clone.AdvanceOut(MappingsRemaining);
break;
}
};
if (m_bPending) {
m_bPending = FALSE;
::KsPinAttemptProcessing(*this, TRUE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -