Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2051 lines
70 KiB

  1. /*++
  2. Copyright (C) 1999 Microsoft Corporation
  3. Module Name:
  4. avcutil.c
  5. Abstract
  6. MS AVC streaming utility functions
  7. Author:
  8. Yee Wu 03/17/2000
  9. Revision History:
  10. Date Who What
  11. ----------- --------- ------------------------------------------------------------
  12. 03/17/2000 YJW created
  13. --*/
  14. #include "filter.h"
  15. #include "ksmedia.h" // KSPROERTY_DROPPEDFRAMES_CURRENT
  16. /************************************
  17. * Synchronous IOCall to lower driver
  18. ************************************/
  19. NTSTATUS
  20. IrpSynchCR(
  21. IN PDEVICE_OBJECT DeviceObject,
  22. IN PIRP pIrp,
  23. IN PKEVENT Event
  24. )
  25. {
  26. ENTER("IrpSynchCR");
  27. KeSetEvent(Event, 0, FALSE);
  28. return STATUS_MORE_PROCESSING_REQUIRED;
  29. } // IrpSynchCR
  30. NTSTATUS
  31. SubmitIrpSynch(
  32. IN PDEVICE_OBJECT DeviceObject,
  33. IN PIRP pIrp,
  34. IN PAV_61883_REQUEST pAVReq
  35. )
  36. {
  37. NTSTATUS Status;
  38. KEVENT Event;
  39. PIO_STACK_LOCATION NextIrpStack;
  40. ENTER("SubmitIrpSynch");
  41. Status = STATUS_SUCCESS;;
  42. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  43. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  44. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  45. NextIrpStack->Parameters.Others.Argument1 = pAVReq;
  46. KeInitializeEvent(&Event, NotificationEvent, FALSE);
  47. IoSetCompletionRoutine(
  48. pIrp,
  49. IrpSynchCR,
  50. &Event,
  51. TRUE,
  52. TRUE,
  53. TRUE
  54. );
  55. Status =
  56. IoCallDriver(
  57. DeviceObject,
  58. pIrp
  59. );
  60. if (Status == STATUS_PENDING) {
  61. TRACE(TL_PNP_INFO,("Irp is pending...\n"));
  62. if(KeGetCurrentIrql() < DISPATCH_LEVEL) {
  63. KeWaitForSingleObject(
  64. &Event,
  65. Executive,
  66. KernelMode,
  67. FALSE,
  68. NULL
  69. );
  70. TRACE(TL_PNP_TRACE,("Irp returned; IoStatus.Status %x\n", pIrp->IoStatus.Status));
  71. Status = pIrp->IoStatus.Status; // Final status
  72. }
  73. else {
  74. ASSERT(FALSE && "Pending but in DISPATCH_LEVEL!");
  75. return Status;
  76. }
  77. }
  78. EXIT("SubmitIrpSynch", Status);
  79. return Status;
  80. } // SubmitIrpSynchAV
  81. /****************************
  82. * Control utility functions
  83. ****************************/
  84. NTSTATUS
  85. AVCStrmGetPlugHandle(
  86. IN PDEVICE_OBJECT DeviceObject,
  87. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  88. )
  89. {
  90. NTSTATUS Status;
  91. PAV_61883_REQUEST pAVReq;
  92. PAGED_CODE();
  93. ENTER("AVCStrmGetPlugHandle");
  94. Status = STATUS_SUCCESS;
  95. // Claim ownership of hMutexAVReqIsoch
  96. KeWaitForMutexObject(&pAVCStrmExt->hMutexAVReq, Executive, KernelMode, FALSE, NULL);
  97. pAVReq = &pAVCStrmExt->AVReq;
  98. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  99. INIT_61883_HEADER(pAVReq, Av61883_GetPlugHandle);
  100. pAVReq->GetPlugHandle.PlugNum = 0;
  101. pAVReq->GetPlugHandle.hPlug = 0;
  102. pAVReq->GetPlugHandle.Type = pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT ? CMP_PlugOut : CMP_PlugIn;
  103. Status = SubmitIrpSynch(DeviceObject, pAVCStrmExt->pIrpAVReq, pAVReq);
  104. if(!NT_SUCCESS(Status)) {
  105. TRACE(TL_61883_ERROR,("GetPlugHandle: Failed:%x\n", Status));
  106. ASSERT(NT_SUCCESS(Status));
  107. pAVCStrmExt->hPlugRemote = NULL;
  108. }
  109. else {
  110. TRACE(TL_61883_TRACE,("GetPlugHandle:hPlug:%x\n", pAVReq->GetPlugHandle.hPlug));
  111. pAVCStrmExt->hPlugRemote = pAVReq->GetPlugHandle.hPlug;
  112. }
  113. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  114. EXIT("AVCStrmGetPlugHandle", Status);
  115. return Status;
  116. }
  117. NTSTATUS
  118. AVCStrmGetPlugState(
  119. IN PDEVICE_OBJECT DeviceObject,
  120. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  121. )
  122. /*++
  123. Routine Description:
  124. Ask 61883.sys for the plug state.
  125. Arguments:
  126. Return Value:
  127. Nothing
  128. --*/
  129. {
  130. NTSTATUS Status;
  131. PAV_61883_REQUEST pAVReq;
  132. PAGED_CODE();
  133. ENTER("AVCStrmGetPlugState");
  134. Status = STATUS_SUCCESS;
  135. //
  136. // Check only requirement: hConnect
  137. //
  138. if(pAVCStrmExt->hPlugRemote == NULL) {
  139. TRACE(TL_STRM_ERROR,("GetPlugState: hPlugRemote is NULL.\n"));
  140. ASSERT(pAVCStrmExt->hPlugRemote != NULL);
  141. return STATUS_UNSUCCESSFUL;
  142. }
  143. // Claim ownership of hMutexAVReqIsoch
  144. KeWaitForMutexObject(&pAVCStrmExt->hMutexAVReq, Executive, KernelMode, FALSE, NULL);
  145. pAVReq = &pAVCStrmExt->AVReq;
  146. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  147. INIT_61883_HEADER(pAVReq, Av61883_GetPlugState);
  148. pAVReq->GetPlugState.hPlug = pAVCStrmExt->hPlugRemote;
  149. Status =
  150. SubmitIrpSynch(
  151. DeviceObject,
  152. pAVCStrmExt->pIrpAVReq,
  153. pAVReq
  154. );
  155. if(!NT_SUCCESS(Status)) {
  156. TRACE(TL_61883_ERROR,("GetPlugState Failed %x\n", Status));
  157. }
  158. else {
  159. // Cache plug state (note: these are dynamic values)
  160. pAVCStrmExt->RemotePlugState = pAVReq->GetPlugState;
  161. TRACE(TL_61883_TRACE,("GetPlugState: ST %x; State %x; DRate %d; Payld %d; BCCnt %d; PPCnt %d\n",
  162. pAVReq->Flags ,
  163. pAVReq->GetPlugState.State,
  164. pAVReq->GetPlugState.DataRate,
  165. pAVReq->GetPlugState.Payload,
  166. pAVReq->GetPlugState.BC_Connections,
  167. pAVReq->GetPlugState.PP_Connections
  168. ));
  169. }
  170. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  171. EXIT("AVCStrmGetPlugState", Status);
  172. return Status;
  173. }
  174. NTSTATUS
  175. AVCStrmMakeConnection(
  176. IN PDEVICE_OBJECT DeviceObject,
  177. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  178. )
  179. /*++
  180. Routine Description:
  181. Make an isoch connection.
  182. --*/
  183. {
  184. NTSTATUS Status;
  185. PAV_61883_REQUEST pAVReq;
  186. PAVCSTRM_FORMAT_INFO pAVCStrmFormatInfo;
  187. PAGED_CODE();
  188. ENTER("AVCStrmMakeConnection");
  189. // Claim ownership of hMutexAVReqIsoch
  190. KeWaitForMutexObject(&pAVCStrmExt->hMutexAVReq, Executive, KernelMode, FALSE, NULL);
  191. TRACE(TL_61883_TRACE,("MakeConnect: State:%d; hConnect:%x\n", pAVCStrmExt->StreamState, pAVCStrmExt->hConnect));
  192. if(pAVCStrmExt->hConnect) {
  193. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  194. return STATUS_SUCCESS;
  195. }
  196. Status = STATUS_SUCCESS;
  197. pAVCStrmFormatInfo = pAVCStrmExt->pAVCStrmFormatInfo;
  198. pAVReq = &pAVCStrmExt->AVReq;
  199. INIT_61883_HEADER(pAVReq, Av61883_Connect);
  200. pAVReq->Connect.Type = CMP_PointToPoint; // !!
  201. // see which way we the data will flow...
  202. if(pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT) {
  203. // Remote(oPCR)->Local(iPCR)
  204. pAVReq->Connect.hOutputPlug = pAVCStrmExt->hPlugRemote;
  205. pAVReq->Connect.hInputPlug = pAVCStrmExt->hPlugLocal;
  206. // Other parameters !!
  207. } else {
  208. // Remote(iPCR)<-Local(oPCR)
  209. pAVReq->Connect.hOutputPlug = pAVCStrmExt->hPlugLocal;
  210. pAVReq->Connect.hInputPlug = pAVCStrmExt->hPlugRemote;
  211. pAVReq->Connect.Format.FMT = (UCHAR) pAVCStrmFormatInfo->cipHdr2.FMT; // From AV/C in/outpug plug signal format status cmd
  212. // 00 for NTSC, 80 for PAL; set the 50/60 bit
  213. // From AV/C in/outpug plug signal format status cmd
  214. pAVReq->Connect.Format.FDF_hi =
  215. ((UCHAR) pAVCStrmFormatInfo->cipHdr2.F5060_OR_TSF << 7) |
  216. ((UCHAR) pAVCStrmFormatInfo->cipHdr2.STYPE << 2) |
  217. ((UCHAR) pAVCStrmFormatInfo->cipHdr2.RSV);
  218. //
  219. // 16bit SYT field = 4BitCycleCount:12BitCycleOffset;
  220. // Will be set by 61883
  221. //
  222. pAVReq->Connect.Format.FDF_mid = 0;
  223. pAVReq->Connect.Format.FDF_lo = 0;
  224. //
  225. // Constants depend on the A/V data format (in or out plug format)
  226. //
  227. pAVReq->Connect.Format.bHeader = (BOOL) pAVCStrmFormatInfo->cipHdr1.SPH;
  228. pAVReq->Connect.Format.Padding = (UCHAR) pAVCStrmFormatInfo->cipHdr1.QPC;
  229. pAVReq->Connect.Format.BlockSize = (UCHAR) pAVCStrmFormatInfo->cipHdr1.DBS;
  230. pAVReq->Connect.Format.Fraction = (UCHAR) pAVCStrmFormatInfo->cipHdr1.FN;
  231. }
  232. pAVReq->Connect.Format.BlockPeriod = pAVCStrmFormatInfo->BlockPeriod;
  233. TRACE(TL_61883_TRACE,("Connect:hOutPlg:%x<->hInPlug:%x; cipQuad2[%.2x:%.2x:%.2x:%.2x]; BlkSz %d; SrcPkt %d; AvgTm %d, BlkPrd %d\n",
  234. pAVReq->Connect.hOutputPlug,
  235. pAVReq->Connect.hInputPlug,
  236. pAVReq->Connect.Format.FMT,
  237. pAVReq->Connect.Format.FDF_hi,
  238. pAVReq->Connect.Format.FDF_mid,
  239. pAVReq->Connect.Format.FDF_lo,
  240. pAVReq->Connect.Format.BlockSize,
  241. pAVCStrmFormatInfo->SrcPacketsPerFrame,
  242. pAVCStrmFormatInfo->AvgTimePerFrame,
  243. pAVReq->Connect.Format.BlockPeriod
  244. ));
  245. Status =
  246. SubmitIrpSynch(
  247. DeviceObject,
  248. pAVCStrmExt->pIrpAVReq,
  249. pAVReq
  250. );
  251. if(!NT_SUCCESS(Status)) {
  252. TRACE(TL_61883_ERROR,("Connect Failed = 0x%x\n", Status));
  253. pAVCStrmExt->hConnect = NULL;
  254. }
  255. else {
  256. TRACE(TL_61883_TRACE,("hConnect = 0x%x\n", pAVReq->Connect.hConnect));
  257. pAVCStrmExt->hConnect = pAVReq->Connect.hConnect;
  258. }
  259. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  260. EXIT("AVCStrmMakeConnection", Status);
  261. return Status;
  262. }
  263. NTSTATUS
  264. AVCStrmBreakConnection(
  265. IN PDEVICE_OBJECT DeviceObject,
  266. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  267. )
  268. /*++
  269. Routine Description:
  270. Break the isoch connection.
  271. --*/
  272. {
  273. NTSTATUS Status;
  274. PAV_61883_REQUEST pAVReq;
  275. #if DBG
  276. PAVC_STREAM_DATA_STRUCT pDataStruc;
  277. #endif
  278. PAGED_CODE();
  279. ENTER("AVCStrmBreakConnection");
  280. // Claim ownership of hMutexAVReqIsoch
  281. KeWaitForMutexObject(&pAVCStrmExt->hMutexAVReq, Executive, KernelMode, FALSE, NULL);
  282. TRACE(TL_STRM_TRACE,("BreakConnect: State:%d; hConnect:%x\n", pAVCStrmExt->StreamState, pAVCStrmExt->hConnect));
  283. if(!pAVCStrmExt->hConnect) {
  284. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  285. return STATUS_SUCCESS;
  286. }
  287. Status = STATUS_SUCCESS;
  288. #if DBG
  289. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  290. #endif
  291. pAVReq = &pAVCStrmExt->AVReq;
  292. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  293. INIT_61883_HEADER(pAVReq, Av61883_Disconnect);
  294. pAVReq->Disconnect.hConnect = pAVCStrmExt->hConnect;
  295. Status =
  296. SubmitIrpSynch(
  297. DeviceObject,
  298. pAVCStrmExt->pIrpAVReq,
  299. pAVReq
  300. );
  301. // This could be caused that the connection was not P2P, and
  302. // it tried to disconnect.
  303. if(!NT_SUCCESS(Status) || Status == STATUS_NO_SUCH_DEVICE) {
  304. TRACE(TL_61883_ERROR,("Disconnect Failed:%x; AvReq->ST %x\n", Status, pAVReq->Flags ));
  305. } else {
  306. TRACE(TL_61883_TRACE,("Disconnect suceeded; ST %x; AvReq->ST %x\n", Status, pAVReq->Flags ));
  307. }
  308. TRACE(TL_STRM_WARNING,("*** DisConn St:%x; Stat: DataRcved:%d; [Pic# =? Prcs:Drp:Cncl] [%d ?=%d+%d+%d]\n",
  309. Status,
  310. (DWORD) pDataStruc->cntDataReceived,
  311. (DWORD) pDataStruc->PictureNumber,
  312. (DWORD) pDataStruc->FramesProcessed,
  313. (DWORD) pDataStruc->FramesDropped,
  314. (DWORD) pDataStruc->cntFrameCancelled
  315. ));
  316. // We will not have another chance to reconnect it so we assume it is disconnected.
  317. pAVCStrmExt->hConnect = NULL;
  318. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  319. EXIT("AVCStrmBreakConnection", Status);
  320. return Status;
  321. }
  322. NTSTATUS
  323. AVCStrmStartIsoch(
  324. IN PDEVICE_OBJECT DeviceObject,
  325. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  326. )
  327. /*++
  328. Routine Description:
  329. Start streaming.
  330. --*/
  331. {
  332. NTSTATUS Status;
  333. PAVC_STREAM_DATA_STRUCT pDataStruc;
  334. PAGED_CODE();
  335. ENTER("AVCStrmStartIsoch");
  336. // Claim ownership of hMutexAVReqIsoch
  337. KeWaitForMutexObject(&pAVCStrmExt->hMutexAVReq, Executive, KernelMode, FALSE, NULL);
  338. if(pAVCStrmExt->IsochIsActive) {
  339. TRACE(TL_STRM_WARNING,("Isoch already active!"));
  340. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  341. return STATUS_SUCCESS;
  342. }
  343. if(!pAVCStrmExt->hConnect) {
  344. ASSERT(pAVCStrmExt->hConnect && "Cannot start isoch while graph is not connected!\n");
  345. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  346. return STATUS_INVALID_PARAMETER;
  347. }
  348. Status = STATUS_SUCCESS;
  349. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  350. TRACE(TL_61883_TRACE,("StartIsoch: flow %d; AQD [%d:%d:%d]\n", pAVCStrmExt->DataFlow, pDataStruc->cntDataAttached, pDataStruc->cntDataQueued, pDataStruc->cntDataDetached));
  351. RtlZeroMemory(&pAVCStrmExt->AVReq, sizeof(AV_61883_REQUEST));
  352. if(pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT) {
  353. INIT_61883_HEADER(&pAVCStrmExt->AVReq, Av61883_Listen);
  354. pAVCStrmExt->AVReq.Listen.hConnect = pAVCStrmExt->hConnect;
  355. } else {
  356. INIT_61883_HEADER(&pAVCStrmExt->AVReq, Av61883_Talk);
  357. pAVCStrmExt->AVReq.Talk.hConnect = pAVCStrmExt->hConnect;
  358. if(pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat == AVCSTRM_FORMAT_MPEG2TS)
  359. pAVCStrmExt->AVReq.Flags = CIP_TALK_DOUBLE_BUFFER | CIP_TALK_USE_SPH_TIMESTAMP;
  360. }
  361. Status =
  362. SubmitIrpSynch(
  363. DeviceObject,
  364. pAVCStrmExt->pIrpAVReq,
  365. &pAVCStrmExt->AVReq
  366. );
  367. if (NT_SUCCESS(Status)) {
  368. pAVCStrmExt->IsochIsActive = TRUE;
  369. TRACE(TL_61883_TRACE,("Av61883_%s; Status %x; Streaming...\n", (pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT ? "Listen" : "Talk"), Status));
  370. }
  371. else {
  372. TRACE(TL_61883_ERROR,("Av61883_%s; failed %x\n", (pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT ? "Listen" : "Talk"), Status));
  373. ASSERT(NT_SUCCESS(Status) && "Start isoch failed!");
  374. }
  375. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  376. EXIT("AVCStrmStartIsoch", Status);
  377. return Status;
  378. }
  379. //
  380. // This wait is based on testing transmitting MPEG2TS data with up to 32 date request.
  381. // Each data request has 256 MPEG2TS data packets. There is a slow motion mode,
  382. // and it may take longer for video to be transmitted in the slow motion mode.
  383. //
  384. #define MAX_ATTACH_WAIT 50000000 // max wait time in seconds
  385. VOID
  386. AVCStrmWaitUntilAttachedAreCompleted(
  387. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  388. )
  389. {
  390. KIRQL oldIrql;
  391. PAVC_STREAM_DATA_STRUCT pDataStruc;
  392. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  393. //
  394. // Wait until attached data to complete transmission before aborting (cancel) them
  395. //
  396. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  397. if( pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_IN
  398. && pDataStruc->cntDataAttached > 0
  399. ) {
  400. LARGE_INTEGER tmMaxWait;
  401. NTSTATUS StatusWait;
  402. #if DBG
  403. ULONGLONG tmStart;
  404. #endif
  405. TRACE(TL_STRM_TRACE,("StopIsoch: MaxWait %d (msec) for %d data buffer to finished transmitting!\n",
  406. MAX_ATTACH_WAIT/10000, pDataStruc->cntDataAttached));
  407. //
  408. // This event will be signalled when all attach buffers are returned.
  409. // It is protected by Spinlock for common data pDataStruc->cntDataAttached.
  410. //
  411. KeClearEvent(&pDataStruc->hNoAttachEvent);
  412. #if DBG
  413. tmStart = GetSystemTime();
  414. #endif
  415. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  416. tmMaxWait = RtlConvertLongToLargeInteger(-(MAX_ATTACH_WAIT));
  417. StatusWait =
  418. KeWaitForSingleObject(
  419. &pDataStruc->hNoAttachEvent,
  420. Executive,
  421. KernelMode,
  422. FALSE,
  423. &tmMaxWait
  424. );
  425. if(StatusWait == STATUS_TIMEOUT) {
  426. TRACE(TL_STRM_ERROR,("TIMEOUT (%d msec) on hNoAttachEvent! DataRcv:%d; AQD [%d:%d:%d]\n",
  427. (DWORD) (GetSystemTime()-tmStart)/10000,
  428. (DWORD) pDataStruc->cntDataReceived,
  429. pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached,
  430. pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued,
  431. pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached
  432. ));
  433. } else {
  434. TRACE(TL_STRM_WARNING,("Status:%x; (%d msec) on hNoAttachEvent. DataRcv:%d; AQD [%d:%d:%d]\n",
  435. StatusWait,
  436. (DWORD) (GetSystemTime()-tmStart)/10000,
  437. (DWORD) pDataStruc->cntDataReceived,
  438. pAVCStrmExt->pAVCStrmDataStruc->cntDataAttached,
  439. pAVCStrmExt->pAVCStrmDataStruc->cntDataQueued,
  440. pAVCStrmExt->pAVCStrmDataStruc->cntDataDetached
  441. ));
  442. }
  443. } else {
  444. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  445. }
  446. }
  447. NTSTATUS
  448. AVCStrmStopIsoch(
  449. IN PDEVICE_OBJECT DeviceObject,
  450. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  451. )
  452. /*++
  453. Routine Description:
  454. Stop streaming.
  455. --*/
  456. {
  457. NTSTATUS Status;
  458. PAVC_STREAM_DATA_STRUCT pDataStruc;
  459. PAGED_CODE();
  460. ENTER("AVCStrmStopIsoch");
  461. // Claim ownership of hMutexAVReqIsoch
  462. KeWaitForMutexObject(&pAVCStrmExt->hMutexAVReq, Executive, KernelMode, FALSE, NULL);
  463. if(!pAVCStrmExt->IsochIsActive) {
  464. TRACE(TL_STRM_WARNING|TL_61883_WARNING,("Isoch already not active!"));
  465. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  466. return STATUS_SUCCESS;
  467. }
  468. if(!pAVCStrmExt->hConnect) {
  469. ASSERT(pAVCStrmExt->hConnect && "Cannot stop isoch while graph is not connected!\n");
  470. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  471. return STATUS_INVALID_PARAMETER;
  472. }
  473. Status = STATUS_SUCCESS;
  474. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  475. TRACE(TL_STRM_TRACE,("IsochSTOP; flow %d; AQD [%d:%d:%d]\n", pAVCStrmExt->DataFlow, pDataStruc->cntDataAttached, pDataStruc->cntDataQueued, pDataStruc->cntDataDetached));
  476. RtlZeroMemory(&pAVCStrmExt->AVReq, sizeof(AV_61883_REQUEST));
  477. INIT_61883_HEADER(&pAVCStrmExt->AVReq, Av61883_Stop);
  478. pAVCStrmExt->AVReq.Listen.hConnect = pAVCStrmExt->hConnect;
  479. Status =
  480. SubmitIrpSynch(
  481. DeviceObject,
  482. pAVCStrmExt->pIrpAVReq,
  483. &pAVCStrmExt->AVReq
  484. );
  485. if (NT_SUCCESS(Status) || Status == STATUS_NO_SUCH_DEVICE) {
  486. TRACE(TL_61883_TRACE,("Av61883_%s; Status %x; Stopped...\n", (pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT ? "Listen" : "Talk"), Status));
  487. } else {
  488. TRACE(TL_61883_ERROR,("Av61883_%s; failed %x\n", (pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT ? "Listen" : "Talk"), Status));
  489. ASSERT(NT_SUCCESS(Status) && "Stop isoch failed!");
  490. }
  491. // Assume isoch is stopped regardless of the return status.
  492. pAVCStrmExt->IsochIsActive = FALSE;
  493. KeReleaseMutex(&pAVCStrmExt->hMutexAVReq, FALSE);
  494. EXIT("AVCStrmStopIsoch", Status);
  495. return Status;
  496. }
  497. /******************************
  498. * Streaming utility funcrtions
  499. *******************************/
  500. //
  501. // GetSystemTime in 100 nS units
  502. //
  503. ULONGLONG GetSystemTime()
  504. {
  505. LARGE_INTEGER rate, ticks;
  506. ticks = KeQueryPerformanceCounter(&rate);
  507. return (KSCONVERT_PERFORMANCE_TIME(rate.QuadPart, ticks));
  508. }
  509. ///
  510. // The "signature" of the header section of Seq0 of incoming source packets:
  511. //
  512. // "Blue" book, Part2, 11.4 (page 50); Figure 66, table 36 (page 111)
  513. //
  514. // ID0 = {SCT2,SCT1,SCT0,RSV,Seq3,Seq2,Seq1,Seq0}
  515. //
  516. // SCT2-0 = {0,0,0} = Header Section Type
  517. // RSV = {1}
  518. // Seq3-0 = {1,1,1,1} for NoInfo or {0,0,0,} for Sequence 0
  519. //
  520. // ID1 = {DSeq3-0, 0, RSV, RSV, RSV}
  521. // DSeq3-0 = {0, 0, 0, 0} = Beginning of a DV frame
  522. //
  523. // ID2 = {DBN7,DBN6,DBN5,DBN4,DBN3,DBN2,DBN1,DBN0}
  524. // DBB7-0 = {0,0,0,0,0,0,0,0,0} = Beginning of a DV frame
  525. //
  526. #define DIF_BLK_ID0_SCT_MASK 0xe0 // 11100000b; Section Type (SCT)2-0 are all 0's for the Header section
  527. #define DIF_BLK_ID1_DSEQ_MASK 0xf0 // 11110000b; DIF Sequence Number(DSEQ)3-0 are all 0's
  528. #define DIF_BLK_ID2_DBN_MASK 0xff // 11111111b; Data Block Number (DBN)7-0 are all 0's
  529. #define DIF_HEADER_DSF 0x80 // 10000000b; DSF=0; 10 DIF Sequences (525-60)
  530. // DSF=1; 12 DIF Sequences (625-50)
  531. #define DIF_HEADER_TFn 0x80 // 10000000b; TFn=0; DIF bloick of area N are transmitted in the current DIF sequence.
  532. // TFn=1; DIF bloick of area N are NOT transmitted in the current DIF sequence.
  533. ULONG
  534. AVCStrmDVReadFrameValidate(
  535. IN PCIP_VALIDATE_INFO pInfo
  536. )
  537. /*++
  538. Routine Description:
  539. Used to validate the header section of a frame. so 61883 will start filling data for a DVFrame.
  540. Note: This routine apply only to DV ONLY.
  541. Return
  542. 0 verified
  543. 1: invallid
  544. --*/
  545. {
  546. if(pInfo->Packet) {
  547. //
  548. // Detect header 0 signature.
  549. //
  550. if(
  551. (pInfo->Packet[0] & DIF_BLK_ID0_SCT_MASK) == 0
  552. && (pInfo->Packet[1] & DIF_BLK_ID1_DSEQ_MASK) == 0
  553. && (pInfo->Packet[2] & DIF_BLK_ID2_DBN_MASK) == 0
  554. ) {
  555. // Check TF1, TF2, and TF3: 1: not transmitted; 0:transmitted
  556. // TF1:Audio; TF2:Video; TF3:Subcode; they all need to be 0 to be valid.
  557. if((pInfo->Packet[5] & 0x80) ||
  558. (pInfo->Packet[6] & 0x80) ||
  559. (pInfo->Packet[7] & 0x80)
  560. ) {
  561. TRACE(TL_CIP_TRACE,("inv src pkts; [%x %x %d %x], [%x %x %x %x]\n",
  562. pInfo->Packet[0],
  563. pInfo->Packet[1],
  564. pInfo->Packet[2],
  565. pInfo->Packet[3],
  566. pInfo->Packet[4],
  567. pInfo->Packet[5],
  568. pInfo->Packet[6],
  569. pInfo->Packet[7]
  570. ));
  571. // Valid header but DIF block for this area is not transmitted.
  572. // Some DV (such as DVCPro) may wait untill its "mecha and servo" to be stable to make these valid.
  573. // This should happen if a graph is in run state before a tape is played (and stablized).
  574. return 1;
  575. }
  576. return 0;
  577. }
  578. else {
  579. return 1;
  580. }
  581. }
  582. else {
  583. TRACE(TL_CIP_ERROR,("Validate: invalid SrcPktSeq; Packet %x\n", pInfo->Packet));
  584. return 1;
  585. }
  586. } // DVReadFrameValidate
  587. NTSTATUS
  588. AVCStrmProcessReadComplete(
  589. PAVCSTRM_DATA_ENTRY pDataEntry,
  590. PAVC_STREAM_EXTENSION pAVCStrmExt,
  591. PAVC_STREAM_DATA_STRUCT pDataStruc
  592. )
  593. /*++
  594. Routine Description:
  595. Process the data read completion.
  596. --*/
  597. {
  598. PKSSTREAM_HEADER pStrmHeader;
  599. LONGLONG LastPictureNumber;
  600. NTSTATUS Status = STATUS_SUCCESS;
  601. pStrmHeader = pDataEntry->StreamHeader;
  602. ASSERT(pStrmHeader->Size >= sizeof(KSSTREAM_HEADER));
  603. // Check CIP_STATUS from 61883
  604. // CIP_STATUS_CORRUPT_FRAME (0x00000001)
  605. if(pDataEntry->Frame->Status & CIP_STATUS_CORRUPT_FRAME) {
  606. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("CIP_STATUS_CORRUPT_FRAME\n"));
  607. pStrmHeader->OptionsFlags = 0;
  608. Status = STATUS_SUCCESS; // Success but no data !
  609. pStrmHeader->DataUsed = 0;
  610. pDataStruc->PictureNumber++; pDataStruc->FramesProcessed++;
  611. }
  612. else
  613. // CIP_STATUS_SUCCESS (0x00000000)
  614. // CIP_STATUS_FIRST_FRAME (0x00000002)
  615. if(pDataEntry->Frame->Status == CIP_STATUS_SUCCESS ||
  616. pDataEntry->Frame->Status & CIP_STATUS_FIRST_FRAME) {
  617. // Only increment FramesProcessed if it is a valid frame;
  618. pDataStruc->FramesProcessed++;
  619. Status = STATUS_SUCCESS;
  620. pStrmHeader->OptionsFlags = KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT;
  621. #ifdef NT51_61883
  622. pStrmHeader->DataUsed = pDataEntry->Frame->CompletedBytes;
  623. #else
  624. pStrmHeader->DataUsed = pAVCStrmExt->pAVCStrmDataStruc->FrameSize;
  625. #endif
  626. // This subunit driver is a Master clock
  627. if (pDataEntry->ClockProvider) {
  628. #ifdef NT51_61883
  629. ULONG ulDeltaCycleCounts;
  630. // If not the first frame. we will calculate the drop frame information.
  631. if(pAVCStrmExt->b1stNewFrameFromPauseState) {
  632. // Default number of packets for a DV frame
  633. if(pDataStruc->FramesProcessed > 1) // PAUSE->RUN->PAUSE->RUN case; no increase for the 1st frame.
  634. pDataStruc->CurrentStreamTime += pAVCStrmExt->pAVCStrmFormatInfo->AvgTimePerFrame;
  635. pAVCStrmExt->b1stNewFrameFromPauseState = FALSE;
  636. } else {
  637. ULONG ulCycleCount16bits;
  638. // Calculate skipped 1394 cycle from the returned CycleTime
  639. VALIDATE_CYCLE_COUNTS(pDataEntry->Frame->Timestamp);
  640. ulCycleCount16bits = CALCULATE_CYCLE_COUNTS(pDataEntry->Frame->Timestamp);
  641. ulDeltaCycleCounts = CALCULATE_DELTA_CYCLE_COUNT(pAVCStrmExt->CycleCount16bits, ulCycleCount16bits);
  642. // Adjust to max allowable gap to the max elapsed time of the CycleTime returned by OHCI 1394.
  643. if(ulDeltaCycleCounts > MAX_CYCLES)
  644. ulDeltaCycleCounts = MAX_CYCLES;
  645. // There are two cases for drop frames: (1) Starve of buffer; (2) no data
  646. // If there is starving, status will be CIP_STATUS_FIRST_FRAME.
  647. if(pDataEntry->Frame->Status & CIP_STATUS_FIRST_FRAME) {
  648. // Convert packets (cycles) to time in 100 nanosecond unit; (one cycle = 1250 * 100 nsec)
  649. // We could use the skip frame, but CycleCount is more accurate.
  650. pDataStruc->CurrentStreamTime += ulDeltaCycleCounts * TIME_PER_CYCLE; // Use cycle count to be precise.
  651. } else {
  652. // Ignore all "drop frames" in the "no data" case
  653. if(ulDeltaCycleCounts * TIME_PER_CYCLE > pAVCStrmExt->pAVCStrmFormatInfo->AvgTimePerFrame)
  654. // There might be some frame(s) skipped due to no data or tape stopped playing, we skip this skipped data.
  655. pDataStruc->CurrentStreamTime += pAVCStrmExt->pAVCStrmFormatInfo->AvgTimePerFrame;
  656. else
  657. pDataStruc->CurrentStreamTime += ulDeltaCycleCounts * TIME_PER_CYCLE; // Use cycle count to be precise.
  658. }
  659. }
  660. // StreamTime start with 0;
  661. pStrmHeader->PresentationTime.Time = pDataStruc->CurrentStreamTime;
  662. // Use to adjust the queried stream time
  663. pAVCStrmExt->LastSystemTime = GetSystemTime();
  664. // Cache current CycleCount
  665. pAVCStrmExt->CycleCount16bits = CALCULATE_CYCLE_COUNTS(pDataEntry->Frame->Timestamp);
  666. #else // NT51_61883
  667. // This is the old way when 61883 was not returning the correct CycleTime.
  668. // This is the old way when 61883 was not returning the correct CycleTime.
  669. pStrmHeader->PresentationTime.Time = pDataStruc->CurrentStreamTime;
  670. pAVCStrmExt->LastSystemTime = GetSystemTime(); // Use to adjust the queried stream time
  671. pDataStruc->CurrentStreamTime += pAVCStrmExt->pAVCStrmFormatInfo->AvgTimePerFrame;
  672. #endif // NT51_61883
  673. // no Clock so "free flowing!"
  674. } else {
  675. pStrmHeader->PresentationTime.Time = 0;
  676. }
  677. // Put in Timestamp info depending on clock provider
  678. pStrmHeader->PresentationTime.Numerator = 1;
  679. pStrmHeader->PresentationTime.Denominator = 1;
  680. // Only if there is a clock, presentation time and drop frames information are set.
  681. // Acoording to DDK:
  682. // The PictureNumber member count represents the idealized count of the current picture,
  683. // which is calculated in one of two ways:
  684. // ("Other" clock) Measure the time since the stream was started and divide by the frame duration.
  685. // (MasterClock) Add together the count of frames captured and the count of frame dropped.
  686. //
  687. // Here, we know the current stream time, and the picture number is calculated from that.
  688. //
  689. if(pDataEntry->ClockProvider) {
  690. pStrmHeader->Duration =
  691. pAVCStrmExt->pAVCStrmFormatInfo->AvgTimePerFrame;
  692. pStrmHeader->OptionsFlags |=
  693. (KSSTREAM_HEADER_OPTIONSF_TIMEVALID | // pStrmHeader->PresentationTime.Time is valid
  694. KSSTREAM_HEADER_OPTIONSF_DURATIONVALID);
  695. if(pDataEntry->Frame->Status & CIP_STATUS_FIRST_FRAME)
  696. pStrmHeader->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  697. // Calculate picture number and dropped frame;
  698. // For NTSC, it could be 267 or 266 packet time per frame. Since integer calculation will round,
  699. // we will add a packet time (TIME_PER_CYCLE = 125 us = 1250 100nsec) to that.This is only used for calculation.
  700. LastPictureNumber = pDataStruc->PictureNumber;
  701. pDataStruc->PictureNumber =
  702. 1 + // Picture number start with 1.but PresetationTime start with 0.
  703. (pStrmHeader->PresentationTime.Time + TIME_PER_CYCLE)
  704. * (LONGLONG) GET_AVG_TIME_PER_FRAME_DENOM(pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat)
  705. / (LONGLONG) GET_AVG_TIME_PER_FRAME_NUM(pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat);
  706. if(pDataStruc->PictureNumber > LastPictureNumber+1) {
  707. pStrmHeader->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY; // If there is a skipped frame, set the discontinuity flag
  708. TRACE(TL_CIP_WARNING,("Discontinuity: LastPic#:%d; Pic#%d; PresTime:%d;\n", (DWORD) LastPictureNumber, (DWORD) pDataStruc->PictureNumber, (DWORD) pStrmHeader->PresentationTime.Time));
  709. }
  710. if(pDataStruc->PictureNumber <= LastPictureNumber) {
  711. TRACE(TL_STRM_TRACE|TL_CIP_TRACE,("Same pic #:%d; LastPic:%d; tmPres:%d; OptionFlags:%x\n",
  712. (DWORD) pDataStruc->PictureNumber,
  713. (DWORD) LastPictureNumber,
  714. (DWORD) pStrmHeader->PresentationTime.Time,
  715. pStrmHeader->OptionsFlags));
  716. pDataStruc->PictureNumber = LastPictureNumber + 1; // Picture number must progress !!!!
  717. }
  718. pDataStruc->FramesDropped = pDataStruc->PictureNumber - pDataStruc->FramesProcessed;
  719. // no Clock so "free flowing!"
  720. } else {
  721. pStrmHeader->Duration = 0; // No clock so not valid.
  722. pDataStruc->PictureNumber++;
  723. TRACE(TL_STRM_TRACE,("No clock: PicNum:%d\n", (DWORD) pDataStruc->PictureNumber));
  724. }
  725. }
  726. else {
  727. // 61883 has not defined this yet!
  728. pStrmHeader->OptionsFlags = 0;
  729. Status = STATUS_SUCCESS;
  730. pStrmHeader->DataUsed = 0;
  731. pDataStruc->PictureNumber++; pDataStruc->FramesProcessed++;
  732. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("Unexpected Frame->Status %x\n", pDataEntry->Frame->Status));
  733. ASSERT(FALSE && "Unknown pDataEntry->Frame->Status");
  734. }
  735. #if 0
  736. // For VidOnly which uses VideoInfoHeader and has
  737. // an extended frame information (KS_FRAME_INFO) appended to KSSTREAM_HEADER
  738. if(pStrmHeader->Size >= (sizeof(KSSTREAM_HEADER) + sizeof(PKS_FRAME_INFO)) ) {
  739. pFrameInfo = (PKS_FRAME_INFO) (pStrmHeader + 1);
  740. pFrameInfo->ExtendedHeaderSize = sizeof(KS_FRAME_INFO);
  741. pFrameInfo->PictureNumber = pDataStruc->PictureNumber;
  742. pFrameInfo->DropCount = pDataStruc->FramesDropped;
  743. pFrameInfo->dwFrameFlags =
  744. KS_VIDEO_FLAG_FRAME | // Complete frame
  745. KS_VIDEO_FLAG_I_FRAME; // Every DV frame is an I frame
  746. }
  747. #endif
  748. #if DBG
  749. // Validate that the data is return in the right sequence
  750. if(pDataEntry->FrameNumber != pDataStruc->FramesProcessed) {
  751. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("ProcessRead: OOSequence %d != %d\n", (DWORD) pDataEntry->FrameNumber, (DWORD) pDataStruc->FramesProcessed));
  752. };
  753. #endif
  754. return Status;
  755. }
  756. ULONG
  757. AVCStrmCompleteRead(
  758. PCIP_NOTIFY_INFO pInfo
  759. )
  760. /*++
  761. Routine Description:
  762. 61883 has completed receiving data and callback to us to complete.
  763. --*/
  764. {
  765. PAVCSTRM_DATA_ENTRY pDataEntry;
  766. PAVC_STREAM_EXTENSION pAVCStrmExt;
  767. PAVC_STREAM_DATA_STRUCT pDataStruc;
  768. KIRQL oldIrql;
  769. // Callback and in DISPATCH_LEVEL
  770. // The called might have acquired spinlock as well!
  771. TRACE(TL_STRM_INFO,("CompleteRead: pInfo:%x\n", pInfo));
  772. pDataEntry = pInfo->Context;
  773. if(!pDataEntry) {
  774. ASSERT(pDataEntry && "Context is NULL!\n");
  775. return 1;
  776. }
  777. pAVCStrmExt = pDataEntry->pAVCStrmExt;
  778. if(!pAVCStrmExt) {
  779. ASSERT(pAVCStrmExt && "pAVCStrmExt is NULL\n");
  780. return 1;
  781. }
  782. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  783. if(!pDataStruc) {
  784. ASSERT(pDataStruc && "pDataStruc is NULL\n");
  785. return 1;
  786. }
  787. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  788. #if DBG
  789. // It is possible that a buffer is completed before it is return from IoCallDriver to attach this buffer.
  790. if(!IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)) {
  791. TRACE(TL_STRM_WARNING,("AVCStrmCompleteRead: pDataEntry:%x not yet attached but completed.\n", pDataEntry));
  792. //
  793. // This irp will be completed from its IoCallDriver to attach this frame.
  794. //
  795. }
  796. #endif
  797. // Can the cancel routione is ahead of us? Error condition.
  798. if(pDataStruc->cntDataAttached <= 0) {
  799. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("AVCStrmCompleteRead:pAVCStrmExt:%x, pDataEntry:%x, AQD[%d:%d:%d]\n",
  800. pAVCStrmExt, pDataEntry, pDataStruc->cntDataAttached, pDataStruc->cntDataQueued,pDataStruc->cntDataDetached));
  801. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  802. return 1;
  803. }
  804. //
  805. // Process this completion based on the return status from 61883
  806. //
  807. pDataEntry->pIrpUpper->IoStatus.Status =
  808. AVCStrmProcessReadComplete(
  809. pDataEntry,
  810. pAVCStrmExt,
  811. pDataStruc
  812. );
  813. //
  814. // There are two possible ways to complete the data request:
  815. //
  816. // (A) Normal case: attach data request (pIrpLower), attached completed, notify callback (here), and completion (pIrpUpper)
  817. // (B) Rare/stress case: attach data request (pIrpLower), notify callback (here), attach complete (pIrpLower), and complete (pIrpUpper)
  818. //
  819. pDataEntry->State |= DE_IRP_LOWER_CALLBACK_COMPLETED;
  820. //
  821. // Case (A): If DE_IRP_LOWER_CALLBACK_COMPLETED is set and pIrpUpper is marked pending, complete the UpperIrp.
  822. //
  823. if(IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)) {
  824. if(IsStateSet(pDataEntry->State, DE_IRP_UPPER_PENDING_COMPLETED)) {
  825. //
  826. // This is the normal case: attached, IoMarkPending, then complete in the callback routine.
  827. //
  828. IoCompleteRequest( pDataEntry->pIrpUpper, IO_NO_INCREMENT ); pDataEntry->State |= DE_IRP_UPPER_COMPLETED;
  829. //
  830. // Transfer from attach to detach list
  831. //
  832. RemoveEntryList(&pDataEntry->ListEntry); InterlockedDecrement(&pDataStruc->cntDataAttached);
  833. #if DBG
  834. if(pDataStruc->cntDataAttached < 0) {
  835. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("pDataStruc:%x; pDataEntry:%x\n", pDataStruc, pDataEntry));
  836. ASSERT(pDataStruc->cntDataAttached >= 0);
  837. }
  838. #endif
  839. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  840. //
  841. // pDataEntry should not be referenced after this.
  842. //
  843. } else {
  844. TRACE(TL_STRM_TRACE,("Watch out! pDataEntry:%x in between attach complete and IoMarkIrpPending!\n", pDataEntry));
  845. //
  846. // Case (B): Complete IrpUpper when return to IoCallDriver(IrpLower)
  847. // Note: The IrpLower has not called IoMarkIrpPending(). (Protected with spinlock)
  848. //
  849. }
  850. } else {
  851. //
  852. // Case (B): Complete IrpUpper when return to IoCallDriver(IrpLower)
  853. //
  854. }
  855. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  856. return 0;
  857. } // AVCStrmCompleteRead
  858. #if DBG
  859. PAVCSTRM_DATA_ENTRY pLastDataEntry;
  860. LONGLONG LastFrameNumber;
  861. #endif
  862. ULONG
  863. AVCStrmCompleteWrite(
  864. PCIP_NOTIFY_INFO pInfo
  865. )
  866. /*++
  867. Routine Description:
  868. 61883 has completed receiving data and callback to us to complete.
  869. --*/
  870. {
  871. PAVCSTRM_DATA_ENTRY pDataEntry;
  872. PAVC_STREAM_EXTENSION pAVCStrmExt;
  873. PAVC_STREAM_DATA_STRUCT pDataStruc;
  874. NTSTATUS irpStatus;
  875. KIRQL oldIrql;
  876. // Callback and in DISPATCH_LEVEL
  877. // The called might have acquired spinlock as well!
  878. TRACE(TL_STRM_INFO,("CompleteWrite: pInfo:%x\n", pInfo));
  879. pDataEntry = pInfo->Context;
  880. if(!pDataEntry) {
  881. ASSERT(pDataEntry && "Context is NULL!\n");
  882. return 1;
  883. }
  884. pAVCStrmExt = pDataEntry->pAVCStrmExt;
  885. if(!pAVCStrmExt) {
  886. ASSERT(pAVCStrmExt && "pAVCStrmExt is NULL\n");
  887. return 1;
  888. }
  889. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  890. if(!pDataStruc) {
  891. ASSERT(pDataStruc && "pDataStruc is NULL\n");
  892. return 1;
  893. }
  894. #if 0 // Must complete it!
  895. // If isoch is not active, then we are in the process of stopping; Let this be cancellable.
  896. if(!pAVCStrmExt->IsochIsActive) {
  897. TRACE(TL_STRM_ERROR,("AVCStrmCompleteRead: IsochActive:%d; pDataEntry:%x\n", pAVCStrmExt->IsochIsActive, pDataEntry));
  898. ASSERT(pAVCStrmExt->IsochIsActive);
  899. return 1;
  900. }
  901. #endif
  902. irpStatus = STATUS_SUCCESS;
  903. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  904. #if DBG
  905. // It is possible that a buffer is completed before it is return from IoCallDriver to attach this buffer.
  906. if(!IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)) {
  907. TRACE(TL_STRM_WARNING,("CompleteWrite: pDataEntry:%x not yet attached but completed.\n", pDataEntry));
  908. //
  909. // This irp will be completed from its IoCallDriver to attach this frame.
  910. //
  911. }
  912. #endif
  913. // Can the cancel routione is ahead of us? Error condition.
  914. if(pDataStruc->cntDataAttached <= 0) {
  915. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("AVCStrmCompleteWrite:pAVCStrmExt:%x, pDataEntry:%x, AQD[%d:%d:%d]\n",
  916. pAVCStrmExt, pDataEntry, pDataStruc->cntDataAttached, pDataStruc->cntDataQueued,pDataStruc->cntDataDetached));
  917. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  918. return 1;
  919. }
  920. //
  921. // Process according to status for the frame
  922. //
  923. if(pDataEntry->Frame->Status & CIP_STATUS_CORRUPT_FRAME) {
  924. pDataStruc->FramesProcessed++;
  925. TRACE(TL_CIP_ERROR,("CIP_STATUS_CORRUPT_FRAME; pIrpUpper:%x; pIrpLower:%x\n", pDataEntry->pIrpUpper, pDataEntry->pIrpLower));
  926. } else
  927. if(pDataEntry->Frame->Status == CIP_STATUS_SUCCESS ||
  928. pDataEntry->Frame->Status & CIP_STATUS_FIRST_FRAME) {
  929. #if DBG
  930. if(pDataEntry->Frame->Status & CIP_STATUS_FIRST_FRAME)
  931. TRACE(TL_CIP_TRACE,("CIP_STATUS_FIRST_FRAME; pIrpUpper:%x; pIrpLower:%x\n", pDataEntry->pIrpUpper, pDataEntry->pIrpLower));
  932. #endif
  933. pDataStruc->FramesProcessed++;
  934. } else {
  935. pDataStruc->FramesProcessed++;
  936. TRACE(TL_CIP_ERROR,("Unknown Status:%x\n", pDataEntry->Frame->Status));
  937. }
  938. pDataStruc->PictureNumber++;
  939. #if DBG
  940. //
  941. // Validate that the data is return in the right sequence
  942. //
  943. if(pDataEntry->FrameNumber != pDataStruc->FramesProcessed) {
  944. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("CompleteWrite: OOSequence FrameNum:%d != FrameProcessed:%d; pIrpUpper:%x; pIrpLower:%x; Last(%d:%x,%x)\n",
  945. (DWORD) pDataEntry->FrameNumber, (DWORD) pDataStruc->FramesProcessed,
  946. pDataEntry->pIrpUpper, pDataEntry->pIrpLower,
  947. (DWORD) pLastDataEntry->FrameNumber, pLastDataEntry->pIrpUpper, pLastDataEntry->pIrpLower
  948. ));
  949. // ASSERT(pDataEntry->FrameNumber == pDataStruc->FramesProcessed);
  950. };
  951. pLastDataEntry = pDataEntry;
  952. LastFrameNumber = pDataEntry->FrameNumber;
  953. #endif
  954. //
  955. // There are two possible ways to complete the data request:
  956. //
  957. // (A) Normal case: attach data request (pIrpLower), attached completed, notify callback (here), and completion (pIrpUpper)
  958. // (B) Rare/stress case: attach data request (pIrpLower), notify callback (here), attach complete (pIrpLower), and complete (pIrpUpper)
  959. //
  960. pDataEntry->pIrpUpper->IoStatus.Status = irpStatus;
  961. pDataEntry->State |= DE_IRP_LOWER_CALLBACK_COMPLETED;
  962. //
  963. // Case (A): If DE_IRP_LOWER_CALLBACK_COMPLETED is set and pIrpUpper is marked pending, complete the UpperIrp.
  964. //
  965. if(IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)) {
  966. if(IsStateSet(pDataEntry->State, DE_IRP_UPPER_PENDING_COMPLETED)) {
  967. //
  968. // This is the normal case: attached, IoMarkPending, then complete in the callback routine.
  969. //
  970. IoCompleteRequest( pDataEntry->pIrpUpper, IO_NO_INCREMENT ); pDataEntry->State |= DE_IRP_UPPER_COMPLETED;
  971. //
  972. // Transfer from attach to detach list
  973. //
  974. RemoveEntryList(&pDataEntry->ListEntry); InterlockedDecrement(&pDataStruc->cntDataAttached);
  975. //
  976. // Signal when there is no more data buffer attached.
  977. //
  978. if(pDataStruc->cntDataAttached == 0)
  979. KeSetEvent(&pDataStruc->hNoAttachEvent, 0, FALSE);
  980. #if DBG
  981. if(pDataStruc->cntDataAttached < 0) {
  982. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("pDataStruc:%x; pDataEntry:%x\n", pDataStruc, pDataEntry));
  983. ASSERT(pDataStruc->cntDataAttached >= 0);
  984. }
  985. #endif
  986. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  987. //
  988. // pDataEntry should not be referenced after this.
  989. //
  990. } else {
  991. TRACE(TL_STRM_TRACE,("Watch out! pDataEntry:%x in between attach complete and IoMarkIrpPending!\n", pDataEntry));
  992. //
  993. // Case (B): Complete IrpUpper when return to IoCallDriver(IrpLower);
  994. // Note: The IrpLower has not called IoMarkIrpPending(). (Protected with spinlock)
  995. //
  996. }
  997. } else {
  998. //
  999. // Case (B): Complete IrpUpper when return to IoCallDriver(IrpLower)
  1000. //
  1001. }
  1002. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  1003. return 0;
  1004. } // AVCStrmCompleteWrite
  1005. NTSTATUS
  1006. AVCStrmAttachFrameCR(
  1007. IN PDEVICE_OBJECT DeviceObject,
  1008. IN PIRP pIrp,
  1009. IN PAVCSTRM_DATA_ENTRY pDataEntry
  1010. )
  1011. /*++
  1012. Routine Description:
  1013. Completion routine for attaching a data request to 61883.
  1014. --*/
  1015. {
  1016. PAVC_STREAM_EXTENSION pAVCStrmExt;
  1017. PAVC_STREAM_DATA_STRUCT pDataStruc;
  1018. KIRQL oldIrql;
  1019. PAGED_CODE();
  1020. pAVCStrmExt = pDataEntry->pAVCStrmExt;
  1021. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  1022. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  1023. //
  1024. // Check for possible attaching data request error
  1025. //
  1026. if(!NT_SUCCESS(pIrp->IoStatus.Status)) {
  1027. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("AttachFrameCR: pDataEntry:%x; pIrp->IoStatus.Status:%x (Error!)\n", pDataEntry, pIrp->IoStatus.Status));
  1028. ASSERT(NT_SUCCESS(pIrp->IoStatus.Status));
  1029. pDataEntry->State |= DE_IRP_ERROR;
  1030. //
  1031. // If attach data request has failed, we complete the pIrpUpper with this error.
  1032. //
  1033. pDataEntry->pIrpUpper->IoStatus.Status = pIrp->IoStatus.Status; // or should we cancel (STATUS_CANCELLED) it?
  1034. IoCompleteRequest( pDataEntry->pIrpUpper, IO_NO_INCREMENT ); pDataEntry->State |= DE_IRP_UPPER_COMPLETED;
  1035. //
  1036. // Transfer from attach to detach list
  1037. //
  1038. RemoveEntryList(&pDataEntry->ListEntry); InterlockedDecrement(&pDataStruc->cntDataAttached);
  1039. //
  1040. // Signal completion event when all attached are completed.
  1041. //
  1042. if(pAVCStrmExt->DataFlow != KSPIN_DATAFLOW_IN && pDataStruc->cntDataAttached == 0)
  1043. KeSetEvent(&pDataStruc->hNoAttachEvent, 0, FALSE);
  1044. ASSERT(pDataStruc->cntDataAttached >= 0);
  1045. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  1046. //
  1047. // No additional processing when return to IoCallDriver() with the error pIrp->IoStatus.Status.
  1048. //
  1049. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  1050. return STATUS_MORE_PROCESSING_REQUIRED;
  1051. }
  1052. #if DBG
  1053. //
  1054. // Validate that the data is attached in the right sequence
  1055. //
  1056. pDataStruc->FramesAttached++;
  1057. if(pDataEntry->FrameNumber != pDataStruc->FramesAttached) {
  1058. TRACE(TL_STRM_WARNING|TL_CIP_WARNING,("Attached completed OOSequence FrameNum:%d != FrameAttached:%d; pIrpUpper:%x; pIrpLower:%x; Last(%d:%x,%x)\n",
  1059. (DWORD) pDataEntry->FrameNumber, (DWORD) pDataStruc->FramesAttached
  1060. ));
  1061. // ASSERT(pDataEntry->FrameNumber == pDataStruc->FramesAttached);
  1062. };
  1063. #endif
  1064. //
  1065. // Attached data reuqest to 61883 is completed (note: however, we do not know if callback is called.)
  1066. //
  1067. pDataEntry->State |= DE_IRP_LOWER_ATTACHED_COMPLETED;
  1068. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  1069. return STATUS_MORE_PROCESSING_REQUIRED;
  1070. }
  1071. VOID
  1072. AVCStrmFormatAttachFrame(
  1073. IN KSPIN_DATAFLOW DataFlow,
  1074. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  1075. IN AVCSTRM_FORMAT AVCStrmFormat,
  1076. IN PAV_61883_REQUEST pAVReq,
  1077. IN PAVCSTRM_DATA_ENTRY pDataEntry,
  1078. IN ULONG ulSourcePacketSize, // Packet length in bytes
  1079. IN ULONG ulFrameSize, // Buffer size; may contain one or multiple source packets
  1080. IN PIRP pIrpUpper,
  1081. IN PKSSTREAM_HEADER StreamHeader,
  1082. IN PVOID FrameBuffer
  1083. )
  1084. /*++
  1085. Routine Description:
  1086. Format an attach frame request.
  1087. --*/
  1088. {
  1089. InitializeListHead(&pDataEntry->ListEntry);
  1090. // A DataEntry must be previously completed!
  1091. ASSERT(IsStateSet(pDataEntry->State, DE_IRP_UPPER_COMPLETED) && "Reusing a data entry that was not completed!");
  1092. pDataEntry->State = DE_PREPARED; // Initial state of a resued DataEntry (start over!)
  1093. pDataEntry->pAVCStrmExt = pAVCStrmExt;
  1094. pDataEntry->pIrpUpper = pIrpUpper;
  1095. pDataEntry->StreamHeader = StreamHeader;
  1096. pDataEntry->FrameBuffer = FrameBuffer;
  1097. ASSERT(pDataEntry->FrameBuffer != NULL);
  1098. pDataEntry->Frame->pNext = NULL;
  1099. pDataEntry->Frame->Status = 0;
  1100. pDataEntry->Frame->Packet = (PUCHAR) FrameBuffer;
  1101. #if DBG
  1102. pDataEntry->FrameNumber = pAVCStrmExt->pAVCStrmDataStruc->cntDataReceived;
  1103. #endif
  1104. pDataEntry->Frame->Flags = 0;
  1105. if(DataFlow == KSPIN_DATAFLOW_OUT) {
  1106. // DV needs validation to determine the header section as the start of a DV frame
  1107. if(AVCStrmFormat == AVCSTRM_FORMAT_SDDV_NTSC ||
  1108. AVCStrmFormat == AVCSTRM_FORMAT_SDDV_PAL ||
  1109. AVCStrmFormat == AVCSTRM_FORMAT_HDDV_NTSC ||
  1110. AVCStrmFormat == AVCSTRM_FORMAT_HDDV_PAL ||
  1111. AVCStrmFormat == AVCSTRM_FORMAT_SDLDV_NTSC ||
  1112. AVCStrmFormat == AVCSTRM_FORMAT_SDLDV_PAL ) {
  1113. pDataEntry->Frame->pfnValidate = AVCStrmDVReadFrameValidate; // use to validate the 1st source packet
  1114. #ifdef NT51_61883
  1115. //
  1116. // Set CIP_USE_SOURCE_HEADER_TIMESTAMP to get 25 bit CycleTime from source packet header
  1117. // (13CycleCount:12CycleOffset)
  1118. // Do not set this to get 16 bit CycleTime from isoch packet (3 SecondCount:13CycleCount)
  1119. //
  1120. pDataEntry->Frame->Flags |= ( CIP_VALIDATE_FIRST_SOURCE
  1121. | CIP_RESET_FRAME_ON_DISCONTINUITY); // Reset buffer pointer when encounter discontinuity
  1122. #endif
  1123. } else {
  1124. // MPEG2 specific flags
  1125. pDataEntry->Frame->pfnValidate = NULL;
  1126. if(pAVCStrmExt->pAVCStrmFormatInfo->OptionFlags & AVCSTRM_FORMAT_OPTION_STRIP_SPH)
  1127. pDataEntry->Frame->Flags |= CIP_STRIP_SOURCE_HEADER;
  1128. }
  1129. pDataEntry->Frame->ValidateContext = pDataEntry;
  1130. pDataEntry->Frame->pfnNotify = AVCStrmCompleteRead;
  1131. }
  1132. else {
  1133. // DV needs validation to determine the header section as the start of a DV frame
  1134. if(AVCStrmFormat == AVCSTRM_FORMAT_SDDV_NTSC ||
  1135. AVCStrmFormat == AVCSTRM_FORMAT_SDDV_PAL ||
  1136. AVCStrmFormat == AVCSTRM_FORMAT_HDDV_NTSC ||
  1137. AVCStrmFormat == AVCSTRM_FORMAT_HDDV_PAL ||
  1138. AVCStrmFormat == AVCSTRM_FORMAT_SDLDV_NTSC ||
  1139. AVCStrmFormat == AVCSTRM_FORMAT_SDLDV_PAL ) {
  1140. pDataEntry->Frame->Flags |= CIP_DV_STYLE_SYT;
  1141. }
  1142. else {
  1143. // MPEG2 specific flag
  1144. }
  1145. pDataEntry->Frame->pfnValidate = NULL;
  1146. pDataEntry->Frame->ValidateContext = NULL;
  1147. pDataEntry->Frame->pfnNotify = AVCStrmCompleteWrite;
  1148. }
  1149. pDataEntry->Frame->NotifyContext = pDataEntry;
  1150. //
  1151. // Av61883_AttachFrames
  1152. //
  1153. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1154. INIT_61883_HEADER(pAVReq, Av61883_AttachFrame);
  1155. pAVReq->AttachFrame.hConnect = pAVCStrmExt->hConnect;
  1156. pAVReq->AttachFrame.FrameLength = ulFrameSize;
  1157. pAVReq->AttachFrame.SourceLength = ulSourcePacketSize;
  1158. pAVReq->AttachFrame.Frame = pDataEntry->Frame;
  1159. TRACE(TL_STRM_TRACE,("DataFlow:%d; pDataEntry:%x; pIrpUp:%x; hConnect:%x; FrameSz:%d; SrcPktSz:%d; Frame:%x;\n pfnVldt:(%x, %x); pfnNtfy:(%x, %x) \n", DataFlow,
  1160. pDataEntry, pIrpUpper, pAVCStrmExt->hConnect, ulFrameSize, ulSourcePacketSize, pDataEntry->Frame,
  1161. pAVReq->AttachFrame.Frame->pfnValidate, pAVReq->AttachFrame.Frame->ValidateContext,
  1162. pAVReq->AttachFrame.Frame->pfnNotify, pAVReq->AttachFrame.Frame->NotifyContext));
  1163. ASSERT(pAVCStrmExt->hConnect);
  1164. }
  1165. NTSTATUS
  1166. AVCStrmCancelOnePacketCR(
  1167. IN PDEVICE_OBJECT DeviceObject,
  1168. IN PIRP pIrpLower,
  1169. IN PAVCSTRM_DATA_ENTRY pDataEntry
  1170. )
  1171. /*++
  1172. Routine Description:
  1173. Completion routine for detach an isoch descriptor associate with a pending IO.
  1174. Will cancel the pending IO here if detaching descriptor has suceeded.
  1175. --*/
  1176. {
  1177. PAVC_STREAM_EXTENSION pAVCStrmExt;
  1178. PAVC_STREAM_DATA_STRUCT pDataStruc;
  1179. KIRQL oldIrql;
  1180. ENTER("AVCStrmCancelOnePacketCR");
  1181. if(!pDataEntry) {
  1182. ASSERT(pDataEntry);
  1183. return STATUS_MORE_PROCESSING_REQUIRED;
  1184. }
  1185. pAVCStrmExt = pDataEntry->pAVCStrmExt;
  1186. ASSERT(pAVCStrmExt);
  1187. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  1188. ASSERT(pDataStruc);
  1189. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  1190. if(!NT_SUCCESS(pIrpLower->IoStatus.Status)) {
  1191. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("CancelOnePacketCR: pIrpLower->IoStatus.Status %x (Error!)\n", pIrpLower->IoStatus.Status));
  1192. ASSERT(pIrpLower->IoStatus.Status != STATUS_NOT_FOUND); // Catch lost packet!
  1193. pDataEntry->State |= DE_IRP_ERROR;
  1194. //
  1195. // Even though there is an error, but we have a valid DataEntry.
  1196. // Go ahead complete and cancel it.
  1197. //
  1198. }
  1199. #ifdef NT51_61883
  1200. //
  1201. // Special case for MPEG2TS data since a data buffer contains multiple data packets
  1202. // (188*N or 192*N) in one data buffer. The first cancelled buffer may contain valid
  1203. // data packet that an application will need to completely present a video frame.
  1204. // So instead of cancelling it, it will be completed.
  1205. //
  1206. if( pAVCStrmExt->pAVCStrmFormatInfo->AVCStrmFormat == AVCSTRM_FORMAT_MPEG2TS
  1207. && pDataEntry->Frame->CompletedBytes) {
  1208. pDataEntry->pIrpUpper->IoStatus.Status =
  1209. AVCStrmProcessReadComplete(
  1210. pDataEntry,
  1211. pAVCStrmExt,
  1212. pDataStruc
  1213. );
  1214. //
  1215. // CompletedBytes should be multiple of 188 or 192 bytes
  1216. //
  1217. ASSERT(pDataEntry->Frame->CompletedBytes % \
  1218. ((pAVCStrmExt->pAVCStrmFormatInfo->OptionFlags & AVCSTRM_FORMAT_OPTION_STRIP_SPH) ? 188 : 192) == 0);
  1219. TRACE(TL_PNP_ERROR,("pDataEntry:%x; Cancelled buffer (MPEG2TS) has %d bytes; Status:%x\n",
  1220. pDataEntry, pDataEntry->Frame->CompletedBytes, pIrpLower->IoStatus.Status, pDataEntry->pIrpUpper->IoStatus.Status));
  1221. } else {
  1222. pDataStruc->cntFrameCancelled++;
  1223. pDataEntry->pIrpUpper->IoStatus.Status = STATUS_CANCELLED;
  1224. TRACE(TL_CIP_TRACE,("pDataEntry:%x; Cancelled buffer (MPEG2TS) has %d bytes; Status:%x\n",
  1225. pDataEntry, pDataEntry->Frame->CompletedBytes, pIrpLower->IoStatus.Status, pDataEntry->pIrpUpper->IoStatus.Status));
  1226. }
  1227. #else
  1228. pDataStruc->cntFrameCancelled++;
  1229. pDataEntry->pIrpUpper->IoStatus.Status = STATUS_CANCELLED;
  1230. #endif
  1231. IoCompleteRequest(pDataEntry->pIrpUpper, IO_NO_INCREMENT); pDataEntry->State |= DE_IRP_UPPER_COMPLETED;
  1232. pDataEntry->State |= DE_IRP_CANCELLED;
  1233. pDataEntry->pIrpUpper = NULL; // No more access of this!
  1234. //
  1235. // Note: pDataEntry is already dequed from DataAttachList
  1236. //
  1237. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  1238. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  1239. EXIT("AVCStrmCancelOnePacketCR", STATUS_MORE_PROCESSING_REQUIRED);
  1240. return STATUS_MORE_PROCESSING_REQUIRED;
  1241. }
  1242. NTSTATUS
  1243. AVCStrmCancelIO(
  1244. IN PDEVICE_OBJECT DeviceObject,
  1245. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. Cancel all pending IOs
  1250. --*/
  1251. {
  1252. NTSTATUS Status;
  1253. PAVC_STREAM_DATA_STRUCT pDataStruc;
  1254. KIRQL oldIrql;
  1255. PAVCSTRM_DATA_ENTRY pDataEntry;
  1256. PAV_61883_REQUEST pAVReq;
  1257. PIO_STACK_LOCATION NextIrpStack;
  1258. PAGED_CODE();
  1259. ENTER("AVCStrmCancelIO");
  1260. Status = STATUS_SUCCESS;
  1261. if(pAVCStrmExt->IsochIsActive) {
  1262. TRACE(TL_STRM_WARNING,("Isoch is active while trying to cancel IO!\n"));
  1263. // Try stop isoch and continue if success!
  1264. Status = AVCStrmStopIsoch(DeviceObject, pAVCStrmExt);
  1265. if(!NT_SUCCESS(Status) && Status != STATUS_NO_SUCH_DEVICE) {
  1266. TRACE(TL_STRM_ERROR,("Isoch stop failed! Cannnot cancelIO while isoch active.\n"));
  1267. return Status;
  1268. }
  1269. }
  1270. //
  1271. // Guard againt data attach completion
  1272. //
  1273. KeWaitForMutexObject(&pAVCStrmExt->hMutexControl, Executive, KernelMode, FALSE, NULL);
  1274. //
  1275. // Cancel all pending IOs
  1276. //
  1277. pDataStruc = pAVCStrmExt->pAVCStrmDataStruc;
  1278. TRACE(TL_STRM_WARNING,("CancelIO Starting: pDataStruc:%x; AQD [%d:%d:%d]\n", pDataStruc,
  1279. pDataStruc->cntDataAttached, pDataStruc->cntDataQueued, pDataStruc->cntDataDetached));
  1280. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  1281. while (!IsListEmpty(&pDataStruc->DataAttachedListHead)) {
  1282. pDataEntry = (PAVCSTRM_DATA_ENTRY) \
  1283. RemoveHeadList(&pDataStruc->DataAttachedListHead); InterlockedDecrement(&pDataStruc->cntDataAttached);
  1284. #if DBG
  1285. if(!IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED)) {
  1286. TRACE(TL_STRM_ERROR|TL_CIP_ERROR,("CancelIO: pDataEntry:%x\n", pDataEntry));
  1287. // Must be already attached in order to cancel it.
  1288. ASSERT(IsStateSet(pDataEntry->State, DE_IRP_LOWER_ATTACHED_COMPLETED));
  1289. }
  1290. #endif
  1291. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  1292. // Issue 61883 request to cancel this attach
  1293. pAVReq = &pDataEntry->AVReq;
  1294. RtlZeroMemory(pAVReq, sizeof(AV_61883_REQUEST));
  1295. INIT_61883_HEADER(pAVReq, Av61883_CancelFrame);
  1296. pAVReq->CancelFrame.hConnect = pAVCStrmExt->hConnect;
  1297. pAVReq->CancelFrame.Frame = pDataEntry->Frame;
  1298. TRACE(TL_STRM_TRACE,("Canceling AttachList: pAvReq %x; pDataEntry:%x\n", pAVReq, pDataEntry));
  1299. NextIrpStack = IoGetNextIrpStackLocation(pDataEntry->pIrpLower);
  1300. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1301. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_61883_CLASS;
  1302. NextIrpStack->Parameters.Others.Argument1 = pAVReq;
  1303. IoSetCompletionRoutine(
  1304. pDataEntry->pIrpLower,
  1305. AVCStrmCancelOnePacketCR,
  1306. pDataEntry,
  1307. TRUE,
  1308. TRUE,
  1309. TRUE
  1310. );
  1311. Status =
  1312. IoCallDriver(
  1313. DeviceObject,
  1314. pDataEntry->pIrpLower
  1315. );
  1316. ASSERT(Status == STATUS_PENDING || Status == STATUS_SUCCESS || Status == STATUS_NO_SUCH_DEVICE);
  1317. KeAcquireSpinLock(&pDataStruc->DataListLock, &oldIrql);
  1318. } // while
  1319. KeReleaseSpinLock(&pDataStruc->DataListLock, oldIrql);
  1320. TRACE(TL_61883_TRACE,("CancelIO complete: pDataStruc:%x; AQD [%d:%d:%d]\n", pDataStruc,
  1321. pDataStruc->cntDataAttached, pDataStruc->cntDataQueued, pDataStruc->cntDataDetached));
  1322. //
  1323. // Guard against data attach completion
  1324. //
  1325. KeReleaseMutex(&pAVCStrmExt->hMutexControl, FALSE);
  1326. EXIT("AVCStrmCancelIO", Status);
  1327. return Status;
  1328. }
  1329. NTSTATUS
  1330. AVCStrmValidateFormat(
  1331. PAVCSTRM_FORMAT_INFO pAVCFormatInfo
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. Validate AVC format information.
  1336. --*/
  1337. {
  1338. NTSTATUS Status;
  1339. PAGED_CODE();
  1340. Status = STATUS_SUCCESS;
  1341. if(pAVCFormatInfo->SizeOfThisBlock != sizeof(AVCSTRM_FORMAT_INFO)) {
  1342. TRACE(TL_STRM_ERROR,("pAVCFormatInfo:%x; SizeOfThisBlock:%d != %d\n", pAVCFormatInfo, pAVCFormatInfo->SizeOfThisBlock, sizeof(AVCSTRM_FORMAT_INFO)));
  1343. ASSERT((pAVCFormatInfo->SizeOfThisBlock == sizeof(AVCSTRM_FORMAT_INFO)) && "Invalid format info parameter!");
  1344. return STATUS_INVALID_PARAMETER;
  1345. }
  1346. TRACE(TL_STRM_TRACE|TL_CIP_TRACE,("ValidateFormat: pAVCFormatInfo:%x; idx:%d; SrcPkt:%d; RcvBuf:%d; XmtBuf:%d; Strip:%d; AvgTm:%d; BlkPeriod:%d\n",
  1347. pAVCFormatInfo,
  1348. pAVCFormatInfo->AVCStrmFormat,
  1349. pAVCFormatInfo->SrcPacketsPerFrame,
  1350. pAVCFormatInfo->NumOfRcvBuffers,
  1351. pAVCFormatInfo->NumOfXmtBuffers,
  1352. pAVCFormatInfo->OptionFlags,
  1353. pAVCFormatInfo->AvgTimePerFrame,
  1354. pAVCFormatInfo->BlockPeriod
  1355. ));
  1356. TRACE(TL_STRM_TRACE|TL_CIP_TRACE,("ValidateFormat: cip1(DBS:%d, FN:%x); cip2(FMT:%x, 50_60:%x, STYPE:%x, SYT:%x)\n",
  1357. pAVCFormatInfo->cipHdr1.DBS,
  1358. pAVCFormatInfo->cipHdr1.FN,
  1359. pAVCFormatInfo->cipHdr2.FMT,
  1360. pAVCFormatInfo->cipHdr2.F5060_OR_TSF,
  1361. pAVCFormatInfo->cipHdr2.STYPE,
  1362. pAVCFormatInfo->cipHdr2.SYT
  1363. ));
  1364. if(pAVCFormatInfo->SrcPacketsPerFrame == 0 ||
  1365. (pAVCFormatInfo->NumOfRcvBuffers == 0 && pAVCFormatInfo->NumOfXmtBuffers == 0) ||
  1366. // pAVCFormatInfo->AvgTimePerFrame == 0 ||
  1367. pAVCFormatInfo->BlockPeriod == 0 ||
  1368. pAVCFormatInfo->cipHdr1.DBS == 0
  1369. ) {
  1370. TRACE(TL_STRM_ERROR,("ValidateFormat: Invalid parametert!\n"));
  1371. return STATUS_INVALID_PARAMETER;
  1372. }
  1373. return Status;
  1374. }
  1375. NTSTATUS
  1376. AVCStrmAllocateQueues(
  1377. IN struct DEVICE_EXTENSION * pDevExt,
  1378. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  1379. IN KSPIN_DATAFLOW DataFlow,
  1380. IN PAVC_STREAM_DATA_STRUCT pDataStruc,
  1381. PAVCSTRM_FORMAT_INFO pAVCStrmFormatInfo
  1382. )
  1383. /*++
  1384. Routine Description:
  1385. Preallocated all nodes for the data queuding.
  1386. --*/
  1387. {
  1388. ULONG ulNumberOfNodes;
  1389. ULONG ulSizeOfOneNode; // Might combine multiple structures
  1390. ULONG ulSizeAllocated;
  1391. PBYTE pMemoryBlock;
  1392. PAVCSTRM_DATA_ENTRY pDataEntry;
  1393. ULONG i;
  1394. PCIP_HDR1 pCipHdr1;
  1395. PAGED_CODE();
  1396. ENTER("AVCStrmAllocateQueues");
  1397. //
  1398. // Pre-allcoate PC resource
  1399. //
  1400. ulNumberOfNodes = DataFlow == KSPIN_DATAFLOW_OUT ? \
  1401. pAVCStrmFormatInfo->NumOfRcvBuffers : pAVCStrmFormatInfo->NumOfXmtBuffers;
  1402. ASSERT(ulNumberOfNodes > 0);
  1403. ulSizeOfOneNode = sizeof(AVCSTRM_DATA_ENTRY) + sizeof(struct _CIP_FRAME);
  1404. ulSizeAllocated = ulNumberOfNodes * ulSizeOfOneNode;
  1405. pMemoryBlock = ExAllocatePool(NonPagedPool, ulSizeAllocated);
  1406. if(!pMemoryBlock) {
  1407. return STATUS_NO_MEMORY;
  1408. }
  1409. RtlZeroMemory(pMemoryBlock, ulSizeAllocated);
  1410. // Initialize data IO structure
  1411. InitializeListHead(&pDataStruc->DataAttachedListHead);
  1412. InitializeListHead(&pDataStruc->DataQueuedListHead);
  1413. InitializeListHead(&pDataStruc->DataDetachedListHead);
  1414. KeInitializeSpinLock(&pDataStruc->DataListLock);
  1415. KeInitializeEvent(&pDataStruc->hNoAttachEvent, NotificationEvent, FALSE);
  1416. // Cache it for freeing purpose;
  1417. pDataStruc->pMemoryBlock = pMemoryBlock;
  1418. pDataEntry = (PAVCSTRM_DATA_ENTRY) pMemoryBlock;
  1419. for (i=0; i < ulNumberOfNodes; i++) {
  1420. ((PBYTE) pDataEntry->Frame) = ((PBYTE) pDataEntry) + sizeof(AVCSTRM_DATA_ENTRY);
  1421. pDataEntry->pIrpLower = IoAllocateIrp(pDevExt->physicalDevObj->StackSize, FALSE);
  1422. if(!pDataEntry->pIrpLower) {
  1423. while(!IsListEmpty(&pDataStruc->DataDetachedListHead)) {
  1424. pDataEntry = (PAVCSTRM_DATA_ENTRY) \
  1425. RemoveHeadList(&pDataStruc->DataDetachedListHead); InterlockedDecrement(&pDataStruc->cntDataDetached);
  1426. if(pDataEntry->pIrpLower) {
  1427. IoFreeIrp(pDataEntry->pIrpLower); pDataEntry->pIrpLower = NULL;
  1428. }
  1429. }
  1430. ExFreePool(pMemoryBlock); pMemoryBlock = NULL;
  1431. return STATUS_INSUFFICIENT_RESOURCES;
  1432. }
  1433. pDataEntry->State = DE_IRP_UPPER_COMPLETED; // Inital state
  1434. InsertTailList(&pDataStruc->DataDetachedListHead, &pDataEntry->ListEntry); InterlockedIncrement(&pDataStruc->cntDataDetached);
  1435. ((PBYTE) pDataEntry) += ulSizeOfOneNode;
  1436. }
  1437. pCipHdr1 = &pAVCStrmFormatInfo->cipHdr1;
  1438. // Calculate source packet size (if strip header, 4 bytes less).
  1439. pDataStruc->SourcePacketSize = \
  1440. pCipHdr1->DBS * 4 * (1 << pCipHdr1->FN) - \
  1441. ((pAVCStrmFormatInfo->OptionFlags & AVCSTRM_FORMAT_OPTION_STRIP_SPH) ? 4 : 0);
  1442. pDataStruc->FrameSize = \
  1443. pDataStruc->SourcePacketSize * pAVCStrmFormatInfo->SrcPacketsPerFrame;
  1444. TRACE(TL_STRM_TRACE,("DBS:%d; FN:%d; SrcPktSz:%d; SrcPktPerFrame:%d; FrameSize:%d\n",
  1445. pCipHdr1->DBS, pCipHdr1->FN,
  1446. pDataStruc->SourcePacketSize, pAVCStrmFormatInfo->SrcPacketsPerFrame,
  1447. pDataStruc->FrameSize
  1448. ));
  1449. TRACE(TL_STRM_TRACE,("pDataStruc:%x; A(%d,%x); Q(%d,%x); D(%d,%x)\n", pDataStruc,
  1450. pDataStruc->cntDataAttached, &pDataStruc->DataAttachedListHead,
  1451. pDataStruc->cntDataQueued, &pDataStruc->DataQueuedListHead,
  1452. pDataStruc->cntDataDetached, &pDataStruc->DataDetachedListHead
  1453. ));
  1454. return STATUS_SUCCESS;
  1455. }
  1456. NTSTATUS
  1457. AVCStrmFreeQueues(
  1458. IN PAVC_STREAM_DATA_STRUCT pDataStruc
  1459. )
  1460. /*++
  1461. Routine Description:
  1462. Free nodes preallocated.
  1463. --*/
  1464. {
  1465. PAVCSTRM_DATA_ENTRY pDataEntry;
  1466. PAGED_CODE();
  1467. ENTER("AVCStrmFreeQueues");
  1468. while(!IsListEmpty(&pDataStruc->DataAttachedListHead)) {
  1469. pDataEntry = (PAVCSTRM_DATA_ENTRY) \
  1470. RemoveHeadList(&pDataStruc->DataAttachedListHead); InterlockedDecrement(&pDataStruc->cntDataAttached);
  1471. if(pDataEntry->pIrpLower) {
  1472. IoFreeIrp(pDataEntry->pIrpLower); pDataEntry->pIrpLower = NULL;
  1473. }
  1474. }
  1475. if(pDataStruc->cntDataAttached == 0) {
  1476. ExFreePool(pDataStruc->pMemoryBlock); pDataStruc->pMemoryBlock = NULL;
  1477. return STATUS_SUCCESS;
  1478. } else {
  1479. TRACE(TL_STRM_ERROR,("FreeQueue: pDataStruc:%x, cntDataAttached:%x\n", pDataStruc, pDataStruc->cntDataAttached));
  1480. ASSERT(pDataStruc->cntDataAttached == 0);
  1481. return STATUS_UNSUCCESSFUL;
  1482. }
  1483. }
  1484. void
  1485. AVCStrmAbortStreamingWorkItemRoutine(
  1486. #ifdef USE_WDM110 // Win2000 code base
  1487. // Extra parameter if using WDM10
  1488. PDEVICE_OBJECT DeviceObject,
  1489. #endif
  1490. IN PAVC_STREAM_EXTENSION pAVCStrmExt
  1491. )
  1492. /*++
  1493. Routine Description:
  1494. This work item routine will stop streaming and cancel all IOs while running at PASSIVE level.
  1495. --*/
  1496. {
  1497. PAGED_CODE();
  1498. ENTER("AVCStrmAbortStreamingWorkItemRoutine");
  1499. TRACE(TL_STRM_WARNING,("CancelWorkItem: StreamState:%d; lCancel:%d\n", pAVCStrmExt->StreamState, pAVCStrmExt->lAbortToken));
  1500. ASSERT(pAVCStrmExt->lAbortToken == 1);
  1501. #ifdef USE_WDM110 // Win2000 code base
  1502. ASSERT(pAVCStrmExt->pIoWorkItem);
  1503. #endif
  1504. if(pAVCStrmExt->StreamState == KSSTATE_STOP) {
  1505. ASSERT(pAVCStrmExt->StreamState == KSSTATE_STOP && "CancelWorkItem: Stream is already stopped!\n");
  1506. goto Done;
  1507. }
  1508. // Cancel all pending IOs
  1509. AVCStrmCancelIO(pAVCStrmExt->pDevExt->physicalDevObj, pAVCStrmExt);
  1510. Done:
  1511. #ifdef USE_WDM110 // Win2000 code base
  1512. // Release work item and release the cancel token
  1513. IoFreeWorkItem(pAVCStrmExt->pIoWorkItem); pAVCStrmExt->pIoWorkItem = NULL;
  1514. #endif
  1515. // Release token and indicate abort has completed.
  1516. InterlockedExchange(&pAVCStrmExt->lAbortToken, 0);
  1517. KeSetEvent(&pAVCStrmExt->hAbortDoneEvent, 0, FALSE);
  1518. }
  1519. /*****************************
  1520. * Property utility funcrtions
  1521. *****************************/
  1522. NTSTATUS
  1523. AVCStrmGetConnectionProperty(
  1524. IN struct DEVICE_EXTENSION * pDevExt,
  1525. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  1526. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1527. PULONG pulActualBytesTransferred
  1528. )
  1529. /*++
  1530. Routine Description:
  1531. Handles KS_PROPERTY_CONNECTION* request. For now, only ALLOCATORFRAMING and
  1532. CONNECTION_STATE are supported.
  1533. --*/
  1534. {
  1535. NTSTATUS Status = STATUS_SUCCESS;
  1536. PAGED_CODE();
  1537. ENTER("AVCStrmGetConnectionProperty");
  1538. TRACE(TL_STRM_TRACE,("GetConnectionProperty: entered ...\n"));
  1539. switch (pSPD->Property->Id) {
  1540. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  1541. if (pDevExt != NULL && pDevExt->NumberOfStreams) {
  1542. PKSALLOCATOR_FRAMING pFraming = (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  1543. pFraming->RequirementsFlags =
  1544. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  1545. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER |
  1546. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
  1547. pFraming->PoolType = NonPagedPool;
  1548. pFraming->Frames = \
  1549. pAVCStrmExt->DataFlow == KSPIN_DATAFLOW_OUT ? \
  1550. pAVCStrmExt->pAVCStrmFormatInfo->NumOfRcvBuffers : \
  1551. pAVCStrmExt->pAVCStrmFormatInfo->NumOfXmtBuffers;
  1552. // Note: we'll allocate the biggest frame. We need to make sure when we're
  1553. // passing the frame back up we also set the number of bytes in the frame.
  1554. pFraming->FrameSize = pAVCStrmExt->pAVCStrmDataStruc->FrameSize;
  1555. pFraming->FileAlignment = 0; // FILE_LONG_ALIGNMENT;
  1556. pFraming->Reserved = 0;
  1557. *pulActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  1558. TRACE(TL_STRM_TRACE,("*** AllocFraming: cntStrmOpen:%d; Frames %d; size:%d\n", \
  1559. pDevExt->NumberOfStreams, pFraming->Frames, pFraming->FrameSize));
  1560. } else {
  1561. TRACE(TL_STRM_ERROR,("*** AllocFraming: pDevExt:%x; cntStrmOpen:%d\n", pDevExt, pDevExt->NumberOfStreams));
  1562. Status = STATUS_INVALID_PARAMETER;
  1563. }
  1564. break;
  1565. default:
  1566. *pulActualBytesTransferred = 0;
  1567. Status = STATUS_NOT_SUPPORTED;
  1568. ASSERT(pSPD->Property->Id == KSPROPERTY_CONNECTION_ALLOCATORFRAMING);
  1569. break;
  1570. }
  1571. TRACE(TL_STRM_TRACE,("GetConnectionProperty: exit.\n"));
  1572. return Status;
  1573. }
  1574. NTSTATUS
  1575. AVCStrmGetDroppedFramesProperty(
  1576. IN struct DEVICE_EXTENSION * pDevExt,
  1577. IN PAVC_STREAM_EXTENSION pAVCStrmExt,
  1578. PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1579. PULONG pulBytesTransferred
  1580. )
  1581. /*++
  1582. Routine Description:
  1583. Return the dropped frame information while captureing.
  1584. --*/
  1585. {
  1586. NTSTATUS Status = STATUS_SUCCESS;
  1587. PAGED_CODE();
  1588. ENTER("AVCStrmGetDroppedFramesProperty");
  1589. switch (pSPD->Property->Id) {
  1590. case KSPROPERTY_DROPPEDFRAMES_CURRENT:
  1591. {
  1592. PKSPROPERTY_DROPPEDFRAMES_CURRENT_S pDroppedFrames =
  1593. (PKSPROPERTY_DROPPEDFRAMES_CURRENT_S) pSPD->PropertyInfo;
  1594. pDroppedFrames->AverageFrameSize = pAVCStrmExt->pAVCStrmDataStruc->FrameSize;
  1595. pDroppedFrames->PictureNumber = pAVCStrmExt->pAVCStrmDataStruc->PictureNumber;
  1596. pDroppedFrames->DropCount = pAVCStrmExt->pAVCStrmDataStruc->FramesDropped; // For transmit, this value includes both dropped and repeated.
  1597. TRACE(TL_STRM_TRACE,("*DroppedFP: Pic#(%d), Drp(%d)\n", (LONG) pDroppedFrames->PictureNumber, (LONG) pDroppedFrames->DropCount));
  1598. *pulBytesTransferred = sizeof (KSPROPERTY_DROPPEDFRAMES_CURRENT_S);
  1599. Status = STATUS_SUCCESS;
  1600. }
  1601. break;
  1602. default:
  1603. *pulBytesTransferred = 0;
  1604. Status = STATUS_NOT_SUPPORTED;
  1605. ASSERT(pSPD->Property->Id == KSPROPERTY_DROPPEDFRAMES_CURRENT);
  1606. break;
  1607. }
  1608. return Status;
  1609. }