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.

1658 lines
44 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 =
  364. &pVideoInfoHeader->VideoInfoHeader;
  365. nSize = KS_SIZE_VIDEOHEADER (pVideoInfoHdrRequested);
  366. DbgLogInfo(("TestCap: New Format\n"));
  367. DbgLogInfo(("TestCap: pVideoInfoHdrRequested=%p\n", pVideoInfoHdrRequested));
  368. DbgLogInfo(("TestCap: KS_VIDEOINFOHEADER size=%d\n", nSize));
  369. DbgLogInfo(("TestCap: Width=%d Height=%d BitCount=%d\n",
  370. pVideoInfoHdrRequested->bmiHeader.biWidth,
  371. pVideoInfoHdrRequested->bmiHeader.biHeight,
  372. pVideoInfoHdrRequested->bmiHeader.biBitCount));
  373. DbgLogInfo(("TestCap: biSizeImage=%d\n",
  374. pVideoInfoHdrRequested->bmiHeader.biSizeImage));
  375. //
  376. // If a previous format was in use, release the memory
  377. //
  378. if (pStrmEx->pVideoInfoHeader) {
  379. ExFreePool(pStrmEx->pVideoInfoHeader);
  380. pStrmEx->pVideoInfoHeader = NULL;
  381. }
  382. // Since the VIDEOINFOHEADER is of potentially variable size
  383. // allocate memory for it
  384. pStrmEx->pVideoInfoHeader = ExAllocatePool(NonPagedPool, nSize);
  385. if (pStrmEx->pVideoInfoHeader == NULL) {
  386. DbgLogError(("TestCap: ExAllocatePool failed\n"));
  387. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  388. return FALSE;
  389. }
  390. // Copy the VIDEOINFOHEADER requested to our storage
  391. RtlCopyMemory(
  392. pStrmEx->pVideoInfoHeader,
  393. pVideoInfoHdrRequested,
  394. nSize);
  395. // A renderer may be switching formats, and in this case, the AvgTimePerFrame
  396. // will be zero. Don't overwrite a previously set framerate.
  397. if (pStrmEx->pVideoInfoHeader->AvgTimePerFrame) {
  398. pStrmEx->AvgTimePerFrame = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  399. }
  400. }
  401. // -------------------------------------------------------------------
  402. // Specifier FORMAT_AnalogVideo for KS_ANALOGVIDEOINFO
  403. // -------------------------------------------------------------------
  404. else if (IsEqualGUID (&pKSDataFormat->Specifier,
  405. &KSDATAFORMAT_SPECIFIER_ANALOGVIDEO)) {
  406. //
  407. // AnalogVideo DataRange == DataFormat!
  408. //
  409. //
  410. // For now, don't even cache this
  411. //
  412. PKS_DATARANGE_ANALOGVIDEO pDataFormatAnalogVideo =
  413. (PKS_DATARANGE_ANALOGVIDEO) pSrb->CommandData.OpenFormat;
  414. }
  415. // -------------------------------------------------------------------
  416. // Specifier FORMAT_VBI for KS_VIDEO_VBI
  417. // -------------------------------------------------------------------
  418. else if (IsEqualGUID (&pKSDataFormat->Specifier,
  419. &KSDATAFORMAT_SPECIFIER_VBI))
  420. {
  421. // On a VBI stream, we save a pointer to StreamFormatVBI, which
  422. // has the timing info we want to get at later.
  423. pStrmEx->pVBIStreamFormat = &StreamFormatVBI;
  424. }
  425. // -------------------------------------------------------------------
  426. // Type FORMAT_NABTS for NABTS pin
  427. // -------------------------------------------------------------------
  428. else if (IsEqualGUID (&pKSDataFormat->SubFormat,
  429. &KSDATAFORMAT_SUBTYPE_NABTS))
  430. {
  431. // On a VBI stream, we save a pointer to StreamFormatVBI, which
  432. // has the timing info we want to get at later. (Even though
  433. // this is really a StreamFormatNABTS pin)
  434. pStrmEx->pVBIStreamFormat = &StreamFormatVBI;
  435. }
  436. // -------------------------------------------------------------------
  437. // for CC pin
  438. // -------------------------------------------------------------------
  439. else if (IsEqualGUID (&pKSDataFormat->SubFormat,
  440. &KSDATAFORMAT_SUBTYPE_CC))
  441. {
  442. // On a VBI stream, we save a pointer to StreamFormatVBI, which
  443. // has the timing info we want to get at later. (Even though
  444. // this is really a StreamFormatCC pin)
  445. pStrmEx->pVBIStreamFormat = &StreamFormatVBI;
  446. }
  447. else {
  448. // Unknown format
  449. pSrb->Status = STATUS_INVALID_PARAMETER;
  450. return FALSE;
  451. }
  452. return TRUE;
  453. }
  454. /*
  455. ** VideoReceiveDataPacket()
  456. **
  457. ** Receives Video data packet commands on the output streams
  458. **
  459. ** Arguments:
  460. **
  461. ** pSrb - Stream request block for the Video stream
  462. **
  463. ** Returns: nothing
  464. **
  465. ** Side Effects: none
  466. */
  467. VOID
  468. STREAMAPI
  469. VideoReceiveDataPacket(
  470. IN PHW_STREAM_REQUEST_BLOCK pSrb
  471. )
  472. {
  473. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  474. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  475. int StreamNumber = pSrb->StreamObject->StreamNumber;
  476. //
  477. // make sure we have a device extension and are at passive level
  478. //
  479. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  480. DEBUG_ASSERT(pHwDevExt!=NULL);
  481. DbgLogTrace(("TestCap: Receiving Stream Data SRB %p, %x\n", pSrb, pSrb->Command));
  482. //
  483. // Default to success
  484. //
  485. pSrb->Status = STATUS_SUCCESS;
  486. //
  487. // determine the type of packet.
  488. //
  489. switch (pSrb->Command){
  490. case SRB_READ_DATA:
  491. // Rule:
  492. // Only accept read requests when in either the Pause or Run
  493. // States. If Stopped, immediately return the SRB.
  494. if (pStrmEx->KSState == KSSTATE_STOP) {
  495. CompleteStreamSRB (pSrb);
  496. break;
  497. }
  498. //
  499. // Put this read request on the pending queue
  500. //
  501. VideoQueueAddSRB (pSrb);
  502. // Since another thread COULD HAVE MODIFIED THE STREAM STATE
  503. // in the midst of adding it to the queue, check the stream
  504. // state again, and cancel the SRB if necessary. Note that
  505. // this race condition was NOT handled in the original DDK
  506. // release of testcap!
  507. if (pStrmEx->KSState == KSSTATE_STOP) {
  508. VideoQueueCancelOneSRB (
  509. pStrmEx,
  510. pSrb);
  511. }
  512. break;
  513. default:
  514. //
  515. // invalid / unsupported command. Fail it as such
  516. //
  517. TRAP;
  518. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  519. CompleteStreamSRB (pSrb);
  520. } // switch (pSrb->Command)
  521. }
  522. /*
  523. ** VideoReceiveCtrlPacket()
  524. **
  525. ** Receives packet commands that control the Video output streams
  526. **
  527. ** Arguments:
  528. **
  529. ** pSrb - The stream request block for the Video stream
  530. **
  531. ** Returns: nothing
  532. **
  533. ** Side Effects: none
  534. */
  535. VOID
  536. STREAMAPI
  537. VideoReceiveCtrlPacket(
  538. IN PHW_STREAM_REQUEST_BLOCK pSrb
  539. )
  540. {
  541. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  542. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  543. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  544. BOOL Busy;
  545. //
  546. // make sure we have a device extension and are at passive level
  547. //
  548. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  549. DEBUG_ASSERT(pHwDevExt!=NULL);
  550. DbgLogTrace(("TestCap: Receiving Stream Control SRB %p, %x\n", pSrb, pSrb->Command));
  551. //
  552. // If we're already processing an SRB, add it to the queue
  553. //
  554. Busy = AddToListIfBusy (
  555. pSrb,
  556. &pHwDevExt->AdapterSpinLock,
  557. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  558. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  559. if (Busy) {
  560. return;
  561. }
  562. while (TRUE) {
  563. //
  564. // Default to success
  565. //
  566. pSrb->Status = STATUS_SUCCESS;
  567. //
  568. // determine the type of packet.
  569. //
  570. switch (pSrb->Command)
  571. {
  572. case SRB_PROPOSE_DATA_FORMAT:
  573. DbgLogInfo(("TestCap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %p, StreamNumber= %d\n", pSrb, StreamNumber));
  574. if (!(AdapterVerifyFormat (
  575. pSrb->CommandData.OpenFormat,
  576. pSrb->StreamObject->StreamNumber))) {
  577. pSrb->Status = STATUS_NO_MATCH;
  578. DbgLogInfo(("TestCap: SRB_PROPOSE_DATA_FORMAT FAILED\n"));
  579. }
  580. // KS support for dynamic format changes is BROKEN right now,
  581. // so we prevent these from happening by saying they ALL fail.
  582. // If this is ever fixed, the next line must be removed.
  583. pSrb->Status = STATUS_NO_MATCH; // prevent dynamic format changes
  584. break;
  585. case SRB_SET_DATA_FORMAT:
  586. DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT\n"));
  587. if (!(AdapterVerifyFormat (
  588. pSrb->CommandData.OpenFormat,
  589. pSrb->StreamObject->StreamNumber))) {
  590. pSrb->Status = STATUS_NO_MATCH;
  591. DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT FAILED\n"));
  592. } else {
  593. VideoSetFormat (pSrb);
  594. DbgLogInfo(("TestCap: SRB_SET_DATA_FORMAT SUCCEEDED\n"));
  595. }
  596. break;
  597. case SRB_GET_DATA_FORMAT:
  598. DbgLogInfo(("TestCap: SRB_GET_DATA_FORMAT\n"));
  599. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  600. break;
  601. case SRB_SET_STREAM_STATE:
  602. VideoSetState(pSrb);
  603. break;
  604. case SRB_GET_STREAM_STATE:
  605. VideoGetState(pSrb);
  606. break;
  607. case SRB_GET_STREAM_PROPERTY:
  608. VideoGetProperty(pSrb);
  609. break;
  610. case SRB_SET_STREAM_PROPERTY:
  611. VideoSetProperty(pSrb);
  612. break;
  613. case SRB_INDICATE_MASTER_CLOCK:
  614. //
  615. // Assigns a clock to a stream
  616. //
  617. VideoIndicateMasterClock (pSrb);
  618. break;
  619. default:
  620. //
  621. // invalid / unsupported command. Fail it as such
  622. //
  623. TRAP;
  624. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  625. }
  626. CompleteStreamSRB (pSrb);
  627. //
  628. // See if there's anything else on the queue
  629. //
  630. Busy = RemoveFromListIfAvailable (
  631. &pSrb,
  632. &pHwDevExt->AdapterSpinLock,
  633. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  634. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  635. if (!Busy) {
  636. break;
  637. }
  638. }
  639. }
  640. /*
  641. ** AnalogVideoReceiveDataPacket()
  642. **
  643. ** Receives AnalogVideo data packet commands on the input stream
  644. **
  645. ** Arguments:
  646. **
  647. ** pSrb - Stream request block for the Analog Video stream.
  648. ** This stream receives tuner control packets.
  649. **
  650. ** Returns: nothing
  651. **
  652. ** Side Effects: none
  653. */
  654. VOID
  655. STREAMAPI
  656. AnalogVideoReceiveDataPacket(
  657. IN PHW_STREAM_REQUEST_BLOCK pSrb
  658. )
  659. {
  660. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  661. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  662. PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
  663. //
  664. // make sure we have a device extension and are at passive level
  665. //
  666. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  667. DEBUG_ASSERT(pHwDevExt!=NULL);
  668. DbgLogInfo(("TestCap: Receiving Tuner packet SRB %p, %x\n", pSrb, pSrb->Command));
  669. //
  670. // Default to success
  671. //
  672. pSrb->Status = STATUS_SUCCESS;
  673. //
  674. // determine the type of packet.
  675. //
  676. switch (pSrb->Command){
  677. case SRB_WRITE_DATA:
  678. //
  679. // This data packet contains the channel change information
  680. // passed on the AnalogVideoIn stream. Devices which support
  681. // VBI data streams need to pass this info on their output pins.
  682. //
  683. if (pDataPacket->FrameExtent == sizeof (KS_TVTUNER_CHANGE_INFO)) {
  684. RtlCopyMemory(
  685. &pHwDevExt->TVTunerChangeInfo,
  686. pDataPacket->Data,
  687. sizeof (KS_TVTUNER_CHANGE_INFO));
  688. }
  689. CompleteStreamSRB (pSrb);
  690. break;
  691. default:
  692. //
  693. // invalid / unsupported command. Fail it as such
  694. //
  695. TRAP;
  696. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  697. CompleteStreamSRB (pSrb);
  698. } // switch (pSrb->Command)
  699. }
  700. /*
  701. ** AnalogVideoReceiveCtrlPacket()
  702. **
  703. ** Receives packet commands that control the Analog Video stream
  704. **
  705. ** Arguments:
  706. **
  707. ** pSrb - The stream request block for the Video stream
  708. **
  709. ** Returns: nothing
  710. **
  711. ** Side Effects: none
  712. */
  713. VOID
  714. STREAMAPI
  715. AnalogVideoReceiveCtrlPacket(
  716. IN PHW_STREAM_REQUEST_BLOCK pSrb
  717. )
  718. {
  719. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  720. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  721. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  722. BOOL Busy;
  723. //
  724. // make sure we have a device extension and we are at passive level
  725. //
  726. DEBUG_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  727. DEBUG_ASSERT(pHwDevExt!=NULL);
  728. DbgLogTrace(("TestCap: Receiving Analog Stream Control SRB %p, %x\n", pSrb, pSrb->Command));
  729. //
  730. // If we're already processing an SRB, add it to the queue
  731. //
  732. Busy = AddToListIfBusy (
  733. pSrb,
  734. &pHwDevExt->AdapterSpinLock,
  735. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  736. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  737. if (Busy) {
  738. return;
  739. }
  740. do {
  741. //
  742. // Default to success
  743. //
  744. pSrb->Status = STATUS_SUCCESS;
  745. //
  746. // determine the type of packet.
  747. //
  748. switch (pSrb->Command)
  749. {
  750. case SRB_PROPOSE_DATA_FORMAT:
  751. DbgLogInfo(("TestCap: Receiving SRB_PROPOSE_DATA_FORMAT SRB %p, StreamNumber= %d\n", pSrb, StreamNumber));
  752. if (!(AdapterVerifyFormat (
  753. pSrb->CommandData.OpenFormat,
  754. pSrb->StreamObject->StreamNumber))) {
  755. pSrb->Status = STATUS_NO_MATCH;
  756. }
  757. break;
  758. case SRB_SET_STREAM_STATE:
  759. //
  760. // Don't use VideoSetState, since we don't want to start another
  761. // timer running
  762. //
  763. pStrmEx->KSState = pSrb->CommandData.StreamState;
  764. DbgLogInfo(("TestCap: STATE=%d, Stream=%d\n", pStrmEx->KSState, StreamNumber));
  765. break;
  766. case SRB_GET_STREAM_STATE:
  767. VideoGetState(pSrb);
  768. break;
  769. case SRB_GET_STREAM_PROPERTY:
  770. VideoGetProperty(pSrb);
  771. break;
  772. case SRB_INDICATE_MASTER_CLOCK:
  773. //
  774. // Assigns a clock to a stream
  775. //
  776. VideoIndicateMasterClock (pSrb);
  777. break;
  778. default:
  779. //
  780. // invalid / unsupported command. Fail it as such
  781. //
  782. TRAP;
  783. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  784. }
  785. CompleteStreamSRB (pSrb);
  786. //
  787. // See if there's anything else on the queue
  788. //
  789. Busy = RemoveFromListIfAvailable (
  790. &pSrb,
  791. &pHwDevExt->AdapterSpinLock,
  792. &pHwDevExt->ProcessingControlSRB [StreamNumber],
  793. &pHwDevExt->StreamControlSRBList[StreamNumber]);
  794. } while ( Busy );
  795. }
  796. /*
  797. ** CompleteStreamSRB ()
  798. **
  799. ** This routine is called when a packet is being completed.
  800. **
  801. ** Arguments:
  802. **
  803. ** pSrb - pointer to the request packet to be completed
  804. **
  805. ** Returns:
  806. **
  807. ** Side Effects: none
  808. */
  809. VOID
  810. STREAMAPI
  811. CompleteStreamSRB (
  812. IN PHW_STREAM_REQUEST_BLOCK pSrb
  813. )
  814. {
  815. DbgLogTrace(("TestCap: Completing Stream SRB %p\n", pSrb));
  816. StreamClassStreamNotification(
  817. StreamRequestComplete,
  818. pSrb->StreamObject,
  819. pSrb);
  820. }
  821. /*
  822. ** VideoGetProperty()
  823. **
  824. ** Routine to process video property requests
  825. **
  826. ** Arguments:
  827. **
  828. ** pSrb - pointer to the stream request block for properties
  829. **
  830. ** Returns:
  831. **
  832. ** Side Effects: none
  833. */
  834. VOID
  835. STREAMAPI
  836. VideoGetProperty(
  837. PHW_STREAM_REQUEST_BLOCK pSrb
  838. )
  839. {
  840. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  841. if (IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set)) {
  842. VideoStreamGetConnectionProperty (pSrb);
  843. }
  844. else if (IsEqualGUID (&PROPSETID_VIDCAP_DROPPEDFRAMES, &pSPD->Property->Set)) {
  845. VideoStreamGetDroppedFramesProperty (pSrb);
  846. }
  847. else {
  848. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  849. }
  850. }
  851. /*
  852. ** VideoSetProperty()
  853. **
  854. ** Routine to process video property requests
  855. **
  856. ** Arguments:
  857. **
  858. ** pSrb - pointer to the stream request block for properties
  859. **
  860. ** Returns:
  861. **
  862. ** Side Effects: none
  863. */
  864. VOID
  865. STREAMAPI
  866. VideoSetProperty(
  867. PHW_STREAM_REQUEST_BLOCK pSrb
  868. )
  869. {
  870. // PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  871. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  872. }
  873. /*
  874. ** VideoTimerRoutine()
  875. **
  876. ** A timer has been created based on the requested capture interval.
  877. ** This is the callback routine for this timer event.
  878. **
  879. ** Note: Devices capable of using interrupts should always
  880. ** trigger capture on a VSYNC interrupt, and not use a timer.
  881. **
  882. ** Arguments:
  883. **
  884. ** Context - pointer to the stream extension
  885. **
  886. ** Returns: nothing
  887. **
  888. ** Side Effects: none
  889. */
  890. VOID
  891. STREAMAPI
  892. VideoTimerRoutine(
  893. PVOID Context
  894. )
  895. {
  896. PSTREAMEX pStrmEx = ((PSTREAMEX)Context);
  897. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  898. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  899. // If we're stopped and the timer is still running, just return.
  900. // This will stop the timer.
  901. if (pStrmEx->KSState == KSSTATE_STOP) {
  902. return;
  903. }
  904. // Capture a frame if it's time and we have a buffer
  905. VideoCaptureRoutine(pStrmEx);
  906. // Schedule the next timer event
  907. // Make it run at 2x the requested capture rate (which is in 100nS units)
  908. StreamClassScheduleTimer (
  909. pStrmEx->pStreamObject, // StreamObject
  910. pHwDevExt, // HwDeviceExtension
  911. (ULONG) (pStrmEx->AvgTimePerFrame / 20), // Microseconds
  912. VideoTimerRoutine, // TimerRoutine
  913. pStrmEx); // Context
  914. }
  915. /*
  916. ** VideoCaptureRoutine()
  917. **
  918. ** Routine to capture video frames based on a timer.
  919. **
  920. ** Note: Devices capable of using interrupts should always
  921. ** trigger capture on a VSYNC interrupt, and not use a timer.
  922. **
  923. ** Arguments:
  924. **
  925. ** Returns: nothing
  926. **
  927. ** Side Effects: none
  928. */
  929. VOID
  930. STREAMAPI
  931. VideoCaptureRoutine(
  932. IN PSTREAMEX pStrmEx
  933. )
  934. {
  935. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  936. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  937. PKSSTREAM_HEADER pDataPacket;
  938. PKS_FRAME_INFO pFrameInfo;
  939. // If we're stopped and the timer is still running, just return.
  940. // This will stop the timer.
  941. if (pStrmEx->KSState == KSSTATE_STOP) {
  942. return;
  943. }
  944. // Find out what time it is, if we're using a clock
  945. if (pStrmEx->hMasterClock ) {
  946. HW_TIME_CONTEXT TimeContext;
  947. TimeContext.HwDeviceExtension = pHwDevExt;
  948. TimeContext.HwStreamObject = pStrmEx->pStreamObject;
  949. TimeContext.Function = TIME_GET_STREAM_TIME;
  950. StreamClassQueryMasterClockSync (
  951. pStrmEx->hMasterClock,
  952. &TimeContext);
  953. pStrmEx->QST_StreamTime = TimeContext.Time;
  954. pStrmEx->QST_Now = TimeContext.SystemTime;
  955. if (pStrmEx->QST_NextFrame == 0) {
  956. pStrmEx->QST_NextFrame = pStrmEx->QST_StreamTime + pStrmEx->AvgTimePerFrame;
  957. }
  958. #ifdef CREATE_A_FLURRY_OF_TIMING_SPEW
  959. DbgLogTrace(("TestCap: Time=%6d mS at SystemTime=%I64d\n",
  960. (LONG) ((LONGLONG) TimeContext.Time / 10000),
  961. TimeContext.SystemTime));
  962. #endif
  963. }
  964. // Only capture in the RUN state
  965. if (pStrmEx->KSState == KSSTATE_RUN) {
  966. //
  967. // Determine if it is time to capture a frame based on
  968. // how much time has elapsed since capture started.
  969. // If there isn't a clock available, then capture immediately.
  970. //
  971. if ((!pStrmEx->hMasterClock) ||
  972. (pStrmEx->QST_StreamTime >= pStrmEx->QST_NextFrame)) {
  973. PHW_STREAM_REQUEST_BLOCK pSrb;
  974. // Increment the picture count (usually this is VSYNC count)
  975. pStrmEx->FrameInfo.PictureNumber++;
  976. //
  977. // Get the next queue SRB (if any)
  978. //
  979. pSrb = VideoQueueRemoveSRB (
  980. pHwDevExt,
  981. StreamNumber);
  982. if (pSrb) {
  983. pDataPacket = pSrb->CommandData.DataBufferArray;
  984. pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
  985. //
  986. // Call the routine which synthesizes images
  987. //
  988. ImageSynth (pSrb,
  989. pHwDevExt->VideoInputConnected,
  990. pStrmEx->VideoControlMode & KS_VideoControlFlag_FlipHorizontal);
  991. // Set additional info fields about the data captured such as:
  992. // Frames Captured
  993. // Frames Dropped
  994. // Field Polarity
  995. pStrmEx->FrameInfo.ExtendedHeaderSize = pFrameInfo->ExtendedHeaderSize;
  996. *pFrameInfo = pStrmEx->FrameInfo;
  997. // Init the flags to zero
  998. pDataPacket->OptionsFlags = 0;
  999. // Set the discontinuity flag if frames have been previously
  1000. // dropped, and then reset our internal flag
  1001. if (pStrmEx->fDiscontinuity) {
  1002. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  1003. pStrmEx->fDiscontinuity = FALSE;
  1004. }
  1005. //
  1006. // Return the timestamp for the frame
  1007. //
  1008. pDataPacket->PresentationTime.Numerator = 1;
  1009. pDataPacket->PresentationTime.Denominator = 1;
  1010. pDataPacket->Duration = pStrmEx->AvgTimePerFrame;
  1011. //
  1012. // if we have a master clock AND this is the capture stream
  1013. //
  1014. if (pStrmEx->hMasterClock && (StreamNumber == 0)) {
  1015. pDataPacket->PresentationTime.Time = pStrmEx->QST_StreamTime;
  1016. pDataPacket->OptionsFlags |=
  1017. KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  1018. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  1019. }
  1020. else {
  1021. //
  1022. // no clock or the preview stream, so just mark the time as unknown
  1023. //
  1024. pDataPacket->PresentationTime.Time = 0;
  1025. // clear the timestamp valid flags
  1026. pDataPacket->OptionsFlags &=
  1027. ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  1028. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  1029. }
  1030. // Every frame we generate is a key frame (aka SplicePoint)
  1031. // Delta frames (B or P) should not set this flag
  1032. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
  1033. // Output a frame count every 100th frame in Debug mode
  1034. if (pStrmEx->FrameInfo.PictureNumber % 100 == 0) {
  1035. DbgLogInfo(("TestCap: Picture %u, Stream=%d\n",
  1036. (unsigned int)pStrmEx->FrameInfo.PictureNumber,
  1037. StreamNumber));
  1038. }
  1039. CompleteStreamSRB (pSrb);
  1040. } // if we have an SRB
  1041. else {
  1042. //
  1043. // No buffer was available when we should have captured one
  1044. // Increment the counter which keeps track of
  1045. // dropped frames
  1046. pStrmEx->FrameInfo.DropCount++;
  1047. // Set the (local) discontinuity flag
  1048. // This will cause the next packet processed to have the
  1049. // KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY flag set.
  1050. pStrmEx->fDiscontinuity = TRUE;
  1051. }
  1052. // Figure out when to capture the next frame
  1053. pStrmEx->QST_NextFrame += pStrmEx->AvgTimePerFrame;
  1054. } // endif time to capture a frame
  1055. } // endif we're running
  1056. }
  1057. /*
  1058. ** VideoSetState()
  1059. **
  1060. ** Sets the current state for a given stream
  1061. **
  1062. ** Arguments:
  1063. **
  1064. ** pSrb - pointer to the stream request block for properties
  1065. **
  1066. ** Returns:
  1067. **
  1068. ** Side Effects: none
  1069. */
  1070. VOID
  1071. STREAMAPI
  1072. VideoSetState(
  1073. PHW_STREAM_REQUEST_BLOCK pSrb
  1074. )
  1075. {
  1076. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  1077. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1078. int StreamNumber = pStrmEx->pStreamObject->StreamNumber;
  1079. KSSTATE PreviousState;
  1080. //
  1081. // For each stream, the following states are used:
  1082. //
  1083. // Stop: Absolute minimum resources are used. No outstanding IRPs.
  1084. // Acquire: KS only state that has no DirectShow correpondence
  1085. // Acquire needed resources.
  1086. // Pause: Getting ready to run. Allocate needed resources so that
  1087. // the eventual transition to Run is as fast as possible.
  1088. // Read SRBs will be queued at either the Stream class
  1089. // or in your driver (depending on when you send "ReadyForNext")
  1090. // and whether you're using the Stream class for synchronization
  1091. // Run: Streaming.
  1092. //
  1093. // Moving to Stop to Run always transitions through Pause.
  1094. //
  1095. // But since a client app could crash unexpectedly, drivers should handle
  1096. // the situation of having outstanding IRPs cancelled and open streams
  1097. // being closed WHILE THEY ARE STREAMING!
  1098. //
  1099. // Note that it is quite possible to transition repeatedly between states:
  1100. // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop
  1101. //
  1102. //
  1103. // Remember the state we're transitioning away from
  1104. //
  1105. PreviousState = pStrmEx->KSState;
  1106. //
  1107. // Set the new state
  1108. //
  1109. pStrmEx->KSState = pSrb->CommandData.StreamState;
  1110. switch (pSrb->CommandData.StreamState)
  1111. {
  1112. case KSSTATE_STOP:
  1113. //
  1114. // The stream class will cancel all outstanding IRPs for us
  1115. // (but only if it is maintaining the queue ie. using Stream Class synchronization)
  1116. // Since Testcap is not using Stream Class synchronization, we must clear the queue here
  1117. VideoQueueCancelAllSRBs (pStrmEx);
  1118. DbgLogInfo(("TestCap: STATE Stopped, Stream=%d\n", StreamNumber));
  1119. break;
  1120. case KSSTATE_ACQUIRE:
  1121. //
  1122. // This is a KS only state, that has no correspondence in DirectShow
  1123. //
  1124. DbgLogInfo(("TestCap: STATE Acquire, Stream=%d\n", StreamNumber));
  1125. break;
  1126. case KSSTATE_PAUSE:
  1127. //
  1128. // On a transition to pause from acquire or stop, start our timer running.
  1129. //
  1130. if (PreviousState == KSSTATE_ACQUIRE || PreviousState == KSSTATE_STOP) {
  1131. // Zero the frame counters
  1132. pStrmEx->FrameInfo.PictureNumber = 0;
  1133. pStrmEx->FrameInfo.DropCount = 0;
  1134. pStrmEx->FrameInfo.dwFrameFlags = 0;
  1135. // Setup the next timer callback(s)
  1136. VideoTimerRoutine(pStrmEx);
  1137. }
  1138. DbgLogInfo(("TestCap: STATE Pause, Stream=%d\n", StreamNumber));
  1139. break;
  1140. case KSSTATE_RUN:
  1141. //
  1142. // Begin Streaming.
  1143. //
  1144. // Reset the discontinuity flag
  1145. pStrmEx->fDiscontinuity = FALSE;
  1146. // Setting the NextFrame time to zero will cause the value to be
  1147. // reset from the stream time
  1148. pStrmEx->QST_NextFrame = 0;
  1149. DbgLogInfo(("TestCap: STATE Run, Stream=%d\n", StreamNumber));
  1150. break;
  1151. } // end switch (pSrb->CommandData.StreamState)
  1152. }
  1153. /*
  1154. ** VideoGetState()
  1155. **
  1156. ** Gets the current state of the requested stream
  1157. **
  1158. ** Arguments:
  1159. **
  1160. ** pSrb - pointer to the stream request block for properties
  1161. **
  1162. ** Returns:
  1163. **
  1164. ** Side Effects: none
  1165. */
  1166. VOID
  1167. STREAMAPI
  1168. VideoGetState(
  1169. PHW_STREAM_REQUEST_BLOCK pSrb
  1170. )
  1171. {
  1172. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1173. pSrb->CommandData.StreamState = pStrmEx->KSState;
  1174. pSrb->ActualBytesTransferred = sizeof (KSSTATE);
  1175. // A very odd rule:
  1176. // When transitioning from stop to pause, DShow tries to preroll
  1177. // the graph. Capture sources can't preroll, and indicate this
  1178. // by returning VFW_S_CANT_CUE in user mode. To indicate this
  1179. // condition from drivers, they must return STATUS_NO_DATA_DETECTED
  1180. if (pStrmEx->KSState == KSSTATE_PAUSE) {
  1181. pSrb->Status = STATUS_NO_DATA_DETECTED;
  1182. }
  1183. }
  1184. /*
  1185. ** VideoStreamGetConnectionProperty()
  1186. **
  1187. ** Gets the properties for a stream
  1188. **
  1189. ** Arguments:
  1190. **
  1191. ** pSrb - pointer to the stream request block for properties
  1192. **
  1193. ** Returns:
  1194. **
  1195. ** Side Effects: none
  1196. */
  1197. VOID
  1198. STREAMAPI
  1199. VideoStreamGetConnectionProperty(
  1200. PHW_STREAM_REQUEST_BLOCK pSrb
  1201. )
  1202. {
  1203. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1204. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1205. ULONG Id = pSPD->Property->Id; // index of the property
  1206. int streamNumber = (int)pSrb->StreamObject->StreamNumber;
  1207. switch (Id) {
  1208. // This property describes the allocator requirements for the stream
  1209. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  1210. {
  1211. PKSALLOCATOR_FRAMING Framing =
  1212. (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  1213. Framing->RequirementsFlags =
  1214. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  1215. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  1216. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
  1217. Framing->PoolType = PagedPool;
  1218. Framing->FileAlignment = 0; // FILE_LONG_ALIGNMENT???;
  1219. Framing->Reserved = 0;
  1220. pSrb->ActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  1221. switch (streamNumber) {
  1222. case STREAM_Capture:
  1223. case STREAM_Preview:
  1224. Framing->Frames = 2;
  1225. Framing->FrameSize =
  1226. pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1227. break;
  1228. case STREAM_VBI:
  1229. Framing->Frames = 8;
  1230. Framing->FrameSize = StreamFormatVBI.DataRange.SampleSize;
  1231. break;
  1232. case STREAM_CC:
  1233. Framing->Frames = 100;
  1234. Framing->FrameSize = StreamFormatCC.SampleSize;
  1235. break;
  1236. case STREAM_NABTS:
  1237. Framing->Frames = 20;
  1238. Framing->FrameSize = StreamFormatNABTS.SampleSize;
  1239. break;
  1240. case STREAM_AnalogVideoInput:
  1241. default:
  1242. pSrb->Status = STATUS_INVALID_PARAMETER;
  1243. break;
  1244. }
  1245. break;
  1246. }
  1247. default:
  1248. TRAP;
  1249. break;
  1250. }
  1251. }
  1252. /*
  1253. ** VideoStreamGetDroppedFramesProperty()
  1254. **
  1255. ** Gets dynamic information about the progress of the capture process.
  1256. **
  1257. ** Arguments:
  1258. **
  1259. ** pSrb - pointer to the stream request block for properties
  1260. **
  1261. ** Returns:
  1262. **
  1263. ** Side Effects: none
  1264. */
  1265. VOID
  1266. STREAMAPI
  1267. VideoStreamGetDroppedFramesProperty(
  1268. PHW_STREAM_REQUEST_BLOCK pSrb
  1269. )
  1270. {
  1271. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1272. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1273. ULONG Id = pSPD->Property->Id; // index of the property
  1274. switch (Id) {
  1275. case KSPROPERTY_DROPPEDFRAMES_CURRENT:
  1276. {
  1277. PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames =
  1278. (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;
  1279. pDroppedFrames->PictureNumber = pStrmEx->FrameInfo.PictureNumber;
  1280. pDroppedFrames->DropCount = pStrmEx->FrameInfo.DropCount;
  1281. pDroppedFrames->AverageFrameSize = pStrmEx->pVideoInfoHeader->bmiHeader.biSizeImage;
  1282. pSrb->ActualBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
  1283. }
  1284. break;
  1285. default:
  1286. TRAP;
  1287. break;
  1288. }
  1289. }
  1290. //==========================================================================;
  1291. // Clock Handling Routines
  1292. //==========================================================================;
  1293. /*
  1294. ** VideoIndicateMasterClock ()
  1295. **
  1296. ** If this stream is not being used as the master clock, this function
  1297. ** is used to provide us with a handle to the clock to use when
  1298. ** requesting the current stream time.
  1299. **
  1300. ** Arguments:
  1301. **
  1302. ** pSrb - pointer to the stream request block for properties
  1303. **
  1304. ** Returns:
  1305. **
  1306. ** Side Effects: none
  1307. */
  1308. VOID
  1309. STREAMAPI
  1310. VideoIndicateMasterClock(
  1311. PHW_STREAM_REQUEST_BLOCK pSrb
  1312. )
  1313. {
  1314. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1315. pStrmEx->hMasterClock = pSrb->CommandData.MasterClockHandle;
  1316. }