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.

1020 lines
29 KiB

  1. /**************************************************************************
  2. AVStream Simulated Hardware Sample
  3. Copyright (c) 2001, Microsoft Corporation.
  4. File:
  5. capture.cpp
  6. Abstract:
  7. This file contains source for the video capture pin on the capture
  8. filter. The capture sample performs "fake" DMA directly into
  9. the capture buffers. Common buffer DMA will work slightly differently.
  10. For common buffer DMA, the general technique would be DPC schedules
  11. processing with KsPinAttemptProcessing. The processing routine grabs
  12. the leading edge, copies data out of the common buffer and advances.
  13. Cloning would not be necessary with this technique. It would be
  14. similiar to the way "AVSSamp" works, but it would be pin-centric.
  15. History:
  16. created 3/8/2001
  17. **************************************************************************/
  18. #include "BDACap.h"
  19. /**************************************************************************
  20. PAGEABLE CODE
  21. **************************************************************************/
  22. #ifdef ALLOC_PRAGMA
  23. #pragma code_seg("PAGE")
  24. #endif // ALLOC_PRAGMA
  25. CCapturePin::
  26. CCapturePin (
  27. IN PKSPIN Pin
  28. ) :
  29. m_Pin (Pin)
  30. /*++
  31. Routine Description:
  32. Construct a new capture pin.
  33. Arguments:
  34. Pin -
  35. The AVStream pin object corresponding to the capture pin
  36. Return Value:
  37. None
  38. --*/
  39. {
  40. PAGED_CODE();
  41. PKSDEVICE Device = KsPinGetDevice (Pin);
  42. //
  43. // Set up our device pointer. This gives us access to "hardware I/O"
  44. // during the capture routines.
  45. //
  46. m_Device = reinterpret_cast <CCaptureDevice *> (Device -> Context);
  47. }
  48. /*************************************************/
  49. NTSTATUS
  50. CCapturePin::
  51. DispatchCreate (
  52. IN PKSPIN Pin,
  53. IN PIRP Irp
  54. )
  55. /*++
  56. Routine Description:
  57. Create a new capture pin. This is the creation dispatch for
  58. the video capture pin.
  59. Arguments:
  60. Pin -
  61. The pin being created
  62. Irp -
  63. The creation Irp
  64. Return Value:
  65. Success / Failure
  66. --*/
  67. {
  68. PAGED_CODE();
  69. NTSTATUS Status = STATUS_SUCCESS;
  70. CCapturePin *CapPin = new (NonPagedPool, MS_SAMPLE_CAPTURE_POOL_TAG) CCapturePin (Pin);
  71. if (!CapPin) {
  72. //
  73. // Return failure if we couldn't create the pin.
  74. //
  75. Status = STATUS_INSUFFICIENT_RESOURCES;
  76. } else {
  77. //
  78. // Add the item to the object bag if we we were successful.
  79. // Whenever the pin closes, the bag is cleaned up and we will be
  80. // freed.
  81. //
  82. Status = KsAddItemToObjectBag (
  83. Pin -> Bag,
  84. reinterpret_cast <PVOID> (CapPin),
  85. reinterpret_cast <PFNKSFREE> (CCapturePin::Cleanup)
  86. );
  87. if (!NT_SUCCESS (Status)) {
  88. delete CapPin;
  89. } else {
  90. Pin -> Context = reinterpret_cast <PVOID> (CapPin);
  91. }
  92. }
  93. //
  94. // If we succeeded so far, stash the video info header away and change
  95. // our allocator framing to reflect the fact that only now do we know
  96. // the framing requirements based on the connection format.
  97. //
  98. PBDA_TRANSPORT_INFO TransportInfo = NULL;
  99. if (NT_SUCCESS (Status)) {
  100. TransportInfo = CapPin -> CaptureBdaTransportInfo ();
  101. if (!TransportInfo) {
  102. Status = STATUS_INSUFFICIENT_RESOURCES;
  103. }
  104. }
  105. if (NT_SUCCESS (Status)) {
  106. //
  107. // We need to edit the descriptor to ensure we don't mess up any other
  108. // pins using the descriptor or touch read-only memory.
  109. //
  110. Status = KsEdit (Pin, &Pin -> Descriptor, 'aChS');
  111. if (NT_SUCCESS (Status)) {
  112. Status = KsEdit (
  113. Pin,
  114. &(Pin -> Descriptor -> AllocatorFraming),
  115. 'aChS'
  116. );
  117. }
  118. //
  119. // If the edits proceeded without running out of memory, adjust
  120. // the framing based on the video info header.
  121. //
  122. if (NT_SUCCESS (Status)) {
  123. //
  124. // We've KsEdit'ed this... I'm safe to cast away constness as
  125. // long as the edit succeeded.
  126. //
  127. PKSALLOCATOR_FRAMING_EX Framing =
  128. const_cast <PKSALLOCATOR_FRAMING_EX> (
  129. Pin -> Descriptor -> AllocatorFraming
  130. );
  131. Framing -> FramingItem [0].Frames = 8;
  132. //
  133. // The physical and optimal ranges must be biSizeImage. We only
  134. // support one frame size, precisely the size of each capture
  135. // image.
  136. //
  137. Framing -> FramingItem [0].PhysicalRange.MinFrameSize =
  138. Framing -> FramingItem [0].PhysicalRange.MaxFrameSize =
  139. Framing -> FramingItem [0].FramingRange.Range.MinFrameSize =
  140. Framing -> FramingItem [0].FramingRange.Range.MaxFrameSize =
  141. TransportInfo -> ulcbPhyiscalFrame;
  142. Framing -> FramingItem [0].PhysicalRange.Stepping =
  143. Framing -> FramingItem [0].FramingRange.Range.Stepping =
  144. 0;
  145. }
  146. }
  147. return Status;
  148. }
  149. /*************************************************/
  150. PBDA_TRANSPORT_INFO
  151. CCapturePin::
  152. CaptureBdaTransportInfo (
  153. )
  154. /*++
  155. Routine Description:
  156. Capture the video info header out of the connection format. This
  157. is what we use to base synthesized images off.
  158. Arguments:
  159. None
  160. Return Value:
  161. The captured video info header or NULL if there is insufficient
  162. memory.
  163. --*/
  164. {
  165. PAGED_CODE();
  166. m_TransportInfo = reinterpret_cast <PBDA_TRANSPORT_INFO> (
  167. ExAllocatePool (
  168. NonPagedPool,
  169. sizeof(BDA_TRANSPORT_INFO)
  170. )
  171. );
  172. if (!m_TransportInfo)
  173. return NULL;
  174. //
  175. // Bag the newly allocated header space. This will get cleaned up
  176. // automatically when the pin closes.
  177. //
  178. NTSTATUS Status =
  179. KsAddItemToObjectBag (
  180. m_Pin -> Bag,
  181. reinterpret_cast <PVOID> (m_TransportInfo),
  182. NULL
  183. );
  184. if (!NT_SUCCESS (Status)) {
  185. ExFreePool (m_TransportInfo);
  186. return NULL;
  187. } else {
  188. m_TransportInfo->ulcbPhyiscalPacket = 188;
  189. m_TransportInfo->ulcbPhyiscalFrame = 188 * 312;
  190. m_TransportInfo->ulcbPhyiscalFrameAlignment = 1;
  191. m_TransportInfo->AvgTimePerFrame = (19200 * 10000 * 8) / (188 * 312);
  192. }
  193. return m_TransportInfo;
  194. }
  195. /*************************************************/
  196. NTSTATUS
  197. CCapturePin::
  198. Process (
  199. )
  200. /*++
  201. Routine Description:
  202. The process dispatch for the pin bridges to this location.
  203. We handle setting up scatter gather mappings, etc...
  204. Arguments:
  205. None
  206. Return Value:
  207. Success / Failure
  208. --*/
  209. {
  210. PAGED_CODE();
  211. NTSTATUS Status = STATUS_SUCCESS;
  212. PKSSTREAM_POINTER Leading;
  213. Leading = KsPinGetLeadingEdgeStreamPointer (
  214. m_Pin,
  215. KSSTREAM_POINTER_STATE_LOCKED
  216. );
  217. while (NT_SUCCESS (Status) && Leading) {
  218. PKSSTREAM_POINTER ClonePointer;
  219. PSTREAM_POINTER_CONTEXT SPContext;
  220. //
  221. // For optimization sake in this particular sample, I will only keep
  222. // one clone stream pointer per frame. This complicates the logic
  223. // here but simplifies the completions.
  224. //
  225. // I'm also choosing to do this since I need to keep track of the
  226. // virtual addresses corresponding to each mapping since I'm faking
  227. // DMA. It simplifies that too.
  228. //
  229. if (!m_PreviousStreamPointer) {
  230. //
  231. // First thing we need to do is clone the leading edge. This allows
  232. // us to keep reference on the frames while they're in DMA.
  233. //
  234. Status = KsStreamPointerClone (
  235. Leading,
  236. NULL,
  237. sizeof (STREAM_POINTER_CONTEXT),
  238. &ClonePointer
  239. );
  240. //
  241. // I use this for easy chunking of the buffer. We're not really
  242. // dealing with physical addresses. This keeps track of what
  243. // virtual address in the buffer the current scatter / gather
  244. // mapping corresponds to for the fake hardware.
  245. //
  246. if (NT_SUCCESS (Status)) {
  247. //
  248. // Set the stream header data used to 0. We update this
  249. // in the DMA completions. For queues with DMA, we must
  250. // update this field ourselves.
  251. //
  252. ClonePointer -> StreamHeader -> DataUsed = 0;
  253. SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
  254. (ClonePointer -> Context);
  255. SPContext -> BufferVirtual =
  256. reinterpret_cast <PUCHAR> (
  257. ClonePointer -> StreamHeader -> Data
  258. );
  259. }
  260. } else {
  261. ClonePointer = m_PreviousStreamPointer;
  262. SPContext = reinterpret_cast <PSTREAM_POINTER_CONTEXT>
  263. (ClonePointer -> Context);
  264. Status = STATUS_SUCCESS;
  265. }
  266. //
  267. // If the clone failed, likely we're out of resources. Break out
  268. // of the loop for now. We may end up starving DMA.
  269. //
  270. if (!NT_SUCCESS (Status)) {
  271. KsStreamPointerUnlock (Leading, FALSE);
  272. break;
  273. }
  274. //
  275. // Program the fake hardware. I would use Clone -> OffsetOut.*, but
  276. // because of the optimization of one stream pointer per frame, it
  277. // doesn't make complete sense.
  278. //
  279. ULONG MappingsUsed =
  280. m_Device -> ProgramScatterGatherMappings (
  281. &(SPContext -> BufferVirtual),
  282. Leading -> OffsetOut.Mappings,
  283. Leading -> OffsetOut.Remaining
  284. );
  285. //
  286. // In order to keep one clone per frame and simplify the fake DMA
  287. // logic, make a check to see if we completely used the mappings in
  288. // the leading edge. Set a flag.
  289. //
  290. if (MappingsUsed == Leading -> OffsetOut.Remaining) {
  291. m_PreviousStreamPointer = NULL;
  292. } else {
  293. m_PreviousStreamPointer = ClonePointer;
  294. }
  295. if (MappingsUsed) {
  296. //
  297. // If any mappings were added to scatter / gather queues,
  298. // advance the leading edge by that number of mappings. If
  299. // we run off the end of the queue, Status will be
  300. // STATUS_DEVICE_NOT_READY. Otherwise, the leading edge will
  301. // point to a new frame. The previous one will not have been
  302. // dismissed (unless "DMA" completed) since there's a clone
  303. // pointer referencing the frames.
  304. //
  305. Status =
  306. KsStreamPointerAdvanceOffsets (
  307. Leading,
  308. 0,
  309. MappingsUsed,
  310. FALSE
  311. );
  312. } else {
  313. //
  314. // The hardware was incapable of adding more entries. The S/G
  315. // table is full.
  316. //
  317. Status = STATUS_PENDING;
  318. break;
  319. }
  320. }
  321. //
  322. // If the leading edge failed to lock (this is always possible, remember
  323. // that locking CAN occassionally fail), don't blow up passing NULL
  324. // into KsStreamPointerUnlock. Also, set m_PendIo to kick us later...
  325. //
  326. if (!Leading) {
  327. m_PendIo = TRUE;
  328. //
  329. // If the lock failed, there's no point in getting called back
  330. // immediately. The lock could fail due to insufficient memory,
  331. // etc... In this case, we don't want to get called back immediately.
  332. // Return pending. The m_PendIo flag will cause us to get kicked
  333. // later.
  334. //
  335. Status = STATUS_PENDING;
  336. }
  337. //
  338. // If we didn't run the leading edge off the end of the queue, unlock it.
  339. //
  340. if (NT_SUCCESS (Status) && Leading) {
  341. KsStreamPointerUnlock (Leading, FALSE);
  342. } else {
  343. //
  344. // DEVICE_NOT_READY indicates that the advancement ran off the end
  345. // of the queue. We couldn't lock the leading edge.
  346. //
  347. if (Status == STATUS_DEVICE_NOT_READY) Status = STATUS_SUCCESS;
  348. }
  349. //
  350. // If we failed with something that requires pending, set the pending I/O
  351. // flag so we know we need to start it again in a completion DPC.
  352. //
  353. if (!NT_SUCCESS (Status) || Status == STATUS_PENDING) {
  354. m_PendIo = TRUE;
  355. }
  356. return Status;
  357. }
  358. /*************************************************/
  359. NTSTATUS
  360. CCapturePin::
  361. CleanupReferences (
  362. )
  363. /*++
  364. Routine Description:
  365. Clean up any references we're holding on frames after we abruptly
  366. stop the hardware.
  367. Arguments:
  368. None
  369. Return Value:
  370. Success / Failure
  371. --*/
  372. {
  373. PAGED_CODE();
  374. PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin);
  375. PKSSTREAM_POINTER NextClone = NULL;
  376. //
  377. // Walk through the clones, deleting them, and setting DataUsed to
  378. // zero since we didn't use any data!
  379. //
  380. while (Clone) {
  381. NextClone = KsStreamPointerGetNextClone (Clone);
  382. Clone -> StreamHeader -> DataUsed = 0;
  383. KsStreamPointerDelete (Clone);
  384. Clone = NextClone;
  385. }
  386. return STATUS_SUCCESS;
  387. }
  388. /*************************************************/
  389. NTSTATUS
  390. CCapturePin::
  391. SetState (
  392. IN KSSTATE ToState,
  393. IN KSSTATE FromState
  394. )
  395. /*++
  396. Routine Description:
  397. This is called when the caputre pin transitions state. The routine
  398. attempts to acquire / release any hardware resources and start up
  399. or shut down capture based on the states we are transitioning to
  400. and away from.
  401. Arguments:
  402. ToState -
  403. The state we're transitioning to
  404. FromState -
  405. The state we're transitioning away from
  406. Return Value:
  407. Success / Failure
  408. --*/
  409. {
  410. PAGED_CODE();
  411. NTSTATUS Status = STATUS_SUCCESS;
  412. switch (ToState) {
  413. case KSSTATE_STOP:
  414. //
  415. // First, stop the hardware if we actually did anything to it.
  416. //
  417. if (m_HardwareState != HardwareStopped) {
  418. Status = m_Device -> Stop ();
  419. ASSERT (NT_SUCCESS (Status));
  420. m_HardwareState = HardwareStopped;
  421. }
  422. //
  423. // We've stopped the "fake hardware". It has cleared out
  424. // it's scatter / gather tables and will no longer be
  425. // completing clones. We had locks on some frames that were,
  426. // however, in hardware. This will clean them up. An
  427. // alternative location would be in the reset dispatch.
  428. // Note, however, that the reset dispatch can occur in any
  429. // state and this should be understood.
  430. //
  431. // Some hardware may fill all S/G mappings before stopping...
  432. // in this case, you may not have to do this. The
  433. // "fake hardware" here simply stops filling mappings and
  434. // cleans its scatter / gather tables out on the Stop call.
  435. //
  436. Status = CleanupReferences ();
  437. //
  438. // Release any hardware resources related to this pin.
  439. //
  440. if (m_AcquiredResources) {
  441. //
  442. // If we got an interface to the clock, we must release it.
  443. //
  444. if (m_Clock) {
  445. m_Clock -> Release ();
  446. m_Clock = NULL;
  447. }
  448. m_Device -> ReleaseHardwareResources (
  449. );
  450. m_AcquiredResources = FALSE;
  451. }
  452. break;
  453. case KSSTATE_ACQUIRE:
  454. //
  455. // Acquire any hardware resources related to this pin. We should
  456. // only acquire them here -- **NOT** at filter create time.
  457. // This means we do not fail creation of a filter because of
  458. // limited hardware resources.
  459. //
  460. if (FromState == KSSTATE_STOP) {
  461. Status = m_Device -> AcquireHardwareResources (
  462. this,
  463. m_TransportInfo
  464. );
  465. if (NT_SUCCESS (Status)) {
  466. m_AcquiredResources = TRUE;
  467. //
  468. // Attempt to get an interface to the master clock.
  469. // This will fail if one has not been assigned. Since
  470. // one must be assigned while the pin is still in
  471. // KSSTATE_STOP, this is a guranteed method of getting
  472. // the clock should one be assigned.
  473. //
  474. if (!NT_SUCCESS (
  475. KsPinGetReferenceClockInterface (
  476. m_Pin,
  477. &m_Clock
  478. )
  479. )) {
  480. //
  481. // If we could not get an interface to the clock,
  482. // don't use one.
  483. //
  484. m_Clock = NULL;
  485. }
  486. } else {
  487. m_AcquiredResources = FALSE;
  488. }
  489. } else {
  490. //
  491. // Standard transport pins will always receive transitions in
  492. // +/- 1 manner. This means we'll always see a PAUSE->ACQUIRE
  493. // transition before stopping the pin.
  494. //
  495. // The below is done because on DirectX 8.0, when the pin gets
  496. // a message to stop, the queue is inaccessible. The reset
  497. // which comes on every stop happens after this (at which time
  498. // the queue is inaccessible also). So, for compatibility with
  499. // DirectX 8.0, I am stopping the "fake" hardware at this
  500. // point and cleaning up all references we have on frames. See
  501. // the comments above regarding the CleanupReferences call.
  502. //
  503. // If this sample were targeting XP only, the below code would
  504. // not be here. Again, I only do this so the sample does not
  505. // hang when it is stopped running on a configuration such as
  506. // Win2K + DX8.
  507. //
  508. if (m_HardwareState != HardwareStopped) {
  509. Status = m_Device -> Stop ();
  510. ASSERT (NT_SUCCESS (Status));
  511. m_HardwareState = HardwareStopped;
  512. }
  513. Status = CleanupReferences ();
  514. }
  515. break;
  516. case KSSTATE_PAUSE:
  517. //
  518. // Stop the hardware simulation if we're coming down from run.
  519. //
  520. if (FromState == KSSTATE_RUN) {
  521. Status = m_Device -> Pause (TRUE);
  522. if (NT_SUCCESS (Status)) {
  523. m_HardwareState = HardwarePaused;
  524. }
  525. }
  526. break;
  527. case KSSTATE_RUN:
  528. //
  529. // Start the hardware simulation or unpause it depending on
  530. // whether we're initially running or we've paused and restarted.
  531. //
  532. if (m_HardwareState == HardwarePaused) {
  533. Status = m_Device -> Pause (FALSE);
  534. } else {
  535. Status = m_Device -> Start ();
  536. }
  537. if (NT_SUCCESS (Status)) {
  538. m_HardwareState = HardwareRunning;
  539. }
  540. break;
  541. }
  542. return Status;
  543. }
  544. /**************************************************************************
  545. LOCKED CODE
  546. **************************************************************************/
  547. #ifdef ALLOC_PRAGMA
  548. #pragma code_seg()
  549. #endif // ALLOC_PRAGMA
  550. void
  551. CCapturePin::
  552. CompleteMappings (
  553. IN ULONG NumMappings
  554. )
  555. /*++
  556. Routine Description:
  557. Called to notify the pin that a given number of scatter / gather
  558. mappings have completed. Let the buffers go if possible.
  559. We're called at DPC.
  560. Arguments:
  561. NumMappings -
  562. The number of mappings that have completed.
  563. Return Value:
  564. None
  565. --*/
  566. {
  567. ULONG MappingsRemaining = NumMappings;
  568. //
  569. // Walk through the clones list and delete clones whose time has come.
  570. // The list is guaranteed to be kept in the order they were cloned.
  571. //
  572. PKSSTREAM_POINTER Clone = KsPinGetFirstCloneStreamPointer (m_Pin);
  573. while (MappingsRemaining && Clone) {
  574. PKSSTREAM_POINTER NextClone = KsStreamPointerGetNextClone (Clone);
  575. //
  576. // Count up the number of bytes we've completed and mark this
  577. // in the Stream Header. In mapped queues
  578. // (KSPIN_FLAG_GENERATE_MAPPINGS), this is the responsibility of
  579. // the minidriver. In non-mapped queues, AVStream performs this.
  580. //
  581. ULONG MappingsToCount =
  582. (MappingsRemaining > Clone -> OffsetOut.Remaining) ?
  583. Clone -> OffsetOut.Remaining :
  584. MappingsRemaining;
  585. //
  586. // Update DataUsed according to the mappings.
  587. //
  588. for (ULONG CurMapping = 0; CurMapping < MappingsToCount; CurMapping++) {
  589. Clone -> StreamHeader -> DataUsed +=
  590. Clone -> OffsetOut.Mappings [CurMapping].ByteCount;
  591. }
  592. //
  593. // If we have completed all remaining mappings in this clone, it
  594. // is an indication that the clone is ready to be deleted and the
  595. // buffer released. Set anything required in the stream header which
  596. // has not yet been set. If we have a clock, we can timestamp the
  597. // sample.
  598. //
  599. if (MappingsRemaining >= Clone -> OffsetOut.Remaining) {
  600. Clone -> StreamHeader -> Duration =
  601. m_TransportInfo -> AvgTimePerFrame;
  602. Clone -> StreamHeader -> PresentationTime.Numerator =
  603. Clone -> StreamHeader -> PresentationTime.Denominator = 1;
  604. //
  605. // If a clock has been assigned, timestamp the packets with the
  606. // time shown on the clock.
  607. //
  608. if (m_Clock) {
  609. LONGLONG ClockTime = m_Clock -> GetTime ();
  610. Clone -> StreamHeader -> PresentationTime.Time = ClockTime;
  611. Clone -> StreamHeader -> OptionsFlags =
  612. KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  613. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  614. } else {
  615. //
  616. // If there is no clock, don't time stamp the packets.
  617. //
  618. Clone -> StreamHeader -> PresentationTime.Time = 0;
  619. }
  620. //
  621. // If all of the mappings in this clone have been completed,
  622. // delete the clone. We've already updated DataUsed above.
  623. //
  624. MappingsRemaining -= Clone -> OffsetOut.Remaining;
  625. KsStreamPointerDelete (Clone);
  626. } else {
  627. //
  628. // If only part of the mappings in this clone have been completed,
  629. // update the pointers. Since we're guaranteed this won't advance
  630. // to a new frame by the check above, it won't fail.
  631. //
  632. KsStreamPointerAdvanceOffsets (
  633. Clone,
  634. 0,
  635. MappingsRemaining,
  636. FALSE
  637. );
  638. MappingsRemaining = 0;
  639. }
  640. //
  641. // Go to the next clone.
  642. //
  643. Clone = NextClone;
  644. }
  645. //
  646. // If we've used all the mappings in hardware and pended, we can kick
  647. // processing to happen again if we've completed mappings.
  648. //
  649. if (m_PendIo) {
  650. m_PendIo = TRUE;
  651. KsPinAttemptProcessing (m_Pin, TRUE);
  652. }
  653. }
  654. /**************************************************************************
  655. DISPATCH AND DESCRIPTOR LAYOUT
  656. **************************************************************************/
  657. #define TS_PAYLOAD 188
  658. #define TS_PACKETS_PER_BUFFER 312
  659. //
  660. // This is the data range description of the capture output pin.
  661. //
  662. const
  663. KSDATARANGE FormatCaptureOut =
  664. {
  665. // insert the KSDATARANGE and KSDATAFORMAT here
  666. {
  667. sizeof( KSDATARANGE), // FormatSize
  668. 0, // Flags - (N/A)
  669. TS_PACKETS_PER_BUFFER * TS_PAYLOAD, // SampleSize
  670. 0, // Reserved
  671. { STATIC_KSDATAFORMAT_TYPE_STREAM }, // MajorFormat
  672. { STATIC_KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT },// SubFormat
  673. { STATIC_KSDATAFORMAT_SPECIFIER_NONE } // Specifier
  674. }
  675. };
  676. //
  677. // This is the data range description of the capture input pin.
  678. //
  679. const
  680. KS_DATARANGE_BDA_TRANSPORT FormatCaptureIn =
  681. {
  682. // insert the KSDATARANGE and KSDATAFORMAT here
  683. {
  684. sizeof( KS_DATARANGE_BDA_TRANSPORT), // FormatSize
  685. 0, // Flags - (N/A)
  686. 0, // SampleSize - (N/A)
  687. 0, // Reserved
  688. { STATIC_KSDATAFORMAT_TYPE_STREAM }, // MajorFormat
  689. { STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT }, // SubFormat
  690. { STATIC_KSDATAFORMAT_SPECIFIER_BDA_TRANSPORT } // Specifier
  691. },
  692. // insert the BDA_TRANSPORT_INFO here
  693. {
  694. TS_PAYLOAD, // ulcbPhyiscalPacket
  695. TS_PACKETS_PER_BUFFER * TS_PAYLOAD, // ulcbPhyiscalFrame
  696. 0, // ulcbPhyiscalFrameAlignment (no requirement)
  697. 0 // AvgTimePerFrame (not known)
  698. }
  699. };
  700. //
  701. // CapturePinDispatch:
  702. //
  703. // This is the dispatch table for the capture pin. It provides notifications
  704. // about creation, closure, processing, data formats, etc...
  705. //
  706. const
  707. KSPIN_DISPATCH
  708. CapturePinDispatch = {
  709. CCapturePin::DispatchCreate, // Pin Create
  710. NULL, // Pin Close
  711. CCapturePin::DispatchProcess, // Pin Process
  712. NULL, // Pin Reset
  713. NULL, // Pin Set Data Format
  714. CCapturePin::DispatchSetState, // Pin Set Device State
  715. NULL, // Pin Connect
  716. NULL, // Pin Disconnect
  717. NULL, // Clock Dispatch
  718. NULL // Allocator Dispatch
  719. };
  720. //
  721. // InputPinDispatch:
  722. //
  723. // This is the dispatch table for the capture pin. It provides notifications
  724. // about creation, closure, processing, data formats, etc...
  725. //
  726. const
  727. KSPIN_DISPATCH
  728. InputPinDispatch = {
  729. CCapturePin::DispatchCreate, // Pin Create
  730. NULL, // Pin Close
  731. NULL, // Pin Process
  732. NULL, // Pin Reset
  733. NULL, // Pin Set Data Format
  734. NULL, // Pin Set Device State
  735. NULL, // Pin Connect
  736. NULL, // Pin Disconnect
  737. NULL, // Clock Dispatch
  738. NULL // Allocator Dispatch
  739. };
  740. //
  741. // CapturePinAllocatorFraming:
  742. //
  743. // This is the simple framing structure for the capture pin. Note that this
  744. // will be modified via KsEdit when the actual capture format is determined.
  745. //
  746. DECLARE_SIMPLE_FRAMING_EX (
  747. CapturePinAllocatorFraming, // FramingExName
  748. STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED), // MemoryType
  749. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  750. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY, // Flags
  751. 8, // Frames
  752. 0, // Alignment
  753. 188 * 312, // MinFrameSize
  754. 188 * 312 // MaxFrameSize
  755. );
  756. //
  757. // CaptureOutPinDataRanges:
  758. //
  759. // This is the list of data ranges supported on the capture output pin.
  760. //
  761. const
  762. PKSDATARANGE
  763. CaptureOutPinDataRanges [CAPTURE_OUT_PIN_DATA_RANGE_COUNT] = {
  764. (PKSDATARANGE) &FormatCaptureOut
  765. };
  766. //
  767. // CaptureInPinDataRanges:
  768. //
  769. // This is the list of data ranges supported on the capture input pin.
  770. //
  771. const
  772. PKSDATARANGE
  773. CaptureInPinDataRanges [CAPTURE_IN_PIN_DATA_RANGE_COUNT] = {
  774. (PKSDATARANGE) &FormatCaptureIn
  775. };