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.

613 lines
18 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 - 1997 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include "strmini.h"
  12. #include "ksmedia.h"
  13. #include "capmain.h"
  14. #ifdef TOSHIBA
  15. #include "bert.h"
  16. #ifdef _FPS_COUNT_
  17. extern ULONG FrameCounter;
  18. extern ULONG InterruptCounter;
  19. #endif//_FPS_COUNT_
  20. #endif//TOSHIBA
  21. #ifdef TOSHIBA
  22. BOOLEAN InterruptAcknowledge( PHW_DEVICE_EXTENSION );
  23. #endif//TOSHIBA
  24. #ifdef TOSHIBA
  25. void ImageSynthXXX (
  26. IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
  27. )
  28. {
  29. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  30. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  31. int StreamNumber = pSrb->StreamObject->StreamNumber;
  32. KS_VIDEOINFOHEADER *pVideoInfoHdr = pStrmEx->pVideoInfoHeader;
  33. UINT biWidth = pVideoInfoHdr->bmiHeader.biWidth;
  34. UINT biHeight = pVideoInfoHdr->bmiHeader.biHeight;
  35. UINT biSizeImage = pVideoInfoHdr->bmiHeader.biSizeImage;
  36. UINT biWidthBytes = KS_DIBWIDTHBYTES (pVideoInfoHdr->bmiHeader);
  37. UINT biBitCount = pVideoInfoHdr->bmiHeader.biBitCount;
  38. UINT LinesToCopy = abs (biHeight);
  39. DWORD biCompression = pVideoInfoHdr->bmiHeader.biCompression;
  40. UINT Line;
  41. PUCHAR pLineBuffer;
  42. PKSSTREAM_HEADER pDataPacket = pSrb->CommandData.DataBufferArray;
  43. PUCHAR pImage = pDataPacket->Data;
  44. ULONG InRPSflag;
  45. ULONG ImageSizeY;
  46. ULONG ImageSizeU;
  47. ULONG ImageSizeV;
  48. DEBUG_ASSERT (pSrb->NumberOfBuffers == 1);
  49. #if 0
  50. // Note: set "ulInDebug = 1" in a debugger to view this output with .ntkern
  51. KdPrint(("\'TsbVcap: ImageSynthBegin\n"));
  52. KdPrint(("\'TsbVcap: biSizeImage=%d, DataPacketLength=%d\n",
  53. biSizeImage, pDataPacket->DataPacketLength));
  54. KdPrint(("\'TsbVcap: biWidth=%d biHeight=%d WidthBytes=%d bpp=%d\n",
  55. biWidth, biHeight, biWidthBytes, biBitCount));
  56. KdPrint(("\'TsbVcap: pImage=%x\n", pImage));
  57. #endif
  58. if (pHwDevExt->Format == FmtYUV12) {
  59. ImageSizeY = biWidth * biHeight;
  60. ImageSizeU = ImageSizeY / 4;
  61. ImageSizeV = ImageSizeY / 4;
  62. } else if (pHwDevExt->Format == FmtYUV9) {
  63. ImageSizeY = biWidth * biHeight;
  64. ImageSizeU = ImageSizeY / 16;
  65. ImageSizeV = ImageSizeY / 16;
  66. } else {
  67. biSizeImage = 0;
  68. return;
  69. }
  70. if (pHwDevExt->dblBufflag) {
  71. InRPSflag = ReadRegUlong(pHwDevExt, BERT_YPTR_REG);
  72. if (InRPSflag == pHwDevExt->pPhysCaptureBufferY.LowPart) {
  73. if (pHwDevExt->Format == FmtYUV12) {
  74. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferY, ImageSizeY );
  75. pImage += ImageSizeY;
  76. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferU, ImageSizeU );
  77. pImage += ImageSizeU;
  78. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferV, ImageSizeV );
  79. } else {
  80. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferY, ImageSizeY );
  81. pImage += ImageSizeY;
  82. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferV, ImageSizeV );
  83. pImage += ImageSizeV;
  84. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferU, ImageSizeU );
  85. }
  86. } else if (InRPSflag == pHwDevExt->pPhysCapBuf2Y.LowPart) {
  87. if (pHwDevExt->Format == FmtYUV12) {
  88. RtlCopyMemory( pImage, pHwDevExt->pCapBuf2Y, ImageSizeY );
  89. pImage += ImageSizeY;
  90. RtlCopyMemory( pImage, pHwDevExt->pCapBuf2U, ImageSizeU );
  91. pImage += ImageSizeU;
  92. RtlCopyMemory( pImage, pHwDevExt->pCapBuf2V, ImageSizeV );
  93. } else {
  94. RtlCopyMemory( pImage, pHwDevExt->pCapBuf2Y, ImageSizeY );
  95. pImage += ImageSizeY;
  96. RtlCopyMemory( pImage, pHwDevExt->pCapBuf2V, ImageSizeV );
  97. pImage += ImageSizeV;
  98. RtlCopyMemory( pImage, pHwDevExt->pCapBuf2U, ImageSizeU );
  99. }
  100. } else {
  101. biSizeImage = 0;
  102. }
  103. } else {
  104. if (pHwDevExt->Format == FmtYUV12) {
  105. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferY, ImageSizeY );
  106. pImage += ImageSizeY;
  107. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferU, ImageSizeU );
  108. pImage += ImageSizeU;
  109. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferV, ImageSizeV );
  110. } else {
  111. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferY, ImageSizeY );
  112. pImage += ImageSizeY;
  113. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferV, ImageSizeV );
  114. pImage += ImageSizeV;
  115. RtlCopyMemory( pImage, pHwDevExt->pCaptureBufferU, ImageSizeU );
  116. }
  117. }
  118. pDataPacket->DataUsed = biSizeImage;
  119. #ifdef _FPS_COUNT_
  120. FrameCounter++;
  121. #endif//_FPS_COUNT_
  122. }
  123. VOID
  124. TransferRoutine(
  125. PHW_DEVICE_EXTENSION pHwDevExt,
  126. int StreamNumber
  127. )
  128. {
  129. PHW_STREAM_REQUEST_BLOCK pSrb;
  130. PSTREAMEX pStrmEx;
  131. PKSSTREAM_HEADER pDataPacket;
  132. PKS_FRAME_INFO pFrameInfo;
  133. pStrmEx = (PSTREAMEX)pHwDevExt->pStrmEx[StreamNumber];
  134. // If we're stopped and the timer is still running, just return.
  135. // This will stop the timer.
  136. if (pStrmEx->KSState == KSSTATE_STOP) {
  137. return;
  138. }
  139. // Find out what time it is, if we're using a clock
  140. if (pStrmEx->hMasterClock ) {
  141. HW_TIME_CONTEXT TimeContext;
  142. TimeContext.HwDeviceExtension = pHwDevExt;
  143. TimeContext.HwStreamObject = pStrmEx->pStreamObject;
  144. TimeContext.Function = TIME_GET_STREAM_TIME;
  145. StreamClassQueryMasterClockSync (
  146. pStrmEx->hMasterClock,
  147. &TimeContext);
  148. pStrmEx->QST_StreamTime = TimeContext.Time;
  149. pStrmEx->QST_Now = TimeContext.SystemTime;
  150. if (pStrmEx->QST_NextFrame == 0) {
  151. pStrmEx->QST_NextFrame = pStrmEx->QST_StreamTime + pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  152. }
  153. #ifdef CREATE_A_FLURRY_OF_TIMING_SPEW
  154. KdPrint(("TsbVcap: Time=%16lx\n", TimeContext.Time));
  155. KdPrint(("TsbVcap: SysTime=%16lx\n", TimeContext.SystemTime));
  156. #endif
  157. }
  158. // Only capture in the RUN state
  159. if (pStrmEx->KSState == KSSTATE_RUN) {
  160. //
  161. // Determine if it is time to capture a frame based on
  162. // how much time has elapsed since capture started.
  163. // If there isn't a clock available, then capture immediately.
  164. //
  165. if ((!pStrmEx->hMasterClock) ||
  166. (pStrmEx->QST_StreamTime >= pStrmEx->QST_NextFrame)) {
  167. // Increment the picture count (usually this is VSYNC count)
  168. pStrmEx->FrameInfo.PictureNumber++;
  169. //
  170. // Get the next queue SRB (if any)
  171. //
  172. pSrb = VideoQueueRemoveSRB (
  173. pHwDevExt,
  174. StreamNumber);
  175. if (pSrb) {
  176. pDataPacket = pSrb->CommandData.DataBufferArray;
  177. pFrameInfo = (PKS_FRAME_INFO) (pDataPacket + 1);
  178. //
  179. // Call the routine which synthesizes images
  180. //
  181. ImageSynthXXX (pSrb);
  182. // Set additional info fields about the data captured such as:
  183. // Frames Captured
  184. // Frames Dropped
  185. // Field Polarity
  186. pStrmEx->FrameInfo.ExtendedHeaderSize = pFrameInfo->ExtendedHeaderSize;
  187. *pFrameInfo = pStrmEx->FrameInfo;
  188. // Init the flags to zero
  189. pDataPacket->OptionsFlags = 0;
  190. // Set the discontinuity flag if frames have been previously
  191. // dropped, and then reset our internal flag
  192. if (pStrmEx->fDiscontinuity) {
  193. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  194. pStrmEx->fDiscontinuity = FALSE;
  195. }
  196. //
  197. // Return the timestamp for the frame
  198. //
  199. pDataPacket->PresentationTime.Numerator = 1;
  200. pDataPacket->PresentationTime.Denominator = 1;
  201. pDataPacket->Duration = pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  202. //
  203. // if we have a master clock AND this is the capture stream
  204. //
  205. if (pStrmEx->hMasterClock && (StreamNumber == 0)) {
  206. pDataPacket->PresentationTime.Time = pStrmEx->QST_StreamTime;
  207. pDataPacket->OptionsFlags |=
  208. KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  209. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID;
  210. }
  211. else {
  212. //
  213. // no clock or the preview stream, so just mark the time as unknown
  214. //
  215. pDataPacket->PresentationTime.Time = 0;
  216. // clear the timestamp valid flags
  217. pDataPacket->OptionsFlags &=
  218. ~(KSSTREAM_HEADER_OPTIONSF_TIMEVALID |
  219. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  220. }
  221. // Every frame we generate is a key frame (aka SplicePoint)
  222. // Delta frames (B or P) should not set this flag
  223. pDataPacket->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
  224. CompleteStreamSRB (pSrb);
  225. } // if we have an SRB
  226. else {
  227. //
  228. // No buffer was available when we should have captured one
  229. // Increment the counter which keeps track of
  230. // dropped frames
  231. pStrmEx->FrameInfo.DropCount++;
  232. // Set the (local) discontinuity flag
  233. // This will cause the next packet processed to have the
  234. // KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY flag set.
  235. pStrmEx->fDiscontinuity = TRUE;
  236. }
  237. // Figure out when to capture the next frame
  238. pStrmEx->QST_NextFrame += pStrmEx->pVideoInfoHeader->AvgTimePerFrame;
  239. } // endif time to capture a frame
  240. } // endif we're running
  241. }
  242. VOID
  243. DeferredRoutine(
  244. PKDPC pDpc,
  245. PDEVICE_OBJECT pDeviceObject,
  246. PIRP pIrpNotUsed,
  247. PVOID Context
  248. )
  249. {
  250. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)Context;
  251. PHW_STREAM_REQUEST_BLOCK pSrb;
  252. PSTREAMEX pStrmEx;
  253. PKSSTREAM_HEADER pDataPacket;
  254. PKS_FRAME_INFO pFrameInfo;
  255. int StreamNumber;
  256. pHwDevExt->DpcRequested = FALSE;
  257. if (pHwDevExt->NeedCameraON == TRUE) {
  258. CameraChkandON(pHwDevExt, MODE_VFW);
  259. KeStallExecutionProcessor(100000); // Wait 100 msec
  260. BertDMARestart(pHwDevExt);
  261. pHwDevExt->bVideoIn = TRUE;
  262. pHwDevExt->NeedCameraON = FALSE;
  263. }
  264. if (pHwDevExt->NeedCameraOFF == TRUE) {
  265. BertDMAEnable(pHwDevExt, FALSE);
  266. pHwDevExt->NeedCameraOFF = FALSE;
  267. }
  268. if (pHwDevExt->bRequestDpc == FALSE) {
  269. return;
  270. }
  271. for (StreamNumber = 0; StreamNumber < MAX_TSBVCAP_STREAMS; StreamNumber++) {
  272. if ( pHwDevExt->pStrmEx[StreamNumber] ) {
  273. TransferRoutine(pHwDevExt, StreamNumber);
  274. }
  275. }
  276. }
  277. #endif//TOSHIBA
  278. /*
  279. ** HwInterrupt()
  280. **
  281. ** Routine is called when an interrupt at the IRQ level specified by the
  282. ** ConfigInfo structure passed to the HwInitialize routine is received.
  283. **
  284. ** Note: IRQs may be shared, so the device should ensure the IRQ received
  285. ** was expected
  286. **
  287. ** Arguments:
  288. **
  289. ** pHwDevEx - the device extension for the hardware interrupt
  290. **
  291. ** Returns:
  292. **
  293. ** Side Effects: none
  294. */
  295. BOOLEAN
  296. HwInterrupt(
  297. IN PHW_DEVICE_EXTENSION pHwDevEx
  298. )
  299. {
  300. #ifdef TOSHIBA
  301. pHwDevEx->bRequestDpc = FALSE;
  302. /*
  303. * call the acknowledge. this will not do any service, but will
  304. * return TRUE if the service routine is to be called.
  305. */
  306. if (!InterruptAcknowledge(pHwDevEx)) {
  307. return(FALSE);
  308. }
  309. /* the isr reckons that it is time to schedule the service
  310. * routine. This is done on a DPC.
  311. */
  312. if( pHwDevEx->bRequestDpc )
  313. {
  314. if (pHwDevEx->DpcRequested) {
  315. KdPrint(("dpc overrun.\n"));
  316. } else {
  317. // KdPrint(("dpc requested.\n"));
  318. pHwDevEx->DpcRequested = TRUE;
  319. IoRequestDpc(pHwDevEx->PDO, NULL, pHwDevEx);
  320. }
  321. }
  322. else
  323. {
  324. KdPrint(("bRequestDpc Flag is False.\n"));
  325. if (pHwDevEx->DpcRequested) {
  326. KdPrint(("dpc overrun.\n"));
  327. } else {
  328. // KdPrint(("dpc requested.\n"));
  329. pHwDevEx->DpcRequested = TRUE;
  330. IoRequestDpc(pHwDevEx->PDO, NULL, pHwDevEx);
  331. }
  332. }
  333. /* everything else is done in dpc routine */
  334. return(TRUE);
  335. #else //TOSHIBA
  336. BOOL fMyIRQ = FALSE;
  337. if (pHwDevEx->IRQExpected)
  338. {
  339. pHwDevEx->IRQExpected = FALSE;
  340. //
  341. // call the routine to handle the IRQ here
  342. //
  343. fMyIRQ = TRUE;
  344. }
  345. //
  346. // returning FALSE indicates that this was not an IRQ for this device, and
  347. // the IRQ dispatcher will pass the IRQ down the chain to the next handler
  348. // for this IRQ level
  349. //
  350. return(fMyIRQ);
  351. #endif//TOSHIBA
  352. }
  353. #ifdef TOSHIBA
  354. /*
  355. * interrupt acknowledge routine. This is called to ack the interrupt
  356. * and re-enable it for next time. It should return TRUE if it is time
  357. * to capture a frame.
  358. */
  359. BOOLEAN
  360. InterruptAcknowledge(PHW_DEVICE_EXTENSION pHwDevExt)
  361. {
  362. LARGE_INTEGER CurrentTime;
  363. ULONG istat;
  364. ULONG intrst;
  365. BOOLEAN bret;
  366. BOOL bSLI;
  367. istat = ReadRegUlong(pHwDevExt, BERT_INTSTAT_REG);
  368. if (0xFFFFFFFF == istat)
  369. return FALSE;
  370. if (!((istat >> 16) & (istat & 0xffff)))
  371. {
  372. return FALSE;
  373. }
  374. intrst = 0x0;
  375. bret = FALSE;
  376. bSLI = FALSE;
  377. if ((istat & RPS_INT_MASK) && (istat & RPS_INT))
  378. {
  379. intrst |= RPS_INT_RESET;
  380. bret = TRUE;
  381. if (pHwDevExt->bVideoIn)
  382. {
  383. pHwDevExt->bRequestDpc = TRUE;
  384. }
  385. #ifdef _FPS_COUNT_
  386. InterruptCounter++;
  387. #endif//_FPS_COUNT_
  388. }
  389. if ((istat & FIELD_INT_MASK) && (istat & FIELD_INT))
  390. {
  391. intrst |= FIELD_INT_RESET;
  392. bret = TRUE;
  393. }
  394. if ((istat & SYNC_LOCK_INT_MASK) && (istat & SYNC_LOCK_INT))
  395. {
  396. intrst |= SYNC_LOCK_INT_RESET;
  397. bret = TRUE;
  398. bSLI = TRUE;
  399. }
  400. if ((istat & FIFO_OVERFLOW_INT_MASK) && (istat & FIFO_OVERFLOW_INT))
  401. {
  402. intrst |= FIFO_OVERFLOW_INT_RESET;
  403. bret = TRUE;
  404. }
  405. if ((istat & LINE_TIMEOUT_INT_MASK) && (istat & LINE_TIMEOUT_INT))
  406. {
  407. intrst |= LINE_TIMEOUT_INT_RESET;
  408. bret = TRUE;
  409. }
  410. if ((istat & RPS_OOB_INT_MASK) && (istat & RPS_OOB_INT))
  411. {
  412. intrst |= RPS_OOB_INT_RESET;
  413. bret = TRUE;
  414. }
  415. if ((istat & REG_UNDEF_INT_MASK) && (istat & REG_UNDEF_INT))
  416. {
  417. intrst |= REG_UNDEF_INT_RESET;
  418. bret = TRUE;
  419. }
  420. if ((istat & SLOW_CLOCK_INT_MASK) && (istat & SLOW_CLOCK_INT))
  421. {
  422. intrst |= SLOW_CLOCK_INT_RESET;
  423. bret = TRUE;
  424. if (pHwDevExt->bVideoIn)
  425. {
  426. if ((ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & ERPS) == 0x0)
  427. {
  428. WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ERPS | CKRE | CKMD));
  429. }
  430. }
  431. }
  432. if ((istat & OVER_RUN_INT_MASK) && (istat & OVER_RUN_INT))
  433. {
  434. intrst |= OVER_RUN_INT_RESET;
  435. bret = TRUE;
  436. if (pHwDevExt->bVideoIn)
  437. {
  438. if ((ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & ERPS) == 0x0)
  439. {
  440. WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ERPS | CKRE | CKMD));
  441. }
  442. }
  443. }
  444. if ((istat & REG_LOAD_INT_MASK) && (istat & REG_LOAD_INT))
  445. {
  446. intrst |= REG_LOAD_INT_RESET;
  447. bret = TRUE;
  448. if (pHwDevExt->bVideoIn)
  449. {
  450. if ((ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & ERPS) == 0x0)
  451. {
  452. WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ERPS | CKRE | CKMD));
  453. }
  454. }
  455. }
  456. if ((istat & LINE_SYNC_INT_MASK) && (istat & LINE_SYNC_INT))
  457. {
  458. intrst |= LINE_SYNC_INT_RESET;
  459. bret = TRUE;
  460. }
  461. if ((istat & IIC_ERROR_INT_MASK) && (istat & IIC_ERROR_INT))
  462. {
  463. intrst |= IIC_ERROR_INT_RESET;
  464. bret = TRUE;
  465. if (pHwDevExt->bVideoIn)
  466. {
  467. if ((ReadRegUlong(pHwDevExt, BERT_CAPSTAT_REG) & ERPS) == 0x0)
  468. {
  469. WriteRegUlong(pHwDevExt, BERT_CAPSTAT_REG, (ERPS | CKRE | CKMD));
  470. }
  471. }
  472. }
  473. if ((istat & PCI_PARITY_ERROR_INT_MASK) && (istat & PCI_PARITY_ERROR_INT))
  474. {
  475. intrst |= PCI_PARITY_ERROR_INT_RESET;
  476. bret = TRUE;
  477. }
  478. if ((istat & PCI_ACCESS_ERROR_INT_MASK) && (istat & PCI_ACCESS_ERROR_INT))
  479. {
  480. intrst |= PCI_ACCESS_ERROR_INT_RESET;
  481. bret = TRUE;
  482. }
  483. if ((istat & SPARE_INT_MASK) && (istat & SPARE_INT))
  484. {
  485. intrst |= SPARE_INT_RESET;
  486. bret = TRUE;
  487. }
  488. if (bret)
  489. {
  490. WriteRegUlong(pHwDevExt, BERT_INTRST_REG, intrst);
  491. }
  492. if (bSLI)
  493. {
  494. if (BertIsLocked(pHwDevExt)) // Mount Camera
  495. {
  496. pHwDevExt->NeedCameraON = TRUE;
  497. KdPrint(("Mount Camera\n"));
  498. }
  499. else // Remove Camera
  500. {
  501. pHwDevExt->NeedCameraOFF = TRUE;
  502. pHwDevExt->bVideoIn = FALSE;
  503. KdPrint(("Remove Camera\n"));
  504. }
  505. }
  506. return bret;
  507. }
  508. #endif//TOSHIBA