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((HWAVEOUT
*)&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
);