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.

606 lines
16 KiB

  1. /*----------------------------------------------------------------------+
  2. | msyuv.c - Microsoft YUV Codec |
  3. | |
  4. | Copyright (c) 1993 Microsoft Corporation. |
  5. | All Rights Reserved. |
  6. | |
  7. +----------------------------------------------------------------------*/
  8. #include <windows.h>
  9. #include <windowsx.h>
  10. //#include <mmsystem.h>
  11. #ifndef _WIN32
  12. #include "stdarg.h"
  13. #endif
  14. #ifdef _WIN32
  15. #include <memory.h> /* for memcpy */
  16. #endif
  17. #include "msyuv.h"
  18. WCHAR szDescription[] = L"Toshiba YUV Codec";
  19. WCHAR szName[] = L"Toshiba YUV411";
  20. WCHAR szAbout[] = L"About";
  21. #define VERSION 0x00010000 // 1.0
  22. /*****************************************************************************
  23. ****************************************************************************/
  24. INSTINFO * NEAR PASCAL Open(ICOPEN FAR * icinfo)
  25. {
  26. INSTINFO * pinst;
  27. //
  28. // refuse to open if we are not being opened as a Video compressor
  29. //
  30. if (icinfo->fccType != ICTYPE_VIDEO)
  31. return NULL;
  32. //
  33. // dwFlags contain wMode
  34. //
  35. if( icinfo->dwFlags != ICMODE_QUERY // Open for infomational purpose
  36. && icinfo->dwFlags != ICMODE_DECOMPRESS
  37. #ifdef ICM_COMPRESS_SUPPORTED
  38. && icinfo->dwFlags != ICMODE_COMPRESS
  39. #endif
  40. #ifdef ICM_DRAW_SUPPORTED
  41. && icinfo->dwFlags != ICMODE_DRAW
  42. #endif
  43. ) {
  44. dprintf1((TEXT("Open: unsupported wMode=%d\n"), icinfo->dwFlags));
  45. return NULL;
  46. }
  47. pinst = (INSTINFO *)LocalAlloc(LPTR, sizeof(INSTINFO));
  48. if (!pinst) {
  49. icinfo->dwError = (DWORD)ICERR_MEMORY;
  50. return NULL;
  51. }
  52. //
  53. // init structure
  54. //
  55. pinst->dwFlags = icinfo->dwFlags;
  56. pinst->pXlate = NULL;
  57. //
  58. // return success.
  59. //
  60. icinfo->dwError = ICERR_OK;
  61. return pinst;
  62. }
  63. /*****************************************************************************
  64. ****************************************************************************/
  65. DWORD NEAR PASCAL Close(INSTINFO * pinst)
  66. {
  67. if (pinst->pXlate) {
  68. DecompressEnd(pinst);
  69. }
  70. #if ICM_DRAW_SUPPORTED
  71. if (pinst->vh) {
  72. DrawEnd(pinst);
  73. }
  74. #endif
  75. LocalFree((HLOCAL)pinst);
  76. return 1;
  77. }
  78. /*****************************************************************************
  79. ****************************************************************************/
  80. BOOL NEAR PASCAL QueryAbout(INSTINFO * pinst)
  81. {
  82. return TRUE;
  83. }
  84. DWORD NEAR PASCAL About(INSTINFO * pinst, HWND hwnd)
  85. {
  86. MessageBoxW(hwnd,szDescription,szAbout,MB_OK|MB_ICONINFORMATION);
  87. return ICERR_OK;
  88. }
  89. /*****************************************************************************
  90. ****************************************************************************/
  91. BOOL NEAR PASCAL QueryConfigure(INSTINFO * pinst)
  92. {
  93. return FALSE;
  94. }
  95. DWORD NEAR PASCAL Configure(INSTINFO * pinst, HWND hwnd)
  96. {
  97. return (TRUE);
  98. }
  99. /*****************************************************************************
  100. ****************************************************************************/
  101. /*
  102. * lossless translation - hence no need for state adjustments
  103. */
  104. DWORD NEAR PASCAL GetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  105. {
  106. return 0;
  107. }
  108. /*****************************************************************************
  109. ****************************************************************************/
  110. DWORD NEAR PASCAL SetState(INSTINFO * pinst, LPVOID pv, DWORD dwSize)
  111. {
  112. return(0);
  113. }
  114. /*****************************************************************************
  115. ****************************************************************************/
  116. DWORD NEAR PASCAL GetInfo(INSTINFO * pinst, ICINFO FAR *icinfo, DWORD dwSize)
  117. {
  118. if (icinfo == NULL)
  119. return sizeof(ICINFO);
  120. if (dwSize < sizeof(ICINFO))
  121. return 0;
  122. icinfo->dwSize = sizeof(ICINFO);
  123. icinfo->fccType = ICTYPE_VIDEO;
  124. icinfo->fccHandler = FOURCC_YUV411;
  125. icinfo->dwFlags = 0;
  126. icinfo->dwVersion = VERSION;
  127. icinfo->dwVersionICM = ICVERSION;
  128. wcscpy(icinfo->szDescription, szDescription);
  129. wcscpy(icinfo->szName, szName);
  130. return sizeof(ICINFO);
  131. }
  132. /*****************************************************************************
  133. ****************************************************************************/
  134. DWORD FAR PASCAL CompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  135. {
  136. return ((DWORD) ICERR_BADFORMAT);
  137. }
  138. /*****************************************************************************
  139. ****************************************************************************/
  140. DWORD FAR PASCAL CompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  141. {
  142. return((DWORD) ICERR_BADFORMAT);
  143. }
  144. /*****************************************************************************
  145. ****************************************************************************/
  146. DWORD FAR PASCAL CompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  147. {
  148. return((DWORD) ICERR_ERROR);
  149. }
  150. /*****************************************************************************
  151. ****************************************************************************/
  152. DWORD FAR PASCAL CompressGetSize(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  153. {
  154. return (0);
  155. }
  156. /*****************************************************************************
  157. ****************************************************************************/
  158. DWORD FAR PASCAL Compress(INSTINFO * pinst, ICCOMPRESS FAR *icinfo, DWORD dwSize)
  159. {
  160. return((DWORD) ICERR_ERROR);
  161. }
  162. /*****************************************************************************
  163. ****************************************************************************/
  164. DWORD FAR PASCAL CompressEnd(INSTINFO * pinst)
  165. {
  166. return (DWORD)ICERR_ERROR;
  167. }
  168. /*****************************************************************************
  169. ****************************************************************************/
  170. DWORD NEAR PASCAL DecompressQuery(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  171. {
  172. //
  173. // determine if the input DIB data is in a format we like.
  174. //
  175. #ifdef TOSHIBA
  176. #if DBG
  177. // DbgBreakPoint();
  178. #endif
  179. if (lpbiIn == NULL ||
  180. ( (lpbiIn->biCompression != FOURCC_YUV411) &&
  181. (lpbiIn->biCompression != FOURCC_YUV422) &&
  182. (lpbiIn->biCompression != FOURCC_YUV9) && // add YUV9
  183. (lpbiIn->biCompression != FOURCC_YUV12 ))) { // add YUV12
  184. #else //TOSHIBA
  185. if (lpbiIn == NULL ||
  186. (lpbiIn->biBitCount != 16) ||
  187. ( (lpbiIn->biCompression != FOURCC_YUV411) &&
  188. (lpbiIn->biCompression != FOURCC_YUV422))) {
  189. #endif//TOSHIBA
  190. dprintf((TEXT("bad input format")));
  191. return (DWORD)ICERR_BADFORMAT;
  192. }
  193. //
  194. // are we being asked to query just the input format?
  195. //
  196. if (lpbiOut == NULL) {
  197. return ICERR_OK;
  198. }
  199. // check output format to make sure we can convert to this
  200. // must be full dib
  201. if (lpbiOut->biCompression == BI_RGB) {
  202. pinst->bRGB565 = FALSE;
  203. #ifdef TOSHIBA
  204. #ifdef COLOR_MODIFY
  205. if (lpbiOut->biBitCount == 24) {
  206. pinst->bRGB24 = TRUE;
  207. } else {
  208. pinst->bRGB24 = FALSE;
  209. }
  210. #endif//COLOR_MODIFY
  211. #endif//TOSHIBA
  212. } else if ((lpbiOut->biCompression == BI_BITFIELDS) &&
  213. (lpbiOut->biBitCount == 16) &&
  214. (((LPDWORD)(lpbiOut+1))[0] == 0x00f800) &&
  215. (((LPDWORD)(lpbiOut+1))[1] == 0x0007e0) &&
  216. (((LPDWORD)(lpbiOut+1))[2] == 0x00001f)) {
  217. dprintf1((TEXT("rgb565 output")));
  218. pinst->bRGB565 = TRUE;
  219. #ifdef TOSHIBA
  220. #ifdef COLOR_MODIFY
  221. pinst->bRGB24 = FALSE;
  222. #endif//COLOR_MODIFY
  223. #endif//TOSHIBA
  224. } else {
  225. dprintf1((TEXT("bad compression for output")));
  226. return (DWORD)ICERR_BADFORMAT;
  227. }
  228. /* must be 1:1 (no stretching) */
  229. if ((lpbiOut->biWidth != lpbiIn->biWidth) ||
  230. (lpbiOut->biHeight != lpbiIn->biHeight)) {
  231. dprintf1((TEXT("YUV can't stretch: %dx%d->%dx%d"),
  232. lpbiIn->biWidth, lpbiIn->biHeight,
  233. lpbiOut->biWidth, lpbiOut->biHeight
  234. ));
  235. return((DWORD) ICERR_BADFORMAT);
  236. }
  237. /*
  238. * we translate to 16 bits
  239. */
  240. #ifdef TOSHIBA
  241. #ifdef COLOR_MODIFY
  242. if ((lpbiOut->biBitCount != 16) &&
  243. (lpbiOut->biBitCount != 24)) {
  244. dprintf1((TEXT("YUV to 16 or 24 only")));
  245. return((DWORD) ICERR_BADFORMAT);
  246. }
  247. #else //COLOR_MODIFY
  248. if (lpbiOut->biBitCount != 16) {
  249. dprintf1((TEXT("YUV 16:16 only")));
  250. return((DWORD) ICERR_BADFORMAT);
  251. }
  252. #endif//COLOR_MODIFY
  253. #else //TOSHIBA
  254. if (lpbiOut->biBitCount != 16) {
  255. dprintf1((TEXT("YUV 16:16 only")));
  256. return((DWORD) ICERR_BADFORMAT);
  257. }
  258. #endif//TOSHIBA
  259. return ICERR_OK;
  260. }
  261. /*****************************************************************************
  262. ****************************************************************************/
  263. DWORD DecompressGetFormat(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  264. {
  265. DWORD dw;
  266. int dx,dy;
  267. dw = DecompressQuery(pinst, lpbiIn, NULL);
  268. if (dw != ICERR_OK) {
  269. return dw;
  270. }
  271. //
  272. // if lpbiOut == NULL then, return the size required to hold a output
  273. // format
  274. //
  275. if (lpbiOut == NULL) {
  276. dprintf2((TEXT("get format size query")));
  277. return (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD);
  278. }
  279. memcpy(lpbiOut, lpbiIn,
  280. (int)lpbiIn->biSize + (int)lpbiIn->biClrUsed * sizeof(RGBQUAD));
  281. dx = (int)lpbiIn->biWidth & ~3;
  282. dy = (int)lpbiIn->biHeight & ~3;
  283. lpbiOut->biWidth = dx;
  284. lpbiOut->biHeight = dy;
  285. #ifdef TOSHIBA
  286. lpbiOut->biBitCount = 16;
  287. #else //TOSHIBA
  288. lpbiOut->biBitCount = lpbiIn->biBitCount; // convert 16->16
  289. #endif//TOSHIBA
  290. lpbiOut->biCompression = BI_RGB;
  291. lpbiOut->biSizeImage = dx*dy*2;
  292. return ICERR_OK;
  293. }
  294. /*****************************************************************************
  295. ****************************************************************************/
  296. DWORD NEAR PASCAL DecompressBegin(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  297. {
  298. DWORD dw;
  299. /* check that the conversion formats are valid */
  300. dw = DecompressQuery(pinst, lpbiIn, lpbiOut);
  301. if (dw != ICERR_OK) {
  302. return dw;
  303. }
  304. /* init the yuv-to-rgb55 xlate table if not already inited */
  305. /* free up the existing table if the formats differ */
  306. if (lpbiIn->biCompression != pinst->dwFormat) {
  307. if (pinst->pXlate != NULL) {
  308. DecompressEnd(pinst);
  309. }
  310. }
  311. if (pinst->pXlate == NULL) {
  312. switch(lpbiIn->biCompression) {
  313. case FOURCC_YUV411:
  314. if (pinst->bRGB565) {
  315. pinst->pXlate = BuildYUVToRGB565(pinst);
  316. } else {
  317. pinst->pXlate = BuildYUVToRGB555(pinst);
  318. }
  319. break;
  320. case FOURCC_YUV422:
  321. if (pinst->bRGB565) {
  322. pinst->pXlate = BuildYUV422ToRGB565(pinst);
  323. } else {
  324. pinst->pXlate = BuildYUV422ToRGB555(pinst);
  325. }
  326. break;
  327. #ifdef TOSHIBA
  328. #ifdef COLOR_MODIFY
  329. case FOURCC_YUV12:
  330. pinst->pXlate = BuildYUVToRB(pinst);
  331. break;
  332. case FOURCC_YUV9:
  333. pinst->pXlate = BuildYUVToRB(pinst); // same to YUV12
  334. break;
  335. #else //COLOR_MODIFY
  336. case FOURCC_YUV12:
  337. if (pinst->bRGB565) {
  338. pinst->pXlate = BuildYUV12ToRGB565(pinst);
  339. } else {
  340. pinst->pXlate = BuildYUV12ToRGB555(pinst);
  341. }
  342. break;
  343. case FOURCC_YUV9:
  344. if (pinst->bRGB565) {
  345. pinst->pXlate = BuildYUV12ToRGB565(pinst); // same to YUV12
  346. } else {
  347. pinst->pXlate = BuildYUV12ToRGB555(pinst); // same to YUV12
  348. }
  349. break;
  350. #endif//COLOR_MODIFY
  351. #endif//TOSHIBA
  352. default:
  353. return((DWORD) ICERR_BADFORMAT);
  354. }
  355. if (pinst->pXlate == NULL) {
  356. return((DWORD) ICERR_MEMORY);
  357. }
  358. pinst->dwFormat = lpbiIn->biCompression;
  359. }
  360. return(ICERR_OK);
  361. }
  362. /*****************************************************************************
  363. ****************************************************************************/
  364. DWORD NEAR PASCAL Decompress(INSTINFO * pinst, ICDECOMPRESS FAR *icinfo, DWORD dwSize)
  365. {
  366. /* must have been a DecompressBegin first */
  367. if (pinst->pXlate == NULL) {
  368. return((DWORD) ICERR_ERROR);
  369. }
  370. #ifdef TOSHIBA
  371. if (pinst->dwFormat == FOURCC_YUV9) {
  372. #ifdef COLOR_MODIFY
  373. if (pinst->bRGB24) {
  374. YUV9ToRGB24(pinst,
  375. icinfo->lpbiInput,
  376. icinfo->lpInput,
  377. icinfo->lpbiOutput,
  378. icinfo->lpOutput
  379. );
  380. } else {
  381. if (pinst->bRGB565) {
  382. YUV9ToRGB565(pinst,
  383. icinfo->lpbiInput,
  384. icinfo->lpInput,
  385. icinfo->lpbiOutput,
  386. icinfo->lpOutput
  387. );
  388. } else {
  389. YUV9ToRGB555(pinst,
  390. icinfo->lpbiInput,
  391. icinfo->lpInput,
  392. icinfo->lpbiOutput,
  393. icinfo->lpOutput
  394. );
  395. }
  396. }
  397. #else //COLOR_MODIFY
  398. YUV9ToRGB(pinst,
  399. icinfo->lpbiInput,
  400. icinfo->lpInput,
  401. icinfo->lpbiOutput,
  402. icinfo->lpOutput
  403. );
  404. #endif//COLOR_MODIFY
  405. } else
  406. if (pinst->dwFormat == FOURCC_YUV12) {
  407. #ifdef COLOR_MODIFY
  408. if (pinst->bRGB24) {
  409. YUV12ToRGB24(pinst,
  410. icinfo->lpbiInput,
  411. icinfo->lpInput,
  412. icinfo->lpbiOutput,
  413. icinfo->lpOutput
  414. );
  415. } else {
  416. if (pinst->bRGB565) {
  417. YUV12ToRGB565(pinst,
  418. icinfo->lpbiInput,
  419. icinfo->lpInput,
  420. icinfo->lpbiOutput,
  421. icinfo->lpOutput
  422. );
  423. } else {
  424. YUV12ToRGB555(pinst,
  425. icinfo->lpbiInput,
  426. icinfo->lpInput,
  427. icinfo->lpbiOutput,
  428. icinfo->lpOutput
  429. );
  430. }
  431. }
  432. #else //COLOR_MODIFY
  433. YUV12ToRGB(pinst,
  434. icinfo->lpbiInput,
  435. icinfo->lpInput,
  436. icinfo->lpbiOutput,
  437. icinfo->lpOutput
  438. );
  439. #endif//COLOR_MODIFY
  440. } else
  441. #endif//TOSHIBA
  442. if (pinst->dwFormat == FOURCC_YUV411) {
  443. YUV411ToRGB(pinst,
  444. icinfo->lpbiInput,
  445. icinfo->lpInput,
  446. icinfo->lpbiOutput,
  447. icinfo->lpOutput
  448. );
  449. } else {
  450. /*
  451. * for compatibility with 16-bit Spigot driver,
  452. * check for Guard field at start of data
  453. */
  454. LPDWORD lpInput = icinfo->lpInput;
  455. if (*lpInput == FOURCC_YUV422) {
  456. lpInput++;
  457. }
  458. YUV422ToRGB(pinst,
  459. icinfo->lpbiInput,
  460. icinfo->lpInput,
  461. icinfo->lpbiOutput,
  462. icinfo->lpOutput
  463. );
  464. }
  465. return ICERR_OK;
  466. }
  467. /*****************************************************************************
  468. *
  469. * DecompressGetPalette() implements ICM_GET_PALETTE
  470. *
  471. * This function has no Compress...() equivalent
  472. *
  473. * It is used to pull the palette from a frame in order to possibly do
  474. * a palette change.
  475. *
  476. ****************************************************************************/
  477. DWORD NEAR PASCAL DecompressGetPalette(INSTINFO * pinst, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut)
  478. {
  479. dprintf2((TEXT("DecompressGetPalette()")));
  480. /*
  481. * only applies to 8-bit output formats. We only decompress to 16 bits
  482. */
  483. return((DWORD) ICERR_BADFORMAT);
  484. }
  485. /*****************************************************************************
  486. ****************************************************************************/
  487. DWORD NEAR PASCAL DecompressEnd(INSTINFO * pinst)
  488. {
  489. if (pinst->pXlate == NULL) {
  490. return (DWORD)ICERR_ERROR;
  491. }
  492. FreeXlate(pinst);
  493. pinst->dwFormat = 0;
  494. return ICERR_OK;
  495. }