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.

553 lines
15 KiB

  1. //==========================================================================;
  2. //
  3. // CWDMVideoStream - WDM Video Stream base class implementation
  4. //
  5. // $Date: 05 Aug 1998 11:10:52 $
  6. // $Revision: 1.0 $
  7. // $Author: Tashjian $
  8. //
  9. // $Copyright: (c) 1997 - 1998 ATI Technologies Inc. All Rights Reserved. $
  10. //
  11. //==========================================================================;
  12. extern "C"
  13. {
  14. #include "strmini.h"
  15. #include "ksmedia.h"
  16. }
  17. #include "wdmvdec.h"
  18. #include "wdmdrv.h"
  19. #include "device.h"
  20. #include "aticonfg.h"
  21. #include "capdebug.h"
  22. #include "StrmInfo.h"
  23. /*
  24. ** VideoReceiveDataPacket()
  25. **
  26. ** Receives Video data packet commands
  27. **
  28. ** Arguments:
  29. **
  30. ** pSrb - Stream request block for the Video stream
  31. **
  32. ** Returns: nothing
  33. **
  34. ** Side Effects: none
  35. */
  36. VOID STREAMAPI VideoReceiveDataPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
  37. {
  38. CWDMVideoStream * pVideoStream = (CWDMVideoStream *)pSrb->StreamObject->HwStreamExtension;
  39. pVideoStream->VideoReceiveDataPacket(pSrb);
  40. }
  41. /*
  42. ** VideoReceiveCtrlPacket()
  43. **
  44. ** Receives packet commands that control the Video stream
  45. **
  46. ** Arguments:
  47. **
  48. ** pSrb - The stream request block for the Video stream
  49. **
  50. ** Returns: nothing
  51. **
  52. ** Side Effects: none
  53. */
  54. VOID STREAMAPI VideoReceiveCtrlPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
  55. {
  56. CWDMVideoStream * pVideoStream = (CWDMVideoStream *)pSrb->StreamObject->HwStreamExtension;
  57. pVideoStream->VideoReceiveCtrlPacket(pSrb);
  58. }
  59. void CWDMVideoStream::TimeoutPacket(IN OUT PHW_STREAM_REQUEST_BLOCK pSrb)
  60. {
  61. if (m_KSState == KSSTATE_STOP || !m_pVideoDecoder->PreEventOccurred())
  62. {
  63. DBGTRACE(("Suspicious timeout. SRB %8x. \n", pSrb));
  64. }
  65. }
  66. CWDMVideoStream::CWDMVideoStream(PHW_STREAM_OBJECT pStreamObject,
  67. CWDMVideoDecoder * pVideoDecoder,
  68. PUINT puiErrorCode)
  69. : m_pStreamObject(pStreamObject),
  70. m_pVideoDecoder(pVideoDecoder)
  71. {
  72. DBGTRACE(("CWDMVideoStream::CWDMVideoStream\n"));
  73. m_pVideoPort = m_pVideoDecoder->GetVideoPort();
  74. m_pDevice = m_pVideoDecoder->GetDevice();
  75. KeInitializeSpinLock(&m_ctrlSrbLock);
  76. InitializeListHead(&m_ctrlSrbQueue);
  77. m_KSState = KSSTATE_STOP;
  78. *puiErrorCode = WDMMINI_NOERROR;
  79. }
  80. CWDMVideoStream::~CWDMVideoStream()
  81. {
  82. KIRQL Irql;
  83. DBGTRACE(("CWDMVideoStream::~CWDMVideoStream()\n"));
  84. KeAcquireSpinLock(&m_ctrlSrbLock, &Irql);
  85. if (!IsListEmpty(&m_ctrlSrbQueue))
  86. {
  87. TRAP();
  88. }
  89. KeReleaseSpinLock(&m_ctrlSrbLock, Irql);
  90. }
  91. /*
  92. ** VideoReceiveDataPacket()
  93. **
  94. ** Receives Video data packet commands
  95. **
  96. ** Arguments:
  97. **
  98. ** pSrb - Stream request block for the Video stream
  99. **
  100. ** Returns: nothing
  101. **
  102. ** Side Effects: none
  103. */
  104. VOID STREAMAPI CWDMVideoStream::VideoReceiveDataPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
  105. {
  106. ASSERT(pSrb->StreamObject->StreamNumber == STREAM_AnalogVideoInput);
  107. ASSERT(pSrb->Irp->MdlAddress);
  108. DBGINFO(("Receiving SD---- SRB=%x\n", pSrb));
  109. pSrb->Status = STATUS_SUCCESS;
  110. switch (pSrb->Command) {
  111. case SRB_WRITE_DATA:
  112. m_pVideoDecoder->ReceivePacket(pSrb);
  113. break;
  114. default:
  115. //
  116. // invalid / unsupported command. Fail it as such
  117. //
  118. TRAP();
  119. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  120. StreamClassStreamNotification( StreamRequestComplete,
  121. pSrb->StreamObject,
  122. pSrb);
  123. break;
  124. }
  125. }
  126. /*
  127. ** VideoReceiveCtrlPacket()
  128. **
  129. ** Receives packet commands that control the Video stream
  130. **
  131. ** Arguments:
  132. **
  133. ** pSrb - The stream request block for the Video stream
  134. **
  135. ** Returns: nothing
  136. **
  137. ** Side Effects: none
  138. */
  139. VOID STREAMAPI CWDMVideoStream::VideoReceiveCtrlPacket(IN PHW_STREAM_REQUEST_BLOCK pSrb)
  140. {
  141. KIRQL Irql;
  142. PSRB_DATA_EXTENSION pSrbExt;
  143. KeAcquireSpinLock(&m_ctrlSrbLock, &Irql);
  144. if (m_processingCtrlSrb)
  145. {
  146. pSrbExt = (PSRB_DATA_EXTENSION)pSrb->SRBExtension;
  147. pSrbExt->pSrb = pSrb;
  148. InsertTailList(&m_ctrlSrbQueue, &pSrbExt->srbListEntry);
  149. KeReleaseSpinLock(&m_ctrlSrbLock, Irql);
  150. return;
  151. }
  152. m_processingCtrlSrb = TRUE;
  153. KeReleaseSpinLock(&m_ctrlSrbLock, Irql);
  154. // This will run until the queue is empty
  155. while (TRUE)
  156. {
  157. // Assume success. Might be changed below
  158. pSrb->Status = STATUS_SUCCESS;
  159. switch (pSrb->Command)
  160. {
  161. case SRB_GET_STREAM_STATE:
  162. VideoGetState(pSrb);
  163. break;
  164. case SRB_SET_STREAM_STATE:
  165. {
  166. BOOL bVPConnected, bVPVBIConnected;
  167. PDEVICE_DATA_EXTENSION pDevExt = (PDEVICE_DATA_EXTENSION)pSrb->HwDeviceExtension;
  168. bVPConnected = pDevExt->CWDMDecoder.IsVideoPortPinConnected();
  169. bVPVBIConnected = pDevExt->CDevice.IsVBIEN();
  170. VideoSetState(pSrb, bVPConnected, bVPVBIConnected);
  171. }
  172. break;
  173. case SRB_GET_STREAM_PROPERTY:
  174. VideoGetProperty(pSrb);
  175. break;
  176. case SRB_SET_STREAM_PROPERTY:
  177. VideoSetProperty(pSrb);
  178. break;
  179. case SRB_INDICATE_MASTER_CLOCK:
  180. VideoIndicateMasterClock (pSrb);
  181. break;
  182. case SRB_PROPOSE_DATA_FORMAT:
  183. // This may be inappropriate for Bt829. CHECK!!!
  184. DBGERROR(("Propose Data format\n"));
  185. if (!(AdapterVerifyFormat (
  186. pSrb->CommandData.OpenFormat,
  187. pSrb->StreamObject->StreamNumber))) {
  188. pSrb->Status = STATUS_NO_MATCH;
  189. }
  190. break;
  191. default:
  192. TRAP();
  193. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  194. break;
  195. }
  196. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  197. KeAcquireSpinLock(&m_ctrlSrbLock, &Irql);
  198. if (IsListEmpty(&m_ctrlSrbQueue))
  199. {
  200. m_processingCtrlSrb = FALSE;
  201. KeReleaseSpinLock(&m_ctrlSrbLock, Irql);
  202. return;
  203. }
  204. else
  205. {
  206. pSrbExt = (PSRB_DATA_EXTENSION)RemoveHeadList(&m_ctrlSrbQueue);
  207. KeReleaseSpinLock(&m_ctrlSrbLock, Irql);
  208. pSrb = pSrbExt->pSrb;
  209. }
  210. }
  211. }
  212. /*
  213. ** VideoSetProperty()
  214. **
  215. ** Routine to process video property requests
  216. **
  217. ** Arguments:
  218. **
  219. ** pSrb - pointer to the stream request block for properties
  220. **
  221. ** Returns:
  222. **
  223. ** Side Effects: none
  224. */
  225. VOID CWDMVideoStream::VideoSetProperty(PHW_STREAM_REQUEST_BLOCK pSrb)
  226. {
  227. DBGERROR(("CWDMVideoStream::VideoSetProperty called"));
  228. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  229. }
  230. /*
  231. ** VideoGetProperty()
  232. **
  233. ** Routine to process video property requests
  234. **
  235. ** Arguments:
  236. **
  237. ** pSrb - pointer to the stream request block for properties
  238. **
  239. ** Returns:
  240. **
  241. ** Side Effects: none
  242. */
  243. VOID CWDMVideoStream::VideoGetProperty(PHW_STREAM_REQUEST_BLOCK pSrb)
  244. {
  245. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  246. if (IsEqualGUID (KSPROPSETID_Connection, pSPD->Property->Set)) {
  247. VideoStreamGetConnectionProperty (pSrb);
  248. }
  249. else {
  250. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  251. }
  252. }
  253. /*
  254. ** VideoSetState()
  255. **
  256. ** Sets the current state of the requested stream
  257. **
  258. ** Arguments:
  259. **
  260. ** pSrb - pointer to the stream request block for properties
  261. **
  262. ** Returns:
  263. **
  264. ** Side Effects: none
  265. */
  266. VOID CWDMVideoStream::VideoSetState(PHW_STREAM_REQUEST_BLOCK pSrb, BOOL bVPConnected, BOOL bVPVBIConnected)
  267. {
  268. //
  269. // For each stream, the following states are used:
  270. //
  271. // Stop: Absolute minimum resources are used. No outstanding IRPs.
  272. // Pause: Getting ready to run. Allocate needed resources so that
  273. // the eventual transition to Run is as fast as possible.
  274. // SRBs will be queued at either the Stream class or in your
  275. // driver.
  276. // Run: Streaming.
  277. //
  278. // Moving to Stop or Run ALWAYS transitions through Pause, so that ONLY
  279. // the following transitions are possible:
  280. //
  281. // Stop -> Pause
  282. // Pause -> Run
  283. // Run -> Pause
  284. // Pause -> Stop
  285. //
  286. // Note that it is quite possible to transition repeatedly between states:
  287. // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop
  288. //
  289. DBGINFO(("CWDMVideoStream::VideoSetState for stream %d\n", pSrb->StreamObject->StreamNumber));
  290. pSrb->Status = STATUS_SUCCESS;
  291. switch (pSrb->CommandData.StreamState)
  292. {
  293. case KSSTATE_STOP:
  294. DBGINFO((" state KSSTATE_STOP"));
  295. // Reset the overridden flag so that the next time we go to the
  296. // Run state, output will be enabled (unless the app overrides
  297. // it again later). We should really do this after the graph
  298. // has been stopped so that if a filter that has yet to be stopped
  299. // cleans up by clearing the flag, it is not considered to be
  300. // overriding it again. Since we are not called after the graph
  301. // has been fully stopped, this is the best we can do.
  302. //
  303. // An alternative (and probably less confusing) approach is to
  304. // leave the overridden flag set and force the app to control
  305. // the output enabled feature if it changes it once.
  306. //
  307. // We have decided to follow the latter approach.
  308. // m_pDevice->SetOutputEnabledOverridden(FALSE);
  309. break;
  310. case KSSTATE_ACQUIRE:
  311. DBGINFO((" state KSSTATE_ACQUIRE"));
  312. ASSERT(m_KSState == KSSTATE_STOP);
  313. break;
  314. case KSSTATE_PAUSE:
  315. DBGINFO((" state KSSTATE_PAUSE"));
  316. if (m_pVideoDecoder->PreEventOccurred() &&
  317. (!m_pDevice->IsOutputEnabledOverridden() || m_pDevice->IsOutputEnabled()) &&
  318. (m_KSState == KSSTATE_STOP || m_KSState == KSSTATE_ACQUIRE))
  319. {
  320. DBGERROR(("VidStrm Pause: Overridden = %d, OutputEnabled = %d",
  321. m_pDevice->IsOutputEnabledOverridden(),
  322. m_pDevice->IsOutputEnabled()
  323. ));
  324. pSrb->Status = STATUS_UNSUCCESSFUL;
  325. }
  326. break;
  327. case KSSTATE_RUN:
  328. DBGINFO((" state KSSTATE_RUN"));
  329. ASSERT(m_KSState == KSSTATE_ACQUIRE || m_KSState == KSSTATE_PAUSE);
  330. if (m_pVideoDecoder->PreEventOccurred() &&
  331. (!m_pDevice->IsOutputEnabledOverridden() || m_pDevice->IsOutputEnabled()))
  332. {
  333. DBGERROR(("VidStrm Run: Overridden = %d, OutputEnabled = %d",
  334. m_pDevice->IsOutputEnabledOverridden(),
  335. m_pDevice->IsOutputEnabled()
  336. ));
  337. pSrb->Status = STATUS_UNSUCCESSFUL;
  338. }
  339. break;
  340. }
  341. if (pSrb->Status == STATUS_SUCCESS) {
  342. m_KSState = pSrb->CommandData.StreamState;
  343. DBGINFO((" entered\n"));
  344. }
  345. else
  346. DBGINFO((" NOT entered ***\n"));
  347. }
  348. /*
  349. ** VideoGetState()
  350. **
  351. ** Gets the current state of the requested stream
  352. **
  353. ** Arguments:
  354. **
  355. ** pSrb - pointer to the stream request block for properties
  356. **
  357. ** Returns:
  358. **
  359. ** Side Effects: none
  360. */
  361. VOID CWDMVideoStream::VideoGetState(PHW_STREAM_REQUEST_BLOCK pSrb)
  362. {
  363. pSrb->CommandData.StreamState = m_KSState;
  364. pSrb->ActualBytesTransferred = sizeof (KSSTATE);
  365. // A very odd rule:
  366. // When transitioning from stop to pause, DShow tries to preroll
  367. // the graph. Capture sources can't preroll, and indicate this
  368. // by returning VFW_S_CANT_CUE in user mode. To indicate this
  369. // condition from drivers, they must return ERROR_NO_DATA_DETECTED
  370. if (m_KSState == KSSTATE_PAUSE) {
  371. pSrb->Status = STATUS_NO_DATA_DETECTED;
  372. }
  373. }
  374. VOID CWDMVideoStream::VideoStreamGetConnectionProperty (PHW_STREAM_REQUEST_BLOCK pSrb)
  375. {
  376. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  377. PKSALLOCATOR_FRAMING Framing = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  378. ASSERT(pSPD->Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING);
  379. if (pSPD->Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING) {
  380. RtlZeroMemory(Framing, sizeof(KSALLOCATOR_FRAMING));
  381. Framing->RequirementsFlags =
  382. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY |
  383. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  384. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY;
  385. Framing->PoolType = NonPagedPool;
  386. Framing->Frames = 1;
  387. Framing->FrameSize =
  388. pSrb->StreamObject->StreamNumber == STREAM_AnalogVideoInput ?
  389. sizeof(KS_TVTUNER_CHANGE_INFO) : 1;
  390. Framing->FileAlignment = 0;//FILE_QUAD_ALIGNMENT;// PAGE_SIZE - 1;
  391. pSrb->ActualBytesTransferred = sizeof(KSALLOCATOR_FRAMING);
  392. }
  393. else {
  394. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  395. }
  396. }
  397. //==========================================================================;
  398. // Clock Handling Routines
  399. //==========================================================================;
  400. /*
  401. ** VideoIndicateMasterClock ()
  402. **
  403. ** If this stream is not being used as the master clock, this function
  404. ** is used to provide us with a handle to the clock to use.
  405. **
  406. ** Arguments:
  407. **
  408. ** pSrb - pointer to the stream request block for properties
  409. **
  410. ** Returns:
  411. **
  412. ** Side Effects: none
  413. */
  414. VOID CWDMVideoStream::VideoIndicateMasterClock(PHW_STREAM_REQUEST_BLOCK pSrb)
  415. {
  416. m_hMasterClock = pSrb->CommandData.MasterClockHandle;
  417. }
  418. DWORD FAR PASCAL DirectDrawEventCallback(DWORD dwEvent, PVOID pContext, DWORD dwParam1, DWORD dwParam2)
  419. {
  420. CDecoderVideoPort* pCDecoderVideoPort = (CDecoderVideoPort*) pContext;
  421. CWDMVideoPortStream* pCWDMVideoPortStream = (CWDMVideoPortStream*) pContext;
  422. CWDMCaptureStream* pCWDMCaptureStream = (CWDMVideoCaptureStream*) pContext;
  423. switch (dwEvent)
  424. {
  425. case DDNOTIFY_PRERESCHANGE:
  426. pCWDMVideoPortStream->PreResChange();
  427. break;
  428. case DDNOTIFY_POSTRESCHANGE:
  429. pCWDMVideoPortStream->PostResChange();
  430. break;
  431. case DDNOTIFY_PREDOSBOX:
  432. pCWDMVideoPortStream->PreDosBox();
  433. break;
  434. case DDNOTIFY_POSTDOSBOX:
  435. pCWDMVideoPortStream->PostDosBox();
  436. break;
  437. case DDNOTIFY_CLOSECAPTURE:
  438. pCWDMCaptureStream->CloseCapture();
  439. break;
  440. case DDNOTIFY_CLOSEDIRECTDRAW:
  441. pCDecoderVideoPort->CloseDirectDraw();
  442. break;
  443. case DDNOTIFY_CLOSEVIDEOPORT:
  444. pCDecoderVideoPort->CloseVideoPort();
  445. break;
  446. default:
  447. TRAP();
  448. break;
  449. }
  450. return 0;
  451. }