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

  1. //==========================================================================;
  2. //
  3. // WDM Video Decoder common SRB dispatcher
  4. //
  5. // $Date: 02 Oct 1998 23:00:24 $
  6. // $Revision: 1.2 $
  7. // $Author: KLEBANOV $
  8. //
  9. // $Copyright: (c) 1997 - 1998 ATI Technologies Inc. All Rights Reserved. $
  10. //
  11. //==========================================================================;
  12. extern "C"
  13. {
  14. #include "strmini.h"
  15. #include "ksmedia.h"
  16. }
  17. #include "wdmvdec.h"
  18. #include "wdmdrv.h"
  19. #include "capdebug.h"
  20. #include "VidStrm.h"
  21. #include "DecProp.h"
  22. #include "StrmInfo.h"
  23. #include "Mediums.h"
  24. #include "mytypes.h"
  25. extern NTSTATUS STREAMAPI DeviceEventProc( PHW_EVENT_DESCRIPTOR pEventDescriptor);
  26. CWDMVideoDecoder::CWDMVideoDecoder(PPORT_CONFIGURATION_INFORMATION pConfigInfo,
  27. CVideoDecoderDevice* pDevice)
  28. : m_pDeviceObject(pConfigInfo->RealPhysicalDeviceObject),
  29. m_CDecoderVPort(pConfigInfo->RealPhysicalDeviceObject),
  30. m_pDevice(pDevice),
  31. m_TVTunerChangedSrb( NULL)
  32. {
  33. DBGTRACE(("CWDMVideoDecoder:CWDMVideoDecoder() enter\n"));
  34. DBGINFO(("Physical Device Object = %lx\n", m_pDeviceObject));
  35. pConfigInfo->StreamDescriptorSize = sizeof (HW_STREAM_HEADER) +
  36. NumStreams * sizeof (HW_STREAM_INFORMATION);
  37. InitializeListHead(&m_srbQueue);
  38. KeInitializeSpinLock(&m_spinLock);
  39. m_bSrbInProcess = FALSE;
  40. if (pDevice)
  41. {
  42. pDevice->SetVideoDecoder(this);
  43. }
  44. }
  45. CWDMVideoDecoder::~CWDMVideoDecoder()
  46. {
  47. DBGTRACE(("CWDMVideoDecoder:~CWDMVideoDecoder()\n"));
  48. }
  49. void CWDMVideoDecoder::ReceivePacket(PHW_STREAM_REQUEST_BLOCK pSrb)
  50. {
  51. KIRQL Irql;
  52. PSRB_DATA_EXTENSION pSrbExt;
  53. KeAcquireSpinLock(&m_spinLock, &Irql);
  54. if (m_bSrbInProcess)
  55. {
  56. pSrbExt = (PSRB_DATA_EXTENSION)pSrb->SRBExtension;
  57. pSrbExt->pSrb = pSrb;
  58. InsertTailList(&m_srbQueue, &pSrbExt->srbListEntry);
  59. KeReleaseSpinLock(&m_spinLock, Irql);
  60. return;
  61. }
  62. m_bSrbInProcess = TRUE;
  63. KeReleaseSpinLock(&m_spinLock, Irql);
  64. for (;;) {
  65. // Assume success. Might be changed below
  66. pSrb->Status = STATUS_SUCCESS;
  67. BOOL notify = TRUE;
  68. // determine the type of packet.
  69. switch(pSrb->Command)
  70. {
  71. case SRB_INITIALIZATION_COMPLETE:
  72. DBGTRACE(("SRB_INITIALIZATION_COMPLETE; SRB=%x\n", pSrb));
  73. // Stream class has finished initialization.
  74. // Now create DShow Medium interface BLOBs.
  75. // This needs to be done at low priority since it uses the registry
  76. //
  77. // Do we need to worry about synchronization here?
  78. SrbInitializationComplete(pSrb);
  79. break;
  80. case SRB_UNINITIALIZE_DEVICE:
  81. DBGTRACE(("SRB_UNINITIALIZE_DEVICE; SRB=%x\n", pSrb));
  82. // close the device.
  83. break;
  84. case SRB_PAGING_OUT_DRIVER:
  85. DBGTRACE(("SRB_PAGING_OUT_DRIVER; SRB=%x\n", pSrb));
  86. //
  87. // The driver is being paged out
  88. // Disable Interrupts if you have them!
  89. //
  90. break;
  91. case SRB_CHANGE_POWER_STATE:
  92. DBGTRACE(("SRB_CHANGE_POWER_STATE. SRB=%x. State=%d\n",
  93. pSrb, pSrb->CommandData.DeviceState));
  94. SrbChangePowerState(pSrb);
  95. break;
  96. case SRB_OPEN_STREAM:
  97. DBGTRACE(("SRB_OPEN_STREAM; SRB=%x\n", pSrb));
  98. SrbOpenStream(pSrb);
  99. break;
  100. case SRB_CLOSE_STREAM:
  101. DBGTRACE(("SRB_CLOSE_STREAM; SRB=%x\n", pSrb));
  102. if (!IsListEmpty(&m_srbQueue)) // is this necessary ???
  103. {
  104. TRAP();
  105. }
  106. SrbCloseStream(pSrb);
  107. break;
  108. case SRB_GET_DATA_INTERSECTION:
  109. DBGTRACE(("SRB_GET_DATA_INTERSECTION; SRB=%x\n", pSrb));
  110. SrbGetDataIntersection(pSrb);
  111. break;
  112. case SRB_GET_STREAM_INFO:
  113. SrbGetStreamInfo(pSrb);
  114. break;
  115. case SRB_GET_DEVICE_PROPERTY:
  116. SrbGetProperty(pSrb);
  117. break;
  118. case SRB_SET_DEVICE_PROPERTY:
  119. SrbSetProperty(pSrb);
  120. break;
  121. case SRB_WRITE_DATA:
  122. DBGTRACE(("SRB_WRITE_DATA; SRB=%x\n", pSrb));
  123. SetTunerInfo(pSrb);
  124. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  125. notify = FALSE;
  126. break;
  127. case SRB_UNKNOWN_DEVICE_COMMAND:
  128. // not sure why this gets called every time.
  129. DBGTRACE(("SRB_UNKNOWN_DEVICE_COMMAND; SRB=%x\n", pSrb));
  130. // TRAP()();
  131. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  132. break;
  133. case SRB_OPEN_DEVICE_INSTANCE:
  134. case SRB_CLOSE_DEVICE_INSTANCE:
  135. default:
  136. TRAP();
  137. // this is a request that we do not understand. Indicate invalid command and complete the request
  138. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  139. }
  140. if (notify)
  141. StreamClassDeviceNotification(DeviceRequestComplete, pSrb->HwDeviceExtension, pSrb);
  142. KeAcquireSpinLock(&m_spinLock, &Irql);
  143. if (IsListEmpty(&m_srbQueue))
  144. {
  145. m_bSrbInProcess = FALSE;
  146. KeReleaseSpinLock(&m_spinLock, Irql);
  147. return;
  148. }
  149. else
  150. {
  151. pSrbExt = (PSRB_DATA_EXTENSION)RemoveHeadList(&m_srbQueue);
  152. KeReleaseSpinLock(&m_spinLock, Irql);
  153. pSrb = pSrbExt->pSrb;
  154. }
  155. }
  156. }
  157. void CWDMVideoDecoder::CancelPacket( PHW_STREAM_REQUEST_BLOCK pSrbToCancel)
  158. {
  159. CWDMVideoStream* pVideoStream = ( CWDMVideoStream*)pSrbToCancel->StreamObject->HwStreamExtension;
  160. DBGINFO(( "Bt829: AdapterCancelPacket, Starting attempting to cancel Srb 0x%x\n",
  161. pSrbToCancel));
  162. if( pVideoStream == NULL)
  163. {
  164. //
  165. // Device command IRPs are not queued, so nothing to do
  166. //
  167. DBGINFO(( "Bt829: AdapterCancelPacketStart, no pVideoStream Srb 0x%x\n",
  168. pSrbToCancel));
  169. return;
  170. }
  171. pVideoStream->CancelPacket( pSrbToCancel);
  172. DBGINFO(( "Bt829: AdapterCancelPacket, Exiting\n"));
  173. }
  174. void CWDMVideoDecoder::TimeoutPacket(PHW_STREAM_REQUEST_BLOCK pSrb)
  175. {
  176. CWDMVideoStream * pVideoStream = (CWDMVideoStream *)pSrb->StreamObject->HwStreamExtension;
  177. DBGTRACE(("Timeout. SRB %8x. \n", pSrb));
  178. pVideoStream->TimeoutPacket(pSrb);
  179. DBGTRACE(("TimeoutPacket: SRB %8x. Resetting.\n", pSrb));
  180. pSrb->TimeoutCounter = pSrb->TimeoutOriginal;
  181. }
  182. BOOL CWDMVideoDecoder::SrbInitializationComplete(PHW_STREAM_REQUEST_BLOCK pSrb)
  183. {
  184. NTSTATUS Status;
  185. ULONG *tmp = (ULONG *) &CrossbarPinDirection[0];
  186. // Create the Registry blobs that DShow uses to create
  187. // graphs via Mediums
  188. Status = StreamClassRegisterFilterWithNoKSPins (
  189. m_pDeviceObject, // IN PDEVICE_OBJECT DeviceObject,
  190. &KSCATEGORY_CROSSBAR, // IN GUID * InterfaceClassGUID,
  191. CrossbarPins(), // IN ULONG PinCount,
  192. (int *) CrossbarPinDirection, // IN ULONG * Flags,
  193. (KSPIN_MEDIUM *) CrossbarMediums, // IN KSPIN_MEDIUM * MediumList,
  194. NULL // IN GUID * CategoryList
  195. );
  196. // Register the Capture filter
  197. // Note: This should be done automatically be MSKsSrv.sys,
  198. // when that component comes on line (if ever) ...
  199. Status = StreamClassRegisterFilterWithNoKSPins (
  200. m_pDeviceObject, // IN PDEVICE_OBJECT DeviceObject,
  201. &KSCATEGORY_CAPTURE, // IN GUID * InterfaceClassGUID,
  202. CapturePins(), // IN ULONG PinCount,
  203. (int *) CapturePinDirection, // IN ULONG * Flags,
  204. (KSPIN_MEDIUM *) CaptureMediums, // IN KSPIN_MEDIUM * MediumList,
  205. NULL // IN GUID * CategoryList
  206. );
  207. pSrb->Status = STATUS_SUCCESS;
  208. return(TRUE);
  209. }
  210. BOOL CWDMVideoDecoder::SrbOpenStream(PHW_STREAM_REQUEST_BLOCK pSrb)
  211. {
  212. DBGTRACE(("CWDMVideoDecoder:SrbOpenStream()\n"));
  213. PHW_STREAM_OBJECT pStreamObject = pSrb->StreamObject;
  214. void * pStrmEx = pStreamObject->HwStreamExtension;
  215. int StreamNumber = pStreamObject->StreamNumber;
  216. PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
  217. CWDMVideoStream * pVideoStream;
  218. CWDMVideoPortStream * pVPVBIStream;
  219. UINT nErrorCode;
  220. RtlZeroMemory(pStrmEx, streamDataExtensionSize);
  221. DBGINFO(("SRBOPENSTREAM ------- StreamNumber=%d\n", StreamNumber));
  222. //
  223. // check that the stream index requested isn't too high
  224. // or that the maximum number of instances hasn't been exceeded
  225. //
  226. if (StreamNumber >= (int)NumStreams || StreamNumber < 0) {
  227. pSrb->Status = STATUS_INVALID_PARAMETER;
  228. goto Exit;
  229. }
  230. //
  231. // Check the validity of the format being requested
  232. //
  233. if (!AdapterVerifyFormat (pKSDataFormat, StreamNumber)) {
  234. pSrb->Status = STATUS_INVALID_PARAMETER;
  235. goto Exit;
  236. }
  237. //
  238. // Set up pointers to the handlers for the stream data and control handlers
  239. //
  240. pStreamObject->ReceiveDataPacket = VideoReceiveDataPacket;
  241. pStreamObject->ReceiveControlPacket = VideoReceiveCtrlPacket;
  242. //
  243. // Indicate the clock support available on this stream
  244. //
  245. pStreamObject->HwClockObject.HwClockFunction = NULL;
  246. pStreamObject->HwClockObject.ClockSupportFlags = 0;
  247. //
  248. // The DMA flag must be set when the device will be performing DMA directly
  249. // to the data buffer addresses passed in to the ReceiceDataPacket routines.
  250. //
  251. pStreamObject->Dma = Streams[StreamNumber].hwStreamObjectInfo.Dma;
  252. //
  253. // The PIO flag must be set when the mini driver will be accessing the data
  254. // buffers passed in using logical addressing
  255. //
  256. pStreamObject->Pio = Streams[StreamNumber].hwStreamObjectInfo.Pio;
  257. //
  258. // How many extra bytes will be passed up from the driver for each frame?
  259. //
  260. pStreamObject->StreamHeaderMediaSpecific =
  261. Streams[StreamNumber].hwStreamObjectInfo.StreamHeaderMediaSpecific;
  262. pStreamObject->StreamHeaderWorkspace =
  263. Streams[StreamNumber].hwStreamObjectInfo.StreamHeaderWorkspace;
  264. //
  265. // Indicate the allocator support available on this stream
  266. //
  267. pStreamObject->Allocator = Streams[StreamNumber].hwStreamObjectInfo.Allocator;
  268. //
  269. // Indicate the event support available on this stream
  270. //
  271. pStreamObject->HwEventRoutine =
  272. Streams[StreamNumber].hwStreamObjectInfo.HwEventRoutine;
  273. switch (StreamNumber)
  274. {
  275. case STREAM_AnalogVideoInput:
  276. ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_ANALOGVIDEO));
  277. pVideoStream = (CWDMVideoStream *)new(pStrmEx)
  278. CWDMVideoStream(pStreamObject, this, &nErrorCode);
  279. break;
  280. case STREAM_VideoCapture:
  281. ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_VIDEOINFO));
  282. m_pVideoCaptureStream = (CWDMVideoCaptureStream *)new(pStrmEx)
  283. CWDMVideoCaptureStream(pStreamObject, this, pKSDataFormat, &nErrorCode);
  284. if (m_pVideoPortStream)
  285. {
  286. m_pVideoPortStream->AttemptRenegotiation();
  287. }
  288. break;
  289. case STREAM_VBICapture:
  290. ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_VBI));
  291. m_pVBICaptureStream = (CWDMVBICaptureStream *)new(pStrmEx)
  292. CWDMVBICaptureStream(pStreamObject, this, pKSDataFormat, &nErrorCode);
  293. break;
  294. case STREAM_VPVideo:
  295. ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_NONE) &&
  296. IsEqualGUID(pKSDataFormat->SubFormat, KSDATAFORMAT_SUBTYPE_VPVideo));
  297. m_pVideoPortStream = (CWDMVideoPortStream *)new(pStrmEx)
  298. CWDMVideoPortStream(pStreamObject, this, &nErrorCode);
  299. if (m_pVideoCaptureStream == NULL)
  300. {
  301. MRect t(0, 0, m_pDevice->GetDefaultDecoderWidth(),
  302. m_pDevice->GetDefaultDecoderHeight());
  303. m_pDevice->SetRect(t);
  304. }
  305. break;
  306. case STREAM_VPVBI:
  307. ASSERT(IsEqualGUID(pKSDataFormat->Specifier, KSDATAFORMAT_SPECIFIER_NONE) &&
  308. IsEqualGUID(pKSDataFormat->SubFormat, KSDATAFORMAT_SUBTYPE_VPVBI));
  309. pVPVBIStream = (CWDMVideoPortStream *)new(pStrmEx)
  310. CWDMVideoPortStream(pStreamObject, this, &nErrorCode);
  311. m_pDevice->SetVBIEN(TRUE);
  312. m_pDevice->SetVBIFMT(TRUE);
  313. break;
  314. default:
  315. pSrb->Status = STATUS_UNSUCCESSFUL;
  316. goto Exit;
  317. }
  318. if(nErrorCode == WDMMINI_NOERROR)
  319. m_OpenStreams++;
  320. else
  321. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  322. Exit:
  323. DBGTRACE(("SrbOpenStream Exit\n"));
  324. return(TRUE);
  325. }
  326. BOOL CWDMVideoDecoder::SrbCloseStream(PHW_STREAM_REQUEST_BLOCK pSrb)
  327. {
  328. int StreamNumber = pSrb->StreamObject->StreamNumber;
  329. DBGTRACE(("CWDMVideoDecoder:SrbCloseStream()\n"));
  330. DBGINFO(("SRBCLOSESTREAM ------- StreamNumber=%d\n", StreamNumber));
  331. //
  332. // the minidriver may wish to free any resources that were allocated at
  333. // open stream time etc.
  334. //
  335. CWDMVideoStream * pVideoStream = (CWDMVideoStream *)pSrb->StreamObject->HwStreamExtension;
  336. delete pVideoStream;
  337. switch (StreamNumber)
  338. {
  339. case STREAM_AnalogVideoInput:
  340. break;
  341. case STREAM_VideoCapture:
  342. m_pVideoCaptureStream = NULL;
  343. break;
  344. case STREAM_VBICapture:
  345. m_pVBICaptureStream = NULL;
  346. break;
  347. case STREAM_VPVideo:
  348. m_pVideoPortStream = NULL;
  349. break;
  350. case STREAM_VPVBI:
  351. m_pDevice->SetVBIEN(FALSE);
  352. m_pDevice->SetVBIFMT(FALSE);
  353. break;
  354. default:
  355. pSrb->Status = STATUS_UNSUCCESSFUL;
  356. return FALSE;
  357. }
  358. if (--m_OpenStreams == 0)
  359. {
  360. DBGINFO(("Last one out turns off the lights\n"));
  361. m_CDecoderVPort.Close();
  362. m_preEventOccurred = FALSE;
  363. m_postEventOccurred = FALSE;
  364. m_pDevice->SaveState();
  365. }
  366. pSrb->Status = STATUS_SUCCESS;
  367. return TRUE;
  368. }
  369. BOOL CWDMVideoDecoder::SrbGetDataIntersection(PHW_STREAM_REQUEST_BLOCK pSrb)
  370. {
  371. DBGTRACE(("CWDMVideoDecoder:SrbGetDataIntersection()\n"));
  372. PSTREAM_DATA_INTERSECT_INFO IntersectInfo;
  373. PKSDATARANGE DataRange;
  374. BOOL OnlyWantsSize;
  375. BOOL MatchFound = FALSE;
  376. ULONG FormatSize;
  377. ULONG StreamNumber;
  378. ULONG j;
  379. ULONG NumberOfFormatArrayEntries;
  380. PKSDATAFORMAT *pAvailableFormats;
  381. IntersectInfo = pSrb->CommandData.IntersectInfo;
  382. StreamNumber = IntersectInfo->StreamNumber;
  383. DataRange = IntersectInfo->DataRange;
  384. //
  385. // Check that the stream number is valid
  386. //
  387. if (StreamNumber >= NumStreams) {
  388. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  389. TRAP();
  390. return FALSE;
  391. }
  392. NumberOfFormatArrayEntries =
  393. Streams[StreamNumber].hwStreamInfo.NumberOfFormatArrayEntries;
  394. //
  395. // Get the pointer to the array of available formats
  396. //
  397. pAvailableFormats = Streams[StreamNumber].hwStreamInfo.StreamFormatsArray;
  398. //
  399. // Is the caller trying to get the format, or the size of the format?
  400. //
  401. OnlyWantsSize = ( (IntersectInfo->SizeOfDataFormatBuffer == sizeof(ULONG)) ||
  402. (IntersectInfo->SizeOfDataFormatBuffer == 0) );
  403. //
  404. // Walk the formats supported by the stream searching for a match
  405. // of the three GUIDs which together define a DATARANGE
  406. //
  407. for (j = 0; j < NumberOfFormatArrayEntries; j++, pAvailableFormats++) {
  408. if (!AdapterCompareGUIDsAndFormatSize(
  409. DataRange,
  410. *pAvailableFormats,
  411. TRUE /* CompareFormatSize */)) {
  412. continue;
  413. }
  414. //
  415. // Now that the three GUIDs match, switch on the Specifier
  416. // to do a further type-specific check
  417. //
  418. // -------------------------------------------------------------------
  419. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  420. // -------------------------------------------------------------------
  421. if (IsEqualGUID (DataRange->Specifier,
  422. KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  423. PKS_DATARANGE_VIDEO DataRangeVideoToVerify =
  424. (PKS_DATARANGE_VIDEO) DataRange;
  425. PKS_DATARANGE_VIDEO DataRangeVideo =
  426. (PKS_DATARANGE_VIDEO) *pAvailableFormats;
  427. PKS_DATAFORMAT_VIDEOINFOHEADER DataFormatVideoInfoHeaderOut;
  428. //
  429. // Check that the other fields match
  430. //
  431. if ((DataRangeVideoToVerify->bFixedSizeSamples != DataRangeVideo->bFixedSizeSamples) ||
  432. (DataRangeVideoToVerify->bTemporalCompression != DataRangeVideo->bTemporalCompression) ||
  433. (DataRangeVideoToVerify->StreamDescriptionFlags != DataRangeVideo->StreamDescriptionFlags) ||
  434. (DataRangeVideoToVerify->MemoryAllocationFlags != DataRangeVideo->MemoryAllocationFlags) ||
  435. (RtlCompareMemory (&DataRangeVideoToVerify->ConfigCaps,
  436. &DataRangeVideo->ConfigCaps,
  437. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
  438. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS))) {
  439. continue;
  440. }
  441. // Validate each step of the size calculations for arithmetic overflow,
  442. // and verify that the specified sizes correlate
  443. // (with unsigned math, a+b < b iff an arithmetic overflow occured)
  444. ULONG VideoHeaderSize = DataRangeVideoToVerify->VideoInfoHeader.bmiHeader.biSize +
  445. FIELD_OFFSET(KS_VIDEOINFOHEADER,bmiHeader);
  446. ULONG RangeSize = VideoHeaderSize +
  447. FIELD_OFFSET(KS_DATARANGE_VIDEO,VideoInfoHeader);
  448. if (VideoHeaderSize < FIELD_OFFSET(KS_VIDEOINFOHEADER,bmiHeader) ||
  449. RangeSize < FIELD_OFFSET(KS_DATARANGE_VIDEO,VideoInfoHeader) ||
  450. RangeSize > DataRangeVideoToVerify->DataRange.FormatSize) {
  451. pSrb->Status = STATUS_INVALID_PARAMETER;
  452. return FALSE;
  453. }
  454. // MATCH FOUND!
  455. MatchFound = TRUE;
  456. FormatSize = sizeof (KSDATAFORMAT) +
  457. VideoHeaderSize;
  458. if (OnlyWantsSize) {
  459. break;
  460. }
  461. // Caller wants the full data format
  462. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  463. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  464. return FALSE;
  465. }
  466. // Copy over the KSDATAFORMAT, followed by the
  467. // actual VideoInfoHeader
  468. DataFormatVideoInfoHeaderOut = (PKS_DATAFORMAT_VIDEOINFOHEADER) IntersectInfo->DataFormatBuffer;
  469. // Copy over the KSDATAFORMAT
  470. RtlCopyMemory(
  471. &DataFormatVideoInfoHeaderOut->DataFormat,
  472. &DataRangeVideoToVerify->DataRange,
  473. sizeof (KSDATARANGE));
  474. DataFormatVideoInfoHeaderOut->DataFormat.FormatSize = FormatSize;
  475. // Copy over the caller's requested VIDEOINFOHEADER
  476. RtlCopyMemory(
  477. &DataFormatVideoInfoHeaderOut->VideoInfoHeader,
  478. &DataRangeVideoToVerify->VideoInfoHeader,
  479. VideoHeaderSize);
  480. // Calculate biSizeImage for this request, and put the result in both
  481. // the biSizeImage field of the bmiHeader AND in the SampleSize field
  482. // of the DataFormat.
  483. //
  484. // Note that for compressed sizes, this calculation will probably not
  485. // be just width * height * bitdepth
  486. DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader.biSizeImage =
  487. DataFormatVideoInfoHeaderOut->DataFormat.SampleSize =
  488. KS_DIBSIZE(DataFormatVideoInfoHeaderOut->VideoInfoHeader.bmiHeader);
  489. //
  490. // Perform other validation such as cropping and scaling checks
  491. //
  492. break;
  493. } // End of VIDEOINFOHEADER specifier
  494. // -------------------------------------------------------------------
  495. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  496. // -------------------------------------------------------------------
  497. else if (IsEqualGUID (DataRange->Specifier,
  498. KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  499. //
  500. // For analog video, the DataRange and DataFormat
  501. // are identical, so just copy the whole structure
  502. //
  503. PKS_DATARANGE_ANALOGVIDEO DataRangeVideo =
  504. (PKS_DATARANGE_ANALOGVIDEO) *pAvailableFormats;
  505. // MATCH FOUND!
  506. MatchFound = TRUE;
  507. FormatSize = sizeof (KS_DATARANGE_ANALOGVIDEO);
  508. if (OnlyWantsSize) {
  509. break;
  510. }
  511. // Caller wants the full data format
  512. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  513. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  514. return FALSE;
  515. }
  516. RtlCopyMemory(
  517. IntersectInfo->DataFormatBuffer,
  518. DataRangeVideo,
  519. sizeof (KS_DATARANGE_ANALOGVIDEO));
  520. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  521. break;
  522. } // End of KS_ANALOGVIDEOINFO specifier
  523. // -------------------------------------------------------------------
  524. // Specifier STATIC_KSDATAFORMAT_TYPE_VIDEO for Video Port
  525. // -------------------------------------------------------------------
  526. else if (IsEqualGUID (DataRange->Specifier,
  527. KSDATAFORMAT_SPECIFIER_NONE) &&
  528. IsEqualGUID (DataRange->SubFormat, KSDATAFORMAT_SUBTYPE_VPVideo)) {
  529. // MATCH FOUND!
  530. MatchFound = TRUE;
  531. FormatSize = sizeof (KSDATAFORMAT);
  532. if (OnlyWantsSize) {
  533. break;
  534. }
  535. // Caller wants the full data format
  536. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  537. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  538. return FALSE;
  539. }
  540. RtlCopyMemory(
  541. IntersectInfo->DataFormatBuffer,
  542. &StreamFormatVideoPort,
  543. sizeof (KSDATAFORMAT));
  544. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  545. break;
  546. }
  547. // -------------------------------------------------------------------
  548. // Specifier KSDATAFORMAT_SPECIFIER_NONE for VP VBI
  549. // -------------------------------------------------------------------
  550. else if (IsEqualGUID (DataRange->Specifier,
  551. KSDATAFORMAT_SPECIFIER_NONE) &&
  552. IsEqualGUID (DataRange->SubFormat, KSDATAFORMAT_SUBTYPE_VPVBI)) {
  553. // MATCH FOUND!
  554. MatchFound = TRUE;
  555. FormatSize = sizeof (KSDATAFORMAT);
  556. if (OnlyWantsSize) {
  557. break;
  558. }
  559. // Caller wants the full data format
  560. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  561. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  562. return FALSE;
  563. }
  564. RtlCopyMemory(
  565. IntersectInfo->DataFormatBuffer,
  566. &StreamFormatVideoPortVBI,
  567. sizeof (KSDATAFORMAT));
  568. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  569. break;
  570. }
  571. // -------------------------------------------------------------------
  572. // Specifier STATIC_KSDATAFORMAT_TYPE_NONE for VBI capture stream
  573. // -------------------------------------------------------------------
  574. else if (IsEqualGUID (DataRange->Specifier,
  575. KSDATAFORMAT_SPECIFIER_VBI)) {
  576. PKS_DATARANGE_VIDEO_VBI DataRangeVBIToVerify =
  577. (PKS_DATARANGE_VIDEO_VBI) DataRange;
  578. PKS_DATARANGE_VIDEO_VBI DataRangeVBI =
  579. (PKS_DATARANGE_VIDEO_VBI) *pAvailableFormats;
  580. //
  581. // Check that the other fields match
  582. //
  583. if ((DataRangeVBIToVerify->bFixedSizeSamples != DataRangeVBI->bFixedSizeSamples) ||
  584. (DataRangeVBIToVerify->bTemporalCompression != DataRangeVBI->bTemporalCompression) ||
  585. (DataRangeVBIToVerify->StreamDescriptionFlags != DataRangeVBI->StreamDescriptionFlags) ||
  586. (DataRangeVBIToVerify->MemoryAllocationFlags != DataRangeVBI->MemoryAllocationFlags) ||
  587. (RtlCompareMemory (&DataRangeVBIToVerify->ConfigCaps,
  588. &DataRangeVBI->ConfigCaps,
  589. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
  590. sizeof (KS_VIDEO_STREAM_CONFIG_CAPS))) {
  591. continue;
  592. }
  593. // MATCH FOUND!
  594. MatchFound = TRUE;
  595. FormatSize = sizeof (KS_DATAFORMAT_VBIINFOHEADER);
  596. if (OnlyWantsSize) {
  597. break;
  598. }
  599. // Caller wants the full data format
  600. if (IntersectInfo->SizeOfDataFormatBuffer < FormatSize) {
  601. pSrb->Status = STATUS_BUFFER_TOO_SMALL;
  602. return FALSE;
  603. }
  604. // Copy over the KSDATAFORMAT, followed by the
  605. // actual VBIInfoHeader
  606. RtlCopyMemory(
  607. &((PKS_DATAFORMAT_VBIINFOHEADER)IntersectInfo->DataFormatBuffer)->DataFormat,
  608. &DataRangeVBIToVerify->DataRange,
  609. sizeof (KSDATARANGE));
  610. ((PKSDATAFORMAT)IntersectInfo->DataFormatBuffer)->FormatSize = FormatSize;
  611. RtlCopyMemory(
  612. &((PKS_DATAFORMAT_VBIINFOHEADER) IntersectInfo->DataFormatBuffer)->VBIInfoHeader,
  613. &DataRangeVBIToVerify->VBIInfoHeader,
  614. sizeof (KS_VBIINFOHEADER));
  615. }
  616. } // End of loop on all formats for this stream
  617. if (!MatchFound) {
  618. pSrb->Status = STATUS_NO_MATCH;
  619. return FALSE;
  620. }
  621. if (OnlyWantsSize) {
  622. // Check for special case where there is no buffer being passed
  623. if ( IntersectInfo->SizeOfDataFormatBuffer == 0 ) {
  624. pSrb->Status = STATUS_BUFFER_OVERFLOW;
  625. }
  626. else {
  627. *(PULONG) IntersectInfo->DataFormatBuffer = FormatSize;
  628. FormatSize = sizeof(ULONG);
  629. }
  630. }
  631. pSrb->ActualBytesTransferred = FormatSize;
  632. return TRUE;
  633. }
  634. void CWDMVideoDecoder::SrbGetStreamInfo(PHW_STREAM_REQUEST_BLOCK pSrb)
  635. {
  636. DBGTRACE(("CWDMVideoDecoder:SrbGetStreamInfo()\n"));
  637. //
  638. // verify that the buffer is large enough to hold our return data
  639. //
  640. DEBUG_ASSERT (pSrb->NumberOfBytesToTransfer >=
  641. sizeof (HW_STREAM_HEADER) +
  642. sizeof (HW_STREAM_INFORMATION) * NumStreams);
  643. //
  644. // Set the header
  645. //
  646. PHW_STREAM_HEADER pstrhdr =
  647. (PHW_STREAM_HEADER)&(pSrb->CommandData.StreamBuffer->StreamHeader);
  648. pstrhdr->NumberOfStreams = NumStreams;
  649. pstrhdr->SizeOfHwStreamInformation = sizeof (HW_STREAM_INFORMATION);
  650. pstrhdr->NumDevPropArrayEntries = NumAdapterProperties();
  651. pstrhdr->DevicePropertiesArray = (PKSPROPERTY_SET)AdapterProperties;
  652. pstrhdr->Topology = &Topology;
  653. //
  654. // stuff the contents of each HW_STREAM_INFORMATION struct
  655. //
  656. PHW_STREAM_INFORMATION pstrinfo =
  657. (PHW_STREAM_INFORMATION)&(pSrb->CommandData.StreamBuffer->StreamInfo);
  658. for (unsigned j = 0; j < NumStreams; j++) {
  659. *pstrinfo++ = Streams[j].hwStreamInfo;
  660. }
  661. DBGTRACE(("Exit: CWDMVideoDecoder:SrbGetStreamInfo()\n"));
  662. }
  663. VOID CWDMVideoDecoder::SrbSetProperty (PHW_STREAM_REQUEST_BLOCK pSrb)
  664. {
  665. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  666. if (IsEqualGUID(PROPSETID_VIDCAP_CROSSBAR, pSPD->Property->Set)) {
  667. m_pDevice->SetCrossbarProperty (pSrb);
  668. }
  669. else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEOPROCAMP, pSPD->Property->Set)) {
  670. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_VIDEOPROCAMP_S));
  671. ULONG Id = pSPD->Property->Id; // index of the property
  672. PKSPROPERTY_VIDEOPROCAMP_S pS = (PKSPROPERTY_VIDEOPROCAMP_S) pSPD->PropertyInfo; // pointer to the data
  673. pSrb->Status = m_pDevice->SetProcAmpProperty(Id, pS->Value);
  674. }
  675. else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEODECODER, pSPD->Property->Set)) {
  676. m_pDevice->SetDecoderProperty (pSrb);
  677. }
  678. else
  679. DBGERROR(("CWDMVideoDecoder:SrbSetProperty() unknown property\n"));
  680. }
  681. VOID CWDMVideoDecoder::SrbGetProperty (PHW_STREAM_REQUEST_BLOCK pSrb)
  682. {
  683. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  684. if (IsEqualGUID (PROPSETID_VIDCAP_CROSSBAR, pSPD->Property->Set)) {
  685. m_pDevice->GetCrossbarProperty (pSrb);
  686. }
  687. else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEOPROCAMP, pSPD->Property->Set)) {
  688. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_VIDEOPROCAMP_S));
  689. ULONG Id = pSPD->Property->Id; // index of the property
  690. PKSPROPERTY_VIDEOPROCAMP_S pS = (PKSPROPERTY_VIDEOPROCAMP_S) pSPD->PropertyInfo; // pointer to the data
  691. RtlCopyMemory(pS, pSPD->Property, sizeof(KSPROPERTY));
  692. pS->Capabilities = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL;
  693. pSrb->Status = m_pDevice->GetProcAmpProperty(Id, &pS->Value);
  694. pSrb->ActualBytesTransferred = pSrb->Status == STATUS_SUCCESS ?
  695. sizeof (KSPROPERTY_VIDEOPROCAMP_S) : 0;
  696. }
  697. else if (IsEqualGUID(PROPSETID_VIDCAP_VIDEODECODER, pSPD->Property->Set)) {
  698. m_pDevice->GetDecoderProperty (pSrb);
  699. }
  700. else
  701. DBGERROR(("CWDMVideoDecoder:SrbGetProperty() unknown property\n"));
  702. }
  703. void CWDMVideoDecoder::SetTunerInfo( PHW_STREAM_REQUEST_BLOCK pSrb)
  704. {
  705. PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
  706. ASSERT (pDataPacket->FrameExtent == sizeof (KS_TVTUNER_CHANGE_INFO));
  707. KIRQL Irql;
  708. if (m_pVBICaptureStream)
  709. m_pVBICaptureStream->DataLock(&Irql);
  710. RtlCopyMemory( &m_TVTunerChangeInfo,
  711. pDataPacket->Data,
  712. sizeof (KS_TVTUNER_CHANGE_INFO));
  713. m_TVTunerChanged = TRUE;
  714. if (m_pVBICaptureStream)
  715. m_pVBICaptureStream->DataUnLock(Irql);
  716. }
  717. BOOL CWDMVideoDecoder::GetTunerInfo(KS_TVTUNER_CHANGE_INFO* pTVChangeInfo)
  718. {
  719. if (m_TVTunerChanged) {
  720. KIRQL Irql;
  721. m_pVBICaptureStream->DataLock(&Irql);
  722. RtlCopyMemory(pTVChangeInfo, &m_TVTunerChangeInfo, sizeof (KS_TVTUNER_CHANGE_INFO));
  723. m_TVTunerChanged = FALSE;
  724. m_pVBICaptureStream->DataUnLock(Irql);
  725. return TRUE;
  726. }
  727. else
  728. return FALSE;
  729. }
  730. BOOL CWDMVideoDecoder::SrbChangePowerState(PHW_STREAM_REQUEST_BLOCK pSrb)
  731. {
  732. DBGTRACE(("CWDMVideoDecoder:SrbChangePowerState()\n"));
  733. switch (pSrb->CommandData.DeviceState)
  734. {
  735. case PowerDeviceD3:
  736. m_preEventOccurred = TRUE;
  737. m_pDevice->SaveState();
  738. break;
  739. case PowerDeviceD2:
  740. m_preEventOccurred = TRUE;
  741. m_pDevice->SaveState();
  742. break;
  743. case PowerDeviceD1:
  744. m_preEventOccurred = TRUE;
  745. m_pDevice->SaveState();
  746. break;
  747. case PowerDeviceD0:
  748. m_postEventOccurred = TRUE;
  749. m_pDevice->RestoreState(m_OpenStreams);
  750. break;
  751. }
  752. pSrb->Status = STATUS_SUCCESS;
  753. return(TRUE);
  754. }
  755. VOID CWDMVideoPortStream::AttemptRenegotiation()
  756. {
  757. int streamNumber = m_pStreamObject->StreamNumber;
  758. if (m_EventCount)
  759. {
  760. DBGINFO(("Attempting renegotiation on stream %d\n", streamNumber));
  761. if (streamNumber == STREAM_VPVideo)
  762. {
  763. StreamClassStreamNotification(
  764. SignalMultipleStreamEvents,
  765. m_pStreamObject,
  766. &MY_KSEVENTSETID_VPNOTIFY,
  767. KSEVENT_VPNOTIFY_FORMATCHANGE);
  768. }
  769. else if (streamNumber == STREAM_VPVBI)
  770. {
  771. StreamClassStreamNotification(
  772. SignalMultipleStreamEvents,
  773. m_pStreamObject,
  774. &MY_KSEVENTSETID_VPVBINOTIFY,
  775. KSEVENT_VPVBINOTIFY_FORMATCHANGE);
  776. }
  777. else
  778. ASSERT(0);
  779. }
  780. else
  781. {
  782. DBGINFO(("NOT attempting renegotiation on stream %d\n", streamNumber));
  783. }
  784. }
  785. NTSTATUS CWDMVideoDecoder::EventProc( IN PHW_EVENT_DESCRIPTOR pEventDescriptor)
  786. {
  787. if( pEventDescriptor->Enable)
  788. m_nMVDetectionEventCount++;
  789. else
  790. m_nMVDetectionEventCount--;
  791. return( STATUS_SUCCESS);
  792. }