1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
4 * Digital video MCI Wine Driver
6 * Copyright 1999, 2000 Eric POUECH
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
)
18 mmckInfo
.ckid
= ckidSTREAMHEADER
;
19 if (mmioDescend(wma
->hFile
, &mmckInfo
, mmckList
, MMIO_FINDCHUNK
) != 0) {
20 WARN("Can't find 'strh' chunk\n");
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");
55 if (mmckInfo
.cksize
< sizeof(WAVEFORMAT
)) {
56 WARN("Size of strf chunk (%ld) < audio format struct\n", mmckInfo
.cksize
);
59 wma
->lpWaveFormat
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
60 if (!wma
->lpWaveFormat
) {
61 WARN("Can't alloc WaveFormat\n");
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);
81 static BOOL
MCIAVI_GetInfoVideo(WINE_MCIAVI
* wma
, const MMCKINFO
* mmckList
)
85 mmckInfo
.ckid
= ckidSTREAMHEADER
;
86 if (mmioDescend(wma
->hFile
, &mmckInfo
, mmckList
, MMIO_FINDCHUNK
) != 0) {
87 WARN("Can't find 'strh' chunk\n");
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");
123 wma
->inbih
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
125 WARN("Can't alloc input BIH\n");
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);
148 struct AviListBuild
{
149 DWORD numVideoFrames
;
150 DWORD numAudioAllocated
;
151 DWORD numAudioBlocks
;
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
)) {
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
++;
174 WARN("Too many video frames\n");
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,
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
++;
194 WARN("Wave chunk without wave format... discarding\n");
198 WARN("Unknown frame type %04x\n", TWOCCFromFOURCC(mmck
->ckid
));
204 BOOL
MCIAVI_GetInfo(WINE_MCIAVI
* wma
)
210 struct AviListBuild alb
;
212 if (mmioDescend(wma
->hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
213 WARN("Can't find 'RIFF' chunk\n");
217 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) || (ckMainRIFF
.fccType
!= formtypeAVI
)) {
218 WARN("Can't find 'AVI ' chunk\n");
222 mmckHead
.fccType
= listtypeAVIHEADER
;
223 if (mmioDescend(wma
->hFile
, &mmckHead
, &ckMainRIFF
, MMIO_FINDLIST
) != 0) {
224 WARN("Can't find 'hdrl' list\n");
228 mmckInfo
.ckid
= ckidAVIMAINHDR
;
229 if (mmioDescend(wma
->hFile
, &mmckInfo
, &mmckHead
, MMIO_FINDCHUNK
) != 0) {
230 WARN("Can't find 'avih' chunk\n");
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");
255 if (!MCIAVI_GetInfoVideo(wma
, &mmckList
)) {
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
)) {
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");
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");
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");
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
) {
302 while (mmioDescend(wma
->hFile
, &tmp
, &mmckInfo
, 0) == 0) {
303 MCIAVI_AddFrame(wma
, &tmp
, &alb
);
304 mmioAscend(wma
->hFile
, &tmp
, 0);
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
);
330 WARN("Can't alloc input buffer\n");
337 BOOL
MCIAVI_OpenVideo(WINE_MCIAVI
* wma
)
340 FOURCC fcc
= wma
->ash_video
.fccHandler
;
342 /* check uncompressed AVI */
343 if ((fcc
== mmioFOURCC('D','I','B',' ')) ||
344 (fcc
== mmioFOURCC('R','L','E',' '))) {
346 MCIAVI_DrawFrame(wma
);
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
);
357 WARN("Can't locate codec for the file\n");
361 outSize
= sizeof(BITMAPINFOHEADER
) + 256 * sizeof(RGBQUAD
);
363 wma
->outbih
= HeapAlloc(GetProcessHeap(), 0, outSize
);
365 WARN("Can't alloc output BIH\n");
368 if (!ICGetDisplayFormat(wma
->hic
, wma
->inbih
, wma
->outbih
, 0, 0, 0)) {
369 WARN("Can't open decompressor\n");
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
);
387 WARN("Can't alloc output buffer\n");
391 if (ICSendMessage(wma
->hic
, ICM_DECOMPRESS_BEGIN
,
392 (DWORD
)wma
->inbih
, (DWORD
)wma
->outbih
) != ICERR_OK
) {
393 WARN("Can't begin decompression\n");
397 MCIAVI_DrawFrame(wma
);
402 static void CALLBACK
MCIAVI_waveCallback(HWAVEOUT hwo
, UINT uMsg
, DWORD dwInstance
,
403 DWORD dwParam1
, DWORD dwParam2
)
405 WINE_MCIAVI
* wma
= (WINE_MCIAVI
*)dwInstance
;
412 InterlockedIncrement(&wma
->dwEventCount
);
413 TRACE("Returning waveHdr=%lx\n", dwParam1
);
414 SetEvent(wma
->hEvent
);
417 ERR("Unknown uMsg=%d\n", uMsg
);
421 DWORD
MCIAVI_OpenAudio(WINE_MCIAVI
* wma
, unsigned* nHdr
, LPWAVEHDR
* pWaveHdr
)
427 dwRet
= waveOutOpen(&wma
->hWave
, WAVE_MAPPER
, wma
->lpWaveFormat
,
428 (DWORD
)MCIAVI_waveCallback
, (DWORD
)wma
, CALLBACK_FUNCTION
);
430 TRACE("Can't open low level audio device %ld\n", dwRet
);
431 dwRet
= MCIERR_DEVICE_OPEN
;
436 /* FIXME: should set up a heuristic to compute the number of wave headers
440 waveHdr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
441 *nHdr
* (sizeof(WAVEHDR
) + wma
->ash_audio
.dwSuggestedBufferSize
));
443 TRACE("Can't alloc wave headers\n");
444 dwRet
= MCIERR_DEVICE_OPEN
;
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
;
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;
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
)
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
;
505 if (!hDC
|| !wma
->inbih
)
508 TRACE("Painting frame %lu\n", wma
->dwCurrVideoFrame
);
511 pBitmapData
= wma
->outdata
;
512 pBitmapInfo
= (LPBITMAPINFO
)wma
->outbih
;
514 nWidth
= wma
->outbih
->biWidth
;
515 nHeight
= wma
->outbih
->biHeight
;
517 pBitmapData
= wma
->indata
;
518 pBitmapInfo
= (LPBITMAPINFO
)wma
->inbih
;
520 nWidth
= wma
->inbih
->biWidth
;
521 nHeight
= wma
->inbih
->biHeight
;
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
);
539 LRESULT
MCIAVI_DrawFrame(WINE_MCIAVI
* wma
)
543 TRACE("Drawing frame %lu\n", wma
->dwCurrVideoFrame
);
545 if (!wma
->lpVideoIndex
[wma
->dwCurrVideoFrame
].dwOffset
)
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
);
554 wma
->inbih
->biSizeImage
= wma
->lpVideoIndex
[wma
->dwCurrVideoFrame
].dwSize
;
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");
564 if (IsWindowVisible(wma
->hWnd
) && (hDC
= GetDC(wma
->hWnd
)) != 0) {
565 MCIAVI_PaintFrame(wma
, hDC
);
566 ReleaseDC(wma
->hWnd
, hDC
);
569 LeaveCriticalSection(&wma
->cs
);