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 struct msg_result
378 {
379     int msg_index;
380     UINT msg;
381     BOOL output_format;
382     int width;
383     int height;
384     int bits;
385     int compression;
386     LRESULT result;
387     BOOL todo;
388 };
389 
390 static struct msg_result expected_msgs[] =
391 {
392     /* Wine bug - shouldn't be called */
393     { 0,  DRV_LOAD,                   FALSE,   0,   0,  0,            0,              TRUE, TRUE},
394     { 0,  DRV_ENABLE,                 FALSE,   0,   0,  0,            0,                 0, TRUE},
395 
396     { 0,  DRV_OPEN,                   FALSE,   0,   0,  0,            0,        0xdeadbeef, FALSE},
397 
398     /* test 1 */
399     { 1,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
400     { 2,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,   ICERR_BADFORMAT, FALSE},
401     { 3,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480,  8,       BI_RGB,   ICERR_BADFORMAT, FALSE},
402     { 4,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 16,       BI_RGB,   ICERR_BADFORMAT, FALSE},
403     { 5,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 16, BI_BITFIELDS,   ICERR_BADFORMAT, FALSE},
404     { 6,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 24,       BI_RGB,   ICERR_BADFORMAT, FALSE},
405     { 7,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,   ICERR_BADFORMAT, FALSE},
406     { 8,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
407 
408     /* test 2 */
409     { 9,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
410     {10,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,   ICERR_BADFORMAT, FALSE},
411     {11,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480,  8,       BI_RGB,   ICERR_BADFORMAT, FALSE},
412     {12,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 16,       BI_RGB,          ICERR_OK, FALSE},
413 
414     /* test 3 */
415     {13,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
416     {14,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
417     {15,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480,  8,       BI_RGB,   ICERR_BADFORMAT, FALSE},
418     {16,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 16,       BI_RGB,          ICERR_OK, FALSE},
419 
420     /* test 4 */
421     {17,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
422     {18,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,   ICERR_BADFORMAT, FALSE},
423     {19,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 24,       BI_RGB,   ICERR_BADFORMAT, FALSE},
424     {20,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,   ICERR_BADFORMAT, FALSE},
425     {21,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
426 
427     /* test 5 */
428     {22,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
429     {23,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
430     {24,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
431 
432     /* test 6 */
433     {25,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
434     {26,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
435     {27,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
436 
437     /* test 7 */
438     {28,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
439     {29,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
440     {30,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480,  9,       BI_RGB,   ICERR_BADFORMAT, FALSE},
441     {31,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,   ICERR_BADFORMAT, FALSE},
442     {32,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
443 
444     /* test 8 */
445     {33,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
446     {34,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
447     {35,  ICM_DECOMPRESS_QUERY,       TRUE,  800, 600, 32,       BI_RGB,          ICERR_OK, FALSE},
448 
449     /* test 9 */
450     {36,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
451     {37,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
452     {38,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
453 
454     /* test 10 */
455     {39,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
456     {40,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
457     {41,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480, 32,       BI_RGB,          ICERR_OK, FALSE},
458 
459     /* test 11 */
460     {42,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
461     {43,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
462     {44,  ICM_DECOMPRESS_QUERY,       TRUE,  270, 270,  8,       BI_RGB,          ICERR_OK, FALSE},
463     {45,  ICM_DECOMPRESS_GET_PALETTE, FALSE,   0,   0,  0,            0, ICERR_UNSUPPORTED, FALSE},
464 
465     /* test 12 */
466     {46,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
467     {47,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
468     {48,  ICM_DECOMPRESS_QUERY,       TRUE,  270, 270, 16,       BI_RGB,          ICERR_OK, FALSE},
469 
470     /* test 13 */
471     {49,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
472     {50,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
473     {51,  ICM_DECOMPRESS_QUERY,       TRUE,  270, 270, 24,       BI_RGB,          ICERR_OK, FALSE},
474 
475     /* test 14 */
476     {52,  ICM_DECOMPRESS_QUERY,       FALSE,   0,   0,  0,            0,          ICERR_OK, FALSE},
477     {53,  ICM_DECOMPRESS_GET_FORMAT,  TRUE,  320, 240, 16,       BI_RGB,          ICERR_OK, FALSE},
478     {54,  ICM_DECOMPRESS_QUERY,       TRUE,  640, 480,  4,       BI_RGB,          ICERR_OK, FALSE},
479 
480     /* Wine bug - shouldn't be called */
481     {55,  DRV_DISABLE,                FALSE,   0,   0,  0,            0,          ICERR_OK, TRUE},
482     {55,  DRV_FREE,                   FALSE,   0,   0,  0,            0,          ICERR_OK, TRUE},
483 };
484 
485 static int msg_index = 0;
486 
487 static struct msg_result *get_expected_msg(UINT msg)
488 {
489     int i = 0;
490     for(; i < sizeof(expected_msgs) / sizeof(expected_msgs[0]); i++)
491     {
492         if (expected_msgs[i].msg_index == msg_index && expected_msgs[i].msg == msg)
493             return &expected_msgs[i];
494     }
495     return NULL;
496 }
497 
498 LRESULT WINAPI driver_proc_test(DWORD_PTR dwDriverId, HDRVR hdrvr, UINT msg,
499                                 LPARAM lParam1, LPARAM lParam2)
500 {
501     struct msg_result *expected = get_expected_msg(msg);
502     LRESULT res = expected ? expected->result : ICERR_UNSUPPORTED;
503 
504     if (msg == DRV_CLOSE)
505         return ICERR_OK;
506 
507     if (!expected)
508     {
509         ok(0, "unexpected message: %04x %ld %ld at msg index %d\n",
510            msg, lParam1, lParam2, msg_index);
511         return ICERR_UNSUPPORTED;
512     }
513     else if (expected->todo)
514     {
515         todo_wine ok(0, "unexpected message: %04x %ld %ld at msg index %d\n",
516                      msg, lParam1, lParam2, msg_index);
517         return res;
518     }
519 
520     switch (msg)
521     {
522         case ICM_DECOMPRESS_QUERY:
523         {
524             BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lParam2;
525 
526             if (!lParam2)
527             {
528                 trace("query -> without format\n");
529                 ok(!expected->output_format, "Expected no output format pointer\n");
530                 break;
531             }
532 
533             ok(expected->output_format, "Expected output format pointer\n");
534             ok(out->biWidth == expected->width,
535                "Expected width %d, got %d\n", expected->width, out->biWidth);
536             ok(out->biHeight == expected->height,
537                "Expected height %d, got %d\n", expected->height, out->biHeight);
538             ok(out->biBitCount == expected->bits,
539                "Expected biBitCount %d, got %d\n", expected->bits, out->biBitCount);
540             ok(out->biCompression == expected->compression,
541                "Expected compression %d, got %d\n", expected->compression, out->biCompression);
542             ok(out->biSizeImage == get_stride(out->biWidth, out->biBitCount) * out->biHeight,
543                "Expected biSizeImage %d, got %d\n", get_stride(out->biWidth, out->biBitCount) * out->biHeight,
544                 out->biSizeImage);
545 
546             trace("query -> width: %d, height: %d, bit: %d, compression: %d, size: %d\n",
547                   out->biWidth, out->biHeight, out->biBitCount, out->biCompression, out->biSizeImage);
548             break;
549         }
550 
551         case ICM_DECOMPRESS_GET_FORMAT:
552         {
553             BITMAPINFOHEADER *out = (BITMAPINFOHEADER *)lParam2;
554 
555             if (!lParam2)
556             {
557                 trace("format -> without format\n");
558                 ok(!expected->output_format, "Expected no output format pointer\n");
559                 break;
560             }
561 
562             ok(expected->output_format, "Expected output format pointer\n");
563             ok(out->biWidth == expected->width,
564                "Expected width %d, got %d\n", expected->width, out->biWidth);
565             ok(out->biHeight == expected->height,
566                "Expected height %d, got %d\n", expected->height, out->biHeight);
567             ok(out->biBitCount == expected->bits,
568                "Expected biBitCount %d, got %d\n", expected->bits, out->biBitCount);
569             ok(out->biCompression == expected->compression,
570                "Expected compression %d, got %d\n", expected->compression, out->biCompression);
571 
572             trace("format -> width: %d, height: %d, bit: %d, compression: %d, size: %d\n",
573                   out->biWidth, out->biHeight, out->biBitCount, out->biCompression, out->biSizeImage);
574 
575             out->biBitCount = 64;
576             break;
577         }
578     }
579 
580     msg_index++;
581     return res;
582 }
583 
584 
585 void test_ICGetDisplayFormat(void)
586 {
587     static const struct
588     {
589         int bits_wanted;
590         int bits_expected;
591         int dx;
592         int width_expected;
593         int dy;
594         int height_expected;
595         int msg_index;
596     }
597     tests[] =
598     {
599         { 8, 64,   0, 640,   0, 480, 9},
600         { 8, 16,   0, 640,   0, 480, 13},
601         { 8, 16,   0, 640,   0, 480, 17},
602         {24, 64,   0, 640,   0, 480, 22},
603         {32, 32,   0, 640,   0, 480, 25},
604         { 0, 32,   0, 640,   0, 480, 28},
605         { 9, 64,   0, 640,   0, 480, 33},
606         {32, 32, 800, 800, 600, 600, 36},
607         {32, 32,  -1, 640,  -1, 480, 39},
608         {32, 32, -90, 640, -60, 480, 42},
609         { 8,  8, 270, 270, 270, 270, 46},
610         {16, 16, 270, 270, 270, 270, 49},
611         {24, 24, 270, 270, 270, 270, 52},
612         { 4,  4,   0, 640,   0, 480, 55},
613     };
614 
615     HIC ic, ic2;
616     BITMAPINFOHEADER in;
617     BITMAPINFOHEADER out;
618     int real_depth;
619     int i;
620 
621     ic = ICOpenFunction(ICTYPE_VIDEO, 0xdeadbeef, ICMODE_DECOMPRESS, driver_proc_test);
622     ok(!!ic, "Opening driver failed\n");
623 
624     for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
625     {
626         memset(&in, 0, sizeof(in));
627         memset(&out, 0, sizeof(out));
628 
629         in.biSize = sizeof(in);
630         in.biWidth = 640;
631         in.biHeight = 480;
632         in.biPlanes = 1;
633         in.biBitCount = 32;
634         in.biCompression = BI_PNG;
635         in.biSizeImage = 1024;
636 
637         out.biBitCount = 16;
638         out.biWidth = 320;
639         out.biHeight = 240;
640 
641         ic2 = ICGetDisplayFormat(ic, &in, &out, tests[i].bits_wanted, tests[i].dx, tests[i].dy);
642         ok(!!ic2, "Expected ICGetDisplayFormat to succeeded\n");
643 
644         ok(out.biBitCount == tests[i].bits_expected,
645            "Expected biBitCount %d, got %d\n", tests[i].bits_expected, out.biBitCount);
646         ok(out.biWidth == tests[i].width_expected,
647            "Expected biWidth %d, got %d\n", tests[i].width_expected, out.biWidth);
648         ok(out.biHeight == tests[i].height_expected,
649            "Expected biHeight %d, got %d\n", tests[i].height_expected, out.biHeight);
650         real_depth = (out.biBitCount > 32) ? 32 : out.biBitCount;
651         ok(out.biSizeImage == get_stride(out.biWidth, real_depth) * out.biHeight,
652            "Expected biSizeImage %d, got %d\n", get_stride(out.biWidth, real_depth) * out.biHeight,
653            out.biSizeImage);
654         ok(msg_index == tests[i].msg_index,
655            "Expected msg_index %d, got %d\n", tests[i].msg_index, msg_index);
656     }
657 
658     ICClose(ic);
659 }
660 
661 static void test_ICInfo(void)
662 {
663     ICINFO info, info2;
664     DWORD i, found;
665     unsigned char *fcc;
666 
667     for (i = found = 0; ICInfo(0, i, &info); i++)
668     {
669         trace("Codec name: %s, fccHandler: 0x%08x\n", wine_dbgstr_w(info.szName), info.fccHandler);
670 
671         ok(ICInfo(info.fccType, info.fccHandler, &info2),
672            "ICInfo failed on fcc 0x%08x\n", info.fccHandler);
673 
674         fcc = (unsigned char *)&info.fccHandler;
675         if (!isalpha(fcc[0])) continue;
676 
677         found++;
678         /* Test getting info with a different case - bug 41602 */
679         if (fcc[0] & 0x20)
680         {
681             fcc[0] &= ~0x20;
682             ok(ICInfo(info.fccType, info.fccHandler, &info2),
683                "ICInfo failed on fcc 0x%08x using lowercase fccHandler\n", info.fccHandler);
684         }
685         else
686         {
687             fcc[0] |= 0x20;
688             ok(ICInfo(info.fccType, info.fccHandler, &info2),
689                "ICInfo failed on fcc 0x%08x using uppercase fccHandler\n", info.fccHandler);
690         }
691     }
692     ok(found != 0, "expected at least one codec\n");
693 }
694 
695 START_TEST(msvfw)
696 {
697     test_OpenCase();
698     test_Locate();
699     test_ICSeqCompress();
700     test_ICGetDisplayFormat();
701     test_ICInfo();
702 }
703