1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * Digital video MCI Wine Driver
6 * Copyright 1999, 2000 Eric POUECH
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "private_mciavi.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
28 static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
32 mmckInfo.ckid = ckidSTREAMHEADER;
33 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
34 WARN("Can't find 'strh' chunk\n");
38 mmioRead(wma->hFile, (LPSTR)&wma->ash_audio, sizeof(wma->ash_audio));
40 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccType)),
41 HIBYTE(LOWORD(wma->ash_audio.fccType)),
42 LOBYTE(HIWORD(wma->ash_audio.fccType)),
43 HIBYTE(HIWORD(wma->ash_audio.fccType)));
44 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccHandler)),
45 HIBYTE(LOWORD(wma->ash_audio.fccHandler)),
46 LOBYTE(HIWORD(wma->ash_audio.fccHandler)),
47 HIBYTE(HIWORD(wma->ash_audio.fccHandler)));
48 TRACE("ash.dwFlags=%ld\n", wma->ash_audio.dwFlags);
49 TRACE("ash.wPriority=%d\n", wma->ash_audio.wPriority);
50 TRACE("ash.wLanguage=%d\n", wma->ash_audio.wLanguage);
51 TRACE("ash.dwInitialFrames=%ld\n", wma->ash_audio.dwInitialFrames);
52 TRACE("ash.dwScale=%ld\n", wma->ash_audio.dwScale);
53 TRACE("ash.dwRate=%ld\n", wma->ash_audio.dwRate);
54 TRACE("ash.dwStart=%ld\n", wma->ash_audio.dwStart);
55 TRACE("ash.dwLength=%ld\n", wma->ash_audio.dwLength);
56 TRACE("ash.dwSuggestedBufferSize=%ld\n", wma->ash_audio.dwSuggestedBufferSize);
57 TRACE("ash.dwQuality=%ld\n", wma->ash_audio.dwQuality);
58 TRACE("ash.dwSampleSize=%ld\n", wma->ash_audio.dwSampleSize);
59 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left,
60 wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right);
62 mmioAscend(wma->hFile, &mmckInfo, 0);
64 mmckInfo.ckid = ckidSTREAMFORMAT;
65 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
66 WARN("Can't find 'strh' chunk\n");
69 if (mmckInfo.cksize < sizeof(WAVEFORMAT)) {
70 WARN("Size of strf chunk (%ld) < audio format struct\n", mmckInfo.cksize);
73 wma->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
74 if (!wma->lpWaveFormat) {
75 WARN("Can't alloc WaveFormat\n");
79 mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize);
81 TRACE("waveFormat.wFormatTag=%d\n", wma->lpWaveFormat->wFormatTag);
82 TRACE("waveFormat.nChannels=%d\n", wma->lpWaveFormat->nChannels);
83 TRACE("waveFormat.nSamplesPerSec=%ld\n", wma->lpWaveFormat->nSamplesPerSec);
84 TRACE("waveFormat.nAvgBytesPerSec=%ld\n", wma->lpWaveFormat->nAvgBytesPerSec);
85 TRACE("waveFormat.nBlockAlign=%d\n", wma->lpWaveFormat->nBlockAlign);
86 TRACE("waveFormat.wBitsPerSample=%d\n", wma->lpWaveFormat->wBitsPerSample);
87 if (mmckInfo.cksize >= sizeof(WAVEFORMATEX))
88 TRACE("waveFormat.cbSize=%d\n", wma->lpWaveFormat->cbSize);
90 mmioAscend(wma->hFile, &mmckInfo, 0);
95 static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
99 mmckInfo.ckid = ckidSTREAMHEADER;
100 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
101 WARN("Can't find 'strh' chunk\n");
105 mmioRead(wma->hFile, (LPSTR)&wma->ash_video, sizeof(wma->ash_video));
107 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccType)),
108 HIBYTE(LOWORD(wma->ash_video.fccType)),
109 LOBYTE(HIWORD(wma->ash_video.fccType)),
110 HIBYTE(HIWORD(wma->ash_video.fccType)));
111 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccHandler)),
112 HIBYTE(LOWORD(wma->ash_video.fccHandler)),
113 LOBYTE(HIWORD(wma->ash_video.fccHandler)),
114 HIBYTE(HIWORD(wma->ash_video.fccHandler)));
115 TRACE("ash.dwFlags=%ld\n", wma->ash_video.dwFlags);
116 TRACE("ash.wPriority=%d\n", wma->ash_video.wPriority);
117 TRACE("ash.wLanguage=%d\n", wma->ash_video.wLanguage);
118 TRACE("ash.dwInitialFrames=%ld\n", wma->ash_video.dwInitialFrames);
119 TRACE("ash.dwScale=%ld\n", wma->ash_video.dwScale);
120 TRACE("ash.dwRate=%ld\n", wma->ash_video.dwRate);
121 TRACE("ash.dwStart=%ld\n", wma->ash_video.dwStart);
122 TRACE("ash.dwLength=%ld\n", wma->ash_video.dwLength);
123 TRACE("ash.dwSuggestedBufferSize=%ld\n", wma->ash_video.dwSuggestedBufferSize);
124 TRACE("ash.dwQuality=%ld\n", wma->ash_video.dwQuality);
125 TRACE("ash.dwSampleSize=%ld\n", wma->ash_video.dwSampleSize);
126 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left,
127 wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right);
129 mmioAscend(wma->hFile, &mmckInfo, 0);
131 mmckInfo.ckid = ckidSTREAMFORMAT;
132 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
133 WARN("Can't find 'strh' chunk\n");
137 wma->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
139 WARN("Can't alloc input BIH\n");
143 mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize);
145 TRACE("bih.biSize=%ld\n", wma->inbih->biSize);
146 TRACE("bih.biWidth=%ld\n", wma->inbih->biWidth);
147 TRACE("bih.biHeight=%ld\n", wma->inbih->biHeight);
148 TRACE("bih.biPlanes=%d\n", wma->inbih->biPlanes);
149 TRACE("bih.biBitCount=%d\n", wma->inbih->biBitCount);
150 TRACE("bih.biCompression=%lx\n", wma->inbih->biCompression);
151 TRACE("bih.biSizeImage=%ld\n", wma->inbih->biSizeImage);
152 TRACE("bih.biXPelsPerMeter=%ld\n", wma->inbih->biXPelsPerMeter);
153 TRACE("bih.biYPelsPerMeter=%ld\n", wma->inbih->biYPelsPerMeter);
154 TRACE("bih.biClrUsed=%ld\n", wma->inbih->biClrUsed);
155 TRACE("bih.biClrImportant=%ld\n", wma->inbih->biClrImportant);
157 mmioAscend(wma->hFile, &mmckInfo, 0);
162 struct AviListBuild {
163 DWORD numVideoFrames;
164 DWORD numAudioAllocated;
165 DWORD numAudioBlocks;
170 static BOOL MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck,
171 struct AviListBuild* alb)
173 if (mmck->ckid == ckidAVIPADDING) return TRUE;
175 switch (TWOCCFromFOURCC(mmck->ckid)) {
177 case cktypeDIBcompressed:
178 case cktypePALchange:
179 TRACE("Adding video frame[%ld]: %ld bytes\n",
180 alb->numVideoFrames, mmck->cksize);
181 if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
182 wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
183 wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
184 if (alb->inVideoSize < mmck->cksize)
185 alb->inVideoSize = mmck->cksize;
186 alb->numVideoFrames++;
188 WARN("Too many video frames\n");
191 case cktypeWAVEbytes:
192 TRACE("Adding audio frame[%ld]: %ld bytes\n",
193 alb->numAudioBlocks, mmck->cksize);
194 if (wma->lpWaveFormat) {
195 if (alb->numAudioBlocks >= alb->numAudioAllocated) {
196 alb->numAudioAllocated += 32;
197 wma->lpAudioIndex = HeapReAlloc(GetProcessHeap(), 0,
199 alb->numAudioAllocated * sizeof(struct MMIOPos));
200 if (!wma->lpAudioIndex) return FALSE;
202 wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset;
203 wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize;
204 if (alb->inAudioSize < mmck->cksize)
205 alb->inAudioSize = mmck->cksize;
206 alb->numAudioBlocks++;
208 WARN("Wave chunk without wave format... discarding\n");
212 WARN("Unknown frame type %04x\n", TWOCCFromFOURCC(mmck->ckid));
218 BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
224 struct AviListBuild alb;
226 if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
227 WARN("Can't find 'RIFF' chunk\n");
231 if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
232 WARN("Can't find 'AVI ' chunk\n");
236 mmckHead.fccType = listtypeAVIHEADER;
237 if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
238 WARN("Can't find 'hdrl' list\n");
242 mmckInfo.ckid = ckidAVIMAINHDR;
243 if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
244 WARN("Can't find 'avih' chunk\n");
248 mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));
250 TRACE("mah.dwMicroSecPerFrame=%ld\n", wma->mah.dwMicroSecPerFrame);
251 TRACE("mah.dwMaxBytesPerSec=%ld\n", wma->mah.dwMaxBytesPerSec);
252 TRACE("mah.dwPaddingGranularity=%ld\n", wma->mah.dwPaddingGranularity);
253 TRACE("mah.dwFlags=%ld\n", wma->mah.dwFlags);
254 TRACE("mah.dwTotalFrames=%ld\n", wma->mah.dwTotalFrames);
255 TRACE("mah.dwInitialFrames=%ld\n", wma->mah.dwInitialFrames);
256 TRACE("mah.dwStreams=%ld\n", wma->mah.dwStreams);
257 TRACE("mah.dwSuggestedBufferSize=%ld\n", wma->mah.dwSuggestedBufferSize);
258 TRACE("mah.dwWidth=%ld\n", wma->mah.dwWidth);
259 TRACE("mah.dwHeight=%ld\n", wma->mah.dwHeight);
261 mmioAscend(wma->hFile, &mmckInfo, 0);
263 mmckList.fccType = listtypeSTREAMHEADER;
264 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
265 WARN("Can't find 'strl' list\n");
269 if (!MCIAVI_GetInfoVideo(wma, &mmckList)) {
273 mmioAscend(wma->hFile, &mmckList, 0);
275 mmckList.fccType = listtypeSTREAMHEADER;
276 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
277 if (!MCIAVI_GetInfoAudio(wma, &mmckList)) {
280 mmioAscend(wma->hFile, &mmckList, 0);
283 mmioAscend(wma->hFile, &mmckHead, 0);
285 /* no need to read optional JUNK chunk */
287 mmckList.fccType = listtypeAVIMOVIE;
288 if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
289 WARN("Can't find 'movi' list\n");
293 wma->dwPlayableVideoFrames = wma->mah.dwTotalFrames;
294 wma->lpVideoIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
295 wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
296 if (!wma->lpVideoIndex) {
297 WARN("Can't alloc video index array\n");
300 wma->dwPlayableAudioBlocks = 0;
301 wma->lpAudioIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
302 wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
303 if (!wma->lpAudioIndex) {
304 WARN("Can't alloc audio index array\n");
308 alb.numAudioBlocks = alb.numVideoFrames = 0;
309 alb.inVideoSize = alb.inAudioSize = 0;
310 alb.numAudioAllocated = 0;
312 while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
313 if (mmckInfo.fccType == listtypeAVIRECORD) {
316 while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
317 MCIAVI_AddFrame(wma, &tmp, &alb);
318 mmioAscend(wma->hFile, &tmp, 0);
321 MCIAVI_AddFrame(wma, &mmckInfo, &alb);
324 mmioAscend(wma->hFile, &mmckInfo, 0);
326 if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
327 WARN("Found %ld video frames (/%ld), reducing playable frames\n",
328 alb.numVideoFrames, wma->dwPlayableVideoFrames);
329 wma->dwPlayableVideoFrames = alb.numVideoFrames;
331 wma->dwPlayableAudioBlocks = alb.numAudioBlocks;
333 if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) {
334 WARN("inVideoSize=%ld suggestedSize=%ld\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
335 wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize;
337 if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) {
338 WARN("inAudioSize=%ld suggestedSize=%ld\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
339 wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize;
342 wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize);
344 WARN("Can't alloc input buffer\n");
351 BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma)
354 FOURCC fcc = wma->ash_video.fccHandler;
356 /* check uncompressed AVI */
357 if ((fcc == mmioFOURCC('D','I','B',' ')) ||
358 (fcc == mmioFOURCC('R','L','E',' '))) {
360 MCIAVI_DrawFrame(wma);
364 /* get the right handle */
365 if (fcc == 0) fcc = wma->inbih->biCompression;
366 if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
368 /* try to get a decompressor for that type */
369 wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS);
371 WARN("Can't locate codec for the file\n");
375 outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
377 wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
379 WARN("Can't alloc output BIH\n");
382 if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
383 WARN("Can't open decompressor\n");
387 TRACE("bih.biSize=%ld\n", wma->outbih->biSize);
388 TRACE("bih.biWidth=%ld\n", wma->outbih->biWidth);
389 TRACE("bih.biHeight=%ld\n", wma->outbih->biHeight);
390 TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes);
391 TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount);
392 TRACE("bih.biCompression=%lx\n", wma->outbih->biCompression);
393 TRACE("bih.biSizeImage=%ld\n", wma->outbih->biSizeImage);
394 TRACE("bih.biXPelsPerMeter=%ld\n", wma->outbih->biXPelsPerMeter);
395 TRACE("bih.biYPelsPerMeter=%ld\n", wma->outbih->biYPelsPerMeter);
396 TRACE("bih.biClrUsed=%ld\n", wma->outbih->biClrUsed);
397 TRACE("bih.biClrImportant=%ld\n", wma->outbih->biClrImportant);
399 wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage);
401 WARN("Can't alloc output buffer\n");
405 if (ICSendMessage(wma->hic, ICM_DECOMPRESS_BEGIN,
406 (DWORD)wma->inbih, (DWORD)wma->outbih) != ICERR_OK) {
407 WARN("Can't begin decompression\n");
411 MCIAVI_DrawFrame(wma);
416 static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,
417 DWORD dwParam1, DWORD dwParam2)
419 WINE_MCIAVI* wma = (WINE_MCIAVI*)dwInstance;
426 InterlockedIncrement(&wma->dwEventCount);
427 TRACE("Returning waveHdr=%lx\n", dwParam1);
428 SetEvent(wma->hEvent);
431 ERR("Unknown uMsg=%d\n", uMsg);
435 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
441 dwRet = waveOutOpen(&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
442 (DWORD)MCIAVI_waveCallback, (DWORD)wma, CALLBACK_FUNCTION);
444 TRACE("Can't open low level audio device %ld\n", dwRet);
445 dwRet = MCIERR_DEVICE_OPEN;
450 /* FIXME: should set up a heuristic to compute the number of wave headers
454 waveHdr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
455 *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize));
457 TRACE("Can't alloc wave headers\n");
458 dwRet = MCIERR_DEVICE_OPEN;
462 for (i = 0; i < *nHdr; i++) {
463 /* other fields are zero:ed on allocation */
464 waveHdr[i].lpData = (char*)waveHdr +
465 *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize;
466 waveHdr[i].dwBufferLength = wma->ash_audio.dwSuggestedBufferSize;
467 if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) {
468 dwRet = MCIERR_INTERNAL;
473 if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) {
474 FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n");
476 wma->dwCurrAudioBlock = 0;
478 wma->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
479 wma->dwEventCount = *nHdr - 1;
485 void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
487 TRACE("%ld (ec=%lu)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount);
489 /* push as many blocks as possible => audio gets priority */
490 while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY &&
491 wma->dwCurrAudioBlock < wma->dwPlayableAudioBlocks) {
492 unsigned whidx = wma->dwCurrAudioBlock % nHdr;
494 ResetEvent(wma->hEvent);
495 if (InterlockedDecrement(&wma->dwEventCount) < 0 ||
496 !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset)
499 mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET);
500 mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize);
502 waveHdr[whidx].dwFlags &= ~WHDR_DONE;
503 waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize;
504 waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
505 wma->dwCurrAudioBlock++;
507 InterlockedIncrement(&wma->dwEventCount);
510 LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
512 void* pBitmapData = NULL;
513 LPBITMAPINFO pBitmapInfo = NULL;
519 if (!hDC || !wma->inbih)
522 TRACE("Painting frame %lu\n", wma->dwCurrVideoFrame);
525 pBitmapData = wma->outdata;
526 pBitmapInfo = (LPBITMAPINFO)wma->outbih;
528 nWidth = wma->outbih->biWidth;
529 nHeight = wma->outbih->biHeight;
531 pBitmapData = wma->indata;
532 pBitmapInfo = (LPBITMAPINFO)wma->inbih;
534 nWidth = wma->inbih->biWidth;
535 nHeight = wma->inbih->biHeight;
539 wma->hbmFrame = CreateCompatibleBitmap(hDC, nWidth, nHeight);
541 SetDIBits(hDC, wma->hbmFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS);
543 hdcMem = CreateCompatibleDC(hDC);
544 hbmOld = SelectObject(hdcMem, wma->hbmFrame);
546 BitBlt(hDC, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);
548 SelectObject(hdcMem, hbmOld);
553 LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma)
557 TRACE("Drawing frame %lu\n", wma->dwCurrVideoFrame);
559 if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
562 EnterCriticalSection(&wma->cs);
564 mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
565 mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
568 wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
571 ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
572 wma->outbih, wma->outdata) != ICERR_OK) {
573 LeaveCriticalSection(&wma->cs);
574 WARN("Decompression error\n");
578 if (IsWindowVisible(wma->hWnd) && (hDC = GetDC(wma->hWnd)) != 0) {
579 MCIAVI_PaintFrame(wma, hDC);
580 ReleaseDC(wma->hWnd, hDC);
583 LeaveCriticalSection(&wma->cs);