Don't return from overlapped ReadFile on EAGAIN and other non-fatal
[wine/gsoc_dplay.git] / dlls / winmm / mciavi / mmoutput.c
blobbcac07d3ea39cc4bcd7e4f33dc7c2c1ed7c11d31
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * Digital video MCI Wine Driver
6 * Copyright 1999, 2000 Eric POUECH
7 */
9 #include "private_mciavi.h"
10 #include "debugtools.h"
12 DEFAULT_DEBUG_CHANNEL(mciavi);
14 static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
16 MMCKINFO mmckInfo;
18 mmckInfo.ckid = ckidSTREAMHEADER;
19 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
20 WARN("Can't find 'strh' chunk\n");
21 return FALSE;
24 mmioRead(wma->hFile, (LPSTR)&wma->ash_audio, sizeof(wma->ash_audio));
26 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccType)),
27 HIBYTE(LOWORD(wma->ash_audio.fccType)),
28 LOBYTE(HIWORD(wma->ash_audio.fccType)),
29 HIBYTE(HIWORD(wma->ash_audio.fccType)));
30 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccHandler)),
31 HIBYTE(LOWORD(wma->ash_audio.fccHandler)),
32 LOBYTE(HIWORD(wma->ash_audio.fccHandler)),
33 HIBYTE(HIWORD(wma->ash_audio.fccHandler)));
34 TRACE("ash.dwFlags=%ld\n", wma->ash_audio.dwFlags);
35 TRACE("ash.wPriority=%d\n", wma->ash_audio.wPriority);
36 TRACE("ash.wLanguage=%d\n", wma->ash_audio.wLanguage);
37 TRACE("ash.dwInitialFrames=%ld\n", wma->ash_audio.dwInitialFrames);
38 TRACE("ash.dwScale=%ld\n", wma->ash_audio.dwScale);
39 TRACE("ash.dwRate=%ld\n", wma->ash_audio.dwRate);
40 TRACE("ash.dwStart=%ld\n", wma->ash_audio.dwStart);
41 TRACE("ash.dwLength=%ld\n", wma->ash_audio.dwLength);
42 TRACE("ash.dwSuggestedBufferSize=%ld\n", wma->ash_audio.dwSuggestedBufferSize);
43 TRACE("ash.dwQuality=%ld\n", wma->ash_audio.dwQuality);
44 TRACE("ash.dwSampleSize=%ld\n", wma->ash_audio.dwSampleSize);
45 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left,
46 wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right);
48 mmioAscend(wma->hFile, &mmckInfo, 0);
50 mmckInfo.ckid = ckidSTREAMFORMAT;
51 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
52 WARN("Can't find 'strh' chunk\n");
53 return FALSE;
55 if (mmckInfo.cksize < sizeof(WAVEFORMAT)) {
56 WARN("Size of strf chunk (%ld) < audio format struct\n", mmckInfo.cksize);
57 return FALSE;
59 wma->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
60 if (!wma->lpWaveFormat) {
61 WARN("Can't alloc WaveFormat\n");
62 return FALSE;
65 mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize);
67 TRACE("waveFormat.wFormatTag=%d\n", wma->lpWaveFormat->wFormatTag);
68 TRACE("waveFormat.nChannels=%d\n", wma->lpWaveFormat->nChannels);
69 TRACE("waveFormat.nSamplesPerSec=%ld\n", wma->lpWaveFormat->nSamplesPerSec);
70 TRACE("waveFormat.nAvgBytesPerSec=%ld\n", wma->lpWaveFormat->nAvgBytesPerSec);
71 TRACE("waveFormat.nBlockAlign=%d\n", wma->lpWaveFormat->nBlockAlign);
72 TRACE("waveFormat.wBitsPerSample=%d\n", wma->lpWaveFormat->wBitsPerSample);
73 if (mmckInfo.cksize >= sizeof(WAVEFORMATEX))
74 TRACE("waveFormat.cbSize=%d\n", wma->lpWaveFormat->cbSize);
76 mmioAscend(wma->hFile, &mmckInfo, 0);
78 return TRUE;
81 static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
83 MMCKINFO mmckInfo;
85 mmckInfo.ckid = ckidSTREAMHEADER;
86 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
87 WARN("Can't find 'strh' chunk\n");
88 return FALSE;
91 mmioRead(wma->hFile, (LPSTR)&wma->ash_video, sizeof(wma->ash_video));
93 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccType)),
94 HIBYTE(LOWORD(wma->ash_video.fccType)),
95 LOBYTE(HIWORD(wma->ash_video.fccType)),
96 HIBYTE(HIWORD(wma->ash_video.fccType)));
97 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccHandler)),
98 HIBYTE(LOWORD(wma->ash_video.fccHandler)),
99 LOBYTE(HIWORD(wma->ash_video.fccHandler)),
100 HIBYTE(HIWORD(wma->ash_video.fccHandler)));
101 TRACE("ash.dwFlags=%ld\n", wma->ash_video.dwFlags);
102 TRACE("ash.wPriority=%d\n", wma->ash_video.wPriority);
103 TRACE("ash.wLanguage=%d\n", wma->ash_video.wLanguage);
104 TRACE("ash.dwInitialFrames=%ld\n", wma->ash_video.dwInitialFrames);
105 TRACE("ash.dwScale=%ld\n", wma->ash_video.dwScale);
106 TRACE("ash.dwRate=%ld\n", wma->ash_video.dwRate);
107 TRACE("ash.dwStart=%ld\n", wma->ash_video.dwStart);
108 TRACE("ash.dwLength=%ld\n", wma->ash_video.dwLength);
109 TRACE("ash.dwSuggestedBufferSize=%ld\n", wma->ash_video.dwSuggestedBufferSize);
110 TRACE("ash.dwQuality=%ld\n", wma->ash_video.dwQuality);
111 TRACE("ash.dwSampleSize=%ld\n", wma->ash_video.dwSampleSize);
112 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left,
113 wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right);
115 mmioAscend(wma->hFile, &mmckInfo, 0);
117 mmckInfo.ckid = ckidSTREAMFORMAT;
118 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
119 WARN("Can't find 'strh' chunk\n");
120 return FALSE;
123 wma->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
124 if (!wma->inbih) {
125 WARN("Can't alloc input BIH\n");
126 return FALSE;
129 mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize);
131 TRACE("bih.biSize=%ld\n", wma->inbih->biSize);
132 TRACE("bih.biWidth=%ld\n", wma->inbih->biWidth);
133 TRACE("bih.biHeight=%ld\n", wma->inbih->biHeight);
134 TRACE("bih.biPlanes=%d\n", wma->inbih->biPlanes);
135 TRACE("bih.biBitCount=%d\n", wma->inbih->biBitCount);
136 TRACE("bih.biCompression=%lx\n", wma->inbih->biCompression);
137 TRACE("bih.biSizeImage=%ld\n", wma->inbih->biSizeImage);
138 TRACE("bih.biXPelsPerMeter=%ld\n", wma->inbih->biXPelsPerMeter);
139 TRACE("bih.biYPelsPerMeter=%ld\n", wma->inbih->biYPelsPerMeter);
140 TRACE("bih.biClrUsed=%ld\n", wma->inbih->biClrUsed);
141 TRACE("bih.biClrImportant=%ld\n", wma->inbih->biClrImportant);
143 mmioAscend(wma->hFile, &mmckInfo, 0);
145 return TRUE;
148 struct AviListBuild {
149 DWORD numVideoFrames;
150 DWORD numAudioAllocated;
151 DWORD numAudioBlocks;
152 DWORD inVideoSize;
153 DWORD inAudioSize;
156 static BOOL MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck,
157 struct AviListBuild* alb)
159 if (mmck->ckid == ckidAVIPADDING) return TRUE;
161 switch (TWOCCFromFOURCC(mmck->ckid)) {
162 case cktypeDIBbits:
163 case cktypeDIBcompressed:
164 case cktypePALchange:
165 TRACE("Adding video frame[%ld]: %ld bytes\n",
166 alb->numVideoFrames, mmck->cksize);
167 if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
168 wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
169 wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
170 if (alb->inVideoSize < mmck->cksize)
171 alb->inVideoSize = mmck->cksize;
172 alb->numVideoFrames++;
173 } else {
174 WARN("Too many video frames\n");
176 break;
177 case cktypeWAVEbytes:
178 TRACE("Adding audio frame[%ld]: %ld bytes\n",
179 alb->numAudioBlocks, mmck->cksize);
180 if (wma->lpWaveFormat) {
181 if (alb->numAudioBlocks >= alb->numAudioAllocated) {
182 alb->numAudioAllocated += 32;
183 wma->lpAudioIndex = HeapReAlloc(GetProcessHeap(), 0,
184 wma->lpAudioIndex,
185 alb->numAudioAllocated * sizeof(struct MMIOPos));
186 if (!wma->lpAudioIndex) return FALSE;
188 wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset;
189 wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize;
190 if (alb->inAudioSize < mmck->cksize)
191 alb->inAudioSize = mmck->cksize;
192 alb->numAudioBlocks++;
193 } else {
194 WARN("Wave chunk without wave format... discarding\n");
196 break;
197 default:
198 WARN("Unknown frame type %04x\n", TWOCCFromFOURCC(mmck->ckid));
199 break;
201 return TRUE;
204 BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
206 MMCKINFO ckMainRIFF;
207 MMCKINFO mmckHead;
208 MMCKINFO mmckList;
209 MMCKINFO mmckInfo;
210 struct AviListBuild alb;
212 if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
213 WARN("Can't find 'RIFF' chunk\n");
214 return FALSE;
217 if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
218 WARN("Can't find 'AVI ' chunk\n");
219 return FALSE;
222 mmckHead.fccType = listtypeAVIHEADER;
223 if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
224 WARN("Can't find 'hdrl' list\n");
225 return FALSE;
228 mmckInfo.ckid = ckidAVIMAINHDR;
229 if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
230 WARN("Can't find 'avih' chunk\n");
231 return FALSE;
234 mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));
236 TRACE("mah.dwMicroSecPerFrame=%ld\n", wma->mah.dwMicroSecPerFrame);
237 TRACE("mah.dwMaxBytesPerSec=%ld\n", wma->mah.dwMaxBytesPerSec);
238 TRACE("mah.dwPaddingGranularity=%ld\n", wma->mah.dwPaddingGranularity);
239 TRACE("mah.dwFlags=%ld\n", wma->mah.dwFlags);
240 TRACE("mah.dwTotalFrames=%ld\n", wma->mah.dwTotalFrames);
241 TRACE("mah.dwInitialFrames=%ld\n", wma->mah.dwInitialFrames);
242 TRACE("mah.dwStreams=%ld\n", wma->mah.dwStreams);
243 TRACE("mah.dwSuggestedBufferSize=%ld\n", wma->mah.dwSuggestedBufferSize);
244 TRACE("mah.dwWidth=%ld\n", wma->mah.dwWidth);
245 TRACE("mah.dwHeight=%ld\n", wma->mah.dwHeight);
247 mmioAscend(wma->hFile, &mmckInfo, 0);
249 mmckList.fccType = listtypeSTREAMHEADER;
250 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
251 WARN("Can't find 'strl' list\n");
252 return FALSE;
255 if (!MCIAVI_GetInfoVideo(wma, &mmckList)) {
256 return FALSE;
259 mmioAscend(wma->hFile, &mmckList, 0);
261 mmckList.fccType = listtypeSTREAMHEADER;
262 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
263 if (!MCIAVI_GetInfoAudio(wma, &mmckList)) {
264 return FALSE;
266 mmioAscend(wma->hFile, &mmckList, 0);
269 mmioAscend(wma->hFile, &mmckHead, 0);
271 /* no need to read optional JUNK chunk */
273 mmckList.fccType = listtypeAVIMOVIE;
274 if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
275 WARN("Can't find 'movi' list\n");
276 return FALSE;
279 wma->dwPlayableVideoFrames = wma->mah.dwTotalFrames;
280 wma->lpVideoIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
281 wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
282 if (!wma->lpVideoIndex) {
283 WARN("Can't alloc video index array\n");
284 return FALSE;
286 wma->dwPlayableAudioBlocks = 0;
287 wma->lpAudioIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
288 wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
289 if (!wma->lpAudioIndex) {
290 WARN("Can't alloc audio index array\n");
291 return FALSE;
294 alb.numAudioBlocks = alb.numVideoFrames = 0;
295 alb.inVideoSize = alb.inAudioSize = 0;
296 alb.numAudioAllocated = 0;
298 while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
299 if (mmckInfo.fccType == listtypeAVIRECORD) {
300 MMCKINFO tmp;
302 while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
303 MCIAVI_AddFrame(wma, &tmp, &alb);
304 mmioAscend(wma->hFile, &tmp, 0);
306 } else {
307 MCIAVI_AddFrame(wma, &mmckInfo, &alb);
310 mmioAscend(wma->hFile, &mmckInfo, 0);
312 if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
313 WARN("Found %ld video frames (/%ld), reducing playable frames\n",
314 alb.numVideoFrames, wma->dwPlayableVideoFrames);
315 wma->dwPlayableVideoFrames = alb.numVideoFrames;
317 wma->dwPlayableAudioBlocks = alb.numAudioBlocks;
319 if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) {
320 WARN("inVideoSize=%ld suggestedSize=%ld\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
321 wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize;
323 if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) {
324 WARN("inAudioSize=%ld suggestedSize=%ld\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
325 wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize;
328 wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize);
329 if (!wma->indata) {
330 WARN("Can't alloc input buffer\n");
331 return FALSE;
334 return TRUE;
337 BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma)
339 DWORD outSize;
340 FOURCC fcc = wma->ash_video.fccHandler;
342 /* check uncompressed AVI */
343 if ((fcc == mmioFOURCC('D','I','B',' ')) ||
344 (fcc == mmioFOURCC('R','L','E',' '))) {
345 wma->hic = 0;
346 MCIAVI_DrawFrame(wma);
347 return TRUE;
350 /* get the right handle */
351 if (fcc == 0) fcc = wma->inbih->biCompression;
352 if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
354 /* try to get a decompressor for that type */
355 wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS);
356 if (!wma->hic) {
357 WARN("Can't locate codec for the file\n");
358 return FALSE;
361 outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
363 wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
364 if (!wma->outbih) {
365 WARN("Can't alloc output BIH\n");
366 return FALSE;
368 if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
369 WARN("Can't open decompressor\n");
370 return FALSE;
373 TRACE("bih.biSize=%ld\n", wma->outbih->biSize);
374 TRACE("bih.biWidth=%ld\n", wma->outbih->biWidth);
375 TRACE("bih.biHeight=%ld\n", wma->outbih->biHeight);
376 TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes);
377 TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount);
378 TRACE("bih.biCompression=%lx\n", wma->outbih->biCompression);
379 TRACE("bih.biSizeImage=%ld\n", wma->outbih->biSizeImage);
380 TRACE("bih.biXPelsPerMeter=%ld\n", wma->outbih->biXPelsPerMeter);
381 TRACE("bih.biYPelsPerMeter=%ld\n", wma->outbih->biYPelsPerMeter);
382 TRACE("bih.biClrUsed=%ld\n", wma->outbih->biClrUsed);
383 TRACE("bih.biClrImportant=%ld\n", wma->outbih->biClrImportant);
385 wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage);
386 if (!wma->outdata) {
387 WARN("Can't alloc output buffer\n");
388 return FALSE;
391 if (ICSendMessage(wma->hic, ICM_DECOMPRESS_BEGIN,
392 (DWORD)wma->inbih, (DWORD)wma->outbih) != ICERR_OK) {
393 WARN("Can't begin decompression\n");
394 return FALSE;
397 MCIAVI_DrawFrame(wma);
399 return TRUE;
402 static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
403 DWORD dwParam1, DWORD dwParam2)
405 WINE_MCIAVI* wma = (WINE_MCIAVI*)dwInstance;
407 switch (uMsg) {
408 case WOM_OPEN:
409 case WOM_CLOSE:
410 break;
411 case WOM_DONE:
412 InterlockedIncrement(&wma->dwEventCount);
413 TRACE("Returning waveHdr=%lx\n", dwParam1);
414 SetEvent(wma->hEvent);
415 break;
416 default:
417 ERR("Unknown uMsg=%d\n", uMsg);
421 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
423 DWORD dwRet;
424 LPWAVEHDR waveHdr;
425 unsigned i;
427 dwRet = waveOutOpen(&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
428 (DWORD)MCIAVI_waveCallback, (DWORD)wma, CALLBACK_FUNCTION);
429 if (dwRet != 0) {
430 TRACE("Can't open low level audio device %ld\n", dwRet);
431 dwRet = MCIERR_DEVICE_OPEN;
432 wma->hWave = 0;
433 goto cleanUp;
436 /* FIXME: should set up a heuristic to compute the number of wave headers
437 * to be used...
439 *nHdr = 7;
440 waveHdr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
441 *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize));
442 if (!waveHdr) {
443 TRACE("Can't alloc wave headers\n");
444 dwRet = MCIERR_DEVICE_OPEN;
445 goto cleanUp;
448 for (i = 0; i < *nHdr; i++) {
449 /* other fields are zero:ed on allocation */
450 waveHdr[i].lpData = (char*)waveHdr +
451 *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize;
452 waveHdr[i].dwBufferLength = wma->ash_audio.dwSuggestedBufferSize;
453 if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) {
454 dwRet = MCIERR_INTERNAL;
455 goto cleanUp;
459 if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) {
460 FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n");
462 wma->dwCurrAudioBlock = 0;
464 wma->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
465 wma->dwEventCount = *nHdr - 1;
466 *pWaveHdr = waveHdr;
467 cleanUp:
468 return dwRet;
471 void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
473 TRACE("%ld (ec=%lu)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount);
475 /* push as many blocks as possible => audio gets priority */
476 while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY &&
477 wma->dwCurrAudioBlock < wma->dwPlayableAudioBlocks) {
478 unsigned whidx = wma->dwCurrAudioBlock % nHdr;
480 ResetEvent(wma->hEvent);
481 if (InterlockedDecrement(&wma->dwEventCount) < 0 ||
482 !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset)
483 break;
485 mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET);
486 mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize);
488 waveHdr[whidx].dwFlags &= ~WHDR_DONE;
489 waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize;
490 waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
491 wma->dwCurrAudioBlock++;
493 InterlockedIncrement(&wma->dwEventCount);
496 LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
498 void* pBitmapData = NULL;
499 LPBITMAPINFO pBitmapInfo = NULL;
500 HDC hdcMem;
501 HBITMAP hbmOld;
502 int nWidth;
503 int nHeight;
505 if (!hDC || !wma->inbih)
506 return TRUE;
508 TRACE("Painting frame %lu\n", wma->dwCurrVideoFrame);
510 if (wma->hic) {
511 pBitmapData = wma->outdata;
512 pBitmapInfo = (LPBITMAPINFO)wma->outbih;
514 nWidth = wma->outbih->biWidth;
515 nHeight = wma->outbih->biHeight;
516 } else {
517 pBitmapData = wma->indata;
518 pBitmapInfo = (LPBITMAPINFO)wma->inbih;
520 nWidth = wma->inbih->biWidth;
521 nHeight = wma->inbih->biHeight;
524 if (!wma->hbmFrame)
525 wma->hbmFrame = CreateCompatibleBitmap(hDC, nWidth, nHeight);
527 SetDIBits(hDC, wma->hbmFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS);
529 hdcMem = CreateCompatibleDC(hDC);
530 hbmOld = SelectObject(hdcMem, wma->hbmFrame);
532 BitBlt(hDC, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
534 SelectObject(hdcMem, hbmOld);
535 DeleteDC(hdcMem);
536 return TRUE;
539 LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma)
541 HDC hDC;
543 TRACE("Drawing frame %lu\n", wma->dwCurrVideoFrame);
545 if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
546 return FALSE;
548 EnterCriticalSection(&wma->cs);
550 mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
551 mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
553 /* FIXME ? */
554 wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
556 if (wma->hic &&
557 ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
558 wma->outbih, wma->outdata) != ICERR_OK) {
559 LeaveCriticalSection(&wma->cs);
560 WARN("Decompression error\n");
561 return FALSE;
564 if (IsWindowVisible(wma->hWnd) && (hDC = GetDC(wma->hWnd)) != 0) {
565 MCIAVI_PaintFrame(wma, hDC);
566 ReleaseDC(wma->hWnd, hDC);
569 LeaveCriticalSection(&wma->cs);
571 return TRUE;