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.

429 lines
11 KiB

  1. /****************************************************************************
  2. *
  3. * PALMAP.C
  4. *
  5. * Stream handler to map to a palette.
  6. *
  7. * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved.
  8. *
  9. * You have a royalty-free right to use, modify, reproduce and
  10. * distribute the Sample Files (and/or any modified version) in
  11. * any way you find useful, provided that you agree that
  12. * Microsoft has no warranty obligations or liability for any
  13. * Sample Application Files which are modified.
  14. *
  15. ***************************************************************************/
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include <win32.h>
  19. #include <mmsystem.h>
  20. #include <vfw.h>
  21. #include "dibmap.h"
  22. #include "palmap.h"
  23. LONG FAR PASCAL AVIStreamMakePalette(PAVISTREAM pavi, LONG lSkip,
  24. HPALETTE FAR *lphpal,
  25. LPBYTE lp16to8,
  26. int nColors)
  27. {
  28. LPHISTOGRAM lpHist = NULL;
  29. LONG l, lEnd;
  30. LONG lRet = AVIERR_OK;
  31. PGETFRAME pgf = NULL;
  32. if (!pavi || !lphpal || nColors < 2 || nColors > 256)
  33. return AVIERR_BADPARAM;
  34. if (lSkip < 1)
  35. lSkip = 1;
  36. lpHist = InitHistogram(NULL);
  37. if (!lpHist)
  38. return AVIERR_MEMORY;
  39. pgf = AVIStreamGetFrameOpen(pavi, NULL);
  40. l = AVIStreamStart(pavi);
  41. lEnd = l + AVIStreamLength(pavi);
  42. for (l = AVIStreamStart(pavi), lEnd = l + AVIStreamLength(pavi);
  43. l < lEnd;
  44. l += lSkip) {
  45. LPBITMAPINFOHEADER lpbi;
  46. lpbi = AVIStreamGetFrame(pgf, l);
  47. if (!lpbi) {
  48. lRet = AVIERR_INTERNAL;
  49. goto error;
  50. }
  51. DibHistogram(lpbi, NULL, 0, 0, -1, -1, lpHist);
  52. }
  53. *lphpal = HistogramPalette(lpHist, lp16to8, nColors);
  54. if (!*lphpal)
  55. lRet = AVIERR_MEMORY;
  56. error:
  57. if (pgf)
  58. AVIStreamGetFrameClose(pgf);
  59. if (lpHist)
  60. FreeHistogram(lpHist);
  61. return lRet;
  62. }
  63. typedef struct {
  64. IAVIStreamVtbl FAR * lpVtbl;
  65. ULONG ulRefCount;
  66. //
  67. // instance data
  68. //
  69. PAVISTREAM pavi;
  70. PGETFRAME pgf;
  71. AVISTREAMINFO avistream;
  72. HPALETTE hpal;
  73. LPBYTE lp16to8;
  74. LONG lLastFrame;
  75. HANDLE hdibLast;
  76. } PALMAPSTREAM, FAR*PPALMAPSTREAM;
  77. ///////////////////////////////////////////////////////////////////////////
  78. ///////////////////////////////////////////////////////////////////////////
  79. HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID FAR* ppvObj);
  80. HRESULT STDMETHODCALLTYPE PalMapStreamCreate (PAVISTREAM ps, LONG lParam1, LONG lParam2);
  81. ULONG STDMETHODCALLTYPE PalMapStreamAddRef (PAVISTREAM ps);
  82. ULONG STDMETHODCALLTYPE PalMapStreamRelease (PAVISTREAM ps);
  83. HRESULT STDMETHODCALLTYPE PalMapStreamInfo (PAVISTREAM ps, AVISTREAMINFO FAR * psi, LONG lSize);
  84. LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame (PAVISTREAM ps, LONG lPos, LONG lFlags);
  85. HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat);
  86. HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat);
  87. HRESULT STDMETHODCALLTYPE PalMapStreamRead (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, LONG FAR * plBytes,LONG FAR * plSamples);
  88. HRESULT STDMETHODCALLTYPE PalMapStreamWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten);
  89. HRESULT STDMETHODCALLTYPE PalMapStreamDelete (PAVISTREAM ps, LONG lStart, LONG lSamples);
  90. HRESULT STDMETHODCALLTYPE PalMapStreamReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG FAR *lpcb);
  91. HRESULT STDMETHODCALLTYPE PalMapStreamWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp,LONG cb);
  92. IAVIStreamVtbl PalMapStreamHandler = {
  93. PalMapStreamQueryInterface,
  94. PalMapStreamAddRef,
  95. PalMapStreamRelease,
  96. PalMapStreamCreate,
  97. PalMapStreamInfo,
  98. PalMapStreamFindKeyFrame,
  99. PalMapStreamReadFormat,
  100. PalMapStreamSetFormat,
  101. PalMapStreamRead,
  102. PalMapStreamWrite,
  103. PalMapStreamDelete,
  104. PalMapStreamReadData,
  105. PalMapStreamWriteData
  106. };
  107. LONG FAR PASCAL AVICreateMappedStream(PAVISTREAM FAR *ppsMapped,
  108. PAVISTREAM ps,
  109. int nColors)
  110. {
  111. PPALMAPSTREAM pavi;
  112. pavi = (PPALMAPSTREAM) GlobalAllocPtr(GHND, sizeof(PALMAPSTREAM));
  113. if (pavi == NULL)
  114. return AVIERR_MEMORY;
  115. pavi->lpVtbl = &PalMapStreamHandler;
  116. (pavi->lpVtbl->Create)((PAVISTREAM) pavi, (LONG) ps, nColors);
  117. // !!! error check
  118. *ppsMapped = (PAVISTREAM) pavi;
  119. return AVIERR_OK;
  120. }
  121. ///////////////////////////////////////////////////////////////////////////
  122. //
  123. // PalMapStreamOpen()
  124. //
  125. // open a single stream of a particular type from a AVI file.
  126. //
  127. // params:
  128. // szFile - PAVISTREAM
  129. // fccType - must be streamtypeVIDEO
  130. // lParam - nColors
  131. //
  132. // returns:
  133. // a PAVISTREAM for the specifed stream or NULL.
  134. //
  135. ///////////////////////////////////////////////////////////////////////////
  136. HRESULT STDMETHODCALLTYPE PalMapStreamCreate(PAVISTREAM ps, LONG lParam1, LONG lParam2)
  137. {
  138. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  139. LONG lRet = AVIERR_OK;
  140. if (AVIStreamAddRef((PAVISTREAM) lParam1) != AVIERR_OK)
  141. return ResultFromScode(AVIERR_FILEOPEN);
  142. pavi->pavi = (PAVISTREAM) lParam1;
  143. AVIStreamInfo(pavi->pavi, &pavi->avistream, sizeof(pavi->avistream));
  144. if (pavi->avistream.fccType != streamtypeVIDEO) {
  145. lRet = AVIERR_INTERNAL;
  146. goto error;
  147. }
  148. pavi->pgf = AVIStreamGetFrameOpen(pavi->pavi, NULL);
  149. if (!pavi->pgf) {
  150. lRet = AVIERR_INTERNAL;
  151. goto error;
  152. }
  153. pavi->avistream.fccHandler = 0;
  154. if (lParam2 < 2 || lParam2 > 256)
  155. lParam2 = 256;
  156. pavi->lp16to8 = GlobalAllocPtr(GMEM_MOVEABLE, 32768L);
  157. if (!pavi->lp16to8) {
  158. lRet = AVIERR_MEMORY;
  159. goto error;
  160. }
  161. lRet = AVIStreamMakePalette(pavi->pavi,
  162. AVIStreamLength(pavi->pavi) / 30,
  163. &pavi->hpal, pavi->lp16to8,
  164. (int) lParam2);
  165. pavi->lLastFrame = -1;
  166. error:
  167. return ResultFromScode(lRet);
  168. }
  169. ///////////////////////////////////////////////////////////////////////////
  170. //
  171. // PalMapStreamAddRef()
  172. //
  173. // increase the reference count of the stream
  174. //
  175. ///////////////////////////////////////////////////////////////////////////
  176. ULONG STDMETHODCALLTYPE PalMapStreamAddRef(PAVISTREAM ps)
  177. {
  178. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  179. return ++pavi->ulRefCount;
  180. }
  181. ///////////////////////////////////////////////////////////////////////////
  182. //
  183. // PalMapStreamRelease()
  184. //
  185. // close a PalMapStream stream
  186. //
  187. ///////////////////////////////////////////////////////////////////////////
  188. ULONG STDMETHODCALLTYPE PalMapStreamRelease(PAVISTREAM ps)
  189. {
  190. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  191. if (--pavi->ulRefCount)
  192. return pavi->ulRefCount;
  193. if (pavi->pgf)
  194. AVIStreamGetFrameClose(pavi->pgf);
  195. pavi->pgf = 0;
  196. if (pavi->pavi)
  197. AVIStreamClose(pavi->pavi);
  198. pavi->pavi = 0;
  199. if (pavi->lp16to8) {
  200. GlobalFreePtr(pavi->lp16to8);
  201. pavi->lp16to8 = 0;
  202. }
  203. if (pavi->hpal) {
  204. DeleteObject(pavi->hpal);
  205. pavi->hpal = 0;
  206. }
  207. if (pavi->hdibLast) {
  208. GlobalFree(pavi->hdibLast);
  209. pavi->hdibLast = 0;
  210. }
  211. GlobalFreePtr(pavi);
  212. return 0;
  213. }
  214. ///////////////////////////////////////////////////////////////////////////
  215. ///////////////////////////////////////////////////////////////////////////
  216. HRESULT STDMETHODCALLTYPE PalMapStreamReadFormat(PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat)
  217. {
  218. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  219. LPBITMAPINFOHEADER lpbi;
  220. LONG lSize;
  221. PalMapStreamRead(ps, lPos, 1, NULL, 0, NULL, NULL);
  222. if (pavi->hdibLast == 0)
  223. return ResultFromScode(AVIERR_INTERNAL);
  224. lpbi = (LPBITMAPINFOHEADER) GlobalLock(pavi->hdibLast);
  225. lSize = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
  226. if (lpFormat)
  227. hmemcpy(lpFormat, lpbi, min(*lpcbFormat, lSize));
  228. *lpcbFormat = lSize;
  229. return 0;
  230. }
  231. LONG STDMETHODCALLTYPE PalMapStreamFindKeyFrame(PAVISTREAM ps, LONG lPos, LONG lFlags)
  232. {
  233. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  234. return lPos;
  235. }
  236. ///////////////////////////////////////////////////////////////////////////
  237. ///////////////////////////////////////////////////////////////////////////
  238. HRESULT STDMETHODCALLTYPE PalMapStreamInfo(PAVISTREAM ps, AVISTREAMINFO FAR * psi, LONG lSize)
  239. {
  240. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  241. if (psi)
  242. hmemcpy(psi, &pavi->avistream, min(lSize, sizeof(pavi->avistream)));
  243. return 0;
  244. }
  245. ///////////////////////////////////////////////////////////////////////////
  246. ///////////////////////////////////////////////////////////////////////////
  247. HRESULT STDMETHODCALLTYPE PalMapStreamRead(PAVISTREAM ps,
  248. LONG lStart,
  249. LONG lSamples,
  250. LPVOID lpBuffer,
  251. LONG cbBuffer,
  252. LONG FAR * plBytes,
  253. LONG FAR * plSamples)
  254. {
  255. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  256. LPBITMAPINFOHEADER lpbi;
  257. LPVOID lp;
  258. if (lStart != pavi->lLastFrame) {
  259. pavi->lLastFrame = -1;
  260. lpbi = AVIStreamGetFrame(pavi->pgf, lStart);
  261. if (!lpbi)
  262. goto ReadNothing;
  263. if (pavi->hdibLast) {
  264. GlobalFree(pavi->hdibLast);
  265. pavi->hdibLast = 0;
  266. }
  267. pavi->hdibLast = DibReduce(lpbi, NULL, pavi->hpal, pavi->lp16to8);
  268. pavi->lLastFrame = lStart;
  269. }
  270. lpbi = (LPBITMAPINFOHEADER) GlobalLock(pavi->hdibLast);
  271. //
  272. // a NULL buffer means return the size buffer needed to read
  273. // the given sample.
  274. //
  275. lp = (LPBYTE) lpbi + lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
  276. if (plBytes)
  277. *plBytes = lpbi->biSizeImage;
  278. if (plSamples)
  279. *plSamples = 1;
  280. if (lpBuffer) {
  281. if (cbBuffer >= (LONG) lpbi->biSizeImage)
  282. hmemcpy(lpBuffer, lp, lpbi->biSizeImage);
  283. else
  284. return ResultFromScode(AVIERR_BUFFERTOOSMALL);
  285. }
  286. return 0;
  287. ReadNothing:
  288. if (plBytes)
  289. *plBytes = 0;
  290. if (plSamples)
  291. *plSamples = 0;
  292. return ResultFromScode(AVIERR_BUFFERTOOSMALL);
  293. }
  294. //
  295. //
  296. // Extra unimplemented functions.....
  297. //
  298. //
  299. //
  300. HRESULT STDMETHODCALLTYPE PalMapStreamQueryInterface(PAVISTREAM ps, REFIID riid, LPVOID FAR* ppvObj)
  301. {
  302. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  303. return ResultFromScode(AVIERR_UNSUPPORTED);
  304. }
  305. HRESULT STDMETHODCALLTYPE PalMapStreamReadData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG FAR *lpcb)
  306. {
  307. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  308. return ResultFromScode(AVIERR_UNSUPPORTED);
  309. }
  310. HRESULT STDMETHODCALLTYPE PalMapStreamSetFormat (PAVISTREAM ps, LONG lPos, LPVOID lpFormat, LONG cbFormat)
  311. {
  312. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  313. return ResultFromScode(AVIERR_UNSUPPORTED);
  314. }
  315. HRESULT STDMETHODCALLTYPE PalMapStreamWriteData (PAVISTREAM ps, DWORD fcc, LPVOID lp, LONG cb)
  316. {
  317. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  318. return ResultFromScode(AVIERR_UNSUPPORTED);
  319. }
  320. HRESULT STDMETHODCALLTYPE PalMapStreamWrite (PAVISTREAM ps, LONG lStart, LONG lSamples, LPVOID lpBuffer, LONG cbBuffer, DWORD dwFlags, LONG FAR *plSampWritten, LONG FAR *plBytesWritten)
  321. {
  322. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  323. return ResultFromScode(AVIERR_UNSUPPORTED);
  324. }
  325. HRESULT STDMETHODCALLTYPE PalMapStreamDelete (PAVISTREAM ps, LONG lStart, LONG lSamples)
  326. {
  327. PPALMAPSTREAM pavi = (PPALMAPSTREAM) ps;
  328. return ResultFromScode(AVIERR_UNSUPPORTED);
  329. }