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 void test_ICInfo(void)
378 {
379     ICINFO info, info2;
380     DWORD i, found;
381     unsigned char *fcc;
382 
383     for (i = found = 0; ICInfo(0, i, &info); i++)
384     {
385         trace("Codec name: %s, fccHandler: 0x%08x\n", wine_dbgstr_w(info.szName), info.fccHandler);
386         ok(info.fccType, "expected nonzero fccType\n");
387 
388         ok(ICInfo(info.fccType, info.fccHandler, &info2),
389            "ICInfo failed on fcc 0x%08x\n", info.fccHandler);
390 
391         fcc = (unsigned char *)&info.fccHandler;
392         if (!isalpha(fcc[0])) continue;
393 
394         found++;
395         /* Test getting info with a different case - bug 41602 */
396         fcc[0] ^= 0x20;
397         ok(ICInfo(info.fccType, info.fccHandler, &info2),
398            "ICInfo failed on fcc 0x%08x\n", info.fccHandler);
399     }
400     ok(found != 0, "expected at least one codec\n");
401 
402     memset(&info, 0, sizeof(info));
403     ok(!ICInfo(ICTYPE_VIDEO, mmioFOURCC('f','a','k','e'), &info), "expected failure\n");
404     ok(info.fccType == ICTYPE_VIDEO, "got 0x%08x\n", info.fccType);
405     ok(info.fccHandler == mmioFOURCC('f','a','k','e'), "got 0x%08x\n", info.fccHandler);
406 }
407 
408 static int get_display_format_test;
409 
410 static DWORD get_size_image(LONG width, LONG height, WORD depth)
411 {
412     DWORD ret = width * depth;
413     ret = (ret + 7) / 8;    /* divide by byte size, rounding up */
414     ret = (ret + 3) & ~3;   /* align to 4 bytes */
415     ret *= abs(height);
416     return ret;
417 }
418 
419 static const RGBQUAD color_yellow = {0x00, 0xff, 0xff, 0x00};
420 
421 static BITMAPINFOHEADER gdf_in, *gdf_out;
422 
423 static LRESULT CALLBACK gdf_driver_proc(DWORD_PTR id, HDRVR driver, UINT msg,
424     LPARAM lparam1, LPARAM lparam2)
425 {
426     LRESULT ret = 0;
427 
428     if (winetest_debug > 1)
429         trace("(%#lx, %p, %#x, %#lx, %#lx)\n", id, driver, msg, lparam1, lparam2);
430 
431     switch(msg)
432     {
433     case DRV_LOAD:
434     case DRV_OPEN:
435     case DRV_CLOSE:
436     case DRV_FREE:
437         return 1;
438     case ICM_DECOMPRESS_QUERY:
439     {
440         BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lparam2;
441         DWORD expected_size;
442 
443         ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1);
444 
445         if (!out)
446             return ICERR_OK;
447 
448         ok(out == gdf_out, "got output %p\n", out);
449 
450         ok(out->biSize == sizeof(*out), "got size %d\n", out->biSize);
451         expected_size = get_size_image(out->biWidth, out->biHeight, out->biBitCount);
452         ok(out->biSizeImage == expected_size, "expected image size %d, got %d\n",
453             expected_size, out->biSizeImage);
454 
455         ok(out->biPlanes == 0xcccc, "got planes %d\n", out->biPlanes);
456         ok(out->biXPelsPerMeter == 0xcccccccc && out->biYPelsPerMeter == 0xcccccccc,
457             "got resolution %dx%d\n", out->biXPelsPerMeter, out->biYPelsPerMeter);
458         ok(out->biClrUsed == 0xcccccccc, "got biClrUsed %u\n", out->biClrUsed);
459         ok(out->biClrImportant == 0xcccccccc, "got biClrImportant %u\n", out->biClrImportant);
460 
461         switch (get_display_format_test)
462         {
463             case 0:
464                 return ICERR_OK;
465             case 1:
466                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 16)
467                     return ICERR_OK;
468                 break;
469             case 2:
470                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_BITFIELDS && out->biBitCount == 16)
471                     return ICERR_OK;
472                 break;
473             case 3:
474                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 24)
475                     return ICERR_OK;
476                 break;
477             case 4:
478                 if (out->biWidth == 30 && out->biHeight == 40 && out->biCompression == BI_RGB && out->biBitCount == 32)
479                     return ICERR_OK;
480                 break;
481             case 5:
482                 if (out->biWidth == 10 && out->biHeight == 20 && out->biCompression == BI_RGB && out->biBitCount == 32)
483                     return ICERR_OK;
484                 break;
485             case 6:
486                 break;
487         }
488 
489         return ICERR_BADFORMAT;
490     }
491     case ICM_DECOMPRESS_GET_FORMAT:
492     {
493         BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lparam2;
494 
495         ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1);
496         if (out)
497         {
498             ok(out == gdf_out, "got output %p\n", out);
499 
500             memset(out, 0x55, sizeof(*out));
501             out->biWidth = 50;
502             out->biHeight = 60;
503             out->biBitCount = 0xdead;
504             out->biCompression = 0xbeef;
505             out->biSizeImage = 0;
506 
507             return ICERR_OK;
508         }
509     }
510     case ICM_DECOMPRESS_GET_PALETTE:
511     {
512         BITMAPINFO *out = (BITMAPINFO *)lparam2;
513 
514         ok(lparam1 == (LPARAM)&gdf_in, "got input %#lx\n", lparam1);
515         if (out)
516         {
517             ok(out == (BITMAPINFO *)gdf_out, "got output %p\n", out);
518 
519             out->bmiHeader.biClrUsed = 1;
520             out->bmiColors[0] = color_yellow;
521 
522             return 0xdeadbeef;
523         }
524     }
525     }
526 
527     return ret;
528 }
529 
530 static void check_bitmap_header_(int line, BITMAPINFOHEADER *header, LONG width, LONG height, WORD depth, DWORD compression)
531 {
532     ok_(__FILE__, line)(header->biWidth == width, "expected %d, got %d\n", width, header->biWidth);
533     ok_(__FILE__, line)(header->biHeight == height, "expected %d, got %d\n", height, header->biHeight);
534     ok_(__FILE__, line)(header->biBitCount == depth, "expected %d, got %d\n", depth, header->biBitCount);
535     ok_(__FILE__, line)(header->biCompression == compression, "expected %#x, got %#x\n", compression, header->biCompression);
536 }
537 #define check_bitmap_header(a,b,c,d,e) check_bitmap_header_(__LINE__,a,b,c,d,e)
538 
539 static void test_ICGetDisplayFormat(void)
540 {
541     static const DWORD testcc = mmioFOURCC('t','e','s','t');
542 #ifdef __REACTOS__
543     char outbuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
544 #else
545     char outbuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
546 #endif
547     BITMAPINFO *out_bmi;
548     LRESULT lres;
549     BOOL ret;
550     HIC hic;
551 
552     memset(&gdf_in, 0xcc, sizeof(gdf_in));
553     gdf_in.biSize = sizeof(gdf_in);
554     gdf_in.biWidth = 10;
555     gdf_in.biHeight = 20;
556     gdf_in.biBitCount = 1;
557     gdf_in.biCompression = testcc;
558 
559     ret = ICInstall(ICTYPE_VIDEO, testcc, (LPARAM)gdf_driver_proc, NULL, ICINSTALL_FUNCTION);
560     ok(ret, "ICInstall failed\n");
561 
562     hic = ICOpen(ICTYPE_VIDEO, testcc, ICMODE_DECOMPRESS);
563     ok(ret, "ICOpen failed\n");
564 
565     memset(outbuf, 0, sizeof(outbuf));
566     gdf_out = (BITMAPINFOHEADER *)outbuf;
567 
568     /* ICGetDisplayFormat tries several default formats; make sure those work */
569     get_display_format_test = 0;
570     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
571     ok(hic != NULL, "ICGetDisplayFormat failed\n");
572     check_bitmap_header(gdf_out, 30, 40, 1, BI_RGB);
573 
574     get_display_format_test = 1;
575     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
576     ok(hic != NULL, "ICGetDisplayFormat failed\n");
577     check_bitmap_header(gdf_out, 30, 40, 16, BI_RGB);
578 
579     get_display_format_test = 2;
580     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
581     ok(hic != NULL, "ICGetDisplayFormat failed\n");
582     check_bitmap_header(gdf_out, 30, 40, 16, BI_BITFIELDS);
583 
584     get_display_format_test = 3;
585     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
586     ok(hic != NULL, "ICGetDisplayFormat failed\n");
587     check_bitmap_header(gdf_out, 30, 40, 24, BI_RGB);
588 
589     get_display_format_test = 4;
590     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
591     ok(hic != NULL, "ICGetDisplayFormat failed\n");
592     check_bitmap_header(gdf_out, 30, 40, 32, BI_RGB);
593 
594     get_display_format_test = 5;
595     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
596     ok(hic != NULL, "ICGetDisplayFormat failed\n");
597     check_bitmap_header(gdf_out, 10, 20, 32, BI_RGB);
598 
599     /* if every default format is rejected, the output of
600      * ICM_DECOMPRESS_GET_FORMAT is returned */
601     get_display_format_test = 6;
602     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 40);
603     ok(hic != NULL, "ICGetDisplayFormat failed\n");
604     check_bitmap_header(gdf_out, 50, 60, 0xdead, 0xbeef);
605 
606     /* given bpp is treated as a lower bound */
607     get_display_format_test = 1;
608     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 24, 30, 40);
609     ok(hic != NULL, "ICGetDisplayFormat failed\n");
610     check_bitmap_header(gdf_out, 50, 60, 0xdead, 0xbeef);
611 
612     get_display_format_test = 3;
613     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 24, 30, 40);
614     ok(hic != NULL, "ICGetDisplayFormat failed\n");
615     check_bitmap_header(gdf_out, 30, 40, 24, BI_RGB);
616 
617     get_display_format_test = 0;
618 
619     /* width or height <= 0 causes the input width and height to be supplied */
620     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 0, 40);
621     ok(hic != NULL, "ICGetDisplayFormat failed\n");
622     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
623 
624     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, 0);
625     ok(hic != NULL, "ICGetDisplayFormat failed\n");
626     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
627 
628     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, -10, 40);
629     ok(hic != NULL, "ICGetDisplayFormat failed\n");
630     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
631 
632     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 1, 30, -10);
633     ok(hic != NULL, "ICGetDisplayFormat failed\n");
634     check_bitmap_header(gdf_out, 10, 20, 1, BI_RGB);
635 
636     /* zero bpp causes 32 bpp to be supplied */
637     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 0, 30, 40);
638     ok(hic != NULL, "ICGetDisplayFormat failed\n");
639     ok(gdf_out->biBitCount == 32 || gdf_out->biBitCount == 24,
640         "got %d\n", gdf_out->biBitCount);
641     ok(gdf_out->biCompression == BI_RGB, "got %#x\n", gdf_out->biCompression);
642 
643     /* specifying 8 bpp yields a request for palette colours */
644     hic = ICGetDisplayFormat(hic, &gdf_in, gdf_out, 8, 30, 40);
645     ok(hic != NULL, "ICGetDisplayFormat failed\n");
646     check_bitmap_header(gdf_out, 30, 40, 8, BI_RGB);
647     ok(gdf_out->biClrUsed == 1, "got biClrUsed %u\n", gdf_out->biClrUsed);
648     out_bmi = (BITMAPINFO *)gdf_out;
649     ok(!memcmp(&out_bmi->bmiColors[0], &color_yellow, sizeof(color_yellow)),
650         "got wrong colour\n");
651 
652     lres = ICClose(hic);
653     ok(lres == ICERR_OK, "got %ld\n", lres);
654 
655     ret = ICRemove(ICTYPE_VIDEO, testcc, 0);
656     ok(ret, "ICRemove failed\n");
657 }
658 
659 START_TEST(msvfw)
660 {
661     test_OpenCase();
662     test_Locate();
663     test_ICSeqCompress();
664     test_ICInfo();
665     test_ICGetDisplayFormat();
666 }
667