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.

2050 lines
81 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2000
  3. Module Name:
  4. MSDVLowr.c
  5. Abstract:
  6. Interface code with 61883 or 1394 class driver.
  7. Last changed by:
  8. Author: Yee J. Wu
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. $Revision:: $
  13. $Date:: $
  14. --*/
  15. #include "strmini.h"
  16. #include "ksmedia.h"
  17. #include "1394.h"
  18. #include "61883.h"
  19. #include "dbg.h"
  20. #include "msdvfmt.h"
  21. #include "msdvdef.h"
  22. #include "MSDVUtil.h"
  23. #include "MSDVGuts.h"
  24. #include "XPrtDefs.h"
  25. #include "EDevCtrl.h"
  26. extern DV_FORMAT_INFO DVFormatInfoTable[];
  27. extern const GUID KSEVENTSETID_Connection_Local;
  28. //
  29. // Simple function prototype
  30. //
  31. VOID
  32. DVSRBRead(
  33. IN PKSSTREAM_HEADER pStrmHeader,
  34. IN ULONG ulFrameSize,
  35. IN PDVCR_EXTENSION pDevExt,
  36. IN PSTREAMEX pStrmExt,
  37. IN PHW_STREAM_REQUEST_BLOCK pSrb // needs Srb->Status
  38. );
  39. NTSTATUS
  40. DVAttachWriteFrame(
  41. IN PSTREAMEX pStrmExt
  42. );
  43. VOID
  44. DVFormatAttachFrame(
  45. IN KSPIN_DATAFLOW DataFlow,
  46. IN PSTREAMEX pStrmExt,
  47. IN PAV_61883_REQUEST pAVReq,
  48. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  49. IN PSRB_DATA_PACKET pSrbDataPacket,
  50. IN ULONG ulSourceLength, // Packet length in bytes
  51. IN ULONG ulFrameSize,
  52. IN PVOID pFrameBuffer
  53. );
  54. VOID
  55. DVAttachFrameThread(
  56. IN PSTREAMEX pStrmExt
  57. );
  58. VOID
  59. DVTerminateAttachFrameThread(
  60. IN PSTREAMEX pStrmExt
  61. );
  62. #if DBG
  63. ULONG cntInvSrcPkt = 0;
  64. #endif
  65. #if 0 // Enable later
  66. #ifdef ALLOC_PRAGMA
  67. #pragma alloc_text(PAGE, DVSRBRead)
  68. #pragma alloc_text(PAGE, DVFormatAttachFrame)
  69. #pragma alloc_text(PAGE, DVAttachFrameThread)
  70. #pragma alloc_text(PAGE, DVTerminateAttachFrameThread)
  71. #pragma alloc_text(PAGE, DVAttachWriteFrame)
  72. #pragma alloc_text(PAGE, DVFormatAttachFrame)
  73. #endif
  74. #endif
  75. ULONG
  76. DVReadFrameValidate(
  77. IN PCIP_VALIDATE_INFO pInfo
  78. )
  79. /*++
  80. Routine Description:
  81. Used to detect the start of a DV frame. A DV frame is started with a header section.
  82. Return
  83. 0 verified
  84. 1: invallid
  85. --*/
  86. {
  87. if(pInfo->Packet) {
  88. //
  89. // Detect header 0 signature.
  90. //
  91. if(
  92. (pInfo->Packet[0] & DIF_BLK_ID0_SCT_MASK) == 0
  93. && (pInfo->Packet[1] & DIF_BLK_ID1_DSEQ_MASK) == 0
  94. && (pInfo->Packet[2] & DIF_BLK_ID2_DBN_MASK) == 0
  95. ) {
  96. //
  97. // This can be used to detect dynamic format change if this function is called
  98. // to check for data packets always. This may require setting this flag:
  99. // CIP_VALIDATE_ALL_SOURCE instead of CIP_VALIDATE_FIRST_SOURCE
  100. //
  101. #if 0 // DBG
  102. PSRB_DATA_PACKET pSrbDataPacket = pInfo->Context;
  103. PSTREAMEX pStrmExt = pSrbDataPacket->pStrmExt;
  104. PDVCR_EXTENSION pDevExt = pStrmExt->pDevExt;
  105. if((pInfo->Packet[0] & DIF_HEADER_DSF) == 0) {
  106. // Indicate a 10 DIF sequences include in a video frame (525-60)/NTSC.
  107. if(
  108. pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_PAL
  109. || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_PAL
  110. ) {
  111. // Dynamic format changes!!
  112. TRACE(TL_STRM_ERROR|TL_CIP_WARNING,("Detect dynamic format change PAL -> NTSC!\n"));
  113. }
  114. } else {
  115. // Indicate a 12 DIF sequences include in a video frame (625-50)/PAL.
  116. if(
  117. pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_NTSC
  118. || pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_NTSC
  119. ) {
  120. // Dynamic format changes!!
  121. TRACE(TL_STRM_ERROR|TL_CIP_WARNING,("Detect dynamic format change NTSC -> PAL!\n"));
  122. }
  123. }
  124. #endif
  125. // Check TF1, TF2, and TF3: 1: not transmitted; 0:transmitted
  126. // TF1:Audio; TF2:Video; TF3:Subcode; they all need to be 0 to be valid.
  127. if(
  128. (pInfo->Packet[5] & DIF_HEADER_TFn)
  129. || (pInfo->Packet[6] & DIF_HEADER_TFn)
  130. || (pInfo->Packet[7] & DIF_HEADER_TFn)
  131. ) {
  132. TRACE(TL_STRM_ERROR|TL_CIP_WARNING,("\'%d inv src pkts; [%x %x %d %x], [%x %x %x %x]\n",
  133. cntInvSrcPkt,
  134. pInfo->Packet[0],
  135. pInfo->Packet[1],
  136. pInfo->Packet[2],
  137. pInfo->Packet[3],
  138. pInfo->Packet[4],
  139. pInfo->Packet[5],
  140. pInfo->Packet[6],
  141. pInfo->Packet[7]
  142. ));
  143. // Valid header but DIF block for this area is not transmitted.
  144. // Some DV (such as DVCPro) may wait untill its "mecha and servo" to be stable to make these valid.
  145. // This should happen if a graph is in run state before a tape is played (and stablized).
  146. return 1;
  147. }
  148. #if DBG
  149. if(cntInvSrcPkt > 0) {
  150. TRACE(TL_CIP_TRACE,("\'%d inv src pkts; [%x %x %d %x] [%x %x %x %x]\n",
  151. cntInvSrcPkt,
  152. pInfo->Packet[0],
  153. pInfo->Packet[1],
  154. pInfo->Packet[2],
  155. pInfo->Packet[3],
  156. pInfo->Packet[4],
  157. pInfo->Packet[5],
  158. pInfo->Packet[6],
  159. pInfo->Packet[7]
  160. ));
  161. cntInvSrcPkt = 0; // Reset
  162. }
  163. #endif
  164. return 0;
  165. }
  166. else {
  167. #if DBG
  168. //
  169. // To detect invalid src pkt sequence;
  170. // If it exceeded the number of source packet per frame, we need to know about it.
  171. //
  172. PSRB_DATA_PACKET pSrbDataPacket = pInfo->Context;
  173. PSTREAMEX pStrmExt = pSrbDataPacket->pStrmExt;
  174. PDVCR_EXTENSION pDevExt = pStrmExt->pDevExt;
  175. if(++cntInvSrcPkt >= DVFormatInfoTable[pDevExt->VideoFormatIndex].ulSrcPackets) {
  176. TRACE(TL_CIP_TRACE,("(%d) Invalid SrcPkt >= max inv src pkt %d; ID0,1,2 = [%x %x %x]\n",
  177. cntInvSrcPkt,
  178. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulSrcPackets,
  179. pInfo->Packet[0], pInfo->Packet[1], pInfo->Packet[2]
  180. ));
  181. if(DVTraceMask & TL_CIP_TRACE) {
  182. ASSERT(cntInvSrcPkt < DVFormatInfoTable[pDevExt->VideoFormatIndex].ulSrcPackets);
  183. }
  184. cntInvSrcPkt = 0; // Reset
  185. }
  186. else {
  187. TRACE(TL_CIP_INFO,("(%d) Invalid SrcPktSeq; ID0,1,2 = [%x,%x,%x]\n",
  188. cntInvSrcPkt, pInfo->Packet[0], pInfo->Packet[1], pInfo->Packet[2] ));
  189. }
  190. #endif
  191. return 1;
  192. }
  193. }
  194. else {
  195. TRACE(TL_CIP_WARNING, ("\'Validate: invalid SrcPktSeq; Packet %x\n", pInfo->Packet));
  196. return 1;
  197. }
  198. } // DVReadFrameValidate
  199. #if DBG
  200. LONGLONG PreviousPictureNumber;
  201. LONGLONG PreviousTime;
  202. CYCLE_TIME PreviousTimestamp;
  203. #endif
  204. ULONG
  205. DVCompleteSrbRead(
  206. PCIP_NOTIFY_INFO pInfo
  207. )
  208. /*++
  209. Routine Description:
  210. 61883 has completed receiving data and callback to us to complete.
  211. --*/
  212. {
  213. PSRB_DATA_PACKET pSrbDataPacket;
  214. PHW_STREAM_REQUEST_BLOCK pSrb;
  215. PKSSTREAM_HEADER pStrmHeader;
  216. PDVCR_EXTENSION pDevExt;
  217. PSTREAMEX pStrmExt;
  218. LONGLONG LastPictureNumber;
  219. PUCHAR pFrameBuffer;
  220. KIRQL oldIrql;
  221. PKS_FRAME_INFO pFrameInfo; // For VidOnly pin only
  222. #if DBG
  223. PXMT_FRAME_STAT pXmtStat;
  224. #endif
  225. // Callback and might be at the DISPATCH_LEVEL
  226. // The caller might have acquired spinlock as well!
  227. pSrbDataPacket = pInfo->Context;
  228. if(!pSrbDataPacket) {
  229. ASSERT(pSrbDataPacket && "Context is NULL!");
  230. return 1;
  231. }
  232. pStrmExt = pSrbDataPacket->pStrmExt;
  233. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  234. #if DBG
  235. // Once it is completed by 61883, it becomes non-cancellable.
  236. if(!pStrmExt->bIsochIsActive) {
  237. TRACE(TL_CIP_WARNING,("CompleteSrbRead: bIsochActive:%d; pSrbDataPacket:%x\n", pStrmExt->bIsochIsActive, pSrbDataPacket));
  238. }
  239. #endif
  240. pSrb = pSrbDataPacket->pSrb; ASSERT(pSrbDataPacket->pSrb);
  241. pDevExt = pStrmExt->pDevExt;
  242. pFrameBuffer = (PUCHAR) pSrbDataPacket->FrameBuffer;
  243. pStrmHeader = pSrb->CommandData.DataBufferArray; ASSERT(pStrmHeader->Size >= sizeof(KSSTREAM_HEADER));
  244. //
  245. // Check CIP_STATUS_* from 61883
  246. //
  247. // CIP_STATUS_CORRUPT_FRAME (0x00000001) // isoch header or cip header was incorrect
  248. if(pSrbDataPacket->Frame->Status & CIP_STATUS_CORRUPT_FRAME) {
  249. TRACE(TL_STRM_WARNING|TL_CIP_TRACE,("\'CIP_STATUS_CORRUPT_FRAME\n"));
  250. pStrmHeader->OptionsFlags = 0;
  251. pSrb->Status = STATUS_SUCCESS; // Success but no data !
  252. pStrmHeader->DataUsed = 0;
  253. pStrmExt->PictureNumber++; pStrmExt->FramesProcessed++;
  254. }
  255. else
  256. // CIP_STATUS_SUCCESS (0x00000000) // 0 so cannot do bitwise operation!!
  257. // CIP_STATUS_FIRST_FRAME (0x00000002) // First attached frame to 61883
  258. if(pSrbDataPacket->Frame->Status == CIP_STATUS_SUCCESS ||
  259. (pSrbDataPacket->Frame->Status & CIP_STATUS_FIRST_FRAME)) {
  260. // Only increment FramesProcessed if it is a valid frame;
  261. pStrmExt->FramesProcessed++;
  262. pSrb->Status = STATUS_SUCCESS;
  263. pStrmHeader->OptionsFlags = KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
  264. pStrmHeader->DataUsed = DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize;
  265. // Put in Timestamp info depending on clock provider
  266. pStrmHeader->PresentationTime.Numerator = 1;
  267. pStrmHeader->PresentationTime.Denominator = 1;
  268. if(pStrmExt->hMasterClock || pStrmExt->hClock) {
  269. pStrmHeader->Duration =
  270. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame;
  271. pStrmHeader->OptionsFlags |=
  272. (KSSTREAM_HEADER_OPTIONSF_TIMEVALID | // pStrmHeader->PresentationTime.Time is valid
  273. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  274. }
  275. //
  276. // Only if there is a clock, presentation time and drop frames information are set.
  277. // Acoording to DDK:
  278. // The PictureNumber member count represents the idealized count of the current picture,
  279. // which is calculated in one of two ways:
  280. // ("Other" clock) Measure the time since the stream was started and divide by the frame duration.
  281. // (MasterClock) Add together the count of frames captured and the count of frame dropped.
  282. //
  283. // Other device (audio?) is the clock provider
  284. if(pStrmExt->hClock) {
  285. pStrmExt->TimeContext.HwDeviceExtension = (struct _HW_DEVICE_EXTENSION *) pDevExt;
  286. pStrmExt->TimeContext.HwStreamObject = pStrmExt->pStrmObject;
  287. pStrmExt->TimeContext.Function = TIME_GET_STREAM_TIME;
  288. pStrmExt->TimeContext.Time = 0;
  289. pStrmExt->TimeContext.SystemTime = 0;
  290. StreamClassQueryMasterClockSync(
  291. pStrmExt->hClock,
  292. &(pStrmExt->TimeContext)
  293. );
  294. pStrmHeader->PresentationTime.Time = pStrmExt->CurrentStreamTime = pStrmExt->TimeContext.Time;
  295. // Calculate picture number and dropped frame;
  296. // For NTSC, it could be 267 or 266 packet time per frame. Since integer calculation will round,
  297. // we will add a packet time (TIME_PER_CYCLE = 125 us = 1250 100nsec) to that.This is only used for calculation.
  298. LastPictureNumber = pStrmExt->PictureNumber;
  299. pStrmExt->PictureNumber =
  300. 1 + // Picture number start with 1.
  301. (pStrmHeader->PresentationTime.Time + TIME_PER_CYCLE)
  302. * (LONGLONG) GET_AVG_TIME_PER_FRAME_DENOM(pStrmExt->pDevExt->VideoFormatIndex)
  303. / (LONGLONG) GET_AVG_TIME_PER_FRAME_NUM(pStrmExt->pDevExt->VideoFormatIndex);
  304. // Detect discontinuity
  305. if(pStrmExt->PictureNumber > LastPictureNumber+1) {
  306. pStrmHeader->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY; // If there is a skipped frame, set the discontinuity flag
  307. TRACE(TL_CIP_WARNING,("\'Discontinuity: LastPic#:%d; Pic#%d; PresTime:%d;\n", (DWORD) LastPictureNumber, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmHeader->PresentationTime.Time));
  308. }
  309. // Detect if picture number did not progress.
  310. // This could be due to two frame being completely very close to each other.
  311. if(pStrmExt->PictureNumber <= LastPictureNumber) {
  312. TRACE(TL_CIP_WARNING,("\'hClock:Same pic #:(%d->%d); tmPres:(%d->%d); (%d:%d:%d) -> (%d:%d:%d); AQD[%d:%d:%d]\n",
  313. (DWORD) PreviousPictureNumber,
  314. (DWORD) pStrmExt->PictureNumber,
  315. (DWORD) PreviousTime,
  316. (DWORD) pStrmHeader->PresentationTime.Time,
  317. PreviousTimestamp.CL_SecondCount, PreviousTimestamp.CL_CycleCount, PreviousTimestamp.CL_CycleOffset,
  318. pSrbDataPacket->Frame->Timestamp.CL_SecondCount,
  319. pSrbDataPacket->Frame->Timestamp.CL_CycleCount,
  320. pSrbDataPacket->Frame->Timestamp.CL_CycleOffset,
  321. pStrmExt->cntDataAttached,
  322. pStrmExt->cntSRBQueued,
  323. pStrmExt->cntDataDetached
  324. ));
  325. pStrmExt->PictureNumber = LastPictureNumber + 1; // Picture number must progress !!!!
  326. }
  327. #if DBG
  328. PreviousPictureNumber = pStrmExt->PictureNumber;
  329. PreviousTime = pStrmHeader->PresentationTime.Time;
  330. PreviousTimestamp = pSrbDataPacket->Frame->Timestamp;
  331. #endif
  332. pStrmExt->FramesDropped = pStrmExt->PictureNumber - pStrmExt->FramesProcessed;
  333. // This subunit driver is a Master clock
  334. } else if (pStrmExt->hMasterClock) {
  335. #ifdef NT51_61883
  336. ULONG ulDeltaCycleCounts;
  337. // No drop frame for PAUSE->RUN transition
  338. if(pStrmExt->b1stNewFrameFromPauseState) {
  339. pStrmHeader->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  340. pStrmExt->b1stNewFrameFromPauseState = FALSE;
  341. } else {
  342. ULONG ulCycleCount16bits;
  343. // Calculate skipped 1394 cycle from the returned CycleTime
  344. VALIDATE_CYCLE_COUNTS(pSrbDataPacket->Frame->Timestamp);
  345. ulCycleCount16bits = CALCULATE_CYCLE_COUNTS(pSrbDataPacket->Frame->Timestamp);
  346. ulDeltaCycleCounts = CALCULATE_DELTA_CYCLE_COUNT(pStrmExt->CycleCount16bits, ulCycleCount16bits);
  347. // Adjust to max allowable gap to the max elapsed time of the CycleTime returned by OHCI 1394.
  348. if(ulDeltaCycleCounts > MAX_CYCLES)
  349. ulDeltaCycleCounts = MAX_CYCLES; // Wrap around
  350. //
  351. // There are two cases for drop frames:
  352. // (1) Starve of buffer; or,
  353. // (2) no data (blank tape or tape is not playing)
  354. //
  355. // For case (1), 61883 returns CIP_STATUS_FIRST_FRAME.
  356. if(pSrbDataPacket->Frame->Status & CIP_STATUS_FIRST_FRAME) {
  357. // Use cycle count to calculate drop frame. We substract 1 from the MaxSrcPacket on purpose to avoid truncating.
  358. // The max range is MAX_CYCLE (8 * 8000 = 64000 cycles)
  359. // 64000 * 125 * 3 / 100100 = 239.76
  360. // 64000 / 266 = 240
  361. // 64000 / 267 = 239
  362. if(ulDeltaCycleCounts >= (DVFormatInfoTable[pDevExt->VideoFormatIndex].ulMaxSrcPackets - 1)) {
  363. ULONG ulFrameElapsed = ulDeltaCycleCounts / (DVFormatInfoTable[pDevExt->VideoFormatIndex].ulMaxSrcPackets - 1);
  364. pStrmExt->FramesDropped += (ulFrameElapsed - 1); // There is a valid frame that is not dropped.
  365. }
  366. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("CIP_STATUS_FIRST_FRAME: Drop:%d; Processed:%d\n", (DWORD) pStrmExt->FramesDropped, pStrmExt->FramesProcessed ));
  367. pStrmHeader->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  368. } else {
  369. // Ignore all "drop frames" in the "no data" case
  370. // pStrmExt->FramesDropped += 0;
  371. }
  372. }
  373. // If we are the clock provider, the stream time is based on sample number * AvgTimePerFrame
  374. pStrmExt->PictureNumber = pStrmExt->FramesProcessed + pStrmExt->FramesDropped;
  375. pStrmHeader->PresentationTime.Time = pStrmExt->CurrentStreamTime =
  376. pStrmExt->PictureNumber
  377. * (LONGLONG) GET_AVG_TIME_PER_FRAME_NUM(pStrmExt->pDevExt->VideoFormatIndex)
  378. / (LONGLONG) GET_AVG_TIME_PER_FRAME_DENOM(pStrmExt->pDevExt->VideoFormatIndex);
  379. // Use to adjust the queried stream time
  380. pStrmExt->LastSystemTime = GetSystemTime();
  381. // Cache current CycleCount
  382. pStrmExt->CycleCount16bits = CALCULATE_CYCLE_COUNTS(pSrbDataPacket->Frame->Timestamp);
  383. #if DBG
  384. // First frame or skipped frame
  385. if(pStrmExt->PictureNumber <= 1 ||
  386. pStrmExt->PictureNumber <= PreviousPictureNumber ||
  387. ulDeltaCycleCounts > DVFormatInfoTable[pDevExt->VideoFormatIndex].ulMaxSrcPackets
  388. )
  389. TRACE(TL_CIP_WARNING,("\'hMasterClock: Same pic #:(%d->%d); tmPres:(%d->%d); (%d:%d:%d) -> (%d:%d:%d); AQD[%d:%d:%d]\n",
  390. (DWORD) PreviousPictureNumber,
  391. (DWORD) pStrmExt->PictureNumber,
  392. (DWORD) PreviousTime,
  393. (DWORD) pStrmHeader->PresentationTime.Time,
  394. PreviousTimestamp.CL_SecondCount, PreviousTimestamp.CL_CycleCount, PreviousTimestamp.CL_CycleOffset,
  395. pSrbDataPacket->Frame->Timestamp.CL_SecondCount,
  396. pSrbDataPacket->Frame->Timestamp.CL_CycleCount,
  397. pSrbDataPacket->Frame->Timestamp.CL_CycleOffset,
  398. pStrmExt->cntDataAttached,
  399. pStrmExt->cntSRBQueued,
  400. pStrmExt->cntDataDetached
  401. ));
  402. PreviousPictureNumber = pStrmExt->PictureNumber;
  403. PreviousTime = pStrmHeader->PresentationTime.Time;
  404. PreviousTimestamp = pSrbDataPacket->Frame->Timestamp;
  405. #endif
  406. #else // NT51_61883
  407. // This is the old way when 61883 was not returning the correct CycleTime.
  408. pStrmHeader->PresentationTime.Time = pStrmExt->CurrentStreamTime;
  409. pStrmExt->LastSystemTime = GetSystemTime(); // Use to adjust the queried stream time
  410. pStrmExt->CurrentStreamTime += DVFormatInfoTable[pDevExt->VideoFormatIndex].ulAvgTimePerFrame;
  411. #endif // NT51_61883
  412. // no Clock so "free flowing!"
  413. } else {
  414. pStrmHeader->PresentationTime.Time = 0;
  415. pStrmHeader->Duration = 0; // No clock so not valid.
  416. pStrmExt->PictureNumber++;
  417. TRACE(TL_CIP_TRACE,("\'No clock: PicNum:%d\n", (DWORD) pStrmExt->PictureNumber));
  418. }
  419. }
  420. else {
  421. // 61883 has not defined this new status at this time!
  422. // Do not know what to do so we will complete it with 0 length for now.
  423. pStrmHeader->OptionsFlags = 0;
  424. pSrb->Status = STATUS_SUCCESS;
  425. pStrmHeader->DataUsed = 0;
  426. pStrmExt->PictureNumber++; pStrmExt->FramesProcessed++;
  427. TRACE(TL_STRM_WARNING|TL_CIP_ERROR,("pSrbDataPacket:%x; unexpected Frame->Status %x\n", pSrbDataPacket, pSrbDataPacket->Frame->Status));
  428. ASSERT(FALSE && "Unknown pSrbDataPacket->Frame->Status");
  429. }
  430. // For VidOnly which uses VideoInfoHeader and has
  431. // an extended frame information (KS_FRAME_INFO) appended to KSSTREAM_HEADER
  432. if( pDevExt->idxStreamNumber == 0 &&
  433. (pStrmHeader->Size >= (sizeof(KSSTREAM_HEADER) + sizeof(PKS_FRAME_INFO)))
  434. ) {
  435. pFrameInfo = (PKS_FRAME_INFO) (pStrmHeader + 1);
  436. pFrameInfo->ExtendedHeaderSize = sizeof(KS_FRAME_INFO);
  437. pFrameInfo->PictureNumber = pStrmExt->PictureNumber;
  438. pFrameInfo->DropCount = pStrmExt->FramesDropped;
  439. pFrameInfo->dwFrameFlags =
  440. KS_VIDEO_FLAG_FRAME | // Complete frame
  441. KS_VIDEO_FLAG_I_FRAME; // Every DV frame is an I frame
  442. }
  443. #if DBG
  444. // Validate that the data is return in the right sequence
  445. if(pSrbDataPacket->FrameNumber != pStrmExt->FramesProcessed) {
  446. TRACE(TL_STRM_WARNING|TL_CIP_ERROR,("\'pSrbDataPacket:%x; Status:%x; Out of Sequence %d != %d; (Dropped:%x)\n",
  447. pSrbDataPacket, pSrbDataPacket->Frame->Status,
  448. (DWORD) pSrbDataPacket->FrameNumber, (DWORD) pStrmExt->FramesProcessed,
  449. (DWORD) pStrmExt->FramesDropped
  450. ));
  451. };
  452. #endif
  453. #if DBG
  454. // Collect transmit buffer statistics
  455. if(pStrmExt->ulStatEntries < MAX_XMT_FRAMES_TRACED) {
  456. pXmtStat = pStrmExt->paXmtStat + pStrmExt->ulStatEntries;
  457. pXmtStat->StreamState = pStrmExt->StreamState;
  458. pXmtStat->cntSRBReceived = (LONG) pStrmExt->cntSRBReceived;
  459. pXmtStat->cntSRBPending = (LONG) pStrmExt->cntSRBPending;
  460. pXmtStat->cntSRBQueued = (LONG) pStrmExt->cntSRBQueued;
  461. pXmtStat->cntDataAttached= pStrmExt->cntDataAttached;
  462. pXmtStat->FrameSlot = (DWORD) pStrmExt->PictureNumber;
  463. pXmtStat->tmStreamTime = pStrmExt->CurrentStreamTime;
  464. pXmtStat->DropCount = (DWORD) pStrmExt->FramesDropped;
  465. pXmtStat->FrameNumber = (DWORD) pSrbDataPacket->FrameNumber;
  466. pXmtStat->OptionsFlags = pSrb->CommandData.DataBufferArray->OptionsFlags;
  467. pXmtStat->tmPresentation = pSrb->CommandData.DataBufferArray->PresentationTime.Time;
  468. pXmtStat->tsTransmitted= pSrbDataPacket->Frame->Timestamp;
  469. pStrmExt->ulStatEntries++;
  470. }
  471. #endif
  472. //
  473. // Mark completion is called.
  474. //
  475. pSrbDataPacket->State |= DE_IRP_CALLBACK_COMPLETED;
  476. //
  477. // Attached->Completed or Completed->Attached.
  478. //
  479. if(IsStateSet(pSrbDataPacket->State, DE_IRP_ATTACHED_COMPLETED)) {
  480. //
  481. // Recycle it back to the detach list
  482. //
  483. RemoveEntryList(&pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached--; ASSERT(pStrmExt->cntDataAttached >= 0);
  484. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  485. #if DBG
  486. // Detect if 61883 is starve. This cause discontinuity.
  487. // This can happen for many valid reasons (slow system).
  488. // An assert is added to detect other unknown reason.
  489. if(pStrmExt->cntDataAttached == 0 && pStrmExt->StreamState == KSSTATE_RUN) {
  490. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\n**** 61883 starved in RUN state (read); AQD[%d:%d:%d]\n\n",
  491. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached
  492. ));
  493. // ASSERT(pStrmExt->cntDataAttached > 0 && "61883 is starve at RUN state!!");
  494. }
  495. #endif
  496. //
  497. // Complete this Srb
  498. //
  499. StreamClassStreamNotification(StreamRequestComplete, pStrmExt->pStrmObject, pSrbDataPacket->pSrb );
  500. pSrbDataPacket->State |= DE_IRP_SRB_COMPLETED; pSrbDataPacket->pSrb = NULL;
  501. #if DBG
  502. pStrmExt->cntSRBPending--;
  503. #endif
  504. } else {
  505. TRACE(TL_STRM_WARNING,("CompleteSrbRead: pSrbDataPacket:%x; Completed before attach.\n", pSrbDataPacket));
  506. }
  507. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  508. return 0;
  509. } // DVCompleteSrbRead
  510. NTSTATUS
  511. DVAttachFrameCR(
  512. IN PDEVICE_OBJECT DeviceObject,
  513. IN PIRP pIrp,
  514. IN PSRB_DATA_PACKET pSrbDataPacket
  515. )
  516. /*++
  517. Routine Description:
  518. Completion routine for attaching a frame for transmitting.
  519. Apply to attaching listen and talk frame.
  520. --*/
  521. {
  522. PHW_STREAM_REQUEST_BLOCK pSrb;
  523. PSTREAMEX pStrmExt;
  524. PLONG plSrbUseCount; // When this count is 0, it can be completed.
  525. KIRQL oldIrql;
  526. pStrmExt = pSrbDataPacket->pStrmExt;
  527. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  528. pSrb = pSrbDataPacket->pSrb;
  529. // This entry is be already attached before IoCallDriver.
  530. // This is done this way because this buffer could be filled and
  531. // completed before the attach completion routine (here) is called.
  532. // If it is completed and callback is called,
  533. // pSrbDataPacket->pSrb has been set to NULL.
  534. // In the error case, pSrbDataPacket->pSrb should not be NULL.
  535. if(!NT_SUCCESS(pIrp->IoStatus.Status)) {
  536. if(pSrbDataPacket->pSrb == NULL) {
  537. // PBinder told me that this cannot happen.
  538. // A buffer is completed (pSRb set to NULL), and still return with an error!
  539. ASSERT(pSrbDataPacket->pSrb);
  540. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  541. return STATUS_MORE_PROCESSING_REQUIRED;
  542. }
  543. pSrbDataPacket->State |= DE_IRP_ERROR;
  544. plSrbUseCount = (PLONG) (pSrb->SRBExtension);
  545. (*plSrbUseCount) --; // -- for being remove from queue
  546. ASSERT(*plSrbUseCount >= 0);
  547. TRACE(TL_CIP_ERROR,("DVAttachFrameCR: pSrb:%x; pSrb->Status:%x; failed pIrp->Status %x; UseCnt:%d\n", pSrb, pSrb->Status, pIrp->IoStatus.Status, *plSrbUseCount));
  548. ASSERT(NT_SUCCESS(pIrp->IoStatus.Status) && "DVAttachFrameCR");
  549. // Complete this SRB only if the count is 0.
  550. if(*plSrbUseCount == 0 && pSrb->Status != STATUS_CANCELLED) {
  551. pSrb->Status = pIrp->IoStatus.Status;
  552. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  553. // Complete SRB
  554. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrbDataPacket->pSrb);
  555. pSrbDataPacket->State |= DE_IRP_SRB_COMPLETED; pSrbDataPacket->pSrb = NULL;
  556. #if DBG
  557. pStrmExt->cntSRBPending--;
  558. #endif
  559. }
  560. // Recycle list
  561. RemoveEntryList(&pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached--; ASSERT(pStrmExt->cntDataAttached >= 0);
  562. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  563. #if DBG
  564. // Detect if 61883 is starve. This cause discontinuity.
  565. // This can happen for many valid reasons (slow system).
  566. // An assert is added to detect other unknown reason.
  567. if(!pStrmExt->bEOStream && pStrmExt->cntDataAttached == 0 && pStrmExt->StreamState == KSSTATE_RUN) {
  568. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\n**** 61883 starve in RUN state (AttachCR); AQD[%d:%d:%d]\n\n",
  569. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached
  570. ));
  571. if (pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  572. // ASSERT(pStrmExt->cntDataAttached > 0 && "61883 is starve at RUN state!!");
  573. }
  574. }
  575. #endif
  576. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  577. return STATUS_MORE_PROCESSING_REQUIRED;
  578. }
  579. //
  580. // Mark attached buffer completed.
  581. //
  582. pSrbDataPacket->State |= DE_IRP_ATTACHED_COMPLETED;
  583. //
  584. // Special case: Completed and then Attached.
  585. //
  586. if(IsStateSet(pSrbDataPacket->State, DE_IRP_CALLBACK_COMPLETED)) {
  587. //
  588. // Recycle it back to the detach list
  589. //
  590. RemoveEntryList(&pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached--; ASSERT(pStrmExt->cntDataAttached >= 0);
  591. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  592. #if DBG
  593. // Detect if 61883 is starve. This cause discontinuity.
  594. // This can happen for many valid reasons (slow system).
  595. // An assert is added to detect other unknown reason.
  596. if(!pStrmExt->bEOStream && pStrmExt->cntDataAttached == 0 && pStrmExt->StreamState == KSSTATE_RUN) {
  597. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\n**** 61883 starve in RUN state (AttachCR); AQD[%d:%d:%d]\n\n",
  598. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached
  599. ));
  600. if (pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  601. // ASSERT(pStrmExt->cntDataAttached > 0 && "61883 is starve at RUN state!!");
  602. }
  603. }
  604. #endif
  605. //
  606. // Complete this Srb
  607. //
  608. StreamClassStreamNotification(StreamRequestComplete, pStrmExt->pStrmObject, pSrbDataPacket->pSrb);
  609. pSrbDataPacket->State |= DE_IRP_SRB_COMPLETED; pSrbDataPacket->pSrb = NULL;
  610. #if DBG
  611. pStrmExt->cntSRBPending--;
  612. #endif
  613. TRACE(TL_STRM_WARNING,("AttachFrameCR: pSrbDataPacket:%x; completed before DttachFrameCR.\n", pSrbDataPacket));
  614. }
  615. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  616. TRACE(TL_CIP_INFO,("\'DVAttachFrameCR: pSrb:%x; AttachCnt:%d\n", pSrb, pStrmExt->cntDataAttached));
  617. return STATUS_MORE_PROCESSING_REQUIRED;
  618. }
  619. VOID
  620. DVSRBRead(
  621. IN PKSSTREAM_HEADER pStrmHeader,
  622. IN ULONG ulFrameSize,
  623. IN PDVCR_EXTENSION pDevExt,
  624. IN PSTREAMEX pStrmExt,
  625. IN PHW_STREAM_REQUEST_BLOCK pSrb // needs Srb->Status
  626. )
  627. /*++
  628. Routine Description:
  629. Called when an Read Data Srb request is received
  630. --*/
  631. {
  632. KIRQL oldIrql;
  633. NTSTATUS Status;
  634. PSRB_DATA_PACKET pSrbDataPacket;
  635. PAV_61883_REQUEST pAVReq;
  636. PLONG plSrbUseCount;
  637. PIO_STACK_LOCATION NextIrpStack;
  638. ULONG ulSrcPktLen; // Packet length in bytes
  639. PVOID pFrameBuffer;
  640. PAGED_CODE();
  641. //
  642. // Some validation
  643. //
  644. if(pStrmHeader->FrameExtent < ulFrameSize) {
  645. TRACE(TL_CIP_WARNING,("\'SRBRead: FrmExt %d < FrmSz %d\n", pStrmHeader->FrameExtent, ulFrameSize));
  646. #ifdef SUPPORT_NEW_AVC
  647. if(pStrmExt->bDV2DVConnect) {
  648. pSrb->Status = STATUS_SUCCESS; // Testing...
  649. } else {
  650. #endif
  651. ASSERT(pStrmHeader->FrameExtent >= ulFrameSize);
  652. pSrb->Status = STATUS_INVALID_PARAMETER;
  653. #ifdef SUPPORT_NEW_AVC
  654. }
  655. #endif
  656. goto ExitReadStreamError;
  657. }
  658. //
  659. // Make sure that there is enough entry
  660. //
  661. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  662. if(IsListEmpty(&pStrmExt->DataDetachedListHead)) {
  663. //
  664. // This can happen only if the upper layer send down more than what we preallocated.
  665. // In this case, we will expand the list.
  666. //
  667. if(!(pSrbDataPacket = ExAllocatePool(NonPagedPool, sizeof(SRB_DATA_PACKET)))) {
  668. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  669. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  670. goto ExitReadStreamError;
  671. }
  672. RtlZeroMemory(pSrbDataPacket, sizeof(SRB_DATA_PACKET));
  673. if(!(pSrbDataPacket->Frame = ExAllocatePool(NonPagedPool, sizeof(CIP_FRAME)))) {
  674. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  675. ExFreePool(pSrbDataPacket);
  676. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  677. goto ExitReadStreamError;
  678. }
  679. if(!(pSrbDataPacket->pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE))) {
  680. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  681. ExFreePool(pSrbDataPacket->Frame); pSrbDataPacket->Frame = 0;
  682. ExFreePool(pSrbDataPacket); pSrbDataPacket = 0;
  683. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  684. goto ExitReadStreamError;
  685. }
  686. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  687. TRACE(TL_CIP_WARNING,("\'Add one node to DetachList\n"));
  688. }
  689. // Get a a nonpaged system-space virtual address for the buffer
  690. // This could fail it there is not enough system resource (MDL).
  691. #ifdef USE_WDM110 // Win2000
  692. //
  693. // Driver verifier flag to use this but if this is used, this driver will not load for Millen!!!
  694. //
  695. pFrameBuffer = MmGetSystemAddressForMdlSafe(pSrb->Irp->MdlAddress, NormalPagePriority);
  696. #else // Win9x
  697. pFrameBuffer = MmGetSystemAddressForMdl (pSrb->Irp->MdlAddress);
  698. #endif
  699. if(pFrameBuffer == NULL) {
  700. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  701. pSrb->Status = STATUS_INSUFFICIENT_RESOURCES;
  702. ASSERT(FALSE && "DVFormatAttachFrame() insufficient resource!");
  703. goto ExitReadStreamError;
  704. }
  705. pSrbDataPacket = (PSRB_DATA_PACKET) RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
  706. plSrbUseCount = (PLONG) (pSrb->SRBExtension); (*plSrbUseCount) = 0; // Not in a queue so 0.
  707. pAVReq = &pSrbDataPacket->AVReq;
  708. ulSrcPktLen = \
  709. (DVFormatInfoTable[pDevExt->VideoFormatIndex].DataBlockSize << 2) * \
  710. (1 << DVFormatInfoTable[pDevExt->VideoFormatIndex].FractionNumber);
  711. //
  712. // Format an attach frame request
  713. //
  714. DVFormatAttachFrame(
  715. pStrmExt->pStrmInfo->DataFlow,
  716. pStrmExt,
  717. pAVReq,
  718. pSrb,
  719. pSrbDataPacket,
  720. ulSrcPktLen,
  721. ulFrameSize,
  722. pFrameBuffer
  723. );
  724. // Completion callback can be called before the attach frame completion routine;
  725. // Add this to the attached list now; if it ever failed, it will be removed in the completion routine.
  726. InsertTailList(&pStrmExt->DataAttachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached++;
  727. (*plSrbUseCount) ++; // ++ for being in queue
  728. ASSERT(*plSrbUseCount > 0);
  729. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  730. NextIrpStack = IoGetNextIrpStackLocation(pSrbDataPacket->pIrp);
  731. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  732. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  733. NextIrpStack->Parameters.Others.Argument1 = &pSrbDataPacket->AVReq;
  734. IoSetCompletionRoutine(
  735. pSrbDataPacket->pIrp,
  736. DVAttachFrameCR,
  737. pSrbDataPacket,
  738. TRUE,
  739. TRUE,
  740. TRUE
  741. );
  742. // Must set to _PENDING or MediaSample will return empty KSSTREAM_HEADER
  743. pSrb->Status = STATUS_PENDING;
  744. pSrbDataPacket->pIrp->IoStatus.Status = STATUS_SUCCESS; // Initialize it
  745. Status = IoCallDriver( pStrmExt->pDevExt->pBusDeviceObject, pSrbDataPacket->pIrp);
  746. ASSERT(Status == STATUS_PENDING || Status == STATUS_SUCCESS);
  747. return;
  748. ExitReadStreamError:
  749. StreamClassStreamNotification(
  750. StreamRequestComplete,
  751. pSrb->StreamObject,
  752. pSrb
  753. );
  754. #if DBG
  755. pStrmExt->cntSRBPending--;
  756. #endif
  757. }
  758. ULONG
  759. DVCompleteSrbWrite(
  760. PCIP_NOTIFY_INFO pInfo
  761. )
  762. /*++
  763. Routine Description:
  764. This fucntion is called when 61883 has completed transmitting a frame.
  765. --*/
  766. {
  767. PSRB_DATA_PACKET pSrbDataPacket ;
  768. PHW_STREAM_REQUEST_BLOCK pSrb;
  769. NTSTATUS Status = STATUS_SUCCESS;
  770. PDVCR_EXTENSION pDevExt;
  771. PSTREAMEX pStrmExt;
  772. PLONG plSrbUseCount; // When this count is 0, it can be completed.
  773. KIRQL oldIrql;
  774. #if DBG
  775. LONG lCycleCountElapsed;
  776. PXMT_FRAME_STAT pXmtStat;
  777. #endif
  778. // Callback and in DISPATCH_LEVEL
  779. // Caller might have acquired SpinLock as well!
  780. pSrbDataPacket = pInfo->Context;
  781. if(!pSrbDataPacket) {
  782. ASSERT(pSrbDataPacket);
  783. return 1;
  784. }
  785. pStrmExt = pSrbDataPacket->pStrmExt;
  786. ASSERT(pStrmExt);
  787. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  788. ASSERT(pSrbDataPacket->pSrb);
  789. pSrb = pSrbDataPacket->pSrb;
  790. pDevExt = pStrmExt->pDevExt;
  791. plSrbUseCount = (PLONG) pSrb->SRBExtension;
  792. // Check return Status
  793. if(!NT_SUCCESS(pSrbDataPacket->Frame->Status)) {
  794. TRACE(TL_CIP_ERROR,("\'DVCompleteSrbWrite: %d: Frame->Status %x\n", (DWORD) pSrbDataPacket->FrameNumber, pSrbDataPacket->Frame->Status));
  795. ASSERT(NT_SUCCESS(pSrbDataPacket->Frame->Status));
  796. pSrb->Status = STATUS_UNSUCCESSFUL;
  797. }
  798. else {
  799. pSrb->Status = STATUS_SUCCESS;
  800. }
  801. (*plSrbUseCount) --; // This count need to be 0 before the SRB is completed.
  802. ASSERT(*plSrbUseCount >= 0);
  803. #if DBG
  804. if(pSrbDataPacket->StreamState == KSSTATE_PAUSE) {
  805. pStrmExt->lPrevCycleCount = pSrbDataPacket->Frame->Timestamp.CL_CycleCount;
  806. pStrmExt->lTotalCycleCount = 0;
  807. pStrmExt->lFramesAccumulatedRun = 0;
  808. pStrmExt->lFramesAccumulatedPaused++;
  809. } else if(pSrbDataPacket->StreamState == KSSTATE_RUN) {
  810. if((LONG) pSrbDataPacket->Frame->Timestamp.CL_CycleCount > pStrmExt->lPrevCycleCount)
  811. lCycleCountElapsed = pSrbDataPacket->Frame->Timestamp.CL_CycleCount - pStrmExt->lPrevCycleCount;
  812. else
  813. lCycleCountElapsed = pSrbDataPacket->Frame->Timestamp.CL_CycleCount + 8000 - pStrmExt->lPrevCycleCount;
  814. if(lCycleCountElapsed <= (LONG) DVFormatInfoTable[pDevExt->VideoFormatIndex].ulSrcPackets) {
  815. TRACE(TL_CIP_WARNING, ("\'#### CycleCounts between frames %d <= expected %d + empty pkt?\n",
  816. lCycleCountElapsed,
  817. DVFormatInfoTable[pDevExt->VideoFormatIndex].ulSrcPackets
  818. ));
  819. }
  820. pStrmExt->lTotalCycleCount += lCycleCountElapsed;
  821. pStrmExt->lFramesAccumulatedRun++;
  822. TRACE(TL_CIP_TRACE,("\'%d) Attached:%d; pSrb:%x; FmSt:%x; CyTm:[SC:%d:CC:%d]; CyclElaps:%d; fps:%d/%d\n",
  823. (DWORD) pSrbDataPacket->FrameNumber,
  824. pStrmExt->cntDataAttached,
  825. pSrb,
  826. pSrbDataPacket->Frame->Status,
  827. pSrbDataPacket->Frame->Timestamp.CL_SecondCount,
  828. pSrbDataPacket->Frame->Timestamp.CL_CycleCount,
  829. lCycleCountElapsed,
  830. pStrmExt->lTotalCycleCount,
  831. (DWORD) pStrmExt->lFramesAccumulatedRun
  832. ));
  833. pStrmExt->lPrevCycleCount = pSrbDataPacket->Frame->Timestamp.CL_CycleCount;
  834. } else {
  835. TRACE(TL_CIP_ERROR,("\'This data was attached at %d state ?????\n", pSrbDataPacket->StreamState));
  836. }
  837. #endif
  838. TRACE(TL_CIP_INFO,("\'%d) FmSt %x; Cnt %d; CyTm:[%d:%d:%d]; PrevCyclCnt:%d\n",
  839. (DWORD) pSrbDataPacket->FrameNumber,
  840. pSrbDataPacket->Frame->Status,
  841. *plSrbUseCount,
  842. pSrbDataPacket->Frame->Timestamp.CL_SecondCount,
  843. pSrbDataPacket->Frame->Timestamp.CL_CycleCount,
  844. pSrbDataPacket->Frame->Timestamp.CL_CycleOffset,
  845. pStrmExt->lPrevCycleCount
  846. ));
  847. TRACE(TL_CIP_INFO,("\'DVCompleteSrbWrite: Frm:%d; Attached:%d; cntUse:%d, Srb:%x; FrmSt:%x; CyclElaps:%d\n",
  848. (DWORD) pSrbDataPacket->FrameNumber,
  849. pStrmExt->cntDataAttached,
  850. *plSrbUseCount,
  851. pSrb,
  852. pSrbDataPacket->Frame->Status,
  853. lCycleCountElapsed
  854. ));
  855. //
  856. // Mark completion is called.
  857. //
  858. pSrbDataPacket->State |= DE_IRP_CALLBACK_COMPLETED;
  859. //
  860. // Attached->Completed or Completed->Attached.
  861. //
  862. if(IsStateSet(pSrbDataPacket->State, DE_IRP_ATTACHED_COMPLETED)) {
  863. //
  864. // Recycle it back to the detach list
  865. //
  866. RemoveEntryList(&pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached--; ASSERT(pStrmExt->cntDataAttached >= 0);
  867. InsertTailList(&pStrmExt->DataDetachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataDetached++;
  868. #if DBG
  869. // Detect if 61883 is starve. This cause discontinuity.
  870. // This can happen for many valid reasons (slow system).
  871. // An assert is added to detect other unknown reason.
  872. if(!pStrmExt->bEOStream && pStrmExt->cntDataAttached == 0 && pStrmExt->StreamState == KSSTATE_RUN) {
  873. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("\n**** 61883 starve in RUN state (write);AQD[%d:%d:%d]\n\n",
  874. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached
  875. ));
  876. if (pStrmExt->pStrmInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  877. // ASSERT(pStrmExt->cntDataAttached > 0 && "61883 is starve at RUN state!!");
  878. }
  879. }
  880. #endif
  881. // Complete this SRB only if the count is 0.
  882. if(*plSrbUseCount == 0) {
  883. TRACE(TL_CIP_TRACE,("\'------------ Srb:%x completing..----------------\n", pSrb));
  884. // Frame that possibly made it to the device
  885. pStrmExt->FramesProcessed++;
  886. pSrb->CommandData.DataBufferArray->DataUsed = DVFormatInfoTable[pDevExt->VideoFormatIndex].ulFrameSize;
  887. StreamClassStreamNotification(StreamRequestComplete, pStrmExt->pStrmObject, pSrbDataPacket->pSrb );
  888. pSrbDataPacket->State |= DE_IRP_SRB_COMPLETED; pSrbDataPacket->pSrb = NULL;
  889. #if DBG
  890. pStrmExt->cntSRBPending--;
  891. #endif
  892. }
  893. } else {
  894. TRACE(TL_STRM_WARNING,("CompleteSrbWrite: pSrbDataPacket:%x; Completed before attach.\n", pSrbDataPacket));
  895. }
  896. #if DBG
  897. // Collect transmit buffer statistics
  898. if((pStrmExt->lFramesAccumulatedPaused + pStrmExt->lFramesAccumulatedRun) <= MAX_XMT_FRAMES_TRACED) {
  899. pXmtStat = pStrmExt->paXmtStat + (pStrmExt->lFramesAccumulatedPaused + pStrmExt->lFramesAccumulatedRun - 1);
  900. pXmtStat->tsTransmitted = pSrbDataPacket->Frame->Timestamp;
  901. if(pSrbDataPacket->Frame->Timestamp.CL_CycleCount == 0) {
  902. TRACE(TL_CIP_WARNING,("\'PAUSE:%d; RUN:%d; %d:%d\n", pStrmExt->lFramesAccumulatedPaused, pStrmExt->lFramesAccumulatedRun,
  903. pSrbDataPacket->Frame->Timestamp.CL_SecondCount, pSrbDataPacket->Frame->Timestamp.CL_CycleCount));
  904. }
  905. }
  906. #endif
  907. // Signal that all SRBs have been attached and transmitted.
  908. if(pStrmExt->bEOStream) {
  909. if(pStrmExt->cntDataAttached == 0 && pStrmExt->cntSRBQueued == 0) {
  910. //
  911. // Signal any pending clock events
  912. //
  913. DVSignalClockEvent(0, pStrmExt, 0, 0);
  914. //
  915. // No data request queued or pending; it is time to signal EOStream to
  916. // trigger EC_COMPLETE.
  917. //
  918. StreamClassStreamNotification(
  919. SignalMultipleStreamEvents,
  920. pStrmExt->pStrmObject,
  921. (GUID *)&KSEVENTSETID_Connection_Local,
  922. KSEVENT_CONNECTION_ENDOFSTREAM
  923. );
  924. TRACE(TL_CIP_WARNING,("\'*-*-* EOStream Signalled: pSrb:%x completed; AQD [%d:%d:%d]; Took %d msec;\n",
  925. pSrb, pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached,
  926. (DWORD) ((GetSystemTime() - pStrmExt->tmStreamStart)/(ULONGLONG) 10000)));
  927. }
  928. else {
  929. TRACE(TL_CIP_TRACE,("\' *EOStream: pSrb:%x completed; cntAttached:%d; cntSRBQ:%d\n", pSrb, (DWORD) pStrmExt->cntDataAttached, (DWORD) pStrmExt->cntSRBQueued));
  930. }
  931. }
  932. //
  933. // If we are not in the ending situtation (EOS pr Stop state) and number of
  934. // attach data request is below a threashold, we singal an event to the
  935. // code that does "throttle" to quickly attach another frame.
  936. //
  937. if(!pStrmExt->bEOStream ||
  938. (pStrmExt->bEOStream && pStrmExt->cntSRBQueued > 0)) {
  939. if(pStrmExt->StreamState != KSSTATE_STOP &&
  940. pStrmExt->cntDataAttached < NUM_BUF_ATTACHED_THEN_ISOCH) {
  941. KeSetEvent(&pStrmExt->hSrbArriveEvent, 0, FALSE);
  942. TRACE(TL_CIP_WARNING,("Threadshold:.AQD:[%d %d %d] < %d\n",
  943. pStrmExt->cntDataAttached,
  944. pStrmExt->cntSRBQueued,
  945. pStrmExt->cntDataDetached,
  946. NUM_BUF_ATTACHED_THEN_ISOCH
  947. ));
  948. }
  949. }
  950. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  951. return 0;
  952. } // DVCompleteSrbWrite
  953. NTSTATUS
  954. DVAttachWriteFrame(
  955. IN PSTREAMEX pStrmExt
  956. )
  957. /*++
  958. Routine Description:
  959. Prepare and submit a frame to 61883 for transmit.
  960. --*/
  961. {
  962. KIRQL oldIrql;
  963. PSRB_DATA_PACKET pSrbDataPacket;
  964. PSRB_ENTRY pSrbEntry;
  965. #if DBG
  966. ULONG SrbNumCache; // Cache the SRB number of tracking purpose
  967. PXMT_FRAME_STAT pXmtStat;
  968. #endif
  969. PHW_STREAM_REQUEST_BLOCK pSrb;
  970. PHW_STREAM_REQUEST_BLOCK pSrbNext;
  971. PVOID pFrameBuffer;
  972. PIO_STACK_LOCATION NextIrpStack;
  973. NTSTATUS Status;
  974. PLONG plSrbUseCount; // When this count is 0, it can be completed.
  975. ULONG ulSrcPktLen;
  976. LARGE_INTEGER Timeout;
  977. PAGED_CODE();
  978. // Serialize setting state to STOP
  979. if(pStrmExt->StreamState != KSSTATE_PAUSE &&
  980. pStrmExt->StreamState != KSSTATE_RUN) {
  981. TRACE(TL_CIP_WARNING,("\'DVAttachWriteFrame: StreamState:%d; no attach! Wait!\n", pStrmExt->StreamState));
  982. Timeout.HighPart = -1;
  983. Timeout.LowPart = (ULONG)(-1 * DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulAvgTimePerFrame);
  984. KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
  985. return STATUS_SUCCESS;
  986. }
  987. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  988. if(IsListEmpty(&pStrmExt->SRBQueuedListHead) ||
  989. IsListEmpty(&pStrmExt->DataDetachedListHead) ) {
  990. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  991. #if DBG
  992. if(!pStrmExt->bEOStream) {
  993. TRACE(TL_CIP_WARNING,("\'StrmSt:%d; DetachList or SrbQ empty: EOStream:%d; AQD [%d:%d:%d]; Wait one frame time.\n",
  994. pStrmExt->StreamState,
  995. pStrmExt->bEOStream,
  996. pStrmExt->cntDataAttached,
  997. pStrmExt->cntSRBQueued,
  998. pStrmExt->cntDataDetached
  999. ));
  1000. }
  1001. #endif
  1002. Timeout.HighPart = -1;
  1003. Timeout.LowPart = (ULONG)(-1 * DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulAvgTimePerFrame);
  1004. KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
  1005. // SRB is queued so it is OK. We will process that later.
  1006. // This is usually cause by receiving more than what we pre-allocate.
  1007. return STATUS_SUCCESS;
  1008. }
  1009. // KSSTATE_PAUSE: "reuse" head of the SrbQ.
  1010. // KSSTATE_RUN: "remove" a Srb from the queue.
  1011. // Get NEXT(SrbQ) and determine if it needs to be removed.
  1012. pSrbEntry = (PSRB_ENTRY) pStrmExt->SRBQueuedListHead.Flink; pSrb = pSrbEntry->pSrb; plSrbUseCount = (PLONG) pSrb->SRBExtension;
  1013. ASSERT(*plSrbUseCount >= 0);
  1014. #if DBG
  1015. SrbNumCache = pSrbEntry->SrbNum;
  1016. #endif
  1017. // Get a a nonpaged system-space virtual address for the buffer
  1018. // This could fail it there is not enough system resource (MDL).
  1019. #ifdef USE_WDM110 // Win2000
  1020. //
  1021. // Driver verifier flag to use this but if this is used, this driver will not load for Millen!!!
  1022. //
  1023. pFrameBuffer = MmGetSystemAddressForMdlSafe(pSrb->Irp->MdlAddress, NormalPagePriority);
  1024. #else
  1025. pFrameBuffer = MmGetSystemAddressForMdl (pSrb->Irp->MdlAddress);
  1026. #endif
  1027. if(pFrameBuffer == NULL) {
  1028. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  1029. ASSERT(FALSE && "Insufficient MDL\n");
  1030. return STATUS_INSUFFICIENT_RESOURCES;
  1031. }
  1032. // Only in RUN state, the stream time in the Srb is considered and Srbs in the SrbQ will be dequeued.
  1033. if(pStrmExt->StreamState == KSSTATE_RUN) {
  1034. #define ALLOWABLE_TIMING_LATENCY TIME_PER_CYCLE
  1035. // Presentation time is honor only if we are the master clock.
  1036. if(pStrmExt->hMasterClock) {
  1037. LONGLONG tmExpectedFrame;
  1038. if( pStrmExt->pDevExt->VideoFormatIndex == FMT_IDX_SD_DVCR_PAL
  1039. || pStrmExt->pDevExt->VideoFormatIndex == FMT_IDX_SDL_DVCR_PAL
  1040. )
  1041. tmExpectedFrame = pStrmExt->PictureNumber * (LONGLONG) FRAME_TIME_PAL;
  1042. else {
  1043. tmExpectedFrame = (pStrmExt->PictureNumber * (LONGLONG) 1000 * (LONGLONG) 1001 ) / (LONGLONG) 3; // trouble NTSC!
  1044. // Adjustment for rounding
  1045. if((pStrmExt->PictureNumber % 3) == 1)
  1046. tmExpectedFrame++;
  1047. }
  1048. // Use to adjust the querued stream time.
  1049. pStrmExt->LastSystemTime = GetSystemTime();
  1050. // There are three situations about the NEXT(SrbQ) comparing with tmExpectedFrame:
  1051. // 1. Early; 2. OnTime; 3.Late
  1052. //
  1053. // tmExpectedFrame
  1054. // |
  1055. // 3>------------2>-----------------1>---------------
  1056. // 3.Late | 2.On Time | 1.Early
  1057. // | x | x |
  1058. // where "x" is the allowable latency (for calculation rounding)
  1059. //
  1060. // Note: allow TIME_PER_CYCLE latency
  1061. /*Early*/
  1062. /*N+1/++*/ if((tmExpectedFrame + ALLOWABLE_TIMING_LATENCY) <= pSrb->CommandData.DataBufferArray->PresentationTime.Time) {
  1063. // FUTURE: if a frame arrive sooner than expected, do not remove SrbQ;
  1064. // instead, repeat until passing its "scheduled departure".
  1065. // Remove NEXT(SrbQ) only if bEOStream
  1066. if(pStrmExt->bEOStream) {
  1067. TRACE(TL_CIP_TRACE,("\'EOStream=== Srb:%x; (SrbNum:%d ?= PicNum:%d) cntSrbQ:%d; Attach:%d ===\n",
  1068. pSrb, pSrbEntry->SrbNum, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->cntSRBQueued, (DWORD) pStrmExt->cntDataAttached));
  1069. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--;
  1070. ExFreePool(pSrbEntry); pSrbEntry = NULL; // Removed so free it!
  1071. }
  1072. TRACE(TL_CIP_TRACE,("\'** Repeat: pSrb:%x; RefCnt:%d; cntSrbQ:%d; PicNum:%d; Drp:%d; PresTime:%d >= CurTime:%d\n",
  1073. pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->FramesDropped,
  1074. (DWORD) (pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000), (DWORD) tmExpectedFrame/10000));
  1075. /*OnTime*/ } else
  1076. /* N */ if((tmExpectedFrame - ALLOWABLE_TIMING_LATENCY) <= pSrb->CommandData.DataBufferArray->PresentationTime.Time) {
  1077. // ON-TIME: may exactly matching or due to integer calculation, within one frame time.
  1078. // Dequeue if there are more than one Srb in the queue.
  1079. #if DBG
  1080. // Detect if a pSrb is used more than once
  1081. if((*plSrbUseCount) > 1) {
  1082. TRACE(TL_CIP_TRACE,("\'* Go: pSrb:%x; RefCnt:%d; cntSrbQ:%d; PicNum:%d; Drp:%d; PresTime:%d >= CurTime:%d\n",
  1083. pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->FramesDropped,
  1084. (DWORD) (pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000), (DWORD) tmExpectedFrame/10000));
  1085. }
  1086. #endif
  1087. if(pStrmExt->bEOStream) {
  1088. // Remove NEXT(SrbQ) only if there are more than one SRB or bEOStream
  1089. TRACE(TL_CIP_TRACE,("\'EOStream=== Srb:%x; (SrbNum:%d ?= PicNum:%d) cntSrbQ:%d; Attach:%d ===\n",
  1090. pSrb, pSrbEntry->SrbNum, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->cntSRBQueued, (DWORD) pStrmExt->cntDataAttached));
  1091. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--;
  1092. ExFreePool(pSrbEntry); pSrbEntry = NULL; // Removed so free it!
  1093. // Remove SRB if more than one SRBs in Q and there is not a discontinuity, or end of stream.
  1094. } else if(pStrmExt->cntSRBQueued > 1) {
  1095. LONGLONG tmExpectedNextFrame = tmExpectedFrame + DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulAvgTimePerFrame;
  1096. pSrbNext = ((SRB_ENTRY *) (pSrbEntry->ListEntry.Flink))->pSrb;
  1097. // Next SRB has the next presentation time
  1098. // May add this check as well: (but check Presentation time is more reliable)
  1099. // pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
  1100. /* N,N+1 */ if((tmExpectedNextFrame + ALLOWABLE_TIMING_LATENCY) > pSrbNext->CommandData.DataBufferArray->PresentationTime.Time) {
  1101. TRACE(TL_CIP_TRACE,("\'=== Srb:%x; (SrbNum:%d ?= PicNum:%d) cntSrbQ:%d; Attach:%d ===\n",
  1102. pSrb, pSrbEntry->SrbNum, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->cntSRBQueued, (DWORD) pStrmExt->cntDataAttached));
  1103. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--;
  1104. ExFreePool(pSrbEntry); pSrbEntry = NULL; // Removed so free it!
  1105. /* N, N+2/++ */ } else {
  1106. TRACE(TL_CIP_TRACE,("\'=== GO(Stale=TRUE) Srb:%x; (SrbNum:%d ?= PicNum:%d) Attach:%d ==\n",
  1107. pSrb, pSrbEntry->SrbNum, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->cntDataAttached));
  1108. // Mark this stale and be remove as soon as another is attached.
  1109. }
  1110. }
  1111. else {
  1112. TRACE(TL_CIP_TRACE,("\'=== GO(Stale=TRUE) Srb:%x; (SrbNum:%d ?= PicNum:%d) Attach:%d ==\n",
  1113. pSrb, pSrbEntry->SrbNum, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->cntDataAttached));
  1114. // Mark this stale and be remove as soon as another is attached.
  1115. pSrbEntry->bStale = TRUE;
  1116. }
  1117. // CLOCK: tick when a frame is transmitted.
  1118. // LATE: this is dropped until there is only one Srb in the SrbQ.
  1119. // WORKITEM: we may need to implement IQualityManagement to inform application to read ahead.
  1120. /*Late*/ }
  1121. /*N-1*/ else {
  1122. if(pStrmExt->cntSRBQueued > 1) {
  1123. pSrbNext = ((SRB_ENTRY *) (pSrbEntry->ListEntry.Flink))->pSrb;
  1124. // Next SRB has the next presentation time; it can be:
  1125. // Current time is N
  1126. // Current frame is late (N-1 or N-2..) and we have more than one Srb in the queue;
  1127. // check next frame:
  1128. // (N?)
  1129. // N-2, N-1, N late more than one frame; (Next frame is also late; dequeu and not transmit; "catch up" case.)
  1130. // N-1, N late one frame; (Next frame is on time; dequeu this frame) <-- Normal case
  1131. // N-1, N+1 late one frame, but next frame is not N+1; (Next frame is early; *current frame will be repeated*)
  1132. //
  1133. // May add this check this as well: (but check Presentation time is more reliable)
  1134. // pSrb->CommandData.DataBufferArray->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY
  1135. //
  1136. // ******************************************************************************************************
  1137. // If next frame is earlier than current stream time, "repeat" current stale frame; else we need to "catch up"!
  1138. // ******************************************************************************************************
  1139. /* N-1++, N */ if((tmExpectedFrame + ALLOWABLE_TIMING_LATENCY) > pSrbNext->CommandData.DataBufferArray->PresentationTime.Time) {
  1140. TRACE(TL_CIP_TRACE,("\'*** Stale(not Sent): pSrb:%x; RefCnt:%d; cntSrbQ:%d; cntAtt:%d; PicNum:%d; Drp:%d; PTm:%d < ExpTm:%d\n",
  1141. pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued, pStrmExt->cntDataAttached, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->FramesDropped,
  1142. (DWORD) (pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000), (DWORD) (tmExpectedFrame/10000) ));
  1143. // Never been attached; remove late entry
  1144. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--;
  1145. ExFreePool(pSrbEntry); pSrbEntry = NULL; // Removed so free it!
  1146. if(*plSrbUseCount == 0) {
  1147. // If no reference to is, complete this.
  1148. pSrb->Status = STATUS_SUCCESS; // It is not a failure but late; maybe other status to indicate "non-fatal" late status..
  1149. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  1150. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  1151. #if DBG
  1152. pStrmExt->cntSRBPending--;
  1153. #endif
  1154. }
  1155. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  1156. // Since SrbQ is not empty and this is a stale frame, call recursively to get to next frame.
  1157. // Only possible error is if there is not sufficient resource (esp MDL)
  1158. // then, we bail out by self terminating this thread.
  1159. if(STATUS_INSUFFICIENT_RESOURCES ==
  1160. DVAttachWriteFrame(pStrmExt)) {
  1161. TRACE(TL_CIP_ERROR,("DVAttachWriteFrame: STATUS_INSUFFICIENT_RESOURCES\n"));
  1162. return STATUS_INSUFFICIENT_RESOURCES;
  1163. } else {
  1164. return STATUS_SUCCESS; // SUCESS unless there is another status to indicate "non-fatal" late.
  1165. }
  1166. /*N-2++, N-1++*/ } else {
  1167. pSrbEntry->bStale = TRUE;
  1168. }
  1169. }
  1170. else {
  1171. // EOStream and is a stale stream, it is the last element in SrbQ.
  1172. // Remove it.
  1173. if(pStrmExt->bEOStream) {
  1174. TRACE(TL_CIP_TRACE,("\'*** Stale(bEOStream): pSrb:%x; RefCnt:%d; cntSrbQ:%d; cntAtt:%d; PicNum:%d; Drp:%d; PTm:%d < ExpTm:%d\n",
  1175. pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued, pStrmExt->cntDataAttached, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->FramesDropped,
  1176. (DWORD) (pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000), (DWORD) (tmExpectedFrame/10000) ));
  1177. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--;
  1178. ExFreePool(pSrbEntry); pSrbEntry = NULL; // Removed so free it!
  1179. if(*plSrbUseCount == 0) {
  1180. // If no reference to is, complete this.
  1181. pSrb->Status = STATUS_SUCCESS; // It is not a failure but late; maybe other status to indicate "non-fatal" late status..
  1182. pSrb->CommandData.DataBufferArray->DataUsed = 0;
  1183. StreamClassStreamNotification(StreamRequestComplete, pSrb->StreamObject, pSrb);
  1184. #if DBG
  1185. pStrmExt->cntSRBPending--;
  1186. #endif
  1187. }
  1188. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  1189. // Update current stream time
  1190. pStrmExt->CurrentStreamTime = tmExpectedFrame;
  1191. return STATUS_SUCCESS; // SUCESS unless there is another status to indicate "non-fatal" late.
  1192. }
  1193. TRACE(TL_CIP_TRACE,("\'*** Stale(Sent): pSrb:%x; RefCnt:%d; cntSrbQ:%d; cntAtt:%d; PicNum:%d; Drp:%d; PTm:%d < ExpTm:%d\n",
  1194. pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued, pStrmExt->cntDataAttached, (DWORD) pStrmExt->PictureNumber, (DWORD) pStrmExt->FramesDropped,
  1195. (DWORD) (pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000), (DWORD) (tmExpectedFrame/10000) ));
  1196. // If this is stale and this is the only frame in SrbQ, Xmt it
  1197. }
  1198. // If late, this frame is always drop.
  1199. pStrmExt->FramesDropped++;
  1200. }
  1201. // Update current stream time
  1202. pStrmExt->CurrentStreamTime = tmExpectedFrame;
  1203. } // if(pStrmExt->hMasterClock)
  1204. else {
  1205. // Not the master clock, no "pacing" so always dequeu (SrbQ) and transmit
  1206. // as long as there is one Srb in the queue.
  1207. if(pStrmExt->cntSRBQueued > 1 || pStrmExt->bEOStream) {
  1208. RemoveEntryList(&pSrbEntry->ListEntry); pStrmExt->cntSRBQueued--; (*plSrbUseCount)--;
  1209. ExFreePool(pSrbEntry); pSrbEntry = NULL; // Removed so free it!
  1210. }
  1211. TRACE(TL_CIP_TRACE,("\'* GO: (NoClock) pSrb:%x; RefCnt:%d; cntSrbQ:%d; PicNum:%d;\n", pSrb, *plSrbUseCount, pStrmExt->cntSRBQueued, (DWORD) pStrmExt->PictureNumber));
  1212. } // if(pStrmExt->hMasterClock)
  1213. // pStrmExt->FramesProcessed is updated when a frame has been transmitted in the notify routine.
  1214. // **** THIS IS THE CLOCK TICK ****
  1215. pStrmExt->PictureNumber++; // After tmExpectedFrame is calculated; Another frame to be attached
  1216. if(pStrmExt->hMasterClock) {
  1217. #ifdef SUPPORT_QUALITY_CONTROL
  1218. // +: late; -: early
  1219. pStrmExt->KSQuality.DeltaTime = pStrmExt->CurrentStreamTime - pSrb->CommandData.DataBufferArray->PresentationTime.Time;
  1220. // Percentage * 10 of frame transmitted
  1221. pStrmExt->KSQuality.Proportion = (ULONG)
  1222. ((pStrmExt->PictureNumber - pStrmExt->FramesDropped) * 1000 / pStrmExt->PictureNumber);
  1223. pStrmExt->KSQuality.Context = /* NOT USED */ 0;
  1224. #define MIN_ATTACH_BUFFER 3
  1225. // This is where we may want to signal that we are near Famine!!
  1226. if (pStrmExt->KSQuality.DeltaTime >
  1227. (DV_NUM_OF_XMT_BUFFERS - MIN_ATTACH_BUFFER) * DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulAvgTimePerFrame) {
  1228. TRACE(TL_CIP_TRACE,("\'QualityControl: pic#%d; drop:%d; Prop:%d; DeltaTime:%d (Srb.tmPres:%d, tmStream:%d)\n",
  1229. (DWORD) pStrmExt->PictureNumber,
  1230. (DWORD) pStrmExt->FramesDropped,
  1231. pStrmExt->KSQuality.Proportion,
  1232. (DWORD) pStrmExt->KSQuality.DeltaTime/10000,
  1233. (DWORD) pSrb->CommandData.DataBufferArray->PresentationTime.Time/10000,
  1234. (DWORD) pStrmExt->CurrentStreamTime/10000
  1235. ));
  1236. }
  1237. #endif
  1238. }
  1239. } // KSSTATE_RUN
  1240. #if DBG
  1241. // Collect transmit buffer statistics
  1242. if(pStrmExt->ulStatEntries < MAX_XMT_FRAMES_TRACED) {
  1243. pXmtStat = pStrmExt->paXmtStat + pStrmExt->ulStatEntries;
  1244. pXmtStat->StreamState = pStrmExt->StreamState;
  1245. pXmtStat->cntSRBReceived = (LONG) pStrmExt->cntSRBReceived;
  1246. pXmtStat->cntSRBPending = (LONG) pStrmExt->cntSRBPending;
  1247. pXmtStat->cntSRBQueued = (LONG) pStrmExt->cntSRBQueued;
  1248. pXmtStat->cntDataAttached= pStrmExt->cntDataAttached;
  1249. pXmtStat->FrameSlot = (DWORD) pStrmExt->PictureNumber;
  1250. pXmtStat->tmStreamTime = pStrmExt->CurrentStreamTime;
  1251. pXmtStat->DropCount = (DWORD) pStrmExt->FramesDropped;
  1252. pXmtStat->FrameNumber = SrbNumCache;
  1253. pXmtStat->OptionsFlags = pSrb->CommandData.DataBufferArray->OptionsFlags;
  1254. pXmtStat->tmPresentation = pSrb->CommandData.DataBufferArray->PresentationTime.Time;
  1255. // get the actual CyclTime when the frame is transmitted in the completion routine.
  1256. pStrmExt->ulStatEntries++;
  1257. }
  1258. #endif
  1259. #ifdef MSDV_SUPPORT_MUTE_AUDIO
  1260. // pSrbEntry could have been freed; if it has not and useCnt>1, then it could be a repeat frame.
  1261. if(pSrbEntry && (*plSrbUseCount) > 1) {
  1262. // Set it only once
  1263. if(!pSrbEntry->bAudioMute)
  1264. pSrbEntry->bAudioMute =
  1265. DVMuteDVFrame(pStrmExt->pDevExt, pFrameBuffer, TRUE);
  1266. }
  1267. #endif
  1268. // Get a data packet node as the context and list node
  1269. pSrbDataPacket = (PSRB_DATA_PACKET) RemoveHeadList(&pStrmExt->DataDetachedListHead); pStrmExt->cntDataDetached--;
  1270. ulSrcPktLen = \
  1271. (DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].DataBlockSize << 2) * \
  1272. (1 << DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].FractionNumber);
  1273. // Format an attach frame request
  1274. DVFormatAttachFrame(
  1275. pStrmExt->pStrmInfo->DataFlow,
  1276. pStrmExt,
  1277. &pSrbDataPacket->AVReq,
  1278. pSrb,
  1279. pSrbDataPacket,
  1280. ulSrcPktLen,
  1281. DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulFrameSize,
  1282. pFrameBuffer
  1283. );
  1284. TRACE(TL_CIP_INFO,("\'------ New>> UseCnt:%d; pAVReq:%x; Srb:%x; DtaPkt:%x; AQD [%d:%d:%d]\n",
  1285. *plSrbUseCount,
  1286. &pSrbDataPacket->AVReq,
  1287. pSrb,
  1288. pSrbDataPacket,
  1289. pStrmExt->cntDataAttached,
  1290. pStrmExt->cntSRBQueued,
  1291. pStrmExt->cntDataDetached
  1292. ));
  1293. // Add this to the attached list
  1294. InsertTailList(&pStrmExt->DataAttachedListHead, &pSrbDataPacket->ListEntry); pStrmExt->cntDataAttached++;
  1295. (*plSrbUseCount) ++; // ++ for being in queue
  1296. ASSERT(*plSrbUseCount > 0);
  1297. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  1298. NextIrpStack = IoGetNextIrpStackLocation(pSrbDataPacket->pIrp);
  1299. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1300. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  1301. NextIrpStack->Parameters.Others.Argument1 = &pSrbDataPacket->AVReq;
  1302. IoSetCompletionRoutine(
  1303. pSrbDataPacket->pIrp,
  1304. DVAttachFrameCR,
  1305. pSrbDataPacket,
  1306. TRUE,
  1307. TRUE,
  1308. TRUE
  1309. );
  1310. pSrbDataPacket->pIrp->IoStatus.Status = STATUS_SUCCESS; // Initialize it to something
  1311. Status = IoCallDriver( pStrmExt->pDevExt->pBusDeviceObject, pSrbDataPacket->pIrp);
  1312. ASSERT(Status == STATUS_PENDING || Status == STATUS_SUCCESS);
  1313. if(!NT_SUCCESS(Status)) {
  1314. // put the resource back!
  1315. TRACE(TL_CIP_ERROR,("DVAttachWriteFrame: Failed to attach; St:%x\n", Status));
  1316. ASSERT(FALSE && "Failed to attach a Xmt frame.");
  1317. }
  1318. //
  1319. // This is our throttle that regulate data attach to DV:
  1320. //
  1321. // This function is called by the attach thread which is running in an infinite loop.
  1322. // This function need to utilize the buffer that it receive and its repeat mechanism to
  1323. // regulate the incoming buffer from client and outgoing buffer attach to 1394 stadck for transmit.
  1324. // One way is to wait while there is certain number of frame already attach.
  1325. KeAcquireSpinLock(pStrmExt->DataListLock, &oldIrql);
  1326. if(!pStrmExt->bEOStream &&
  1327. // Need to keep NUM_BUF_ATTACHED_THEN_ISOCH buffer attached at all time to keep 61883 isoch xmt going.
  1328. (pStrmExt->StreamState == KSSTATE_RUN && pStrmExt->cntDataAttached > NUM_BUF_ATTACHED_THEN_ISOCH ||
  1329. pStrmExt->StreamState == KSSTATE_PAUSE && pStrmExt->cntDataAttached >= NUM_BUF_ATTACHED_THEN_ISOCH )
  1330. ) {
  1331. NTSTATUS StatusDelay = STATUS_SUCCESS;
  1332. #if DBG
  1333. ULONGLONG tmStart = GetSystemTime();
  1334. TRACE(TL_CIP_TRACE,("\'[Pic# %d]; SrbNum:%d; Dropped:%d; pSrb:%x; StrmSt:%d; EOS:%d; AQD:[%d;%d;%d]; ",
  1335. (DWORD) pStrmExt->PictureNumber, SrbNumCache, (DWORD) pStrmExt->FramesDropped, pSrb, pStrmExt->StreamState, pStrmExt->bEOStream,
  1336. pStrmExt->cntDataAttached, pStrmExt->cntSRBQueued, pStrmExt->cntDataDetached));
  1337. #endif
  1338. Timeout.HighPart = -1;
  1339. Timeout.LowPart = (ULONG)(-1 * DVFormatInfoTable[pStrmExt->pDevExt->VideoFormatIndex].ulAvgTimePerFrame * \
  1340. (pStrmExt->StreamState == KSSTATE_PAUSE ? 1 : (pStrmExt->cntDataAttached - NUM_BUF_ATTACHED_THEN_ISOCH))) ;
  1341. // Wait the full time until we are very low in SrbQ or Attached buffers.
  1342. if(pStrmExt->cntSRBQueued <= 1 && pStrmExt->cntDataAttached <= NUM_BUF_ATTACHED_THEN_ISOCH) {
  1343. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql); // Guard against pStrmExt->cntSRBQueued
  1344. // Down to one frame so we will wait for an event and will be signalled
  1345. // when a new frame has arrived, or
  1346. // when number of attach buffer is below the minimum.
  1347. StatusDelay =
  1348. KeWaitForSingleObject(
  1349. &pStrmExt->hSrbArriveEvent,
  1350. Executive,
  1351. KernelMode,
  1352. FALSE,
  1353. &Timeout
  1354. );
  1355. // Important: If signalled, reset it else (timeout),
  1356. // we are still behind so next time we will not wait!
  1357. if(StatusDelay == STATUS_SUCCESS)
  1358. KeClearEvent(&pStrmExt->hSrbArriveEvent);
  1359. }
  1360. else {
  1361. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  1362. // Wait for frame(s) to be delivered; this is our throttle..
  1363. // The timeout period can be one or up to
  1364. // (pStrmExt->cntDataAttached - NUM_BUF_ATTACHED_THEN_ISOCH) frames
  1365. KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
  1366. }
  1367. #if DBG
  1368. TRACE(TL_CIP_TRACE,("\'Wait(ST:%x) %d nsec!\n", StatusDelay, (DWORD) ((GetSystemTime() - tmStart)/10)));
  1369. #endif
  1370. } else {
  1371. KeReleaseSpinLock(pStrmExt->DataListLock, oldIrql);
  1372. }
  1373. return Status;
  1374. }
  1375. VOID
  1376. DVFormatAttachFrame(
  1377. IN KSPIN_DATAFLOW DataFlow,
  1378. IN PSTREAMEX pStrmExt,
  1379. IN PAV_61883_REQUEST pAVReq,
  1380. IN PHW_STREAM_REQUEST_BLOCK pSrb,
  1381. IN PSRB_DATA_PACKET pSrbDataPacket,
  1382. IN ULONG ulSourceLength, // Packet length in bytes
  1383. IN ULONG ulFrameSize, // Buffer size; may contain one or multiple source packets
  1384. IN PVOID pFrameBuffer
  1385. )
  1386. /*++
  1387. Routine Description:
  1388. Format an attach frame request.
  1389. --*/
  1390. {
  1391. ASSERT(pSrb);
  1392. //
  1393. // Setup PSRB_DATA_PACKET, except its Frame structure (PCIP_APP_FRAME)
  1394. //
  1395. InitializeListHead(&pSrbDataPacket->ListEntry);
  1396. pSrbDataPacket->State = DE_PREPARED; // Initial state of a resued DataEntry (start over!)
  1397. pSrbDataPacket->pSrb = pSrb;
  1398. pSrbDataPacket->StreamState = pStrmExt->StreamState; // StreamState when this buffer is attached.
  1399. pSrbDataPacket->pStrmExt = pStrmExt;
  1400. pSrbDataPacket->FrameBuffer = pFrameBuffer;
  1401. ASSERT(pSrbDataPacket->FrameBuffer != NULL);
  1402. pSrbDataPacket->Frame->pNext = NULL;
  1403. pSrbDataPacket->Frame->Status = 0;
  1404. pSrbDataPacket->Frame->Packet = (PUCHAR) pFrameBuffer;
  1405. if(DataFlow == KSPIN_DATAFLOW_OUT) {
  1406. pSrbDataPacket->FrameNumber = pStrmExt->cntSRBReceived;
  1407. #ifdef NT51_61883
  1408. // This is needed since we have an old 61883.h in Lab06 (according to include path, anyway).
  1409. // Remove this when 61883.h is updated.
  1410. #ifndef CIP_RESET_FRAME_ON_DISCONTINUITY
  1411. #define CIP_RESET_FRAME_ON_DISCONTINUITY 0x00000040
  1412. #endif
  1413. //
  1414. // Set CIP_USE_SOURCE_HEADER_TIMESTAMP to get 25 bit CycleTime from source packet header (13CycleCount:12CycleOffset)
  1415. // Do not set this to get 16 bit CycleTime from isoch packet (3 SecondCount:13CycleCount)
  1416. //
  1417. pSrbDataPacket->Frame->Flags = CIP_VALIDATE_FIRST_SOURCE // Verify the start of a DV frame
  1418. | CIP_RESET_FRAME_ON_DISCONTINUITY; // No partial frame
  1419. #else
  1420. pSrbDataPacket->Frame->Flags = 0;
  1421. #endif
  1422. pSrbDataPacket->Frame->pfnValidate = DVReadFrameValidate; // use to validate the 1st source packet
  1423. pSrbDataPacket->Frame->ValidateContext = pSrbDataPacket;
  1424. pSrbDataPacket->Frame->pfnNotify = DVCompleteSrbRead;
  1425. }
  1426. else {
  1427. pSrbDataPacket->FrameNumber = pStrmExt->FramesProcessed;
  1428. pSrbDataPacket->Frame->Flags = CIP_DV_STYLE_SYT;
  1429. pSrbDataPacket->Frame->pfnValidate = NULL;
  1430. pSrbDataPacket->Frame->ValidateContext = NULL;
  1431. pSrbDataPacket->Frame->pfnNotify = DVCompleteSrbWrite;
  1432. }
  1433. pSrbDataPacket->Frame->NotifyContext = pSrbDataPacket;
  1434. //
  1435. // Av61883_AttachFrames
  1436. //
  1437. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1438. INIT_61883_HEADER(pAVReq, Av61883_AttachFrame);
  1439. pAVReq->AttachFrame.hConnect = pStrmExt->hConnect;
  1440. pAVReq->AttachFrame.FrameLength = ulFrameSize;
  1441. pAVReq->AttachFrame.SourceLength = ulSourceLength;
  1442. pAVReq->AttachFrame.Frame = pSrbDataPacket->Frame;
  1443. ASSERT(pStrmExt->hConnect);
  1444. ASSERT(pSrbDataPacket->Frame);
  1445. }
  1446. VOID
  1447. DVAttachFrameThread(
  1448. IN PSTREAMEX pStrmExt
  1449. )
  1450. /*++
  1451. Routine Description:
  1452. This is a system thread to attach frame for transmit.
  1453. --*/
  1454. {
  1455. NTSTATUS Status;
  1456. PDVCR_EXTENSION pDevExt;
  1457. KIRQL OldIrql;
  1458. PAGED_CODE();
  1459. pDevExt = pStrmExt->pDevExt;
  1460. //
  1461. // Pump up the priority since we are dealing with real time data
  1462. //
  1463. KeSetPriorityThread(KeGetCurrentThread(),
  1464. #if 1
  1465. LOW_REALTIME_PRIORITY
  1466. #else
  1467. HIGH_PRIORITY
  1468. #endif
  1469. );
  1470. while (!pStrmExt->bTerminateThread) {
  1471. //
  1472. // Halt this thread operation if other critical service
  1473. // is requested.
  1474. //
  1475. if(
  1476. !pStrmExt->bTerminateThread
  1477. && (pStrmExt->lNeedService > 0)
  1478. ) { // not fullly awake/powered.
  1479. NTSTATUS StatusWait;
  1480. TRACE(TL_CIP_WARNING,("\'Request stop thread for other service: lNeedService:%d; pStrmExt:%x; AQD[%d,%d,%d]\n",
  1481. pStrmExt->lNeedService, pStrmExt,
  1482. pStrmExt->cntDataAttached,
  1483. pStrmExt->cntSRBQueued,
  1484. pStrmExt->cntDataDetached
  1485. ));
  1486. InterlockedDecrement(&pStrmExt->lNeedService); // One reuqest serviced.
  1487. //
  1488. // Indicate that thread is about to stop. Signal it so other operation can begin.
  1489. //
  1490. KeSetEvent(&pStrmExt->hStopThreadEvent, 0 ,FALSE);
  1491. TRACE(TL_CIP_WARNING,("\'>>>> Enter WFSO(hRunThreadEvent)\n"));
  1492. StatusWait =
  1493. KeWaitForSingleObject(
  1494. &pStrmExt->hRunThreadEvent,
  1495. Executive,
  1496. KernelMode,
  1497. FALSE,
  1498. 0
  1499. );
  1500. TRACE(TL_CIP_WARNING,("\'<<<< Exit WFSO(hRunThreadEvent); lNeedService:%d\n", pStrmExt->lNeedService));
  1501. ASSERT(pStrmExt->lNeedService == 0);
  1502. }
  1503. // Halt attach operation if
  1504. // not in either PAUSE or RUN state ( i.e. in STOP state)
  1505. // Device is removed
  1506. // in the process of being cancelled.
  1507. if(
  1508. !pStrmExt->bTerminateThread
  1509. && pStrmExt->StreamState != KSSTATE_PAUSE
  1510. && pStrmExt->StreamState != KSSTATE_RUN
  1511. || pStrmExt->pDevExt->bDevRemoved
  1512. || pStrmExt->lCancelStateWorkItem > 0
  1513. ) {
  1514. NTSTATUS StatusWait;
  1515. TRACE(TL_CIP_WARNING,("\'Enter WFSO(hSrbArriveEvent): StrmState:%d; bDevRemoved:%d\n", pStrmExt->StreamState, pStrmExt->pDevExt->bDevRemoved));
  1516. StatusWait = // Can only return STATUS_SUCCESS (signal) or STATUS_TIMEOUT
  1517. KeWaitForSingleObject(
  1518. &pStrmExt->hSrbArriveEvent, // Signal with arrival of the first frame
  1519. Executive,
  1520. KernelMode, // Cannot return STATUS_USER_APC
  1521. FALSE, // Cannot be alerted STATUS_ALERTED
  1522. 0 // INFINITE!!
  1523. );
  1524. // Reset notification event (or it will stay signalled).
  1525. KeClearEvent(&pStrmExt->hSrbArriveEvent);
  1526. TRACE(TL_CIP_WARNING,("\'Exit WFSO(hSrbArriveEvent): StrmState:%d; bDevRemoved:%d\n", pStrmExt->StreamState, pStrmExt->pDevExt->bDevRemoved));
  1527. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  1528. // Simulate preroll at the RUN state
  1529. // We do this only when we are the clock provider to avoid dropping frame
  1530. // This timed WFSO is necessary if application send us only one frame while in RUN state.
  1531. #define PREROLL_WAITTIME 2000000
  1532. if(
  1533. !pStrmExt->bTerminateThread &&
  1534. pStrmExt->hMasterClock
  1535. ) {
  1536. LARGE_INTEGER DueTime;
  1537. DueTime = RtlConvertLongToLargeInteger(-((LONG) PREROLL_WAITTIME));
  1538. TRACE(TL_CIP_WARNING,("\'Enter WFSO(hPreRollEvent)\n"));
  1539. StatusWait = // Can only return STATUS_SUCCESS (signal) or STATUS_TIMEOUT
  1540. KeWaitForSingleObject(
  1541. &pStrmExt->hPreRollEvent,
  1542. Executive,
  1543. KernelMode, // Cannot return STATUS_USER_APC
  1544. FALSE, // Cannot be alerted STATUS_ALERTED
  1545. &DueTime
  1546. );
  1547. // hPreRollEvent is a ont shot event; no need to reset it; let it stay signalled.
  1548. TRACE(TL_CIP_WARNING,("\'Exit WFSO(hPreRollEvent); waited %d msec; waitStatus:%x\n", (DWORD) ((GetSystemTime() - pStrmExt->tmStreamStart)/10000), StatusWait ));
  1549. }
  1550. #endif
  1551. }
  1552. #if DBG
  1553. if(
  1554. !pStrmExt->bTerminateThread
  1555. && !pStrmExt->bEOStream
  1556. && pStrmExt->FramesProcessed > 0
  1557. && pStrmExt->cntDataAttached < NUM_BUF_ATTACHED_THEN_ISOCH
  1558. ) {
  1559. TRACE(TL_CIP_TRACE,("\'AttachBuf is low!! SrbRcv:%d;Pic#:%d;Prc:%d;;Drop:%d;Cncl:%d; AQD [%d:%d:%d]\n",
  1560. (DWORD) pStrmExt->cntSRBReceived,
  1561. (DWORD) pStrmExt->PictureNumber,
  1562. (DWORD) pStrmExt->FramesProcessed,
  1563. (DWORD) pStrmExt->FramesDropped,
  1564. (DWORD) pStrmExt->cntSRBCancelled,
  1565. pStrmExt->cntDataAttached,
  1566. pStrmExt->cntSRBQueued,
  1567. pStrmExt->cntDataDetached
  1568. ));
  1569. }
  1570. #endif
  1571. // Attach another frame for transmit
  1572. // Only possible error is if there is not sufficient resource (esp MDL)
  1573. // Then, we bail out by self terminating this thread.
  1574. if(
  1575. !pStrmExt->pDevExt->bDevRemoved
  1576. && !pStrmExt->bTerminateThread
  1577. ) {
  1578. if(STATUS_INSUFFICIENT_RESOURCES == \
  1579. DVAttachWriteFrame(pStrmExt)) {
  1580. TRACE(TL_CIP_ERROR,("STATUS_INSUFFICIENT_RESOURCES while attaching write frame.\n"));
  1581. pStrmExt->bTerminateThread = TRUE;
  1582. }
  1583. }
  1584. //
  1585. // Start Isoch_Talk once we have enough buffers attached.
  1586. // It is possible that streaming state is set to RUN before we have enough attach buffer
  1587. // start streaming. So we need to kick start here.
  1588. //
  1589. if(
  1590. !pStrmExt->bTerminateThread
  1591. && !pStrmExt->pDevExt->bDevRemoved
  1592. && pStrmExt->pDevExt->PowerState == PowerDeviceD0 // Need to be PoweredON
  1593. && pStrmExt->lCancelStateWorkItem == 0 // No pending cancel work item
  1594. && !pStrmExt->bIsochIsActive
  1595. && (pStrmExt->StreamState == KSSTATE_PAUSE || pStrmExt->StreamState == KSSTATE_RUN)
  1596. && pStrmExt->cntDataAttached >= NUM_BUF_ATTACHED_THEN_ISOCH
  1597. ) {
  1598. Status =
  1599. DVStreamingStart(
  1600. pStrmExt->pStrmInfo->DataFlow,
  1601. pStrmExt,
  1602. pStrmExt->pDevExt
  1603. );
  1604. }
  1605. }
  1606. TRACE(TL_STRM_WARNING,("\'*** ThreadTerminating... AQD [%d:%d:%d]\n",
  1607. pStrmExt->cntDataAttached,
  1608. pStrmExt->cntSRBQueued,
  1609. pStrmExt->cntDataDetached
  1610. ));
  1611. KeAcquireSpinLock(&pStrmExt->pDevExt->AVCCmdLock, &OldIrql);
  1612. if(pStrmExt->lNeedService) {
  1613. TRACE(TL_STRM_WARNING,("Thread is exiting but lNeedService:%x != 0!\n", pStrmExt->lNeedService));
  1614. KeSetEvent(&pStrmExt->hStopThreadEvent, 0 ,FALSE);
  1615. InterlockedDecrement(&pStrmExt->lNeedService);
  1616. ASSERT(pStrmExt->lNeedService == 0);
  1617. }
  1618. KeReleaseSpinLock(&pStrmExt->pDevExt->AVCCmdLock, OldIrql);
  1619. KeSetEvent(&pStrmExt->hThreadEndEvent, 0, FALSE); // Signal it
  1620. Status = PsTerminateSystemThread(STATUS_SUCCESS); // Must be called at PASSIVE_LEVEL
  1621. // End of this thread!
  1622. }
  1623. VOID
  1624. DVTerminateAttachFrameThread(
  1625. IN PSTREAMEX pStrmExt
  1626. )
  1627. /*++
  1628. Routine Description:
  1629. To terminate the system thread. It waits for an event that is triggered
  1630. right before PsTerminateSystemThread() is called.
  1631. --*/
  1632. {
  1633. PAGED_CODE();
  1634. TRACE(TL_CIP_WARNING,("\'DVTerminateAttachFrameThread enter\n"));
  1635. //
  1636. // Wake up the DataReady thread and terminate it if not already done so.
  1637. //
  1638. ASSERT(pStrmExt->bIsochIsActive == FALSE && "Terminate therad while IsochActive!");
  1639. //
  1640. // This function can be called from either CloseStrean or SurpriseRemoval;
  1641. // When a DV is surprise removal, this function may get called from both functions.
  1642. // Assuming StreamClass is serializing these two functions, no need to serialize it locally.
  1643. //
  1644. if(pStrmExt->bTerminateThread) {
  1645. TRACE(TL_CIP_ERROR,("DVTerminateAttachFrameThread: Thread already terminated. Was surprise removed?\n"));
  1646. return;
  1647. }
  1648. // ****** Terminate thread ******
  1649. pStrmExt->bTerminateThread = TRUE;
  1650. // ******
  1651. // With bTerminate thread set, let the thread run and terminate.
  1652. KeSetEvent(&pStrmExt->hRunThreadEvent, 0 ,FALSE);
  1653. // WFSO while in STOP state; signal so it can be terminated.
  1654. KeSetEvent(&pStrmExt->hSrbArriveEvent, 0, FALSE);
  1655. #ifdef SUPPORT_PREROLL_AT_RUN_STATE
  1656. // Signal it in case that it is still in WFSO.
  1657. KeSetEvent(&pStrmExt->hPreRollEvent, 0, FALSE);
  1658. #endif
  1659. KeWaitForSingleObject(
  1660. &pStrmExt->hThreadEndEvent,
  1661. Executive,
  1662. KernelMode,
  1663. FALSE,
  1664. NULL
  1665. );
  1666. TRACE(TL_CIP_WARNING,("\'Thread terminated!\n"));
  1667. ObDereferenceObject(
  1668. &pStrmExt->pAttachFrameThreadObject
  1669. );
  1670. TRACE(TL_CIP_WARNING,("\'ObDereferenceObject done!\n"));
  1671. }