VOID STREAMAPI AdapterCloseStream ( PHW_STREAM_REQUEST_BLOCK pSrb ) { PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension; PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); int StreamNumber = pSrb->StreamObject->StreamNumber; PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat; KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader; DbgLogInfo(("TestCap: -------- ADAPTERCLOSESTREAM ------ StreamNumber=%d\n", StreamNumber)); if (pHwDevExt->StreamSRBListSize > 0) { VideoQueueCancelAllSRBs (pStrmEx); DbgLogError(("TestCap: Outstanding SRBs at stream close!!!\n")); } pHwDevExt->ActualInstances[StreamNumber]--; ASSERT (pHwDevExt->pStrmEx [StreamNumber] != 0); pHwDevExt->pStrmEx [StreamNumber] = 0; // // the minidriver should free any resources that were allocate at // open stream time etc. // // Free the variable length VIDEOINFOHEADER if (pVideoInfoHdr) { ExFreePool(pVideoInfoHdr); pStrmEx->pVideoInfoHeader = NULL; } // Make sure we no longer reference the clock pStrmEx->hMasterClock = NULL; // Make sure the state is reset to stopped, pStrmEx->KSState = KSSTATE_STOP; }
BOOL STREAMAPI VideoSetFormat( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension; PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); int StreamNumber = pSrb->StreamObject->StreamNumber; UINT nSize; PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat; // ------------------------------------------------------------------- // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER // ------------------------------------------------------------------- if (IsEqualGUID (&pKSDataFormat->Specifier, &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) { PKS_DATAFORMAT_VIDEOINFOHEADER pVideoInfoHeader = (PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat; PKS_VIDEOINFOHEADER pVideoInfoHdrRequested = &pVideoInfoHeader->VideoInfoHeader; nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested); DbgLogInfo(("TestCap: New Format\n")); DbgLogInfo(("TestCap: pVideoInfoHdrRequested=%p\n", pVideoInfoHdrRequested)); DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n", nSize)); DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n", pVideoInfoHdrRequested->bmiHeader.biWidth, pVideoInfoHdrRequested->bmiHeader.biHeight, pVideoInfoHdrRequested->bmiHeader.biBitCount)); DbgLogInfo(("TestCap: biSizeImage=%d\n", pVideoInfoHdrRequested->bmiHeader.biSizeImage)); // // If a previous format was in use, release the memory // if (pStrmEx->pVideoInfoHeader) { ExFreePool(pStrmEx->pVideoInfoHeader); pStrmEx->pVideoInfoHeader = NULL; } // Since the VIDEOINFOHEADER is of potentially variable size // allocate memory for it pStrmEx->pVideoInfoHeader = ExAllocatePool(NonPagedPool, nSize); if (pStrmEx->pVideoInfoHeader == NULL) { DbgLogError(("TestCap: ExAllocatePool failed\n")); pSrb->Status = STATUS_INSUFFICIENT_RESOURCES; return FALSE; } // Copy the VIDEOINFOHEADER requested to our storage RtlCopyMemory( pStrmEx->pVideoInfoHeader, pVideoInfoHdrRequested, nSize); // A renderer may be switching formats, and in this case, the AvgTimePerFrame // will be zero. Don't overwrite a previously set framerate. if (pStrmEx->pVideoInfoHeader->AvgTimePerFrame) { pStrmEx->AvgTimePerFrame = pStrmEx->pVideoInfoHeader->AvgTimePerFrame; } } else { // Unknown format pSrb->Status = STATUS_INVALID_PARAMETER; return FALSE; } return TRUE; }
BOOL STREAMAPI AdapterVerifyFormat( PKSDATAFORMAT pKSDataFormatToVerify, int StreamNumber ) { BOOL fOK = FALSE; ULONG j; ULONG NumberOfFormatArrayEntries; PKSDATAFORMAT *pAvailableFormats; // // Check that the stream number is valid // if (StreamNumber >= DRIVER_STREAM_COUNT) { TRAP; return FALSE; } NumberOfFormatArrayEntries = Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries; // // Get the pointer to the array of available formats // pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray; DbgLogInfo(("TestCap: AdapterVerifyFormat, Stream=%d\n", StreamNumber)); DbgLogInfo(("TestCap: FormatSize=%d\n", pKSDataFormatToVerify->FormatSize)); DbgLogInfo(("TestCap: MajorFormat=%x\n", pKSDataFormatToVerify->MajorFormat)); // // Walk the formats supported by the stream // for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) { // Check for a match on the three GUIDs and format size if (!AdapterCompareGUIDsAndFormatSize( 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; DbgLogInfo(("TestCap: AdapterVerifyFormat\n")); DbgLogInfo(("TestCap: pVideoInfoHdrToVerify=%x\n", pVideoInfoHdrToVerify)); DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n", KS_SIZE_VIDEOHEADER (pVideoInfoHdrToVerify))); DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n", pVideoInfoHdrToVerify->bmiHeader.biWidth, pVideoInfoHdrToVerify->bmiHeader.biHeight, pVideoInfoHdrToVerify->bmiHeader.biBitCount)); DbgLogInfo(("TestCap: biSizeImage=%d\n", pVideoInfoHdrToVerify->bmiHeader.biSizeImage)); /* ** 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; } // // 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; // // Perform all other verification tests here!!! // fOK = TRUE; break; } // End of KS_ANALOGVIDEOINFO specifier // ------------------------------------------------------------------- // Specifier FORMAT_VBI for KS_VIDEO_VBI // ------------------------------------------------------------------- else if (IsEqualGUID (&pKSDataFormatToVerify->Specifier, &KSDATAFORMAT_SPECIFIER_VBI)) { // // Do some VBI-specific tests // PKS_DATAFORMAT_VBIINFOHEADER pKSVBIDataFormat; DbgLogInfo(("Testcap: This is a VBIINFOHEADER format pin.\n" )); pKSVBIDataFormat = (PKS_DATAFORMAT_VBIINFOHEADER)pKSDataFormatToVerify; // // Check VideoStandard, we only support NTSC_M // if (KS_AnalogVideo_NTSC_M == pKSVBIDataFormat->VBIInfoHeader.VideoStandard) { fOK = TRUE; break; } else { DbgLogError( ("Testcap: AdapterVerifyFormat : VideoStandard(%d) != NTSC_M\n", pKSVBIDataFormat->VBIInfoHeader.VideoStandard)); } } // ------------------------------------------------------------------- // Type FORMAT_NABTS for NABTS pin // ------------------------------------------------------------------- else if (IsEqualGUID (&pKSDataFormatToVerify->SubFormat, &KSDATAFORMAT_SUBTYPE_NABTS)) { fOK = TRUE; break; } // ------------------------------------------------------------------- // for CC pin // ------------------------------------------------------------------- else if (IsEqualGUID (&pKSDataFormatToVerify->SubFormat, &KSDATAFORMAT_SUBTYPE_CC)) { fOK = TRUE; break; } } // End of loop on all formats for this stream return fOK; }
BOOL STREAMAPI AdapterFormatFromRange( IN PHW_STREAM_REQUEST_BLOCK pSrb ) { PSTREAM_DATA_INTERSECT_INFO IntersectInfo; PKSDATARANGE DataRange; BOOL OnlyWantsSize; BOOL MatchFound = FALSE; ULONG FormatSize; ULONG StreamNumber; ULONG j; ULONG NumberOfFormatArrayEntries; PKSDATAFORMAT *pAvailableFormats; DbgLogInfo(("TestCap: Enter AdapterFormatFromRange\n")); IntersectInfo = pSrb->CommandData.IntersectInfo; StreamNumber = IntersectInfo->StreamNumber; DataRange = IntersectInfo->DataRange; // // Check that the stream number is valid // if (StreamNumber >= DRIVER_STREAM_COUNT) { 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)); // // 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, 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; if(MatchFound) { DbgLogInfo(("TestCap: MatchFound!!!!\n")); } FormatSize = sizeof (KSDATAFORMAT) + KS_SIZE_VIDEOHEADER (&DataRangeVideoToVerify->VideoInfoHeader); 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 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); // // 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 FORMAT_VBI for KS_VIDEO_VBI // ------------------------------------------------------------------- else if (IsEqualGUID (&DataRange->Specifier, &KSDATAFORMAT_SPECIFIER_VBI)) { PKS_DATARANGE_VIDEO_VBI pDataRangeVBI = (PKS_DATARANGE_VIDEO_VBI)*pAvailableFormats; PKS_DATAFORMAT_VBIINFOHEADER InterVBIHdr = (PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer; // MATCH FOUND! MatchFound = TRUE; FormatSize = sizeof (KS_DATAFORMAT_VBIINFOHEADER); // Is the caller trying to get the format, or the size of it? if (OnlyWantsSize) break; // Verify that there is enough room in the supplied buffer // for the whole thing if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) { if (IntersectInfo->SizeOfDataFormatBuffer > 0) { DbgLogError( ("Testcap::AdapterFormatFromRange: " "Specifier==VBI, Buffer too small=%d vs. %d\n", IntersectInfo->SizeOfDataFormatBuffer, FormatSize)); } pSrb->Status = STATUS_BUFFER_TOO_SMALL; return FALSE; } // If there is room, go ahead... RtlCopyMemory(&InterVBIHdr->DataFormat, &pDataRangeVBI->DataRange, sizeof (KSDATARANGE)); ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize; RtlCopyMemory(&InterVBIHdr->VBIInfoHeader, &pDataRangeVBI->VBIInfoHeader, sizeof(KS_VBIINFOHEADER)); break; } // End of KS_VIDEO_VBI specifier // ------------------------------------------------------------------- // Type FORMAT_NABTS for NABTS pin // ------------------------------------------------------------------- else if (IsEqualGUID (&DataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_NABTS)) { PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats; // MATCH FOUND! MatchFound = TRUE; FormatSize = sizeof (KSDATAFORMAT); // Is the caller trying to get the format, or the size of it? if (OnlyWantsSize) break; // Verify that there is enough room in the supplied buffer // for the whole thing if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize) { RtlCopyMemory(IntersectInfo->DataFormatBuffer, pDataRange, FormatSize); ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize; } else { if (IntersectInfo->SizeOfDataFormatBuffer > 0) { DbgLogError( ("Testcap::AdapterFormatFromRange: " "SubFormat==NABTS, Buffer too small=%d vs. %d\n", IntersectInfo->SizeOfDataFormatBuffer, FormatSize)); } pSrb->Status = STATUS_BUFFER_TOO_SMALL; return FALSE; } break; } // End of KS_SUBTYPE_NABTS // ------------------------------------------------------------------- // for CC pin // ------------------------------------------------------------------- else if (IsEqualGUID (&DataRange->SubFormat, &KSDATAFORMAT_SUBTYPE_CC)) { PKSDATARANGE pDataRange = (PKSDATARANGE)*pAvailableFormats; // MATCH FOUND! MatchFound = TRUE; FormatSize = sizeof (KSDATAFORMAT); // Is the caller trying to get the format, or the size of it? if (OnlyWantsSize) break; // Verify that there is enough room in the supplied buffer // for the whole thing if (IntersectInfo->SizeOfDataFormatBuffer >= FormatSize) { RtlCopyMemory(IntersectInfo->DataFormatBuffer, pDataRange, FormatSize); ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize; } else { if (IntersectInfo->SizeOfDataFormatBuffer > 0) { DbgLogError( ("Testcap::AdapterFormatFromRange: " "SubFormat==CC, Buffer too small=%d vs. %d\n", IntersectInfo->SizeOfDataFormatBuffer, FormatSize)); } pSrb->Status = STATUS_BUFFER_TOO_SMALL; return FALSE; } break; } // End of CC pin format check else { pSrb->Status = STATUS_NO_MATCH; return FALSE; } } // End of loop on all formats for this stream if (!MatchFound) { pSrb->Status = STATUS_NO_MATCH; return FALSE; } if (OnlyWantsSize) { *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize; FormatSize = sizeof(ULONG); } pSrb->ActualBytesTransferred = FormatSize; return TRUE; }
BOOLEAN STREAMAPI HwInitialize ( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb ) { STREAM_PHYSICAL_ADDRESS adr; ULONG Size; PUCHAR pDmaBuf; int j; PPORT_CONFIGURATION_INFORMATION ConfigInfo = pSrb->CommandData.ConfigInfo; PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)ConfigInfo->HwDeviceExtension; DbgLogInfo(("Testcap: HwInitialize()\n")); if (ConfigInfo->NumberOfAccessRanges != 0) { DbgLogError(("Testcap: illegal config info\n")); pSrb->Status = STATUS_NO_SUCH_DEVICE; return (FALSE); } DbgLogInfo(("TestCap: Number of access ranges = %lx\n", ConfigInfo->NumberOfAccessRanges)); DbgLogInfo(("TestCap: Memory Range = %lx\n", pHwDevExt->ioBaseLocal)); DbgLogInfo(("TestCap: IRQ = %lx\n", ConfigInfo->BusInterruptLevel)); if (ConfigInfo->NumberOfAccessRanges != 0) { pHwDevExt->ioBaseLocal = (PULONG)(ULONG_PTR) (ConfigInfo->AccessRanges[0].RangeStart.LowPart); } pHwDevExt->Irq = (USHORT)(ConfigInfo->BusInterruptLevel); ConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) + DRIVER_STREAM_COUNT * sizeof (HW_STREAM_INFORMATION); pDmaBuf = StreamClassGetDmaBuffer(pHwDevExt); adr = StreamClassGetPhysicalAddress(pHwDevExt, NULL, pDmaBuf, DmaBuffer, &Size); // Init VideoProcAmp properties pHwDevExt->Brightness = BrightnessDefault; pHwDevExt->BrightnessFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO; pHwDevExt->Contrast = ContrastDefault; pHwDevExt->ContrastFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_AUTO; pHwDevExt->ColorEnable = ColorEnableDefault; pHwDevExt->ColorEnableFlags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL; // Init CameraControl properties pHwDevExt->Focus = FocusDefault; pHwDevExt->FocusFlags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO; pHwDevExt->Zoom = ZoomDefault; pHwDevExt->ZoomFlags = KSPROPERTY_CAMERACONTROL_FLAGS_AUTO; // Init VideoControl properties pHwDevExt->VideoControlMode = 0; // Init VideoCompression properties pHwDevExt->CompressionSettings.CompressionKeyFrameRate = 15; pHwDevExt->CompressionSettings.CompressionPFramesPerKeyFrame = 3; pHwDevExt->CompressionSettings.CompressionQuality = 5000; pHwDevExt->PDO = ConfigInfo->RealPhysicalDeviceObject; DbgLogInfo(("TestCap: Physical Device Object = %lx\n", pHwDevExt->PDO)); for (j = 0; j < MAX_TESTCAP_STREAMS; j++){ // For each stream, maintain a separate queue for data and control InitializeListHead (&pHwDevExt->StreamSRBList[j]); InitializeListHead (&pHwDevExt->StreamControlSRBList[j]); KeInitializeSpinLock (&pHwDevExt->StreamSRBSpinLock[j]); pHwDevExt->StreamSRBListSize[j] = 0; } // Init ProtectionStatus pHwDevExt->ProtectionStatus = 0; // The following allows multiple instance of identical hardware // to be installed. GlobalDriverMediumInstanceCount is set in the Medium.Id field. pHwDevExt->DriverMediumInstanceCount = GlobalDriverMediumInstanceCount++; DbgLogInfo(("TestCap: Exit, HwInitialize()\n")); pSrb->Status = STATUS_SUCCESS; return (TRUE); }
void ImageSynth ( IN OUT PHW_STREAM_REQUEST_BLOCK pSrb, IN ImageXferCommands Command, IN BOOL FlipHorizontal ) { PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension; PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension); int StreamNumber = pSrb->StreamObject->StreamNumber; KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader; UINT biWidth = pVideoInfoHdr->bmiHeader.biWidth; UINT biHeight = pVideoInfoHdr->bmiHeader.biHeight; UINT biSizeImage = pVideoInfoHdr->bmiHeader.biSizeImage; UINT biWidthBytes = KS_DIBWIDTHBYTES (pVideoInfoHdr->bmiHeader); UINT biBitCount = pVideoInfoHdr->bmiHeader.biBitCount; UINT LinesToCopy = abs (biHeight); DWORD biCompression = pVideoInfoHdr->bmiHeader.biCompression; UINT Line; PUCHAR pLineBuffer; PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray; PUCHAR pImage = pDataPacket->Data; DEBUG_ASSERT (pSrb->NumberOfBuffers == 1); #if 0 // Note: set "ulInDebug = 1" in a debugger to view this output with .ntkern DbgLogTrace(("\'TestCap: ImageSynthBegin\n")); DbgLogTrace(("\'TestCap: biSizeImage=%d, DataPacketLength=%d\n", biSizeImage, pDataPacket->DataPacketLength)); DbgLogTrace(("\'TestCap: biWidth=%d biHeight=%d WidthBytes=%d bpp=%d\n", biWidth, biHeight, biWidthBytes, biBitCount)); DbgLogTrace(("\'TestCap: pImage=%x\n", pImage)); #endif // // Synthesize a single line of image data, which will then be replicated // pLineBuffer = &pStrmEx->LineBuffer[0]; if ((biBitCount == 24) && (biCompression == KS_BI_RGB)) { switch (Command) { case IMAGE_XFER_NTSC_EIA_100AMP_100SAT: // 100% saturation { UINT x, col; PUCHAR pT = pLineBuffer; for (x = 0; x < biWidth; x++) { col = (x * 8) / biWidth; col = FlipHorizontal ? (7 - col) : col; *pT++ = NTSCColorBars100Amp100SatRGB24[0][col]; // Red *pT++ = NTSCColorBars100Amp100SatRGB24[1][col]; // Green *pT++ = NTSCColorBars100Amp100SatRGB24[2][col]; // Blue } } break; case IMAGE_XFER_NTSC_EIA_75AMP_100SAT: // 75% Saturation { UINT x, col; PUCHAR pT = pLineBuffer; for (x = 0; x < biWidth; x++) { col = (x * 8) / biWidth; col = FlipHorizontal ? (7 - col) : col; *pT++ = NTSCColorBars75Amp100SatRGB24[0][col]; // Red *pT++ = NTSCColorBars75Amp100SatRGB24[1][col]; // Green *pT++ = NTSCColorBars75Amp100SatRGB24[2][col]; // Blue } } break; case IMAGE_XFER_BLACK: // Camma corrected Grayscale ramp { UINT x, col; PUCHAR pT = pLineBuffer; for (x = 0; x < biWidth; x++) { col = (255 * (x * 10) / biWidth) / 10; col = FlipHorizontal ? (255 - col) : col; *pT++ = (BYTE) col; // Red *pT++ = (BYTE) col; // Green *pT++ = (BYTE) col; // Blue } } break; case IMAGE_XFER_WHITE: // All white RtlFillMemory( pLineBuffer, biWidthBytes, (UCHAR) 255); break; case IMAGE_XFER_GRAY_INCREASING: // grayscale increasing with each image captured RtlFillMemory( pLineBuffer, biWidthBytes, (UCHAR) (pStrmEx->FrameInfo.PictureNumber * 8)); break; default: break; } } // endif RGB24 else if ((biBitCount == 16) && (biCompression == FOURCC_YUV422)) { switch (Command) { case IMAGE_XFER_NTSC_EIA_100AMP_100SAT: default: { UINT x, col; PUCHAR pT = pLineBuffer; for (x = 0; x < (biWidth / 2); x++) { col = (x * 8) / (biWidth / 2); col = FlipHorizontal ? (7 - col) : col; *pT++ = NTSCColorBars100Amp100SatYUV[0][col]; // U *pT++ = NTSCColorBars100Amp100SatYUV[1][col]; // Y *pT++ = NTSCColorBars100Amp100SatYUV[2][col]; // V *pT++ = NTSCColorBars100Amp100SatYUV[3][col]; // Y } } break; } } else { DbgLogError(("\'TestCap: Unknown format in ImageSynth!!!\n")); TRAP; } // // Copy the single line synthesized to all rows of the image // for (Line = 0; Line < LinesToCopy; Line++, pImage += biWidthBytes) { // Show some action on an otherwise static image // This will be a changing grayscale horizontal band // at the bottom of an RGB image and a changing color band at the // top of a YUV image if (Line >= 3 && Line <= 6) { UINT j; for (j = 0; j < biWidthBytes; j++) { *(pImage + j) = (UCHAR) pStrmEx->FrameInfo.PictureNumber; } continue; } // Copy the synthesized line RtlCopyMemory( pImage, pLineBuffer, biWidthBytes); } // // Report back the actual number of bytes copied to the destination buffer // (This can be smaller than the allocated buffer for compressed images) // pDataPacket->DataUsed = biSizeImage; }