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.

499 lines
13 KiB

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. // handle AVI RLE files with custom code.
  4. //
  5. // use this code to deal with .AVI files without the MCIAVI runtime
  6. //
  7. // restrictions:
  8. // AVI file must be a simple DIB format (RLE or none)
  9. // AVI file must fit into memory.
  10. //
  11. // ToddLa
  12. //
  13. //////////////////////////////////////////////////////////////////////////
  14. #include "ctlspriv.h"
  15. extern "C" {
  16. #include "rlefile.h"
  17. }
  18. #include <lendian.hpp>
  19. extern "C"
  20. BOOL RleFile_Init(RLEFILE *prle, LPVOID pFile, HANDLE hRes, DWORD dwFileLen);
  21. //////////////////////////////////////////////////////////////////////////
  22. //
  23. //////////////////////////////////////////////////////////////////////////
  24. LPVOID LoadFile(LPCTSTR szFile, DWORD * pFileLength)
  25. {
  26. LPVOID pFile;
  27. HANDLE hFile;
  28. HANDLE h;
  29. DWORD FileLength;
  30. hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL,
  31. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  32. if (hFile == INVALID_HANDLE_VALUE)
  33. return 0;
  34. FileLength = (LONG)GetFileSize(hFile, NULL);
  35. if (pFileLength)
  36. *pFileLength = FileLength ;
  37. h = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  38. if (!h)
  39. {
  40. CloseHandle(hFile);
  41. return 0;
  42. }
  43. pFile = MapViewOfFile(h, FILE_MAP_READ, 0, 0, 0);
  44. CloseHandle(hFile);
  45. CloseHandle(h);
  46. if (pFile == NULL)
  47. return 0;
  48. return pFile;
  49. }
  50. //////////////////////////////////////////////////////////////////////////
  51. //
  52. // RleFile_OpenFromFile
  53. //
  54. // load a .AVI file into memory and setup all of our pointers so we
  55. // know how to deal with it.
  56. //
  57. //////////////////////////////////////////////////////////////////////////
  58. extern "C"
  59. BOOL RleFile_OpenFromFile(RLEFILE *prle, LPCTSTR szFile)
  60. {
  61. DWORD dwFileLen;
  62. LPVOID pFile;
  63. // MAKEINTRESOURCE() things can't come from files
  64. if (IS_INTRESOURCE(szFile))
  65. return FALSE;
  66. if (pFile = LoadFile(szFile, &dwFileLen))
  67. return RleFile_Init(prle, pFile, NULL, dwFileLen);
  68. else
  69. return FALSE;
  70. }
  71. //////////////////////////////////////////////////////////////////////////
  72. //
  73. // RleFile_OpenFromResource
  74. //
  75. // load a .AVI file into memory and setup all of our pointers so we
  76. // know how to deal with it.
  77. //
  78. //////////////////////////////////////////////////////////////////////////
  79. extern "C"
  80. BOOL RleFile_OpenFromResource(RLEFILE *prle, HINSTANCE hInstance, LPCTSTR szName, LPCTSTR szType)
  81. {
  82. HRSRC h;
  83. HANDLE hRes;
  84. // not a MAKEINTRESOURCE(), and points to NULL
  85. if (!IS_INTRESOURCE(szName) && (*szName == 0))
  86. return FALSE;
  87. h = FindResource(hInstance, szName, szType);
  88. if (h == NULL)
  89. return FALSE;
  90. if (hRes = LoadResource(hInstance, h))
  91. return RleFile_Init(prle, LockResource(hRes), hRes, 0);
  92. else
  93. return FALSE;
  94. }
  95. //////////////////////////////////////////////////////////////////////////
  96. //
  97. // RleFile_Close
  98. //
  99. // nuke all stuff we did to open the file.
  100. //
  101. //////////////////////////////////////////////////////////////////////////
  102. extern "C"
  103. BOOL RleFile_Close(RLEFILE *prle)
  104. {
  105. if (prle->hpal)
  106. DeleteObject(prle->hpal);
  107. if (prle->pFile)
  108. {
  109. if (prle->hRes)
  110. {
  111. FreeResource(prle->hRes);
  112. }
  113. else
  114. UnmapViewOfFile(prle->pFile);
  115. }
  116. prle->hpal = NULL;
  117. prle->pFile = NULL;
  118. prle->hRes = NULL;
  119. prle->pMainHeader = NULL;
  120. prle->pStream = NULL;
  121. prle->pFormat = NULL;
  122. prle->pMovie = NULL;
  123. prle->pIndex = NULL;
  124. return TRUE;
  125. }
  126. //////////////////////////////////////////////////////////////////////////
  127. //
  128. // RleFile_Init
  129. //
  130. //////////////////////////////////////////////////////////////////////////
  131. extern "C"
  132. BOOL RleFile_Init(RLEFILE *prle, LPVOID pFile, HANDLE hRes, DWORD dwFileLen)
  133. {
  134. DWORD_LENDIAN UNALIGNED *pdw;
  135. DWORD_LENDIAN UNALIGNED *pdwEnd;
  136. DWORD dwRiff;
  137. DWORD dwType;
  138. DWORD dwLength;
  139. int stream;
  140. if (prle->pFile == pFile)
  141. return TRUE;
  142. RleFile_Close(prle);
  143. prle->pFile = pFile;
  144. prle->hRes = hRes;
  145. if (prle->pFile == NULL)
  146. return FALSE;
  147. //
  148. // now that the file is in memory walk the memory image filling in
  149. // interesting stuff.
  150. //
  151. pdw = (DWORD_LENDIAN UNALIGNED *)prle->pFile;
  152. dwRiff = *pdw++;
  153. dwLength = *pdw++;
  154. dwType = *pdw++;
  155. if ((dwFileLen > 0) && (dwLength > dwFileLen)) {
  156. // File is physically shorter than the length written in its header.
  157. // Can't handle it.
  158. goto exit;
  159. }
  160. if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  161. goto exit; // not even a RIFF file
  162. if (dwType != formtypeAVI)
  163. goto exit; // not a AVI file
  164. pdwEnd = (DWORD_LENDIAN UNALIGNED *)((BYTE PTR *)pdw + dwLength-4);
  165. stream = 0;
  166. while (pdw < pdwEnd)
  167. {
  168. dwType = *pdw++;
  169. dwLength = *pdw++;
  170. switch (dwType)
  171. {
  172. case mmioFOURCC('L', 'I', 'S', 'T'):
  173. dwType = *pdw++;
  174. dwLength -= 4;
  175. switch (dwType)
  176. {
  177. case listtypeAVIMOVIE:
  178. prle->pMovie = (LPVOID)pdw;
  179. break;
  180. case listtypeSTREAMHEADER:
  181. case listtypeAVIHEADER:
  182. dwLength = 0; // decend
  183. break;
  184. default:
  185. break; // ignore
  186. }
  187. break;
  188. case ckidAVIMAINHDR:
  189. {
  190. prle->pMainHeader = (MainAVIHeader PTR *)pdw;
  191. prle->NumFrames = (int)prle->pMainHeader->dwTotalFrames;
  192. prle->Width = (int)prle->pMainHeader->dwWidth;
  193. prle->Height = (int)prle->pMainHeader->dwHeight;
  194. prle->Rate = (int)(prle->pMainHeader->dwMicroSecPerFrame/1000);
  195. if (prle->pMainHeader->dwInitialFrames != 0)
  196. goto exit;
  197. if (prle->pMainHeader->dwStreams > 2)
  198. goto exit;
  199. }
  200. break;
  201. case ckidSTREAMHEADER:
  202. {
  203. stream++;
  204. if (prle->pStream != NULL)
  205. break;
  206. if (((AVIStreamHeader PTR *)pdw)->fccType != streamtypeVIDEO)
  207. break;
  208. prle->iStream = stream-1;
  209. prle->pStream = (AVIStreamHeader PTR*)pdw;
  210. if (prle->pStream->dwFlags & AVISF_VIDEO_PALCHANGES)
  211. goto exit;
  212. }
  213. break;
  214. case ckidSTREAMFORMAT:
  215. if (prle->pFormat != NULL)
  216. break;
  217. if (prle->pStream == NULL)
  218. break;
  219. prle->pFormat = (LPBITMAPINFOHEADER)pdw;
  220. if (prle->pFormat->biSize != sizeof(BITMAPINFOHEADER))
  221. goto exit;
  222. if (prle->pFormat->biCompression != 0 &&
  223. prle->pFormat->biCompression != BI_RLE8)
  224. goto exit;
  225. if (prle->pFormat->biWidth != prle->Width)
  226. goto exit;
  227. if (prle->pFormat->biHeight != prle->Height)
  228. goto exit;
  229. hmemcpy(&prle->bi, prle->pFormat, dwLength);
  230. prle->bi.biSizeImage = 0;
  231. prle->FullSizeImage = ((prle->bi.biWidth * prle->bi.biBitCount + 31) & ~31)/8U * prle->bi.biHeight;
  232. break;
  233. case ckidAVINEWINDEX:
  234. // we dont convert indexes because we dont know how many there are
  235. // but we will have to convert each usage of it
  236. prle->pIndex = (AVIINDEXENTRY PTR *)pdw;
  237. break;
  238. }
  239. pdw = (DWORD_LENDIAN *)((BYTE PTR *)pdw + ((dwLength+1)&~1));
  240. }
  241. //
  242. // if the file has nothing in it we care about get out, note
  243. // we dont need a index, we do need some data though.
  244. //
  245. if (prle->NumFrames == 0 ||
  246. prle->pMainHeader == NULL ||
  247. prle->pStream == NULL ||
  248. prle->pFormat == NULL ||
  249. prle->pMovie == NULL )
  250. {
  251. goto exit;
  252. }
  253. //
  254. // if we cared about a palette we would create it here.
  255. //
  256. //
  257. // file open'ed ok seek to the first frame.
  258. //
  259. prle->iFrame = -42;
  260. RleFile_Seek(prle, 0);
  261. return TRUE;
  262. exit:
  263. RleFile_Close(prle);
  264. return FALSE;
  265. }
  266. //////////////////////////////////////////////////////////////////////////
  267. //
  268. // RleFile_ChangeColor
  269. //
  270. // change the color table of the AVI
  271. //
  272. //////////////////////////////////////////////////////////////////////////
  273. extern "C"
  274. BOOL RleFile_ChangeColor(RLEFILE *prle, COLORREF rgbS, COLORREF rgbD)
  275. {
  276. DWORD dwS;
  277. DWORD dwD;
  278. DWORD PTR *ColorTable;
  279. int i;
  280. dwS = RGB(GetBValue(rgbS), GetGValue(rgbS), GetRValue(rgbS));
  281. dwD = RGB(GetBValue(rgbD), GetGValue(rgbD), GetRValue(rgbD));
  282. if (prle == NULL || prle->pFormat == NULL)
  283. return FALSE;
  284. ColorTable = (DWORD PTR *)((BYTE PTR *)&prle->bi + prle->bi.biSize);
  285. for (i=0; i<(int)prle->bi.biClrUsed; i++)
  286. {
  287. if (ColorTable[i] == dwS)
  288. ColorTable[i] = dwD;
  289. }
  290. return TRUE;
  291. }
  292. //////////////////////////////////////////////////////////////////////////
  293. //
  294. // RleFile_Seek
  295. //
  296. // find the data for the specifed frame.
  297. //
  298. //////////////////////////////////////////////////////////////////////////
  299. extern "C"
  300. BOOL RleFile_Seek(RLEFILE *prle, int iFrame)
  301. {
  302. int n;
  303. if (prle == NULL || prle->pMovie == NULL)
  304. return FALSE;
  305. if (iFrame >= prle->NumFrames)
  306. return FALSE;
  307. if (iFrame < 0)
  308. return FALSE;
  309. if (iFrame == prle->iFrame)
  310. return TRUE;
  311. if (prle->iFrame >= 0 && prle->iFrame < iFrame)
  312. {
  313. n = prle->nFrame; // start where you left off last time
  314. }
  315. else
  316. {
  317. n = -1; // start at the begining
  318. prle->iFrame = -1; // current frame
  319. prle->iKeyFrame = 0; // current key
  320. }
  321. while (prle->iFrame < iFrame)
  322. {
  323. n++;
  324. if (StreamFromFOURCC(*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].ckid)) == (UINT)prle->iStream)
  325. {
  326. prle->iFrame++; // new frame
  327. if ((long)(*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].dwFlags)) & AVIIF_KEYFRAME)
  328. prle->iKeyFrame = prle->iFrame; /* // new key frame */
  329. }
  330. }
  331. prle->nFrame = n;
  332. /* warning this points to bitmap bits in wintel format ! */
  333. prle->pFrame = (BYTE PTR *)prle->pMovie +
  334. (int)(*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].dwChunkOffset)) + 4;
  335. prle->cbFrame = *(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].dwChunkLength);
  336. ASSERT( (DWORD)(*(DWORD_LENDIAN UNALIGNED *)&(((DWORD PTR *)prle->pFrame)[-1])) == (DWORD)prle->cbFrame);
  337. ASSERT( (DWORD)(*(DWORD_LENDIAN UNALIGNED *)&(((DWORD PTR *)prle->pFrame)[-2])) == (DWORD)*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].ckid));
  338. prle->bi.biSizeImage = prle->cbFrame;
  339. if (prle->cbFrame == prle->FullSizeImage)
  340. prle->bi.biCompression = 0;
  341. else
  342. prle->bi.biCompression = BI_RLE8;
  343. return TRUE;
  344. }
  345. //////////////////////////////////////////////////////////////////////////
  346. //
  347. // RleFile_Paint
  348. //
  349. // draw the specifed frame, makes sure the entire frame is updated
  350. // dealing with non-key frames correctly.
  351. //
  352. //////////////////////////////////////////////////////////////////////////
  353. extern "C"
  354. BOOL RleFile_Paint(RLEFILE *prle, HDC hdc, int iFrame, int x, int y)
  355. {
  356. int i;
  357. BOOL f;
  358. if (prle == NULL || prle->pMovie == NULL)
  359. return FALSE;
  360. if (f = RleFile_Seek(prle, iFrame))
  361. {
  362. iFrame = prle->iFrame;
  363. for (i=prle->iKeyFrame; i<=iFrame; i++)
  364. RleFile_Draw(prle, hdc, i, x, y);
  365. }
  366. return f;
  367. }
  368. //////////////////////////////////////////////////////////////////////////
  369. //
  370. // RleFile_Draw
  371. //
  372. // draw the data for a specifed frame
  373. //
  374. //////////////////////////////////////////////////////////////////////////
  375. extern "C"
  376. BOOL RleFile_Draw(RLEFILE *prle, HDC hdc, int iFrame, int x, int y)
  377. {
  378. BOOL f;
  379. if (prle == NULL || prle->pMovie == NULL)
  380. return FALSE;
  381. if (prle->hpal)
  382. {
  383. SelectPalette(hdc, prle->hpal, FALSE);
  384. RealizePalette(hdc);
  385. }
  386. if (f = RleFile_Seek(prle, iFrame))
  387. {
  388. if (prle->cbFrame > 0)
  389. {
  390. StretchDIBits(hdc,
  391. x, y, prle->Width, prle->Height,
  392. 0, 0, prle->Width, prle->Height,
  393. prle->pFrame, (LPBITMAPINFO)&prle->bi,
  394. DIB_RGB_COLORS, SRCCOPY);
  395. }
  396. }
  397. return f;
  398. }