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.

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