Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1019 lines
34 KiB

//==========================================================================;
//
// WDM Video Decoder common SRB dispatcher
//
// $Date: 02 Oct 1998 23:00:24 $
// $Revision: 1.2 $
// $Author: KLEBANOV $
//
// $Copyright: (c) 1997 - 1998 ATI Technologies Inc. All Rights Reserved. $
//
//==========================================================================;
extern "C"
{
#include "strmini.h"
#include "ksmedia.h"
}
#include "wdmvdec.h"
#include "wdmdrv.h"
#include "capdebug.h"
#include "VidStrm.h"
#include "DecProp.h"
#include "StrmInfo.h"
#include "Mediums.h"
#include "mytypes.h"
extern NTSTATUS STREAMAPI DeviceEventProc( PHW_EVENT_DESCRIPTOR pEventDescriptor);
CWDMVideoDecoder::CWDMVideoDecoder(PPORT_CONFIGURATION_INFORMATION pConfigInfo,
CVideoDecoderDevice* pDevice)
: m_pDeviceObject(pConfigInfo->RealPhysicalDeviceObject),
m_CDecoderVPort(pConfigInfo->RealPhysicalDeviceObject),
m_pDevice(pDevice),
m_TVTunerChangedSrb( NULL)
{
DBGTRACE(("CWDMVideoDecoder:CWDMVideoDecoder() enter\n"));
DBGINFO(("Physical Device Object = %lx\n", m_pDeviceObject));
pConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) +
NumStreams * sizeof (HW_STREAM_INFORMATION);
InitializeListHead(&m_srbQueue);
KeInitializeSpinLock(&m_spinLock);
m_bSrbInProcess = FALSE;
if (pDevice)
{
pDevice->SetVideoDecoder(this);
}
}
CWDMVideoDecoder::~CWDMVideoDecoder()
{
DBGTRACE(("CWDMVideoDecoder:~CWDMVideoDecoder()\n"));
}
void CWDMVideoDecoder::ReceivePacket(PHW_STREAM_REQUEST_BLOCK pSrb)
{
KIRQL Irql;
PSRB_DATA_EXTENSION pSrbExt;
KeAcquireSpinLock(&m_spinLock, &Irql);
if (m_bSrbInProcess)
{
pSrbExt = (PSRB_DATA_EXTENSION)pSrb->SRBExtension;
pSrbExt->pSrb = pSrb;
InsertTailList(&m_srbQueue, &pSrbExt->srbListEntry);
KeReleaseSpinLock(&m_spinLock, Irql);
return;
}
m_bSrbInProcess = TRUE;
KeReleaseSpinLock(&m_spinLock, Irql);
for (;;) {
// Assume success. Might be changed below
pSrb->Status = STATUS_SUCCESS;
BOOL notify = TRUE;
// determine the type of packet.
switch(pSrb->Command)
{
case SRB_INITIALIZATION_COMPLETE:
DBGTRACE(("SRB_INITIALIZATION_COMPLETE; SRB=%x\n", pSrb));
// Stream class has finished initialization.
// Now create DShow Medium interface BLOBs.
// This needs to be done at low priority since it uses the registry
//
// Do we need to worry about synchronization here?
SrbInitializationComplete(pSrb);
break;
case SRB_UNINITIALIZE_DEVICE:
DBGTRACE(("SRB_UNINITIALIZE_DEVICE; SRB=%x\n", pSrb));
// close the device.
break;
case SRB_PAGING_OUT_DRIVER:
DBGTRACE(("SRB_PAGING_OUT_DRIVER; SRB=%x\n", pSrb));
//
// The driver is being paged out
// Disable Interrupts if you have them!
//
break;
case SRB_CHANGE_POWER_STATE:
DBGTRACE(("SRB_CHANGE_POWER_STATE. SRB=%x. State=%d\n",
pSrb, pSrb->CommandData.DeviceState));
SrbChangePowerState(pSrb);
break;
case SRB_OPEN_STREAM:
DBGTRACE(("SRB_OPEN_STREAM; SRB=%x\n", pSrb));
SrbOpenStream(pSrb);
break;
case SRB_CLOSE_STREAM:
DBGTRACE(("SRB_CLOSE_STREAM; SRB=%x\n", pSrb));
if (!IsListEmpty(&m_srbQueue)) // is this necessary ???
{
TRAP();
}
SrbCloseStream(pSrb);
break;
case SRB_GET_DATA_INTERSECTION:
DBGTRACE(("SRB_GET_DATA_INTERSECTION; SRB=%x\n", pSrb));
SrbGetDataIntersection(pSrb);
break;
case SRB_GET_STREAM_INFO:
SrbGetStreamInfo(pSrb);
break;
case SRB_GET_DEVICE_PROPERTY:
SrbGetProperty(pSrb);
break;
case SRB_SET_DEVICE_PROPERTY:
SrbSetProperty(pSrb);
break;
case SRB_WRITE_DATA:
DBGTRACE(("SRB_WRITE_DATA; SRB=%x\n", pSrb));
SetTunerInfo(pSrb);
StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
notify = FALSE;
break;
case SRB_UNKNOWN_DEVICE_COMMAND:
// not sure why this gets called every time.
DBGTRACE(("SRB_UNKNOWN_DEVICE_COMMAND; SRB=%x\n", pSrb));
// TRAP()();
pSrb->Status = STATUS_NOT_IMPLEMENTED;
break;
case SRB_OPEN_DEVICE_INSTANCE:
case SRB_CLOSE_DEVICE_INSTANCE:
default:
TRAP();
// this is a request that we do not understand. Indicate invalid command and complete the request
pSrb->Status = STATUS_NOT_IMPLEMENTED;
}
if (notify)
StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
KeAcquireSpinLock(&m_spinLock, &Irql);
if (IsListEmpty(&m_srbQueue))
{
m_bSrbInProcess = FALSE;
KeReleaseSpinLock(&m_spinLock, Irql);
return;
}
else
{
pSrbExt = (PSRB_DATA_EXTENSION)RemoveHeadList(&m_srbQueue);
KeReleaseSpinLock(&m_spinLock, Irql);
pSrb = pSrbExt->pSrb;
}
}
}
void CWDMVideoDecoder::CancelPacket( PHW_STREAM_REQUEST_BLOCK pSrbToCancel)
{
CWDMVideoStream* pVideoStream = ( CWDMVideoStream*)pSrbToCancel->StreamObject->HwStreamExtension;
DBGINFO(( "Bt829: AdapterCancelPacket, Starting attempting to cancel Srb 0x%x\n",
pSrbToCancel));
if( pVideoStream == NULL)
{
//
// Device command IRPs are not queued, so nothing to do
//
DBGINFO(( "Bt829: AdapterCancelPacketStart, no pVideoStream Srb 0x%x\n",
pSrbToCancel));
return;
}
pVideoStream->CancelPacket( pSrbToCancel);
DBGINFO(( "Bt829: AdapterCancelPacket, Exiting\n"));
}
void CWDMVideoDecoder::TimeoutPacket(PHW_STREAM_REQUEST_BLOCK pSrb)
{
CWDMVideoStream * pVideoStream = (CWDMVideoStream *)pSrb->StreamObject->HwStreamExtension;
DBGTRACE(("Timeout. SRB %8x. \n", pSrb));
pVideoStream->TimeoutPacket(pSrb);
DBGTRACE(("TimeoutPacket: SRB %8x. Resetting.\n", pSrb));
pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
}
BOOL CWDMVideoDecoder::SrbInitializationComplete(PHW_STREAM_REQUEST_BLOCK pSrb)
{
NTSTATUS Status;
ULONG *tmp = (ULONG *) &CrossbarPinDirection[0];
// Create the Registry blobs that DShow uses to create
// graphs via Mediums
Status = StreamClassRegisterFilterWithNoKSPins (
m_pDeviceObject, // IN PDEVICE_OBJECT DeviceObject,
&KSCATEGORY_CROSSBAR, // IN GUID * InterfaceClassGUID,
CrossbarPins(), // IN ULONG PinCount,
(int *) CrossbarPinDirection, // IN ULONG * Flags,
(KSPIN_MEDIUM *) CrossbarMediums, // IN KSPIN_MEDIUM * MediumList,
NULL // IN GUID * CategoryList
);
// Register the Capture filter
// Note: This should be done automatically be MSKsSrv.sys,
// when that component comes on line (if ever) ...
Status = StreamClassRegisterFilterWithNoKSPins (
m_pDeviceObject, // IN PDEVICE_OBJECT DeviceObject,
&KSCATEGORY_CAPTURE, // IN GUID * InterfaceClassGUID,
CapturePins(), // IN ULONG PinCount,
(int *) CapturePinDirection, // IN ULONG * Flags,
(KSPIN_MEDIUM *) CaptureMediums, // IN KSPIN_MEDIUM * MediumList,
NULL // IN GUID * CategoryList
);
pSrb->Status = STATUS_SUCCESS;
return(TRUE);
}
BOOL CWDMVideoDecoder::SrbOpenStream(PHW_STREAM_REQUEST_BLOCK pSrb)
{
DBGTRACE(("CWDMVideoDecoder:SrbOpenStream()\n"));
PHW_STREAM_OBJECT pStreamObject = pSrb->StreamObject;
void * pStrmEx = pStreamObject->HwStreamExtension;
int StreamNumber = pStreamObject->StreamNumber;
PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
CWDMVideoStream * pVideoStream;
CWDMVideoPortStream * pVPVBIStream;
UINT nErrorCode;
RtlZeroMemory(pStrmEx, streamDataExtensionSize);
DBGINFO(("SRBOPENSTREAM ------- StreamNumber=%d\n", StreamNumber));
//
// check that the stream index requested isn't too high
// or that the maximum number of instances hasn't been exceeded
//
if (StreamNumber >= (int)NumStreams || StreamNumber < 0) {
pSrb->Status = STATUS_INVALID_PARAMETER;
goto Exit;
}
//
// Check the validity of the format being requested
//
if (!AdapterVerifyFormat (pKSDataFormat, StreamNumber)) {
pSrb->Status = STATUS_INVALID_PARAMETER;
goto Exit;
}
//
// Set up pointers to the handlers for the stream data and control handlers
//
pStreamObject->ReceiveDataPacket = VideoReceiveDataPacket;
pStreamObject->ReceiveControlPacket = VideoReceiveCtrlPacket;
//
// Indicate the clock support available on this stream
//
pStreamObject->HwClockObject.HwClockFunction = NULL;
pStreamObject->HwClockObject.ClockSupportFlags = 0;
//
// The DMA flag must be set when the device will be performing DMA directly
// to the data buffer addresses passed in to the ReceiceDataPacket routines.
//
pStreamObject->Dma = Streams[StreamNumber].hwStreamObjectInfo.Dma;
//
// The PIO flag must be set when the mini driver will be accessing the data
// buffers passed in using logical addressing
//
pStreamObject->Pio = Streams[StreamNumber].hwStreamObjectInfo.Pio;
//
// How many extra bytes will be passed up from the driver for each frame?
//
pStreamObject->StreamHeaderMediaSpecific =
Streams[StreamNumber].hwStreamObjectInfo.StreamHeaderMediaSpecific;
pStreamObject->StreamHeaderWorkspace =
Streams[StreamNumber].hwStreamObjectInfo.StreamHeaderWorkspace;
//
// Indicate the allocator support available on this stream
//
pStreamObject->Allocator = Streams[StreamNumber].hwStreamObjectInfo.Allocator;
//
// Indicate the event support available on this stream
//
pStreamObject->HwEventRoutine =
Streams[StreamNumber].hwStreamObjectInfo.HwEventRoutine;
switch (StreamNumber)
{
case STREAM_AnalogVideoInput:
ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_ANALOGVIDEO));
pVideoStream = (CWDMVideoStream *)new(pStrmEx)
CWDMVideoStream(pStreamObject, this, &nErrorCode);
break;
case STREAM_VideoCapture:
ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO));
m_pVideoCaptureStream = (CWDMVideoCaptureStream *)new(pStrmEx)
CWDMVideoCaptureStream(pStreamObject, this, pKSDataFormat, &nErrorCode);
if (m_pVideoPortStream)
{
m_pVideoPortStream->AttemptRenegotiation();
}
break;
case STREAM_VBICapture:
ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_VBI));
m_pVBICaptureStream = (CWDMVBICaptureStream *)new(pStrmEx)
CWDMVBICaptureStream(pStreamObject, this, pKSDataFormat, &nErrorCode);
break;
case STREAM_VPVideo:
ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_NONE) &&
IsEqualGUID(pKSDataFormat->SubFormat, KSDATAFORMAT_SUBTYPE_VPVideo));
m_pVideoPortStream = (CWDMVideoPortStream *)new(pStrmEx)
CWDMVideoPortStream(pStreamObject, this, &nErrorCode);
if (m_pVideoCaptureStream == NULL)
{
MRect t(0, 0, m_pDevice->GetDefaultDecoderWidth(),
m_pDevice->GetDefaultDecoderHeight());
m_pDevice->SetRect(t);
}
break;
case STREAM_VPVBI:
ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_NONE) &&
IsEqualGUID(pKSDataFormat->SubFormat, KSDATAFORMAT_SUBTYPE_VPVBI));
pVPVBIStream = (CWDMVideoPortStream *)new(pStrmEx)
CWDMVideoPortStream(pStreamObject, this, &nErrorCode);
m_pDevice->SetVBIEN(TRUE);
m_pDevice->SetVBIFMT(TRUE);
break;
default:
pSrb->Status = STATUS_UNSUCCESSFUL;
goto Exit;
}
if(nErrorCode == WDMMINI_NOERROR)
m_OpenStreams++;
else
pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
Exit:
DBGTRACE(("SrbOpenStream Exit\n"));
return(TRUE);
}
BOOL CWDMVideoDecoder::SrbCloseStream(PHW_STREAM_REQUEST_BLOCK pSrb)
{
int StreamNumber = pSrb->StreamObject->StreamNumber;
DBGTRACE(("CWDMVideoDecoder:SrbCloseStream()\n"));
DBGINFO(("SRBCLOSESTREAM ------- StreamNumber=%d\n", StreamNumber));
//
// the minidriver may wish to free any resources that were allocated at
// open stream time etc.
//
CWDMVideoStream * pVideoStream = (CWDMVideoStream *)pSrb->StreamObject->HwStreamExtension;
delete pVideoStream;
switch (StreamNumber)
{
case STREAM_AnalogVideoInput:
break;
case STREAM_VideoCapture:
m_pVideoCaptureStream = NULL;
break;
case STREAM_VBICapture:
m_pVBICaptureStream = NULL;
break;
case STREAM_VPVideo:
m_pVideoPortStream = NULL;
break;
case STREAM_VPVBI:
m_pDevice->SetVBIEN(FALSE);
m_pDevice->SetVBIFMT(FALSE);
break;
default:
pSrb->Status = STATUS_UNSUCCESSFUL;
return FALSE;
}
if (--m_OpenStreams == 0)
{
DBGINFO(("Last one out turns off the lights\n"));
m_CDecoderVPort.Close();
m_preEventOccurred = FALSE;
m_postEventOccurred = FALSE;
m_pDevice->SaveState();
}
pSrb->Status = STATUS_SUCCESS;
return TRUE;
}
BOOL CWDMVideoDecoder::SrbGetDataIntersection(PHW_STREAM_REQUEST_BLOCK pSrb)
{
DBGTRACE(("CWDMVideoDecoder:SrbGetDataIntersection()\n"));
PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
PKSDATARANGE DataRange;
BOOL OnlyWantsSize;
BOOL MatchFound = FALSE;
ULONG FormatSize;
ULONG StreamNumber;
ULONG j;
ULONG NumberOfFormatArrayEntries;
PKSDATAFORMAT *pAvailableFormats;
IntersectInfo = pSrb->CommandData.IntersectInfo;
StreamNumber = IntersectInfo->StreamNumber;
DataRange = IntersectInfo->DataRange;
//
// Check that the stream number is valid
//
if (StreamNumber >= NumStreams) {
pSrb->Status = STATUS_NOT_IMPLEMENTED;
TRAP();
return FALSE;
}
NumberOfFormatArrayEntries =
Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
//
// Get the pointer to the array of available formats
//
pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
//
// Is the caller trying to get the format, or the size of the format?
//
OnlyWantsSize = ( (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG)) ||
(IntersectInfo->SizeOfDataFormatBuffer == 0) );
//
// Walk the formats supported by the stream searching for a match
// of the three GUIDs which together define a DATARANGE
//
for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
if (!AdapterCompareGUIDsAndFormatSize(
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;
}
// Validate each step of the size calculations for arithmetic overflow,
// and verify that the specified sizes correlate
// (with unsigned math, a+b < b iff an arithmetic overflow occured)
ULONG VideoHeaderSize = DataRangeVideoToVerify->VideoInfoHeader.bmiHeader.biSize +
FIELD_OFFSET(KS_VIDEOINFOHEADER,bmiHeader);
ULONG RangeSize = VideoHeaderSize +
FIELD_OFFSET(KS_DATARANGE_VIDEO,VideoInfoHeader);
if (VideoHeaderSize < FIELD_OFFSET(KS_VIDEOINFOHEADER,bmiHeader) ||
RangeSize < FIELD_OFFSET(KS_DATARANGE_VIDEO,VideoInfoHeader) ||
RangeSize > DataRangeVideoToVerify->DataRange.FormatSize) {
pSrb->Status = STATUS_INVALID_PARAMETER;
return FALSE;
}
// MATCH FOUND!
MatchFound = TRUE;
FormatSize = sizeof (KSDATAFORMAT) +
VideoHeaderSize;
if (OnlyWantsSize) {
break;
}
// Caller wants the full data format
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
// 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 caller's requested VIDEOINFOHEADER
RtlCopyMemory(
&DataFormatVideoInfoHeaderOut->VideoInfoHeader,
&DataRangeVideoToVerify->VideoInfoHeader,
VideoHeaderSize);
// 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);
//
// 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) {
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
RtlCopyMemory(
IntersectInfo->DataFormatBuffer,
DataRangeVideo,
sizeof (KS_DATARANGE_ANALOGVIDEO));
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
break;
} // End of KS_ANALOGVIDEOINFO specifier
// -------------------------------------------------------------------
// Specifier STATIC_KSDATAFORMAT_TYPE_VIDEO for Video Port
// -------------------------------------------------------------------
else if (IsEqualGUID (DataRange->Specifier,
KSDATAFORMAT_SPECIFIER_NONE) &&
IsEqualGUID (DataRange->SubFormat, KSDATAFORMAT_SUBTYPE_VPVideo)) {
// MATCH FOUND!
MatchFound = TRUE;
FormatSize = sizeof (KSDATAFORMAT);
if (OnlyWantsSize) {
break;
}
// Caller wants the full data format
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
RtlCopyMemory(
IntersectInfo->DataFormatBuffer,
&StreamFormatVideoPort,
sizeof (KSDATAFORMAT));
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
break;
}
// -------------------------------------------------------------------
// Specifier KSDATAFORMAT_SPECIFIER_NONE for VP VBI
// -------------------------------------------------------------------
else if (IsEqualGUID (DataRange->Specifier,
KSDATAFORMAT_SPECIFIER_NONE) &&
IsEqualGUID (DataRange->SubFormat, KSDATAFORMAT_SUBTYPE_VPVBI)) {
// MATCH FOUND!
MatchFound = TRUE;
FormatSize = sizeof (KSDATAFORMAT);
if (OnlyWantsSize) {
break;
}
// Caller wants the full data format
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
RtlCopyMemory(
IntersectInfo->DataFormatBuffer,
&StreamFormatVideoPortVBI,
sizeof (KSDATAFORMAT));
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
break;
}
// -------------------------------------------------------------------
// Specifier STATIC_KSDATAFORMAT_TYPE_NONE for VBI capture stream
// -------------------------------------------------------------------
else if (IsEqualGUID (DataRange->Specifier,
KSDATAFORMAT_SPECIFIER_VBI)) {
PKS_DATARANGE_VIDEO_VBI DataRangeVBIToVerify =
(PKS_DATARANGE_VIDEO_VBI) DataRange;
PKS_DATARANGE_VIDEO_VBI DataRangeVBI =
(PKS_DATARANGE_VIDEO_VBI) *pAvailableFormats;
//
// Check that the other fields match
//
if ((DataRangeVBIToVerify->bFixedSizeSamples != DataRangeVBI->bFixedSizeSamples) ||
(DataRangeVBIToVerify->bTemporalCompression != DataRangeVBI->bTemporalCompression) ||
(DataRangeVBIToVerify->StreamDescriptionFlags != DataRangeVBI->StreamDescriptionFlags) ||
(DataRangeVBIToVerify->MemoryAllocationFlags != DataRangeVBI->MemoryAllocationFlags) ||
(RtlCompareMemory (&DataRangeVBIToVerify->ConfigCaps,
&DataRangeVBI->ConfigCaps,
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS))) {
continue;
}
// MATCH FOUND!
MatchFound = TRUE;
FormatSize = sizeof (KS_DATAFORMAT_VBIINFOHEADER);
if (OnlyWantsSize) {
break;
}
// Caller wants the full data format
if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
pSrb->Status = STATUS_BUFFER_TOO_SMALL;
return FALSE;
}
// Copy over the KSDATAFORMAT, followed by the
// actual VBIInfoHeader
RtlCopyMemory(
&((PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer)->DataFormat,
&DataRangeVBIToVerify->DataRange,
sizeof (KSDATARANGE));
((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
RtlCopyMemory(
&((PKS_DATAFORMAT_VBIINFOHEADER) IntersectInfo->DataFormatBuffer)->VBIInfoHeader,
&DataRangeVBIToVerify->VBIInfoHeader,
sizeof (KS_VBIINFOHEADER));
}
} // End of loop on all formats for this stream
if (!MatchFound) {
pSrb->Status = STATUS_NO_MATCH;
return FALSE;
}
if (OnlyWantsSize) {
// Check for special case where there is no buffer being passed
if ( IntersectInfo->SizeOfDataFormatBuffer == 0 ) {
pSrb->Status = STATUS_BUFFER_OVERFLOW;
}
else {
*(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
FormatSize = sizeof(ULONG);
}
}
pSrb->ActualBytesTransferred = FormatSize;
return TRUE;
}
void CWDMVideoDecoder::SrbGetStreamInfo(PHW_STREAM_REQUEST_BLOCK pSrb)
{
DBGTRACE(("CWDMVideoDecoder:SrbGetStreamInfo()\n"));
//
// verify that the buffer is large enough to hold our return data
//
DEBUG_ASSERT (pSrb->NumberOfBytesToTransfer >=
sizeof (HW_STREAM_HEADER) +
sizeof (HW_STREAM_INFORMATION) * NumStreams);
//
// Set the header
//
PHW_STREAM_HEADER pstrhdr =
(PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
pstrhdr->NumberOfStreams = NumStreams;
pstrhdr->SizeOfHwStreamInformation = sizeof (HW_STREAM_INFORMATION);
pstrhdr->NumDevPropArrayEntries = NumAdapterProperties();
pstrhdr->DevicePropertiesArray = (PKSPROPERTY_SET)AdapterProperties;
pstrhdr->Topology = &Topology;
//
// stuff the contents of each HW_STREAM_INFORMATION struct
//
PHW_STREAM_INFORMATION pstrinfo =
(PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
for (unsigned j = 0; j < NumStreams; j++) {
*pstrinfo++ = Streams[j].hwStreamInfo;
}
DBGTRACE(("Exit: CWDMVideoDecoder:SrbGetStreamInfo()\n"));
}
VOID CWDMVideoDecoder::SrbSetProperty (PHW_STREAM_REQUEST_BLOCK pSrb)
{
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
if (IsEqualGUID(PROPSETID_VIDCAP_CROSSBAR, pSPD->Property->Set)) {
m_pDevice->SetCrossbarProperty (pSrb);
}
else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEOPROCAMP, pSPD->Property->Set)) {
ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_VIDEOPROCAMP_S));
ULONG Id = pSPD->Property->Id; // index of the property
PKSPROPERTY_VIDEOPROCAMP_S pS = (PKSPROPERTY_VIDEOPROCAMP_S) pSPD->PropertyInfo; // pointer to the data
pSrb->Status = m_pDevice->SetProcAmpProperty(Id, pS->Value);
}
else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEODECODER, pSPD->Property->Set)) {
m_pDevice->SetDecoderProperty (pSrb);
}
else
DBGERROR(("CWDMVideoDecoder:SrbSetProperty() unknown property\n"));
}
VOID CWDMVideoDecoder::SrbGetProperty (PHW_STREAM_REQUEST_BLOCK pSrb)
{
PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
if (IsEqualGUID (PROPSETID_VIDCAP_CROSSBAR, pSPD->Property->Set)) {
m_pDevice->GetCrossbarProperty (pSrb);
}
else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEOPROCAMP, pSPD->Property->Set)) {
ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_VIDEOPROCAMP_S));
ULONG Id = pSPD->Property->Id; // index of the property
PKSPROPERTY_VIDEOPROCAMP_S pS = (PKSPROPERTY_VIDEOPROCAMP_S) pSPD->PropertyInfo; // pointer to the data
RtlCopyMemory(pS, pSPD->Property, sizeof(KSPROPERTY));
pS->Capabilities = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
pSrb->Status = m_pDevice->GetProcAmpProperty(Id, &pS->Value);
pSrb->ActualBytesTransferred = pSrb->Status == STATUS_SUCCESS ?
sizeof (KSPROPERTY_VIDEOPROCAMP_S) : 0;
}
else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEODECODER, pSPD->Property->Set)) {
m_pDevice->GetDecoderProperty (pSrb);
}
else
DBGERROR(("CWDMVideoDecoder:SrbGetProperty() unknown property\n"));
}
void CWDMVideoDecoder::SetTunerInfo( PHW_STREAM_REQUEST_BLOCK pSrb)
{
PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
ASSERT (pDataPacket->FrameExtent == sizeof (KS_TVTUNER_CHANGE_INFO));
KIRQL Irql;
if (m_pVBICaptureStream)
m_pVBICaptureStream->DataLock(&Irql);
RtlCopyMemory( &m_TVTunerChangeInfo,
pDataPacket->Data,
sizeof (KS_TVTUNER_CHANGE_INFO));
m_TVTunerChanged = TRUE;
if (m_pVBICaptureStream)
m_pVBICaptureStream->DataUnLock(Irql);
}
BOOL CWDMVideoDecoder::GetTunerInfo(KS_TVTUNER_CHANGE_INFO* pTVChangeInfo)
{
if (m_TVTunerChanged) {
KIRQL Irql;
m_pVBICaptureStream->DataLock(&Irql);
RtlCopyMemory(pTVChangeInfo, &m_TVTunerChangeInfo, sizeof (KS_TVTUNER_CHANGE_INFO));
m_TVTunerChanged = FALSE;
m_pVBICaptureStream->DataUnLock(Irql);
return TRUE;
}
else
return FALSE;
}
BOOL CWDMVideoDecoder::SrbChangePowerState(PHW_STREAM_REQUEST_BLOCK pSrb)
{
DBGTRACE(("CWDMVideoDecoder:SrbChangePowerState()\n"));
switch (pSrb->CommandData.DeviceState)
{
case PowerDeviceD3:
m_preEventOccurred = TRUE;
m_pDevice->SaveState();
break;
case PowerDeviceD2:
m_preEventOccurred = TRUE;
m_pDevice->SaveState();
break;
case PowerDeviceD1:
m_preEventOccurred = TRUE;
m_pDevice->SaveState();
break;
case PowerDeviceD0:
m_postEventOccurred = TRUE;
m_pDevice->RestoreState(m_OpenStreams);
break;
}
pSrb->Status = STATUS_SUCCESS;
return(TRUE);
}
VOID CWDMVideoPortStream::AttemptRenegotiation()
{
int streamNumber = m_pStreamObject->StreamNumber;
if (m_EventCount)
{
DBGINFO(("Attempting renegotiation on stream %d\n", streamNumber));
if (streamNumber == STREAM_VPVideo)
{
StreamClassStreamNotification(
SignalMultipleStreamEvents,
m_pStreamObject,
&MY_KSEVENTSETID_VPNOTIFY,
KSEVENT_VPNOTIFY_FORMATCHANGE);
}
else if (streamNumber == STREAM_VPVBI)
{
StreamClassStreamNotification(
SignalMultipleStreamEvents,
m_pStreamObject,
&MY_KSEVENTSETID_VPVBINOTIFY,
KSEVENT_VPVBINOTIFY_FORMATCHANGE);
}
else
ASSERT(0);
}
else
{
DBGINFO(("NOT attempting renegotiation on stream %d\n", streamNumber));
}
}
NTSTATUS CWDMVideoDecoder::EventProc( IN PHW_EVENT_DESCRIPTOR pEventDescriptor)
{
if( pEventDescriptor->Enable)
m_nMVDetectionEventCount++;
else
m_nMVDetectionEventCount--;
return( STATUS_SUCCESS);
}