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.

1678 lines
47 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 - 1999 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 "capxfer.h"
  16. #include "ntstatus.h"
  17. //==========================================================================;
  18. // General queue management routines
  19. //==========================================================================;
  20. /*
  21. ** AddToListIfBusy ()
  22. **
  23. ** Grabs a spinlock, checks the busy flag, and if set adds an SRB to a queue
  24. **
  25. ** Arguments:
  26. **
  27. ** pSrb - Stream request block
  28. **
  29. ** SpinLock - The spinlock to use when checking the flag
  30. **
  31. ** BusyFlag - The flag to check
  32. **
  33. ** ListHead - The list onto which the Srb will be added if the busy flag is set
  34. **
  35. ** Returns:
  36. **
  37. ** The state of the busy flag on entry. This will be TRUE if we're already
  38. ** processing an SRB, and FALSE if no SRB is already in progress.
  39. **
  40. ** Side Effects: none
  41. */
  42. BOOL
  43. STREAMAPI
  44. AddToListIfBusy (
  45. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  46. IN KSPIN_LOCK *SpinLock,
  47. IN OUT BOOL *BusyFlag,
  48. IN LIST_ENTRY *ListHead
  49. )
  50. {
  51. KIRQL Irql;
  52. PSRB_EXTENSION pSrbExt = (PSRB_EXTENSION)pSrb->SRBExtension;
  53. KeAcquireSpinLock (SpinLock, &Irql);
  54. // If we're already processing another SRB, add this current request
  55. // to the queue and return TRUE
  56. if (*BusyFlag == TRUE) {
  57. // Save the SRB pointer away in the SRB Extension
  58. pSrbExt->pSrb = pSrb;
  59. InsertTailList(ListHead, &pSrbExt->ListEntry);
  60. KeReleaseSpinLock(SpinLock, Irql);
  61. return TRUE;
  62. }
  63. // Otherwise, set the busy flag, release the spinlock, and return FALSE
  64. *BusyFlag = TRUE;
  65. KeReleaseSpinLock(SpinLock, Irql);
  66. return FALSE;
  67. }
  68. /*
  69. ** RemoveFromListIfAvailable ()
  70. **
  71. ** Grabs a spinlock, checks for an available SRB, and removes it from the list
  72. **
  73. ** Arguments:
  74. **
  75. ** &pSrb - where to return the Stream request block if available
  76. **
  77. ** SpinLock - The spinlock to use
  78. **
  79. ** BusyFlag - The flag to clear if the list is empty
  80. **
  81. ** ListHead - The list from which an SRB will be removed if available
  82. **
  83. ** Returns:
  84. **
  85. ** TRUE if an SRB was removed from the list
  86. ** FALSE if the list is empty
  87. **
  88. ** Side Effects: none
  89. */
  90. BOOL
  91. STREAMAPI
  92. RemoveFromListIfAvailable (
  93. IN OUT PHW_STREAM_REQUEST_BLOCK *pSrb,
  94. IN KSPIN_LOCK *SpinLock,
  95. IN OUT BOOL *BusyFlag,
  96. IN LIST_ENTRY *ListHead
  97. )
  98. {
  99. KIRQL Irql;
  100. KeAcquireSpinLock (SpinLock, &Irql);
  101. //
  102. // If the queue is now empty, clear the busy flag, and return
  103. //
  104. if (IsListEmpty(ListHead)) {
  105. *BusyFlag = FALSE;
  106. KeReleaseSpinLock(SpinLock, Irql);
  107. return FALSE;
  108. }
  109. //
  110. // otherwise extract the SRB
  111. //
  112. else {
  113. PUCHAR ptr;
  114. PSRB_EXTENSION pSrbExt;
  115. ptr = (PUCHAR)RemoveHeadList(ListHead);
  116. *BusyFlag = TRUE;
  117. KeReleaseSpinLock(SpinLock, Irql);
  118. // Get the SRB out of the SRB extension and return it
  119. pSrbExt = (PSRB_EXTENSION) (((PUCHAR) ptr) -
  120. FIELDOFFSET(SRB_EXTENSION, ListEntry));
  121. *pSrb = pSrbExt->pSrb;
  122. }
  123. return TRUE;
  124. }
  125. //==========================================================================;
  126. // Routines for managing the SRB queue on a per stream basis
  127. //==========================================================================;
  128. /*
  129. ** VideoQueueAddSRB ()
  130. **
  131. ** Adds a stream data SRB to a stream queue. The queue is maintained in a
  132. ** first in, first out order.
  133. **
  134. ** Arguments:
  135. **
  136. ** pSrb - Stream request block for the Video stream
  137. **
  138. ** Returns: nothing
  139. **
  140. ** Side Effects: none
  141. */
  142. VOID
  143. STREAMAPI
  144. VideoQueueAddSRB (
  145. IN PHW_STREAM_REQUEST_BLOCK pSrb
  146. )
  147. {
  148. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  149. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  150. int StreamNumber = pSrb->StreamObject->StreamNumber;
  151. KIRQL oldIrql;
  152. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  153. // Save the SRB pointer in the IRP so we can use the IRPs
  154. // ListEntry to maintain a doubly linked list of pending
  155. // requests
  156. pSrb->Irp->Tail.Overlay.DriverContext[0] = pSrb;
  157. InsertTailList (
  158. &pHwDevExt->StreamSRBList[StreamNumber],
  159. &pSrb->Irp->Tail.Overlay.ListEntry);
  160. // Increment the count of outstanding SRBs in this queue
  161. pHwDevExt->StreamSRBListSize[StreamNumber]++;
  162. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  163. }
  164. /*
  165. ** VideoQueueRemoveSRB ()
  166. **
  167. ** Removes a stream data SRB from a stream queue
  168. **
  169. ** Arguments:
  170. **
  171. ** pHwDevExt - Device Extension
  172. **
  173. ** StreamNumber - Index of the stream
  174. **
  175. ** Returns: SRB or NULL
  176. **
  177. ** Side Effects: none
  178. */
  179. PHW_STREAM_REQUEST_BLOCK
  180. STREAMAPI
  181. VideoQueueRemoveSRB (
  182. PHW_DEVICE_EXTENSION pHwDevExt,
  183. int StreamNumber
  184. )
  185. {
  186. PUCHAR ptr;
  187. PIRP pIrp;
  188. PHW_STREAM_REQUEST_BLOCK pSrb = NULL;
  189. KIRQL oldIrql;
  190. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  191. //
  192. // Get the SRB out of the IRP out of the pending list
  193. //
  194. if (!IsListEmpty (&pHwDevExt->StreamSRBList[StreamNumber])) {
  195. ptr = (PUCHAR) RemoveHeadList(
  196. &pHwDevExt->StreamSRBList[StreamNumber]);
  197. pIrp = (PIRP) (((PUCHAR) ptr) -
  198. FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
  199. pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
  200. // Decrement the count of SRBs in this queue
  201. pHwDevExt->StreamSRBListSize[StreamNumber]--;
  202. }
  203. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  204. return pSrb;
  205. }
  206. /*
  207. ** VideoQueueCancelAllSRBs()
  208. **
  209. ** In case of a client crash, this empties the stream queue when the stream closes
  210. **
  211. ** Arguments:
  212. **
  213. ** pStrmEx - pointer to the stream extension
  214. **
  215. ** Returns:
  216. **
  217. ** Side Effects: none
  218. */
  219. VOID
  220. STREAMAPI
  221. VideoQueueCancelAllSRBs (
  222. PSTREAMEX pStrmEx
  223. )
  224. {
  225. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pStrmEx->pHwDevExt;
  226. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  227. PUCHAR ptr;
  228. PIRP pIrp;
  229. PHW_STREAM_REQUEST_BLOCK pSrb;
  230. KIRQL oldIrql;
  231. if (pStrmEx->KSState != KSSTATE_STOP) {
  232. DbgLogInfo(("TestCap: VideoQueueCancelAllSRBs without being in the stopped state\n"));
  233. // May need to force the device to a stopped state here
  234. // may need to disable interrupts here !
  235. }
  236. //
  237. // The stream class will cancel all outstanding IRPs for us
  238. // (but only if we've set TurnOffSynchronization = FALSE)
  239. //
  240. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  241. //
  242. // Get the SRB out of the IRP out of the pending list
  243. //
  244. while (!IsListEmpty (&pHwDevExt->StreamSRBList[StreamNumber])) {
  245. ptr = (PUCHAR) RemoveHeadList(
  246. &pHwDevExt->StreamSRBList[StreamNumber]);
  247. pIrp = (PIRP) (((PUCHAR) ptr) -
  248. FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
  249. pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
  250. // Decrement the count of SRBs in this queue
  251. pHwDevExt->StreamSRBListSize[StreamNumber]--;
  252. //
  253. // Make the length zero, and status cancelled
  254. //
  255. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  256. pSrb->Status = STATUS_CANCELLED;
  257. DbgLogInfo(("TestCap: VideoQueueCancelALLSRBs FOUND Srb=%p, Stream=%d\n", pSrb, StreamNumber));
  258. CompleteStreamSRB (pSrb);
  259. }
  260. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  261. DbgLogInfo(("TestCap: VideoQueueCancelAll Completed\n"));
  262. }
  263. /*
  264. ** VideoQueueCancelOneSRB()
  265. **
  266. ** Called when cancelling a particular SRB
  267. **
  268. ** Arguments:
  269. **
  270. ** pStrmEx - pointer to the stream extension
  271. **
  272. ** pSRBToCancel - pointer to the SRB
  273. **
  274. ** Returns:
  275. **
  276. ** TRUE if the SRB was found in this queue
  277. **
  278. ** Side Effects: none
  279. */
  280. BOOL
  281. STREAMAPI
  282. VideoQueueCancelOneSRB (
  283. PSTREAMEX pStrmEx,
  284. PHW_STREAM_REQUEST_BLOCK pSrbToCancel
  285. )
  286. {
  287. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pStrmEx->pHwDevExt;
  288. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  289. KIRQL oldIrql;
  290. BOOL Found = FALSE;
  291. PIRP pIrp;
  292. PHW_STREAM_REQUEST_BLOCK pSrb;
  293. PLIST_ENTRY Entry;
  294. KeAcquireSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], &oldIrql);
  295. Entry = pHwDevExt->StreamSRBList[StreamNumber].Flink;
  296. //
  297. // Loop through the linked list from the beginning to end,
  298. // trying to find the SRB to cancel
  299. //
  300. while (Entry != &pHwDevExt->StreamSRBList[StreamNumber]) {
  301. pIrp = (PIRP) (((PUCHAR) Entry) -
  302. FIELDOFFSET(IRP, Tail.Overlay.ListEntry));
  303. pSrb = (PHW_STREAM_REQUEST_BLOCK) pIrp->Tail.Overlay.DriverContext[0];
  304. if (pSrb == pSrbToCancel) {
  305. RemoveEntryList(Entry);
  306. Found = TRUE;
  307. break;
  308. }
  309. Entry = Entry->Flink;
  310. }
  311. KeReleaseSpinLock (&pHwDevExt->StreamSRBSpinLock[StreamNumber], oldIrql);
  312. if (Found) {
  313. pHwDevExt->StreamSRBListSize[StreamNumber]--;
  314. //
  315. // Make the length zero, and status cancelled
  316. //
  317. pSrbToCancel->CommandData.DataBufferArray->DataUsed = 0;
  318. pSrbToCancel->Status = STATUS_CANCELLED;
  319. CompleteStreamSRB (pSrbToCancel);
  320. DbgLogInfo(("TestCap: VideoQueueCancelOneSRB FOUND Srb=%p, Stream=%d\n", pSrb, StreamNumber));
  321. }
  322. DbgLogInfo(("TestCap: VideoQueueCancelOneSRB Completed Stream=%d\n", StreamNumber));
  323. return Found;
  324. }
  325. /*
  326. ** VideoSetFormat()
  327. **
  328. ** Sets the format for a video stream. This happens both when the
  329. ** stream is first opened, and also when dynamically switching formats
  330. ** on the preview pin.
  331. **
  332. ** It is assumed that the format has been verified for correctness before
  333. ** this call is made.
  334. **
  335. ** Arguments:
  336. **
  337. ** pSrb - Stream request block for the Video stream
  338. **
  339. ** Returns:
  340. **
  341. ** TRUE if the format could be set, else FALSE
  342. **
  343. ** Side Effects: none
  344. */
  345. BOOL
  346. STREAMAPI
  347. VideoSetFormat(
  348. IN PHW_STREAM_REQUEST_BLOCK pSrb
  349. )
  350. {
  351. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  352. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  353. int StreamNumber = pSrb->StreamObject->StreamNumber;
  354. UINT nSize;
  355. PKSDATAFORMAT pKSDataFormat = pSrb->CommandData.OpenFormat;
  356. // -------------------------------------------------------------------
  357. // Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
  358. // -------------------------------------------------------------------
  359. if (IsEqualGUID (&pKSDataFormat->Specifier,
  360. &KSDATAFORMAT_SPECIFIER_VIDEOINFO)) {
  361. PKS_DATAFORMAT_VIDEOINFOHEADER pVideoInfoHeader =
  362. (PKS_DATAFORMAT_VIDEOINFOHEADER) pSrb->CommandData.OpenFormat;
  363. PKS_VIDEOINFOHEADER pVideoInfoHdrRequested = &pVideoInfoHeader->VideoInfoHeader;
  364. PKS_VIDEOINFOHEADER pNewVideoInfoHeader, pOldVideoInfoHeader;
  365. KIRQL oldIrql;
  366. nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested);
  367. DbgLogInfo(("TestCap: New Format\n"));
  368. DbgLogInfo(("TestCap: pVideoInfoHdrRequested=%p\n", pVideoInfoHdrRequested));
  369. DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n", nSize));
  370. DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n",
  371. pVideoInfoHdrRequested->bmiHeader.biWidth,
  372. pVideoInfoHdrRequested->bmiHeader.biHeight,
  373. pVideoInfoHdrRequested->bmiHeader.biBitCount));
  374. DbgLogInfo(("TestCap: biSizeImage=%d\n",
  375. pVideoInfoHdrRequested->bmiHeader.biSizeImage));
  376. // Since the VIDEOINFOHEADER is of potentially variable size
  377. // allocate memory for it
  378. pNewVideoInfoHeader = ExAllocatePool(NonPagedPool, nSize);
  379. if (pNewVideoInfoHeader == NULL) {
  380. DbgLogError(("TestCap: ExAllocatePool failed\n"));
  381. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  382. return FALSE;
  383. }
  384. // Copy the VIDEOINFOHEADER requested to our storage
  385. RtlCopyMemory(
  386. pNewVideoInfoHeader,
  387. pVideoInfoHdrRequested,
  388. nSize);
  389. //
  390. // We have the new format, act on it. First take the lock, we might be
  391. // setting format dynamically when ImageSync is using the format on the other proc.
  392. //
  393. KeAcquireSpinLock( &pStrmEx->lockVideoInfoHeader, &oldIrql );
  394. //
  395. // update it and release the lock. Could have used interlockedexchangepointer but
  396. // it's not available downlevel
  397. //
  398. pOldVideoInfoHeader = pStrmEx->pVideoInfoHeader;
  399. pStrmEx->pVideoInfoHeader = pNewVideoInfoHeader;
  400. //
  401. // remember this so getdropped frame needs no locks usig biSizeImage
  402. //
  403. pStrmEx->biSizeImage = pNewVideoInfoHeader->bmiHeader.biSizeImage;
  404. // A renderer may be switching formats, and in this case, the AvgTimePerFrame
  405. // will be zero. Don't overwrite a previously set framerate.
  406. if (pStrmEx->pVideoInfoHeader->AvgTimePerFrame) {
  407. pStrmEx->AvgTimePerFrame = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  408. }
  409. KeReleaseSpinLock( &pStrmEx->lockVideoInfoHeader, oldIrql );
  410. if ( pOldVideoInfoHeader ) {
  411. //
  412. // if there is a previous one, free it
  413. //
  414. ExFreePool( pOldVideoInfoHeader );
  415. }
  416. }
  417. // -------------------------------------------------------------------
  418. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  419. // -------------------------------------------------------------------
  420. else if (IsEqualGUID (&pKSDataFormat->Specifier,
  421. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  422. //
  423. // AnalogVideo DataRange == DataFormat!
  424. //
  425. //
  426. // For now, don't even cache this
  427. //
  428. PKS_DATARANGE_ANALOGVIDEO pDataFormatAnalogVideo =
  429. (PKS_DATARANGE_ANALOGVIDEO) pSrb->CommandData.OpenFormat;
  430. }
  431. // -------------------------------------------------------------------
  432. // Specifier FORMAT_VBI for KS_VIDEO_VBI
  433. // -------------------------------------------------------------------
  434. else if (IsEqualGUID (&pKSDataFormat->Specifier,
  435. &KSDATAFORMAT_SPECIFIER_VBI))
  436. {
  437. // On a VBI stream, we save a pointer to StreamFormatVBI, which
  438. // has the timing info we want to get at later.
  439. pStrmEx->pVBIStreamFormat = &StreamFormatVBI;
  440. }
  441. // -------------------------------------------------------------------
  442. // Type FORMAT_NABTS for NABTS pin
  443. // -------------------------------------------------------------------
  444. else if (IsEqualGUID (&pKSDataFormat->SubFormat,
  445. &KSDATAFORMAT_SUBTYPE_NABTS))
  446. {
  447. // On a VBI stream, we save a pointer to StreamFormatVBI, which
  448. // has the timing info we want to get at later. (Even though
  449. // this is really a StreamFormatNABTS pin)
  450. pStrmEx->pVBIStreamFormat = &StreamFormatVBI;
  451. }
  452. // -------------------------------------------------------------------
  453. // for CC pin
  454. // -------------------------------------------------------------------
  455. else if (IsEqualGUID (&pKSDataFormat->SubFormat,
  456. &KSDATAFORMAT_SUBTYPE_CC))
  457. {
  458. // On a VBI stream, we save a pointer to StreamFormatVBI, which
  459. // has the timing info we want to get at later. (Even though
  460. // this is really a StreamFormatCC pin)
  461. pStrmEx->pVBIStreamFormat = &StreamFormatVBI;
  462. }
  463. else {
  464. // Unknown format
  465. pSrb->Status = STATUS_INVALID_PARAMETER;
  466. return FALSE;
  467. }
  468. return TRUE;
  469. }
  470. /*
  471. ** VideoReceiveDataPacket()
  472. **
  473. ** Receives Video data packet commands on the output streams
  474. **
  475. ** Arguments:
  476. **
  477. ** pSrb - Stream request block for the Video stream
  478. **
  479. ** Returns: nothing
  480. **
  481. ** Side Effects: none
  482. */
  483. VOID
  484. STREAMAPI
  485. VideoReceiveDataPacket(
  486. IN PHW_STREAM_REQUEST_BLOCK pSrb
  487. )
  488. {
  489. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  490. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  491. int StreamNumber = pSrb->StreamObject->StreamNumber;
  492. //
  493. // make sure we have a device extension and are at passive level
  494. //
  495. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  496. DEBUG_ASSERT(pHwDevExt!=NULL);
  497. DbgLogTrace(("TestCap: Receiving Stream Data SRB %p, %x\n", pSrb, pSrb->Command));
  498. //
  499. // Default to success
  500. //
  501. pSrb->Status = STATUS_SUCCESS;
  502. //
  503. // determine the type of packet.
  504. //
  505. switch (pSrb->Command){
  506. case SRB_READ_DATA:
  507. // Rule:
  508. // Only accept read requests when in either the Pause or Run
  509. // States. If Stopped, immediately return the SRB.
  510. if (pStrmEx->KSState == KSSTATE_STOP) {
  511. CompleteStreamSRB (pSrb);
  512. break;
  513. }
  514. //
  515. // Put this read request on the pending queue
  516. //
  517. VideoQueueAddSRB (pSrb);
  518. // Since another thread COULD HAVE MODIFIED THE STREAM STATE
  519. // in the midst of adding it to the queue, check the stream
  520. // state again, and cancel the SRB if necessary. Note that
  521. // this race condition was NOT handled in the original DDK
  522. // release of testcap!
  523. if (pStrmEx->KSState == KSSTATE_STOP) {
  524. VideoQueueCancelOneSRB (
  525. pStrmEx,
  526. pSrb);
  527. }
  528. break;
  529. default:
  530. //
  531. // invalid / unsupported command. Fail it as such
  532. //
  533. TRAP;
  534. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  535. CompleteStreamSRB (pSrb);
  536. } // switch (pSrb->Command)
  537. }
  538. /*
  539. ** VideoReceiveCtrlPacket()
  540. **
  541. ** Receives packet commands that control the Video output streams
  542. **
  543. ** Arguments:
  544. **
  545. ** pSrb - The stream request block for the Video stream
  546. **
  547. ** Returns: nothing
  548. **
  549. ** Side Effects: none
  550. */
  551. VOID
  552. STREAMAPI
  553. VideoReceiveCtrlPacket(
  554. IN PHW_STREAM_REQUEST_BLOCK pSrb
  555. )
  556. {
  557. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  558. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  559. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  560. BOOL Busy;
  561. //
  562. // make sure we have a device extension and are at passive level
  563. //
  564. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  565. DEBUG_ASSERT(pHwDevExt!=NULL);
  566. DbgLogTrace(("TestCap: Receiving Stream Control SRB %p, %x\n", pSrb, pSrb->Command));
  567. //
  568. // If we're already processing an SRB, add it to the queue
  569. //
  570. Busy = AddToListIfBusy (
  571. pSrb,
  572. &pHwDevExt->AdapterSpinLock,
  573. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  574. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  575. if (Busy) {
  576. return;
  577. }
  578. while (TRUE) {
  579. //
  580. // Default to success
  581. //
  582. pSrb->Status = STATUS_SUCCESS;
  583. //
  584. // determine the type of packet.
  585. //
  586. switch (pSrb->Command)
  587. {
  588. case SRB_PROPOSE_DATA_FORMAT:
  589. DbgLogInfo(("TestCap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %p, StreamNumber= %d\n", pSrb, StreamNumber));
  590. if (!(AdapterVerifyFormat (
  591. pSrb->CommandData.OpenFormat,
  592. pSrb->StreamObject->StreamNumber))) {
  593. pSrb->Status = STATUS_NO_MATCH;
  594. DbgLogInfo(("TestCap: SRB_PROPOSE_DATA_FORMAT FAILED\n"));
  595. }
  596. // KS support for dynamic format changes is BROKEN right now,
  597. // so we prevent these from happening by saying they ALL fail.
  598. // If this is ever fixed, the next line must be removed.
  599. pSrb->Status = STATUS_NO_MATCH; // prevent dynamic format changes
  600. break;
  601. case SRB_SET_DATA_FORMAT:
  602. DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT\n"));
  603. if (!(AdapterVerifyFormat (
  604. pSrb->CommandData.OpenFormat,
  605. pSrb->StreamObject->StreamNumber))) {
  606. pSrb->Status = STATUS_NO_MATCH;
  607. DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT FAILED\n"));
  608. } else {
  609. VideoSetFormat (pSrb);
  610. DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT SUCCEEDED\n"));
  611. }
  612. break;
  613. case SRB_GET_DATA_FORMAT:
  614. DbgLogInfo(("TestCap: SRB_GET_DATA_FORMAT\n"));
  615. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  616. break;
  617. case SRB_SET_STREAM_STATE:
  618. VideoSetState(pSrb);
  619. break;
  620. case SRB_GET_STREAM_STATE:
  621. VideoGetState(pSrb);
  622. break;
  623. case SRB_GET_STREAM_PROPERTY:
  624. VideoGetProperty(pSrb);
  625. break;
  626. case SRB_SET_STREAM_PROPERTY:
  627. VideoSetProperty(pSrb);
  628. break;
  629. case SRB_INDICATE_MASTER_CLOCK:
  630. //
  631. // Assigns a clock to a stream
  632. //
  633. VideoIndicateMasterClock (pSrb);
  634. break;
  635. default:
  636. //
  637. // invalid / unsupported command. Fail it as such
  638. //
  639. TRAP;
  640. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  641. }
  642. CompleteStreamSRB (pSrb);
  643. //
  644. // See if there's anything else on the queue
  645. //
  646. Busy = RemoveFromListIfAvailable (
  647. &pSrb,
  648. &pHwDevExt->AdapterSpinLock,
  649. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  650. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  651. if (!Busy) {
  652. break;
  653. }
  654. }
  655. }
  656. /*
  657. ** AnalogVideoReceiveDataPacket()
  658. **
  659. ** Receives AnalogVideo data packet commands on the input stream
  660. **
  661. ** Arguments:
  662. **
  663. ** pSrb - Stream request block for the Analog Video stream.
  664. ** This stream receives tuner control packets.
  665. **
  666. ** Returns: nothing
  667. **
  668. ** Side Effects: none
  669. */
  670. VOID
  671. STREAMAPI
  672. AnalogVideoReceiveDataPacket(
  673. IN PHW_STREAM_REQUEST_BLOCK pSrb
  674. )
  675. {
  676. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  677. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  678. PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
  679. //
  680. // make sure we have a device extension and are at passive level
  681. //
  682. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  683. DEBUG_ASSERT(pHwDevExt!=NULL);
  684. DbgLogInfo(("TestCap: Receiving Tuner packet SRB %p, %x\n", pSrb, pSrb->Command));
  685. //
  686. // Default to success
  687. //
  688. pSrb->Status = STATUS_SUCCESS;
  689. //
  690. // determine the type of packet.
  691. //
  692. switch (pSrb->Command){
  693. case SRB_WRITE_DATA:
  694. //
  695. // This data packet contains the channel change information
  696. // passed on the AnalogVideoIn stream. Devices which support
  697. // VBI data streams need to pass this info on their output pins.
  698. //
  699. if (pDataPacket->FrameExtent == sizeof (KS_TVTUNER_CHANGE_INFO)) {
  700. RtlCopyMemory(
  701. &pHwDevExt->TVTunerChangeInfo,
  702. pDataPacket->Data,
  703. sizeof (KS_TVTUNER_CHANGE_INFO));
  704. }
  705. CompleteStreamSRB (pSrb);
  706. break;
  707. default:
  708. //
  709. // invalid / unsupported command. Fail it as such
  710. //
  711. TRAP;
  712. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  713. CompleteStreamSRB (pSrb);
  714. } // switch (pSrb->Command)
  715. }
  716. /*
  717. ** AnalogVideoReceiveCtrlPacket()
  718. **
  719. ** Receives packet commands that control the Analog Video stream
  720. **
  721. ** Arguments:
  722. **
  723. ** pSrb - The stream request block for the Video stream
  724. **
  725. ** Returns: nothing
  726. **
  727. ** Side Effects: none
  728. */
  729. VOID
  730. STREAMAPI
  731. AnalogVideoReceiveCtrlPacket(
  732. IN PHW_STREAM_REQUEST_BLOCK pSrb
  733. )
  734. {
  735. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  736. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  737. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  738. BOOL Busy;
  739. //
  740. // make sure we have a device extension and we are at passive level
  741. //
  742. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  743. DEBUG_ASSERT(pHwDevExt!=NULL);
  744. DbgLogTrace(("TestCap: Receiving Analog Stream Control SRB %p, %x\n", pSrb, pSrb->Command));
  745. //
  746. // If we're already processing an SRB, add it to the queue
  747. //
  748. Busy = AddToListIfBusy (
  749. pSrb,
  750. &pHwDevExt->AdapterSpinLock,
  751. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  752. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  753. if (Busy) {
  754. return;
  755. }
  756. do {
  757. //
  758. // Default to success
  759. //
  760. pSrb->Status = STATUS_SUCCESS;
  761. //
  762. // determine the type of packet.
  763. //
  764. switch (pSrb->Command)
  765. {
  766. case SRB_PROPOSE_DATA_FORMAT:
  767. DbgLogInfo(("TestCap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %p, StreamNumber= %d\n", pSrb, StreamNumber));
  768. if (!(AdapterVerifyFormat (
  769. pSrb->CommandData.OpenFormat,
  770. pSrb->StreamObject->StreamNumber))) {
  771. pSrb->Status = STATUS_NO_MATCH;
  772. }
  773. break;
  774. case SRB_SET_STREAM_STATE:
  775. //
  776. // Don't use VideoSetState, since we don't want to start another
  777. // timer running
  778. //
  779. pStrmEx->KSState = pSrb->CommandData.StreamState;
  780. DbgLogInfo(("TestCap: STATE=%d, Stream=%d\n", pStrmEx->KSState, StreamNumber));
  781. break;
  782. case SRB_GET_STREAM_STATE:
  783. VideoGetState(pSrb);
  784. break;
  785. case SRB_GET_STREAM_PROPERTY:
  786. VideoGetProperty(pSrb);
  787. break;
  788. case SRB_INDICATE_MASTER_CLOCK:
  789. //
  790. // Assigns a clock to a stream
  791. //
  792. VideoIndicateMasterClock (pSrb);
  793. break;
  794. default:
  795. //
  796. // invalid / unsupported command. Fail it as such
  797. //
  798. TRAP;
  799. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  800. }
  801. CompleteStreamSRB (pSrb);
  802. //
  803. // See if there's anything else on the queue
  804. //
  805. Busy = RemoveFromListIfAvailable (
  806. &pSrb,
  807. &pHwDevExt->AdapterSpinLock,
  808. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  809. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  810. } while ( Busy );
  811. }
  812. /*
  813. ** CompleteStreamSRB ()
  814. **
  815. ** This routine is called when a packet is being completed.
  816. **
  817. ** Arguments:
  818. **
  819. ** pSrb - pointer to the request packet to be completed
  820. **
  821. ** Returns:
  822. **
  823. ** Side Effects: none
  824. */
  825. VOID
  826. STREAMAPI
  827. CompleteStreamSRB (
  828. IN PHW_STREAM_REQUEST_BLOCK pSrb
  829. )
  830. {
  831. DbgLogTrace(("TestCap: Completing Stream SRB %p\n", pSrb));
  832. StreamClassStreamNotification(
  833. StreamRequestComplete,
  834. pSrb->StreamObject,
  835. pSrb);
  836. }
  837. /*
  838. ** VideoGetProperty()
  839. **
  840. ** Routine to process video property requests
  841. **
  842. ** Arguments:
  843. **
  844. ** pSrb - pointer to the stream request block for properties
  845. **
  846. ** Returns:
  847. **
  848. ** Side Effects: none
  849. */
  850. VOID
  851. STREAMAPI
  852. VideoGetProperty(
  853. PHW_STREAM_REQUEST_BLOCK pSrb
  854. )
  855. {
  856. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  857. if (IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
  858. VideoStreamGetConnectionProperty (pSrb);
  859. }
  860. else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
  861. VideoStreamGetDroppedFramesProperty (pSrb);
  862. }
  863. else {
  864. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  865. }
  866. }
  867. /*
  868. ** VideoSetProperty()
  869. **
  870. ** Routine to process video property requests
  871. **
  872. ** Arguments:
  873. **
  874. ** pSrb - pointer to the stream request block for properties
  875. **
  876. ** Returns:
  877. **
  878. ** Side Effects: none
  879. */
  880. VOID
  881. STREAMAPI
  882. VideoSetProperty(
  883. PHW_STREAM_REQUEST_BLOCK pSrb
  884. )
  885. {
  886. // PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  887. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  888. }
  889. /*
  890. ** VideoTimerRoutine()
  891. **
  892. ** A timer has been created based on the requested capture interval.
  893. ** This is the callback routine for this timer event.
  894. **
  895. ** Note: Devices capable of using interrupts should always
  896. ** trigger capture on a VSYNC interrupt, and not use a timer.
  897. **
  898. ** Arguments:
  899. **
  900. ** Context - pointer to the stream extension
  901. **
  902. ** Returns: nothing
  903. **
  904. ** Side Effects: none
  905. */
  906. VOID
  907. STREAMAPI
  908. VideoTimerRoutine(
  909. PVOID Context
  910. )
  911. {
  912. PSTREAMEX pStrmEx = ((PSTREAMEX)Context);
  913. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  914. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  915. // If we're stopped and the timer is still running, just return.
  916. // This will stop the timer.
  917. if (pStrmEx->KSState == KSSTATE_STOP) {
  918. return;
  919. }
  920. // Capture a frame if it's time and we have a buffer
  921. VideoCaptureRoutine(pStrmEx);
  922. // Schedule the next timer event
  923. // Make it run at 2x the requested capture rate (which is in 100nS units)
  924. StreamClassScheduleTimer (
  925. pStrmEx->pStreamObject, // StreamObject
  926. pHwDevExt, // HwDeviceExtension
  927. (ULONG) (pStrmEx->AvgTimePerFrame / 20), // Microseconds
  928. VideoTimerRoutine, // TimerRoutine
  929. pStrmEx); // Context
  930. }
  931. /*
  932. ** VideoCaptureRoutine()
  933. **
  934. ** Routine to capture video frames based on a timer.
  935. **
  936. ** Note: Devices capable of using interrupts should always
  937. ** trigger capture on a VSYNC interrupt, and not use a timer.
  938. **
  939. ** Arguments:
  940. **
  941. ** Returns: nothing
  942. **
  943. ** Side Effects: none
  944. */
  945. VOID
  946. STREAMAPI
  947. VideoCaptureRoutine(
  948. IN PSTREAMEX pStrmEx
  949. )
  950. {
  951. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  952. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  953. PKSSTREAM_HEADER pDataPacket;
  954. PKS_FRAME_INFO pFrameInfo;
  955. // If we're stopped and the timer is still running, just return.
  956. // This will stop the timer.
  957. if (pStrmEx->KSState == KSSTATE_STOP) {
  958. return;
  959. }
  960. // Find out what time it is, if we're using a clock
  961. if (pStrmEx->hMasterClock ) {
  962. HW_TIME_CONTEXT TimeContext;
  963. TimeContext.HwDeviceExtension = pHwDevExt;
  964. TimeContext.HwStreamObject = pStrmEx->pStreamObject;
  965. TimeContext.Function = TIME_GET_STREAM_TIME;
  966. StreamClassQueryMasterClockSync (
  967. pStrmEx->hMasterClock,
  968. &TimeContext);
  969. pStrmEx->QST_StreamTime = TimeContext.Time;
  970. pStrmEx->QST_Now = TimeContext.SystemTime;
  971. if (pStrmEx->QST_NextFrame == 0) {
  972. pStrmEx->QST_NextFrame = pStrmEx->QST_StreamTime + pStrmEx->AvgTimePerFrame;
  973. }
  974. #ifdef CREATE_A_FLURRY_OF_TIMING_SPEW
  975. DbgLogTrace(("TestCap: Time=%6d mS at SystemTime=%I64d\n",
  976. (LONG) ((LONGLONG) TimeContext.Time / 10000),
  977. TimeContext.SystemTime));
  978. #endif
  979. }
  980. // Only capture in the RUN state
  981. if (pStrmEx->KSState == KSSTATE_RUN) {
  982. //
  983. // Determine if it is time to capture a frame based on
  984. // how much time has elapsed since capture started.
  985. // If there isn't a clock available, then capture immediately.
  986. //
  987. if ((!pStrmEx->hMasterClock) ||
  988. (pStrmEx->QST_StreamTime >= pStrmEx->QST_NextFrame)) {
  989. PHW_STREAM_REQUEST_BLOCK pSrb;
  990. // Increment the picture count (usually this is VSYNC count)
  991. pStrmEx->FrameInfo.PictureNumber++;
  992. //
  993. // Get the next queue SRB (if any)
  994. //
  995. pSrb = VideoQueueRemoveSRB (
  996. pHwDevExt,
  997. StreamNumber);
  998. if (pSrb) {
  999. pDataPacket = pSrb->CommandData.DataBufferArray;
  1000. pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
  1001. //
  1002. // Call the routine which synthesizes images
  1003. //
  1004. ImageSynth (pSrb,
  1005. pHwDevExt->VideoInputConnected,
  1006. pStrmEx->VideoControlMode & KS_VideoControlFlag_FlipHorizontal);
  1007. // Set additional info fields about the data captured such as:
  1008. // Frames Captured
  1009. // Frames Dropped
  1010. // Field Polarity
  1011. pStrmEx->FrameInfo.ExtendedHeaderSize = pFrameInfo->ExtendedHeaderSize;
  1012. *pFrameInfo = pStrmEx->FrameInfo;
  1013. // Init the flags to zero
  1014. pDataPacket->OptionsFlags = 0;
  1015. // Set the discontinuity flag if frames have been previously
  1016. // dropped, and then reset our internal flag
  1017. if (pStrmEx->fDiscontinuity) {
  1018. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  1019. pStrmEx->fDiscontinuity = FALSE;
  1020. }
  1021. //
  1022. // Return the timestamp for the frame
  1023. //
  1024. pDataPacket->PresentationTime.Numerator = 1;
  1025. pDataPacket->PresentationTime.Denominator = 1;
  1026. pDataPacket->Duration = pStrmEx->AvgTimePerFrame;
  1027. //
  1028. // if we have a master clock AND this is the capture stream
  1029. //
  1030. if (pStrmEx->hMasterClock && (StreamNumber == 0)) {
  1031. pDataPacket->PresentationTime.Time = pStrmEx->QST_StreamTime;
  1032. pDataPacket->OptionsFlags |=
  1033. KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  1034. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  1035. }
  1036. else {
  1037. //
  1038. // no clock or the preview stream, so just mark the time as unknown
  1039. //
  1040. pDataPacket->PresentationTime.Time = 0;
  1041. // clear the timestamp valid flags
  1042. pDataPacket->OptionsFlags &=
  1043. ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  1044. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  1045. }
  1046. // Every frame we generate is a key frame (aka SplicePoint)
  1047. // Delta frames (B or P) should not set this flag
  1048. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
  1049. // Output a frame count every 100th frame in Debug mode
  1050. if (pStrmEx->FrameInfo.PictureNumber % 100 == 0) {
  1051. DbgLogInfo(("TestCap: Picture %u, Stream=%d\n",
  1052. (unsigned int)pStrmEx->FrameInfo.PictureNumber,
  1053. StreamNumber));
  1054. }
  1055. CompleteStreamSRB (pSrb);
  1056. } // if we have an SRB
  1057. else {
  1058. //
  1059. // No buffer was available when we should have captured one
  1060. // Increment the counter which keeps track of
  1061. // dropped frames
  1062. pStrmEx->FrameInfo.DropCount++;
  1063. // Set the (local) discontinuity flag
  1064. // This will cause the next packet processed to have the
  1065. // KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY flag set.
  1066. pStrmEx->fDiscontinuity = TRUE;
  1067. }
  1068. // Figure out when to capture the next frame
  1069. pStrmEx->QST_NextFrame += pStrmEx->AvgTimePerFrame;
  1070. } // endif time to capture a frame
  1071. } // endif we're running
  1072. }
  1073. /*
  1074. ** VideoSetState()
  1075. **
  1076. ** Sets the current state for a given stream
  1077. **
  1078. ** Arguments:
  1079. **
  1080. ** pSrb - pointer to the stream request block for properties
  1081. **
  1082. ** Returns:
  1083. **
  1084. ** Side Effects: none
  1085. */
  1086. VOID
  1087. STREAMAPI
  1088. VideoSetState(
  1089. PHW_STREAM_REQUEST_BLOCK pSrb
  1090. )
  1091. {
  1092. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  1093. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1094. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  1095. KSSTATE PreviousState;
  1096. //
  1097. // For each stream, the following states are used:
  1098. //
  1099. // Stop: Absolute minimum resources are used. No outstanding IRPs.
  1100. // Acquire: KS only state that has no DirectShow correpondence
  1101. // Acquire needed resources.
  1102. // Pause: Getting ready to run. Allocate needed resources so that
  1103. // the eventual transition to Run is as fast as possible.
  1104. // Read SRBs will be queued at either the Stream class
  1105. // or in your driver (depending on when you send "ReadyForNext")
  1106. // and whether you're using the Stream class for synchronization
  1107. // Run: Streaming.
  1108. //
  1109. // Moving to Stop to Run always transitions through Pause.
  1110. //
  1111. // But since a client app could crash unexpectedly, drivers should handle
  1112. // the situation of having outstanding IRPs cancelled and open streams
  1113. // being closed WHILE THEY ARE STREAMING!
  1114. //
  1115. // Note that it is quite possible to transition repeatedly between states:
  1116. // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop
  1117. //
  1118. //
  1119. // Remember the state we're transitioning away from
  1120. //
  1121. PreviousState = pStrmEx->KSState;
  1122. //
  1123. // Set the new state
  1124. //
  1125. pStrmEx->KSState = pSrb->CommandData.StreamState;
  1126. switch (pSrb->CommandData.StreamState)
  1127. {
  1128. case KSSTATE_STOP:
  1129. //
  1130. // The stream class will cancel all outstanding IRPs for us
  1131. // (but only if it is maintaining the queue ie. using Stream Class synchronization)
  1132. // Since Testcap is not using Stream Class synchronization, we must clear the queue here
  1133. VideoQueueCancelAllSRBs (pStrmEx);
  1134. DbgLogInfo(("TestCap: STATE Stopped, Stream=%d\n", StreamNumber));
  1135. break;
  1136. case KSSTATE_ACQUIRE:
  1137. //
  1138. // This is a KS only state, that has no correspondence in DirectShow
  1139. //
  1140. DbgLogInfo(("TestCap: STATE Acquire, Stream=%d\n", StreamNumber));
  1141. break;
  1142. case KSSTATE_PAUSE:
  1143. //
  1144. // On a transition to pause from acquire or stop, start our timer running.
  1145. //
  1146. if (PreviousState == KSSTATE_ACQUIRE || PreviousState == KSSTATE_STOP) {
  1147. // Zero the frame counters
  1148. pStrmEx->FrameInfo.PictureNumber = 0;
  1149. pStrmEx->FrameInfo.DropCount = 0;
  1150. pStrmEx->FrameInfo.dwFrameFlags = 0;
  1151. // Setup the next timer callback(s)
  1152. VideoTimerRoutine(pStrmEx);
  1153. }
  1154. DbgLogInfo(("TestCap: STATE Pause, Stream=%d\n", StreamNumber));
  1155. break;
  1156. case KSSTATE_RUN:
  1157. //
  1158. // Begin Streaming.
  1159. //
  1160. // Reset the discontinuity flag
  1161. pStrmEx->fDiscontinuity = FALSE;
  1162. // Setting the NextFrame time to zero will cause the value to be
  1163. // reset from the stream time
  1164. pStrmEx->QST_NextFrame = 0;
  1165. DbgLogInfo(("TestCap: STATE Run, Stream=%d\n", StreamNumber));
  1166. break;
  1167. } // end switch (pSrb->CommandData.StreamState)
  1168. }
  1169. /*
  1170. ** VideoGetState()
  1171. **
  1172. ** Gets the current state of the requested stream
  1173. **
  1174. ** Arguments:
  1175. **
  1176. ** pSrb - pointer to the stream request block for properties
  1177. **
  1178. ** Returns:
  1179. **
  1180. ** Side Effects: none
  1181. */
  1182. VOID
  1183. STREAMAPI
  1184. VideoGetState(
  1185. PHW_STREAM_REQUEST_BLOCK pSrb
  1186. )
  1187. {
  1188. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1189. pSrb->CommandData.StreamState = pStrmEx->KSState;
  1190. pSrb->ActualBytesTransferred = sizeof (KSSTATE);
  1191. // A very odd rule:
  1192. // When transitioning from stop to pause, DShow tries to preroll
  1193. // the graph. Capture sources can't preroll, and indicate this
  1194. // by returning VFW_S_CANT_CUE in user mode. To indicate this
  1195. // condition from drivers, they must return STATUS_NO_DATA_DETECTED
  1196. if (pStrmEx->KSState == KSSTATE_PAUSE) {
  1197. pSrb->Status = STATUS_NO_DATA_DETECTED;
  1198. }
  1199. }
  1200. /*
  1201. ** VideoStreamGetConnectionProperty()
  1202. **
  1203. ** Gets the properties for a stream
  1204. **
  1205. ** Arguments:
  1206. **
  1207. ** pSrb - pointer to the stream request block for properties
  1208. **
  1209. ** Returns:
  1210. **
  1211. ** Side Effects: none
  1212. */
  1213. VOID
  1214. STREAMAPI
  1215. VideoStreamGetConnectionProperty(
  1216. PHW_STREAM_REQUEST_BLOCK pSrb
  1217. )
  1218. {
  1219. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1220. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1221. ULONG Id = pSPD->Property->Id; // index of the property
  1222. int streamNumber = (int)pSrb->StreamObject->StreamNumber;
  1223. switch (Id) {
  1224. // This property describes the allocator requirements for the stream
  1225. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  1226. {
  1227. PKSALLOCATOR_FRAMING Framing =
  1228. (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  1229. Framing->RequirementsFlags =
  1230. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  1231. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  1232. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
  1233. Framing->PoolType = PagedPool;
  1234. Framing->FileAlignment = 0; // FILE_LONG_ALIGNMENT???;
  1235. Framing->Reserved = 0;
  1236. pSrb->ActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  1237. switch (streamNumber) {
  1238. case STREAM_Capture:
  1239. case STREAM_Preview:
  1240. Framing->Frames = 2;
  1241. Framing->FrameSize =
  1242. pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1243. break;
  1244. case STREAM_VBI:
  1245. Framing->Frames = 8;
  1246. Framing->FrameSize = StreamFormatVBI.DataRange.SampleSize;
  1247. break;
  1248. case STREAM_CC:
  1249. Framing->Frames = 100;
  1250. Framing->FrameSize = StreamFormatCC.SampleSize;
  1251. break;
  1252. case STREAM_NABTS:
  1253. Framing->Frames = 20;
  1254. Framing->FrameSize = StreamFormatNABTS.SampleSize;
  1255. break;
  1256. case STREAM_AnalogVideoInput:
  1257. default:
  1258. pSrb->Status = STATUS_INVALID_PARAMETER;
  1259. break;
  1260. }
  1261. break;
  1262. }
  1263. default:
  1264. TRAP;
  1265. break;
  1266. }
  1267. }
  1268. /*
  1269. ** VideoStreamGetDroppedFramesProperty()
  1270. **
  1271. ** Gets dynamic information about the progress of the capture process.
  1272. **
  1273. ** Arguments:
  1274. **
  1275. ** pSrb - pointer to the stream request block for properties
  1276. **
  1277. ** Returns:
  1278. **
  1279. ** Side Effects: none
  1280. */
  1281. VOID
  1282. STREAMAPI
  1283. VideoStreamGetDroppedFramesProperty(
  1284. PHW_STREAM_REQUEST_BLOCK pSrb
  1285. )
  1286. {
  1287. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1288. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1289. ULONG Id = pSPD->Property->Id; // index of the property
  1290. switch (Id) {
  1291. case KSPROPERTY_DROPPEDFRAMES_CURRENT:
  1292. {
  1293. PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames =
  1294. (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;
  1295. pDroppedFrames->PictureNumber = pStrmEx->FrameInfo.PictureNumber;
  1296. // pStrmEx->biSizeImage is init to 0 by stream.sys 0'ing whole pStrmEx.
  1297. pDroppedFrames->DropCount = pStrmEx->FrameInfo.DropCount;
  1298. pDroppedFrames->AverageFrameSize = pStrmEx->biSizeImage;
  1299. pSrb->ActualBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
  1300. }
  1301. break;
  1302. default:
  1303. TRAP;
  1304. break;
  1305. }
  1306. }
  1307. //==========================================================================;
  1308. // Clock Handling Routines
  1309. //==========================================================================;
  1310. /*
  1311. ** VideoIndicateMasterClock ()
  1312. **
  1313. ** If this stream is not being used as the master clock, this function
  1314. ** is used to provide us with a handle to the clock to use when
  1315. ** requesting the current stream time.
  1316. **
  1317. ** Arguments:
  1318. **
  1319. ** pSrb - pointer to the stream request block for properties
  1320. **
  1321. ** Returns:
  1322. **
  1323. ** Side Effects: none
  1324. */
  1325. VOID
  1326. STREAMAPI
  1327. VideoIndicateMasterClock(
  1328. PHW_STREAM_REQUEST_BLOCK pSrb
  1329. )
  1330. {
  1331. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1332. pStrmEx->hMasterClock = pSrb->CommandData.MasterClockHandle;
  1333. }