icmdxv.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. // dxvmpg.cpp : Defines the entry point for the console application.
  2. //
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include "dkpltfrm.h" /* platform specifics */
  6. #include "duktypes.h" /* predefined general types used at duck */
  7. #include "duck_mem.h" /* interface to memory manager */
  8. #include "dxl_main.h" /* interface to dxv */
  9. #include <windows.h>
  10. #include <mmsystem.h>
  11. #include <vfw.h>
  12. /* formats that might be supported by a codec and dxv */
  13. /* call me crazy ... but I want to make this public ... ie in the HEADER ! */
  14. BMIMapping DXL_BMIMap[] =
  15. {
  16. { DXL_MKFOURCC('Y','V','1','2'), 12, 3, DXYV12 },
  17. { DXL_MKFOURCC('I','Y','U','V'), 12, 1, DXI420 },
  18. { DXL_MKFOURCC('Y','U','Y','2'), 16, 1, DXYUY2 },
  19. { DXL_MKFOURCC('Y','V','Y','U'), 16, 1, DXYVYU },
  20. { DXL_MKFOURCC('U','Y','V','Y'), 16, 1, DXUYVY },
  21. { 0, 24, 1, DXRGB24 },
  22. { 0, 32, 1, DXRGB32 }
  23. };
  24. static char *MakeFourCCString(unsigned long fcc, char *buff)
  25. {
  26. sprintf(buff,"%c%c%c%c",
  27. (fcc & 0xFF) >> 0,
  28. (fcc & 0xFF00) >> 8,
  29. (fcc & 0xFF0000) >> 16,
  30. (fcc & 0xFF000000) >> 24
  31. );
  32. return buff;
  33. }
  34. /* Report to a little HTML file */
  35. void DXL_ReportBMIMapping(char *filename)
  36. {
  37. FILE *fp;
  38. int len = sizeof(DXL_BMIMap) / sizeof(BMIMapping);
  39. fp = fopen(filename,"w");
  40. if (fp)
  41. {
  42. int t;
  43. char temp[5];
  44. fprintf(fp, "<table BORDER=1>");
  45. fprintf(fp, "<tr><td>FOURCC</td><td>BitDepth</td><td>Planes</td><td>dxvBitDepth</td></tr>");
  46. for(t = 0; t < len; t++)
  47. {
  48. fprintf(fp, "<tr><td>%s<br>%x</td> <td>%ld</td> <td>%ld</td> <td>%ld</td></tr>",
  49. MakeFourCCString(DXL_BMIMap[t].biCompression,temp),
  50. DXL_BMIMap[t].biCompression,
  51. DXL_BMIMap[t].biBitCount,
  52. DXL_BMIMap[t].biPlanes,
  53. DXL_BMIMap[t].bd
  54. );
  55. }
  56. fprintf(fp,"</table>");
  57. fclose(fp);
  58. }
  59. }
  60. /********* USAGE
  61. In addition to regular DXV services, this library will invoke VFW
  62. codecs for decompression services.
  63. Because of a bug in the frame parsing, the library is compiled to
  64. decompress TM2X via its codec as well. So be certain to have a
  65. TM2X VFW codec installed.
  66. The library has only been tested with TM2X(2.5.1.8),
  67. Indeo 5.2 and MPEG4.2. Other codecs may work, but only if
  68. they support RGB32, RGB24, and RGB16 (555 and/or 565).
  69. MS-CRAM and Cinepak crashed painfully in tests so far.
  70. The library assumes support for all 4 RGB truecolor modes
  71. mentioned above, (NOTE: TM2X doesn't support RGB24 yet!)
  72. - 5/19/99 -
  73. We added black-lining blitters for stretched modes. Note that
  74. 24 bit display uses a 32bit offscreen buffer which is blitted
  75. down to 24bit when stretched, this makes the asm code that much
  76. simpler.
  77. To use:
  78. in addition to the regular DXV,
  79. link s_icm.lib to your application and do the following
  80. substitute:
  81. DXL_InitVideoEx(int lmaxScreens,int lmaxImages);
  82. in place of:
  83. DXL_InitVideo(int lmaxScreens,int lmaxImages)
  84. use:
  85. movie->xImage =
  86. DXL_AlterXImage(movie->xImage,movie->vData,
  87. HFB_GetStreamInfo(movie->vStream)->a.BitmapInfo.ulHandler,
  88. 0,
  89. HFB_GetStreamInfo(movie->vStream)->a.BitmapInfo.usWidth,
  90. HFB_GetStreamInfo(movie->vStream)->a.BitmapInfo.usHeight);
  91. in place of:
  92. movie->xImage = DXL_CreateXImage(movie->vData);
  93. and, prior to any calls to:
  94. DXL_dxImageToVScreen(movie->xImage, movie->vScreen);
  95. you must call:
  96. DXL_SetXImageCSize(movie->xImage, movie->vLength);
  97. ********/
  98. static dxvBitDepth bitDepths[] =
  99. {
  100. DXRGB32,DXRGB24,DXRGB16,DXRGBNULL
  101. };
  102. /* define an xImage structure based on the core xImage struct */
  103. typedef struct tXImageCODEC{
  104. xImageBaseStruct;
  105. DK_BITMAPINFOHEADER bihIn;
  106. unsigned long bihInFields[3];
  107. DK_BITMAPINFOHEADER bihOut;
  108. unsigned long bihOutFields[3];
  109. HIC hic;
  110. int changeVScreen;
  111. BMIMapping* maps[20];
  112. int maxMaps;
  113. } DXL_CODEC,*DXL_CODEC_HANDLE;
  114. char* DXL_DecodeICERR(int err, char *storage, int length)
  115. {
  116. (void)length; // not used
  117. switch (err)
  118. {
  119. case ICERR_UNSUPPORTED :
  120. strcpy(storage,"ICERR_UNSUPPORTED");
  121. break;
  122. case ICERR_BADFORMAT :
  123. strcpy(storage,"ICERR_BADFORMAT");
  124. break;
  125. case ICERR_MEMORY :
  126. strcpy(storage,"ICERR_MEMORY");
  127. break;
  128. case ICERR_ERROR :
  129. strcpy(storage,"ICERR_ERROR");
  130. break;
  131. default :
  132. strcpy(storage,"Defaulted to ICERR_ERROR");
  133. break;
  134. }
  135. return storage;
  136. }
  137. DK_BITMAPINFOHEADER* DXL_VSCREEN_2_BMI
  138. (
  139. DXL_XIMAGE_HANDLE xImage,
  140. DXL_VSCREEN_HANDLE vScreen,
  141. DK_BITMAPINFOHEADER *bmih,
  142. dxvBitDepth* bd1
  143. )
  144. {
  145. unsigned char *addr;
  146. dxvBlitQuality bq;
  147. dxvBitDepth bd;
  148. short pitch;
  149. short height;
  150. int t;
  151. DXL_CODEC_HANDLE src = (DXL_CODEC_HANDLE ) xImage;
  152. duck_memcpy(bmih,&((DXL_CODEC_HANDLE ) xImage)->bihIn,sizeof(DK_BITMAPINFOHEADER));
  153. DXL_GetVScreenAttributes(vScreen, (void **) &addr, &bq, &bd, &pitch, &height );
  154. for(t = 0; t < src->maxMaps; t++)
  155. {
  156. if (src->maps[t]->bd == bd)
  157. {
  158. bmih->biBitCount = src->maps[t]->biBitCount;
  159. bmih->biCompression = src->maps[t]->biCompression;
  160. bmih->biPlanes = src->maps[t]->biPlanes;
  161. bmih->biWidth = pitch / (bmih->biBitCount / 8);
  162. bmih->biHeight = height;
  163. bmih->biSizeImage = pitch * bmih->biHeight;
  164. fprintf(stderr,"\nBMI from VScreen attributes ...\n");
  165. fprintf(stderr,"\t pitch = %ld\n", pitch);
  166. fprintf(stderr,"\t width = %ld\n", bmih->biWidth);
  167. fprintf(stderr,"\t height = %ld\n", bmih->biHeight);
  168. fprintf(stderr,"\t biCompression = %c%c%c%c\n",
  169. ((char *) &bmih->biCompression)[0],
  170. ((char *) &bmih->biCompression)[1],
  171. ((char *) &bmih->biCompression)[2],
  172. ((char *) &bmih->biCompression)[3]
  173. );
  174. fflush(stderr);
  175. return bmih;
  176. }
  177. }
  178. *bd1 = bd;
  179. return 0;
  180. }
  181. int DXL_ReportBestBMIMatch(DXL_XIMAGE_HANDLE xImage, BMIMapping** map, int *maxMaps, int doConsoleReport)
  182. {
  183. int t;
  184. int ret;
  185. char buff[5];
  186. int len = sizeof(DXL_BMIMap)/sizeof(BMIMapping);
  187. int matches = 0;
  188. DXL_CODEC_HANDLE src = (DXL_CODEC_HANDLE ) xImage;
  189. DK_BITMAPINFOHEADER temp;
  190. (void)doConsoleReport; //unused
  191. src->bihIn.dxFlavor = 2; /* use the extended ICM functions */
  192. duck_memcpy(&temp,&src->bihIn,sizeof(DK_BITMAPINFOHEADER));
  193. for(t = 0; t < len; t++) /* for each one we support with out mapping */
  194. {
  195. temp.biBitCount = DXL_BMIMap[t].biBitCount;
  196. temp.biCompression = DXL_BMIMap[t].biCompression;
  197. temp.biPlanes = DXL_BMIMap[t].biPlanes;
  198. temp.biSizeImage = temp.biBitCount * temp.biWidth * temp.biHeight / 8;
  199. ret = ICDecompressQuery(src->hic, &(src->bihIn), &temp );
  200. if (ret == ICERR_OK)
  201. {
  202. fprintf(stderr,"format of %s supported, planes = %ld, rank = %ld\n",
  203. MakeFourCCString(temp.biCompression, buff ), temp.biPlanes, matches + 1);
  204. fflush(stderr);
  205. if (matches < *maxMaps)
  206. {
  207. src->maps[matches] = map[matches] = &DXL_BMIMap[t];
  208. matches += 1;
  209. }
  210. }
  211. else
  212. {
  213. fprintf(stderr,"format of %s NOT supported, planes = %ld\n",
  214. MakeFourCCString(temp.biCompression, buff ), temp.biPlanes);
  215. fflush(stderr);
  216. }
  217. }
  218. src->maxMaps = *maxMaps = matches;
  219. /* This could be done somewhere else ! */
  220. duck_memset(&src->bihOut,0,sizeof(DK_BITMAPINFOHEADER));
  221. return matches;
  222. }
  223. static int decompress1(DXL_XIMAGE_HANDLE xImage, DXL_VSCREEN_HANDLE vScreen)
  224. {
  225. /* Keep the warnings away ! */
  226. DXL_CODEC_HANDLE src = (DXL_CODEC_HANDLE ) xImage;
  227. // DWORD dwFlags = 0;
  228. DWORD ret;
  229. dxvBitDepth bd;
  230. int changeOutput = src->changeVScreen;
  231. if (changeOutput)
  232. {
  233. /* should be cleared first time in so width zero ! */
  234. if (src->bihOut.biWidth != 0)
  235. ICDecompressEnd(src->hic);
  236. if ( DXL_VSCREEN_2_BMI(xImage, vScreen, (DK_BITMAPINFOHEADER *) &(src->bihOut), &bd ) == 0)
  237. {
  238. /* user asks for unsupported surface FOURCC */
  239. fprintf(stderr, "User asks for unsupported dxvBitDepth = %ld\n", bd );
  240. fflush(stderr);
  241. return ICERR_BADFORMAT;
  242. }
  243. ret = ICDecompressBegin(src->hic, &src->bihIn, &src->bihOut);
  244. if (ret != ICERR_OK)
  245. {
  246. return ret;
  247. }
  248. }
  249. src->bihIn.biSizeImage = src->fSize;
  250. ret = ICDecompress( src->hic, 0,
  251. (BITMAPINFOHEADER *) &src->bihIn, src->addr,
  252. (BITMAPINFOHEADER *) &src->bihOut,
  253. (char *) vScreen->addr);
  254. if (ret != ICERR_OK)
  255. {
  256. fprintf(stderr,"Oh boy decompress may have failed !\n");
  257. assert(0);
  258. exit(0);
  259. }
  260. src->changeVScreen = 0;
  261. return ICERR_OK;
  262. }
  263. static int decompress2(DXL_XIMAGE_HANDLE xImage, DXL_VSCREEN_HANDLE vScreen)
  264. {
  265. /* Keep the warnings away ! */
  266. DXL_CODEC_HANDLE src = (DXL_CODEC_HANDLE ) xImage;
  267. DWORD dwFlags = 0;
  268. DWORD ret;
  269. dxvBitDepth bd;
  270. if (src->changeVScreen)
  271. {
  272. /* should be cleared first time in so width zero ! */
  273. if (src->bihOut.biWidth != 0)
  274. ICDecompressExEnd(src->hic);
  275. if ( DXL_VSCREEN_2_BMI(xImage, vScreen, (DK_BITMAPINFOHEADER *) &(src->bihOut), &bd ) == 0)
  276. {
  277. /* user asks for unsupported surface FOURCC */
  278. fprintf(stderr, "User asks for unsupported dxvBitDepth = %ld\n", bd );
  279. fflush(stderr);
  280. return ICERR_BADFORMAT;
  281. }
  282. ret = ICDecompressExBegin(
  283. src->hic,
  284. dwFlags,
  285. (BITMAPINFOHEADER *) &(src->bihIn),
  286. src->addr,
  287. 0,
  288. 0,
  289. src->bihIn.biWidth,
  290. src->bihIn.biHeight,
  291. (BITMAPINFOHEADER *) &(src->bihOut),
  292. (char *) vScreen->addr,
  293. 0,
  294. 0,
  295. src->bihIn.biWidth,
  296. src->bihIn.biHeight
  297. );
  298. if (ret == ICERR_UNSUPPORTED)
  299. {
  300. return ICERR_UNSUPPORTED;
  301. }
  302. if (ret != ICERR_OK)
  303. {
  304. char *storage = (char *) calloc(256,sizeof(char));
  305. fprintf(stderr,"ICDecompressExBegin returns error code = %ld\n", ret);
  306. fprintf(stderr,"Decoded as ... %s\n", DXL_DecodeICERR(ret, storage, sizeof(storage) - 1));
  307. fflush(stderr);
  308. if (storage)
  309. free(storage);
  310. assert(0);
  311. }
  312. src->changeVScreen = 0;
  313. }
  314. src->bihIn.biSizeImage = src->fSize;
  315. ret = ICDecompressEx(
  316. src->hic,
  317. dwFlags,
  318. (BITMAPINFOHEADER *) &src->bihIn,
  319. src->addr,
  320. 0,
  321. 0,
  322. src->bihIn.biWidth,
  323. src->bihIn.biHeight,
  324. (BITMAPINFOHEADER *) &src->bihOut,
  325. (char *) vScreen->addr,
  326. 0,
  327. 0,
  328. src->bihIn.biWidth,
  329. src->bihIn.biHeight
  330. );
  331. if (ret != ICERR_OK)
  332. {
  333. fprintf(stderr,"Oh boy decompress may have failed !\n");
  334. assert(0);
  335. exit(0);
  336. }
  337. return 0;
  338. }
  339. static int decompress(DXL_XIMAGE_HANDLE xImage, DXL_VSCREEN_HANDLE vScreen2)
  340. {
  341. DXL_CODEC_HANDLE xThis = (DXL_CODEC_HANDLE) xImage;
  342. int retVal = ICERR_OK;
  343. /* Try the version that handles wack pitch first ! */
  344. if (xThis->bihIn.dxFlavor == 2)
  345. {
  346. retVal = decompress2(xImage, vScreen2);
  347. if (retVal == ICERR_UNSUPPORTED)
  348. {
  349. xThis->bihIn.dxFlavor = 1;
  350. }
  351. }
  352. /* if the wack pitch one failed */
  353. if (xThis->bihIn.dxFlavor == 1)
  354. {
  355. retVal = decompress1(xImage, vScreen2);
  356. }
  357. return retVal;
  358. }
  359. /*
  360. close down a decompressor, releasing the icm decompressor,
  361. the xImage (decompressor), and the intermediate vScreen (surface)
  362. */
  363. static int destroyCodec(DXL_XIMAGE_HANDLE xImage)
  364. {
  365. DXL_CODEC_HANDLE xThis = (DXL_CODEC_HANDLE ) xImage;
  366. if (xThis)
  367. {
  368. if (xThis->hic)
  369. {
  370. ICDecompressEnd(xThis->hic);
  371. ICClose(xThis->hic);
  372. }
  373. duck_free(xThis);
  374. }
  375. return DXL_OK;
  376. }
  377. static char* duckToNarrow(char *s)
  378. {
  379. char dst[256];
  380. int t=0;
  381. if (s)
  382. {
  383. do
  384. {
  385. dst[t] = s[2*t];
  386. t = t + 1;
  387. }
  388. while ( *((short *) &s[t]) );
  389. dst[t] = '\0';
  390. strcpy(s,dst);
  391. return s;
  392. }
  393. else
  394. {
  395. return 0;
  396. }
  397. } /* end duckToNarrow */
  398. /*
  399. called during initialization and/or when xImage (decompressor)
  400. attributes change, note that nImage and src are actually
  401. synonymous and should be cleared out a bit (to say the least!)
  402. !!!!!!
  403. This function should be prepared to get data that is NOT of the
  404. type native to the decoder, It should do it's best to verify it
  405. as valid data and should clean up after itself and return NULL
  406. if it doesn't recognize the format of the data
  407. */
  408. static DXL_XIMAGE_HANDLE reCreateCodec(DXL_CODEC_HANDLE src,unsigned char *data,
  409. int type,enum BITDEPTH bitDepth,int w,int h)
  410. {
  411. #pragma warning(disable: 4210) // nonstandard extension used : function given file scope
  412. DXL_XIMAGE_HANDLE createCodec(unsigned char *data);
  413. #pragma warning(default: 4210) // nonstandard extension used : function given file scope
  414. DXL_XIMAGE_HANDLE nImage;
  415. DK_BITMAPINFOHEADER *bmiHeader = (DK_BITMAPINFOHEADER *) data;
  416. unsigned long fccHandler;
  417. (void)h; // unused
  418. (void)w; // unused
  419. (void)bitDepth; //unused
  420. (void)type; //unused
  421. if (src != NULL) /* if an xImage/decompressor already exists, destroy it */
  422. destroyCodec((DXL_XIMAGE_HANDLE ) src);
  423. /* create a new xImage, specific to this type of decoder, (
  424. see "DXL_CODEC" struct above and dxl_main.h) */
  425. nImage = (DXL_XIMAGE_HANDLE)duck_calloc(1,sizeof(DXL_CODEC),DMEM_GENERAL);
  426. src = (DXL_CODEC_HANDLE ) nImage;
  427. if (!nImage) return NULL;
  428. duck_memset(nImage,0,sizeof(DXL_CODEC));
  429. src->changeVScreen = 1; /* True ... inform decompresss the dest has changed */
  430. /* set up the "vtable" of interface calls */
  431. src->create = (DXL_XIMAGE_HANDLE (*)(void *)) createCodec;
  432. src->recreate = (DXL_XIMAGE_HANDLE (*)(DXL_XIMAGE_HANDLE,void *,int,int,int,int)) reCreateCodec;
  433. nImage->destroy = destroyCodec;
  434. nImage->dx = decompress;
  435. nImage->blit = NULL; /* there is no interleaved blitter for codecs */
  436. src->bdPrefs = bitDepths; /* plug in the list of prefered bit depths */
  437. nImage->addr = data;
  438. nImage->dkFlags.inUse = 1;
  439. duck_memcpy(&src->bihIn, bmiHeader,sizeof(DK_BITMAPINFOHEADER));
  440. duck_memset(&src->bihOut, 0, sizeof(DK_BITMAPINFOHEADER));
  441. src->w = (short ) (src->bihIn.biWidth);
  442. src->h = (short ) (src->bihIn.biHeight);
  443. src->imWidth = (short) src->w;
  444. src->imHeight = (short) src->h;
  445. fccHandler = src->bihIn.fccHandler;
  446. if (fccHandler == 0)
  447. {
  448. src->hic=ICLocate(ICTYPE_VIDEO, fccHandler, (BITMAPINFOHEADER *) &src->bihIn, 0, ICMODE_DECOMPRESS);
  449. }
  450. else
  451. {
  452. src->hic=ICOpen(ICTYPE_VIDEO, fccHandler, ICMODE_DECOMPRESS);
  453. }
  454. {
  455. ICINFO i;
  456. memset(&i,0,sizeof(ICINFO));
  457. if (ICGetInfo( src->hic, &i, sizeof(ICINFO) ))
  458. {
  459. char temp[5];
  460. unsigned long biCompression = src->bihIn.biCompression;
  461. fccHandler = src->bihIn.fccHandler = i.fccHandler;
  462. fprintf(stderr, "Short Name : %s\n"
  463. "Driver : %s\n"
  464. "driver version = %d %d or as hex = %x\n"
  465. "Description : %s\n"
  466. "Codec biCompression = %s\n"
  467. "Codec fccHandler = %s\n",
  468. duckToNarrow( (char *) i.szName),
  469. duckToNarrow( (char *) i.szDriver),
  470. ((i.dwVersion & 0x0000FFFF) >> 0 ),
  471. ((i.dwVersion & 0xFFFF0000) >> 16 ),
  472. i.dwVersion,
  473. duckToNarrow( (char *) i.szDescription),
  474. MakeFourCCString(biCompression, temp),
  475. MakeFourCCString(fccHandler, temp)
  476. );
  477. fflush(stderr);
  478. }
  479. }
  480. if (src->hic == 0)
  481. {
  482. destroyCodec((DXL_XIMAGE_HANDLE ) src);
  483. fprintf(stderr, "codec for fourCC = %c%c%c%c, %x won't open\n",
  484. (fccHandler & 0xFF000000) >> 24,
  485. (fccHandler & 0xFF0000) >> 16,
  486. (fccHandler & 0xFF00) >> 8,
  487. (fccHandler & 0xFF) >> 0,
  488. fccHandler
  489. );
  490. fflush(stderr);
  491. return 0;
  492. }
  493. return nImage;
  494. }
  495. /* in this "glue" case, just calls through to the create function */
  496. #pragma warning(disable:4211) //nonstandard extension used : redefined extern to static
  497. static DXL_XIMAGE_HANDLE createCodec(unsigned char *bmih)
  498. {
  499. return reCreateCodec(NULL, bmih ,0,(enum BITDEPTH ) 0,0,0);
  500. }
  501. #pragma warning(default:4211) //nonstandard extension used : redefined extern to static