1 /* 2 * Unit tests for video playback 3 * 4 * Copyright 2008,2010 Jörg Höhle 5 * Copyright 2008 Austin English 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define WIN32_LEAN_AND_MEAN 23 #include <windows.h> 24 #include <vfw.h> 25 26 #include "wine/test.h" 27 28 static inline int get_stride(int width, int depth) 29 { 30 return ((depth * width + 31) >> 3) & ~3; 31 } 32 33 static void test_OpenCase(void) 34 { 35 HIC h; 36 ICINFO info; 37 /* Check if default handler works */ 38 h = ICOpen(mmioFOURCC('v','i','d','c'),0,ICMODE_DECOMPRESS); 39 ok(0!=h,"ICOpen(vidc.0) failed\n"); 40 if (h) { 41 info.dwSize = sizeof(info); 42 info.szName[0] = 0; 43 ICGetInfo(h, &info, sizeof(info)); 44 trace("The default decompressor is %s\n", wine_dbgstr_w(info.szName)); 45 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 46 } 47 h = ICOpen(mmioFOURCC('v','i','d','c'),0,ICMODE_COMPRESS); 48 ok(0!=h || broken(h == 0),"ICOpen(vidc.0) failed\n"); /* Not present in Win8 */ 49 if (h) { 50 info.dwSize = sizeof(info); 51 info.szName[0] = 0; 52 ICGetInfo(h, &info, sizeof(info)); 53 trace("The default compressor is %s\n", wine_dbgstr_w(info.szName)); 54 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 55 } 56 57 /* Open a compressor with combinations of lowercase 58 * and uppercase compressortype and handler. 59 */ 60 h = ICOpen(mmioFOURCC('v','i','d','c'),mmioFOURCC('m','s','v','c'),ICMODE_DECOMPRESS); 61 ok(0!=h,"ICOpen(vidc.msvc) failed\n"); 62 if (h) { 63 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 64 } 65 h = ICOpen(mmioFOURCC('v','i','d','c'),mmioFOURCC('M','S','V','C'),ICMODE_DECOMPRESS); 66 ok(0!=h,"ICOpen(vidc.MSVC) failed\n"); 67 if (h) { 68 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 69 } 70 h = ICOpen(mmioFOURCC('V','I','D','C'),mmioFOURCC('m','s','v','c'),ICMODE_DECOMPRESS); 71 ok(0!=h,"ICOpen(VIDC.msvc) failed\n"); 72 if (h) { 73 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 74 } 75 h = ICOpen(mmioFOURCC('V','I','D','C'),mmioFOURCC('M','S','V','C'),ICMODE_DECOMPRESS); 76 ok(0!=h,"ICOpen(VIDC.MSVC) failed\n"); 77 if (h) { 78 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 79 } 80 h = ICOpen(mmioFOURCC('v','i','d','c'),mmioFOURCC('m','S','v','C'),ICMODE_DECOMPRESS); 81 ok(0!=h,"ICOpen(vidc.mSvC) failed\n"); 82 if (h) { 83 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 84 } 85 h = ICOpen(mmioFOURCC('v','I','d','C'),mmioFOURCC('m','s','v','c'),ICMODE_DECOMPRESS); 86 ok(0!=h,"ICOpen(vIdC.msvc) failed\n"); 87 if (h) { 88 ok(ICClose(h)==ICERR_OK,"ICClose failed\n"); 89 } 90 } 91 92 static void test_Locate(void) 93 { 94 static BITMAPINFOHEADER bi = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RLE8, 0,100000,100000, 0,0}; 95 static BITMAPINFOHEADER bo = {sizeof(BITMAPINFOHEADER),32,8, 1,8, BI_RGB, 0,100000,100000, 0,0}; 96 BITMAPINFOHEADER tmp = {sizeof(BITMAPINFOHEADER)}; 97 HIC h; 98 DWORD err; 99 100 /* Oddly, MSDN documents that ICLocate takes BITMAPINFOHEADER 101 * pointers, while ICDecompressQuery takes the larger 102 * BITMAPINFO. Probably it's all the same as long as the 103 * variable length color quads are present when they are 104 * needed. */ 105 106 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 107 ok(h != 0, "RLE8->RGB failed\n"); 108 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 109 110 bo.biHeight = - bo.biHeight; 111 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 112 ok(h == 0, "RLE8->RGB height<0 succeeded\n"); 113 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 114 bo.biHeight = - bo.biHeight; 115 116 bi.biCompression = mmioFOURCC('c','v','i','d'); /* Cinepak */ 117 h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('c','v','i','d'), ICMODE_DECOMPRESS); 118 if (h == 0) win_skip("Cinepak/ICCVID codec not found\n"); 119 else { 120 bo.biBitCount = bi.biBitCount = 32; 121 err = ICDecompressQuery(h, &bi, &bo); 122 ok(err == ICERR_OK, "Query cvid->RGB32: %d\n", err); 123 124 err = ICDecompressQuery(h, &bi, NULL); 125 ok(err == ICERR_OK, "Query cvid 32: %d\n", err); 126 127 bo.biHeight = -bo.biHeight; 128 err = ICDecompressQuery(h, &bi, &bo); 129 ok(err == ICERR_OK, "Query cvid->RGB32 height<0: %d\n", err); 130 bo.biHeight = -bo.biHeight; 131 132 bi.biWidth = 17; 133 134 bi.biBitCount = 8; 135 err = ICDecompressGetFormat(h, &bi, &tmp); 136 ok(err == ICERR_OK, "Query cvid output format: %d\n", err); 137 ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount); 138 ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n", 139 get_stride(17, 24) * 8, tmp.biSizeImage); 140 141 bi.biBitCount = 15; 142 err = ICDecompressGetFormat(h, &bi, &tmp); 143 ok(err == ICERR_OK, "Query cvid output format: %d\n", err); 144 ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount); 145 ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n", 146 get_stride(17, 24) * 8, tmp.biSizeImage); 147 148 bi.biBitCount = 16; 149 err = ICDecompressGetFormat(h, &bi, &tmp); 150 ok(err == ICERR_OK, "Query cvid output format: %d\n", err); 151 ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount); 152 ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n", 153 get_stride(17, 24) * 8, tmp.biSizeImage); 154 155 bi.biBitCount = 24; 156 err = ICDecompressGetFormat(h, &bi, &tmp); 157 ok(err == ICERR_OK, "Query cvid output format: %d\n", err); 158 ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount); 159 ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n", 160 get_stride(17, 24) * 8, tmp.biSizeImage); 161 162 bi.biBitCount = 32; 163 err = ICDecompressGetFormat(h, &bi, &tmp); 164 ok(err == ICERR_OK, "Query cvid output format: %d\n", err); 165 ok(tmp.biBitCount == 24, "Expected 24 bit, got %d bit\n", tmp.biBitCount); 166 ok(tmp.biSizeImage == get_stride(17, 24) * 8, "Expected size %d, got %d\n", 167 get_stride(17, 24) * 8, tmp.biSizeImage); 168 169 bi.biWidth = 32; 170 171 ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 172 173 bo.biBitCount = bi.biBitCount = 8; 174 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 175 todo_wine ok(h != 0, "cvid->RGB8 failed\n"); 176 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 177 bo.biHeight = - bo.biHeight; 178 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 179 todo_wine ok(h != 0, "cvid->RGB8 height<0 failed\n"); 180 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 181 bo.biHeight = - bo.biHeight; 182 183 bo.biBitCount = bi.biBitCount = 16; 184 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 185 ok(h != 0, "cvid->RGB16 failed\n"); 186 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 187 bo.biHeight = - bo.biHeight; 188 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 189 ok(h != 0, "cvid->RGB16 height<0 failed\n"); 190 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 191 bo.biHeight = - bo.biHeight; 192 193 bo.biBitCount = bi.biBitCount = 32; 194 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 195 ok(h != 0, "cvid->RGB32 failed\n"); 196 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 197 bo.biHeight = - bo.biHeight; 198 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 199 ok(h != 0, "cvid->RGB32 height<0 failed\n"); 200 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 201 bo.biHeight = - bo.biHeight; 202 203 bi.biCompression = mmioFOURCC('C','V','I','D'); 204 /* Unlike ICOpen, upper case fails with ICLocate. */ 205 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 206 ok(h == 0, "CVID->RGB32 upper case succeeded\n"); 207 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 208 } 209 210 bi.biCompression = mmioFOURCC('M','S','V','C'); /* MS Video 1 */ 211 212 bo.biBitCount = bi.biBitCount = 16; 213 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 214 ok(h != 0, "MSVC->RGB16 failed\n"); 215 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 216 217 bo.biHeight = - bo.biHeight; 218 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 219 todo_wine ok(h != 0, "MSVC->RGB16 height<0 failed\n"); 220 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 221 bo.biHeight = - bo.biHeight; 222 223 bo.biHeight--; 224 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 225 ok(h == 0, "MSVC->RGB16 height too small succeeded\n"); 226 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 227 bo.biHeight++; 228 229 /* ICLocate wants upper case MSVC */ 230 bi.biCompression = mmioFOURCC('m','s','v','c'); 231 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 232 ok(h == 0, "msvc->RGB16 succeeded\n"); 233 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 234 235 bi.biCompression = mmioFOURCC('M','S','V','C'); 236 h = ICOpen(ICTYPE_VIDEO, mmioFOURCC('M','S','V','C'), ICMODE_DECOMPRESS); 237 ok(h != 0, "No MSVC codec installed!?\n"); 238 if (h != 0) { 239 err = ICDecompressQuery(h, &bi, &bo); 240 ok(err == ICERR_OK, "Query MSVC->RGB16: %d\n", err); 241 242 err = ICDecompressQuery(h, &bi, NULL); 243 ok(err == ICERR_OK, "Query MSVC 16: %d\n", err); 244 245 bo.biHeight = -bo.biHeight; 246 err = ICDecompressQuery(h, &bi, &bo); 247 todo_wine ok(err == ICERR_OK, "Query MSVC->RGB16 height<0: %d\n", err); 248 bo.biHeight = -bo.biHeight; 249 250 bo.biBitCount = 24; 251 err = ICDecompressQuery(h, &bi, &bo); 252 ok(err == ICERR_OK, "Query MSVC 16->24: %d\n", err); 253 bo.biBitCount = 16; 254 255 bi.biWidth = 553; 256 257 bi.biBitCount = 8; 258 err = ICDecompressGetFormat(h, &bi, &tmp); 259 ok(err == ICERR_OK, "Query MSVC output format: %d\n", err); 260 ok(tmp.biBitCount == 8, "Expected 8 bit, got %d bit\n", tmp.biBitCount); 261 ok(tmp.biWidth == 552, "Expected width 552, got %d\n", tmp.biWidth); 262 ok(tmp.biSizeImage == get_stride(552, 8) * 8, "Expected size %d, got %d\n", 263 get_stride(552, 8) * 8, tmp.biSizeImage); 264 265 bi.biBitCount = 15; 266 err = ICDecompressGetFormat(h, &bi, &tmp); 267 ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err); 268 269 bi.biBitCount = 16; 270 err = ICDecompressGetFormat(h, &bi, &tmp); 271 ok(err == ICERR_OK, "Query MSVC output format: %d\n", err); 272 ok(tmp.biBitCount == 16, "Expected 16 bit, got %d bit\n", tmp.biBitCount); 273 ok(tmp.biWidth == 552, "Expected width 552, got %d\n", tmp.biWidth); 274 ok(tmp.biSizeImage == get_stride(552, 16) * 8, "Expected size %d, got %d\n", 275 get_stride(552, 16) * 8, tmp.biSizeImage); 276 277 bi.biBitCount = 24; 278 err = ICDecompressGetFormat(h, &bi, &tmp); 279 ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err); 280 281 bi.biBitCount = 32; 282 err = ICDecompressGetFormat(h, &bi, &tmp); 283 ok(err == ICERR_BADFORMAT, "Query MSVC output format: %d\n", err); 284 285 bi.biHeight = 17; 286 bi.biBitCount = 8; 287 err = ICDecompressGetFormat(h, &bi, &tmp); 288 ok(err == ICERR_OK, "Query MSVC output format: %d\n", err); 289 ok(tmp.biHeight == 16, "Expected height 16, got %d\n", tmp.biHeight); 290 bi.biHeight = 8; 291 292 bi.biWidth = 32; 293 294 bi.biCompression = mmioFOURCC('m','s','v','c'); 295 err = ICDecompressQuery(h, &bi, &bo); 296 ok(err == ICERR_BADFORMAT, "Query msvc->RGB16: %d\n", err); 297 298 ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 299 } 300 301 bi.biCompression = BI_RGB; 302 bo.biBitCount = bi.biBitCount = 8; 303 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 304 ok(h != 0, "RGB8->RGB identity failed\n"); 305 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 306 307 bi.biCompression = BI_RLE8; 308 h = ICLocate(ICTYPE_VIDEO, 0, &bi, &bo, ICMODE_DECOMPRESS); 309 ok(h != 0, "RLE8->RGB again failed\n"); 310 if (h) ok(ICClose(h) == ICERR_OK,"ICClose failed\n"); 311 } 312 313 static void test_ICSeqCompress(void) 314 { 315 /* The purpose of this test is to validate sequential frame compressing 316 * functions. The MRLE codec will be used because Wine supports it and 317 * it is present in any Windows. 318 */ 319 HIC h; 320 DWORD err, vidc = mmioFOURCC('v','i','d','c'), mrle = mmioFOURCC('m', 'r', 'l', 'e'); 321 DWORD i; 322 LONG frame_len; 323 BOOL key_frame, ret; 324 char *frame; 325 COMPVARS pc; 326 struct { BITMAPINFOHEADER header; RGBQUAD map[256]; } 327 input_header = { {sizeof(BITMAPINFOHEADER), 32, 1, 1, 8, 0, 32*8, 0, 0, 256, 256}, 328 {{255,0,0}, {0,255,0}, {0,0,255}, {255,255,255}}}; 329 PBITMAPINFO bitmap = (PBITMAPINFO) &input_header; 330 static BYTE input[32] = {1,2,3,3,3,3,2,3,1}; 331 static const BYTE output_kf[] = {1,1,1,2,4,3,0,3,2,3,1,0,23,0,0,0,0,1}, /* key frame*/ 332 output_nkf[] = {0,0,0,1}; /* non key frame */ 333 334 h = ICOpen(vidc, mrle, ICMODE_COMPRESS); 335 ok(h != NULL, "Expected non-NULL\n"); 336 337 pc.cbSize = sizeof(pc); 338 pc.dwFlags = ICMF_COMPVARS_VALID; 339 pc.fccType = vidc; 340 pc.fccHandler = mrle; 341 pc.hic = h; 342 pc.lpbiIn = NULL; 343 pc.lpbiOut = NULL; 344 pc.lpBitsOut = pc.lpBitsPrev = pc.lpState = NULL; 345 pc.lQ = ICQUALITY_DEFAULT; 346 pc.lKey = 1; 347 pc.lDataRate = 300; 348 pc.lpState = NULL; 349 pc.cbState = 0; 350 351 ret = ICSeqCompressFrameStart(&pc, bitmap); 352 ok(ret == TRUE, "Expected TRUE\n"); 353 /* Check that reserved pointers were allocated */ 354 ok(pc.lpbiIn != NULL, "Expected non-NULL\n"); 355 ok(pc.lpbiOut != NULL, "Expected non-NULL\n"); 356 357 for(i = 0; i < 9; i++) 358 { 359 frame_len = 0; 360 frame = ICSeqCompressFrame(&pc, 0, input, &key_frame, &frame_len); 361 ok(frame != NULL, "Frame[%d]: Expected non-NULL\n", i); 362 if (frame_len == sizeof(output_nkf)) 363 ok(!memcmp(output_nkf, frame, frame_len), "Frame[%d]: Contents do not match\n", i); 364 else if (frame_len == sizeof(output_kf)) 365 ok(!memcmp(output_kf, frame, frame_len), "Frame[%d]: Contents do not match\n", i); 366 else 367 ok(0, "Unknown frame size of %d byten\n", frame_len); 368 } 369 370 ICSeqCompressFrameEnd(&pc); 371 ICCompressorFree(&pc); 372 /* ICCompressorFree already closed the HIC */ 373 err = ICClose(h); 374 ok(err == ICERR_BADHANDLE, "Expected -8, got %d\n", err); 375 } 376 377 static ICINFO enum_info; 378 379 static LRESULT CALLBACK enum_driver_proc(DWORD_PTR id, HDRVR driver, UINT msg, 380 LPARAM lparam1, LPARAM lparam2) 381 { 382 ICINFO *info = (ICINFO *)lparam1; 383 384 ok(!id, "Got unexpected id %#lx.\n", id); 385 ok(msg == ICM_GETINFO, "Got unexpected message %#x.\n", msg); 386 ok(info == &enum_info, "Expected lparam1 %p, got %p.\n", &enum_info, info); 387 ok(lparam2 == sizeof(ICINFO), "Got lparam2 %ld.\n", lparam2); 388 389 ok(!info->fccType, "Got unexpected type %#x.\n", info->fccType); 390 ok(!info->fccHandler, "Got unexpected handler %#x.\n", info->fccHandler); 391 ok(!info->dwFlags, "Got unexpected flags %#x.\n", info->dwFlags); 392 ok(!info->dwVersion, "Got unexpected version %#x.\n", info->dwVersion); 393 ok(info->dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info->dwVersionICM); 394 ok(!info->szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info->szName)); 395 ok(!info->szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info->szDescription)); 396 ok(!info->szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(info->szDriver)); 397 398 info->dwVersion = 0xdeadbeef; 399 return sizeof(ICINFO); 400 } 401 402 static void test_ICInfo(void) 403 { 404 static const WCHAR bogusW[] = {'b','o','g','u','s',0}; 405 static const DWORD test_type = mmioFOURCC('w','i','n','e'); 406 static const DWORD test_handler = mmioFOURCC('t','e','s','t'); 407 DWORD i = 0, found = 0; 408 char buffer[MAX_PATH]; 409 ICINFO info, info2; 410 unsigned char *fcc; 411 DWORD size; 412 BOOL ret; 413 HKEY key; 414 LONG res; 415 416 for (;;) 417 { 418 memset(&info, 0x55, sizeof(info)); 419 info.dwSize = sizeof(info); 420 if (!ICInfo(0, i++, &info)) 421 break; 422 trace("Codec name: %s, fccHandler: 0x%08x\n", wine_dbgstr_w(info.szName), info.fccHandler); 423 ok(info.fccType, "Expected nonzero type.\n"); 424 ok(info.fccHandler, "Expected nonzero handler.\n"); 425 ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags); 426 ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion); 427 ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM); 428 ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName)); 429 ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription)); 430 431 ok(ICInfo(info.fccType, info.fccHandler, &info2), 432 "ICInfo failed on fcc 0x%08x\n", info.fccHandler); 433 434 fcc = (unsigned char *)&info.fccHandler; 435 if (!isalpha(fcc[0])) continue; 436 437 found++; 438 /* Test getting info with a different case - bug 41602 */ 439 fcc[0] ^= 0x20; 440 ok(ICInfo(info.fccType, info.fccHandler, &info2), 441 "ICInfo failed on fcc 0x%08x\n", info.fccHandler); 442 } 443 ok(found != 0, "expected at least one codec\n"); 444 445 memset(&info, 0x55, sizeof(info)); 446 info.dwSize = sizeof(info); 447 ok(!ICInfo(ICTYPE_VIDEO, mmioFOURCC('f','a','k','e'), &info), "expected failure\n"); 448 ok(info.fccType == ICTYPE_VIDEO, "got 0x%08x\n", info.fccType); 449 ok(info.fccHandler == mmioFOURCC('f','a','k','e'), "got 0x%08x\n", info.fccHandler); 450 ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags); 451 ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion); 452 ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM); 453 ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName)); 454 ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription)); 455 ok(!info.szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(info.szDriver)); 456 457 if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows NT" 458 "\\CurrentVersion\\Drivers32", 0, KEY_ALL_ACCESS, &key)) 459 { 460 ret = ICInstall(test_type, test_handler, (LPARAM)"bogus", NULL, ICINSTALL_DRIVER); 461 ok(ret, "Failed to install driver.\n"); 462 463 size = sizeof(buffer); 464 res = RegQueryValueExA(key, "wine.test", NULL, NULL, (BYTE *)buffer, &size); 465 ok(!res, "Failed to query value, error %d.\n", res); 466 ok(!strcmp(buffer, "bogus"), "Got unexpected value \"%s\".\n", buffer); 467 468 memset(&info, 0x55, sizeof(info)); 469 info.dwSize = sizeof(info); 470 ok(ICInfo(test_type, test_handler, &info), "Expected success.\n"); 471 ok(info.fccType == test_type, "Got unexpected type %#x.\n", info.fccType); 472 ok(info.fccHandler == test_handler, "Got unexpected handler %#x.\n", info.fccHandler); 473 ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags); 474 ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion); 475 ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM); 476 ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName)); 477 ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription)); 478 ok(!lstrcmpW(info.szDriver, bogusW), "Got unexpected driver %s.\n", wine_dbgstr_w(info.szDriver)); 479 480 /* Drivers installed after msvfw32 is loaded are not enumerated. */ 481 todo_wine 482 ok(!ICInfo(test_type, 0, &info), "Expected failure.\n"); 483 484 ret = ICRemove(test_type, test_handler, 0); 485 ok(ret, "Failed to remove driver.\n"); 486 487 res = RegDeleteValueA(key, "wine.test"); 488 ok(res == ERROR_FILE_NOT_FOUND, "Got error %u.\n", res); 489 RegCloseKey(key); 490 } 491 else 492 win_skip("Not enough permissions to register codec drivers.\n"); 493 494 if (WritePrivateProfileStringA("drivers32", "wine.test", "bogus", "system.ini")) 495 { 496 memset(&info, 0x55, sizeof(info)); 497 info.dwSize = sizeof(info); 498 ok(ICInfo(test_type, test_handler, &info), "Expected success.\n"); 499 ok(info.fccType == test_type, "Got unexpected type %#x.\n", info.fccType); 500 ok(info.fccHandler == test_handler, "Got unexpected handler %#x.\n", info.fccHandler); 501 ok(!info.dwFlags, "Got unexpected flags %#x.\n", info.dwFlags); 502 ok(!info.dwVersion, "Got unexpected version %#x.\n", info.dwVersion); 503 ok(info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", info.dwVersionICM); 504 ok(!info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szName)); 505 ok(!info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(info.szDescription)); 506 ok(!lstrcmpW(info.szDriver, bogusW), "Got unexpected driver %s.\n", wine_dbgstr_w(info.szDriver)); 507 508 /* Drivers installed after msvfw32 is loaded are not enumerated. */ 509 todo_wine 510 ok(!ICInfo(test_type, 0, &info), "Expected failure.\n"); 511 512 ret = WritePrivateProfileStringA("drivers32", "wine.test", NULL, "system.ini"); 513 ok(ret, "Failed to remove INI entry.\n"); 514 } 515 516 ret = ICInstall(test_type, test_handler, (LPARAM)enum_driver_proc, NULL, ICINSTALL_FUNCTION); 517 ok(ret, "Failed to install driver.\n"); 518 519 memset(&enum_info, 0x55, sizeof(enum_info)); 520 enum_info.dwSize = sizeof(enum_info); 521 ok(ICInfo(test_type, test_handler, &enum_info), "Expected success.\n"); 522 ok(!enum_info.fccType, "Got unexpected type %#x.\n", enum_info.fccType); 523 ok(!enum_info.fccHandler, "Got unexpected handler %#x.\n", enum_info.fccHandler); 524 ok(!enum_info.dwFlags, "Got unexpected flags %#x.\n", enum_info.dwFlags); 525 ok(enum_info.dwVersion == 0xdeadbeef, "Got unexpected version %#x.\n", enum_info.dwVersion); 526 ok(enum_info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", enum_info.dwVersionICM); 527 ok(!enum_info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szName)); 528 ok(!enum_info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szDescription)); 529 ok(!enum_info.szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(enum_info.szDriver)); 530 531 /* Functions installed after msvfw32 is loaded are enumerated. */ 532 memset(&enum_info, 0x55, sizeof(enum_info)); 533 enum_info.dwSize = sizeof(enum_info); 534 ok(ICInfo(test_type, 0, &enum_info), "Expected success.\n"); 535 ok(!enum_info.fccType, "Got unexpected type %#x.\n", enum_info.fccType); 536 ok(!enum_info.fccHandler, "Got unexpected handler %#x.\n", enum_info.fccHandler); 537 ok(!enum_info.dwFlags, "Got unexpected flags %#x.\n", enum_info.dwFlags); 538 ok(enum_info.dwVersion == 0xdeadbeef, "Got unexpected version %#x.\n", enum_info.dwVersion); 539 ok(enum_info.dwVersionICM == ICVERSION, "Got unexpected ICM version %#x.\n", enum_info.dwVersionICM); 540 ok(!enum_info.szName[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szName)); 541 ok(!enum_info.szDescription[0], "Got unexpected name %s.\n", wine_dbgstr_w(enum_info.szDescription)); 542 ok(!enum_info.szDriver[0], "Got unexpected driver %s.\n", wine_dbgstr_w(enum_info.szDriver)); 543 544 ret = ICRemove(test_type, test_handler, 0); 545 ok(ret, "Failed to remove driver.\n"); 546 } 547 548 static int get_display_format_test; 549 550 static DWORD get_size_image(LONG width, LONG height, WORD depth) 551 { 552 DWORD ret = width * depth; 553 ret = (ret + 7) / 8; /* divide by byte size, rounding up */ 554 ret = (ret + 3) & ~3; /* align to 4 bytes */ 555 ret *= abs(height); 556 return ret; 557 } 558 559 static const RGBQUAD color_yellow = {0x00, 0xff, 0xff, 0x00}; 560 561 static BITMAPINFOHEADER gdf_in, *gdf_out; 562 563 static LRESULT CALLBACK gdf_driver_proc(DWORD_PTR id, HDRVR driver, UINT msg, 564 LPARAM lparam1, LPARAM lparam2) 565 { 566 LRESULT ret = 0; 567 568 if (winetest_debug > 1) 569 trace("(%#lx, %p, %#x, %#lx, %#lx)\n", id, driver, msg, lparam1, lparam2); 570 571 switch(msg) 572 { 573 case DRV_LOAD: 574 case DRV_OPEN: 575 case DRV_CLOSE: 576 case DRV_FREE: 577 return 1; 578 case ICM_DECOMPRESS_QUERY: 579 { 580 BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lparam2; 581 DWORD expected_size; 582 583 ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1); 584 585 if (!out) 586 return ICERR_OK; 587 588 ok(out == gdf_out, "got output %p\n", out); 589 590 ok(out->biSize == sizeof(*out), "got size %d\n", out->biSize); 591 expected_size = get_size_image(out->biWidth, out->biHeight, out->biBitCount); 592 ok(out->biSizeImage == expected_size, "expected image size %d, got %d\n", 593 expected_size, out->biSizeImage); 594 595 ok(out->biPlanes == 0xcccc, "got planes %d\n", out->biPlanes); 596 ok(out->biXPelsPerMeter == 0xcccccccc && out->biYPelsPerMeter == 0xcccccccc, 597 "got resolution %dx%d\n", out->biXPelsPerMeter, out->biYPelsPerMeter); 598 ok(out->biClrUsed == 0xcccccccc, "got biClrUsed %u\n", out->biClrUsed); 599 ok(out->biClrImportant == 0xcccccccc, "got biClrImportant %u\n", out->biClrImportant); 600 601 switch (get_display_format_test) 602 { 603 case 0: 604 return ICERR_OK; 605 case 1: 606 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 16) 607 return ICERR_OK; 608 break; 609 case 2: 610 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_BITFIELDS && out->biBitCount == 16) 611 return ICERR_OK; 612 break; 613 case 3: 614 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 24) 615 return ICERR_OK; 616 break; 617 case 4: 618 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 32) 619 return ICERR_OK; 620 break; 621 case 5: 622 if (out->biWidth == 10 && out->biHeight == 20 && out->biCompression == BI_RGB && out->biBitCount == 32) 623 return ICERR_OK; 624 break; 625 case 6: 626 break; 627 } 628 629 return ICERR_BADFORMAT; 630 } 631 case ICM_DECOMPRESS_GET_FORMAT: 632 { 633 BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lparam2; 634 635 ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1); 636 if (out) 637 { 638 ok(out == gdf_out, "got output %p\n", out); 639 640 memset(out, 0x55, sizeof(*out)); 641 out->biWidth = 50; 642 out->biHeight = 60; 643 out->biBitCount = 0xdead; 644 out->biCompression = 0xbeef; 645 out->biSizeImage = 0; 646 647 return ICERR_OK; 648 } 649 } 650 case ICM_DECOMPRESS_GET_PALETTE: 651 { 652 BITMAPINFO *out = (BITMAPINFO *)lparam2; 653 654 ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1); 655 if (out) 656 { 657 ok(out == (BITMAPINFO *)gdf_out, "got output %p\n", out); 658 659 out->bmiHeader.biClrUsed = 1; 660 out->bmiColors[0] = color_yellow; 661 662 return 0xdeadbeef; 663 } 664 } 665 } 666 667 return ret; 668 } 669 670 static void check_bitmap_header_(int line, BITMAPINFOHEADER *header, LONG width, LONG height, WORD depth, DWORD compression) 671 { 672 ok_(__FILE__, line)(header->biWidth == width, "expected %d, got %d\n", width, header->biWidth); 673 ok_(__FILE__, line)(header->biHeight == height, "expected %d, got %d\n", height, header->biHeight); 674 ok_(__FILE__, line)(header->biBitCount == depth, "expected %d, got %d\n", depth, header->biBitCount); 675 ok_(__FILE__, line)(header->biCompression == compression, "expected %#x, got %#x\n", compression, header->biCompression); 676 } 677 #define check_bitmap_header(a,b,c,d,e) check_bitmap_header_(__LINE__,a,b,c,d,e) 678 679 static void test_ICGetDisplayFormat(void) 680 { 681 static const DWORD testcc = mmioFOURCC('t','e','s','t'); 682 #ifdef __REACTOS__ 683 char outbuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)]; 684 #else 685 char outbuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; 686 #endif 687 BITMAPINFO *out_bmi; 688 LRESULT lres; 689 BOOL ret; 690 HIC hic; 691 692 memset(&gdf_in, 0xcc, sizeof(gdf_in)); 693 gdf_in.biSize = sizeof(gdf_in); 694 gdf_in.biWidth = 10; 695 gdf_in.biHeight = 20; 696 gdf_in.biBitCount = 1; 697 gdf_in.biCompression = testcc; 698 699 ret = ICInstall(ICTYPE_VIDEO, testcc, (LPARAM)gdf_driver_proc, NULL, ICINSTALL_FUNCTION); 700 ok(ret, "ICInstall failed\n"); 701 702 hic = ICOpen(ICTYPE_VIDEO, testcc, ICMODE_DECOMPRESS); 703 ok(ret, "ICOpen failed\n"); 704 705 memset(outbuf, 0, sizeof(outbuf)); 706 gdf_out = (BITMAPINFOHEADER *)outbuf; 707 708 /* ICGetDisplayFormat tries several default formats; make sure those work */ 709 get_display_format_test = 0; 710 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 711 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 712 check_bitmap_header(gdf_out, 30, 40, 1, BI_RGB); 713 714 get_display_format_test = 1; 715 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 716 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 717 check_bitmap_header(gdf_out, 30, 40, 16, BI_RGB); 718 719 get_display_format_test = 2; 720 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 721 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 722 check_bitmap_header(gdf_out, 30, 40, 16, BI_BITFIELDS); 723 724 get_display_format_test = 3; 725 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 726 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 727 check_bitmap_header(gdf_out, 30, 40, 24, BI_RGB); 728 729 get_display_format_test = 4; 730 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 731 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 732 check_bitmap_header(gdf_out, 30, 40, 32, BI_RGB); 733 734 get_display_format_test = 5; 735 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 736 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 737 check_bitmap_header(gdf_out, 10, 20, 32, BI_RGB); 738 739 /* if every default format is rejected, the output of 740 * ICM_DECOMPRESS_GET_FORMAT is returned */ 741 get_display_format_test = 6; 742 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40); 743 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 744 check_bitmap_header(gdf_out, 50, 60, 0xdead, 0xbeef); 745 746 /* given bpp is treated as a lower bound */ 747 get_display_format_test = 1; 748 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 24, 30, 40); 749 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 750 check_bitmap_header(gdf_out, 50, 60, 0xdead, 0xbeef); 751 752 get_display_format_test = 3; 753 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 24, 30, 40); 754 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 755 check_bitmap_header(gdf_out, 30, 40, 24, BI_RGB); 756 757 get_display_format_test = 0; 758 759 /* width or height <= 0 causes the input width and height to be supplied */ 760 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 0, 40); 761 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 762 check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB); 763 764 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 0); 765 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 766 check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB); 767 768 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, -10, 40); 769 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 770 check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB); 771 772 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, -10); 773 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 774 check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB); 775 776 /* zero bpp causes 32 bpp to be supplied */ 777 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 0, 30, 40); 778 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 779 ok(gdf_out->biBitCount == 32 || gdf_out->biBitCount == 24, 780 "got %d\n", gdf_out->biBitCount); 781 ok(gdf_out->biCompression == BI_RGB, "got %#x\n", gdf_out->biCompression); 782 783 /* specifying 8 bpp yields a request for palette colours */ 784 hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 8, 30, 40); 785 ok(hic != NULL, "ICGetDisplayFormat failed\n"); 786 check_bitmap_header(gdf_out, 30, 40, 8, BI_RGB); 787 ok(gdf_out->biClrUsed == 1, "got biClrUsed %u\n", gdf_out->biClrUsed); 788 out_bmi = (BITMAPINFO *)gdf_out; 789 ok(!memcmp(&out_bmi->bmiColors[0], &color_yellow, sizeof(color_yellow)), 790 "got wrong colour\n"); 791 792 lres = ICClose(hic); 793 ok(lres == ICERR_OK, "got %ld\n", lres); 794 795 ret = ICRemove(ICTYPE_VIDEO, testcc, 0); 796 ok(ret, "ICRemove failed\n"); 797 } 798 799 START_TEST(msvfw) 800 { 801 test_OpenCase(); 802 test_Locate(); 803 test_ICSeqCompress(); 804 test_ICInfo(); 805 test_ICGetDisplayFormat(); 806 } 807