📄 basestrm.cpp
字号:
StreamClassScheduleTimer (
m_pClassObject, // StreamObject
Adapter(), // HwDeviceExtension
(ULONG) (m_pVideoInfoHeader->AvgTimePerFrame / 20), // Microseconds
VideoTimerRoutine, // TimerRoutine
this); // Context
// -- excessive tracing... use during DEBUG only! --
// #ifdef __VIDCAP_TRACEON__
// TVS << TraceInfo << "VidcapBaseStream::OnVideoTimer -- End\n";
// #endif
}
NTSTATUS VidcapBaseStream::OnOpen(PHW_STREAM_REQUEST_BLOCK pSrb)
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::OnOpen -- Start\n";
#endif
PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
int StreamNumber = pSrb->StreamObject->StreamNumber;
pSrb->Status = VerifyFormat(pSrb->CommandData.OpenFormat) ?
STATUS_SUCCESS : STATUS_INVALID_PARAMETER;
if (IsEqualGUID (pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO))
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceAlways << "VidcapBaseStream::OnOpen -- Format == KSDATAFORMAT_SPECIFIER_VIDEOINFO\n";
#endif
PKS_DATAFORMAT_VIDEOINFOHEADER pVideoInfoHeader =
(PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
PKS_VIDEOINFOHEADER pVideoInfoHdrRequested = &pVideoInfoHeader->VideoInfoHeader;
ULONG nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested);
m_pVideoInfoHeader = (PKS_VIDEOINFOHEADER) new(NonPagedPool) UCHAR[nSize];
if (m_pVideoInfoHeader == NULL)
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
// Copy the VIDEOINFOHEADER requested to our storage
RtlCopyMemory(m_pVideoInfoHeader, pVideoInfoHdrRequested, nSize);
}
// -------------------------------------------------------------------
// Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
// -------------------------------------------------------------------
else if (IsEqualGUID (pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_ANALOGVIDEO))
{
//
// AnalogVideo DataRange == DataFormat!
//
// For now, don't even cache this
// BUGBUG
//
#ifdef __VIDCAP_TRACEON__
TVS << TraceAlways << "VidcapBaseStream::OnOpen -- Format == KSDATAFORMAT_SPECIFIER_ANALOGVIDEO\n";
#endif
PKS_DATARANGE_ANALOGVIDEO pDataFormatAnalogVideo =
(PKS_DATARANGE_ANALOGVIDEO) pSrb->CommandData.OpenFormat;
}
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::OnOpen -- End\n";
#endif
return pSrb->Status;
}
BOOL VidcapBaseStream::VerifyFormat(PKSDATAFORMAT pKSDataFormatToVerify)
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::VerifyFormat -- Start\n";
#endif
BOOL fOK = FALSE;
ULONG i;
PKSDATAFORMAT* pAvailableFormats = StreamFormatsArray();
KdPrint(("TestCap: FormatSize=%d\n", pKSDataFormatToVerify->FormatSize));
KdPrint(("TestCap: MajorFormat=%x\n", pKSDataFormatToVerify->MajorFormat));
//
// Walk the formats supported by the stream
//
for (i = 0; i < NumberOfStreamFormats(); i++, pAvailableFormats++)
{
// Check for a match on the three GUIDs and format size
if (!CompareGUIDsAndFormatSize(
pKSDataFormatToVerify,
*pAvailableFormats,
FALSE /* CompareFormatSize */ ))
continue;
//
// Now that the three GUIDs match, switch on the Specifier
// to do a further type-specific check
//
// -------------------------------------------------------------------
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
// -------------------------------------------------------------------
if (IsEqualGUID (pKSDataFormatToVerify->Specifier,
KSDATAFORMAT_SPECIFIER_VIDEOINFO))
{
PKS_DATAFORMAT_VIDEOINFOHEADER pDataFormatVideoInfoHeader =
(PKS_DATAFORMAT_VIDEOINFOHEADER) pKSDataFormatToVerify;
PKS_VIDEOINFOHEADER pVideoInfoHdrToVerify =
(PKS_VIDEOINFOHEADER) &pDataFormatVideoInfoHeader->VideoInfoHeader;
PKS_DATARANGE_VIDEO pKSDataRangeVideo = (PKS_DATARANGE_VIDEO) *pAvailableFormats;
KS_VIDEO_STREAM_CONFIG_CAPS *pConfigCaps = &pKSDataRangeVideo->ConfigCaps;
RECT rcImage;
/*
** HOW BIG IS THE IMAGE REQUESTED (pseudocode follows)
**
** if (IsRectEmpty (&rcTarget) {
** SetRect (&rcImage, 0, 0,
** BITMAPINFOHEADER.biWidth,
BITMAPINFOHEADER.biHeight);
** }
** else {
** // Probably rendering to a DirectDraw surface,
** // where biWidth is used to expressed the "stride"
** // in units of pixels (not bytes) of the destination surface.
** // Therefore, use rcTarget to get the actual image size
**
** rcImage = rcTarget;
** }
*/
if ((pVideoInfoHdrToVerify->rcTarget.right -
pVideoInfoHdrToVerify->rcTarget.left <= 0) ||
(pVideoInfoHdrToVerify->rcTarget.bottom -
pVideoInfoHdrToVerify->rcTarget.top <= 0)) {
rcImage.left = rcImage.top = 0;
rcImage.right = pVideoInfoHdrToVerify->bmiHeader.biWidth;
rcImage.bottom = pVideoInfoHdrToVerify->bmiHeader.biHeight;
}
else {
rcImage = pVideoInfoHdrToVerify->rcTarget;
}
//
// BUGBUG, perform all other verification tests here!!!
//
//
// HOORAY, the format passed all of the tests, so we support it
//
fOK = TRUE;
break;
} // End of VIDEOINFOHEADER specifier
// -------------------------------------------------------------------
// Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
// -------------------------------------------------------------------
else if (IsEqualGUID (pKSDataFormatToVerify->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;
//
// BUGBUG, perform all other verification tests here!!!
//
fOK = TRUE;
break;
} // End of KS_ANALOGVIDEOINFO specifier
} // End of loop on all formats for this stream
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::VerifyFormat -- End\n";
#endif
return fOK;
}
BOOL VidcapBaseStream::CompareGUIDsAndFormatSize(
IN PKSDATARANGE DataRange1,
IN PKSDATARANGE DataRange2,
BOOL fCompareFormatSize
)
{
return (
IsEqualGUID (
DataRange1->MajorFormat,
DataRange2->MajorFormat) &&
IsEqualGUID (
DataRange1->SubFormat,
DataRange2->SubFormat) &&
IsEqualGUID (
DataRange1->Specifier,
DataRange2->Specifier) &&
(fCompareFormatSize ?
(DataRange1->FormatSize == DataRange2->FormatSize) : TRUE ));
}
NTSTATUS VidcapBaseStream::GetDataIntersection(PHW_STREAM_REQUEST_BLOCK pSrb)
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetDataIntersection -- Start\n";
#endif
PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
PKSDATARANGE DataRange;
BOOL OnlyWantsSize;
BOOL MatchFound = FALSE;
ULONG FormatSize;
PKSDATAFORMAT* pAvailableFormats;
IntersectInfo = pSrb->CommandData.IntersectInfo;
DataRange = IntersectInfo->DataRange;
//
// Get the pointer to the array of available formats
//
pAvailableFormats = StreamFormatsArray();
//
// Is the caller trying to get the format, or the size of the format?
//
OnlyWantsSize = (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG));
//
// Walk the formats supported by the stream searching for a match
// of the three GUIDs which together define a DATARANGE
//
for (ULONG i = 0; i < NumberOfStreamFormats(); i++, pAvailableFormats++) {
if (!CompareGUIDsAndFormatSize(
DataRange,
*pAvailableFormats,
TRUE /* CompareFormatSize */))
{
continue;
}
//
// Now that the three GUIDs match, switch on the Specifier
// to do a further type-specific check
//
// -------------------------------------------------------------------
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
// -------------------------------------------------------------------
if (IsEqualGUID (DataRange->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO))
{
PKS_DATARANGE_VIDEO DataRangeVideoToVerify =
(PKS_DATARANGE_VIDEO) DataRange;
PKS_DATARANGE_VIDEO DataRangeVideo =
(PKS_DATARANGE_VIDEO) *pAvailableFormats;
PKS_DATAFORMAT_VIDEOINFOHEADER DataFormatVideoInfoHeaderOut;
//
// Check that the other fields match
//
if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
(DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
(DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
(DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
(RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps,
&DataRangeVideo->ConfigCaps,
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
{
continue;
}
// MATCH FOUND!
MatchFound = TRUE;
FormatSize = sizeof (KSDATAFORMAT) +
KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader);
if (OnlyWantsSize)
break;
// Caller wants the full data format
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize)
return(STATUS_BUFFER_TOO_SMALL);
// Copy over the KSDATAFORMAT, followed by the
// actual VideoInfoHeader
DataFormatVideoInfoHeaderOut = (PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer;
// Copy over the KSDATAFORMAT
RtlCopyMemory(
&DataFormatVideoInfoHeaderOut->DataFormat,
&DataRangeVideoToVerify->DataRange,
sizeof (KSDATARANGE));
DataFormatVideoInfoHeaderOut->DataFormat.FormatSize = FormatSize;
// Copy over the callers requested VIDEOINFOHEADER
RtlCopyMemory(
&DataFormatVideoInfoHeaderOut->VideoInfoHeader,
&DataRangeVideoToVerify->VideoInfoHeader,
KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->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
DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);
//
// BUGBUG Perform other validation such as cropping and scaling checks
//
break;
} // End of VIDEOINFOHEADER specifier
// -------------------------------------------------------------------
// 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)
return(STATUS_BUFFER_TOO_SMALL);
RtlCopyMemory(
IntersectInfo->DataFormatBuffer,
DataRangeVideo,
sizeof (KS_DATARANGE_ANALOGVIDEO));
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
break;
} // End of KS_ANALOGVIDEOINFO specifier
else
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceAlways << "VidcapBaseStream::GetDataIntersection -- End, Returning STATUS_NO_MATCH\n";
#endif
return(STATUS_NO_MATCH);
}
} // End of loop on all formats for this stream
if (OnlyWantsSize)
{
*(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
pSrb->ActualBytesTransferred = sizeof(ULONG);
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetDataIntersection -- End, Size Only, STATUS_SUCCESS\n";
#endif
return(STATUS_SUCCESS);
}
pSrb->ActualBytesTransferred = FormatSize;
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetDataIntersection -- End, Returning STATUS_SUCCESS\n";
#endif
return(STATUS_SUCCESS);
}
void VidcapBaseStream::GetConnectionProperty(PHW_STREAM_REQUEST_BLOCK pSrb)
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetConnectionProperty -- Start\n";
#endif
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
ULONG Id = pSPD->Property->Id; // index of the property
switch (Id)
{
case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
if (NULL != m_pVideoInfoHeader)
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetConnectionProperty -- Got ALLOCATORFRAMING\n";
#endif
PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
Framing->RequirementsFlags =
KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
Framing->PoolType = PagedPool;
Framing->Frames = 1;
Framing->FrameSize = m_pVideoInfoHeader->bmiHeader.biSizeImage;
Framing->FileAlignment = 0; // FILE_LONG_ALIGNMENT???;
Framing->Reserved = 0;
pSrb->ActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
pSrb->Status = STATUS_SUCCESS;
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetConnectionProperty -- STATUS_SUCCESS\n";
#endif
}
else
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetConnectionProperty -- KSPROPERTY_CONNECTION_ALLOCATORFRAMING Invalid Parameter\n";
#endif
pSrb->Status = STATUS_INVALID_PARAMETER;
}
break;
default:
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetConnectionProperty -- STATUS_NOT_IMPLEMENTED\n";
#endif
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
}
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetConnectionProperty -- End\n";
#endif
}
void VidcapBaseStream::GetDroppedFramesProperty(PHW_STREAM_REQUEST_BLOCK pSrb)
{
#ifdef __VIDCAP_TRACEON__
TVS << TraceInfo << "VidcapBaseStream::GetDroppedFramesProperty -- Start\n";
#endif
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
ULONG Id = pSPD->Property->Id; // index of the property
switch (Id)
{
case KSPROPERTY_DROPPEDFRAMES_CURRENT:
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -