//==========================================================================; // // 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); }