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.

2335 lines
79 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include <strmini.h>
  12. #include <ksmedia.h>
  13. #include "kskludge.h"
  14. #include "codmain.h"
  15. #include "coddebug.h"
  16. #include <ntstatus.h>
  17. #include "defaults.h"
  18. #include "ccdecode.h"
  19. #include "ccformatcodes.h"
  20. #ifdef PERFTEST
  21. extern enum STREAM_DEBUG_LEVEL _CDebugLevel;
  22. enum STREAM_DEBUG_LEVEL OldLevel;
  23. ULONGLONG PerfThreshold = 250;
  24. #endif // PERFTEST
  25. //==========================================================================;
  26. // Routines for processing VBI streams
  27. //==========================================================================;
  28. void
  29. CheckResultsArray(
  30. PHW_DEVICE_EXTENSION pHwDevExt,
  31. unsigned int StartLine,
  32. unsigned int EndLine )
  33. {
  34. PDSPRESULT new;
  35. //
  36. // (Re)size the results array if needed
  37. //
  38. if( 0 == pHwDevExt->DSPResult ||
  39. EndLine > pHwDevExt->DSPResultEndLine ||
  40. StartLine < pHwDevExt->DSPResultStartLine )
  41. {
  42. if (StartLine > pHwDevExt->DSPResultStartLine)
  43. StartLine = pHwDevExt->DSPResultStartLine;
  44. if (EndLine < pHwDevExt->DSPResultEndLine)
  45. EndLine = pHwDevExt->DSPResultEndLine;
  46. new = ( PDSPRESULT ) ExAllocatePool(
  47. NonPagedPool,
  48. sizeof( DSPRESULT ) * ( EndLine - StartLine + 1 ) );
  49. if( new ) {
  50. if (pHwDevExt->DSPResult)
  51. ExFreePool( pHwDevExt->DSPResult );
  52. pHwDevExt->DSPResult = new;
  53. pHwDevExt->DSPResultStartLine = StartLine;
  54. pHwDevExt->DSPResultEndLine = EndLine;
  55. CDebugPrint( DebugLevelInfo,
  56. (CODECNAME ": Resized results array\n" ));
  57. }
  58. else {
  59. CDebugPrint( DebugLevelInfo,
  60. (CODECNAME ": Resize results array failed\n" ));
  61. CASSERT( new );
  62. pHwDevExt->Statistics.Common.InternalErrors++;
  63. }
  64. }
  65. }
  66. /*
  67. ** CheckNewVBIInfo
  68. **
  69. ** Checks for a new VBIInfoHeader
  70. **
  71. ** Here's a little trickery to save having separate builds for the infinite pin
  72. ** tee and MSTee filters. IPT, being Ring3, doesn't pass VBIInfoHeaders, but it
  73. ** does pass the flags to show they've changed. We only make a copy if the
  74. ** data is good, otherwise we stick with the default header we started with.
  75. **
  76. ** Arguments:
  77. **
  78. ** PHW_DEVICE_EXTENSION pHwDevExt
  79. ** PSTREAMEX pInStrmEx
  80. ** PKS_VBI_FRAME_INFO pInVBIFrameInfo
  81. ** PKSSTREAM_HEADER pInStreamHeader
  82. **
  83. ** Returns: nothing
  84. **
  85. ** Side Effects: none
  86. */
  87. int CheckNewVBIInfo(
  88. PHW_DEVICE_EXTENSION pHwDevExt,
  89. PSTREAMEX pInStrmEx,
  90. PKS_VBI_FRAME_INFO pInVBIFrameInfo
  91. )
  92. {
  93. PKS_VBIINFOHEADER pVBIInfoHeader = &pInStrmEx->CurrentVBIInfoHeader;
  94. PVBICODECFILTERING_STATISTICS_CC Stats = &pHwDevExt->Statistics;
  95. if( 0 == pInVBIFrameInfo->VBIInfoHeader.StartLine
  96. || 0 == pInVBIFrameInfo->VBIInfoHeader.EndLine
  97. || 0 == pInVBIFrameInfo->VBIInfoHeader.ActualLineStartTime )
  98. {
  99. return 0;
  100. }
  101. CDebugPrint( DebugLevelInfo, (CODECNAME ": VBIInfoHeader Change\n" ));
  102. Stats->Common.VBIHeaderChanges++;
  103. //
  104. // Resize the results array if needed
  105. //
  106. CheckResultsArray(pHwDevExt,
  107. pInVBIFrameInfo->VBIInfoHeader.StartLine,
  108. pInVBIFrameInfo->VBIInfoHeader.EndLine);
  109. //
  110. // Copy new VBI info header over old
  111. //
  112. RtlCopyMemory( pVBIInfoHeader,
  113. &pInVBIFrameInfo->VBIInfoHeader,
  114. sizeof( KS_VBIINFOHEADER ));
  115. //pVBIInfoHeader->ActualLineStartTime = 780;
  116. RtlZeroMemory( &pInStrmEx->ScanlinesDiscovered,
  117. sizeof( pInStrmEx->ScanlinesDiscovered ));
  118. RtlZeroMemory( &pInStrmEx->SubstreamsDiscovered,
  119. sizeof( pInStrmEx->SubstreamsDiscovered ));
  120. CDebugPrint( DebugLevelVerbose,
  121. ( CODECNAME ": VBIInfoHeader->StartLine %lu\n",
  122. pVBIInfoHeader->StartLine ));
  123. CDebugPrint( DebugLevelVerbose,
  124. ( CODECNAME ": VBIInfoHeader->EndLine %lu\n",
  125. pVBIInfoHeader->EndLine ));
  126. //CDebugPrint( DebugLevelVerbose,
  127. // ( CODECNAME ": VBIInfoHeader->SamplingFrequency %lu\n",
  128. // pVBIInfoHeader->SamplingFrequency ));
  129. CDebugPrint( DebugLevelVerbose,
  130. ( CODECNAME ": VBIInfoHeader->MinLineStartTime %lu\n",
  131. pVBIInfoHeader->MinLineStartTime ));
  132. CDebugPrint( DebugLevelVerbose,
  133. ( CODECNAME ": VBIInfoHeader->MaxLineStartTime %lu\n",
  134. pVBIInfoHeader->MaxLineStartTime ));
  135. CDebugPrint( DebugLevelVerbose,
  136. ( CODECNAME ": VBIInfoHeader->ActualLineStartTime %lu\n",
  137. pVBIInfoHeader->ActualLineStartTime ));
  138. CDebugPrint( DebugLevelVerbose,
  139. ( CODECNAME ": VBIInfoHeader->ActualLineEndTime %lu\n",
  140. pVBIInfoHeader->ActualLineEndTime ));
  141. CDebugPrint( DebugLevelVerbose,
  142. ( CODECNAME ": VBIInfoHeader->VideoStandard %lu\n",
  143. pVBIInfoHeader->VideoStandard ));
  144. CDebugPrint( DebugLevelVerbose,
  145. ( CODECNAME ": VBIInfoHeader->SamplesPerLine %lu\n",
  146. pVBIInfoHeader->SamplesPerLine ));
  147. CDebugPrint( DebugLevelVerbose,
  148. ( CODECNAME ": VBIInfoHeader->StrideInBytes %lu\n",
  149. pVBIInfoHeader->StrideInBytes ));
  150. CDebugPrint( DebugLevelVerbose,
  151. ( CODECNAME ": VBIInfoHeader->BufferSize %lu\n",
  152. pVBIInfoHeader->BufferSize ));
  153. return 1;
  154. }
  155. /*
  156. ** ProcessChannelChange
  157. **
  158. ** Handles a VBI_FLAG_TVTUNER_CHANGE event
  159. **
  160. ** Arguments:
  161. **
  162. ** PHW_DEVICE_EXTENSION pHwDevExt
  163. ** PSTREAMEX pInStrmEx
  164. ** PKS_VBI_FRAME_INFO pInVBIFrameInfo
  165. ** PKSSTREAM_HEADER pInStreamHeader
  166. **
  167. ** Returns: nothing
  168. **
  169. ** Side Effects: none
  170. */
  171. int ProcessChannelChange(
  172. PHW_DEVICE_EXTENSION pHwDevExt,
  173. PSTREAMEX pInStrmEx,
  174. PKS_VBI_FRAME_INFO pInVBIFrameInfo,
  175. PKSSTREAM_HEADER pInStreamHeader
  176. )
  177. {
  178. PKS_VBIINFOHEADER pVBIInfoHeader = &pInStrmEx->CurrentVBIInfoHeader;
  179. PVBICODECFILTERING_STATISTICS_CC Stats = &pHwDevExt->Statistics;
  180. PKS_TVTUNER_CHANGE_INFO pChangeInfo = &pInVBIFrameInfo->TvTunerChangeInfo;
  181. ULONG CurrentStrmEx;
  182. ULONG i;
  183. if( pChangeInfo->dwFlags & KS_TVTUNER_CHANGE_BEGIN_TUNE )
  184. {
  185. CDebugPrint( DebugLevelInfo, (CODECNAME ": TVTuner Change START\n" ));
  186. pHwDevExt->fTunerChange = TRUE;
  187. }
  188. else if( pChangeInfo->dwFlags & KS_TVTUNER_CHANGE_END_TUNE )
  189. {
  190. Stats->Common.TvTunerChanges++;
  191. pHwDevExt->fTunerChange = FALSE;
  192. CDebugPrint( DebugLevelInfo, (CODECNAME ": TVTuner Change END\n" ));
  193. RtlZeroMemory( &pInStrmEx->ScanlinesDiscovered,
  194. sizeof( pInStrmEx->ScanlinesDiscovered ));
  195. RtlZeroMemory( &pInStrmEx->SubstreamsDiscovered,
  196. sizeof( pInStrmEx->SubstreamsDiscovered ));
  197. CurrentStrmEx = 0;
  198. //
  199. // Flag a discontuity. This is passed to outgoing SRBs and will force
  200. // the downstream Line 21 decoder to clear its current CC data off the
  201. // screen.
  202. //
  203. for( i = 0; i < pHwDevExt->ActualInstances[STREAM_CC]; i++ )
  204. {
  205. PSTREAMEX pOutStrmEx;
  206. PHW_STREAM_REQUEST_BLOCK pOutSrb;
  207. PVBICODECFILTERING_STATISTICS_CC_PIN PinStats;
  208. do
  209. {
  210. CASSERT( CurrentStrmEx < MAX_PIN_INSTANCES );
  211. pOutStrmEx = pHwDevExt->pStrmEx[STREAM_CC][CurrentStrmEx++];
  212. }while( !pOutStrmEx );
  213. PinStats = &pOutStrmEx->PinStats;
  214. //
  215. // Get the next output stream SRB if it's available.
  216. //
  217. if( QueueRemove( &pOutSrb,
  218. &pOutStrmEx->StreamDataSpinLock,
  219. &pOutStrmEx->StreamDataQueue ) )
  220. {
  221. PKSSTREAM_HEADER pOutStreamHeader = pOutSrb->CommandData.DataBufferArray;
  222. PKS_VBI_FRAME_INFO pOutVBIFrameInfo = (PKS_VBI_FRAME_INFO)(pOutStreamHeader+1);
  223. PUCHAR pOutData = (PUCHAR)pOutStreamHeader->Data;
  224. if( pOutStreamHeader->FrameExtent < CCSamples )
  225. {
  226. CDebugPrint( DebugLevelError,
  227. ( CODECNAME ": Outgoing Data SRB buffer is too small %u\n",
  228. pOutStreamHeader->FrameExtent ));
  229. PinStats->Common.InternalErrors++;
  230. Stats->Common.OutputFailures++;
  231. pOutStreamHeader->DataUsed = 0;
  232. }
  233. else
  234. {
  235. PinStats->Common.SRBsProcessed++;
  236. Stats->Common.OutputSRBsProcessed++;
  237. CDebugPrint( DebugLevelInfo,
  238. (CODECNAME ": Propagating data discontinuity, instance %u\n", i ));
  239. pOutData[0] = 0;
  240. pOutData[1] = 0;
  241. pOutStreamHeader->DataUsed = 2;
  242. pOutStreamHeader->OptionsFlags =
  243. pInStreamHeader->OptionsFlags |
  244. KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  245. CDebugPrint( DebugLevelInfo,
  246. (CODECNAME ": OptionsFlags %x\n", pOutStreamHeader->OptionsFlags ));
  247. CDebugPrint( DebugLevelInfo,
  248. ("" "Time %x Num %x Denom %x\n",
  249. pInStreamHeader->PresentationTime.Time,
  250. pInStreamHeader->PresentationTime.Numerator,
  251. pInStreamHeader->PresentationTime.Denominator
  252. ));
  253. RtlCopyMemory( &pOutStreamHeader->PresentationTime,
  254. &pInStreamHeader->PresentationTime,
  255. sizeof( pOutStreamHeader->PresentationTime ));
  256. pOutStreamHeader->Duration = pInStreamHeader->Duration;
  257. }
  258. CDebugPrint( DebugLevelVerbose,
  259. ( CODECNAME ": Releasing Output SRB %x\n", pOutSrb ));
  260. // Complete the output SRB
  261. StreamClassStreamNotification( StreamRequestComplete,
  262. pOutSrb->StreamObject, pOutSrb );
  263. pOutStrmEx->fDiscontinuity = FALSE;
  264. PinStats->Common.BytesOutput += pOutStreamHeader->DataUsed;
  265. Stats->Common.BytesOutput += pOutStreamHeader->DataUsed;
  266. }
  267. else
  268. {
  269. pOutStrmEx->fDiscontinuity = TRUE;
  270. Stats->Common.OutputSRBsMissing++;
  271. }
  272. }
  273. return 1;
  274. }
  275. return 0;
  276. }
  277. void
  278. DebugPrintSubStreamMode( DWORD dwMode )
  279. {
  280. #ifdef DEBUG
  281. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_XDS )
  282. {
  283. CDebugPrint( DebugLevelWarning, ( "\n[XDS]" ));
  284. }
  285. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_CC1 )
  286. {
  287. CDebugPrint( DebugLevelWarning, ( "\n[CC1]" ));
  288. }
  289. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_CC2 )
  290. {
  291. CDebugPrint( DebugLevelWarning, ( "\n[CC2]" ));
  292. }
  293. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_CC3 )
  294. {
  295. CDebugPrint( DebugLevelWarning, ( "\n[CC3]" ));
  296. }
  297. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_CC4 )
  298. {
  299. CDebugPrint( DebugLevelWarning, ( "\n[CC4]" ));
  300. }
  301. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_T1 )
  302. {
  303. CDebugPrint( DebugLevelWarning, ( "\n[T1]" ));
  304. }
  305. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_T2 )
  306. {
  307. CDebugPrint( DebugLevelWarning, ( "\n[T2]" ));
  308. }
  309. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_T3 )
  310. {
  311. CDebugPrint( DebugLevelWarning, ( "\n[T3]" ));
  312. }
  313. if ( dwMode & KS_CC_SUBSTREAM_SERVICE_T4 )
  314. {
  315. CDebugPrint( DebugLevelWarning, ( "\n[T4]" ));
  316. }
  317. #endif
  318. }
  319. // Get the substream mode for the current data sample - optionally change the substream mode
  320. // The following "protocol" is loosely defined by FCC 91-119, FCC 92-157 and EIA 608
  321. // Be advised that EIA 608 describes clearly which (few) byte pairs change the substream mode
  322. DWORD
  323. GetSubStreamMode( DWORD dwFrameFlags, LPDWORD pdwCurrentSubStreamMode, PDSPRESULT pDSPResult )
  324. {
  325. DWORD dwSubStreamMode = *pdwCurrentSubStreamMode;
  326. DWORD dwDataChannel = 0;
  327. dwFrameFlags &= (KS_VBI_FLAG_FIELD1 | KS_VBI_FLAG_FIELD2);
  328. if ( pDSPResult->Confidence >= 75 )
  329. {
  330. // Inspect the first byte(minus parity) to see what substream this might be
  331. switch ( pDSPResult->Decoded[0] & 0x7F )
  332. {
  333. case CC_XDS_START_CURRENT:
  334. case CC_XDS_CONTINUE_CURRENT:
  335. case CC_XDS_START_FUTURE:
  336. case CC_XDS_CONTINUE_FUTURE:
  337. case CC_XDS_START_CHANNEL:
  338. case CC_XDS_CONTINUE_CHANNEL:
  339. case CC_XDS_START_MISC:
  340. case CC_XDS_CONTINUE_MISC:
  341. case CC_XDS_START_PUBLIC_SERVICE:
  342. case CC_XDS_CONTINUE_PUBLIC_SERVICE:
  343. case CC_XDS_START_RESERVED:
  344. case CC_XDS_CONTINUE_RESERVED:
  345. case CC_XDS_START_UNDEFINED:
  346. case CC_XDS_CONTINUE_UNDEFINED:
  347. case CC_XDS_END:
  348. // Set the substream mode as XDS from here on out
  349. dwSubStreamMode = ( dwFrameFlags | KS_CC_SUBSTREAM_SERVICE_XDS);
  350. DebugPrintSubStreamMode( dwSubStreamMode );
  351. *pdwCurrentSubStreamMode = dwSubStreamMode;
  352. break;
  353. case CC_MCC_FIELD1_DC1:
  354. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_CC1;
  355. break;
  356. case CC_MCC_FIELD1_DC2:
  357. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_CC2;
  358. break;
  359. case CC_MCC_FIELD2_DC1:
  360. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_CC3;
  361. break;
  362. case CC_MCC_FIELD2_DC2:
  363. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_CC4;
  364. break;
  365. }
  366. // If we found a data channel escape, inspect the second byte(minus parity) to see what substream may be.
  367. if ( dwDataChannel )
  368. {
  369. switch ( pDSPResult->Decoded[1] & 0x7F )
  370. {
  371. case CC_MCC_RCL:
  372. case CC_MCC_RU2:
  373. case CC_MCC_RU3:
  374. case CC_MCC_RU4:
  375. case CC_MCC_RDC:
  376. case CC_MCC_EOC:
  377. // The mode is good for this data pair and thereafter
  378. dwSubStreamMode = (dwFrameFlags | dwDataChannel);
  379. DebugPrintSubStreamMode( dwSubStreamMode );
  380. *pdwCurrentSubStreamMode = dwSubStreamMode;
  381. break;
  382. case CC_MCC_TR:
  383. case CC_MCC_RTD:
  384. // The mode is TEXT rather CC, map to the text channel ids
  385. switch ( dwDataChannel )
  386. {
  387. case KS_CC_SUBSTREAM_SERVICE_CC1:
  388. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_T1;
  389. break;
  390. case KS_CC_SUBSTREAM_SERVICE_CC2:
  391. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_T2;
  392. break;
  393. case KS_CC_SUBSTREAM_SERVICE_CC3:
  394. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_T3;
  395. break;
  396. case KS_CC_SUBSTREAM_SERVICE_CC4:
  397. dwDataChannel = KS_CC_SUBSTREAM_SERVICE_T4;
  398. break;
  399. }
  400. // The mode is good for this data byte pair and thereafter
  401. dwSubStreamMode = (dwFrameFlags | dwDataChannel);
  402. DebugPrintSubStreamMode( dwSubStreamMode );
  403. *pdwCurrentSubStreamMode = dwSubStreamMode;
  404. break;
  405. case CC_MCC_EDM:
  406. case CC_MCC_ENM:
  407. // The mode is only good for this data byte pair. Reverts back thereafter
  408. dwSubStreamMode = (dwFrameFlags | dwDataChannel);
  409. DebugPrintSubStreamMode( dwSubStreamMode );
  410. DebugPrintSubStreamMode( *pdwCurrentSubStreamMode );
  411. break;
  412. }
  413. }
  414. }
  415. return dwSubStreamMode;
  416. }
  417. /*
  418. ** OutputCC
  419. **
  420. ** Outputs just-decoded/received CC to any interested pins
  421. **
  422. ** Arguments:
  423. **
  424. ** PHW_DEVICE_EXTENSION pHwDevExt
  425. ** PSTREAMEX pInStrmEx
  426. ** PKS_VBI_FRAME_INFO pInVBIFrameInfo
  427. ** PKSSTREAM_HEADER pInStreamHeader
  428. **
  429. ** Returns: nothing
  430. **
  431. ** Side Effects: none
  432. */
  433. void OutputCC(
  434. PHW_DEVICE_EXTENSION pHwDevExt,
  435. PSTREAMEX pInStrmEx,
  436. DWORD dwOriginalFrameFlags,
  437. PKSSTREAM_HEADER pInStreamHeader )
  438. {
  439. ULONG i,
  440. ScanlineCount,
  441. CurrentStrmEx = 0;
  442. PKS_VBIINFOHEADER pVBIInfoHeader = &pInStrmEx->CurrentVBIInfoHeader;
  443. PVBICODECFILTERING_STATISTICS_CC Stats = 0;
  444. #ifdef PERFTEST
  445. ULONGLONG PerfStartTime = 0,
  446. PerfPreDownstreamCompletion = 0,
  447. PerfPostDownstreamCompletion = 0;
  448. LARGE_INTEGER PerfFrequency;
  449. PerfStartTime = KeQueryPerformanceCounter( &PerfFrequency ).QuadPart;
  450. OldLevel = _CDebugLevel;
  451. _CDebugLevel = DebugLevelFatal;
  452. #endif // PERFTEST
  453. CASSERT(pHwDevExt);
  454. CASSERT(pInStrmEx);
  455. Stats = &pHwDevExt->Statistics;
  456. CDebugPrint( DebugLevelInfo, ( "*" ));
  457. CDebugPrint( DebugLevelTrace, ( CODECNAME ": --->OutputCC\n" ));
  458. // If this substream is requested by anybody (field or cc data channel)
  459. if(( pInStrmEx->SubstreamsRequested.SubstreamMask ))
  460. {
  461. // Loop through all pending outbound requests and fill each irp with the requested data then complete the IO
  462. for( ScanlineCount = pVBIInfoHeader->StartLine; ScanlineCount <= pVBIInfoHeader->EndLine;
  463. ScanlineCount++ )
  464. {
  465. DWORD dwSubStreams = 0;
  466. DWORD dwFieldIndex = dwOriginalFrameFlags & KS_VBI_FLAG_FIELD1 ? 0 : 1;
  467. DWORD dwScanLineIndex = ScanlineCount - pHwDevExt->DSPResultStartLine;
  468. if( !TESTBIT( pInStrmEx->ScanlinesRequested.DwordBitArray, ScanlineCount ))
  469. continue;
  470. dwSubStreams = GetSubStreamMode(
  471. dwOriginalFrameFlags,
  472. &pHwDevExt->SubStreamState[dwScanLineIndex][dwFieldIndex],
  473. &pHwDevExt->DSPResult[dwScanLineIndex]
  474. );
  475. CDebugPrint( DebugLevelWarning, ( "%c%c",
  476. pHwDevExt->DSPResult[dwScanLineIndex].Decoded[0] & 0x7f,
  477. pHwDevExt->DSPResult[dwScanLineIndex].Decoded[1] & 0x7f ));
  478. CDebugPrint( DebugLevelInfo, (CODECNAME ": F%u %luus L%u %u%% %02x %02x\n",
  479. dwSubStreams & pInStrmEx->SubstreamsRequested.SubstreamMask,
  480. pVBIInfoHeader->ActualLineStartTime,
  481. ScanlineCount,
  482. pHwDevExt->DSPResult[dwScanLineIndex].Confidence,
  483. pHwDevExt->DSPResult[dwScanLineIndex].Decoded[0] & 0xff,
  484. pHwDevExt->DSPResult[dwScanLineIndex].Decoded[1] & 0xff ));
  485. CurrentStrmEx = 0;
  486. for( i = 0; i < pHwDevExt->ActualInstances[STREAM_CC]; i++ )
  487. {
  488. PSTREAMEX pOutStrmEx;
  489. PHW_STREAM_REQUEST_BLOCK pOutSrb;
  490. PVBICODECFILTERING_STATISTICS_CC_PIN PinStats;
  491. do
  492. {
  493. CASSERT( CurrentStrmEx < MAX_PIN_INSTANCES );
  494. if( CurrentStrmEx == MAX_PIN_INSTANCES )
  495. Stats->Common.InternalErrors++;
  496. pOutStrmEx = pHwDevExt->pStrmEx[STREAM_CC][CurrentStrmEx++];
  497. }while( !pOutStrmEx );
  498. if( !TESTBIT( pOutStrmEx->ScanlinesRequested.DwordBitArray, ScanlineCount ) ||
  499. !( pOutStrmEx->SubstreamsRequested.SubstreamMask & dwSubStreams ))
  500. continue;
  501. PinStats = &pOutStrmEx->PinStats;
  502. //
  503. // Update the average confidence for this pin
  504. //
  505. PinStats->Common.LineConfidenceAvg = ( PinStats->Common.LineConfidenceAvg +
  506. pHwDevExt->DSPResult[dwScanLineIndex].Confidence ) / 2;
  507. if( pHwDevExt->DSPResult[dwScanLineIndex].Confidence >= 75 )
  508. {
  509. SETBIT( pInStrmEx->ScanlinesDiscovered.DwordBitArray, ScanlineCount );
  510. SETBIT( pOutStrmEx->ScanlinesDiscovered.DwordBitArray, ScanlineCount );
  511. SETBIT( pHwDevExt->ScanlinesDiscovered.DwordBitArray, ScanlineCount );
  512. pInStrmEx->SubstreamsDiscovered.SubstreamMask |= dwSubStreams;
  513. pOutStrmEx->SubstreamsDiscovered.SubstreamMask |= dwSubStreams;
  514. pHwDevExt->SubstreamsDiscovered.SubstreamMask |= dwSubStreams;
  515. }
  516. else
  517. {
  518. Stats->Common.DSPFailures++;
  519. PinStats->Common.SRBsIgnored++;
  520. if(( dwSubStreams & KS_CC_SUBSTREAM_ODD ) &&
  521. TESTBIT( pInStrmEx->LastOddScanlinesDiscovered.DwordBitArray, ScanlineCount ))
  522. pOutStrmEx->fDiscontinuity = TRUE;
  523. if(( dwSubStreams & KS_CC_SUBSTREAM_EVEN ) &&
  524. TESTBIT( pInStrmEx->LastEvenScanlinesDiscovered.DwordBitArray, ScanlineCount ))
  525. pOutStrmEx->fDiscontinuity = TRUE;
  526. if( !pOutStrmEx->fDiscontinuity )
  527. continue;
  528. }
  529. // Only process the output streams which have an SRB ready
  530. if( QueueRemove( &pOutSrb,
  531. &pOutStrmEx->StreamDataSpinLock,
  532. &pOutStrmEx->StreamDataQueue
  533. ))
  534. {
  535. PKSSTREAM_HEADER pOutStreamHeader = pOutSrb->CommandData.DataBufferArray;
  536. PKS_VBI_FRAME_INFO pOutVBIFrameInfo = (PKS_VBI_FRAME_INFO)(pOutStreamHeader+1);
  537. PUCHAR pOutData = (PUCHAR)pOutStreamHeader->Data;
  538. PinStats->Common.SRBsProcessed++;
  539. Stats->Common.OutputSRBsProcessed++;
  540. if( pOutStreamHeader->FrameExtent < pOutStrmEx->MatchedFormat.SampleSize )
  541. {
  542. CDebugPrint( DebugLevelError,
  543. ( CODECNAME ": Outgoing Data SRB buffer is too small %u\n",
  544. pOutStreamHeader->FrameExtent ));
  545. PinStats->Common.InternalErrors++;
  546. Stats->Common.OutputFailures++;
  547. pOutStreamHeader->DataUsed = 0;
  548. }
  549. // Check on inbound & outbound data formats to decide
  550. // whether to copy or decode the inbound data
  551. // Figure out how much of the decoded data was requested
  552. pOutStreamHeader->Size = pInStreamHeader->Size;
  553. pOutStreamHeader->OptionsFlags = pInStreamHeader->OptionsFlags;
  554. pOutStreamHeader->Duration = pInStreamHeader->Duration;
  555. RtlCopyMemory( &pOutStreamHeader->PresentationTime,
  556. &pInStreamHeader->PresentationTime,
  557. sizeof( pOutStreamHeader->PresentationTime ));
  558. // pOutData is the output location.
  559. ASSERT( pOutStreamHeader->FrameExtent >= CCSamples );
  560. pOutStreamHeader->DataUsed = 2;
  561. //
  562. // If we have a discontinity to go out then send it
  563. // instead of the data
  564. //
  565. if( pOutStrmEx->fDiscontinuity )
  566. {
  567. PinStats->Common.Discontinuities++;
  568. pOutData[0] = 0xff;
  569. pOutData[1] = 0xff;
  570. pOutStreamHeader->OptionsFlags |=
  571. KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY;
  572. pOutStrmEx->fDiscontinuity = FALSE;
  573. }
  574. else
  575. {
  576. pOutData[0] = pHwDevExt->DSPResult[ScanlineCount - pHwDevExt->DSPResultStartLine].Decoded[0];
  577. pOutData[1] = pHwDevExt->DSPResult[ScanlineCount - pHwDevExt->DSPResultStartLine].Decoded[1];
  578. }
  579. CDebugPrint( DebugLevelInfo,
  580. (CODECNAME ": OptionsFlags %x\n", pOutStreamHeader->OptionsFlags ));
  581. CDebugPrint( DebugLevelInfo,
  582. ("" "Time %x Num %x Denom %x\n",
  583. pInStreamHeader->PresentationTime.Time,
  584. pInStreamHeader->PresentationTime.Numerator,
  585. pInStreamHeader->PresentationTime.Denominator
  586. ));
  587. //CDebugPrint( DebugLevelWarning, ( "" "%d%", i ));
  588. Stats->Common.BytesOutput += pOutStreamHeader->DataUsed;
  589. PinStats->Common.BytesOutput += pOutStreamHeader->DataUsed;
  590. CDebugPrint( DebugLevelVerbose,
  591. ( CODECNAME ": Releasing Output SRB %x\n",
  592. pOutSrb ));
  593. // Complete the output SRB
  594. #ifdef PERFTEST
  595. if( i == 0 )
  596. PerfPreDownstreamCompletion =
  597. KeQueryPerformanceCounter( NULL ).QuadPart;
  598. #endif // PERFTEST
  599. StreamClassStreamNotification( StreamRequestComplete,
  600. pOutSrb->StreamObject, pOutSrb );
  601. #ifdef PERFTEST
  602. if( i == 0 )
  603. PerfPostDownstreamCompletion =
  604. KeQueryPerformanceCounter( NULL ).QuadPart;
  605. #endif // PERFTEST
  606. }
  607. else
  608. {
  609. PinStats->Common.SRBsMissing++;
  610. Stats->Common.OutputSRBsMissing++;
  611. }
  612. }
  613. }
  614. }
  615. //
  616. // Remember the streams we discovered so that if they aren't discovered next
  617. // time we know we have to send a single discontinuity.
  618. //
  619. if(( dwOriginalFrameFlags & KS_CC_SUBSTREAM_EVEN ) == KS_CC_SUBSTREAM_EVEN )
  620. RtlCopyMemory( &pInStrmEx->LastEvenScanlinesDiscovered, &pInStrmEx->ScanlinesDiscovered,
  621. sizeof( pInStrmEx->LastEvenScanlinesDiscovered ));
  622. if(( dwOriginalFrameFlags & KS_CC_SUBSTREAM_ODD ) == KS_CC_SUBSTREAM_ODD )
  623. RtlCopyMemory( &pInStrmEx->LastOddScanlinesDiscovered, &pInStrmEx->ScanlinesDiscovered,
  624. sizeof( pInStrmEx->LastOddScanlinesDiscovered ));
  625. #ifdef PERFTEST
  626. PerfFrequency.QuadPart /= 1000000L; // Convert to ticks/us
  627. if( PerfPreDownstreamCompletion )
  628. {
  629. PerfPreDownstreamCompletion -= PerfStartTime;
  630. PerfPreDownstreamCompletion /= PerfFrequency.QuadPart;
  631. }
  632. if( PerfPostDownstreamCompletion )
  633. {
  634. PerfPostDownstreamCompletion -= PerfStartTime;
  635. PerfPostDownstreamCompletion /= PerfFrequency.QuadPart;
  636. }
  637. //
  638. // Complain if anything takes more than threshold
  639. //
  640. if( PerfPreDownstreamCompletion > PerfThreshold )
  641. CDebugPrint( DebugLevelFatal, ( CODECNAME ": PerfPreDownstreamCompletion %luus\n",
  642. PerfPreDownstreamCompletion ));
  643. if( PerfPostDownstreamCompletion > PerfThreshold )
  644. CDebugPrint( DebugLevelFatal, ( CODECNAME ": PerfPostDownstreamCompletion %luus\n",
  645. PerfPostDownstreamCompletion ));
  646. _CDebugLevel = OldLevel;
  647. #endif // PERFTEST
  648. CDebugPrint( DebugLevelTrace, ( CODECNAME ": <---OutputCC\n" ));
  649. }
  650. /*
  651. ** VBIDecode
  652. **
  653. ** Decodes an incoming SRB. SRB is already removed from queue.
  654. **
  655. ** Arguments:
  656. **
  657. ** PHW_DEVICE_EXTENSION pHwDevExt
  658. ** PSTREAMEX pInStrmEx
  659. ** IN PHW_STREAM_REQUEST_BLOCK pInSrb
  660. **
  661. ** Returns:
  662. **
  663. ** Side Effects: none
  664. */
  665. #ifdef DEBUG
  666. short CCskipDecode = 0;
  667. #endif /*DEBUG*/
  668. void VBIDecode(
  669. PHW_DEVICE_EXTENSION pHwDevExt,
  670. PSTREAMEX pInStrmEx,
  671. PHW_STREAM_REQUEST_BLOCK pInSrb,
  672. BOOL OkToHold )
  673. {
  674. PKSSTREAM_HEADER pInStreamHeader = pInSrb->CommandData.DataBufferArray;
  675. KSSTREAM_HEADER InStreamHeaderCopy;
  676. PKS_VBI_FRAME_INFO pInVBIFrameInfo = (PKS_VBI_FRAME_INFO)(pInStreamHeader+1);
  677. DWORD dwFrameFlags;
  678. PUCHAR pInData = (PUCHAR)pInStreamHeader->Data;
  679. ULONG i, j,
  680. ScanlineCount,
  681. DSPStatus,
  682. CurrentStrmEx = 0;
  683. CCLineStats DSPStatistics;
  684. PKS_VBIINFOHEADER pVBIInfoHeader = &pInStrmEx->CurrentVBIInfoHeader;
  685. PVBICODECFILTERING_STATISTICS_CC Stats = 0;
  686. CASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  687. #ifdef PERFTEST
  688. ULONGLONG PerfStartTime = 0,
  689. PerfPreUpstreamCompletion = 0,
  690. PerfPostUpstreamCompletion = 0;
  691. LARGE_INTEGER PerfFrequency;
  692. PerfStartTime = KeQueryPerformanceCounter( &PerfFrequency ).QuadPart;
  693. OldLevel = _CDebugLevel;
  694. _CDebugLevel = DebugLevelFatal;
  695. #endif // PERFTEST
  696. CASSERT(pHwDevExt);
  697. CASSERT(pInStrmEx);
  698. Stats = &pHwDevExt->Statistics;
  699. CDebugPrint( DebugLevelTrace, ( CODECNAME ": --->VBIDecode\n" ));
  700. #ifdef CCINPUTPIN
  701. if (!OkToHold)
  702. goto GoodToGo; // We've already processed discontinuties & stuff below
  703. #endif // CCINPUTPIN
  704. CDebugPrint( DebugLevelInfo, ( "*" ));
  705. Stats->Common.InputSRBsProcessed++;
  706. //
  707. // If DataUsed == 0 then don't bother
  708. //
  709. if( pInStreamHeader->DataUsed < 1
  710. #ifdef DEBUG
  711. || CCskipDecode
  712. #endif /*DEBUG*/
  713. )
  714. {
  715. Stats->Common.SRBsIgnored++;
  716. #ifdef DEBUG
  717. if (!CCskipDecode)
  718. #endif /*DEBUG*/
  719. CDebugPrint( DebugLevelError, ( CODECNAME ": DataUsed == 0, abandoning\n" ));
  720. StreamClassStreamNotification( StreamRequestComplete, pInSrb->StreamObject,
  721. pInSrb );
  722. return;
  723. }
  724. //
  725. // Test for dropped fields
  726. //
  727. if( pInStrmEx->LastPictureNumber )
  728. {
  729. LONGLONG Dropped = pInVBIFrameInfo->PictureNumber - pInStrmEx->LastPictureNumber - 1;
  730. if( Dropped > 0 )
  731. {
  732. if( Dropped < 60*60*60 ) // One hour worth of video fields
  733. Stats->Common.InputSRBsMissing += (DWORD)Dropped;
  734. else
  735. Stats->Common.InputSRBsMissing++; // Some improbable number of fields got dropped, indicate a single lost field.
  736. CDebugPrint( DebugLevelWarning, ( "$" ));
  737. }
  738. }
  739. pInStrmEx->LastPictureNumber = pInVBIFrameInfo->PictureNumber;
  740. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": pInVBIFrameInfo->ExtendedHeaderSize %d\n",
  741. pInVBIFrameInfo->ExtendedHeaderSize ));
  742. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": pInVBIFrameInfo->dwFrameFlags %x\n",
  743. pInVBIFrameInfo->dwFrameFlags ));
  744. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": pInVBIFrameInfo->PictureNumber %lu\n",
  745. pInVBIFrameInfo->PictureNumber ));
  746. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": pInVBIFrameInfo->DropCount %lu\n",
  747. pInVBIFrameInfo->DropCount ));
  748. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": pInVBIFrameInfo->dwSamplingFrequency %lu\n",
  749. pInVBIFrameInfo->dwSamplingFrequency ));
  750. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": pInStreamHeader->FrameExtent %d\n",
  751. pInStreamHeader->FrameExtent ));
  752. //
  753. // Update stats
  754. //
  755. if( ( pInStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY ) ||
  756. ( pInStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY ) )
  757. Stats->Common.InputDiscontinuities++;
  758. //
  759. // Check for a new VBIINFOHEADER
  760. //
  761. if( pInVBIFrameInfo->dwFrameFlags & KS_VBI_FLAG_VBIINFOHEADER_CHANGE ) {
  762. CheckNewVBIInfo( pHwDevExt, pInStrmEx, pInVBIFrameInfo );
  763. }
  764. //
  765. // Check for a channel change
  766. //
  767. if( pInVBIFrameInfo->dwFrameFlags & KS_VBI_FLAG_TVTUNER_CHANGE )
  768. {
  769. if( ProcessChannelChange(
  770. pHwDevExt, pInStrmEx, pInVBIFrameInfo, pInStreamHeader ))
  771. {
  772. StreamClassStreamNotification(
  773. StreamRequestComplete,
  774. pInSrb->StreamObject,
  775. pInSrb );
  776. return;
  777. }
  778. }
  779. //
  780. // pHwDevExt->fTunerChange is set while the TV tuner is changing channels.
  781. // SRBs are junk until the channel change completes so complete.
  782. //
  783. if( pHwDevExt->fTunerChange)
  784. {
  785. CDebugPrint( DebugLevelVerbose,
  786. ( CODECNAME ": Completing, channel change in progress\n" ));
  787. StreamClassStreamNotification(
  788. StreamRequestComplete,
  789. pInSrb->StreamObject,
  790. pInSrb );
  791. return;
  792. }
  793. // Clear the current scanline & substream request masks
  794. RtlZeroMemory( &pInStrmEx->ScanlinesRequested, sizeof(pInStrmEx->ScanlinesRequested) );
  795. RtlZeroMemory( &pInStrmEx->SubstreamsRequested, sizeof(pInStrmEx->SubstreamsRequested) );
  796. //
  797. // Calculate the current request from union of the output pins w/pending SRBs that are
  798. // interested in this substream.
  799. //
  800. CurrentStrmEx = 0;
  801. for( i = 0; i < pHwDevExt->ActualInstances[STREAM_CC]; i++ )
  802. {
  803. PSTREAMEX pOutStrmEx;
  804. do
  805. {
  806. CASSERT( CurrentStrmEx < MAX_PIN_INSTANCES );
  807. pOutStrmEx = pHwDevExt->pStrmEx[STREAM_CC][CurrentStrmEx++];
  808. }while( !pOutStrmEx );
  809. if ( pInVBIFrameInfo->dwFrameFlags & KS_VBI_FLAG_TVTUNER_CHANGE )
  810. pOutStrmEx->fDiscontinuity = TRUE;
  811. //
  812. // For actual processing, just include the scanlines of the clients who are
  813. // interested in this particular substream.
  814. //
  815. if ( ( ( pInVBIFrameInfo->dwFrameFlags & KS_CC_SUBSTREAM_ODD ) &&
  816. ( pOutStrmEx->SubstreamsRequested.SubstreamMask & (KS_CC_SUBSTREAM_ODD|KS_CC_SUBSTREAM_FIELD1_MASK) ) ) ||
  817. ( ( pInVBIFrameInfo->dwFrameFlags & KS_CC_SUBSTREAM_EVEN ) &&
  818. ( pOutStrmEx->SubstreamsRequested.SubstreamMask & (KS_CC_SUBSTREAM_EVEN|KS_CC_SUBSTREAM_FIELD2_MASK) ) ) )
  819. {
  820. for( j = 0; j < SIZEOF_ARRAY( pInStrmEx->ScanlinesRequested.DwordBitArray ); j++ )
  821. pInStrmEx->ScanlinesRequested.DwordBitArray[j] |=
  822. pOutStrmEx->ScanlinesRequested.DwordBitArray[j];
  823. // Create the union of all the requested substreams
  824. pInStrmEx->SubstreamsRequested.SubstreamMask |=
  825. pOutStrmEx->SubstreamsRequested.SubstreamMask;
  826. }
  827. }
  828. // Decode the union of all the pending decode requests into a local decode buffer.
  829. #ifdef CCINPUTPIN
  830. GoodToGo:
  831. // Whoever gets there first (VBI pin vs. HW pin) supplies CC data
  832. ExAcquireFastMutex(&pHwDevExt->LastPictureMutex);
  833. if (pInStrmEx->LastPictureNumber <= pHwDevExt->LastPictureNumber) {
  834. // HW pin beat us to it
  835. ExReleaseFastMutex(&pHwDevExt->LastPictureMutex);
  836. StreamClassStreamNotification( StreamRequestComplete,
  837. pInSrb->StreamObject,
  838. pInSrb );
  839. return;
  840. }
  841. // Is the HW stream open?
  842. if (OkToHold && pHwDevExt->ActualInstances[STREAM_CCINPUT] > 0)
  843. {
  844. KIRQL Irql;
  845. // We're going to give the HW pin a chance to catch up
  846. ExReleaseFastMutex(&pHwDevExt->LastPictureMutex);
  847. KeAcquireSpinLock(&pInStrmEx->VBIOnHoldSpinLock, &Irql);
  848. CASSERT(NULL == pInStrmEx->pVBISrbOnHold);
  849. pInStrmEx->pVBISrbOnHold = pInSrb;
  850. KeReleaseSpinLock(&pInStrmEx->VBIOnHoldSpinLock, Irql);
  851. return;
  852. }
  853. // HW input pin not open or too late; we'll process this SRB
  854. pHwDevExt->LastPictureNumber = pInStrmEx->LastPictureNumber;
  855. ExReleaseFastMutex(&pHwDevExt->LastPictureMutex);
  856. #endif // CCINPUTPIN
  857. CDebugPrint( DebugLevelTrace,
  858. ( CODECNAME ": Requested SubstreamMask %x\n",
  859. pInStrmEx->SubstreamsRequested.SubstreamMask ));
  860. CDebugPrint( DebugLevelTrace,
  861. ( CODECNAME ": Requested Scanlines %08x%08x\n",
  862. pInStrmEx->ScanlinesRequested.DwordBitArray[1],
  863. pInStrmEx->ScanlinesRequested.DwordBitArray[0] ));
  864. RtlZeroMemory( pHwDevExt->DSPResult,
  865. sizeof( DSPRESULT ) *
  866. ( pHwDevExt->DSPResultEndLine - pHwDevExt->DSPResultStartLine + 1 ));
  867. // If this substream is requested by anybody, AND there is no discontinuity set
  868. if ( ( ( ( pInVBIFrameInfo->dwFrameFlags & KS_CC_SUBSTREAM_ODD ) &&
  869. ( pInStrmEx->SubstreamsRequested.SubstreamMask & (KS_CC_SUBSTREAM_ODD|KS_CC_SUBSTREAM_FIELD1_MASK) ) ||
  870. ( ( pInVBIFrameInfo->dwFrameFlags & KS_CC_SUBSTREAM_EVEN ) &&
  871. ( pInStrmEx->SubstreamsRequested.SubstreamMask & (KS_CC_SUBSTREAM_EVEN|KS_CC_SUBSTREAM_FIELD2_MASK) ) ) ) &&
  872. !pInStrmEx->fDiscontinuity ))
  873. {
  874. // Flag this as discovered
  875. // pInStrmEx->SubstreamsDiscovered.SubstreamMask |= ( pInVBIFrameInfo->dwFrameFlags &
  876. // pInStrmEx->SubstreamsRequested.SubstreamMask );
  877. // pHwDevExt->SubstreamsDiscovered.SubstreamMask |= pInStrmEx->SubstreamsDiscovered.SubstreamMask;
  878. // loop for each requested scanline
  879. CDebugPrint( DebugLevelVerbose, ( "" "\n" ));
  880. for( ScanlineCount = pVBIInfoHeader->StartLine; ScanlineCount <= pVBIInfoHeader->EndLine;
  881. ScanlineCount++ )
  882. {
  883. if( !TESTBIT( pInStrmEx->ScanlinesRequested.DwordBitArray, ScanlineCount ))
  884. continue;
  885. CDebugPrint( DebugLevelTrace, ( CODECNAME ": Scanning %u\n", ScanlineCount ));
  886. CASSERT( ( ScanlineCount - pVBIInfoHeader->StartLine) * pVBIInfoHeader->StrideInBytes < pVBIInfoHeader->BufferSize );
  887. DSPStatistics.nSize = sizeof( DSPStatistics );
  888. DSPStatus = CCDecodeLine(
  889. pHwDevExt->DSPResult[ScanlineCount - pHwDevExt->DSPResultStartLine].Decoded,
  890. &DSPStatistics,
  891. &pInData[( ScanlineCount - pVBIInfoHeader->StartLine ) * pVBIInfoHeader->StrideInBytes],
  892. &pInStrmEx->State,
  893. pVBIInfoHeader
  894. );
  895. CASSERT( DSPStatus == CC_OK );
  896. if( DSPStatus == CC_OK )
  897. {
  898. pHwDevExt->DSPResult[ScanlineCount - pHwDevExt->DSPResultStartLine].Confidence = DSPStatistics.nConfidence;
  899. Stats->Common.LineConfidenceAvg = ( Stats->Common.LineConfidenceAvg +
  900. DSPStatistics.nConfidence ) / 2;
  901. }
  902. else
  903. Stats->Common.InternalErrors++;
  904. }
  905. }
  906. else
  907. Stats->Common.SRBsIgnored++;
  908. //
  909. // Copy the input stream header info for later reference
  910. //
  911. InStreamHeaderCopy = *pInStreamHeader;
  912. dwFrameFlags = pInVBIFrameInfo->dwFrameFlags;
  913. #ifdef PERFTEST
  914. PerfPreUpstreamCompletion = KeQueryPerformanceCounter( NULL ).QuadPart;
  915. #endif // PERFTEST
  916. //
  917. // Complete the upstream SRB.
  918. //
  919. StreamClassStreamNotification( StreamRequestComplete, pInSrb->StreamObject,
  920. pInSrb );
  921. #ifdef PERFTEST
  922. PerfPostUpstreamCompletion = KeQueryPerformanceCounter( NULL ).QuadPart;
  923. #endif // PERFTEST
  924. //
  925. // Lose all references to the just completed SRB
  926. //
  927. pInSrb = 0;
  928. pInStreamHeader = 0;
  929. pInVBIFrameInfo = 0;
  930. pInData = 0;
  931. #ifdef PERFTEST
  932. PerfFrequency.QuadPart /= 1000000L; // Convert to ticks/us
  933. PerfPreUpstreamCompletion -= PerfStartTime;
  934. PerfPreUpstreamCompletion /= PerfFrequency.QuadPart;
  935. PerfPostUpstreamCompletion -= PerfStartTime;
  936. PerfPostUpstreamCompletion /= PerfFrequency.QuadPart;
  937. //
  938. // Complain if anything takes more than threshold
  939. //
  940. if( PerfPreUpstreamCompletion > PerfThreshold )
  941. CDebugPrint( DebugLevelFatal, ( CODECNAME ": PerfPreUpstreamCompletion %luus\n",
  942. PerfPreUpstreamCompletion ));
  943. if( PerfPostUpstreamCompletion > PerfThreshold )
  944. CDebugPrint( DebugLevelFatal, ( CODECNAME ": PerfPostUpstreamCompletion %luus\n",
  945. PerfPostUpstreamCompletion ));
  946. _CDebugLevel = OldLevel;
  947. #endif // PERFTEST
  948. //
  949. // Now output to anyone interested
  950. //
  951. OutputCC(pHwDevExt, pInStrmEx, dwFrameFlags, &InStreamHeaderCopy);
  952. CDebugPrint( DebugLevelTrace, ( CODECNAME ": <---VBIDecode\n" ));
  953. }
  954. /*
  955. ** VBIhwDecode
  956. **
  957. ** Handles an incoming CCINPUT SRB. SRB is already removed from queue.
  958. **
  959. ** Arguments:
  960. **
  961. ** PHW_DEVICE_EXTENSION pHwDevExt
  962. ** PSTREAMEX pInStrmEx
  963. ** IN PHW_STREAM_REQUEST_BLOCK pInSrb
  964. **
  965. ** Returns:
  966. **
  967. ** Side Effects: none
  968. */
  969. #ifdef CCINPUTPIN
  970. #ifdef DEBUG
  971. short CCskipHwDecode = 0;
  972. #endif /*DEBUG*/
  973. #ifdef NEWCCINPUTFORMAT
  974. void VBIhwDecode(
  975. PHW_DEVICE_EXTENSION pHwDevExt,
  976. PSTREAMEX pInStrmEx,
  977. PHW_STREAM_REQUEST_BLOCK pInSrb )
  978. {
  979. PKSSTREAM_HEADER pInStreamHeader = pInSrb->CommandData.DataBufferArray;
  980. KSSTREAM_HEADER InStreamHeaderCopy;
  981. PCC_HW_FIELD pCCin = (PCC_HW_FIELD)pInStreamHeader->Data;
  982. ULONG CurrentStrmEx = 0;
  983. PVBICODECFILTERING_STATISTICS_CC Stats = 0;
  984. int line, start, end;
  985. int hidx;
  986. int didx;
  987. DWORD fields;
  988. CASSERT(KeGetCurrentIrql() <= APC_LEVEL);
  989. CASSERT(pHwDevExt);
  990. CASSERT(pInStrmEx);
  991. Stats = &pHwDevExt->Statistics;
  992. CDebugPrint( DebugLevelInfo, ( "*" ));
  993. CDebugPrint( DebugLevelTrace, ( CODECNAME ": --->VBIhwDecode\n" ));
  994. Stats->Common.InputSRBsProcessed++;
  995. //
  996. // If DataUsed == 0 then don't bother
  997. //
  998. if( pInStreamHeader->DataUsed < sizeof (CC_HW_FIELD)
  999. #ifdef DEBUG
  1000. || CCskipHwDecode
  1001. #endif /*DEBUG*/
  1002. )
  1003. {
  1004. #ifdef DEBUG
  1005. if (!CCskipHwDecode)
  1006. #endif /*DEBUG*/
  1007. {
  1008. Stats->Common.SRBsIgnored++;
  1009. CDebugPrint( DebugLevelError,
  1010. ( CODECNAME ": DataUsed is too small, abandoning\n" ));
  1011. }
  1012. StreamClassStreamNotification(
  1013. StreamRequestComplete, pInSrb->StreamObject, pInSrb );
  1014. return;
  1015. }
  1016. pInStrmEx->LastPictureNumber = pCCin->PictureNumber;
  1017. //
  1018. // Update stats
  1019. //
  1020. if( ( pInStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY ) ||
  1021. ( pInStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY ) )
  1022. Stats->Common.InputDiscontinuities++;
  1023. //
  1024. // pHwDevExt->fTunerChange is set while the TV tuner is changing channels.
  1025. // SRBs are junk until the channel change completes so complete.
  1026. //
  1027. if( pHwDevExt->fTunerChange )
  1028. {
  1029. CDebugPrint( DebugLevelVerbose,
  1030. ( CODECNAME ": Completing, channel change in progress\n" ));
  1031. StreamClassStreamNotification(
  1032. StreamRequestComplete, pInSrb->StreamObject, pInSrb );
  1033. return;
  1034. }
  1035. #ifdef CCINPUTPIN
  1036. // Check to see if this field has been decoded already (are we too late?)
  1037. ExAcquireFastMutex(&pHwDevExt->LastPictureMutex);
  1038. if (pInStrmEx->LastPictureNumber <= pHwDevExt->LastPictureNumber) {
  1039. ExReleaseFastMutex(&pHwDevExt->LastPictureMutex);
  1040. StreamClassStreamNotification(
  1041. StreamRequestComplete, pInSrb->StreamObject, pInSrb );
  1042. return;
  1043. }
  1044. // Nope, we're not too late. Stow the data.
  1045. pHwDevExt->LastPictureNumber = pInStrmEx->LastPictureNumber;
  1046. ExReleaseFastMutex(&pHwDevExt->LastPictureMutex);
  1047. #endif // CCINPUTPIN
  1048. // figure out where hardware decoding starts and ends
  1049. for( start = 1; start < 1024; ++start ) {
  1050. if( TESTBIT( pCCin->ScanlinesRequested.DwordBitArray, start ))
  1051. break;
  1052. }
  1053. for( end = 1023; end > start; --end ) {
  1054. if( TESTBIT( pCCin->ScanlinesRequested.DwordBitArray, end ))
  1055. break;
  1056. }
  1057. if (1024 == start) {
  1058. StreamClassStreamNotification( StreamRequestComplete,
  1059. pInSrb->StreamObject,
  1060. pInSrb );
  1061. return;
  1062. }
  1063. CASSERT(start <= end);
  1064. // Resize Result array if needed
  1065. CheckResultsArray(pHwDevExt, start, end);
  1066. // loop for each scanline
  1067. CDebugPrint( DebugLevelVerbose, ( "" "\n" ));
  1068. hidx = 0;
  1069. for( line = start; line <= end && hidx < CC_MAX_HW_DECODE_LINES; ++line )
  1070. {
  1071. if( !TESTBIT( pCCin->ScanlinesRequested.DwordBitArray, line ))
  1072. continue;
  1073. CDebugPrint( DebugLevelTrace,
  1074. ( CODECNAME ": Scanning %u\n", line ));
  1075. didx = line - pHwDevExt->DSPResultStartLine;
  1076. pHwDevExt->DSPResult[didx].Decoded[0] = pCCin->Lines[hidx].Decoded[0];
  1077. pHwDevExt->DSPResult[didx].Decoded[1] = pCCin->Lines[hidx].Decoded[1];
  1078. ++hidx;
  1079. pHwDevExt->DSPResult[didx].Confidence = 99; // HW decoded
  1080. Stats->Common.LineConfidenceAvg =
  1081. (Stats->Common.LineConfidenceAvg + 99) / 2;
  1082. }
  1083. //
  1084. // Copy the input stream header & other info for later reference
  1085. //
  1086. InStreamHeaderCopy = *pInStreamHeader;
  1087. fields = pCCin->fieldFlags & (KS_VBI_FLAG_FIELD1|KS_VBI_FLAG_FIELD2);
  1088. //
  1089. // Complete the upstream SRB.
  1090. //
  1091. StreamClassStreamNotification( StreamRequestComplete,
  1092. pInSrb->StreamObject,
  1093. pInSrb );
  1094. //
  1095. // Lose all references to the just completed SRB
  1096. //
  1097. pInSrb = 0;
  1098. pInStreamHeader = 0;
  1099. pCCin = 0;
  1100. OutputCC(pHwDevExt, pInStrmEx, fields, &InStreamHeaderCopy);
  1101. CDebugPrint( DebugLevelTrace, ( CODECNAME ": <---VBIhwDecode\n" ));
  1102. }
  1103. #else //NEWCCINPUTFORMAT
  1104. void VBIhwDecode(
  1105. PHW_DEVICE_EXTENSION pHwDevExt,
  1106. PSTREAMEX pInStrmEx,
  1107. PHW_STREAM_REQUEST_BLOCK pInSrb )
  1108. {
  1109. PKSSTREAM_HEADER pInStreamHeader = pInSrb->CommandData.DataBufferArray;
  1110. KSSTREAM_HEADER InStreamHeaderCopy;
  1111. PUCHAR pInData = (PUCHAR)pInStreamHeader->Data;
  1112. ULONG CurrentStrmEx = 0;
  1113. PVBICODECFILTERING_STATISTICS_CC Stats = 0;
  1114. CASSERT((ULONG)pHwDevExt);
  1115. CASSERT((ULONG)pInStrmEx);
  1116. Stats = &pHwDevExt->Statistics;
  1117. CDebugPrint( DebugLevelInfo, ( "*" ));
  1118. CDebugPrint( DebugLevelTrace, ( CODECNAME ": --->VBIhwDecode\n" ));
  1119. Stats->Common.InputSRBsProcessed++;
  1120. //
  1121. // If DataUsed == 0 then don't bother
  1122. //
  1123. if( pInStreamHeader->DataUsed < 2
  1124. #ifdef DEBUG
  1125. || CCskipHwDecode
  1126. #endif /*DEBUG*/
  1127. )
  1128. {
  1129. #ifdef DEBUG
  1130. if (!CCskipDecode)
  1131. #endif /*DEBUG*/
  1132. Stats->Common.SRBsIgnored++;
  1133. CDebugPrint( DebugLevelError, ( CODECNAME ": DataUsed is too small, abandoning\n" ));
  1134. StreamClassStreamNotification(
  1135. StreamRequestComplete, pInSrb->StreamObject, pInSrb );
  1136. return;
  1137. }
  1138. //
  1139. // Update stats
  1140. //
  1141. if( ( pInStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY ) ||
  1142. ( pInStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY ) )
  1143. Stats->Common.InputDiscontinuities++;
  1144. //
  1145. // pHwDevExt->fTunerChange is set while the TV tuner is changing channels.
  1146. // SRBs are junk until the channel change completes so complete.
  1147. //
  1148. if( pHwDevExt->fTunerChange )
  1149. {
  1150. CDebugPrint( DebugLevelVerbose,
  1151. ( CODECNAME ": Completing, channel change in progress\n" ));
  1152. StreamClassStreamNotification(
  1153. StreamRequestComplete, pInSrb->StreamObject, pInSrb );
  1154. return;
  1155. }
  1156. // loop for each requested scanline
  1157. CDebugPrint( DebugLevelVerbose, ( "" "\n" ));
  1158. pHwDevExt->DSPResult[21-10].Decoded[0] = pInData[0];
  1159. pHwDevExt->DSPResult[21-10].Decoded[1] = pInData[1];
  1160. pHwDevExt->DSPResult[21-10].Confidence = 95;
  1161. Stats->Common.LineConfidenceAvg =
  1162. ( Stats->Common.LineConfidenceAvg +
  1163. pHwDevExt->DSPResult[21-10].Confidence ) / 2;
  1164. //
  1165. // Copy the input stream header for later reference
  1166. //
  1167. InStreamHeaderCopy = *pInStreamHeader;
  1168. //
  1169. // Complete the upstream SRB.
  1170. //
  1171. StreamClassStreamNotification( StreamRequestComplete,
  1172. pInSrb->StreamObject,
  1173. pInSrb );
  1174. //
  1175. // Lose all references to the just completed SRB
  1176. //
  1177. pInSrb = 0;
  1178. pInStreamHeader = 0;
  1179. pInData = 0;
  1180. //
  1181. // Now output to anyone interested
  1182. //
  1183. OutputCC(pHwDevExt, pInStrmEx, KS_VBI_FLAG_FIELD1, &InStreamHeaderCopy);
  1184. CDebugPrint( DebugLevelTrace, ( CODECNAME ": <---VBIhwDecode\n" ));
  1185. }
  1186. #endif //NEWCCINPUTFORMAT
  1187. #endif //CCINPUTPIN
  1188. /*
  1189. ** VBIReceiveDataPacket()
  1190. **
  1191. ** Receives Video data packet commands
  1192. **
  1193. ** Arguments:
  1194. **
  1195. ** pSrb - Stream request block for the Video stream
  1196. **
  1197. ** Returns: nothing
  1198. **
  1199. ** Side Effects: none
  1200. */
  1201. VOID
  1202. STREAMAPI
  1203. VBIReceiveDataPacket(
  1204. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1205. )
  1206. {
  1207. PHW_DEVICE_EXTENSION pHwDevExt = (PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension;
  1208. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1209. int ThisStreamNr = (int)pSrb->StreamObject->StreamNumber;
  1210. #ifdef DEBUG
  1211. static int QdepthReportFreq = 0;
  1212. static unsigned int QDRCount = 0;
  1213. #endif // DEBUG
  1214. //
  1215. // make sure we have a device extension
  1216. //
  1217. CASSERT(pHwDevExt);
  1218. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VBIReceiveDataPacket(pSrb=%x)\n", pSrb));
  1219. //
  1220. // Default to success
  1221. //
  1222. pSrb->Status = STATUS_SUCCESS;
  1223. //
  1224. // Disable timeout
  1225. //
  1226. pSrb->TimeoutCounter = 0;
  1227. //
  1228. // determine the type of packet.
  1229. //
  1230. // Rule:
  1231. // Only accept read requests when in either the Pause or Run
  1232. // States. If Stopped, immediately return the SRB.
  1233. if (pStrmEx->KSState == KSSTATE_STOP) {
  1234. StreamClassStreamNotification( StreamRequestComplete,
  1235. pSrb->StreamObject, pSrb );
  1236. return;
  1237. }
  1238. switch (pSrb->Command)
  1239. {
  1240. #ifdef DRIVER_DEBUGGING_TEST
  1241. case SRB_READ_DATA:
  1242. case SRB_WRITE_DATA:
  1243. // When initially bringing up a driver, it is useful to just
  1244. // try immediately completing the SRB, thus verifying
  1245. // the streaming process independent of really accessing
  1246. // your hardware.
  1247. StreamClassStreamNotification( StreamRequestComplete,
  1248. pSrb->StreamObject, pSrb );
  1249. break;
  1250. #else // DRIVER_DEBUGGING_TEST
  1251. case SRB_READ_DATA:
  1252. if( ThisStreamNr != STREAM_CC )
  1253. {
  1254. CDebugPrint( DebugLevelError, ( CODECNAME ": Read Stream # Bad\n" ));
  1255. CDEBUG_BREAK();
  1256. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1257. }
  1258. else
  1259. {
  1260. CDebugPrint( DebugLevelTrace, ( CODECNAME ": Stream %u Instance %u\n", ThisStreamNr,
  1261. pStrmEx->StreamInstance ));
  1262. if( pStrmEx->StreamInstance != 0 )
  1263. CDebugPrint( DebugLevelTrace, ( CODECNAME ": Stream %u Instance %u\n", ThisStreamNr,
  1264. pStrmEx->StreamInstance ));
  1265. QueueAdd( pSrb, &pStrmEx->StreamDataSpinLock, &pStrmEx->StreamDataQueue );
  1266. // Since another thread COULD HAVE MODIFIED THE STREAM STATE
  1267. // in the midst of adding it to the queue, check the stream
  1268. // state again, and cancel the SRB if necessary.
  1269. // Note that this race condition was NOT handled in the
  1270. // original DDK release of testcap!
  1271. if (pStrmEx->KSState == KSSTATE_STOP)
  1272. CodecCancelPacket(pSrb);
  1273. }
  1274. break;
  1275. case SRB_WRITE_DATA:
  1276. if( STREAM_VBI == ThisStreamNr)
  1277. {
  1278. #ifdef DEBUG
  1279. static int MaxVBIqDepth = 0;
  1280. static int AvgVBIqDepth = 1000; // 1.000
  1281. int qDepth = 0;
  1282. #endif // DEBUG
  1283. CDebugPrint( DebugLevelTrace, ( CODECNAME ": Stream VBI Writing\n"));
  1284. if( QueueAddIfNotEmpty( pSrb, &pStrmEx->StreamDataSpinLock,
  1285. &pStrmEx->StreamDataQueue ))
  1286. break;
  1287. do
  1288. {
  1289. #ifdef CCINPUTPIN
  1290. KIRQL Irql;
  1291. #endif // CCINPUTPIN
  1292. #ifdef DEBUG
  1293. ++qDepth;
  1294. ++QDRCount;
  1295. #endif // DEBUG
  1296. #ifdef CCINPUTPIN
  1297. KeAcquireSpinLock(&pStrmEx->VBIOnHoldSpinLock, &Irql);
  1298. if (NULL != pStrmEx->pVBISrbOnHold)
  1299. {
  1300. PHW_STREAM_REQUEST_BLOCK pTempSrb;
  1301. pTempSrb = pStrmEx->pVBISrbOnHold;
  1302. pStrmEx->pVBISrbOnHold = NULL;
  1303. KeReleaseSpinLock(&pStrmEx->VBIOnHoldSpinLock, Irql);
  1304. VBIDecode( pHwDevExt, pStrmEx, pTempSrb, 0 );
  1305. }
  1306. else
  1307. KeReleaseSpinLock(&pStrmEx->VBIOnHoldSpinLock, Irql);
  1308. #endif // CCINPUTPIN
  1309. VBIDecode( pHwDevExt, pStrmEx, pSrb, 1 );
  1310. }while( QueueRemove( &pSrb, &pStrmEx->StreamDataSpinLock,
  1311. &pStrmEx->StreamDataQueue ));
  1312. #ifdef DEBUG
  1313. if (qDepth > MaxVBIqDepth)
  1314. MaxVBIqDepth = qDepth;
  1315. AvgVBIqDepth = (AvgVBIqDepth * 7 / 8) + (qDepth * 1000 / 8);
  1316. if (QdepthReportFreq > 0 && 0 == QDRCount % QdepthReportFreq) {
  1317. CDebugPrint( 0,
  1318. (CODECNAME ": Max VBI Q depth = %3d, Avg VBI Q depth = %3d.%03d\n",
  1319. MaxVBIqDepth,
  1320. AvgVBIqDepth / 1000,
  1321. AvgVBIqDepth % 1000));
  1322. }
  1323. #endif // DEBUG
  1324. }
  1325. #ifdef CCINPUTPIN
  1326. else if (STREAM_CCINPUT == ThisStreamNr)
  1327. {
  1328. #ifdef DEBUG
  1329. static int MaxCCINqDepth = 0;
  1330. static int AvgCCINqDepth = 1000; // 1.000
  1331. int qDepth = 0;
  1332. #endif // DEBUG
  1333. CDebugPrint( DebugLevelTrace, (CODECNAME ": Stream CCINPUT Writing\n"));
  1334. if( QueueAddIfNotEmpty( pSrb, &pStrmEx->StreamDataSpinLock,
  1335. &pStrmEx->StreamDataQueue ))
  1336. break;
  1337. do
  1338. {
  1339. #ifdef DEBUG
  1340. ++qDepth;
  1341. ++QDRCount;
  1342. #endif // DEBUG
  1343. VBIhwDecode( pHwDevExt, pStrmEx, pSrb );
  1344. }while( QueueRemove( &pSrb, &pStrmEx->StreamDataSpinLock,
  1345. &pStrmEx->StreamDataQueue ));
  1346. #ifdef DEBUG
  1347. if (qDepth > MaxCCINqDepth)
  1348. MaxCCINqDepth = qDepth;
  1349. AvgCCINqDepth = (AvgCCINqDepth * 7 / 8) + (qDepth * 1000 / 8);
  1350. if (QdepthReportFreq > 0 && 0 == QDRCount % QdepthReportFreq) {
  1351. CDebugPrint( 0,
  1352. (CODECNAME ": Max CCIN Q depth = %3d, Avg CCIN Q depth = %3d.%03d\n",
  1353. MaxCCINqDepth,
  1354. AvgCCINqDepth / 1000,
  1355. AvgCCINqDepth % 1000));
  1356. }
  1357. #endif // DEBUG
  1358. }
  1359. #endif // CCINPUTPIN
  1360. else
  1361. {
  1362. CDebugPrint( DebugLevelError, ( CODECNAME, ": Write Stream # Bad (%u)\n", ThisStreamNr ));
  1363. CDEBUG_BREAK();
  1364. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1365. }
  1366. break;
  1367. #endif // DRIVER_DEBUGGING_TEST
  1368. break;
  1369. default:
  1370. //
  1371. // invalid / unsupported command. Fail it as such
  1372. //
  1373. CDEBUG_BREAK();
  1374. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1375. StreamClassStreamNotification( StreamRequestComplete,
  1376. pSrb->StreamObject, pSrb );
  1377. } // switch (pSrb->Command)
  1378. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VBIReceiveDataPacket(pSrb=%x)\n", pSrb));
  1379. }
  1380. /*
  1381. ** VBIReceiveCtrlPacket()
  1382. **
  1383. ** Receives packet commands that control the Video stream
  1384. **
  1385. ** Arguments:
  1386. **
  1387. ** pSrb - The stream request block for the Video stream
  1388. **
  1389. ** Returns: nothing
  1390. **
  1391. ** Side Effects: none
  1392. */
  1393. VOID
  1394. STREAMAPI
  1395. VBIReceiveCtrlPacket(
  1396. IN PHW_STREAM_REQUEST_BLOCK pSrb
  1397. )
  1398. {
  1399. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  1400. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1401. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VBIReceiveCtrlPacket(pSrb=%x)\n", pSrb));
  1402. CASSERT(pHwDevExt);
  1403. //
  1404. // Default to success
  1405. //
  1406. pSrb->Status = STATUS_SUCCESS;
  1407. if( QueueAddIfNotEmpty( pSrb,
  1408. &pStrmEx->StreamControlSpinLock,
  1409. &pStrmEx->StreamControlQueue
  1410. ))
  1411. return;
  1412. do
  1413. {
  1414. //
  1415. // determine the type of packet.
  1416. //
  1417. switch (pSrb->Command)
  1418. {
  1419. case SRB_PROPOSE_DATA_FORMAT:
  1420. if ( !CodecVerifyFormat( pSrb->CommandData.OpenFormat,
  1421. pSrb->StreamObject->StreamNumber,
  1422. NULL ) )
  1423. {
  1424. pSrb->Status = STATUS_NO_MATCH;
  1425. }
  1426. break;
  1427. case SRB_SET_STREAM_STATE:
  1428. VideoSetState(pSrb);
  1429. break;
  1430. case SRB_GET_STREAM_STATE:
  1431. VideoGetState(pSrb);
  1432. break;
  1433. case SRB_GET_STREAM_PROPERTY:
  1434. VideoGetProperty(pSrb);
  1435. break;
  1436. case SRB_SET_STREAM_PROPERTY:
  1437. VideoSetProperty(pSrb);
  1438. break;
  1439. case SRB_INDICATE_MASTER_CLOCK:
  1440. //
  1441. // Assigns a clock to a stream
  1442. //
  1443. VideoIndicateMasterClock(pSrb);
  1444. break;
  1445. default:
  1446. //
  1447. // invalid / unsupported command. Fail it as such
  1448. //
  1449. CDEBUG_BREAK();
  1450. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1451. }
  1452. StreamClassStreamNotification( StreamRequestComplete, pSrb->StreamObject,
  1453. pSrb );
  1454. }while( QueueRemove( &pSrb, &pStrmEx->StreamControlSpinLock,
  1455. &pStrmEx->StreamControlQueue ));
  1456. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VBIReceiveCtrlPacket(pSrb=%x)\n", pSrb));
  1457. }
  1458. /*
  1459. ** VideoGetProperty()
  1460. **
  1461. ** Routine to process video property requests
  1462. **
  1463. ** Arguments:
  1464. **
  1465. ** pSrb - pointer to the stream request block for properties
  1466. **
  1467. ** Returns:
  1468. **
  1469. ** Side Effects: none
  1470. */
  1471. VOID
  1472. VideoGetProperty(
  1473. PHW_STREAM_REQUEST_BLOCK pSrb
  1474. )
  1475. {
  1476. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1477. int StreamNumber = (int)pSrb->StreamObject->StreamNumber;
  1478. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VideoGetProperty(pSrb=%x)\n", pSrb));
  1479. if (IsEqualGUID (&KSPROPSETID_Connection, &pSPD->Property->Set))
  1480. {
  1481. VideoStreamGetConnectionProperty( pSrb );
  1482. }
  1483. else if (IsEqualGUID (&KSPROPSETID_VBICodecFiltering, &pSPD->Property->Set))
  1484. {
  1485. VideoStreamGetVBIFilteringProperty (pSrb);
  1486. }
  1487. else
  1488. {
  1489. CDebugPrint( DebugLevelTrace, ( CODECNAME ": Unsupported Property Set\n" ));
  1490. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1491. }
  1492. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VideoGetProperty(pSrb=%x)\n", pSrb));
  1493. }
  1494. /*
  1495. ** VideoSetProperty()
  1496. **
  1497. ** Routine to process video property requests
  1498. **
  1499. ** Arguments:
  1500. **
  1501. ** pSrb - pointer to the stream request block for properties
  1502. **
  1503. ** Returns:
  1504. **
  1505. ** Side Effects: none
  1506. */
  1507. VOID
  1508. VideoSetProperty(
  1509. PHW_STREAM_REQUEST_BLOCK pSrb
  1510. )
  1511. {
  1512. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1513. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VideoSetProperty(pSrb=%x)\n", pSrb));
  1514. if (IsEqualGUID (&KSPROPSETID_VBICodecFiltering, &pSPD->Property->Set))
  1515. {
  1516. VideoStreamSetVBIFilteringProperty (pSrb);
  1517. }
  1518. else
  1519. if( IsEqualGUID( &KSPROPSETID_Stream, &pSPD->Property->Set ))
  1520. {
  1521. pSrb->Status = STATUS_SUCCESS;
  1522. }
  1523. else
  1524. {
  1525. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1526. }
  1527. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VideoSetProperty(pSrb=%x)\n", pSrb));
  1528. }
  1529. /*
  1530. ** VideoSetState()
  1531. **
  1532. ** Sets the current state of the requested stream
  1533. **
  1534. ** Arguments:
  1535. **
  1536. ** pSrb - pointer to the stream request block for properties
  1537. **
  1538. ** Returns:
  1539. **
  1540. ** Side Effects: none
  1541. */
  1542. VOID
  1543. VideoSetState(
  1544. PHW_STREAM_REQUEST_BLOCK pSrb
  1545. )
  1546. {
  1547. PHW_DEVICE_EXTENSION pHwDevExt = ((PHW_DEVICE_EXTENSION)pSrb->HwDeviceExtension);
  1548. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1549. PHW_STREAM_REQUEST_BLOCK pCurrentSrb;
  1550. int StreamNumber = (int)pSrb->StreamObject->StreamNumber;
  1551. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VideoSetState(pSrb=%x)\n", pSrb));
  1552. //
  1553. // For each stream, the following states are used:
  1554. //
  1555. // Stop: Absolute minimum resources are used. No outstanding IRPs.
  1556. // Acquire: KS only state that has no DirectShow correpondence
  1557. // Acquire needed resources.
  1558. // Pause: Getting ready to run. Allocate needed resources so that
  1559. // the eventual transition to Run is as fast as possible.
  1560. // Read SRBs will be queued at either the Stream class
  1561. // or in your driver (depending on when you send "ReadyForNext")
  1562. // Run: Streaming.
  1563. //
  1564. // Moving to Stop to Run always transitions through Pause.
  1565. //
  1566. // But since a client app could crash unexpectedly, drivers should handle
  1567. // the situation of having outstanding IRPs cancelled and open streams
  1568. // being closed WHILE THEY ARE STREAMING!
  1569. //
  1570. // Note that it is quite possible to transition repeatedly between states:
  1571. // Stop -> Pause -> Stop -> Pause -> Run -> Pause -> Run -> Pause -> Stop
  1572. //
  1573. switch (pSrb->CommandData.StreamState)
  1574. {
  1575. case KSSTATE_STOP:
  1576. //
  1577. // If transitioning to the stopped state, then complete any outstanding IRPs
  1578. //
  1579. while( QueueRemove( &pCurrentSrb, &pStrmEx->StreamDataSpinLock,
  1580. &pStrmEx->StreamDataQueue ))
  1581. {
  1582. CDebugPrint(DebugLevelVerbose,( CODECNAME ": Cancelling %X\n",
  1583. pCurrentSrb ));
  1584. pCurrentSrb->Status = STATUS_CANCELLED;
  1585. pCurrentSrb->CommandData.DataBufferArray->DataUsed = 0;
  1586. StreamClassStreamNotification( StreamRequestComplete,
  1587. pCurrentSrb->StreamObject, pCurrentSrb );
  1588. }
  1589. CDebugPrint( DebugLevelTrace, ( CODECNAME ": KSSTATE_STOP %u\n", StreamNumber ));
  1590. break;
  1591. case KSSTATE_ACQUIRE:
  1592. //
  1593. // This is a KS only state, that has no correspondence in DirectShow
  1594. //
  1595. CDebugPrint( DebugLevelTrace, ( CODECNAME ": KSSTATE_ACQUIRE %u\n", StreamNumber ));
  1596. break;
  1597. case KSSTATE_PAUSE:
  1598. //
  1599. // On a transition to pause from acquire, start our timer running.
  1600. //
  1601. if (pStrmEx->KSState == KSSTATE_ACQUIRE || pStrmEx->KSState == KSSTATE_STOP) {
  1602. // Remember the time at which the clock was started
  1603. pHwDevExt->QST_Start = VideoGetSystemTime();
  1604. // And initialize the last frame timestamp
  1605. pHwDevExt->QST_Now = pHwDevExt->QST_Start;
  1606. // Fireup the codec HERE in preparation for receiving data & requests.
  1607. // INSERT CODE HERE
  1608. }
  1609. CDebugPrint( DebugLevelTrace, ( CODECNAME ": KSSTATE_PAUSE %u\n", StreamNumber ));
  1610. break;
  1611. case KSSTATE_RUN:
  1612. //
  1613. // Begin Streaming.
  1614. //
  1615. // Remember the time at which the clock was started
  1616. pHwDevExt->QST_Start = VideoGetSystemTime();
  1617. // Zero the frame info, it should be reset when the first sample arrives.
  1618. RtlZeroMemory (&pStrmEx->FrameInfo, sizeof (pStrmEx->FrameInfo));
  1619. // Zero the last known picture numbers
  1620. pStrmEx->LastPictureNumber = 0;
  1621. pHwDevExt->LastPictureNumber = 0;
  1622. // Reset the discontinuity flag
  1623. pStrmEx->fDiscontinuity = FALSE;
  1624. CDebugPrint( DebugLevelTrace, ( CODECNAME ": KSSTATE_RUN %u\n", StreamNumber ));
  1625. break;
  1626. default:
  1627. CDebugPrint( DebugLevelError, ( CODECNAME ": UNKNOWN STATE %u\n", StreamNumber ));
  1628. CDEBUG_BREAK();
  1629. break;
  1630. } // end switch (pSrb->CommandData.StreamState)
  1631. //
  1632. // Remember the state of this stream
  1633. //
  1634. pStrmEx->KSState = pSrb->CommandData.StreamState;
  1635. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VideoSetState(pSrb=%x)\n", pSrb));
  1636. }
  1637. /*
  1638. ** VideoGetState()
  1639. **
  1640. ** Gets the current state of the requested stream
  1641. **
  1642. ** Arguments:
  1643. **
  1644. ** pSrb - pointer to the stream request block for properties
  1645. **
  1646. ** Returns:
  1647. **
  1648. ** Side Effects: none
  1649. */
  1650. VOID
  1651. VideoGetState(
  1652. PHW_STREAM_REQUEST_BLOCK pSrb
  1653. )
  1654. {
  1655. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1656. CDebugPrint(DebugLevelTrace,(CODECNAME ":--->VideoGetState(pSrb=%x)\n", pSrb));
  1657. pSrb->CommandData.StreamState = pStrmEx->KSState;
  1658. pSrb->ActualBytesTransferred = sizeof (KSSTATE);
  1659. // A very odd rule:
  1660. // When transitioning from stop to pause, DShow tries to preroll
  1661. // the graph. Capture sources can't preroll, and indicate this
  1662. // by returning VFW_S_CANT_CUE in user mode. To indicate this
  1663. // condition from drivers, they must return ERROR_NO_DATA_DETECTED
  1664. if (pStrmEx->KSState == KSSTATE_PAUSE) {
  1665. pSrb->Status = STATUS_NO_DATA_DETECTED;
  1666. }
  1667. CDebugPrint(DebugLevelTrace,(CODECNAME ":<---VideoGetState(pSrb=%x)=%d\n", pSrb, pStrmEx->KSState));
  1668. }
  1669. /*
  1670. ** VideoStreamGetConnectionProperty()
  1671. **
  1672. ** Gets the current state of the requested stream
  1673. **
  1674. ** Arguments:
  1675. **
  1676. ** pSrb - pointer to the stream request block for properties
  1677. **
  1678. ** Returns:
  1679. **
  1680. ** Side Effects: none
  1681. */
  1682. VOID
  1683. VideoStreamGetConnectionProperty(
  1684. PHW_STREAM_REQUEST_BLOCK pSrb
  1685. )
  1686. {
  1687. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1688. PHW_DEVICE_EXTENSION pHwDevExt = pStrmEx->pHwDevExt;
  1689. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1690. ULONG Id = pSPD->Property->Id; // index of the property
  1691. int StreamNumber = ( int )pSrb->StreamObject->StreamNumber;
  1692. CDebugPrint(DebugLevelTrace,
  1693. ( CODECNAME ":--->VideoStreamGetConnectionProperty(pSrb=%x)\n",
  1694. pSrb));
  1695. pSrb->ActualBytesTransferred = 0;
  1696. switch (Id)
  1697. {
  1698. case KSPROPERTY_CONNECTION_ALLOCATORFRAMING:
  1699. {
  1700. PKSALLOCATOR_FRAMING Framing =
  1701. (PKSALLOCATOR_FRAMING) pSPD->PropertyInfo;
  1702. // PKS_DATARANGE_VIDEO_VBI pVBIFormat;
  1703. CDebugPrint(DebugLevelVerbose,
  1704. ( CODECNAME ": VideoStreamGetConnectionProperty : KSPROPERTY_CONNECTION_ALLOCATORFRAMING %u\n",
  1705. StreamNumber));
  1706. Framing->RequirementsFlags =
  1707. KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY |
  1708. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
  1709. KSALLOCATOR_REQUIREMENTF_INPLACE_MODIFIER;
  1710. Framing->PoolType = NonPagedPool;
  1711. Framing->FileAlignment = 0; // None OR FILE_QUAD_ALIGNMENT OR PAGE_SIZE - 1;
  1712. Framing->Reserved = 0;
  1713. switch( StreamNumber )
  1714. {
  1715. case STREAM_VBI:
  1716. Framing->Frames = 8;
  1717. Framing->FrameSize = pStrmEx->OpenedFormat.SampleSize;
  1718. break;
  1719. case STREAM_CC:
  1720. if( CodecCompareGUIDsAndFormatSize( &pStrmEx->OpenedFormat,
  1721. pHwDevExt->Streams[STREAM_CC].hwStreamInfo.StreamFormatsArray[0], FALSE ))
  1722. {
  1723. Framing->Frames = 60;
  1724. Framing->FrameSize = CCSamples;
  1725. }
  1726. else if( CodecCompareGUIDsAndFormatSize( &pStrmEx->OpenedFormat,
  1727. pHwDevExt->Streams[STREAM_CC].hwStreamInfo.StreamFormatsArray[1], FALSE ))
  1728. {
  1729. Framing->Frames = 8;
  1730. Framing->FrameSize = pStrmEx->OpenedFormat.SampleSize;
  1731. }
  1732. else
  1733. {
  1734. CDebugPrint( DebugLevelError, ( CODECNAME ": VideoStreamGetConnectionProperty: Invalid Format\n" ));
  1735. CDEBUG_BREAK();
  1736. }
  1737. break;
  1738. #ifdef CCINPUTPIN
  1739. case STREAM_CCINPUT:
  1740. Framing->Frames = 60;
  1741. Framing->FrameSize = CCSamples;
  1742. break;
  1743. #endif // CCINPUTPIN
  1744. default:
  1745. CDebugPrint( DebugLevelError, ( CODECNAME ": VideoStreamGetConnectionProperty: Invalid Stream #\n" ));
  1746. CDEBUG_BREAK();
  1747. }
  1748. CDebugPrint( DebugLevelVerbose, ( CODECNAME ": Negotiated sample size is %d\n",
  1749. Framing->FrameSize ));
  1750. pSrb->ActualBytesTransferred = sizeof (KSALLOCATOR_FRAMING);
  1751. break;
  1752. }
  1753. default:
  1754. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1755. CDebugPrint(DebugLevelVerbose,
  1756. ( CODECNAME ": VideoStreamGetConnectionProperty : Unknown Property Id=%d\n", Id));
  1757. CDEBUG_BREAK();
  1758. break;
  1759. }
  1760. CDebugPrint(DebugLevelTrace,
  1761. ( CODECNAME ":<---VideoStreamGetConnectionProperty(pSrb=%x)\n",
  1762. pSrb));
  1763. }
  1764. /*
  1765. ** VideoStreamGetVBIFilteringProperty()
  1766. **
  1767. ** Gets the current state of the requested stream
  1768. **
  1769. ** Arguments:
  1770. **
  1771. ** pSrb - pointer to the stream request block for properties
  1772. **
  1773. ** Returns:
  1774. **
  1775. ** Side Effects: none
  1776. */
  1777. VOID
  1778. VideoStreamGetVBIFilteringProperty(
  1779. PHW_STREAM_REQUEST_BLOCK pSrb
  1780. )
  1781. {
  1782. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1783. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1784. ULONG Id = pSPD->Property->Id; // index of the property
  1785. LONG nBytes = pSPD->PropertyOutputSize - sizeof(KSPROPERTY); // size of data supplied
  1786. CDebugPrint(DebugLevelTrace,
  1787. ( CODECNAME ":--->VideoStreamGetVBIFilteringProperty(pSrb=%x)\n",
  1788. pSrb));
  1789. ASSERT (nBytes >= sizeof (LONG));
  1790. pSrb->ActualBytesTransferred = 0;
  1791. switch (Id)
  1792. {
  1793. case KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY:
  1794. {
  1795. PKSPROPERTY_VBICODECFILTERING_SCANLINES_S Property =
  1796. (PKSPROPERTY_VBICODECFILTERING_SCANLINES_S) pSPD->PropertyInfo;
  1797. nBytes = min( nBytes, sizeof( pStrmEx->ScanlinesRequested ) );
  1798. RtlCopyMemory( &Property->Scanlines, &pStrmEx->ScanlinesRequested, nBytes );
  1799. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1800. CDebugPrint(DebugLevelVerbose,
  1801. ( CODECNAME ": VideoStreamGetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY\n"));
  1802. break;
  1803. }
  1804. case KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY:
  1805. {
  1806. PKSPROPERTY_VBICODECFILTERING_SCANLINES_S Property =
  1807. (PKSPROPERTY_VBICODECFILTERING_SCANLINES_S) pSPD->PropertyInfo;
  1808. CDebugPrint(DebugLevelVerbose,
  1809. ( CODECNAME ": VideoStreamGetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY\n"));
  1810. nBytes = min( nBytes, sizeof( pStrmEx->ScanlinesDiscovered ) );
  1811. RtlCopyMemory( &Property->Scanlines, &pStrmEx->ScanlinesDiscovered, nBytes );
  1812. // Clear the data after the read so that it's always "fresh"
  1813. RtlZeroMemory( &pStrmEx->ScanlinesDiscovered, nBytes );
  1814. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1815. break;
  1816. }
  1817. case KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY:
  1818. {
  1819. PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S Property =
  1820. (PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S) pSPD->PropertyInfo;
  1821. nBytes = min( nBytes, sizeof( pStrmEx->SubstreamsRequested ) );
  1822. RtlCopyMemory( &Property->Substreams, &pStrmEx->SubstreamsRequested, nBytes );
  1823. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1824. CDebugPrint(DebugLevelInfo,
  1825. ( CODECNAME ": VideoStreamGetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY %08x\n",
  1826. Property->Substreams ));
  1827. break;
  1828. }
  1829. case KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY:
  1830. {
  1831. PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S Property =
  1832. (PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S) pSPD->PropertyInfo;
  1833. CDebugPrint(DebugLevelVerbose,
  1834. ( CODECNAME ": VideoStreamGetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY\n"));
  1835. nBytes = min( nBytes, sizeof( pStrmEx->SubstreamsDiscovered ) );
  1836. RtlCopyMemory( &Property->Substreams, &pStrmEx->SubstreamsDiscovered, nBytes );
  1837. // Clear the data after the read so that it's always "fresh"
  1838. RtlZeroMemory( &pStrmEx->SubstreamsDiscovered, nBytes );
  1839. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1840. break;
  1841. }
  1842. case KSPROPERTY_VBICODECFILTERING_STATISTICS:
  1843. {
  1844. PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S Property =
  1845. (PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S) pSPD->PropertyInfo;
  1846. CDebugPrint(DebugLevelVerbose,
  1847. ( CODECNAME ": VideoStreamGetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S\n"));
  1848. nBytes = min( nBytes, sizeof( pStrmEx->PinStats ) );
  1849. RtlCopyMemory( &Property->Statistics, &pStrmEx->PinStats, nBytes );
  1850. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1851. break;
  1852. }
  1853. default:
  1854. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1855. CDebugPrint(DebugLevelVerbose,
  1856. ( CODECNAME ": VideoStreamGetVBIFilteringProperty : Unknown Property Id=%d\n", Id));
  1857. CDEBUG_BREAK();
  1858. break;
  1859. }
  1860. CDebugPrint(DebugLevelTrace,
  1861. ( CODECNAME ":<---VideoStreamGetVBIFilteringProperty(pSrb=%x)\n",
  1862. pSrb));
  1863. }
  1864. /*
  1865. ** VideoStreamSetVBIFilteringProperty()
  1866. **
  1867. ** Sets the current state of the requested stream
  1868. **
  1869. ** Arguments:
  1870. **
  1871. ** pSrb - pointer to the stream request block for properties
  1872. **
  1873. ** Returns:
  1874. **
  1875. ** Side Effects: none
  1876. */
  1877. VOID
  1878. VideoStreamSetVBIFilteringProperty(
  1879. PHW_STREAM_REQUEST_BLOCK pSrb
  1880. )
  1881. {
  1882. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  1883. PSTREAM_PROPERTY_DESCRIPTOR pSPD = pSrb->CommandData.PropertyInfo;
  1884. ULONG Id = pSPD->Property->Id; // index of the property
  1885. ULONG nBytes = pSPD->PropertyOutputSize - sizeof(KSPROPERTY); // size of data supplied
  1886. ASSERT (nBytes >= sizeof (LONG));
  1887. CDebugPrint(DebugLevelTrace,
  1888. ( CODECNAME ":--->VideoStreamSetVBIFilteringProperty(pSrb=%x)\n",
  1889. pSrb));
  1890. pSrb->ActualBytesTransferred = 0;
  1891. switch (Id)
  1892. {
  1893. case KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY:
  1894. {
  1895. PKSPROPERTY_VBICODECFILTERING_SCANLINES_S Property =
  1896. (PKSPROPERTY_VBICODECFILTERING_SCANLINES_S) pSPD->PropertyInfo;
  1897. CDebugPrint(DebugLevelVerbose,
  1898. ( CODECNAME ": VideoStreamSetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SCANLINES_REQUESTED_BIT_ARRAY\n"));
  1899. nBytes = min( nBytes, sizeof( pStrmEx->ScanlinesRequested ) );
  1900. RtlCopyMemory( &pStrmEx->ScanlinesRequested, &Property->Scanlines, nBytes );
  1901. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1902. break;
  1903. }
  1904. #ifdef SETDISCOVERED
  1905. case KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY:
  1906. {
  1907. PKSPROPERTY_VBICODECFILTERING_SCANLINES_S Property =
  1908. (PKSPROPERTY_VBICODECFILTERING_SCANLINES_S) pSPD->PropertyInfo;
  1909. CDebugPrint(DebugLevelVerbose,
  1910. ( CODECNAME ": VideoStreamSetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SCANLINES_DISCOVERED_BIT_ARRAY\n"));
  1911. nBytes = min( nBytes, sizeof(pStrmEx->ScanlinesDiscovered ) );
  1912. RtlCopyMemory( &pStrmEx->ScanlinesDiscovered, &Property->Scanlines, nBytes );
  1913. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1914. break;
  1915. }
  1916. #endif // SETDISCOVERED
  1917. case KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY:
  1918. {
  1919. PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S Property =
  1920. (PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S) pSPD->PropertyInfo;
  1921. nBytes = min( nBytes, sizeof(pStrmEx->SubstreamsRequested ) );
  1922. RtlCopyMemory( &pStrmEx->SubstreamsRequested, &Property->Substreams, nBytes );
  1923. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1924. CDebugPrint(DebugLevelInfo,
  1925. ( CODECNAME ": VideoStreamSetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_REQUESTED_BIT_ARRAY %08x\n",
  1926. pStrmEx->SubstreamsRequested.SubstreamMask));
  1927. break;
  1928. }
  1929. #ifdef SETDISCOVERED
  1930. case KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY:
  1931. {
  1932. PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S Property =
  1933. (PKSPROPERTY_VBICODECFILTERING_CC_SUBSTREAMS_S) pSPD->PropertyInfo;
  1934. CDebugPrint(DebugLevelVerbose,
  1935. ( CODECNAME ": VideoStreamSetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_SUBSTREAMS_DISCOVERED_BIT_ARRAY\n"));
  1936. nBytes = min( nBytes, sizeof(pStrmEx->SubstreamsDiscovered ) );
  1937. RtlCopyMemory( &pStrmEx->SubstreamsDiscovered, &Property->Substreams, nBytes );
  1938. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1939. break;
  1940. }
  1941. #endif // SETDISCOVERED
  1942. case KSPROPERTY_VBICODECFILTERING_STATISTICS:
  1943. {
  1944. PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S Property =
  1945. (PKSPROPERTY_VBICODECFILTERING_STATISTICS_CC_PIN_S) pSPD->PropertyInfo;
  1946. CDebugPrint(DebugLevelVerbose,
  1947. ( CODECNAME ": VideoStreamSetVBIFilteringProperty : KSPROPERTY_VBICODECFILTERING_STATISTICS\n"));
  1948. nBytes = min( nBytes, sizeof( pStrmEx->PinStats ) );
  1949. RtlCopyMemory( &pStrmEx->PinStats, &Property->Statistics, nBytes );
  1950. pSrb->ActualBytesTransferred = nBytes + sizeof(KSPROPERTY);
  1951. break;
  1952. }
  1953. default:
  1954. pSrb->Status = STATUS_NOT_IMPLEMENTED;
  1955. CDebugPrint(DebugLevelVerbose,
  1956. ( CODECNAME ": VideoStreamSetVBIFilteringProperty : Unknown Property Id=%d\n", Id));
  1957. CDEBUG_BREAK();
  1958. break;
  1959. }
  1960. CDebugPrint(DebugLevelTrace,
  1961. ( CODECNAME ":<---VideoStreamSetVBIFilteringProperty(pSrb=%x)\n",
  1962. pSrb));
  1963. }
  1964. /*
  1965. ** GetSystemTime ()
  1966. **
  1967. ** Returns the system time in 100 nS units
  1968. **
  1969. ** Arguments:
  1970. **
  1971. ** Returns:
  1972. **
  1973. ** Side Effects: none
  1974. */
  1975. ULONGLONG
  1976. VideoGetSystemTime()
  1977. {
  1978. ULONGLONG ticks;
  1979. ULONGLONG rate;
  1980. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VideoGetSystemTime()\n"));
  1981. ticks = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
  1982. //
  1983. // convert from ticks to 100ns clock
  1984. //
  1985. ticks = (ticks & 0xFFFFFFFF00000000) / rate * 10000000 +
  1986. (ticks & 0x00000000FFFFFFFF) * 10000000 / rate;
  1987. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VideoGetSystemTime()\n"));
  1988. return(ticks);
  1989. }
  1990. //==========================================================================;
  1991. // Clock Handling Routines
  1992. //==========================================================================;
  1993. /*
  1994. ** VideoIndicateMasterClock ()
  1995. **
  1996. ** This function is used to provide us with a handle to the clock to use.
  1997. **
  1998. ** Arguments:
  1999. **
  2000. ** pSrb - pointer to the stream request block for properties
  2001. **
  2002. ** Returns:
  2003. **
  2004. ** Side Effects: none
  2005. */
  2006. VOID
  2007. VideoIndicateMasterClock(
  2008. PHW_STREAM_REQUEST_BLOCK pSrb
  2009. )
  2010. {
  2011. PSTREAMEX pStrmEx = (PSTREAMEX)pSrb->StreamObject->HwStreamExtension;
  2012. CDebugPrint(DebugLevelTrace,( CODECNAME ":--->VideoIndicateMasterClock(pSrb=%x)\n", pSrb));
  2013. pStrmEx->hClock = pSrb->CommandData.MasterClockHandle;
  2014. CDebugPrint(DebugLevelTrace,( CODECNAME ":<---VideoIndicateMasterClock(pSrb=%x)\n", pSrb));
  2015. }