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