Source code of Windows XP (NT5)
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.

2001 lines
56 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include "strmini.h"
  12. #include "ksmedia.h"
  13. #include "capmain.h"
  14. #include "capdebug.h"
  15. #include "ntstatus.h"
  16. #ifdef TOSHIBA
  17. #include "bert.h"
  18. extern ULONG CurrentOSType;
  19. #ifdef _FPS_COUNT_
  20. ULONG InterruptCounter = 0;
  21. ULONG FrameCounter = 0;
  22. #endif//_FPS_COUNT_
  23. #endif//TOSHIBA
  24. //==========================================================================;
  25. // General queue management routines
  26. //==========================================================================;
  27. /*
  28. ** AddToListIfBusy ()
  29. **
  30. ** Grabs a spinlock, checks the busy flag, and if set adds an SRB to a queue
  31. **
  32. ** Arguments:
  33. **
  34. ** pSrb - Stream request block
  35. **
  36. ** SpinLock - The spinlock to use when checking the flag
  37. **
  38. ** BusyFlag - The flag to check
  39. **
  40. ** ListHead - The list onto which the Srb will be added if the busy flag is set
  41. **
  42. ** Returns:
  43. **
  44. ** The state of the busy flag on entry. This will be TRUE if we're already
  45. ** processing an SRB, and FALSE if no SRB is already in progress.
  46. **
  47. ** Side Effects: none
  48. */
  49. BOOL
  50. STREAMAPI
  51. AddToListIfBusy (
  52. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  53. IN KSPIN_LOCK *SpinLock,
  54. IN OUT BOOL *BusyFlag,
  55. IN LIST_ENTRY *ListHead
  56. )
  57. {
  58. KIRQL Irql;
  59. PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension;
  60. KeAcquireSpinLock (SpinLock, &Irql);
  61. // If we're already processing another SRB, add this current request
  62. // to the queue and return TRUE
  63. if (*BusyFlag == TRUE) {
  64. // Save the SRB pointer away in the SRB Extension
  65. pSrbExt->pSrb = pSrb;
  66. InsertTailList(ListHead, &pSrbExt->ListEntry);
  67. KeReleaseSpinLock(SpinLock, Irql);
  68. return TRUE;
  69. }
  70. // Otherwise, set the busy flag, release the spinlock, and return FALSE
  71. *BusyFlag = TRUE;
  72. KeReleaseSpinLock(SpinLock, Irql);
  73. return FALSE;
  74. }
  75. /*
  76. ** RemoveFromListIfAvailable ()
  77. **
  78. ** Grabs a spinlock, checks for an available SRB, and removes it from the list
  79. **
  80. ** Arguments:
  81. **
  82. ** &pSrb - where to return the Stream request block if available
  83. **
  84. ** SpinLock - The spinlock to use
  85. **
  86. ** BusyFlag - The flag to clear if the list is empty
  87. **
  88. ** ListHead - The list from which an SRB will be removed if available
  89. **
  90. ** Returns:
  91. **
  92. ** TRUE if an SRB was removed from the list
  93. ** FALSE if the list is empty
  94. **
  95. ** Side Effects: none
  96. */
  97. BOOL
  98. STREAMAPI
  99. RemoveFromListIfAvailable (
  100. IN OUT PHW_STREAM_REQUEST_BLOCK *pSrb,
  101. IN KSPIN_LOCK *SpinLock,
  102. IN OUT BOOL *BusyFlag,
  103. IN LIST_ENTRY *ListHead
  104. )
  105. {
  106. KIRQL Irql;
  107. KeAcquireSpinLock (SpinLock, &Irql);
  108. //
  109. // If the queue is now empty, clear the busy flag, and return
  110. //
  111. if (IsListEmpty(ListHead)) {
  112. *BusyFlag = FALSE;
  113. KeReleaseSpinLock(SpinLock, Irql);
  114. return FALSE;
  115. }
  116. //
  117. // otherwise extract the SRB
  118. //
  119. else {
  120. PUCHAR ptr;
  121. PSRB_EXTENSION pSrbExt;
  122. ptr = (PUCHAR)RemoveHeadList(ListHead);
  123. *BusyFlag = TRUE;
  124. KeReleaseSpinLock(SpinLock, Irql);
  125. // Get the SRB out of the SRB extension and return it
  126. pSrbExt = (PSRB_EXTENSION) (((PUCHAR) ptr) -
  127. FIELDOFFSET(SRB_EXTENSION, ListEntry));
  128. *pSrb = pSrbExt->pSrb;
  129. }
  130. return TRUE;
  131. }
  132. //==========================================================================;
  133. // Routines for managing the SRB queue on a per stream basis
  134. //==========================================================================;
  135. /*
  136. ** VideoQueueAddSRB ()
  137. **
  138. ** Adds a stream data SRB to a stream queue. The queue is maintained in a
  139. ** first in, first out order.
  140. **
  141. ** Arguments:
  142. **
  143. ** pSrb - Stream request block for the Video stream
  144. **
  145. ** Returns: nothing
  146. **
  147. ** Side Effects: none
  148. */
  149. VOID
  150. STREAMAPI
  151. VideoQueueAddSRB (
  152. IN PHW_STREAM_REQUEST_BLOCK pSrb
  153. )
  154. {
  155. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  156. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  157. int StreamNumber = pSrb->StreamObject->StreamNumber;
  158. KIRQL oldIrql;
  159. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  160. // Save the SRB pointer in the IRP so we can use the IRPs
  161. // ListEntry to maintain a doubly linked list of pending
  162. // requests
  163. pSrb->Irp->Tail.Overlay.DriverContext[0] = pSrb;
  164. InsertTailList (
  165. &pHwDevExt->StreamSRBList[StreamNumber],
  166. &pSrb->Irp->Tail.Overlay.ListEntry);
  167. // Increment the count of outstanding SRBs in this queue
  168. pHwDevExt->StreamSRBListSize[StreamNumber]++;
  169. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  170. }
  171. /*
  172. ** VideoQueueRemoveSRB ()
  173. **
  174. ** Removes a stream data SRB from a stream queue
  175. **
  176. ** Arguments:
  177. **
  178. ** pHwDevExt - Device Extension
  179. **
  180. ** StreamNumber - Index of the stream
  181. **
  182. ** Returns: SRB or NULL
  183. **
  184. ** Side Effects: none
  185. */
  186. PHW_STREAM_REQUEST_BLOCK
  187. STREAMAPI
  188. VideoQueueRemoveSRB (
  189. PHW_DEVICE_EXTENSION pHwDevExt,
  190. int StreamNumber
  191. )
  192. {
  193. PUCHAR ptr;
  194. PIRP pIrp;
  195. PHW_STREAM_REQUEST_BLOCK pSrb = NULL;
  196. KIRQL oldIrql;
  197. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  198. //
  199. // Get the SRB out of the IRP out of the pending list
  200. //
  201. if (!IsListEmpty (&pHwDevExt->StreamSRBList[StreamNumber])) {
  202. ptr = (PUCHAR) RemoveHeadList(
  203. &pHwDevExt->StreamSRBList[StreamNumber]);
  204. pIrp = (PIRP) (((PUCHAR) ptr) -
  205. FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
  206. pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
  207. // Decrement the count of SRBs in this queue
  208. pHwDevExt->StreamSRBListSize[StreamNumber]--;
  209. }
  210. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  211. return pSrb;
  212. }
  213. /*
  214. ** VideoQueueCancelAllSRBs()
  215. **
  216. ** In case of a client crash, this empties the stream queue when the stream closes
  217. **
  218. ** Arguments:
  219. **
  220. ** pStrmEx - pointer to the stream extension
  221. **
  222. ** Returns:
  223. **
  224. ** Side Effects: none
  225. */
  226. VOID
  227. STREAMAPI
  228. VideoQueueCancelAllSRBs (
  229. PSTREAMEX pStrmEx
  230. )
  231. {
  232. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pStrmEx->pHwDevExt;
  233. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  234. PUCHAR ptr;
  235. PIRP pIrp;
  236. PHW_STREAM_REQUEST_BLOCK pSrb;
  237. KIRQL oldIrql;
  238. if (pStrmEx->KSState != KSSTATE_STOP) {
  239. KdPrint(("TsbVcap: ERROR Cleanup without being in the stopped state\n"));
  240. // May need to force the device to a stopped state here
  241. // may need to disable interrupts here !
  242. }
  243. //
  244. // The stream class will cancel all outstanding IRPs for us
  245. // (but only if we've set TurnOffSynchronization = FALSE)
  246. //
  247. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  248. //
  249. // Get the SRB out of the IRP out of the pending list
  250. //
  251. while (!IsListEmpty (&pHwDevExt->StreamSRBList[StreamNumber])) {
  252. ptr = (PUCHAR) RemoveHeadList(
  253. &pHwDevExt->StreamSRBList[StreamNumber]);
  254. pIrp = (PIRP) (((PUCHAR) ptr) -
  255. FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
  256. pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
  257. // Decrement the count of SRBs in this queue
  258. pHwDevExt->StreamSRBListSize[StreamNumber]--;
  259. //
  260. // Make the length zero, and status cancelled
  261. //
  262. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  263. pSrb->Status = STATUS_CANCELLED;
  264. KdPrint(("TsbVcap: VideoQueueCancelALLSRBs FOUND Srb=%x\n", pSrb));
  265. CompleteStreamSRB (pSrb);
  266. }
  267. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  268. KdPrint(("TsbVcap: VideoQueueCancelAll\n"));
  269. }
  270. /*
  271. ** VideoQueueCancelOneSRB()
  272. **
  273. ** Called when cancelling a particular SRB
  274. **
  275. ** Arguments:
  276. **
  277. ** pStrmEx - pointer to the stream extension
  278. **
  279. ** pSRBToCancel - pointer to the SRB
  280. **
  281. ** Returns:
  282. **
  283. ** TRUE if the SRB was found in this queue
  284. **
  285. ** Side Effects: none
  286. */
  287. BOOL
  288. STREAMAPI
  289. VideoQueueCancelOneSRB (
  290. PSTREAMEX pStrmEx,
  291. PHW_STREAM_REQUEST_BLOCK pSrbToCancel
  292. )
  293. {
  294. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pStrmEx->pHwDevExt;
  295. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  296. KIRQL oldIrql;
  297. BOOL Found = FALSE;
  298. PIRP pIrp;
  299. PHW_STREAM_REQUEST_BLOCK pSrb;
  300. PLIST_ENTRY Entry;
  301. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  302. Entry = pHwDevExt->StreamSRBList[StreamNumber].Flink;
  303. //
  304. // Loop through the linked list from the beginning to end,
  305. // trying to find the SRB to cancel
  306. //
  307. while (Entry != &pHwDevExt->StreamSRBList[StreamNumber]) {
  308. pIrp = (PIRP) (((PUCHAR) Entry) -
  309. FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
  310. pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
  311. if (pSrb == pSrbToCancel) {
  312. RemoveEntryList(Entry);
  313. Found = TRUE;
  314. break;
  315. }
  316. Entry = Entry->Flink;
  317. }
  318. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  319. if (Found) {
  320. pHwDevExt->StreamSRBListSize[StreamNumber]--;
  321. //
  322. // Make the length zero, and status cancelled
  323. //
  324. pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
  325. pSrbToCancel->Status = STATUS_CANCELLED;
  326. CompleteStreamSRB (pSrbToCancel);
  327. KdPrint(("TsbVcap: VideoQueueCancelOneSRB FOUND Srb=%x\n", pSrb));
  328. }
  329. KdPrint(("TsbVcap: VideoQueueCancelOneSRB\n"));
  330. return Found;
  331. }
  332. /*
  333. ** VideoSetFormat()
  334. **
  335. ** Sets the format for a video stream. This happens both when the
  336. ** stream is first opened, and also when dynamically switching formats
  337. ** on the preview pin.
  338. **
  339. ** It is assumed that the format has been verified for correctness before
  340. ** this call is made.
  341. **
  342. ** Arguments:
  343. **
  344. ** pSrb - Stream request block for the Video stream
  345. **
  346. ** Returns:
  347. **
  348. ** TRUE if the format could be set, else FALSE
  349. **
  350. ** Side Effects: none
  351. */
  352. BOOL
  353. STREAMAPI
  354. VideoSetFormat(
  355. IN PHW_STREAM_REQUEST_BLOCK pSrb
  356. )
  357. {
  358. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  359. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  360. int StreamNumber = pSrb->StreamObject->StreamNumber;
  361. UINT nSize;
  362. PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
  363. #ifdef TOSHIBA
  364. ULONG ImageSize;
  365. ULONG ImageSizeY;
  366. ULONG ImageSizeU;
  367. ULONG ImageSizeV;
  368. ULONG ulFrameRate;
  369. DWORD dwAddr;
  370. UINT biWidth;
  371. UINT biHeight;
  372. int Counter;
  373. PSTREAMEX pStrmExTmp;
  374. #endif//TOSHIBA
  375. // -------------------------------------------------------------------
  376. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  377. // -------------------------------------------------------------------
  378. if (IsEqualGUID (&pKSDataFormat->Specifier,
  379. &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  380. PKS_DATAFORMAT_VIDEOINFOHEADER pVideoInfoHeader =
  381. (PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
  382. PKS_VIDEOINFOHEADER pVideoInfoHdrRequested =
  383. &pVideoInfoHeader->VideoInfoHeader;
  384. nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested);
  385. KdPrint(("TsbVcap: New Format\n"));
  386. KdPrint(("TsbVcap: pVideoInfoHdrRequested=%x\n", pVideoInfoHdrRequested));
  387. KdPrint(("TsbVcap: KS_VIDEOINFOHEADER size=%d\n", nSize));
  388. KdPrint(("TsbVcap: Width=%d Height=%d BitCount=%d\n",
  389. pVideoInfoHdrRequested->bmiHeader.biWidth,
  390. pVideoInfoHdrRequested->bmiHeader.biHeight,
  391. pVideoInfoHdrRequested->bmiHeader.biBitCount));
  392. KdPrint(("TsbVcap: biSizeImage=%d\n",
  393. pVideoInfoHdrRequested->bmiHeader.biSizeImage));
  394. #ifdef TOSHIBA // '98-12-10 Added, for Bug-Report 253563
  395. if ( (pVideoInfoHdrRequested->bmiHeader.biWidth & 0x03) ||
  396. (pVideoInfoHdrRequested->bmiHeader.biHeight & 0x03) ) {
  397. pSrb->Status = STATUS_INVALID_PARAMETER;
  398. return FALSE;
  399. }
  400. #endif//TOSHIBA
  401. #ifdef TOSHIBA
  402. for (Counter = 0; Counter < MAX_TSBVCAP_STREAMS; Counter++) {
  403. if ( pStrmExTmp = (PSTREAMEX)pHwDevExt->pStrmEx[Counter] ) {
  404. // Check other opened stream format
  405. if ( pStrmExTmp->pVideoInfoHeader ) {
  406. if ( (pStrmExTmp->pVideoInfoHeader->bmiHeader.biWidth !=
  407. pVideoInfoHdrRequested->bmiHeader.biWidth) ||
  408. (pStrmExTmp->pVideoInfoHeader->bmiHeader.biHeight !=
  409. pVideoInfoHdrRequested->bmiHeader.biHeight) ||
  410. (pStrmExTmp->pVideoInfoHeader->bmiHeader.biBitCount !=
  411. pVideoInfoHdrRequested->bmiHeader.biBitCount) ) {
  412. pSrb->Status = STATUS_INVALID_PARAMETER;
  413. return FALSE;
  414. }
  415. }
  416. }
  417. }
  418. #endif//TOSHIBA
  419. //
  420. // If a previous format was in use, release the memory
  421. //
  422. if (pStrmEx->pVideoInfoHeader) {
  423. ExFreePool(pStrmEx->pVideoInfoHeader);
  424. pStrmEx->pVideoInfoHeader = NULL;
  425. }
  426. // Since the VIDEOINFOHEADER is of potentially variable size
  427. // allocate memory for it
  428. pStrmEx->pVideoInfoHeader = ExAllocatePool(NonPagedPool, nSize);
  429. if (pStrmEx->pVideoInfoHeader == NULL) {
  430. KdPrint(("TsbVcap: ExAllocatePool failed\n"));
  431. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  432. return FALSE;
  433. }
  434. // Copy the VIDEOINFOHEADER requested to our storage
  435. RtlCopyMemory(
  436. pStrmEx->pVideoInfoHeader,
  437. pVideoInfoHdrRequested,
  438. nSize);
  439. #ifdef TOSHIBA
  440. if (pHwDevExt->NeedHWInit) HWInit(pHwDevExt);
  441. biWidth = pVideoInfoHdrRequested->bmiHeader.biWidth,
  442. biHeight = pVideoInfoHdrRequested->bmiHeader.biHeight,
  443. pHwDevExt->ulWidth = biWidth;
  444. pHwDevExt->ulHeight = biHeight;
  445. ImageSize = biWidth * biHeight;
  446. switch (pVideoInfoHdrRequested->bmiHeader.biCompression)
  447. {
  448. case FOURCC_YUV12: // I420
  449. pHwDevExt->Format = FmtYUV12;
  450. pHwDevExt->YoffsetEven = 0;
  451. pHwDevExt->UoffsetEven = 0;
  452. pHwDevExt->VoffsetEven = 0;
  453. pHwDevExt->YoffsetOdd = 0;
  454. pHwDevExt->UoffsetOdd = 0;
  455. pHwDevExt->VoffsetOdd = 0;
  456. pHwDevExt->Ystride = 0;
  457. pHwDevExt->Ustride = 0;
  458. pHwDevExt->Vstride = 0;
  459. if ( CurrentOSType ) { // NT5.0
  460. ImageSizeY = ImageSize;
  461. ImageSizeU = ImageSize / 4;
  462. ImageSizeV = ImageSize / 4;
  463. } else { // Win98
  464. pHwDevExt->pCaptureBufferU = (PUCHAR)pHwDevExt->pCaptureBufferY + ImageSize;
  465. pHwDevExt->pCaptureBufferV = (PUCHAR)pHwDevExt->pCaptureBufferU + ImageSize/4;
  466. pHwDevExt->pPhysCaptureBufferU.LowPart = pHwDevExt->pPhysCaptureBufferY.LowPart + ImageSize;
  467. pHwDevExt->pPhysCaptureBufferV.LowPart = pHwDevExt->pPhysCaptureBufferU.LowPart + ImageSize/4;
  468. }
  469. ImageSize = ImageSize * 12 / 8;
  470. break;
  471. case FOURCC_YVU9: // YVU9
  472. pHwDevExt->Format = FmtYUV9;
  473. pHwDevExt->YoffsetEven = 0;
  474. pHwDevExt->UoffsetEven = 0;
  475. pHwDevExt->VoffsetEven = 0;
  476. pHwDevExt->YoffsetOdd = 0;
  477. pHwDevExt->UoffsetOdd = 0;
  478. pHwDevExt->VoffsetOdd = 0;
  479. pHwDevExt->Ystride = 0;
  480. pHwDevExt->Ustride = 0;
  481. pHwDevExt->Vstride = 0;
  482. if ( CurrentOSType ) { // NT5.0
  483. ImageSizeY = ImageSize;
  484. ImageSizeU = ImageSize / 16;
  485. ImageSizeV = ImageSize / 16;
  486. } else { // Win98
  487. pHwDevExt->pCaptureBufferV = (PUCHAR)pHwDevExt->pCaptureBufferY + ImageSize;
  488. pHwDevExt->pCaptureBufferU = (PUCHAR)pHwDevExt->pCaptureBufferV + ImageSize/16;
  489. pHwDevExt->pPhysCaptureBufferV.LowPart = pHwDevExt->pPhysCaptureBufferY.LowPart + ImageSize;
  490. pHwDevExt->pPhysCaptureBufferU.LowPart = pHwDevExt->pPhysCaptureBufferV.LowPart + ImageSize/16;
  491. }
  492. ImageSize = ImageSize * 9 / 8;
  493. break;
  494. default:
  495. pSrb->Status = STATUS_INVALID_PARAMETER;
  496. return FALSE;
  497. }
  498. if (ImageSize > MAX_CAPTURE_BUFFER_SIZE) {
  499. if (pStrmEx->pVideoInfoHeader) {
  500. ExFreePool(pStrmEx->pVideoInfoHeader);
  501. pStrmEx->pVideoInfoHeader = NULL;
  502. }
  503. pSrb->Status = STATUS_INVALID_PARAMETER;
  504. return FALSE;
  505. }
  506. ulFrameRate = pHwDevExt->uiFramePerSecond;
  507. if (pHwDevExt->BufferSize != ImageSize) {
  508. if ( CurrentOSType ) { // NT5.0
  509. ULONG ulSize;
  510. PVOID VirtualAddress;
  511. PHYSICAL_ADDRESS LimitAddress;
  512. PHYSICAL_ADDRESS PhysicalAddress;
  513. pHwDevExt->IsRPSReady = FALSE;
  514. if ( pHwDevExt->pCaptureBufferY )
  515. {
  516. // free frame buffer
  517. MmFreeContiguousMemory(pHwDevExt->pCaptureBufferY);
  518. pHwDevExt->pCaptureBufferY = NULL;
  519. }
  520. if ( pHwDevExt->pCaptureBufferU )
  521. {
  522. // free frame buffer
  523. MmFreeContiguousMemory(pHwDevExt->pCaptureBufferU);
  524. pHwDevExt->pCaptureBufferU = NULL;
  525. }
  526. if ( pHwDevExt->pCaptureBufferV )
  527. {
  528. // free frame buffer
  529. MmFreeContiguousMemory(pHwDevExt->pCaptureBufferV);
  530. pHwDevExt->pCaptureBufferV = NULL;
  531. }
  532. // Allocate frame buffer
  533. LimitAddress.LowPart = 0xFFFFFFFF;
  534. LimitAddress.HighPart = 0;
  535. pHwDevExt->BufferSize = ImageSize;
  536. VirtualAddress = MmAllocateContiguousMemory(ImageSizeY, LimitAddress);
  537. if (VirtualAddress == 0)
  538. {
  539. pHwDevExt->pPhysCaptureBufferY.LowPart = 0;
  540. pHwDevExt->pPhysCaptureBufferY.HighPart = 0;
  541. pHwDevExt->pPhysCaptureBufferU.LowPart = 0;
  542. pHwDevExt->pPhysCaptureBufferU.HighPart = 0;
  543. pHwDevExt->pPhysCaptureBufferV.LowPart = 0;
  544. pHwDevExt->pPhysCaptureBufferV.HighPart = 0;
  545. pHwDevExt->BufferSize = 0;
  546. pSrb->Status = STATUS_INVALID_PARAMETER;
  547. return FALSE;
  548. }
  549. RtlZeroMemory(VirtualAddress, ImageSizeY);
  550. pHwDevExt->pCaptureBufferY = VirtualAddress;
  551. PhysicalAddress = MmGetPhysicalAddress(pHwDevExt->pCaptureBufferY);
  552. pHwDevExt->pPhysCaptureBufferY = PhysicalAddress;
  553. VirtualAddress = MmAllocateContiguousMemory(ImageSizeU, LimitAddress);
  554. if (VirtualAddress == 0)
  555. {
  556. MmFreeContiguousMemory(pHwDevExt->pCaptureBufferY);
  557. pHwDevExt->pCaptureBufferY = NULL;
  558. pHwDevExt->pPhysCaptureBufferY.LowPart = 0;
  559. pHwDevExt->pPhysCaptureBufferY.HighPart = 0;
  560. pHwDevExt->pPhysCaptureBufferU.LowPart = 0;
  561. pHwDevExt->pPhysCaptureBufferU.HighPart = 0;
  562. pHwDevExt->pPhysCaptureBufferV.LowPart = 0;
  563. pHwDevExt->pPhysCaptureBufferV.HighPart = 0;
  564. pHwDevExt->BufferSize = 0;
  565. pSrb->Status = STATUS_INVALID_PARAMETER;
  566. return FALSE;
  567. }
  568. RtlZeroMemory(VirtualAddress, ImageSizeU);
  569. pHwDevExt->pCaptureBufferU = VirtualAddress;
  570. PhysicalAddress = MmGetPhysicalAddress(pHwDevExt->pCaptureBufferU);
  571. pHwDevExt->pPhysCaptureBufferU = PhysicalAddress;
  572. VirtualAddress = MmAllocateContiguousMemory(ImageSizeV, LimitAddress);
  573. if (VirtualAddress == 0)
  574. {
  575. MmFreeContiguousMemory(pHwDevExt->pCaptureBufferY);
  576. pHwDevExt->pCaptureBufferY = NULL;
  577. MmFreeContiguousMemory(pHwDevExt->pCaptureBufferU);
  578. pHwDevExt->pCaptureBufferU = NULL;
  579. pHwDevExt->pPhysCaptureBufferY.LowPart = 0;
  580. pHwDevExt->pPhysCaptureBufferY.HighPart = 0;
  581. pHwDevExt->pPhysCaptureBufferU.LowPart = 0;
  582. pHwDevExt->pPhysCaptureBufferU.HighPart = 0;
  583. pHwDevExt->pPhysCaptureBufferV.LowPart = 0;
  584. pHwDevExt->pPhysCaptureBufferV.HighPart = 0;
  585. pHwDevExt->BufferSize = 0;
  586. pSrb->Status = STATUS_INVALID_PARAMETER;
  587. return FALSE;
  588. }
  589. RtlZeroMemory(VirtualAddress, ImageSizeV);
  590. pHwDevExt->pCaptureBufferV = VirtualAddress;
  591. PhysicalAddress = MmGetPhysicalAddress(pHwDevExt->pCaptureBufferV);
  592. pHwDevExt->pPhysCaptureBufferV = PhysicalAddress;
  593. ulFrameRate = 15;
  594. pHwDevExt->dblBufflag = FALSE;
  595. } else {
  596. pHwDevExt->IsRPSReady = FALSE;
  597. pHwDevExt->BufferSize = ImageSize;
  598. if ((ImageSize * 2) > MAX_CAPTURE_BUFFER_SIZE) {
  599. ulFrameRate = 15;
  600. pHwDevExt->dblBufflag = FALSE;
  601. } else {
  602. ulFrameRate = 30;
  603. Alloc_TriBuffer(pHwDevExt);
  604. pHwDevExt->dblBufflag = TRUE;
  605. }
  606. }
  607. }
  608. if(!ImageSetInputImageSize(pHwDevExt, &(pHwDevExt->SrcRect))) // Insert 97-04-08(Tue)
  609. {
  610. pSrb->Status = STATUS_INVALID_PARAMETER;
  611. return FALSE;
  612. }
  613. if(!ImageSetOutputImageSize(pHwDevExt, pHwDevExt->ulWidth, pHwDevExt->ulHeight)) // Insert 97-04-08(Tue)
  614. {
  615. pSrb->Status = STATUS_INVALID_PARAMETER;
  616. return FALSE;
  617. }
  618. if (!BertFifoConfig(pHwDevExt, pHwDevExt->Format))
  619. {
  620. pSrb->Status = STATUS_INVALID_PARAMETER;
  621. return FALSE;
  622. }
  623. if(!ImageSetHueBrightnessContrastSat(pHwDevExt)){ // Insert 97-04-08(Tue)
  624. return FALSE;
  625. }
  626. if ( pHwDevExt->ColorEnable ) {
  627. if ( get_AblFilter( pHwDevExt ) ) {
  628. set_filtering( pHwDevExt, TRUE );
  629. } else {
  630. set_filtering( pHwDevExt, FALSE );
  631. pHwDevExt->ColorEnable = 0;
  632. }
  633. } else {
  634. set_filtering( pHwDevExt, FALSE );
  635. }
  636. //
  637. // check the bounds for the frame rate
  638. //
  639. if (pHwDevExt->uiFramePerSecond != ulFrameRate)
  640. {
  641. pHwDevExt->uiFramePerSecond = ulFrameRate;
  642. pHwDevExt->IsRPSReady = FALSE;
  643. }
  644. if (pHwDevExt->IsRPSReady == FALSE)
  645. {
  646. dwAddr = (DWORD)pHwDevExt->pPhysRpsDMABuf.LowPart;
  647. #if 0
  648. dwAddr = (dwAddr + 0x1FFF) & 0xFFFFE000;
  649. #endif
  650. pHwDevExt->s_physDmaActiveFlag = dwAddr + 0X1860;
  651. if( pHwDevExt->dblBufflag ){
  652. BertTriBuildNodes(pHwDevExt); // Add 97-04-08(Tue)
  653. }
  654. else{
  655. BertBuildNodes(pHwDevExt); // Add 97-04-08(Tue)
  656. }
  657. pHwDevExt->IsRPSReady = TRUE;
  658. }
  659. #endif//TOSHIBA
  660. }
  661. // -------------------------------------------------------------------
  662. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  663. // -------------------------------------------------------------------
  664. else if (IsEqualGUID (&pKSDataFormat->Specifier,
  665. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  666. //
  667. // AnalogVideo DataRange == DataFormat!
  668. //
  669. // For now, don't even cache this
  670. // TODO - Save the requested format
  671. //
  672. PKS_DATARANGE_ANALOGVIDEO pDataFormatAnalogVideo =
  673. (PKS_DATARANGE_ANALOGVIDEO) pSrb->CommandData.OpenFormat;
  674. }
  675. else {
  676. // Unknown format
  677. pSrb->Status = STATUS_INVALID_PARAMETER;
  678. return FALSE;
  679. }
  680. return TRUE;
  681. }
  682. /*
  683. ** VideoReceiveDataPacket()
  684. **
  685. ** Receives Video data packet commands on the output streams
  686. **
  687. ** Arguments:
  688. **
  689. ** pSrb - Stream request block for the Video stream
  690. **
  691. ** Returns: nothing
  692. **
  693. ** Side Effects: none
  694. */
  695. VOID
  696. STREAMAPI
  697. VideoReceiveDataPacket(
  698. IN PHW_STREAM_REQUEST_BLOCK pSrb
  699. )
  700. {
  701. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  702. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  703. int StreamNumber = pSrb->StreamObject->StreamNumber;
  704. //
  705. // make sure we have a device extension and are at passive level
  706. //
  707. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  708. DEBUG_ASSERT((ULONG)pHwDevExt);
  709. KdPrint(("TsbVcap: Receiving Stream Data SRB %8x, %x\n", pSrb, pSrb->Command));
  710. //
  711. // Default to success
  712. //
  713. pSrb->Status = STATUS_SUCCESS;
  714. //
  715. // determine the type of packet.
  716. //
  717. switch (pSrb->Command){
  718. case SRB_READ_DATA:
  719. // Rule:
  720. // Only accept read requests when in either the Pause or Run
  721. // States. If Stopped, immediately return the SRB.
  722. if (pStrmEx->KSState == KSSTATE_STOP) {
  723. CompleteStreamSRB (pSrb);
  724. break;
  725. }
  726. #ifdef TOSHIBA
  727. if (pHwDevExt->bVideoIn == FALSE) {
  728. CompleteStreamSRB (pSrb);
  729. break;
  730. }
  731. #endif//TOSHIBA
  732. //
  733. // Put this read request on the pending queue
  734. //
  735. VideoQueueAddSRB (pSrb);
  736. break;
  737. default:
  738. //
  739. // invalid / unsupported command. Fail it as such
  740. //
  741. TRAP
  742. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  743. CompleteStreamSRB (pSrb);
  744. } // switch (pSrb->Command)
  745. }
  746. /*
  747. ** VideoReceiveCtrlPacket()
  748. **
  749. ** Receives packet commands that control the Video output streams
  750. **
  751. ** Arguments:
  752. **
  753. ** pSrb - The stream request block for the Video stream
  754. **
  755. ** Returns: nothing
  756. **
  757. ** Side Effects: none
  758. */
  759. VOID
  760. STREAMAPI
  761. VideoReceiveCtrlPacket(
  762. IN PHW_STREAM_REQUEST_BLOCK pSrb
  763. )
  764. {
  765. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  766. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  767. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  768. BOOL Busy;
  769. //
  770. // make sure we have a device extension and are at passive level
  771. //
  772. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  773. DEBUG_ASSERT((ULONG)pHwDevExt);
  774. KdPrint(("TsbVcap: Receiving Stream Control SRB %8x, %x\n", pSrb, pSrb->Command));
  775. //
  776. // If we're already processing an SRB, add it to the queue
  777. //
  778. Busy = AddToListIfBusy (
  779. pSrb,
  780. &pHwDevExt->AdapterSpinLock,
  781. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  782. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  783. if (Busy) {
  784. return;
  785. }
  786. while (TRUE) {
  787. //
  788. // Default to success
  789. //
  790. pSrb->Status = STATUS_SUCCESS;
  791. //
  792. // determine the type of packet.
  793. //
  794. switch (pSrb->Command)
  795. {
  796. case SRB_PROPOSE_DATA_FORMAT:
  797. KdPrint(("TsbVcap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %8x, StreamNumber= %d\n", pSrb, StreamNumber));
  798. if (!(AdapterVerifyFormat (
  799. pSrb->CommandData.OpenFormat,
  800. pSrb->StreamObject->StreamNumber))) {
  801. pSrb->Status = STATUS_NO_MATCH;
  802. KdPrint(("TsbVcap: SRB_PROPOSE_DATA_FORMAT FAILED\n"));
  803. }
  804. break;
  805. case SRB_SET_DATA_FORMAT:
  806. KdPrint(("TsbVcap: SRB_SET_DATA_FORMAT\n"));
  807. if (!(AdapterVerifyFormat (
  808. pSrb->CommandData.OpenFormat,
  809. pSrb->StreamObject->StreamNumber))) {
  810. pSrb->Status = STATUS_NO_MATCH;
  811. KdPrint(("TsbVcap: SRB_SET_DATA_FORMAT FAILED\n"));
  812. } else {
  813. VideoSetFormat (pSrb);
  814. KdPrint(("TsbVcap: SRB_SET_DATA_FORMAT SUCCEEDED\n"));
  815. }
  816. break;
  817. case SRB_GET_DATA_FORMAT:
  818. KdPrint(("TsbVcap: SRB_GET_DATA_FORMAT\n"));
  819. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  820. break;
  821. case SRB_SET_STREAM_STATE:
  822. VideoSetState(pSrb);
  823. break;
  824. case SRB_GET_STREAM_STATE:
  825. VideoGetState(pSrb);
  826. break;
  827. case SRB_GET_STREAM_PROPERTY:
  828. VideoGetProperty(pSrb);
  829. break;
  830. case SRB_SET_STREAM_PROPERTY:
  831. VideoSetProperty(pSrb);
  832. break;
  833. case SRB_INDICATE_MASTER_CLOCK:
  834. //
  835. // Assigns a clock to a stream
  836. //
  837. VideoIndicateMasterClock (pSrb);
  838. break;
  839. default:
  840. //
  841. // invalid / unsupported command. Fail it as such
  842. //
  843. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  844. }
  845. CompleteStreamSRB (pSrb);
  846. //
  847. // See if there's anything else on the queue
  848. //
  849. Busy = RemoveFromListIfAvailable (
  850. &pSrb,
  851. &pHwDevExt->AdapterSpinLock,
  852. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  853. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  854. if (!Busy) {
  855. break;
  856. }
  857. }
  858. }
  859. #ifndef TOSHIBA
  860. /*
  861. ** AnalogVideoReceiveDataPacket()
  862. **
  863. ** Receives AnalogVideo data packet commands on the input stream
  864. **
  865. ** Arguments:
  866. **
  867. ** pSrb - Stream request block for the Analog Video stream.
  868. ** This stream receives tuner control packets.
  869. **
  870. ** Returns: nothing
  871. **
  872. ** Side Effects: none
  873. */
  874. VOID
  875. STREAMAPI
  876. AnalogVideoReceiveDataPacket(
  877. IN PHW_STREAM_REQUEST_BLOCK pSrb
  878. )
  879. {
  880. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  881. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  882. PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
  883. //
  884. // make sure we have a device extension and are at passive level
  885. //
  886. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  887. DEBUG_ASSERT((ULONG)pHwDevExt);
  888. KdPrint(("TsbVcap: Receiving Tuner packet SRB %8x, %x\n", pSrb, pSrb->Command));
  889. //
  890. // Default to success
  891. //
  892. pSrb->Status = STATUS_SUCCESS;
  893. //
  894. // determine the type of packet.
  895. //
  896. switch (pSrb->Command){
  897. case SRB_WRITE_DATA:
  898. //
  899. // This data packet contains the channel change information
  900. // passed on the AnalogVideoIn stream. Devices which support
  901. // VBI data streams need to pass this info on their output pins.
  902. //
  903. if (pDataPacket->FrameExtent == sizeof (KS_TVTUNER_CHANGE_INFO)) {
  904. RtlCopyMemory(
  905. &pHwDevExt->TVTunerChangeInfo,
  906. pDataPacket->Data,
  907. sizeof (KS_TVTUNER_CHANGE_INFO));
  908. }
  909. CompleteStreamSRB (pSrb);
  910. break;
  911. default:
  912. //
  913. // invalid / unsupported command. Fail it as such
  914. //
  915. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  916. CompleteStreamSRB (pSrb);
  917. } // switch (pSrb->Command)
  918. }
  919. /*
  920. ** AnalogVideoReceiveCtrlPacket()
  921. **
  922. ** Receives packet commands that control the Analog Video stream
  923. **
  924. ** Arguments:
  925. **
  926. ** pSrb - The stream request block for the Video stream
  927. **
  928. ** Returns: nothing
  929. **
  930. ** Side Effects: none
  931. */
  932. VOID
  933. STREAMAPI
  934. AnalogVideoReceiveCtrlPacket(
  935. IN PHW_STREAM_REQUEST_BLOCK pSrb
  936. )
  937. {
  938. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  939. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  940. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  941. BOOL Busy;
  942. //
  943. // make sure we have a device extension and we are at passive level
  944. //
  945. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  946. DEBUG_ASSERT((ULONG)pHwDevExt);
  947. KdPrint(("TsbVcap: Receiving Analog Stream Control SRB %8x, %x\n", pSrb, pSrb->Command));
  948. //
  949. // If we're already processing an SRB, add it to the queue
  950. //
  951. Busy = AddToListIfBusy (
  952. pSrb,
  953. &pHwDevExt->AdapterSpinLock,
  954. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  955. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  956. if (Busy) {
  957. return;
  958. }
  959. while (TRUE) {
  960. //
  961. // Default to success
  962. //
  963. pSrb->Status = STATUS_SUCCESS;
  964. //
  965. // determine the type of packet.
  966. //
  967. switch (pSrb->Command)
  968. {
  969. case SRB_PROPOSE_DATA_FORMAT:
  970. KdPrint(("TsbVcap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %8x, StreamNumber= %d\n", pSrb, StreamNumber));
  971. if (!(AdapterVerifyFormat (
  972. pSrb->CommandData.OpenFormat,
  973. pSrb->StreamObject->StreamNumber))) {
  974. pSrb->Status = STATUS_NO_MATCH;
  975. }
  976. break;
  977. case SRB_SET_STREAM_STATE:
  978. //
  979. // Don't use VideoSetState, since we don't want to start another
  980. // timer running
  981. //
  982. pStrmEx->KSState = pSrb->CommandData.StreamState;
  983. break;
  984. case SRB_GET_STREAM_STATE:
  985. VideoGetState(pSrb);
  986. break;
  987. case SRB_GET_STREAM_PROPERTY:
  988. VideoGetProperty(pSrb);
  989. break;
  990. case SRB_INDICATE_MASTER_CLOCK:
  991. //
  992. // Assigns a clock to a stream
  993. //
  994. VideoIndicateMasterClock (pSrb);
  995. break;
  996. default:
  997. //
  998. // invalid / unsupported command. Fail it as such
  999. //
  1000. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1001. }
  1002. CompleteStreamSRB (pSrb);
  1003. //
  1004. // See if there's anything else on the queue
  1005. //
  1006. Busy = RemoveFromListIfAvailable (
  1007. &pSrb,
  1008. &pHwDevExt->AdapterSpinLock,
  1009. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  1010. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  1011. if (!Busy) {
  1012. break;
  1013. }
  1014. }
  1015. }
  1016. #endif//TOSHIBA
  1017. /*
  1018. ** CompleteStreamSRB ()
  1019. **
  1020. ** This routine is called when a packet is being completed.
  1021. **
  1022. ** Arguments:
  1023. **
  1024. ** pSrb - pointer to the request packet to be completed
  1025. **
  1026. ** Returns:
  1027. **
  1028. ** Side Effects: none
  1029. */
  1030. VOID
  1031. STREAMAPI
  1032. CompleteStreamSRB (
  1033. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1034. )
  1035. {
  1036. KdPrint(("TsbVcap: Completing Stream SRB %8x\n", pSrb));
  1037. StreamClassStreamNotification(
  1038. StreamRequestComplete,
  1039. pSrb->StreamObject,
  1040. pSrb);
  1041. }
  1042. /*
  1043. ** VideoGetProperty()
  1044. **
  1045. ** Routine to process video property requests
  1046. **
  1047. ** Arguments:
  1048. **
  1049. ** pSrb - pointer to the stream request block for properties
  1050. **
  1051. ** Returns:
  1052. **
  1053. ** Side Effects: none
  1054. */
  1055. VOID
  1056. STREAMAPI
  1057. VideoGetProperty(
  1058. PHW_STREAM_REQUEST_BLOCK pSrb
  1059. )
  1060. {
  1061. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1062. if (IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
  1063. VideoStreamGetConnectionProperty (pSrb);
  1064. }
  1065. else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
  1066. VideoStreamGetDroppedFramesProperty (pSrb);
  1067. }
  1068. else {
  1069. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1070. }
  1071. }
  1072. /*
  1073. ** VideoSetProperty()
  1074. **
  1075. ** Routine to process video property requests
  1076. **
  1077. ** Arguments:
  1078. **
  1079. ** pSrb - pointer to the stream request block for properties
  1080. **
  1081. ** Returns:
  1082. **
  1083. ** Side Effects: none
  1084. */
  1085. VOID
  1086. STREAMAPI
  1087. VideoSetProperty(
  1088. PHW_STREAM_REQUEST_BLOCK pSrb
  1089. )
  1090. {
  1091. // PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1092. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1093. }
  1094. #ifdef TOSHIBA
  1095. #ifdef _FPS_COUNT_
  1096. VOID
  1097. STREAMAPI
  1098. VideoFpsOutputRoutine(
  1099. IN PSTREAMEX pStrmEx
  1100. )
  1101. {
  1102. if (pStrmEx->KSState == KSSTATE_RUN) {
  1103. DbgPrint("INT = %d FPS = %d\n", InterruptCounter, FrameCounter);
  1104. InterruptCounter = 0;
  1105. FrameCounter = 0;
  1106. }
  1107. }
  1108. VOID
  1109. STREAMAPI
  1110. VideoTimerRoutine(
  1111. PVOID Context
  1112. )
  1113. {
  1114. PSTREAMEX pStrmEx = ((PSTREAMEX)Context);
  1115. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  1116. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  1117. // If we're stopped and the timer is still running, just return.
  1118. // This will stop the timer.
  1119. if (pStrmEx->KSState == KSSTATE_STOP) {
  1120. return;
  1121. }
  1122. // Capture a frame if it's time and we have a buffer
  1123. VideoFpsOutputRoutine(pStrmEx);
  1124. // Schedule the next timer event
  1125. // Make it run at 2x the requested capture rate (which is in 100nS units)
  1126. StreamClassScheduleTimer (
  1127. pStrmEx->pStreamObject, // StreamObject
  1128. pHwDevExt, // HwDeviceExtension
  1129. (ULONG) 1000000, // Microseconds
  1130. VideoTimerRoutine, // TimerRoutine
  1131. pStrmEx); // Context
  1132. }
  1133. #endif//_FPS_COUNT_
  1134. #else //TOSHIBA
  1135. /*
  1136. ** VideoTimerRoutine()
  1137. **
  1138. ** A timer has been created based on the requested capture interval.
  1139. ** This is the callback routine for this timer event.
  1140. **
  1141. ** Note: Devices capable of using interrupts should always
  1142. ** trigger capture on a VSYNC interrupt, and not use a timer.
  1143. **
  1144. ** Arguments:
  1145. **
  1146. ** Context - pointer to the stream extension
  1147. **
  1148. ** Returns: nothing
  1149. **
  1150. ** Side Effects: none
  1151. */
  1152. VOID
  1153. STREAMAPI
  1154. VideoTimerRoutine(
  1155. PVOID Context
  1156. )
  1157. {
  1158. PSTREAMEX pStrmEx = ((PSTREAMEX)Context);
  1159. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  1160. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  1161. // If we're stopped and the timer is still running, just return.
  1162. // This will stop the timer.
  1163. if (pStrmEx->KSState == KSSTATE_STOP) {
  1164. return;
  1165. }
  1166. // Capture a frame if it's time and we have a buffer
  1167. VideoCaptureRoutine(pStrmEx);
  1168. // Schedule the next timer event
  1169. // Make it run at 2x the requested capture rate (which is in 100nS units)
  1170. StreamClassScheduleTimer (
  1171. pStrmEx->pStreamObject, // StreamObject
  1172. pHwDevExt, // HwDeviceExtension
  1173. (ULONG) (pStrmEx->pVideoInfoHeader->AvgTimePerFrame / 20), // Microseconds
  1174. VideoTimerRoutine, // TimerRoutine
  1175. pStrmEx); // Context
  1176. }
  1177. /*
  1178. ** VideoCaptureRoutine()
  1179. **
  1180. ** Routine to capture video frames based on a timer.
  1181. **
  1182. ** Note: Devices capable of using interrupts should always
  1183. ** trigger capture on a VSYNC interrupt, and not use a timer.
  1184. **
  1185. ** Arguments:
  1186. **
  1187. ** Returns: nothing
  1188. **
  1189. ** Side Effects: none
  1190. */
  1191. VOID
  1192. STREAMAPI
  1193. VideoCaptureRoutine(
  1194. IN PSTREAMEX pStrmEx
  1195. )
  1196. {
  1197. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  1198. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  1199. PKSSTREAM_HEADER pDataPacket;
  1200. PKS_FRAME_INFO pFrameInfo;
  1201. // If we're stopped and the timer is still running, just return.
  1202. // This will stop the timer.
  1203. if (pStrmEx->KSState == KSSTATE_STOP) {
  1204. return;
  1205. }
  1206. // Find out what time it is, if we're using a clock
  1207. if (pStrmEx->hMasterClock ) {
  1208. HW_TIME_CONTEXT TimeContext;
  1209. TimeContext.HwDeviceExtension = pHwDevExt;
  1210. TimeContext.HwStreamObject = pStrmEx->pStreamObject;
  1211. TimeContext.Function = TIME_GET_STREAM_TIME;
  1212. StreamClassQueryMasterClockSync (
  1213. pStrmEx->hMasterClock,
  1214. &TimeContext);
  1215. pStrmEx->QST_StreamTime = TimeContext.Time;
  1216. pStrmEx->QST_Now = TimeContext.SystemTime;
  1217. if (pStrmEx->QST_NextFrame == 0) {
  1218. pStrmEx->QST_NextFrame = pStrmEx->QST_StreamTime + pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  1219. }
  1220. #ifdef CREATE_A_FLURRY_OF_TIMING_SPEW
  1221. KdPrint(("TsbVcap: Time=%16lx\n", TimeContext.Time));
  1222. KdPrint(("TsbVcap: SysTime=%16lx\n", TimeContext.SystemTime));
  1223. #endif
  1224. }
  1225. // Only capture in the RUN state
  1226. if (pStrmEx->KSState == KSSTATE_RUN) {
  1227. //
  1228. // Determine if it is time to capture a frame based on
  1229. // how much time has elapsed since capture started.
  1230. // If there isn't a clock available, then capture immediately.
  1231. //
  1232. if ((!pStrmEx->hMasterClock) ||
  1233. (pStrmEx->QST_StreamTime >= pStrmEx->QST_NextFrame)) {
  1234. PHW_STREAM_REQUEST_BLOCK pSrb;
  1235. // Increment the picture count (usually this is VSYNC count)
  1236. pStrmEx->FrameInfo.PictureNumber++;
  1237. //
  1238. // Get the next queue SRB (if any)
  1239. //
  1240. pSrb = VideoQueueRemoveSRB (
  1241. pHwDevExt,
  1242. StreamNumber);
  1243. if (pSrb) {
  1244. pDataPacket = pSrb->CommandData.DataBufferArray;
  1245. pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
  1246. //
  1247. // Call the routine which synthesizes images
  1248. //
  1249. ImageSynth (pSrb,
  1250. pHwDevExt->VideoInputConnected,
  1251. pStrmEx->VideoControlMode & KS_VideoControlFlag_FlipHorizontal);
  1252. // Set additional info fields about the data captured such as:
  1253. // Frames Captured
  1254. // Frames Dropped
  1255. // Field Polarity
  1256. pStrmEx->FrameInfo.ExtendedHeaderSize = pFrameInfo->ExtendedHeaderSize;
  1257. *pFrameInfo = pStrmEx->FrameInfo;
  1258. // Init the flags to zero
  1259. pDataPacket->OptionsFlags = 0;
  1260. // Set the discontinuity flag if frames have been previously
  1261. // dropped, and then reset our internal flag
  1262. if (pStrmEx->fDiscontinuity) {
  1263. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  1264. pStrmEx->fDiscontinuity = FALSE;
  1265. }
  1266. //
  1267. // Return the timestamp for the frame
  1268. //
  1269. pDataPacket->PresentationTime.Numerator = 1;
  1270. pDataPacket->PresentationTime.Denominator = 1;
  1271. pDataPacket->Duration = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  1272. //
  1273. // if we have a master clock AND this is the capture stream
  1274. //
  1275. if (pStrmEx->hMasterClock && (StreamNumber == 0)) {
  1276. pDataPacket->PresentationTime.Time = pStrmEx->QST_StreamTime;
  1277. pDataPacket->OptionsFlags |=
  1278. KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  1279. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  1280. }
  1281. else {
  1282. //
  1283. // no clock or the preview stream, so just mark the time as unknown
  1284. //
  1285. pDataPacket->PresentationTime.Time = 0;
  1286. // clear the timestamp valid flags
  1287. pDataPacket->OptionsFlags &=
  1288. ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  1289. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  1290. }
  1291. // Every frame we generate is a key frame (aka SplicePoint)
  1292. // Delta frames (B or P) should not set this flag
  1293. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
  1294. CompleteStreamSRB (pSrb);
  1295. } // if we have an SRB
  1296. else {
  1297. //
  1298. // No buffer was available when we should have captured one
  1299. // Increment the counter which keeps track of
  1300. // dropped frames
  1301. pStrmEx->FrameInfo.DropCount++;
  1302. // Set the (local) discontinuity flag
  1303. // This will cause the next packet processed to have the
  1304. // KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY flag set.
  1305. pStrmEx->fDiscontinuity = TRUE;
  1306. }
  1307. // Figure out when to capture the next frame
  1308. pStrmEx->QST_NextFrame += pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  1309. } // endif time to capture a frame
  1310. } // endif we're running
  1311. }
  1312. #endif//TOSHIBA
  1313. /*
  1314. ** VideoSetState()
  1315. **
  1316. ** Sets the current state for a given stream
  1317. **
  1318. ** Arguments:
  1319. **
  1320. ** pSrb - pointer to the stream request block for properties
  1321. **
  1322. ** Returns:
  1323. **
  1324. ** Side Effects: none
  1325. */
  1326. VOID
  1327. STREAMAPI
  1328. VideoSetState(
  1329. PHW_STREAM_REQUEST_BLOCK pSrb
  1330. )
  1331. {
  1332. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  1333. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1334. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  1335. KSSTATE PreviousState;
  1336. //
  1337. // For each stream, the following states are used:
  1338. //
  1339. // Stop: Absolute minimum resources are used. No outstanding IRPs.
  1340. // Acquire: KS only state that has no DirectShow correpondence
  1341. // Acquire needed resources.
  1342. // Pause: Getting ready to run. Allocate needed resources so that
  1343. // the eventual transition to Run is as fast as possible.
  1344. // Read SRBs will be queued at either the Stream class
  1345. // or in your driver (depending on when you send "ReadyForNext")
  1346. // and whether you're using the Stream class for synchronization
  1347. // Run: Streaming.
  1348. //
  1349. // Moving to Stop to Run always transitions through Pause.
  1350. //
  1351. // But since a client app could crash unexpectedly, drivers should handle
  1352. // the situation of having outstanding IRPs cancelled and open streams
  1353. // being closed WHILE THEY ARE STREAMING!
  1354. //
  1355. // Note that it is quite possible to transition repeatedly between states:
  1356. // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop
  1357. //
  1358. //
  1359. // Remember the state we're transitioning away from
  1360. //
  1361. PreviousState = pStrmEx->KSState;
  1362. //
  1363. // Set the new state
  1364. //
  1365. pStrmEx->KSState = pSrb->CommandData.StreamState;
  1366. switch (pSrb->CommandData.StreamState)
  1367. {
  1368. case KSSTATE_STOP:
  1369. //
  1370. // The stream class will cancel all outstanding IRPs for us
  1371. // (but only if it is maintaining the queue ie. using Stream Class synchronization)
  1372. // Since TsbVcap is not using Stream Class synchronization, we must clear the queue here
  1373. #ifdef TOSHIBA
  1374. if (pHwDevExt->bVideoIn == TRUE) {
  1375. // disable the RPS_INT and field interrupts
  1376. BertInterruptEnable(pHwDevExt, FALSE);
  1377. BertDMAEnable(pHwDevExt, FALSE);
  1378. // wait for the current data xfer to complete
  1379. // if (!BertIsCAPSTATReady(pHwDevExt)) return FALSE;
  1380. pHwDevExt->bVideoIn = FALSE;
  1381. }
  1382. #endif//TOSHIBA
  1383. VideoQueueCancelAllSRBs (pStrmEx);
  1384. KdPrint(("TsbVcap: STATE Stopped, Stream=%d\n", StreamNumber));
  1385. break;
  1386. case KSSTATE_ACQUIRE:
  1387. //
  1388. // This is a KS only state, that has no correspondence in DirectShow
  1389. //
  1390. KdPrint(("TsbVcap: STATE Acquire, Stream=%d\n", StreamNumber));
  1391. break;
  1392. case KSSTATE_PAUSE:
  1393. //
  1394. // On a transition to pause from acquire or stop, start our timer running.
  1395. //
  1396. if (PreviousState == KSSTATE_ACQUIRE || PreviousState == KSSTATE_STOP) {
  1397. // Zero the frame counters
  1398. pStrmEx->FrameInfo.PictureNumber = 0;
  1399. pStrmEx->FrameInfo.DropCount = 0;
  1400. pStrmEx->FrameInfo.dwFrameFlags = 0;
  1401. #ifdef TOSHIBA
  1402. #ifdef _FPS_COUNT_
  1403. FrameCounter = 0;
  1404. InterruptCounter = 0;
  1405. StreamClassScheduleTimer (
  1406. pSrb->StreamObject, // StreamObject
  1407. pHwDevExt, // HwDeviceExtension
  1408. (ULONG) 1000000, // Microseconds
  1409. VideoTimerRoutine, // TimerRoutine
  1410. pStrmEx); // Context
  1411. #endif//_FPS_COUNT_
  1412. if (!BertIsLocked(pHwDevExt))
  1413. {
  1414. pHwDevExt->NeedHWInit = TRUE;
  1415. }
  1416. pHwDevExt->bVideoIn = TRUE;
  1417. // enable the RPS_INT and field interrupts
  1418. BertInterruptEnable(pHwDevExt, TRUE);
  1419. BertDMAEnable(pHwDevExt, TRUE);
  1420. } else {
  1421. // disable the RPS_INT and field interrupts
  1422. BertInterruptEnable(pHwDevExt, FALSE);
  1423. BertDMAEnable(pHwDevExt, FALSE);
  1424. // wait for the current data xfer to complete
  1425. // if (!BertIsCAPSTATReady(pHwDevExt)) return FALSE;
  1426. pHwDevExt->bVideoIn = FALSE;
  1427. #else //TOSHIBA
  1428. // Setup the next timer callback
  1429. // Make it run at 2x the requested capture rate (which is in 100nS units)
  1430. StreamClassScheduleTimer (
  1431. pSrb->StreamObject, // StreamObject
  1432. pHwDevExt, // HwDeviceExtension
  1433. (ULONG) (pStrmEx->pVideoInfoHeader->AvgTimePerFrame / 20), // Microseconds
  1434. VideoTimerRoutine, // TimerRoutine
  1435. pStrmEx); // Context
  1436. #endif//TOSHIBA
  1437. }
  1438. KdPrint(("TsbVcap: STATE Pause, Stream=%d\n", StreamNumber));
  1439. break;
  1440. case KSSTATE_RUN:
  1441. //
  1442. // Begin Streaming.
  1443. //
  1444. // Reset the discontinuity flag
  1445. pStrmEx->fDiscontinuity = FALSE;
  1446. // Setting the NextFrame time to zero will cause the value to be
  1447. // reset from the stream time
  1448. pStrmEx->QST_NextFrame = 0;
  1449. #ifdef TOSHIBA
  1450. if (pHwDevExt->bVideoIn == FALSE) {
  1451. if (!BertIsLocked(pHwDevExt))
  1452. {
  1453. pHwDevExt->NeedHWInit = TRUE;
  1454. }
  1455. pHwDevExt->bVideoIn = TRUE;
  1456. // enable the RPS_INT and field interrupts
  1457. BertInterruptEnable(pHwDevExt, TRUE);
  1458. BertDMAEnable(pHwDevExt, TRUE);
  1459. }
  1460. #endif//TOSHIBA
  1461. KdPrint(("TsbVcap: STATE Run, Stream=%d\n", StreamNumber));
  1462. break;
  1463. } // end switch (pSrb->CommandData.StreamState)
  1464. }
  1465. /*
  1466. ** VideoGetState()
  1467. **
  1468. ** Gets the current state of the requested stream
  1469. **
  1470. ** Arguments:
  1471. **
  1472. ** pSrb - pointer to the stream request block for properties
  1473. **
  1474. ** Returns:
  1475. **
  1476. ** Side Effects: none
  1477. */
  1478. VOID
  1479. STREAMAPI
  1480. VideoGetState(
  1481. PHW_STREAM_REQUEST_BLOCK pSrb
  1482. )
  1483. {
  1484. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1485. pSrb->CommandData.StreamState = pStrmEx->KSState;
  1486. pSrb->ActualBytesTransferred = sizeof (KSSTATE);
  1487. // A very odd rule:
  1488. // When transitioning from stop to pause, DShow tries to preroll
  1489. // the graph. Capture sources can't preroll, and indicate this
  1490. // by returning VFW_S_CANT_CUE in user mode. To indicate this
  1491. // condition from drivers, they must return STATUS_NO_DATA_DETECTED
  1492. if (pStrmEx->KSState == KSSTATE_PAUSE) {
  1493. pSrb->Status = STATUS_NO_DATA_DETECTED;
  1494. }
  1495. }
  1496. /*
  1497. ** VideoStreamGetConnectionProperty()
  1498. **
  1499. ** Gets the properties for a stream
  1500. **
  1501. ** Arguments:
  1502. **
  1503. ** pSrb - pointer to the stream request block for properties
  1504. **
  1505. ** Returns:
  1506. **
  1507. ** Side Effects: none
  1508. */
  1509. VOID
  1510. STREAMAPI
  1511. VideoStreamGetConnectionProperty(
  1512. PHW_STREAM_REQUEST_BLOCK pSrb
  1513. )
  1514. {
  1515. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1516. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1517. ULONG Id = pSPD->Property->Id; // index of the property
  1518. switch (Id) {
  1519. // This property describes the allocator requirements for the stream
  1520. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  1521. if (pStrmEx->pVideoInfoHeader) {
  1522. PKSALLOCATOR_FRAMING Framing =
  1523. (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  1524. Framing->RequirementsFlags =
  1525. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  1526. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  1527. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
  1528. Framing->PoolType = PagedPool;
  1529. Framing->Frames = 1;
  1530. Framing->FrameSize = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1531. Framing->FileAlignment = 0; // FILE_LONG_ALIGNMENT???;
  1532. Framing->Reserved = 0;
  1533. pSrb->ActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  1534. }
  1535. else {
  1536. pSrb->Status = STATUS_INVALID_PARAMETER;
  1537. }
  1538. break;
  1539. default:
  1540. break;
  1541. }
  1542. }
  1543. /*
  1544. ** VideoStreamGetDroppedFramesProperty()
  1545. **
  1546. ** Gets dynamic information about the progress of the capture process.
  1547. **
  1548. ** Arguments:
  1549. **
  1550. ** pSrb - pointer to the stream request block for properties
  1551. **
  1552. ** Returns:
  1553. **
  1554. ** Side Effects: none
  1555. */
  1556. VOID
  1557. STREAMAPI
  1558. VideoStreamGetDroppedFramesProperty(
  1559. PHW_STREAM_REQUEST_BLOCK pSrb
  1560. )
  1561. {
  1562. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1563. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1564. ULONG Id = pSPD->Property->Id; // index of the property
  1565. switch (Id) {
  1566. case KSPROPERTY_DROPPEDFRAMES_CURRENT:
  1567. {
  1568. PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames =
  1569. (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;
  1570. pDroppedFrames->PictureNumber = pStrmEx->FrameInfo.PictureNumber;
  1571. pDroppedFrames->DropCount = pStrmEx->FrameInfo.DropCount;
  1572. pDroppedFrames->AverageFrameSize = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1573. pSrb->ActualBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
  1574. }
  1575. break;
  1576. default:
  1577. break;
  1578. }
  1579. }
  1580. //==========================================================================;
  1581. // Clock Handling Routines
  1582. //==========================================================================;
  1583. /*
  1584. ** VideoIndicateMasterClock ()
  1585. **
  1586. ** If this stream is not being used as the master clock, this function
  1587. ** is used to provide us with a handle to the clock to use when
  1588. ** requesting the current stream time.
  1589. **
  1590. ** Arguments:
  1591. **
  1592. ** pSrb - pointer to the stream request block for properties
  1593. **
  1594. ** Returns:
  1595. **
  1596. ** Side Effects: none
  1597. */
  1598. VOID
  1599. STREAMAPI
  1600. VideoIndicateMasterClock(
  1601. PHW_STREAM_REQUEST_BLOCK pSrb
  1602. )
  1603. {
  1604. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1605. pStrmEx->hMasterClock = pSrb->CommandData.MasterClockHandle;
  1606. }
  1607. /*
  1608. ** GetSystemTime ()
  1609. **
  1610. ** Returns the system time in 100 nS units
  1611. **
  1612. ** Arguments:
  1613. **
  1614. ** Returns:
  1615. **
  1616. ** Side Effects: none
  1617. */
  1618. ULONGLONG
  1619. STREAMAPI
  1620. VideoGetSystemTime(
  1621. )
  1622. {
  1623. ULONGLONG ticks;
  1624. ULONGLONG rate;
  1625. ticks = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
  1626. //
  1627. // convert from ticks to 100ns clock
  1628. //
  1629. ticks = (ticks & 0xFFFFFFFF00000000) / rate * 10000000 +
  1630. (ticks & 0x00000000FFFFFFFF) * 10000000 / rate;
  1631. return(ticks);
  1632. }