Windows NT 4.0 source code leak
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.

527 lines
14 KiB

4 years ago
  1. /****************************************************************************
  2. *
  3. * DRAWPROC.C
  4. *
  5. * Standard AVI drawing handler.
  6. *
  7. * InstallAVIDrawHandler()
  8. *
  9. * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved.
  10. *
  11. * You have a royalty-free right to use, modify, reproduce and
  12. * distribute the Sample Files (and/or any modified version) in
  13. * any way you find useful, provided that you agree that
  14. * Microsoft has no warranty obligations or liability for any
  15. * Sample Application Files which are modified.
  16. *
  17. ***************************************************************************/
  18. #include <win32.h>
  19. #define NOAVIFILE
  20. #include <vfw.h>
  21. #include "common.h"
  22. #include "mciavi.h"
  23. #define FOURCC_VIDS mmioFOURCC('v','i','d','s')
  24. #define FOURCC_AVIDraw mmioFOURCC('D','R','A','W')
  25. #define VERSION_AVIDraw 0x00010000 // 1.00
  26. #ifdef DEBUG
  27. HDRAWDIB ghdd;
  28. #endif
  29. #ifndef HUGE
  30. #define HUGE _huge
  31. #endif
  32. /***************************************************************************
  33. ***************************************************************************/
  34. typedef struct {
  35. HDRAWDIB hdd;
  36. HDC hdc; // HDC to draw to
  37. int xDst; // destination rectangle
  38. int yDst;
  39. int dxDst;
  40. int dyDst;
  41. int xSrc; // source rectangle
  42. int ySrc;
  43. int dxSrc;
  44. int dySrc;
  45. BOOL fBackground;
  46. BOOL fRle;
  47. DWORD biSizeImage;
  48. BOOL fNeedUpdate;
  49. LONG rate; // playback rate (uSec / frame)
  50. } INSTINFO, *PINSTINFO;
  51. // static stuff in this file.
  52. LONG FAR PASCAL _loadds ICAVIDrawProc(DWORD id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2);
  53. static LONG AVIDrawOpen(ICOPEN FAR * icopen);
  54. static LONG AVIDrawClose(PINSTINFO pi);
  55. static LONG AVIDrawGetInfo(ICINFO FAR *icinfo, LONG lSize);
  56. static LONG AVIDrawQuery(PINSTINFO pi, LPBITMAPINFOHEADER lpbiIn);
  57. static LONG AVIDrawSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd);
  58. STATICFN LONG AVIDrawBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd);
  59. STATICFN LONG AVIDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd);
  60. static LONG AVIDrawEnd(PINSTINFO pi);
  61. static LONG AVIDrawChangePalette(PINSTINFO pi, LPBITMAPINFOHEADER lpbi);
  62. /***************************************************************************
  63. ***************************************************************************/
  64. LONG FAR PASCAL _loadds ICAVIDrawProc(DWORD id, HDRVR hDriver, UINT uiMessage, LPARAM lParam1, LPARAM lParam2)
  65. {
  66. INSTINFO *pi = (INSTINFO *)(UINT)id;
  67. switch (uiMessage)
  68. {
  69. case DRV_LOAD:
  70. case DRV_FREE:
  71. return 1;
  72. /*********************************************************************
  73. open
  74. *********************************************************************/
  75. case DRV_OPEN:
  76. if (lParam2 == 0L)
  77. return 1;
  78. return AVIDrawOpen((ICOPEN FAR *)lParam2);
  79. case DRV_CLOSE:
  80. return AVIDrawClose(pi);
  81. /*********************************************************************
  82. Configure/Info messages
  83. *********************************************************************/
  84. case DRV_QUERYCONFIGURE: // configuration from drivers applet
  85. return 0;
  86. case DRV_CONFIGURE:
  87. return 1;
  88. case ICM_CONFIGURE:
  89. case ICM_ABOUT:
  90. return ICERR_UNSUPPORTED;
  91. /*********************************************************************
  92. state messages
  93. *********************************************************************/
  94. case ICM_GETSTATE:
  95. case ICM_SETSTATE:
  96. return 0L;
  97. // case ICM_GETINFO:
  98. // return AVIDrawGetInfo((ICINFO FAR *)lParam1, lParam2);
  99. /*********************************************************************
  100. decompress messages
  101. *********************************************************************/
  102. case ICM_DRAW_QUERY:
  103. return AVIDrawQuery(pi, (LPBITMAPINFOHEADER)lParam1);
  104. case ICM_DRAW_SUGGESTFORMAT:
  105. return AVIDrawSuggestFormat(pi, (ICDRAWSUGGEST FAR *) lParam1, lParam2);
  106. case ICM_DRAW_BEGIN:
  107. return AVIDrawBegin(pi, (ICDRAWBEGIN FAR *) lParam1, lParam2);
  108. case ICM_DRAW_REALIZE:
  109. pi->hdc = (HDC) lParam1;
  110. if (!pi->hdc || !pi->hdd)
  111. break;
  112. pi->fBackground = (BOOL) lParam2;
  113. return DrawDibRealize(pi->hdd, pi->hdc, pi->fBackground);
  114. case ICM_DRAW_GET_PALETTE:
  115. if (!pi->hdd)
  116. break;
  117. return (LONG) DrawDibGetPalette(pi->hdd);
  118. case ICM_DRAW:
  119. return AVIDraw(pi, (ICDRAW FAR *)lParam1, lParam2);
  120. case ICM_DRAW_CHANGEPALETTE:
  121. return AVIDrawChangePalette(pi, (LPBITMAPINFOHEADER) lParam1);
  122. case ICM_DRAW_END:
  123. return AVIDrawEnd(pi);
  124. case ICM_DRAW_START:
  125. return DrawDibStart(pi->hdd, pi->rate);
  126. case ICM_DRAW_STOP:
  127. return DrawDibStop(pi->hdd);
  128. /*********************************************************************
  129. standard driver messages
  130. *********************************************************************/
  131. case DRV_DISABLE:
  132. case DRV_ENABLE:
  133. return 1;
  134. case DRV_INSTALL:
  135. case DRV_REMOVE:
  136. return 1;
  137. }
  138. return ICERR_UNSUPPORTED;
  139. }
  140. /*****************************************************************************
  141. *
  142. * AVIDrawOpen() is called from the DRV_OPEN message
  143. *
  144. ****************************************************************************/
  145. static LONG AVIDrawOpen(ICOPEN FAR * icopen)
  146. {
  147. INSTINFO * pinst;
  148. if (icopen->dwFlags & ICMODE_COMPRESS)
  149. return 0;
  150. if (icopen->dwFlags & ICMODE_DECOMPRESS)
  151. return 0;
  152. pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  153. if (!pinst)
  154. {
  155. icopen->dwError = ICERR_MEMORY;
  156. return 0;
  157. }
  158. DPF2(("*** AVIDrawOpen()\n"));
  159. //
  160. // init structure
  161. //
  162. pinst->hdd = DrawDibOpen();
  163. #ifdef DEBUG
  164. // hack: put the hdd where FindDrawDevice can find it
  165. ghdd = pinst->hdd;
  166. #endif
  167. //
  168. // return success.
  169. //
  170. icopen->dwError = ICERR_OK;
  171. return (LONG) (UINT) pinst;
  172. }
  173. /*****************************************************************************
  174. *
  175. * Close() is called on the DRV_CLOSE message.
  176. *
  177. ****************************************************************************/
  178. static LONG AVIDrawClose(PINSTINFO pi)
  179. {
  180. DPF2(("*** AVIDrawClose()\n"));
  181. if (pi->hdd) {
  182. DrawDibClose(pi->hdd);
  183. }
  184. LocalFree((HLOCAL) pi);
  185. return 1;
  186. }
  187. #if 0
  188. /*****************************************************************************
  189. *
  190. * AVIDrawGetInfo() implements the ICM_GETINFO message
  191. *
  192. ****************************************************************************/
  193. static LONG AVIDrawGetInfo(ICINFO FAR *icinfo, LONG lSize)
  194. {
  195. if (icinfo == NULL)
  196. return sizeof(ICINFO);
  197. if (lSize < sizeof(ICINFO))
  198. return 0;
  199. icinfo->dwSize = sizeof(ICINFO);
  200. icinfo->fccType = FOURCC_VIDS;
  201. icinfo->fccHandler = FOURCC_AVIDraw;
  202. icinfo->dwFlags = VIDCF_DRAW; // supports inter-frame
  203. icinfo->dwVersion = VERSION_AVIDraw;
  204. icinfo->dwVersionICM = ICVERSION;
  205. icinfo->szName[0] = 0;
  206. icinfo->szDescription[0]= 0;
  207. return sizeof(ICINFO);
  208. }
  209. #endif
  210. /*****************************************************************************
  211. *
  212. * AVIDrawQuery() implements ICM_DRAW_QUERY
  213. *
  214. ****************************************************************************/
  215. static LONG AVIDrawQuery(PINSTINFO pi,
  216. LPBITMAPINFOHEADER lpbiIn)
  217. {
  218. //
  219. // determine if the input DIB data is in a format we like.
  220. //
  221. if (lpbiIn == NULL)
  222. return ICERR_BADFORMAT;
  223. //
  224. // determine if the input DIB data is in a format we like.
  225. //
  226. // !!! Do we need a DrawDibQuery or something here to let this handle
  227. // any compressed format?
  228. #ifdef DRAWDIBNODECOMPRESS
  229. if (lpbiIn->biCompression != BI_RGB &&
  230. #if 0
  231. !(lpbiIn->biBitCount == 8 && lpbiIn->biCompression == BI_RLE8))
  232. #else
  233. 1)
  234. #endif
  235. return ICERR_BADFORMAT;
  236. #endif
  237. return ICERR_OK;
  238. }
  239. static LONG AVIDrawSuggestFormat(PINSTINFO pi, ICDRAWSUGGEST FAR *lpicd, LONG cbicd)
  240. {
  241. HIC hic;
  242. if (lpicd->lpbiSuggest == NULL)
  243. return sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
  244. hic = ICGetDisplayFormat(NULL, lpicd->lpbiIn, lpicd->lpbiSuggest,
  245. 0, lpicd->dxDst, lpicd->dyDst);
  246. if (hic)
  247. ICClose(hic);
  248. return sizeof(BITMAPINFOHEADER) + lpicd->lpbiSuggest->biClrUsed * sizeof(RGBQUAD);
  249. }
  250. /*****************************************************************************
  251. *
  252. * AVIDrawBegin() implements ICM_DRAW_BEGIN
  253. *
  254. ****************************************************************************/
  255. STATICFN LONG AVIDrawBegin(PINSTINFO pi, ICDRAWBEGIN FAR *lpicd, LONG cbicd)
  256. {
  257. LONG l;
  258. UINT wFlags;
  259. if (lpicd->dwFlags & ICDRAW_FULLSCREEN)
  260. return ICERR_UNSUPPORTED;
  261. l = AVIDrawQuery(pi, lpicd->lpbi);
  262. if ((l != ICERR_OK) || (lpicd->dwFlags & ICDRAW_QUERY))
  263. return l;
  264. // Copy over whatever we want to remember
  265. pi->xDst = lpicd->xDst;
  266. pi->yDst = lpicd->yDst;
  267. pi->dxDst = lpicd->dxDst;
  268. pi->dyDst = lpicd->dyDst;
  269. pi->xSrc = lpicd->xSrc;
  270. pi->ySrc = lpicd->ySrc;
  271. pi->dxSrc = lpicd->dxSrc;
  272. pi->dySrc = lpicd->dySrc;
  273. pi->rate = muldiv32(lpicd->dwScale,1000000,lpicd->dwRate);
  274. pi->hdc = lpicd->hdc;
  275. // !!! Should this be done somewhere else? drawdib mabey!
  276. if (pi->hdc)
  277. SetStretchBltMode(pi->hdc, COLORONCOLOR);
  278. wFlags = 0;
  279. // !!! We need some way to have a "stupid" mode here....
  280. if (lpicd->dwFlags & ICDRAW_BUFFER)
  281. wFlags |= DDF_BUFFER;
  282. // Don't animate if we're realizing in the background
  283. if (lpicd->dwFlags & ICDRAW_ANIMATE && !(pi->fBackground))
  284. wFlags |= DDF_ANIMATE;
  285. //
  286. // remember if this is RLE because we may need to hack it later.
  287. //
  288. pi->fRle = lpicd->lpbi->biCompression == BI_RLE8;
  289. pi->biSizeImage = (DWORD)(((UINT)lpicd->lpbi->biWidth+3)&~3)*(DWORD)(UINT)lpicd->lpbi->biHeight;
  290. DPF2(("*** AVIDrawBegin()\n"));
  291. if (lpicd->hpal == (HPALETTE)MCI_AVI_SETVIDEO_PALETTE_HALFTONE) {
  292. DrawDibSetPalette(pi->hdd, NULL);
  293. wFlags |= DDF_HALFTONE;
  294. }
  295. else
  296. DrawDibSetPalette(pi->hdd, lpicd->hpal);
  297. if (!DrawDibBegin(pi->hdd, pi->hdc,
  298. pi->dxDst, pi->dyDst,
  299. lpicd->lpbi,
  300. pi->dxSrc, pi->dySrc,
  301. wFlags))
  302. return ICERR_UNSUPPORTED;
  303. if (pi->hdc)
  304. DrawDibRealize(pi->hdd, pi->hdc, pi->fBackground);
  305. return ICERR_OK;
  306. }
  307. /*****************************************************************************
  308. *
  309. * AVIDraw() implements ICM_DRAW
  310. *
  311. ****************************************************************************/
  312. STATICFN LONG AVIDraw(PINSTINFO pi, ICDRAW FAR *lpicd, LONG cbicd)
  313. {
  314. UINT wFlags;
  315. BOOL f;
  316. wFlags = DDF_SAME_DRAW|DDF_SAME_HDC; // !!! Right flags?
  317. if ((lpicd->lpData == NULL) || (lpicd->cbData == 0)) {
  318. if ((lpicd->dwFlags & ICDRAW_UPDATE) || pi->fNeedUpdate) {
  319. DrawDibRealize(pi->hdd, pi->hdc, pi->fBackground);
  320. wFlags |= DDF_UPDATE;
  321. pi->fNeedUpdate = FALSE;
  322. lpicd->lpData = NULL;
  323. lpicd->cbData = 0;
  324. }
  325. else
  326. return ICERR_OK; // no data to draw.
  327. }
  328. else {
  329. if (lpicd->dwFlags & ICDRAW_PREROLL) {
  330. wFlags |= DDF_DONTDRAW;
  331. pi->fNeedUpdate = TRUE;
  332. } else if (lpicd->dwFlags & ICDRAW_HURRYUP) {
  333. wFlags |= DDF_HURRYUP;
  334. pi->fNeedUpdate = TRUE;
  335. } else
  336. pi->fNeedUpdate = FALSE;
  337. if (lpicd->dwFlags & ICDRAW_NOTKEYFRAME)
  338. wFlags |= DDF_NOTKEYFRAME;
  339. //
  340. // if we get a update while playing and we are drawing RLE delta's
  341. // make sure we update.
  342. //
  343. if (pi->fRle && (lpicd->dwFlags & ICDRAW_UPDATE)) {
  344. DrawDibDraw(pi->hdd, pi->hdc, pi->xDst, pi->yDst,
  345. 0,0,NULL,NULL,0,0,0,0,DDF_UPDATE|DDF_SAME_HDC|DDF_SAME_DRAW);
  346. }
  347. }
  348. //
  349. // We need a hack here for the RLE case, to make sure that
  350. // DIBs are marked correctly as BI_RLE8 or BI_RGB....
  351. //
  352. if (pi->fRle) {
  353. DPF2(("pi->fRle is true, cbData==%d, biSizeImage=%d\n",
  354. lpicd->cbData, pi->biSizeImage));
  355. if (lpicd->cbData == pi->biSizeImage)
  356. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RGB;
  357. else {
  358. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8;
  359. // We MUST set the correct size
  360. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biSizeImage = lpicd->cbData;
  361. }
  362. }
  363. f = DrawDibDraw(pi->hdd, pi->hdc,
  364. pi->xDst, pi->yDst,
  365. pi->dxDst, pi->dyDst,
  366. lpicd->lpFormat,
  367. lpicd->lpData,
  368. pi->xSrc, pi->ySrc,
  369. pi->dxSrc, pi->dySrc,
  370. wFlags);
  371. if (pi->fRle)
  372. ((LPBITMAPINFOHEADER)lpicd->lpFormat)->biCompression = BI_RLE8;
  373. if (!f) {
  374. if (wFlags & DDF_UPDATE)
  375. DPF(("DrawDibUpdate failed\n"));
  376. else
  377. DPF(("DrawDibDraw failed\n"));
  378. if (wFlags & DDF_UPDATE) {
  379. if (lpicd->dwFlags & ICDRAW_UPDATE)
  380. return ICERR_CANTUPDATE;
  381. else
  382. return ICERR_OK;
  383. } else
  384. return ICERR_ERROR;
  385. }
  386. return ICERR_OK;
  387. }
  388. static LONG AVIDrawChangePalette(PINSTINFO pi, LPBITMAPINFOHEADER lpbi)
  389. {
  390. PALETTEENTRY ape[256];
  391. LPRGBQUAD lprgb;
  392. int i;
  393. lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize);
  394. for (i = 0; i < (int) lpbi->biClrUsed; i++) {
  395. ape[i].peRed = lprgb[i].rgbRed;
  396. ape[i].peGreen = lprgb[i].rgbGreen;
  397. ape[i].peBlue = lprgb[i].rgbBlue;
  398. ape[i].peFlags = 0;
  399. }
  400. DrawDibChangePalette(pi->hdd, 0, (int) lpbi->biClrUsed,
  401. (LPPALETTEENTRY)ape);
  402. return ICERR_OK;
  403. }
  404. /*****************************************************************************
  405. *
  406. * AVIDrawEnd() implements ICM_DRAW_END
  407. *
  408. ****************************************************************************/
  409. static LONG AVIDrawEnd(PINSTINFO pi)
  410. {
  411. return ICERR_OK;
  412. }