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.

643 lines
16 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. #ifdef UNIX
  19. #include <mwavi.h>
  20. #include "unixstuff.h"
  21. #endif
  22. #include <lendian.hpp>
  23. extern "C"
  24. BOOL RleFile_Init(RLEFILE *prle, LPVOID pFile, HANDLE hRes, DWORD dwFileLen);
  25. //////////////////////////////////////////////////////////////////////////
  26. //
  27. //////////////////////////////////////////////////////////////////////////
  28. LPVOID LoadFile(LPCTSTR szFile, DWORD * pFileLength)
  29. {
  30. LPVOID pFile;
  31. HANDLE hFile;
  32. HANDLE h;
  33. DWORD FileLength;
  34. #ifdef WIN32
  35. #ifndef MAINWIN
  36. hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL,
  37. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  38. #else
  39. // sunos5 does not want to map NFS files when there is locking on them
  40. hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
  41. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  42. #endif
  43. if (hFile == INVALID_HANDLE_VALUE)
  44. return 0;
  45. FileLength = (LONG)GetFileSize(hFile, NULL);
  46. if (pFileLength)
  47. *pFileLength = FileLength ;
  48. h = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  49. if (!h)
  50. {
  51. CloseHandle(hFile);
  52. return 0;
  53. }
  54. pFile = MapViewOfFile(h, FILE_MAP_READ, 0, 0, 0);
  55. CloseHandle(hFile);
  56. CloseHandle(h);
  57. if (pFile == NULL)
  58. return 0;
  59. #else
  60. hFile = (HANDLE)_lopen(szFile, OF_READ);
  61. if (hFile == (HANDLE)-1)
  62. return 0;
  63. FileLength = _llseek((int)hFile, 0, SEEK_END);
  64. _llseek((int)hFile, 0, SEEK_SET);
  65. pFile = GlobalAllocPtr(GHND, FileLength);
  66. if (pFile && _hread((int)hFile, pFile, FileLength) != FileLength)
  67. {
  68. GlobalFreePtr(pFile);
  69. pFile = NULL;
  70. }
  71. _lclose((int)hFile);
  72. #endif
  73. return pFile;
  74. }
  75. //////////////////////////////////////////////////////////////////////////
  76. //
  77. // RleFile_OpenFromFile
  78. //
  79. // load a .AVI file into memory and setup all of our pointers so we
  80. // know how to deal with it.
  81. //
  82. //////////////////////////////////////////////////////////////////////////
  83. extern "C"
  84. BOOL RleFile_OpenFromFile(RLEFILE *prle, LPCTSTR szFile)
  85. {
  86. DWORD dwFileLen;
  87. LPVOID pFile;
  88. // MAKEINTRESOURCE() things can't come from files
  89. if (IS_INTRESOURCE(szFile))
  90. return FALSE;
  91. if (pFile = LoadFile(szFile, &dwFileLen))
  92. return RleFile_Init(prle, pFile, NULL, dwFileLen);
  93. else
  94. return FALSE;
  95. }
  96. //////////////////////////////////////////////////////////////////////////
  97. //
  98. // RleFile_OpenFromResource
  99. //
  100. // load a .AVI file into memory and setup all of our pointers so we
  101. // know how to deal with it.
  102. //
  103. //////////////////////////////////////////////////////////////////////////
  104. extern "C"
  105. BOOL RleFile_OpenFromResource(RLEFILE *prle, HINSTANCE hInstance, LPCTSTR szName, LPCTSTR szType)
  106. {
  107. HRSRC h;
  108. HANDLE hRes;
  109. // not a MAKEINTRESOURCE(), and points to NULL
  110. #ifndef MAINWIN
  111. if (!IS_INTRESOURCE(szName) && (*szName == 0))
  112. return FALSE;
  113. #else
  114. if (!MwIsIntegerResource(szName) && (*szName == 0))
  115. return FALSE;
  116. #endif
  117. h = FindResource(hInstance, szName, szType);
  118. if (h == NULL)
  119. return FALSE;
  120. if (hRes = LoadResource(hInstance, h))
  121. return RleFile_Init(prle, LockResource(hRes), hRes, 0);
  122. else
  123. return FALSE;
  124. }
  125. //////////////////////////////////////////////////////////////////////////
  126. //
  127. // RleFile_Close
  128. //
  129. // nuke all stuff we did to open the file.
  130. //
  131. //////////////////////////////////////////////////////////////////////////
  132. extern "C"
  133. BOOL RleFile_Close(RLEFILE *prle)
  134. {
  135. if (prle->hpal)
  136. DeleteObject(prle->hpal);
  137. if (prle->pFile)
  138. {
  139. #ifdef WIN32
  140. if (prle->hRes)
  141. {
  142. #ifdef UNIX
  143. UnlockResource(prle->hRes);
  144. #endif
  145. FreeResource(prle->hRes);
  146. }
  147. else
  148. UnmapViewOfFile(prle->pFile);
  149. #else
  150. GlobalFreePtr(prle->pFile);
  151. #endif
  152. }
  153. #ifdef UNIX
  154. CHECK_FREE( prle->pStream );
  155. CHECK_FREE( prle->pFormat );
  156. #endif
  157. prle->hpal = NULL;
  158. prle->pFile = NULL;
  159. prle->hRes = NULL;
  160. prle->pMainHeader = NULL;
  161. prle->pStream = NULL;
  162. prle->pFormat = NULL;
  163. prle->pMovie = NULL;
  164. prle->pIndex = NULL;
  165. return TRUE;
  166. }
  167. //////////////////////////////////////////////////////////////////////////
  168. //
  169. // RleFile_Init
  170. //
  171. //////////////////////////////////////////////////////////////////////////
  172. extern "C"
  173. BOOL RleFile_Init(RLEFILE *prle, LPVOID pFile, HANDLE hRes, DWORD dwFileLen)
  174. {
  175. DWORD_LENDIAN UNALIGNED *pdw;
  176. DWORD_LENDIAN UNALIGNED *pdwEnd;
  177. DWORD dwRiff;
  178. DWORD dwType;
  179. DWORD dwLength;
  180. int stream;
  181. if (prle->pFile == pFile)
  182. return TRUE;
  183. RleFile_Close(prle);
  184. prle->pFile = pFile;
  185. prle->hRes = hRes;
  186. if (prle->pFile == NULL)
  187. return FALSE;
  188. //
  189. // now that the file is in memory walk the memory image filling in
  190. // interesting stuff.
  191. //
  192. pdw = (DWORD_LENDIAN UNALIGNED *)prle->pFile;
  193. dwRiff = *pdw++;
  194. dwLength = *pdw++;
  195. dwType = *pdw++;
  196. #ifndef UNIX
  197. if ((dwFileLen > 0) && (dwLength > dwFileLen)) {
  198. // File is physically shorter than the length written in its header.
  199. // Can't handle it.
  200. goto exit;
  201. }
  202. #endif
  203. if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  204. goto exit; // not even a RIFF file
  205. if (dwType != formtypeAVI)
  206. goto exit; // not a AVI file
  207. pdwEnd = (DWORD_LENDIAN UNALIGNED *)((BYTE PTR *)pdw + dwLength-4);
  208. stream = 0;
  209. while (pdw < pdwEnd)
  210. {
  211. dwType = *pdw++;
  212. dwLength = *pdw++;
  213. switch (dwType)
  214. {
  215. case mmioFOURCC('L', 'I', 'S', 'T'):
  216. dwType = *pdw++;
  217. dwLength -= 4;
  218. switch (dwType)
  219. {
  220. case listtypeAVIMOVIE:
  221. prle->pMovie = (LPVOID)pdw;
  222. break;
  223. case listtypeSTREAMHEADER:
  224. case listtypeAVIHEADER:
  225. dwLength = 0; // decend
  226. break;
  227. default:
  228. break; // ignore
  229. }
  230. break;
  231. case ckidAVIMAINHDR:
  232. {
  233. #ifdef UNIX
  234. MainAVIHeader mavih;
  235. prle->pMainHeader=&mavih;
  236. MwReadMainAVIHeader( (BYTE*) pdw,
  237. sizeof(*prle->pMainHeader),
  238. prle->pMainHeader );
  239. #else
  240. prle->pMainHeader = (MainAVIHeader PTR *)pdw;
  241. #endif
  242. prle->NumFrames = (int)prle->pMainHeader->dwTotalFrames;
  243. prle->Width = (int)prle->pMainHeader->dwWidth;
  244. prle->Height = (int)prle->pMainHeader->dwHeight;
  245. prle->Rate = (int)(prle->pMainHeader->dwMicroSecPerFrame/1000);
  246. if (prle->pMainHeader->dwInitialFrames != 0)
  247. goto exit;
  248. if (prle->pMainHeader->dwStreams > 2)
  249. goto exit;
  250. }
  251. break;
  252. case ckidSTREAMHEADER:
  253. {
  254. #ifdef UNIX
  255. AVIStreamHeader *paviSH;
  256. #endif
  257. stream++;
  258. if (prle->pStream != NULL)
  259. break;
  260. #ifndef UNIX
  261. if (((AVIStreamHeader PTR *)pdw)->fccType != streamtypeVIDEO)
  262. break;
  263. #else
  264. paviSH = (AVIStreamHeader*) malloc(sizeof(AVIStreamHeader));
  265. if ( paviSH == NULL )
  266. break;
  267. MwReadAVIStreamHeader( (BYTE*) pdw,sizeof(*paviSH),paviSH );
  268. if (paviSH->fccType != streamtypeVIDEO) {
  269. CHECK_FREE( paviSH );
  270. break;
  271. }
  272. #endif
  273. prle->iStream = stream-1;
  274. #ifndef UNIX
  275. prle->pStream = (AVIStreamHeader PTR*)pdw;
  276. #else
  277. prle->pStream = paviSH;
  278. #endif
  279. if (prle->pStream->dwFlags & AVISF_VIDEO_PALCHANGES)
  280. goto exit;
  281. }
  282. break;
  283. case ckidSTREAMFORMAT:
  284. if (prle->pFormat != NULL)
  285. break;
  286. if (prle->pStream == NULL)
  287. break;
  288. #ifdef UNIX
  289. prle->pFormat = (LPBITMAPINFOHEADER) malloc( dwLength );
  290. if ( prle->pFormat == NULL )
  291. goto exit;
  292. MwReadBITMAPINFO( (BYTE*) pdw, dwLength,
  293. (BITMAPINFO*) prle->pFormat );
  294. #else
  295. prle->pFormat = (LPBITMAPINFOHEADER)pdw;
  296. #endif
  297. if (prle->pFormat->biSize != sizeof(BITMAPINFOHEADER))
  298. goto exit;
  299. if (prle->pFormat->biCompression != 0 &&
  300. prle->pFormat->biCompression != BI_RLE8)
  301. goto exit;
  302. if (prle->pFormat->biWidth != prle->Width)
  303. goto exit;
  304. if (prle->pFormat->biHeight != prle->Height)
  305. goto exit;
  306. hmemcpy(&prle->bi, prle->pFormat, dwLength);
  307. prle->bi.biSizeImage = 0;
  308. prle->FullSizeImage = ((prle->bi.biWidth * prle->bi.biBitCount + 31) & ~31)/8U * prle->bi.biHeight;
  309. break;
  310. case ckidAVINEWINDEX:
  311. // we dont convert indexes because we dont know how many there are
  312. // but we will have to convert each usage of it
  313. prle->pIndex = (AVIINDEXENTRY PTR *)pdw;
  314. break;
  315. }
  316. pdw = (DWORD_LENDIAN *)((BYTE PTR *)pdw + ((dwLength+1)&~1));
  317. }
  318. //
  319. // if the file has nothing in it we care about get out, note
  320. // we dont need a index, we do need some data though.
  321. //
  322. if (prle->NumFrames == 0 ||
  323. prle->pMainHeader == NULL ||
  324. prle->pStream == NULL ||
  325. prle->pFormat == NULL ||
  326. prle->pMovie == NULL )
  327. {
  328. goto exit;
  329. }
  330. //
  331. // if we cared about a palette we would create it here.
  332. //
  333. //
  334. // file open'ed ok seek to the first frame.
  335. //
  336. prle->iFrame = -42;
  337. RleFile_Seek(prle, 0);
  338. return TRUE;
  339. exit:
  340. RleFile_Close(prle);
  341. return FALSE;
  342. }
  343. //////////////////////////////////////////////////////////////////////////
  344. //
  345. // RleFile_ChangeColor
  346. //
  347. // change the color table of the AVI
  348. //
  349. //////////////////////////////////////////////////////////////////////////
  350. extern "C"
  351. BOOL RleFile_ChangeColor(RLEFILE *prle, COLORREF rgbS, COLORREF rgbD)
  352. {
  353. #ifndef UNIX
  354. DWORD dwS;
  355. DWORD dwD;
  356. DWORD PTR *ColorTable;
  357. int i;
  358. dwS = RGB(GetBValue(rgbS), GetGValue(rgbS), GetRValue(rgbS));
  359. dwD = RGB(GetBValue(rgbD), GetGValue(rgbD), GetRValue(rgbD));
  360. if (prle == NULL || prle->pFormat == NULL)
  361. return FALSE;
  362. ColorTable = (DWORD PTR *)((BYTE PTR *)&prle->bi + prle->bi.biSize);
  363. for (i=0; i<(int)prle->bi.biClrUsed; i++)
  364. {
  365. if (ColorTable[i] == dwS)
  366. ColorTable[i] = dwD;
  367. }
  368. return TRUE;
  369. #else
  370. RGBQUAD dwS;
  371. RGBQUAD dwD;
  372. RGBQUAD PTR *ColorTable;
  373. int i;
  374. dwS.rgbRed = GetRValue(rgbS);
  375. dwS.rgbGreen = GetGValue(rgbS);
  376. dwS.rgbBlue = GetBValue(rgbS);
  377. dwS.rgbReserved = 0;
  378. dwD.rgbRed = GetRValue(rgbD);
  379. dwD.rgbGreen = GetGValue(rgbD);
  380. dwD.rgbBlue = GetBValue(rgbD);
  381. // Support for CDE colormap index colors (davidd)
  382. dwD.rgbReserved = (BYTE)(rgbD >> 24);
  383. if (prle == NULL || prle->pFormat == NULL)
  384. return FALSE;
  385. ColorTable = (RGBQUAD PTR *)((BYTE PTR *)&prle->bi + prle->bi.biSize);
  386. for (i=0; i<(int)prle->bi.biClrUsed; i++)
  387. {
  388. if ((ColorTable[i].rgbRed == dwS.rgbRed) &&
  389. (ColorTable[i].rgbGreen == dwS.rgbGreen) &&
  390. (ColorTable[i].rgbBlue == dwS.rgbBlue)) {
  391. ColorTable[i] = dwD;
  392. }
  393. }
  394. return TRUE;
  395. #endif
  396. }
  397. //////////////////////////////////////////////////////////////////////////
  398. //
  399. // RleFile_Seek
  400. //
  401. // find the data for the specifed frame.
  402. //
  403. //////////////////////////////////////////////////////////////////////////
  404. extern "C"
  405. BOOL RleFile_Seek(RLEFILE *prle, int iFrame)
  406. {
  407. int n;
  408. if (prle == NULL || prle->pMovie == NULL)
  409. return FALSE;
  410. #if 0
  411. if (iFrame == FRAME_CURRENT)
  412. iFrame = prle->iFrame;
  413. if (iFrame == FRAME_NEXT)
  414. {
  415. iFrame = prle->iFrame+1;
  416. if (iFrame >= prle->NumFrames)
  417. iFrame = 0;
  418. }
  419. if (iFrame == FRAME_PREV)
  420. {
  421. iFrame = prle->iFrame-1;
  422. if (iFrame == -1)
  423. iFrame = prle->NumFrames-1;
  424. }
  425. #endif
  426. if (iFrame >= prle->NumFrames)
  427. return FALSE;
  428. if (iFrame < 0)
  429. return FALSE;
  430. if (iFrame == prle->iFrame)
  431. return TRUE;
  432. if (prle->iFrame >= 0 && prle->iFrame < iFrame)
  433. {
  434. n = prle->nFrame; // start where you left off last time
  435. }
  436. else
  437. {
  438. n = -1; // start at the begining
  439. prle->iFrame = -1; // current frame
  440. prle->iKeyFrame = 0; // current key
  441. }
  442. while (prle->iFrame < iFrame)
  443. {
  444. n++;
  445. if (StreamFromFOURCC(*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].ckid)) == (UINT)prle->iStream)
  446. {
  447. prle->iFrame++; // new frame
  448. if ((long)(*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].dwFlags)) & AVIIF_KEYFRAME)
  449. prle->iKeyFrame = prle->iFrame; /* // new key frame */
  450. }
  451. }
  452. prle->nFrame = n;
  453. /* warning this points to bitmap bits in wintel format ! */
  454. prle->pFrame = (BYTE PTR *)prle->pMovie +
  455. (int)(*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].dwChunkOffset)) + 4;
  456. prle->cbFrame = *(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].dwChunkLength);
  457. ASSERT( (DWORD)(*(DWORD_LENDIAN UNALIGNED *)&(((DWORD PTR *)prle->pFrame)[-1])) == (DWORD)prle->cbFrame);
  458. ASSERT( (DWORD)(*(DWORD_LENDIAN UNALIGNED *)&(((DWORD PTR *)prle->pFrame)[-2])) == (DWORD)*(DWORD_LENDIAN UNALIGNED *)(&prle->pIndex[n].ckid));
  459. prle->bi.biSizeImage = prle->cbFrame;
  460. if (prle->cbFrame == prle->FullSizeImage)
  461. prle->bi.biCompression = 0;
  462. else
  463. prle->bi.biCompression = BI_RLE8;
  464. return TRUE;
  465. }
  466. //////////////////////////////////////////////////////////////////////////
  467. //
  468. // RleFile_Paint
  469. //
  470. // draw the specifed frame, makes sure the entire frame is updated
  471. // dealing with non-key frames correctly.
  472. //
  473. //////////////////////////////////////////////////////////////////////////
  474. extern "C"
  475. BOOL RleFile_Paint(RLEFILE *prle, HDC hdc, int iFrame, int x, int y)
  476. {
  477. int i;
  478. BOOL f;
  479. if (prle == NULL || prle->pMovie == NULL)
  480. return FALSE;
  481. if (f = RleFile_Seek(prle, iFrame))
  482. {
  483. iFrame = prle->iFrame;
  484. for (i=prle->iKeyFrame; i<=iFrame; i++)
  485. RleFile_Draw(prle, hdc, i, x, y);
  486. }
  487. return f;
  488. }
  489. //////////////////////////////////////////////////////////////////////////
  490. //
  491. // RleFile_Draw
  492. //
  493. // draw the data for a specifed frame
  494. //
  495. //////////////////////////////////////////////////////////////////////////
  496. extern "C"
  497. BOOL RleFile_Draw(RLEFILE *prle, HDC hdc, int iFrame, int x, int y)
  498. {
  499. BOOL f;
  500. if (prle == NULL || prle->pMovie == NULL)
  501. return FALSE;
  502. if (prle->hpal)
  503. {
  504. SelectPalette(hdc, prle->hpal, FALSE);
  505. RealizePalette(hdc);
  506. }
  507. if (f = RleFile_Seek(prle, iFrame))
  508. {
  509. if (prle->cbFrame > 0)
  510. {
  511. StretchDIBits(hdc,
  512. x, y, prle->Width, prle->Height,
  513. 0, 0, prle->Width, prle->Height,
  514. prle->pFrame, (LPBITMAPINFO)&prle->bi,
  515. DIB_RGB_COLORS, SRCCOPY);
  516. }
  517. }
  518. return f;
  519. }