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.

496 lines
12 KiB

  1. #include <windows.h>
  2. #include <qos.h>
  3. #include <winsock2.h>
  4. #include "frameop.h"
  5. #include <confdbg.h>
  6. #include <avutil.h>
  7. #include "..\nac\utils.h"
  8. #include "vidinout.h"
  9. #include "vcmstrm.h"
  10. #ifdef DEBUG
  11. extern "C" BOOL g_framedebug = TRUE;
  12. #endif
  13. // Base class methods
  14. STDMETHODIMP_(ULONG)
  15. CFrameOp::AddRef(
  16. void
  17. )
  18. {
  19. FX_ENTRY("CFrameOp::AddRef");
  20. DEBUGMSG(ZONE_NMCAP_REFCOUNT,("%s: refcnt+(0x%08lX [CFrameOp])=%d\r\n", _fx_, this, m_cRef+1));
  21. return InterlockedIncrement(&m_cRef);
  22. }
  23. STDMETHODIMP_(ULONG)
  24. CFrameOp::Release(
  25. void
  26. )
  27. {
  28. LONG res;
  29. FX_ENTRY("CFrameOp::Release");
  30. DEBUGMSG(ZONE_NMCAP_REFCOUNT,("%s: refcnt-(0x%08lX [CFrameOp])=%d\r\n", _fx_, this, m_cRef-1));
  31. res = InterlockedDecrement(&m_cRef);
  32. if (res == 0) {
  33. if (m_pool) {
  34. m_pool->Release();
  35. }
  36. if (m_next)
  37. m_next->Release();
  38. DEBUGMSG(ZONE_NMCAP_CDTOR,("%s: deleting (0x%08lX [CFrameOp])\r\n", _fx_, this));
  39. delete this;
  40. }
  41. return res;
  42. }
  43. // CCaptureFrame methods
  44. CCaptureFrame::~CCaptureFrame(
  45. )
  46. {
  47. if (m_hbuf1)
  48. FreeFrameBuffer(m_hcapdev, m_hbuf1);
  49. if (m_hbuf2)
  50. FreeFrameBuffer(m_hcapdev, m_hbuf2);
  51. }
  52. STDMETHODIMP
  53. CCaptureFrame::DoOp(
  54. IBitmapSurface** ppbs
  55. )
  56. {
  57. HFRAMEBUF hbuf;
  58. BYTE* pBits;
  59. m_pool->GetBuffer(ppbs, &hbuf);
  60. if (*ppbs) {
  61. pBits = CaptureFrame(m_hcapdev, hbuf);
  62. return NO_ERROR;
  63. }
  64. return E_OUTOFMEMORY;
  65. }
  66. BOOL
  67. CCaptureFrame::InitCapture(
  68. HCAPDEV hcapdev,
  69. LPBITMAPINFOHEADER lpbmh
  70. )
  71. {
  72. FX_ENTRY("CCaptureFrame::InitCapture");
  73. if ((m_hbuf1 = AllocFrameBuffer(hcapdev)) &&
  74. (m_hbuf2 = AllocFrameBuffer(hcapdev))) {
  75. if ((m_pool = new CVidPool)) {
  76. m_pool->AddRef();
  77. if (m_pool->InitPool(0, lpbmh) == NO_ERROR) {
  78. m_pool->AddExternalBuffer(GetFrameBufferPtr(hcapdev, m_hbuf1), (void*)m_hbuf1);
  79. m_pool->AddExternalBuffer(GetFrameBufferPtr(hcapdev, m_hbuf2), (void*)m_hbuf2);
  80. m_hcapdev = hcapdev;
  81. DEBUGMSG(ZONE_NMCAP_CDTOR,("%s: init capture (0x%08lX [CCaptureFrame])\r\n", _fx_, this));
  82. return TRUE;
  83. }
  84. else {
  85. ERRORMESSAGE(("%s: Failed to init capture pool", _fx_));
  86. m_pool->Release();
  87. }
  88. }
  89. else
  90. {
  91. ERRORMESSAGE(("%s: Failed to alloc capture pool", _fx_));
  92. }
  93. FreeFrameBuffer(hcapdev, m_hbuf2);
  94. }
  95. else
  96. {
  97. ERRORMESSAGE(("%s: Failed to allocate frame buffer", _fx_));
  98. }
  99. if (m_hbuf1)
  100. FreeFrameBuffer(hcapdev, m_hbuf1);
  101. return FALSE;
  102. }
  103. // CStreamCaptureFrame methods
  104. CStreamCaptureFrame::~CStreamCaptureFrame(
  105. )
  106. {
  107. StopStreaming(m_hcapdev);
  108. UninitializeStreaming(m_hcapdev);
  109. }
  110. STDMETHODIMP
  111. CStreamCaptureFrame::DoOp(
  112. IBitmapSurface** ppbs
  113. )
  114. {
  115. long pitch;
  116. CAPFRAMEINFO cfi;
  117. CBitmap *pcb;
  118. FX_ENTRY ("CStreamCaptureFrame::DoOp")
  119. m_pool->GetBuffer(&pcb, NULL);
  120. if (pcb) {
  121. if (pcb->m_bits) {
  122. PutBufferIntoStream(m_hcapdev, (BYTE*)pcb->m_bits);
  123. pcb->m_bits = NULL;
  124. }
  125. GetNextReadyBuffer(m_hcapdev, &cfi);
  126. if (pcb->m_bits = (LPBYTE)cfi.lpData) {
  127. *ppbs = (IBitmapSurface*)pcb;
  128. return NO_ERROR;
  129. }
  130. DEBUGMSG(ZONE_NMCAP_STREAMING,("%s: Failed to get buffer from DCAP\r\n", _fx_));
  131. pcb->Release();
  132. }
  133. *ppbs = NULL;
  134. return E_OUTOFMEMORY;
  135. }
  136. void GiveBufferToDriver (CBitmap *pBitmap, DWORD_PTR refdata)
  137. {
  138. if (pBitmap->m_bits && refdata) {
  139. PutBufferIntoStream((HCAPDEV)refdata, (BYTE*)pBitmap->m_bits);
  140. pBitmap->m_bits = NULL;
  141. }
  142. }
  143. BOOL
  144. CStreamCaptureFrame::InitCapture(
  145. HCAPDEV hcapdev,
  146. LPBITMAPINFOHEADER lpbmh
  147. )
  148. {
  149. CAPSTREAM cs;
  150. CAPFRAMEINFO cfi;
  151. FX_ENTRY("CStreamCaptureFrame::InitCapture");
  152. // Initialize streaming
  153. cs.dwSize = sizeof (CAPSTREAM);
  154. cs.nFPSx100 = 30 * 100;
  155. cs.ncCapBuffers = 5;
  156. if (InitializeStreaming(hcapdev, &cs, 0)) {
  157. if (StartStreaming(hcapdev)) {
  158. if (WaitForSingleObject(cs.hevWait, 5000) != WAIT_TIMEOUT) {
  159. if ((m_pool = new CVidPool)) {
  160. m_pool->AddRef();
  161. if (m_pool->InitPool(0, lpbmh) == NO_ERROR) {
  162. m_pool->m_pAddingToFree = &GiveBufferToDriver;
  163. m_pool->m_refdata = (DWORD_PTR)hcapdev;
  164. m_pool->AddExternalBuffer(NULL, (void*)1);
  165. m_pool->AddExternalBuffer(NULL, (void*)2);
  166. m_hcapdev = hcapdev;
  167. DEBUGMSG(ZONE_NMCAP_CDTOR,("%s: init stream capture (0x%08lX [CStreamCaptureFrame])\r\n", _fx_, this));
  168. return TRUE;
  169. }
  170. else
  171. {
  172. ERRORMESSAGE(("%s: Failed to init capture pool", _fx_));
  173. m_pool->Release();
  174. }
  175. }
  176. else
  177. {
  178. ERRORMESSAGE(("%s: Failed to alloc capture pool", _fx_));
  179. }
  180. }
  181. else
  182. {
  183. ERRORMESSAGE(("%s: Error no frame events received", _fx_));
  184. }
  185. }
  186. else
  187. {
  188. ERRORMESSAGE(("%s: Error starting streaming", _fx_));
  189. }
  190. UninitializeStreaming(hcapdev);
  191. }
  192. else
  193. {
  194. ERRORMESSAGE(("%s: Error initializing streaming", _fx_));
  195. }
  196. return FALSE;
  197. }
  198. // CICMcvtFrame methods
  199. CICMcvtFrame::~CICMcvtFrame(
  200. )
  201. {
  202. if (m_hic) {
  203. ICDecompressEnd(m_hic);
  204. ICClose(m_hic);
  205. }
  206. if (m_inlpbmh)
  207. LocalFree((HANDLE)m_inlpbmh);
  208. if (m_outlpbmh)
  209. LocalFree((HANDLE)m_outlpbmh);
  210. }
  211. STDMETHODIMP
  212. CICMcvtFrame::DoOp(
  213. IBitmapSurface** ppbs
  214. )
  215. {
  216. BYTE* pBits;
  217. BYTE* pCvtBits;
  218. long pitch;
  219. IBitmapSurface *pBS;
  220. m_pool->GetBuffer(&pBS, NULL);
  221. if (pBS) {
  222. (*ppbs)->LockBits(NULL, 0, (void**)&pBits, &pitch);
  223. pBS->LockBits(NULL, 0, (void**)&pCvtBits, &pitch);
  224. ICDecompress(m_hic, 0, m_inlpbmh, pBits, m_outlpbmh, pCvtBits);
  225. (*ppbs)->UnlockBits(NULL, pBits);
  226. pBS->UnlockBits(NULL, pCvtBits);
  227. (*ppbs)->Release(); // done with the capture buffer
  228. *ppbs = pBS;
  229. return NO_ERROR;
  230. }
  231. return E_OUTOFMEMORY;
  232. }
  233. BOOL
  234. CICMcvtFrame::InitCvt(
  235. LPBITMAPINFOHEADER lpbmh,
  236. DWORD bmhLen,
  237. LPBITMAPINFOHEADER *plpbmhdsp
  238. )
  239. {
  240. DWORD dwLen;
  241. HIC hic;
  242. FX_ENTRY("CICMcvtFrame::InitCvt");
  243. *plpbmhdsp = lpbmh;
  244. if (lpbmh->biCompression != BI_RGB) {
  245. *plpbmhdsp = NULL;
  246. // make internal copy of input BITMAPINFOHEADER
  247. m_inlpbmh = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, bmhLen);
  248. if (!m_inlpbmh) {
  249. ERRORMESSAGE(("%s: No memory for display bitmapinfoheader", _fx_));
  250. return FALSE;
  251. }
  252. CopyMemory(m_inlpbmh, lpbmh, bmhLen);
  253. // alloc space for display BITMAPINFOHEADER
  254. dwLen = sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);
  255. m_outlpbmh = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, dwLen);
  256. if (!m_outlpbmh) {
  257. LocalFree((HANDLE)m_inlpbmh);
  258. ERRORMESSAGE(("%s: No memory for display bitmapinfoheader", _fx_));
  259. return FALSE;
  260. }
  261. // First attempt to find a codec to convert to RGB24
  262. hic = ICGetDisplayFormat(NULL, lpbmh, m_outlpbmh, 24, 0, 0);
  263. if (!hic) {
  264. // nothing available to convert to RGB24, so see what we can get
  265. hic = ICGetDisplayFormat(NULL, lpbmh, m_outlpbmh, 0, 0, 0);
  266. }
  267. if (hic) {
  268. if (m_outlpbmh->biCompression == BI_RGB) {
  269. // we got a codec that can convert to RGB
  270. *plpbmhdsp = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, dwLen);
  271. if (*plpbmhdsp) {
  272. CopyMemory(*plpbmhdsp, m_outlpbmh, dwLen);
  273. if ((m_pool = new CVidPool)) {
  274. m_pool->AddRef();
  275. if (m_pool->InitPool(2, m_outlpbmh) == NO_ERROR) {
  276. m_hic = hic;
  277. ICDecompressBegin(m_hic, m_inlpbmh, m_outlpbmh);
  278. DEBUGMSG(ZONE_NMCAP_CDTOR,("%s: init ICM cvt (0x%08lX [CICMcvtFrame])\r\n", _fx_, this));
  279. return TRUE;
  280. }
  281. else {
  282. ERRORMESSAGE(("%s: Failed to init codec pool", _fx_));
  283. m_pool->Release();
  284. }
  285. }
  286. else
  287. {
  288. ERRORMESSAGE(("%s: Failed to alloc codec pool", _fx_));
  289. }
  290. LocalFree((HANDLE)*plpbmhdsp);
  291. }
  292. else
  293. {
  294. ERRORMESSAGE(("%s: Failed to init codec pool", _fx_));
  295. }
  296. }
  297. ICClose(hic); // close the opened codec
  298. }
  299. else
  300. {
  301. ERRORMESSAGE(("%s: No available codecs to decode format", _fx_));
  302. }
  303. // free allocate BITMAPINFOHEADER memory
  304. LocalFree((HANDLE)m_inlpbmh);
  305. m_inlpbmh = NULL;
  306. LocalFree((HANDLE)m_outlpbmh);
  307. m_outlpbmh = NULL;
  308. }
  309. return FALSE;
  310. }
  311. //CFilterChain methods
  312. CFilterChain::~CFilterChain(
  313. )
  314. {
  315. if (m_head)
  316. m_head->Release();
  317. }
  318. STDMETHODIMP
  319. CFilterChain::DoOp(
  320. IBitmapSurface** ppbs
  321. )
  322. {
  323. CFilterFrame *cfo;
  324. HRESULT hres;
  325. cfo = m_head;
  326. while (cfo) {
  327. if (cfo->m_enabled) {
  328. if ((hres = cfo->DoOp(ppbs)) != NOERROR) {
  329. return hres;
  330. }
  331. }
  332. cfo = (CFilterFrame*)cfo->m_next;
  333. }
  334. return NOERROR;
  335. }
  336. //CFilterFrame methods
  337. CFilterFrame::~CFilterFrame(
  338. )
  339. {
  340. if (m_effect)
  341. m_effect->Release();
  342. }
  343. STDMETHODIMP
  344. CFilterFrame::DoOp(
  345. IBitmapSurface** ppbs
  346. )
  347. {
  348. HRESULT hres;
  349. IBitmapSurface* pBS;
  350. if (m_inplace) {
  351. return m_effect->DoEffect(*ppbs, NULL, NULL, NULL);
  352. }
  353. else {
  354. m_pool->GetBuffer(&pBS, NULL);
  355. if (pBS) {
  356. hres = m_effect->DoEffect(*ppbs, pBS, NULL, NULL);
  357. (*ppbs)->Release();
  358. *ppbs = pBS;
  359. return hres;
  360. }
  361. return E_OUTOFMEMORY;
  362. }
  363. }
  364. BOOL
  365. CFilterFrame::InitFilter(
  366. IBitmapEffect *effect,
  367. LPBITMAPINFOHEADER lpbmhIn,
  368. CVidPool *pool
  369. )
  370. {
  371. DWORD dwFlags;
  372. FX_ENTRY("CFilterFrame::InitFilter");
  373. m_effect = effect;
  374. if (effect->GetMiscStatusBits(&dwFlags) == NO_ERROR) {
  375. m_inplace = (dwFlags & BITMAP_EFFECT_INPLACE);
  376. }
  377. else
  378. m_inplace = TRUE; // assumption!
  379. if (!m_inplace) {
  380. // we'll need a pool
  381. if (!pool || !(pool->Growable()))
  382. return FALSE;
  383. m_pool = pool;
  384. m_pool->AddRef();
  385. }
  386. DEBUGMSG(ZONE_NMCAP_CDTOR,("%s: init filter (0x%08lX [CFilterFrame])\r\n", _fx_, this));
  387. return TRUE;
  388. }
  389. //CConvertFrame internal routines
  390. //CConvertFrame methods
  391. CConvertFrame::~CConvertFrame()
  392. {
  393. if (m_refdata)
  394. LocalFree((HANDLE)m_refdata);
  395. }
  396. STDMETHODIMP
  397. CConvertFrame::DoOp(
  398. IBitmapSurface** ppbs
  399. )
  400. {
  401. IBitmapSurface* pBS;
  402. if (m_convert) {
  403. m_pool->GetBuffer(&pBS, NULL);
  404. if (pBS) {
  405. if (m_convert(*ppbs, pBS, m_refdata)) {
  406. (*ppbs)->Release();
  407. *ppbs = pBS;
  408. return NO_ERROR;
  409. }
  410. else {
  411. pBS->Release();
  412. return E_FAIL;
  413. }
  414. }
  415. else
  416. return E_OUTOFMEMORY;
  417. }
  418. return E_UNEXPECTED;
  419. }
  420. BOOL
  421. CConvertFrame::InitConverter(
  422. LPBITMAPINFOHEADER lpbmh,
  423. FRAMECONVERTPROC *convertproc,
  424. LPVOID refdata
  425. )
  426. {
  427. if (convertproc) {
  428. if ((m_pool = new CVidPool)) {
  429. m_pool->AddRef();
  430. if (m_pool->InitPool(2, lpbmh) == NO_ERROR) {
  431. m_convert = convertproc;
  432. m_refdata = refdata;
  433. return TRUE;
  434. }
  435. m_pool->Release();
  436. m_pool = NULL;
  437. }
  438. }
  439. return FALSE;
  440. }
  441.