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.

1234 lines
38 KiB

  1. /*----------------------------------------------------------------------+
  2. | msvidc.c - Microsoft Video 1 Compressor |
  3. | |
  4. | Copyright (c) 1990-1995 Microsoft Corporation. |
  5. | Portions Copyright Media Vision Inc. |
  6. | All Rights Reserved. |
  7. | |
  8. | You have a non-exclusive, worldwide, royalty-free, and perpetual |
  9. | license to use this source code in developing hardware, software |
  10. | (limited to drivers and other software required for hardware |
  11. | functionality), and firmware for video display and/or processing |
  12. | boards. Microsoft makes no warranties, express or implied, with |
  13. | respect to the Video 1 codec, including without limitation warranties |
  14. | of merchantability or fitness for a particular purpose. Microsoft |
  15. | shall not be liable for any damages whatsoever, including without |
  16. | limitation consequential damages arising from your use of the Video 1 |
  17. | codec. |
  18. | |
  19. | |
  20. +----------------------------------------------------------------------*/
  21. #include <win32.h>
  22. #include <ole2.h>
  23. #include <mmsystem.h>
  24. #ifndef _INC_COMPDDK
  25. #define _INC_COMPDDK 50 /* version number */
  26. #endif
  27. #include <vfw.h>
  28. #ifdef _WIN32
  29. #define abs(x) ((x) < 0 ? -(x) : (x))
  30. #endif
  31. #ifdef _WIN32
  32. #include <memory.h> /* for memcpy */
  33. #endif
  34. #ifdef _WIN32
  35. #define _FPInit() 0
  36. #define _FPTerm(x)
  37. #else
  38. void _acrtused2(void) {}
  39. extern LPVOID WINAPI _FPInit(void);
  40. extern void WINAPI _FPTerm(LPVOID);
  41. #endif
  42. #include "msvidc.h"
  43. #ifdef _WIN32
  44. #include "profile.h"
  45. #endif
  46. #ifndef _WIN32
  47. static BOOL gf286 = FALSE;
  48. #endif
  49. #define FOURCC_MSVC mmioFOURCC('M','S','V','C')
  50. #define FOURCC_CRAM mmioFOURCC('C','R','A','M')
  51. #define FOURCC_Cram mmioFOURCC('C','r','a','m')
  52. #define TWOCC_XX aviTWOCC('d', 'c')
  53. #define QUALITY_DEFAULT 2500
  54. #define VERSION 0x00010000 // 1.0
  55. ICSTATE DefaultState = {75};
  56. INT_PTR FAR PASCAL _LOADDS ConfigureDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
  57. #ifndef _WIN32
  58. //
  59. // put the compress stuff in the "rare" segment
  60. //
  61. #pragma alloc_text(_TEXT, ConfigureDlgProc)
  62. #pragma alloc_text(_TEXT, CompressBegin)
  63. #pragma alloc_text(_TEXT, CompressQuery)
  64. #pragma alloc_text(_TEXT, CompressGetFormat)
  65. #pragma alloc_text(_TEXT, Compress)
  66. #pragma alloc_text(_TEXT, CompressGetSize)
  67. #pragma alloc_text(_TEXT, CompressEnd)
  68. #endif
  69. /*****************************************************************************
  70. * dither stuff..
  71. ****************************************************************************/
  72. #include <dith775.h>
  73. LPVOID lpDitherTable;
  74. //////////////////////////////////////////////////////////////////////////////
  75. //
  76. // Dither16InitScale()
  77. //
  78. //////////////////////////////////////////////////////////////////////////////
  79. #pragma optimize("", off)
  80. STATICFN LPVOID Dither16InitScale()
  81. {
  82. LPVOID p;
  83. LPBYTE pbLookup;
  84. LPWORD pwScale;
  85. UINT r,g,b;
  86. p = GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE, 32768l*2+64000);
  87. if (p == NULL)
  88. return NULL;
  89. pwScale = (LPWORD)p;
  90. for (r=0; r<32; r++)
  91. for (g=0; g<32; g++)
  92. for (b=0; b<32; b++)
  93. *pwScale++ = 1600 * r + 40 * g + b;
  94. pbLookup = (LPBYTE)(((WORD _huge *)p) + 32768l);
  95. for (r=0; r<40; r++)
  96. for (g=0; g<40; g++)
  97. for (b=0; b<40; b++)
  98. *pbLookup++ = lookup775[35*rlevel[r] + 5*glevel[g] + blevel[b]];
  99. return p;
  100. }
  101. #pragma optimize("", on)
  102. /*****************************************************************************
  103. ****************************************************************************/
  104. #ifndef _WIN32
  105. BOOL NEAR PASCAL VideoLoad(void)
  106. {
  107. gf286 = (BOOL)(GetWinFlags() & WF_CPU286);
  108. #ifdef DEBUG
  109. gf286 = GetProfileIntA("Debug", "cpu", gf286 ? 286 : 386) == 286;
  110. #endif
  111. return TRUE;
  112. }
  113. #endif
  114. /*****************************************************************************
  115. ****************************************************************************/
  116. void NEAR PASCAL VideoFree()
  117. {
  118. // CompressFrameFree(); // let compression stuff clean up...
  119. if (lpDitherTable != NULL) {
  120. GlobalFreePtr(lpDitherTable);
  121. lpDitherTable = NULL;
  122. }
  123. }
  124. /*****************************************************************************
  125. ****************************************************************************/
  126. INSTINFO * NEAR PASCAL VideoOpen(ICOPEN FAR * icinfo)
  127. {
  128. INSTINFO * pinst;
  129. //
  130. // refuse to open if we are not being opened as a Video compressor
  131. //
  132. if (icinfo->fccType != ICTYPE_VIDEO)
  133. return NULL;
  134. pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  135. if (!pinst) {
  136. icinfo->dwError = (DWORD)ICERR_MEMORY;
  137. return NULL;
  138. }
  139. //
  140. // init structure
  141. //
  142. pinst->dwFlags = icinfo->dwFlags;
  143. pinst->nCompress = 0;
  144. pinst->nDecompress = 0;
  145. pinst->nDraw = 0;
  146. //
  147. // set the default state.
  148. //
  149. SetState(pinst, NULL, 0);
  150. //
  151. // return success.
  152. //
  153. icinfo->dwError = ICERR_OK;
  154. return pinst;
  155. }
  156. /*****************************************************************************
  157. ****************************************************************************/
  158. LONG NEAR PASCAL VideoClose(INSTINFO * pinst)
  159. {
  160. while (pinst->nCompress > 0)
  161. CompressEnd(pinst);
  162. while (pinst->nDecompress > 0)
  163. DecompressEnd(pinst);
  164. while (pinst->nDraw > 0)
  165. DrawEnd(pinst);
  166. LocalFree((HLOCAL)pinst);
  167. return 1;
  168. }
  169. /*****************************************************************************
  170. ****************************************************************************/
  171. #ifndef QueryAbout
  172. BOOL NEAR PASCAL QueryAbout(INSTINFO * pinst)
  173. {
  174. return TRUE;
  175. }
  176. #endif
  177. LONG NEAR PASCAL About(INSTINFO * pinst, HWND hwnd)
  178. {
  179. char achDescription[128];
  180. char achAbout[64];
  181. LoadStringA(ghModule, IDS_DESCRIPTION, achDescription, sizeof(achDescription));
  182. LoadStringA(ghModule, IDS_ABOUT, achAbout, sizeof(achAbout));
  183. MessageBoxA(hwnd,achDescription,achAbout,
  184. MB_OK|MB_ICONINFORMATION);
  185. return ICERR_OK;
  186. }
  187. /*****************************************************************************
  188. ****************************************************************************/
  189. #ifndef QueryConfigure
  190. BOOL NEAR PASCAL QueryConfigure(INSTINFO * pinst)
  191. {
  192. return TRUE;
  193. }
  194. #endif
  195. LONG NEAR PASCAL Configure(INSTINFO * pinst, HWND hwnd)
  196. {
  197. return (LONG) DialogBoxParam(ghModule,TEXT("Configure"),hwnd,ConfigureDlgProc, (LONG_PTR)(UINT_PTR)pinst);
  198. }
  199. /*****************************************************************************
  200. ****************************************************************************/
  201. LONG NEAR PASCAL GetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  202. {
  203. if (pv == NULL || dwSize == 0)
  204. return sizeof(ICSTATE);
  205. if (dwSize < sizeof(ICSTATE))
  206. return 0;
  207. *((ICSTATE FAR *)pv) = pinst->CurrentState;
  208. // return number of bytes copied
  209. return sizeof(ICSTATE);
  210. }
  211. /*****************************************************************************
  212. ****************************************************************************/
  213. LONG NEAR PASCAL SetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  214. {
  215. if (pv == NULL)
  216. pinst->CurrentState = DefaultState;
  217. else if (dwSize == sizeof(ICSTATE))
  218. pinst->CurrentState = *((ICSTATE FAR *)pv);
  219. else
  220. return 0;
  221. // return number of bytes copied
  222. return sizeof(ICSTATE);
  223. }
  224. #if !defined NUMELMS
  225. #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
  226. #endif
  227. #if defined _WIN32 && !defined UNICODE
  228. int LoadUnicodeString(HINSTANCE hinst, UINT wID, LPWSTR lpBuffer, int cchBuffer)
  229. {
  230. char ach[128];
  231. int i;
  232. i = LoadString(hinst, wID, ach, sizeof(ach));
  233. if (i > 0)
  234. MultiByteToWideChar(CP_ACP, 0, ach, -1, lpBuffer, cchBuffer);
  235. return i;
  236. }
  237. #else
  238. #define LoadUnicodeString LoadString
  239. #endif
  240. /*****************************************************************************
  241. ****************************************************************************/
  242. LONG NEAR PASCAL GetInfo(INSTINFO * pinst, ICINFO FAR *icinfo, DWORD dwSize)
  243. {
  244. if (icinfo == NULL)
  245. return sizeof(ICINFO);
  246. if (dwSize < sizeof(ICINFO))
  247. return 0;
  248. icinfo->dwSize = sizeof(ICINFO);
  249. icinfo->fccType = ICTYPE_VIDEO;
  250. icinfo->fccHandler = FOURCC_MSVC;
  251. icinfo->dwFlags = VIDCF_QUALITY | // supports quality
  252. VIDCF_TEMPORAL; // supports inter-frame
  253. icinfo->dwVersion = VERSION;
  254. icinfo->dwVersionICM = ICVERSION;
  255. LoadUnicodeString(ghModule, IDS_DESCRIPTION, icinfo->szDescription, NUMELMS(icinfo->szDescription));
  256. LoadUnicodeString(ghModule, IDS_NAME, icinfo->szName, NUMELMS(icinfo->szName));
  257. return sizeof(ICINFO);
  258. }
  259. /*****************************************************************************
  260. ****************************************************************************/
  261. LONG FAR PASCAL CompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  262. {
  263. if (lpbiOut)
  264. DPF(("CompressQuery %dx%dx%d --> %dx%dx%d'%4.4hs'", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount, (int)lpbiOut->biWidth, (int)lpbiOut->biHeight, (int)lpbiOut->biBitCount, (LPSTR)&lpbiOut->biCompression));
  265. else
  266. DPF(("CompressQuery %dx%dx%d", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount));
  267. //
  268. // determine if the input DIB data is in a format we like.
  269. //
  270. if (lpbiIn == NULL ||
  271. !(lpbiIn->biBitCount == 8 ||
  272. lpbiIn->biBitCount == 16 ||
  273. lpbiIn->biBitCount == 24 ||
  274. lpbiIn->biBitCount == 32) ||
  275. lpbiIn->biPlanes != 1 ||
  276. lpbiIn->biWidth < 4 ||
  277. lpbiIn->biHeight < 4 ||
  278. lpbiIn->biCompression != BI_RGB)
  279. return ICERR_BADFORMAT;
  280. //
  281. // are we being asked to query just the input format?
  282. //
  283. if (lpbiOut == NULL)
  284. return ICERR_OK;
  285. //
  286. // make sure we can handle the format to compress to also.
  287. //
  288. if (!(lpbiOut->biCompression == FOURCC_MSVC || // must be 'MSVC' or 'CRAM'
  289. lpbiOut->biCompression == FOURCC_CRAM) ||
  290. !(lpbiOut->biBitCount == 16 || // must be 8 or 16
  291. lpbiOut->biBitCount == 8) ||
  292. (lpbiOut->biPlanes != 1) ||
  293. (lpbiOut->biWidth & ~3) != (lpbiIn->biWidth & ~3) || // must be 1:1 (no stretch)
  294. (lpbiOut->biHeight & ~3) != (lpbiIn->biHeight & ~3))
  295. return ICERR_BADFORMAT;
  296. return ICERR_OK;
  297. }
  298. /*****************************************************************************
  299. ****************************************************************************/
  300. LONG FAR PASCAL CompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  301. {
  302. LONG l;
  303. if (l = CompressQuery(pinst, lpbiIn, NULL))
  304. return l;
  305. if (lpbiIn->biBitCount == 8)
  306. {
  307. //
  308. // if lpbiOut == NULL then, return the size required to hold a output
  309. // format
  310. //
  311. DWORD dwClrUsed = lpbiIn->biClrUsed;
  312. if (dwClrUsed == 0) {
  313. dwClrUsed = 256;
  314. }
  315. l = lpbiIn->biSize + (int)dwClrUsed * sizeof(RGBQUAD);
  316. if (lpbiOut == NULL)
  317. return l;
  318. hmemcpy(lpbiOut, lpbiIn, (int)l);
  319. lpbiOut->biBitCount = 8;
  320. }
  321. else
  322. {
  323. //
  324. // if lpbiOut == NULL then, return the size required to hold a output
  325. // format
  326. //
  327. if (lpbiOut == NULL)
  328. return (int)lpbiIn->biSize;
  329. *lpbiOut = *lpbiIn;
  330. lpbiOut->biClrUsed = 0;
  331. lpbiOut->biBitCount = 16;
  332. }
  333. lpbiOut->biWidth = lpbiIn->biWidth & ~3;
  334. lpbiOut->biHeight = lpbiIn->biHeight & ~3;
  335. lpbiOut->biCompression = FOURCC_CRAM;
  336. lpbiOut->biSizeImage = CompressGetSize(pinst, lpbiIn, lpbiOut);
  337. return ICERR_OK;
  338. }
  339. /*****************************************************************************
  340. ****************************************************************************/
  341. LONG FAR PASCAL CompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  342. {
  343. LONG l;
  344. if (l = CompressQuery(pinst, lpbiIn, lpbiOut))
  345. return l;
  346. DPF(("CompressBegin %dx%dx%d --> %dx%dx%d'%4.4ls'", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount, (int)lpbiOut->biWidth, (int)lpbiOut->biHeight, (int)lpbiOut->biBitCount,(LPSTR)&lpbiOut->biCompression));
  347. //
  348. // initialize for compression, for real....
  349. //
  350. pinst->nCompress = 1;
  351. return CompressFrameBegin(lpbiIn, lpbiOut, &pinst->lpITable, pinst->rgbqOut);
  352. }
  353. /*****************************************************************************
  354. ****************************************************************************/
  355. LONG FAR PASCAL CompressGetSize(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  356. {
  357. int dx,dy;
  358. dx = (int)lpbiIn->biWidth;
  359. dy = (int)lpbiIn->biHeight;
  360. /* maximum compressed size *** your code here *** */
  361. if (lpbiOut->biBitCount == 8)
  362. // worst case size of data 10 bytes per 16 pixels (8 colors + mask)
  363. // remember the EOF code!
  364. return ((DWORD)dx * (DWORD)dy * 10l) / 16l + 2l;
  365. else
  366. // worst case size of data 18 bytes per 16 pixels (8 colors + mask)
  367. // remember the EOF code!
  368. return ((DWORD)dx * (DWORD)dy * 10l) / 8l + 2l; // 10/8 ~= 18/16
  369. ////////return ((DWORD)dx * (DWORD)dy * 18l) / 16l + 2l;
  370. }
  371. /*****************************************************************************
  372. ****************************************************************************/
  373. LONG FAR PASCAL Compress(INSTINFO * pinst, ICCOMPRESS FAR *icinfo, DWORD dwSize)
  374. {
  375. LONG l;
  376. LPBITMAPINFOHEADER lpbiIn = icinfo->lpbiInput;
  377. LPBITMAPINFOHEADER lpbiOut = icinfo->lpbiOutput;
  378. DWORD threshold;
  379. DWORD thresholdPrev;
  380. DWORD dwQualityPrev;
  381. DWORD dwQuality;
  382. BOOL fBegin;
  383. LPVOID smag;
  384. PCELLS compressTemp;
  385. if (l = CompressQuery(pinst, icinfo->lpbiInput, icinfo->lpbiOutput))
  386. return l;
  387. //
  388. // check for being called without a BEGIN message, and do the begin for
  389. // the caller
  390. //
  391. if (fBegin = (pinst->nCompress == 0))
  392. {
  393. if (l = CompressBegin(pinst, icinfo->lpbiInput, icinfo->lpbiOutput))
  394. return l;
  395. }
  396. smag = _FPInit();
  397. DPF(("Compress %dx%dx%d --> %dx%dx%d'%4.4ls'", (int)lpbiIn->biWidth, (int)lpbiIn->biHeight, (int)lpbiIn->biBitCount, (int)lpbiOut->biWidth, (int)lpbiOut->biHeight, (int)lpbiOut->biBitCount, (LPSTR)&lpbiOut->biCompression));
  398. if (icinfo->dwQuality == ICQUALITY_DEFAULT)
  399. dwQuality = QUALITY_DEFAULT;
  400. else
  401. dwQuality = ICQUALITY_HIGH - icinfo->dwQuality;
  402. dwQualityPrev = MulDiv((UINT)dwQuality,100,pinst->CurrentState.wTemporalRatio);
  403. threshold = QualityToThreshold(dwQuality);
  404. thresholdPrev = QualityToThreshold(dwQualityPrev);
  405. if (pinst->Status)
  406. pinst->Status(pinst->lParam, ICSTATUS_START, 0);
  407. // For Win16, this needs to be in the data segment so we
  408. // can use a near pointer to it.
  409. compressTemp = (PCELLS) LocalAlloc(LPTR, sizeof(CELLS));
  410. if (!compressTemp)
  411. return ICERR_MEMORY;
  412. if (lpbiOut->biBitCount == 8)
  413. l = CompressFrame8(
  414. icinfo->lpbiInput, // DIB header to compress
  415. icinfo->lpInput, // DIB bits to compress
  416. icinfo->lpOutput, // put compressed data here
  417. threshold, // edge threshold
  418. thresholdPrev, // inter-frame threshold
  419. icinfo->lpbiPrev, // previous frame
  420. icinfo->lpPrev, // previous frame
  421. pinst->Status, // status callback
  422. pinst->lParam,
  423. compressTemp,
  424. pinst->lpITable,
  425. pinst->rgbqOut);
  426. else
  427. l = CompressFrame16(
  428. icinfo->lpbiInput, // DIB header to compress
  429. icinfo->lpInput, // DIB bits to compress
  430. icinfo->lpOutput, // put compressed data here
  431. threshold, // edge threshold
  432. thresholdPrev, // inter-frame threshold
  433. icinfo->lpbiPrev, // previous frame
  434. icinfo->lpPrev, // previous frame
  435. pinst->Status, // status callback
  436. pinst->lParam,
  437. compressTemp);
  438. LocalFree((HLOCAL) compressTemp);
  439. if (pinst->Status)
  440. pinst->Status(pinst->lParam, ICSTATUS_END, 0);
  441. _FPTerm(smag);
  442. if (l == -1)
  443. return ICERR_ERROR;
  444. lpbiOut->biWidth = lpbiIn->biWidth & ~3;
  445. lpbiOut->biHeight = lpbiIn->biHeight & ~3;
  446. lpbiOut->biCompression = FOURCC_CRAM;
  447. lpbiOut->biSizeImage = l;
  448. ////lpbiOut->biBitCount = 16;
  449. //
  450. // return the chunk id
  451. //
  452. if (icinfo->lpckid)
  453. *icinfo->lpckid = TWOCC_XX;
  454. //
  455. // set the AVI index flags,
  456. //
  457. // make it a keyframe?
  458. //
  459. if (icinfo->lpdwFlags) {
  460. *icinfo->lpdwFlags = AVIIF_TWOCC;
  461. if (icinfo->lpbiPrev == NULL || numberOfSkips == 0)
  462. *icinfo->lpdwFlags |= AVIIF_KEYFRAME;
  463. }
  464. if (fBegin)
  465. CompressEnd(pinst);
  466. return ICERR_OK;
  467. }
  468. /*****************************************************************************
  469. ****************************************************************************/
  470. LONG FAR PASCAL CompressEnd(INSTINFO * pinst)
  471. {
  472. if (pinst->nCompress == 0)
  473. return ICERR_ERROR;
  474. pinst->nCompress = 0;
  475. return CompressFrameEnd(&pinst->lpITable);
  476. }
  477. /*****************************************************************************
  478. *
  479. * decompress tables
  480. *
  481. * indexed by:
  482. * SRC: 0=8 bit Cram 1=16 bit Cram
  483. * STRETCH: 0=1:1, 1=1:2
  484. * DST: 0=8, 1=16, 2=24, 3=32
  485. *
  486. ****************************************************************************/
  487. #ifdef _WIN32
  488. DECOMPPROC DecompressWin32[2][2][5] = {
  489. DecompressFrame8, // Cram8 1:1 to 8
  490. NULL, // Cram8 1:1 to 16 (555)
  491. NULL, // Cram8 1:1 to 24
  492. NULL, // Cram8 1:1 to 32
  493. NULL, // Cram8 1:1 to 565
  494. DecompressFrame8X2C, // Cram8 1:2 to 8
  495. NULL, // Cram8 1:2 to 16 (555)
  496. NULL, // Cram8 1:2 to 24
  497. NULL, // Cram8 1:2 to 32
  498. NULL, // Cram8 1:2 to 565
  499. DecompressFrame16To8C, // Cram16 1:1 to 8
  500. DecompressFrame16To555C, // Cram16 1:1 to 16 (555)
  501. DecompressFrame24, // Cram16 1:1 to 24
  502. NULL, // Cram16 1:1 to 32
  503. DecompressFrame16To565C, // Cram16 1:1 to 565
  504. DecompressFrame16To8X2C, // Cram16 1:2 to 8
  505. NULL, // Cram16 1:2 to 16 (555)
  506. NULL, // Cram16 1:2 to 24
  507. NULL, // Cram16 1:2 to 32
  508. NULL}; // Cram16 1:2 to 565
  509. #else
  510. DECOMPPROC Decompress386[2][2][5] = {
  511. DecompressCram8, // Cram8 1:1 to 8
  512. NULL, // Cram8 1:1 to 16 (555)
  513. NULL, // Cram8 1:1 to 24
  514. NULL, // Cram8 1:1 to 32
  515. NULL, // Cram8 1:1 to 565
  516. DecompressCram8x2, // Cram8 1:2 to 8
  517. NULL, // Cram8 1:2 to 16 (555)
  518. NULL, // Cram8 1:2 to 24
  519. NULL, // Cram8 1:2 to 32
  520. NULL, // Cram8 1:2 to 565
  521. DecompressCram168, // Cram16 1:1 to 8
  522. DecompressCram16, // Cram16 1:1 to 16 (555)
  523. NULL, // Cram16 1:1 to 24
  524. NULL /* DecompressCram32 */, // Cram16 1:1 to 32
  525. NULL /* DecompressFrame16To565C */, // Cram16 1:1 to 565
  526. NULL, // Cram16 1:2 to 8
  527. DecompressCram16x2, // Cram16 1:2 to 16 (555)
  528. NULL, // Cram16 1:2 to 24
  529. NULL, // Cram16 1:2 to 32
  530. NULL}; // Cram16 1:2 to 565
  531. DECOMPPROC Decompress286[2][2][5] = {
  532. DecompressCram8_286, // Cram8 1:1 to 8
  533. NULL, // Cram8 1:1 to 16 (555)
  534. NULL, // Cram8 1:1 to 24
  535. NULL, // Cram8 1:1 to 32
  536. NULL, // Cram8 1:1 to 565
  537. NULL, // Cram8 1:2 to 8
  538. NULL, // Cram8 1:2 to 16 (555)
  539. NULL, // Cram8 1:2 to 24
  540. NULL, // Cram8 1:2 to 32
  541. NULL, // Cram8 1:2 to 565
  542. NULL, // Cram16 1:1 to 8
  543. DecompressCram16_286, // Cram16 1:1 to 16 (555)
  544. NULL, // Cram16 1:1 to 24
  545. NULL, // Cram16 1:1 to 32
  546. NULL, // Cram16 1:1 to 565
  547. NULL, // Cram16 1:2 to 8
  548. NULL, // Cram16 1:2 to 16 (555)
  549. NULL, // Cram16 1:2 to 24
  550. NULL, // Cram16 1:2 to 32
  551. NULL}; // Cram16 1:2 to 565
  552. #endif
  553. /*****************************************************************************
  554. ****************************************************************************/
  555. LONG NEAR PASCAL DecompressQueryFmt(
  556. INSTINFO * pinst,
  557. LPBITMAPINFOHEADER lpbiSrc)
  558. {
  559. //
  560. // determine if the input DIB data is in a format we like.
  561. //
  562. if (lpbiSrc == NULL ||
  563. !(lpbiSrc->biBitCount == 16 || lpbiSrc->biBitCount == 8) ||
  564. (lpbiSrc->biPlanes != 1) ||
  565. !(lpbiSrc->biCompression == FOURCC_MSVC ||
  566. lpbiSrc->biCompression == FOURCC_CRAM))
  567. return ICERR_BADFORMAT;
  568. return ICERR_OK;
  569. }
  570. /*****************************************************************************
  571. ****************************************************************************/
  572. LONG NEAR PASCAL DecompressQuery(
  573. INSTINFO * pinst,
  574. DWORD dwFlags,
  575. LPBITMAPINFOHEADER lpbiSrc,
  576. LPVOID pSrc,
  577. int xSrc,
  578. int ySrc,
  579. int dxSrc,
  580. int dySrc,
  581. LPBITMAPINFOHEADER lpbiDst,
  582. LPVOID pDst,
  583. int xDst,
  584. int yDst,
  585. int dxDst,
  586. int dyDst)
  587. {
  588. #ifndef _WIN32
  589. DWORD biSizeImage;
  590. #endif
  591. DECOMPPROC fn;
  592. int s,d,n;
  593. //
  594. // determine if the input DIB data is in a format we like.
  595. //
  596. if (DecompressQueryFmt(pinst, lpbiSrc))
  597. return ICERR_BADFORMAT;
  598. //
  599. // allow (-1) as a default width/height
  600. //
  601. if (dxSrc == -1)
  602. dxSrc = (int)lpbiSrc->biWidth;
  603. if (dySrc == -1)
  604. dySrc = (int)lpbiSrc->biHeight;
  605. //
  606. // we cant clip the source.
  607. //
  608. if (xSrc != 0 || ySrc != 0)
  609. return ICERR_BADPARAM;
  610. if ((dxSrc != (int)lpbiSrc->biWidth) || (dySrc != (int)lpbiSrc->biHeight))
  611. return ICERR_BADPARAM;
  612. //
  613. // are we being asked to query just the input format?
  614. //
  615. if (lpbiDst == NULL)
  616. return ICERR_OK;
  617. //
  618. // allow (-1) as a default width/height
  619. //
  620. if (dxDst == -1)
  621. dxDst = (int)lpbiDst->biWidth;
  622. if (dyDst == -1)
  623. dyDst = abs((int)lpbiDst->biHeight);
  624. #ifndef _WIN32
  625. if (gf286)
  626. biSizeImage = (DWORD)(UINT)abs((int)lpbiDst->biHeight)*(DWORD)(WORD)DIBWIDTHBYTES(*lpbiDst);
  627. #endif
  628. s = lpbiSrc->biBitCount/8-1; // s = 0,1
  629. #ifdef _WIN32
  630. // Can't support 16:32 access in our C version, of course....
  631. if (lpbiDst->biCompression == BI_1632) {
  632. return ICERR_BADFORMAT;
  633. }
  634. #endif
  635. if (lpbiDst->biBitCount != 8 && lpbiDst->biBitCount != 16 && lpbiDst->biBitCount != 24 && lpbiDst->biBitCount != 32)
  636. {
  637. return ICERR_BADFORMAT;
  638. }
  639. // must be full dib or a '1632' DIB
  640. if (lpbiDst->biCompression != BI_RGB &&
  641. lpbiDst->biCompression != BI_1632) {
  642. if (lpbiDst->biCompression != BI_BITFIELDS) {
  643. DPF(("MSVIDC asked to decompress to '%.4hs'!", &lpbiDst->biCompression));
  644. return ICERR_BADFORMAT;
  645. }
  646. // allow 565 dibs
  647. if ((lpbiDst->biBitCount == 16) &&
  648. (((LPDWORD)(lpbiDst+1))[0] == 0x00f800) &&
  649. (((LPDWORD)(lpbiDst+1))[1] == 0x0007e0) &&
  650. (((LPDWORD)(lpbiDst+1))[2] == 0x00001f) ) {
  651. // ok - its 565 format
  652. d = 4;
  653. } else {
  654. DPF(("Bad bitmask (%lX %lX %lX) in %d-bit BI_BITMAP case!",
  655. lpbiDst->biBitCount,
  656. ((LPDWORD)(lpbiDst+1))[0],
  657. ((LPDWORD)(lpbiDst+1))[1],
  658. ((LPDWORD)(lpbiDst+1))[2]));
  659. return ICERR_BADFORMAT;
  660. }
  661. } else {
  662. d = lpbiDst->biBitCount/8-1; // d = 0,1,2,3
  663. if (lpbiDst->biCompression == BI_1632 && lpbiDst->biBitCount == 16) {
  664. if ((((LPDWORD)(lpbiDst+1))[0] == 0x007400) &&
  665. (((LPDWORD)(lpbiDst+1))[1] == 0x0003f0) &&
  666. (((LPDWORD)(lpbiDst+1))[2] == 0x00000f) ) {
  667. // ok - it's 555 format
  668. } else if ((((LPDWORD)(lpbiDst+1))[0] == 0x00f800) &&
  669. (((LPDWORD)(lpbiDst+1))[1] == 0x0007e0) &&
  670. (((LPDWORD)(lpbiDst+1))[2] == 0x00001f) ) {
  671. // ok - it's 565 format
  672. d = 4;
  673. } else {
  674. DPF(("Bad bitmask (%lX %lX %lX) in 16-bit BI_1632 case!",
  675. ((LPDWORD)(lpbiDst+1))[0],
  676. ((LPDWORD)(lpbiDst+1))[1],
  677. ((LPDWORD)(lpbiDst+1))[2]));
  678. return ICERR_BADFORMAT;
  679. }
  680. }
  681. // What about 24-bit BI_1632? Should we check the masks?
  682. }
  683. //
  684. // n = 0 for 1:1, 1 for 1:2
  685. //
  686. if (dxDst == dxSrc && dyDst == dySrc)
  687. n = 0;
  688. else if (dxDst == dxSrc*2 && dyDst == dySrc*2)
  689. n = 1;
  690. else
  691. return ICERR_BADSIZE;
  692. #ifdef DEBUG
  693. DPF(("DecompressQuery %dx%dx%d [%d,%d,%d,%d] --> %dx%dx%d (565) [%d,%d,%d,%d]",
  694. (int)lpbiSrc->biWidth, (int)lpbiSrc->biHeight, (int)lpbiSrc->biBitCount,
  695. xSrc, ySrc, dxSrc, dySrc,
  696. (int)lpbiDst->biWidth, (int)lpbiDst->biHeight, (int)lpbiDst->biBitCount,
  697. d == 4 ? "(565)" : "",
  698. xDst, yDst, dxDst, dyDst));
  699. #endif
  700. #ifdef _WIN32
  701. fn = DecompressWin32[s][n][d];
  702. #else
  703. if (gf286)
  704. {
  705. fn = Decompress286[s][n][d];
  706. if (fn && biSizeImage > 64l*1024)
  707. fn = fn==DecompressCram8_286 ? DecompressFrame8 : NULL;
  708. }
  709. else
  710. {
  711. fn = Decompress386[s][n][d];
  712. }
  713. #endif
  714. if (fn == NULL)
  715. return ICERR_BADFORMAT;
  716. pinst->DecompressTest = fn; // return this to DecompressBegin.
  717. return ICERR_OK;
  718. }
  719. /*****************************************************************************
  720. ****************************************************************************/
  721. LONG NEAR PASCAL DecompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  722. {
  723. LONG l;
  724. int dx,dy;
  725. if (l = DecompressQueryFmt(pinst, lpbiIn))
  726. return l;
  727. //
  728. // if lpbiOut == NULL then, return the size required to hold a output
  729. // format
  730. //
  731. if (lpbiOut == NULL)
  732. return (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
  733. hmemcpy(lpbiOut, lpbiIn,
  734. (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
  735. dx = (int)lpbiIn->biWidth & ~3;
  736. dy = (int)lpbiIn->biHeight & ~3;
  737. lpbiOut->biWidth = dx;
  738. lpbiOut->biHeight = dy;
  739. lpbiOut->biBitCount = lpbiIn->biBitCount; // convert 8->8 16->16
  740. lpbiOut->biPlanes = 1;
  741. lpbiOut->biCompression = BI_RGB;
  742. lpbiOut->biSizeImage = (DWORD)(WORD)abs(dy)*(DWORD)(WORD)DIBWIDTHBYTES(*lpbiOut);
  743. return ICERR_OK;
  744. }
  745. /*****************************************************************************
  746. ****************************************************************************/
  747. LONG NEAR PASCAL DecompressBegin(
  748. INSTINFO * pinst,
  749. DWORD dwFlags,
  750. LPBITMAPINFOHEADER lpbiSrc,
  751. LPVOID pSrc,
  752. int xSrc,
  753. int ySrc,
  754. int dxSrc,
  755. int dySrc,
  756. LPBITMAPINFOHEADER lpbiDst,
  757. LPVOID pDst,
  758. int xDst,
  759. int yDst,
  760. int dxDst,
  761. int dyDst)
  762. {
  763. LONG l;
  764. if (l = DecompressQuery(pinst, dwFlags, lpbiSrc, pSrc, xSrc, ySrc, dxSrc, dySrc, lpbiDst, pDst, xDst, yDst, dxDst, dyDst))
  765. return l;
  766. pinst->DecompressProc = pinst->DecompressTest;
  767. //
  768. // make sure biSizeImage is set, the decompress code needs it to be
  769. //
  770. if (lpbiDst->biSizeImage == 0)
  771. lpbiDst->biSizeImage = (DWORD)(WORD)abs((int)lpbiDst->biHeight)*(DWORD)(WORD)DIBWIDTHBYTES(*lpbiDst);
  772. //
  773. // init the dither tables !!! call MSVIDEO, dont have code here!!!
  774. //
  775. if (lpbiSrc->biBitCount == 16 &&
  776. lpbiDst->biBitCount == 8)
  777. {
  778. if (lpDitherTable == NULL)
  779. lpDitherTable = Dither16InitScale();
  780. if (lpDitherTable == NULL)
  781. return ICERR_MEMORY;
  782. }
  783. pinst->nDecompress = 1;
  784. return ICERR_OK;
  785. }
  786. /*****************************************************************************
  787. *
  788. * Decompress
  789. *
  790. * we can assume certain things here because DecompressQuery() only lets
  791. * valid stuff in.
  792. *
  793. * the source rect is always the entire source.
  794. * the dest rect is either 1:1 or 1:2
  795. *
  796. ****************************************************************************/
  797. LONG NEAR PASCAL Decompress(
  798. INSTINFO * pinst,
  799. DWORD dwFlags,
  800. LPBITMAPINFOHEADER lpbiSrc,
  801. LPVOID pSrc,
  802. int xSrc,
  803. int ySrc,
  804. int dxSrc,
  805. int dySrc,
  806. LPBITMAPINFOHEADER lpbiDst,
  807. LPVOID pDst,
  808. int xDst,
  809. int yDst,
  810. int dxDst,
  811. int dyDst)
  812. {
  813. //
  814. // if we are called without a begin do the begin now, but dont make
  815. // the begin "stick"
  816. //
  817. if (pinst->nDecompress == 0)
  818. {
  819. LONG err;
  820. if (err = DecompressBegin(pinst, dwFlags, lpbiSrc, pSrc, xSrc, ySrc, dxSrc, dySrc, lpbiDst, pDst, xDst, yDst, dxDst, dyDst))
  821. return err;
  822. pinst->nDecompress = 0;
  823. }
  824. #ifdef DEBUG
  825. if (lpbiDst->biSizeImage == 0)
  826. DebugBreak();
  827. if (pinst->DecompressProc == NULL)
  828. DebugBreak();
  829. #endif
  830. (*pinst->DecompressProc)(lpbiSrc,pSrc,lpbiDst,pDst,xDst,yDst);
  831. return ICERR_OK;
  832. }
  833. /*****************************************************************************
  834. *
  835. * DecompressGetPalette() implements ICM_GET_PALETTE
  836. *
  837. * This function has no Compress...() equivalent
  838. *
  839. * It is used to pull the palette from a frame in order to possibly do
  840. * a palette change.
  841. *
  842. ****************************************************************************/
  843. LONG NEAR PASCAL DecompressGetPalette(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  844. {
  845. LONG l;
  846. int i;
  847. RGBQUAD FAR * prgb;
  848. DPF(("DecompressGetPalette()"));
  849. if (l = DecompressQueryFmt(pinst, lpbiIn))
  850. return l;
  851. if (lpbiOut->biBitCount != 8)
  852. return ICERR_BADFORMAT;
  853. //
  854. // if you decompress full-color to 8 bit you need to put the "dither"
  855. // palette in lpbiOut
  856. //
  857. if (lpbiIn->biBitCount != 8)
  858. {
  859. lpbiOut->biClrUsed = 256;
  860. prgb = (LPVOID)(lpbiOut + 1);
  861. for (i=0; i<256; i++)
  862. {
  863. prgb[i].rgbRed = dpal775[i][0];
  864. prgb[i].rgbGreen = dpal775[i][1];
  865. prgb[i].rgbBlue = dpal775[i][2];
  866. prgb[i].rgbReserved = 0;
  867. }
  868. return ICERR_OK;
  869. }
  870. if (lpbiIn->biClrUsed == 0)
  871. lpbiIn->biClrUsed = 256;
  872. //
  873. // return the 8bit palette used for decompression.
  874. //
  875. hmemcpy(
  876. (LPBYTE)lpbiOut + (int)lpbiOut->biSize,
  877. (LPBYTE)lpbiIn + (int)lpbiIn->biSize,
  878. (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
  879. lpbiOut->biClrUsed = lpbiIn->biClrUsed;
  880. return ICERR_OK;
  881. }
  882. /*****************************************************************************
  883. ****************************************************************************/
  884. LONG NEAR PASCAL DecompressEnd(INSTINFO * pinst)
  885. {
  886. if (pinst->nDecompress == 0)
  887. return ICERR_ERROR;
  888. pinst->nDecompress = 0;
  889. return ICERR_OK;
  890. }
  891. /*****************************************************************************
  892. ****************************************************************************/
  893. LONG NEAR PASCAL DrawBegin(INSTINFO * pinst,ICDRAWBEGIN FAR *icinfo, DWORD dwSize)
  894. {
  895. return ICERR_UNSUPPORTED;
  896. }
  897. /*****************************************************************************
  898. ****************************************************************************/
  899. LONG NEAR PASCAL Draw(INSTINFO * pinst, ICDRAW FAR *icinfo, DWORD dwSize)
  900. {
  901. return ICERR_UNSUPPORTED;
  902. }
  903. /*****************************************************************************
  904. ****************************************************************************/
  905. LONG NEAR PASCAL DrawEnd(INSTINFO * pinst)
  906. {
  907. return ICERR_UNSUPPORTED;
  908. }
  909. /*****************************************************************************
  910. ****************************************************************************/
  911. INT_PTR FAR PASCAL _LOADDS ConfigureDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  912. {
  913. int i;
  914. HWND hsb;
  915. TCHAR ach[10];
  916. static TCHAR chDecimal = TEXT('.');
  917. static INSTINFO *pinst;
  918. #define SCROLL_MIN 1 // 0.00
  919. #define SCROLL_MAX 100 // 1.00
  920. switch (msg)
  921. {
  922. case WM_COMMAND:
  923. switch (wParam)
  924. {
  925. case IDOK:
  926. hsb = GetDlgItem(hdlg,ID_SCROLL);
  927. pinst->CurrentState.wTemporalRatio = GetScrollPos(hsb,SB_CTL);
  928. EndDialog(hdlg,TRUE);
  929. break;
  930. case IDCANCEL:
  931. EndDialog(hdlg,FALSE);
  932. break;
  933. }
  934. break;
  935. case WM_HSCROLL:
  936. hsb = GET_WM_HSCROLL_HWND(wParam, lParam);
  937. i = GetScrollPos(hsb,SB_CTL);
  938. switch (GET_WM_HSCROLL_CODE(wParam, lParam))
  939. {
  940. case SB_LINEDOWN: i += 1; break;
  941. case SB_LINEUP: i -= 1; break;
  942. case SB_PAGEDOWN: i += 10; break;
  943. case SB_PAGEUP: i -= 10; break;
  944. case SB_THUMBTRACK:
  945. case SB_THUMBPOSITION:
  946. i = (int)GET_WM_HSCROLL_POS(wParam, lParam);
  947. break;
  948. default:
  949. return TRUE;
  950. }
  951. i = max(SCROLL_MIN,min(SCROLL_MAX,i));
  952. SetScrollPos(hsb,SB_CTL,i,TRUE);
  953. wsprintf(ach, TEXT("%d%c%02d"), i/100, chDecimal, i%100);
  954. SetDlgItemText(hdlg,ID_TEXT,ach);
  955. return TRUE;
  956. case WM_INITDIALOG:
  957. pinst = (INSTINFO *)lParam;
  958. ach[0] = chDecimal;
  959. ach[1] = 0;
  960. GetProfileString(TEXT("intl"), TEXT("sDecimal"), ach, ach,
  961. sizeof(ach) / sizeof(ach[0]));
  962. chDecimal = ach[0];
  963. hsb = GetDlgItem(hdlg,ID_SCROLL);
  964. i = pinst->CurrentState.wTemporalRatio;
  965. SetScrollRange(hsb,SB_CTL,SCROLL_MIN, SCROLL_MAX, TRUE);
  966. SetScrollPos(hsb,SB_CTL,i,TRUE);
  967. wsprintf(ach, TEXT("%d%c%02d"), i/100, chDecimal, i%100);
  968. SetDlgItemText(hdlg,ID_TEXT,ach);
  969. return TRUE;
  970. }
  971. return FALSE;
  972. }
  973. /*****************************************************************************
  974. ****************************************************************************/
  975. #ifdef DEBUG
  976. #define _WINDLL
  977. #include <stdarg.h>
  978. #ifdef _WIN32
  979. #define GetProfileIntA mmGetProfileIntA
  980. #endif
  981. void FAR CDECL dprintf(LPSTR szFormat, ...)
  982. {
  983. char ach[128];
  984. static BOOL fDebug = -1;
  985. va_list va;
  986. va_start(va, szFormat);
  987. if (fDebug == -1)
  988. fDebug = GetProfileIntA("Debug", "MSVIDC", FALSE);
  989. if (!fDebug)
  990. return;
  991. #ifdef _WIN32
  992. wsprintfA(ach, "MSVIDC32: (tid %x) ", GetCurrentThreadId());
  993. wvsprintfA(ach+strlen(ach),szFormat,va);
  994. #else
  995. lstrcpyA(ach, "MSVIDC: ");
  996. wvsprintfA(ach+8,szFormat,va);
  997. #endif
  998. lstrcatA(ach, "\r\n");
  999. OutputDebugStringA(ach);
  1000. va_end(va);
  1001. }
  1002. #endif