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.

634 lines
21 KiB

  1. /****************************************************************************
  2. * @doc INTERNAL WDMPIN
  3. *
  4. * @module WDMPin.cpp | Include file for <c CWDMPin> class used to access
  5. * video data on a video streaming pin exposed by the WDM class driver.
  6. *
  7. * @comm This code is based on the VfW to WDM mapper code written by
  8. * FelixA and E-zu Wu. The original code can be found on
  9. * \\redrum\slmro\proj\wdm10\\src\image\vfw\win9x\raytube.
  10. *
  11. * Documentation by George Shaw on kernel streaming can be found in
  12. * \\popcorn\razzle1\src\spec\ks\ks.doc.
  13. *
  14. * WDM streaming capture is discussed by Jay Borseth in
  15. * \\blues\public\jaybo\WDMVCap.doc.
  16. ***************************************************************************/
  17. #include "Precomp.h"
  18. /****************************************************************************
  19. * @doc INTERNAL CWDMPINMETHOD
  20. *
  21. * @mfunc void | CWDMPin | CWDMPin | Video pin class constructor.
  22. *
  23. * @parm DWORD | dwDeviceID | Capture device ID.
  24. ***************************************************************************/
  25. CWDMPin::CWDMPin(DWORD dwDeviceID) : CWDMDriver(dwDeviceID)
  26. {
  27. m_hKS = (HANDLE)NULL;
  28. m_fStarted = FALSE;
  29. m_hKsUserDLL = (HINSTANCE)NULL;
  30. m_pKsCreatePin = (LPFNKSCREATEPIN)NULL;
  31. ZeroMemory(&m_biHdr, sizeof(KS_BITMAPINFOHEADER));
  32. }
  33. /****************************************************************************
  34. * @doc INTERNAL CWDMPINMETHOD
  35. *
  36. * @mfunc void | CWDMPin | ~CWDMPin | Video pin class destructor. Closes
  37. * the video pin and releases the video buffers allocated.
  38. ***************************************************************************/
  39. CWDMPin::~CWDMPin()
  40. {
  41. FX_ENTRY("CWDMPin::~CWDMPin");
  42. DEBUGMSG(ZONE_INIT, ("%s: Destroying the video pin, m_hKS=0x%08lX\r\n", _fx_, m_hKS));
  43. // Nuke the video streaming pin
  44. DestroyPin();
  45. // Close the driver
  46. if (GetDriverHandle())
  47. CloseDriver();
  48. // Release kernel streaming DLL (KSUSER.DLL)
  49. if (m_hKsUserDLL)
  50. FreeLibrary(m_hKsUserDLL);
  51. }
  52. /****************************************************************************
  53. * @doc INTERNAL CWDMPINMETHOD
  54. *
  55. * @mfunc BOOL | CWDMPin | GetFrame | This function gets a frame from the
  56. * video streaming pin.
  57. *
  58. * @parm LPVIDEOHDR | lpVHdr | Pointer to the destination buffer to receive
  59. * the video frame and information.
  60. *
  61. * @parm PDWORD | pdwBytesUsed | Pointer to the number of bytes used to
  62. * read the video frame.
  63. *
  64. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  65. ***************************************************************************/
  66. BOOL CWDMPin::GetFrame(LPVIDEOHDR lpVHdr)
  67. {
  68. FX_ENTRY("CWDMPin::GetFrame");
  69. ASSERT(lpVHdr && lpVHdr->lpData && GetDriverHandle() && m_hKS && (lpVHdr->dwBufferLength >= m_biHdr.biSizeImage));
  70. DWORD bRtn;
  71. // Check input params and state
  72. if (!lpVHdr || !lpVHdr->lpData || !GetDriverHandle() || !m_hKS || (lpVHdr->dwBufferLength < m_biHdr.biSizeImage))
  73. {
  74. ERRORMESSAGE(("%s: No buffer, no driver, no PIN connection, or buffer too small\r\n", _fx_));
  75. goto MyError0;
  76. }
  77. // Put the pin in streaming mode
  78. if (!Start())
  79. {
  80. ERRORMESSAGE(("%s: Cannot set streaming state to KSSTATE_RUN\r\n", _fx_));
  81. goto MyError0;
  82. }
  83. // Initialize structure to do a read on the video pin
  84. DWORD cbBytesReturned;
  85. KS_HEADER_AND_INFO SHGetImage;
  86. ZeroMemory(&SHGetImage,sizeof(SHGetImage));
  87. SHGetImage.StreamHeader.Data = (LPDWORD)lpVHdr->lpData;
  88. SHGetImage.StreamHeader.Size = sizeof (KS_HEADER_AND_INFO);
  89. SHGetImage.StreamHeader.FrameExtent = m_biHdr.biSizeImage;
  90. SHGetImage.FrameInfo.ExtendedHeaderSize = sizeof (KS_FRAME_INFO);
  91. // Read a frame on the video pin
  92. bRtn = DeviceIoControl(m_hKS, IOCTL_KS_READ_STREAM, &SHGetImage, sizeof(SHGetImage), &SHGetImage, sizeof(SHGetImage), &cbBytesReturned);
  93. if (!bRtn)
  94. {
  95. ERRORMESSAGE(("%s: DevIo rtn (%d), GetLastError=%d. StreamState->STOP\r\n", _fx_, bRtn, GetLastError()));
  96. // Stop streaming on the video pin
  97. Stop();
  98. goto MyError0;
  99. }
  100. // Sanity check
  101. ASSERT(SHGetImage.StreamHeader.FrameExtent >= SHGetImage.StreamHeader.DataUsed);
  102. if (SHGetImage.StreamHeader.FrameExtent < SHGetImage.StreamHeader.DataUsed)
  103. {
  104. ERRORMESSAGE(("%s: We've corrupted memory!\r\n", _fx_));
  105. goto MyError0;
  106. }
  107. lpVHdr->dwTimeCaptured = timeGetTime();
  108. lpVHdr->dwBytesUsed = SHGetImage.StreamHeader.DataUsed;
  109. lpVHdr->dwFlags |= VHDR_KEYFRAME;
  110. return TRUE;
  111. MyError0:
  112. if (lpVHdr)
  113. {
  114. lpVHdr->dwBytesUsed = 0UL;
  115. lpVHdr->dwTimeCaptured = timeGetTime();
  116. }
  117. return FALSE;
  118. }
  119. /****************************************************************************
  120. * @doc INTERNAL CWDMPINMETHOD
  121. *
  122. * @mfunc BOOL | CWDMPin | Start | This function puts the video
  123. * pin in streaming mode.
  124. *
  125. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  126. ***************************************************************************/
  127. BOOL CWDMPin::Start()
  128. {
  129. if (m_fStarted)
  130. return TRUE;
  131. if (SetState(KSSTATE_PAUSE))
  132. m_fStarted = SetState(KSSTATE_RUN);
  133. return m_fStarted;
  134. }
  135. /****************************************************************************
  136. * @doc INTERNAL CWDMPINMETHOD
  137. *
  138. * @mfunc BOOL | CWDMPin | Stop | This function stops streaming on the
  139. * video pin.
  140. *
  141. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  142. ***************************************************************************/
  143. BOOL CWDMPin::Stop()
  144. {
  145. if (m_fStarted)
  146. {
  147. if (SetState(KSSTATE_PAUSE))
  148. if (SetState(KSSTATE_STOP))
  149. m_fStarted = FALSE;
  150. }
  151. return (BOOL)(m_fStarted == FALSE);
  152. }
  153. /****************************************************************************
  154. * @doc INTERNAL CWDMPINMETHOD
  155. *
  156. * @mfunc BOOL | CWDMPin | SetState | This function sets the state of the
  157. * video streaming pin.
  158. *
  159. * @parm KSSTATE | ksState | New state.
  160. *
  161. * @rdesc Returns TRUE if successful, or FALSE otherwise.
  162. ***************************************************************************/
  163. BOOL CWDMPin::SetState(KSSTATE ksState)
  164. {
  165. KSPROPERTY ksProp = {0};
  166. DWORD cbRet;
  167. ksProp.Set = KSPROPSETID_Connection;
  168. ksProp.Id = KSPROPERTY_CONNECTION_STATE;
  169. ksProp.Flags = KSPROPERTY_TYPE_SET;
  170. return DeviceIoControl(m_hKS, IOCTL_KS_PROPERTY, &ksProp, sizeof(ksProp), &ksState, sizeof(KSSTATE), &cbRet);
  171. }
  172. /****************************************************************************
  173. * @doc INTERNAL CWDMPINMETHOD
  174. *
  175. * @mfunc BOOL | CWDMPin | SetState | This function either finds a video
  176. * data range compatible with the bitamp info header passed in, of the
  177. * prefered video data range.
  178. *
  179. * @parm PKS_BITMAPINFOHEADER | pbiHdr | Bitmap info header to match.
  180. *
  181. * @parm BOOL | pfValidMatch | Set to TRUE if a match was found, FALSE
  182. * otherwise.
  183. *
  184. * @rdesc Returns a valid pointer to a <t KS_DATARANGE_VIDEO> structure if
  185. * successful, or a NULL pointer otherwise.
  186. *
  187. * @comm \\redrum\slmro\proj\wdm10\src\dvd\amovie\proxy\filter\ksutil.cpp(207):KsGetMediaTypes(
  188. ***************************************************************************/
  189. PKS_DATARANGE_VIDEO CWDMPin::FindMatchDataRangeVideo(PKS_BITMAPINFOHEADER pbiHdr, BOOL *pfValidMatch)
  190. {
  191. FX_ENTRY("CWDMPin::FindMatchDataRangeVideo");
  192. ASSERT(pfValidMatch && pbiHdr);
  193. // Check input params and state
  194. if (!pbiHdr || !pfValidMatch)
  195. {
  196. ERRORMESSAGE(("%s: Bad input params\r\n", _fx_));
  197. return (PKS_DATARANGE_VIDEO)NULL;
  198. }
  199. // Default
  200. *pfValidMatch = FALSE;
  201. PDATA_RANGES pDataRanges = GetDriverSupportedDataRanges();
  202. ASSERT(pDataRanges != 0);
  203. if (!pDataRanges)
  204. return (PKS_DATARANGE_VIDEO)NULL;
  205. PKS_DATARANGE_VIDEO pSelDRVideo, pDRVideo = &pDataRanges->Data, pFirstDRVideo = 0;
  206. KS_BITMAPINFOHEADER * pbInfo;
  207. // PhilF-: This code assumes that all structures are KS_DATARANGE_VIDEO. This
  208. // may not be a valid assumption foir palettized data types. Check with JayBo
  209. for (ULONG i = 0; i < pDataRanges->Count; i++)
  210. {
  211. // Meaningless unless it is *_VIDEOINFO
  212. if (pDRVideo->DataRange.Specifier == KSDATAFORMAT_SPECIFIER_VIDEOINFO)
  213. {
  214. // We don't care about TV Tuner like devices
  215. if (pDRVideo->ConfigCaps.VideoStandard == KS_AnalogVideo_None)
  216. {
  217. // Save first useable data range
  218. if (!pFirstDRVideo)
  219. pFirstDRVideo = pDRVideo;
  220. pbInfo = &((pDRVideo->VideoInfoHeader).bmiHeader);
  221. if ( (pbInfo->biBitCount == pbiHdr->biBitCount) && (pbInfo->biCompression == pbiHdr->biCompression) &&
  222. ( (((pDRVideo->ConfigCaps.OutputGranularityX == 0) || (pDRVideo->ConfigCaps.OutputGranularityY == 0))
  223. && (pDRVideo->ConfigCaps.InputSize.cx == pbiHdr->biWidth) && (pDRVideo->ConfigCaps.InputSize.cy == pbiHdr->biHeight)) ||
  224. ((pDRVideo->ConfigCaps.MinOutputSize.cx <= pbiHdr->biWidth) && (pbiHdr->biWidth <= pDRVideo->ConfigCaps.MaxOutputSize.cx) &&
  225. (pDRVideo->ConfigCaps.MinOutputSize.cy <= pbiHdr->biHeight) && (pbiHdr->biHeight <= pDRVideo->ConfigCaps.MaxOutputSize.cy) &&
  226. ((pbiHdr->biWidth % pDRVideo->ConfigCaps.OutputGranularityX) == 0) && ((pbiHdr->biHeight % pDRVideo->ConfigCaps.OutputGranularityY) == 0)) ) )
  227. {
  228. *pfValidMatch = TRUE;
  229. pSelDRVideo = pDRVideo;
  230. break;
  231. }
  232. } // VideoStandard
  233. } // Specifier
  234. pDRVideo++; // Next KS_DATARANGE_VIDEO
  235. }
  236. // If no valid match, use the first range found
  237. if (!*pfValidMatch)
  238. pSelDRVideo = pFirstDRVideo;
  239. return (pSelDRVideo);
  240. }
  241. /****************************************************************************
  242. * @doc INTERNAL CWDMPINMETHOD
  243. *
  244. * @mfunc BOOL | CWDMPin | CreatePin | This function actually creates a
  245. * video streaming pin on the class driver.
  246. *
  247. * @parm PKS_BITMAPINFOHEADER | pbiNewHdr | This pointer to a bitmap info
  248. * header specifies the format of the video data we want from the pin.
  249. *
  250. * @parm DWORD | dwAvgTimePerFrame | This parameter specifies the frame
  251. * at which we want video frames to be produced on the pin.
  252. *
  253. * @rdesc Returns TRUE is successful, FALSE otherwise.
  254. ***************************************************************************/
  255. BOOL CWDMPin::CreatePin(PKS_BITMAPINFOHEADER pbiNewHdr, DWORD dwAvgTimePerFrame)
  256. {
  257. FX_ENTRY("CWDMPin::CreatePin");
  258. ASSERT(m_pKsCreatePin);
  259. PKS_BITMAPINFOHEADER pbiHdr;
  260. BOOL bMustMatch, bValidMatch;
  261. #ifdef _DEBUG
  262. char szFourCC[5] = {0};
  263. #endif
  264. if (pbiNewHdr)
  265. {
  266. // We need to find a video data range that matches the bitmap info header passed in
  267. bMustMatch = TRUE;
  268. pbiHdr = pbiNewHdr;
  269. }
  270. else
  271. {
  272. // We'll use the preferred video data range and default bitmap format
  273. bMustMatch = FALSE;
  274. pbiHdr = &m_biHdr;
  275. }
  276. PKS_DATARANGE_VIDEO pSelDRVideo = FindMatchDataRangeVideo(pbiHdr, &bValidMatch);
  277. if (!pSelDRVideo)
  278. return FALSE;
  279. if (bMustMatch && !bValidMatch)
  280. return FALSE;
  281. // If we already have a pin, nuke it
  282. if (GetPinHandle())
  283. DestroyPin();
  284. // Connect to a new PIN.
  285. DATAPINCONNECT DataConnect;
  286. ZeroMemory(&DataConnect, sizeof(DATAPINCONNECT));
  287. DataConnect.Connect.PinId = 0; // CODEC0 sink
  288. DataConnect.Connect.PinToHandle = NULL; // no "connect to"
  289. DataConnect.Connect.Interface.Set = KSINTERFACESETID_Standard;
  290. DataConnect.Connect.Interface.Id = KSINTERFACE_STANDARD_STREAMING; // STREAMING
  291. DataConnect.Connect.Medium.Set = KSMEDIUMSETID_Standard;
  292. DataConnect.Connect.Medium.Id = KSMEDIUM_STANDARD_DEVIO;
  293. DataConnect.Connect.Priority.PriorityClass = KSPRIORITY_NORMAL;
  294. DataConnect.Connect.Priority.PrioritySubClass = 1;
  295. CopyMemory(&(DataConnect.Data.DataFormat), &(pSelDRVideo->DataRange), sizeof(KSDATARANGE));
  296. CopyMemory(&(DataConnect.Data.VideoInfoHeader), &pSelDRVideo->VideoInfoHeader, sizeof(KS_VIDEOINFOHEADER));
  297. // Adjust the image sizes if necessary
  298. if (bValidMatch)
  299. {
  300. DataConnect.Data.VideoInfoHeader.bmiHeader.biWidth = pbiHdr->biWidth;
  301. DataConnect.Data.VideoInfoHeader.bmiHeader.biHeight = abs(pbiHdr->biHeight); // Support only +biHeight!
  302. DataConnect.Data.VideoInfoHeader.bmiHeader.biSizeImage = pbiHdr->biSizeImage;
  303. }
  304. // Overwrite the default frame rate if non-zero
  305. if (dwAvgTimePerFrame > 0)
  306. DataConnect.Data.VideoInfoHeader.AvgTimePerFrame = (REFERENCE_TIME)dwAvgTimePerFrame;
  307. #ifdef _DEBUG
  308. *((DWORD*)&szFourCC) = DataConnect.Data.VideoInfoHeader.bmiHeader.biCompression;
  309. #endif
  310. DEBUGMSG(ZONE_INIT, ("%s: Request image format: FourCC(%s) %d * %d * %d bits = %d bytes\r\n", _fx_, szFourCC, DataConnect.Data.VideoInfoHeader.bmiHeader.biWidth, DataConnect.Data.VideoInfoHeader.bmiHeader.biHeight, DataConnect.Data.VideoInfoHeader.bmiHeader.biBitCount, DataConnect.Data.VideoInfoHeader.bmiHeader.biSizeImage));
  311. DEBUGMSG(ZONE_INIT, ("%s: Request frame rate: %d fps\r\n", _fx_, 10000000/dwAvgTimePerFrame));
  312. DEBUGMSG(ZONE_INIT, ("%s: m_hKS was=0x%08lX\r\n", _fx_, m_hKS));
  313. #ifndef HIDE_WDM_DEVICES
  314. DWORD dwErr = (*m_pKsCreatePin)(GetDriverHandle(), (PKSPIN_CONNECT)&DataConnect, GENERIC_READ | GENERIC_WRITE, &m_hKS);
  315. #else
  316. DWORD dwErr = 0UL;
  317. m_hKS = NULL;
  318. #endif
  319. if (dwAvgTimePerFrame != 0)
  320. {
  321. DEBUGMSG(ZONE_INIT, ("%s: m_hKS is now=0x%08lX set to stream at %d fps\r\n", _fx_, m_hKS, 10000000/dwAvgTimePerFrame));
  322. }
  323. else
  324. {
  325. DEBUGMSG(ZONE_INIT, ("%s: m_hKS is now=0x%08lX\r\n", _fx_, m_hKS));
  326. }
  327. if (dwErr || (m_hKS == NULL))
  328. {
  329. ERRORMESSAGE(("%s: KsCreatePin returned 0x%08lX failure and m_hKS=0x%08lX\r\n", _fx_, dwErr, m_hKS));
  330. if (m_hKS == INVALID_HANDLE_VALUE)
  331. {
  332. m_hKS = (HANDLE)NULL;
  333. }
  334. return FALSE;
  335. }
  336. // Cache the bitmap info header
  337. CopyMemory(&m_biHdr, &DataConnect.Data.VideoInfoHeader.bmiHeader, sizeof(KS_BITMAPINFOHEADER));
  338. m_dwAvgTimePerFrame = (DWORD)DataConnect.Data.VideoInfoHeader.AvgTimePerFrame;
  339. DEBUGMSG(ZONE_INIT, ("%s: New m_biHdr:\r\n biSize=%ld\r\n biWidth=%ld\r\n biHeight=%ld\r\n biPlanes=%ld\r\n biBitCount=%ld\r\n biCompression=%ld\r\n biSizeImage=%ld\r\n", _fx_, m_biHdr.biSize, m_biHdr.biWidth, m_biHdr.biHeight, m_biHdr.biPlanes, m_biHdr.biBitCount, m_biHdr.biCompression, m_biHdr.biSizeImage));
  340. DEBUGMSG(ZONE_INIT, ("%s: New m_dwAvgTimePerFrame=%ld (%fd fps)\r\n", _fx_, m_dwAvgTimePerFrame, 10000000/m_dwAvgTimePerFrame));
  341. return TRUE;
  342. }
  343. /****************************************************************************
  344. * @doc INTERNAL CWDMPINMETHOD
  345. *
  346. * @mfunc BOOL | CWDMPin | DestroyPin | This function nukes a video
  347. * streaming pin.
  348. *
  349. * @rdesc Returns TRUE is successful, FALSE otherwise.
  350. ***************************************************************************/
  351. BOOL CWDMPin::DestroyPin()
  352. {
  353. BOOL fRet = TRUE;
  354. FX_ENTRY("CWDMPin::DestroyPin");
  355. DEBUGMSG(ZONE_INIT, ("%s: Destroy PIN m_hKS=0x%08lX\r\n", _fx_, m_hKS));
  356. if (m_hKS)
  357. {
  358. Stop();
  359. if (!(fRet = CloseHandle(m_hKS)))
  360. {
  361. ERRORMESSAGE(("%s: CloseHandle(m_hKS=0x%08lX) failed with GetLastError()=0x%08lX\r\n", _fx_, m_hKS, GetLastError()));
  362. }
  363. m_hKS = NULL;
  364. }
  365. return fRet;
  366. }
  367. /****************************************************************************
  368. * @doc INTERNAL CWDMPINMETHOD
  369. *
  370. * @mfunc BOOL | CWDMPin | SetBitmapInfo | This function sets the video
  371. * format of video streaming pin.
  372. *
  373. * @parm PKS_BITMAPINFOHEADER | pbiHdrNew | This pointer to a bitmap info
  374. * header specifies the format of the video data we want from the pin.
  375. *
  376. * @rdesc Returns TRUE is successful, FALSE otherwise.
  377. ***************************************************************************/
  378. BOOL CWDMPin::SetBitmapInfo(PKS_BITMAPINFOHEADER pbiHdrNew)
  379. {
  380. FX_ENTRY("CWDMPin::SetBitmapInfo");
  381. // Validate call
  382. if (!GetDriverHandle())
  383. {
  384. ERRORMESSAGE(("%s: Driver hasn't been opened yet\r\n", _fx_));
  385. return FALSE;
  386. }
  387. DEBUGMSG(ZONE_INIT, ("%s: New pbiHdrNew:\r\n biSize=%ld\r\n biWidth=%ld\r\n biHeight=%ld\r\n biPlanes=%ld\r\n biBitCount=%ld\r\n biCompression=%ld\r\n biSizeImage=%ld\r\n", _fx_, pbiHdrNew->biSize, pbiHdrNew->biWidth, pbiHdrNew->biHeight, pbiHdrNew->biPlanes, pbiHdrNew->biBitCount, pbiHdrNew->biCompression, pbiHdrNew->biSizeImage));
  388. // Check if we need to change anything
  389. if ( GetPinHandle() && (m_biHdr.biHeight == pbiHdrNew->biHeight) && (m_biHdr.biWidth == pbiHdrNew->biWidth) &&
  390. (m_biHdr.biBitCount == pbiHdrNew->biBitCount) && (m_biHdr.biSizeImage == pbiHdrNew->biSizeImage) &&
  391. (m_biHdr.biCompression == pbiHdrNew->biCompression) )
  392. return TRUE;
  393. else
  394. return CreatePin(pbiHdrNew, m_dwAvgTimePerFrame);
  395. }
  396. /****************************************************************************
  397. * @doc INTERNAL CWDMPINMETHOD
  398. *
  399. * @mfunc BOOL | CWDMPin | GetBitmapInfo | This function gets the video
  400. * format of a video streaming pin.
  401. *
  402. * @parm PKS_BITMAPINFOHEADER | pbInfo | This parameter points to a bitmap
  403. * info header structure to receive the video format.
  404. *
  405. * @parm WORD | wSize | This parameter specifies the size of the bitmap
  406. * info header structure.
  407. *
  408. * @rdesc Returns TRUE is successful, FALSE otherwise.
  409. ***************************************************************************/
  410. BOOL CWDMPin::GetBitmapInfo(PKS_BITMAPINFOHEADER pbInfo, WORD wSize)
  411. {
  412. FX_ENTRY("CWDMPin::GetBitmapInfo");
  413. // Validate call
  414. if (!m_hKS && !m_biHdr.biSizeImage)
  415. {
  416. ERRORMESSAGE(("%s: No existing PIN handle or no available format\r\n", _fx_));
  417. return FALSE;
  418. }
  419. CopyMemory(pbInfo, &m_biHdr, wSize);
  420. // Support only positive +biHeight.
  421. if (pbInfo->biHeight < 0)
  422. {
  423. pbInfo->biHeight = -pbInfo->biHeight;
  424. DEBUGMSG(ZONE_INIT, ("%s: Changed biHeight from -%ld to %ld\r\n", _fx_, pbInfo->biHeight, pbInfo->biHeight));
  425. }
  426. return TRUE;
  427. }
  428. /****************************************************************************
  429. * @doc INTERNAL CWDMPINMETHOD
  430. *
  431. * @mfunc BOOL | CWDMPin | GetPaletteInfo | This function gets the video
  432. * palette of a video streaming pin.
  433. *
  434. * @parm CAPTUREPALETTE * | pPal | This parameter points to a palette
  435. * structure to receive the video palette.
  436. *
  437. * @parm DWORD | dwcbSize | This parameter specifies the size of the video
  438. * palette.
  439. *
  440. * @rdesc Returns TRUE is successful, FALSE otherwise.
  441. ***************************************************************************/
  442. BOOL CWDMPin::GetPaletteInfo(CAPTUREPALETTE *pPal, DWORD dwcbSize)
  443. {
  444. FX_ENTRY("CWDMPin::GetBitmapInfo");
  445. // Validate call
  446. if (!m_hKS && !m_biHdr.biSizeImage && (m_biHdr.biBitCount > 8))
  447. {
  448. ERRORMESSAGE(("%s: No existing PIN handle, no available format, or bad biBitCount\r\n", _fx_));
  449. return FALSE;
  450. }
  451. // PhilF-: Copy some real bits there
  452. // CopyMemory(pbInfo, &m_biHdr, wSize);
  453. return TRUE;
  454. }
  455. /****************************************************************************
  456. * @doc INTERNAL CWDMPINMETHOD
  457. *
  458. * @mfunc BOOL | CWDMPin | SetAverageTimePerFrame | This function sets the
  459. * video frame rate of a video streaming pin.
  460. *
  461. * @parm DWORD | dwAvgTimePerFrame | This parameter specifies the rate
  462. * at which we want video frames to be produced on the pin.
  463. *
  464. * @rdesc Returns TRUE is successful, FALSE otherwise.
  465. ***************************************************************************/
  466. BOOL CWDMPin::SetAverageTimePerFrame(DWORD dwNewAvgTimePerFrame)
  467. {
  468. FX_ENTRY("CWDMPin::SetAverageTimePerFrame");
  469. // Validate call
  470. if (!GetDriverHandle())
  471. {
  472. ERRORMESSAGE(("%s: Driver hasn't been opened yet\r\n", _fx_));
  473. return FALSE;
  474. }
  475. DEBUGMSG(ZONE_INIT, ("%s: Current frame interval=%d; new frame intercal=%d\r\n", _fx_, m_dwAvgTimePerFrame, dwNewAvgTimePerFrame));
  476. if (m_dwAvgTimePerFrame != dwNewAvgTimePerFrame)
  477. return CreatePin(&m_biHdr, dwNewAvgTimePerFrame);
  478. else
  479. {
  480. DEBUGMSG(ZONE_INIT, ("%s: No need to change frame rate\r\n", _fx_));
  481. return TRUE;
  482. }
  483. }
  484. /****************************************************************************
  485. * @doc INTERNAL CWDMPINMETHOD
  486. *
  487. * @mfunc BOOL | CWDMPin | OpenDriverAndPin | This function opens the class
  488. * driver and creates a video streaming pin.
  489. *
  490. * @rdesc Returns TRUE is successful, FALSE otherwise.
  491. ***************************************************************************/
  492. BOOL CWDMPin::OpenDriverAndPin()
  493. {
  494. FX_ENTRY("CWDMPin::OpenDriverAndPin");
  495. // Load KSUSER.DLL and get a proc address
  496. if (m_hKsUserDLL = LoadLibrary("KSUSER"))
  497. {
  498. if (m_pKsCreatePin = (LPFNKSCREATEPIN)GetProcAddress(m_hKsUserDLL, "KsCreatePin"))
  499. {
  500. // Open the class driver
  501. if (OpenDriver())
  502. {
  503. // Create a video streaming pin on the driver
  504. if (CreatePin((PKS_BITMAPINFOHEADER)NULL))
  505. {
  506. return TRUE;
  507. }
  508. else
  509. {
  510. DEBUGMSG(ZONE_INIT, ("%s: Pin connection creation failed!\r\n", _fx_));
  511. if (GetDriverHandle())
  512. CloseDriver();
  513. }
  514. }
  515. }
  516. FreeLibrary(m_hKsUserDLL);
  517. }
  518. return FALSE;
  519. }