ReactOS 0.4.15-dev-7924-g5949c20
mmoutput.c
Go to the documentation of this file.
1/*
2 * Digital video MCI Wine Driver
3 *
4 * Copyright 1999, 2000 Eric POUECH
5 * Copyright 2003 Dmitry Timoshkov
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#include "private_mciavi.h"
23#include "wine/debug.h"
24
26
27static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO *mmckStream)
28{
29 MMCKINFO mmckInfo;
30
31 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccType)),
35 if (wma->ash_audio.fccHandler) /* not all streams specify a handler */
36 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccHandler)),
40 else
41 TRACE("ash.fccHandler=0, no handler specified\n");
42 TRACE("ash.dwFlags=%d\n", wma->ash_audio.dwFlags);
43 TRACE("ash.wPriority=%d\n", wma->ash_audio.wPriority);
44 TRACE("ash.wLanguage=%d\n", wma->ash_audio.wLanguage);
45 TRACE("ash.dwInitialFrames=%d\n", wma->ash_audio.dwInitialFrames);
46 TRACE("ash.dwScale=%d\n", wma->ash_audio.dwScale);
47 TRACE("ash.dwRate=%d\n", wma->ash_audio.dwRate);
48 TRACE("ash.dwStart=%d\n", wma->ash_audio.dwStart);
49 TRACE("ash.dwLength=%d\n", wma->ash_audio.dwLength);
50 TRACE("ash.dwSuggestedBufferSize=%d\n", wma->ash_audio.dwSuggestedBufferSize);
51 TRACE("ash.dwQuality=%d\n", wma->ash_audio.dwQuality);
52 TRACE("ash.dwSampleSize=%d\n", wma->ash_audio.dwSampleSize);
53 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left,
54 wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right);
55
56 /* rewind to the start of the stream */
57 mmioAscend(wma->hFile, mmckStream, 0);
58
59 mmckInfo.ckid = ckidSTREAMFORMAT;
60 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
61 WARN("Can't find 'strf' chunk\n");
62 return FALSE;
63 }
64 if (mmckInfo.cksize < sizeof(WAVEFORMAT)) {
65 WARN("Size of strf chunk (%d) < audio format struct\n", mmckInfo.cksize);
66 return FALSE;
67 }
68 wma->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
69 if (!wma->lpWaveFormat) {
70 WARN("Can't alloc WaveFormat\n");
71 return FALSE;
72 }
73
74 mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize);
75
76 TRACE("waveFormat.wFormatTag=%d\n", wma->lpWaveFormat->wFormatTag);
77 TRACE("waveFormat.nChannels=%d\n", wma->lpWaveFormat->nChannels);
78 TRACE("waveFormat.nSamplesPerSec=%d\n", wma->lpWaveFormat->nSamplesPerSec);
79 TRACE("waveFormat.nAvgBytesPerSec=%d\n", wma->lpWaveFormat->nAvgBytesPerSec);
80 TRACE("waveFormat.nBlockAlign=%d\n", wma->lpWaveFormat->nBlockAlign);
81 TRACE("waveFormat.wBitsPerSample=%d\n", wma->lpWaveFormat->wBitsPerSample);
82 if (mmckInfo.cksize >= sizeof(WAVEFORMATEX))
83 TRACE("waveFormat.cbSize=%d\n", wma->lpWaveFormat->cbSize);
84
85 return TRUE;
86}
87
88static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO* mmckStream)
89{
90 MMCKINFO mmckInfo;
91
92 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccType)),
96 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccHandler)),
100 TRACE("ash.dwFlags=%d\n", wma->ash_video.dwFlags);
101 TRACE("ash.wPriority=%d\n", wma->ash_video.wPriority);
102 TRACE("ash.wLanguage=%d\n", wma->ash_video.wLanguage);
103 TRACE("ash.dwInitialFrames=%d\n", wma->ash_video.dwInitialFrames);
104 TRACE("ash.dwScale=%d\n", wma->ash_video.dwScale);
105 TRACE("ash.dwRate=%d\n", wma->ash_video.dwRate);
106 TRACE("ash.dwStart=%d\n", wma->ash_video.dwStart);
107 TRACE("ash.dwLength=%d\n", wma->ash_video.dwLength);
108 TRACE("ash.dwSuggestedBufferSize=%d\n", wma->ash_video.dwSuggestedBufferSize);
109 TRACE("ash.dwQuality=%d\n", wma->ash_video.dwQuality);
110 TRACE("ash.dwSampleSize=%d\n", wma->ash_video.dwSampleSize);
111 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left,
112 wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right);
113
114 /* rewind to the start of the stream */
115 mmioAscend(wma->hFile, mmckStream, 0);
116
117 mmckInfo.ckid = ckidSTREAMFORMAT;
118 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
119 WARN("Can't find 'strf' chunk\n");
120 return FALSE;
121 }
122
123 wma->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
124 if (!wma->inbih) {
125 WARN("Can't alloc input BIH\n");
126 return FALSE;
127 }
128
129 mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize);
130
131 TRACE("bih.biSize=%d\n", wma->inbih->biSize);
132 TRACE("bih.biWidth=%d\n", wma->inbih->biWidth);
133 TRACE("bih.biHeight=%d\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=%x\n", wma->inbih->biCompression);
137 TRACE("bih.biSizeImage=%d\n", wma->inbih->biSizeImage);
138 TRACE("bih.biXPelsPerMeter=%d\n", wma->inbih->biXPelsPerMeter);
139 TRACE("bih.biYPelsPerMeter=%d\n", wma->inbih->biYPelsPerMeter);
140 TRACE("bih.biClrUsed=%d\n", wma->inbih->biClrUsed);
141 TRACE("bih.biClrImportant=%d\n", wma->inbih->biClrImportant);
142
143 SetRect(&wma->source, 0, 0, wma->inbih->biWidth, wma->inbih->biHeight);
144 wma->dest = wma->source;
145
146 return TRUE;
147}
148
155};
156
158 struct AviListBuild* alb)
159{
160 const BYTE *p;
161 DWORD stream_n;
162 DWORD twocc;
163
164 if (mmck->ckid == ckidAVIPADDING) return TRUE;
165
166 p = (const BYTE *)&mmck->ckid;
167
168 if (!isxdigit(p[0]) || !isxdigit(p[1]))
169 {
170 WARN("wrongly encoded stream #\n");
171 return FALSE;
172 }
173
174 stream_n = (p[0] <= '9') ? (p[0] - '0') : (tolower(p[0]) - 'a' + 10);
175 stream_n <<= 4;
176 stream_n |= (p[1] <= '9') ? (p[1] - '0') : (tolower(p[1]) - 'a' + 10);
177
178 TRACE("ckid %4.4s (stream #%d)\n", (LPSTR)&mmck->ckid, stream_n);
179
180 /* Some (rare?) AVI files have video streams name XXYY where XX = stream number and YY = TWOCC
181 * of the last 2 characters of the biCompression member of the BITMAPINFOHEADER structure.
182 * Ex: fccHandler = IV32 & biCompression = IV32 => stream name = XX32
183 * fccHandler = MSVC & biCompression = CRAM => stream name = XXAM
184 * Another possibility is that these TWOCC are simply ignored.
185 * Default to cktypeDIBcompressed when this case happens.
186 */
187 twocc = TWOCCFromFOURCC(mmck->ckid);
188 if (twocc == TWOCCFromFOURCC(wma->inbih->biCompression))
189 twocc = cktypeDIBcompressed;
190 /* Also detect some chunks that seem to be used by Indeo videos where the chunk is named
191 * after the codec. */
192 else if (twocc == LOWORD(wma->ash_video.fccHandler))
193 twocc = cktypeDIBcompressed;
194 switch (twocc) {
195 case cktypeDIBbits:
197 case cktypePALchange:
198 if (stream_n != wma->video_stream_n)
199 {
200 TRACE("data belongs to another video stream #%d\n", stream_n);
201 return FALSE;
202 }
203
204 TRACE("Adding video frame[%d]: %d bytes\n",
205 alb->numVideoFrames, mmck->cksize);
206
207 if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
208 wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
209 wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
210 if (alb->inVideoSize < mmck->cksize)
211 alb->inVideoSize = mmck->cksize;
212 alb->numVideoFrames++;
213 } else {
214 WARN("Too many video frames\n");
215 }
216 break;
217 case cktypeWAVEbytes:
218 if (stream_n != wma->audio_stream_n)
219 {
220 TRACE("data belongs to another audio stream #%d\n", stream_n);
221 return FALSE;
222 }
223
224 TRACE("Adding audio frame[%d]: %d bytes\n",
225 alb->numAudioBlocks, mmck->cksize);
226 if (wma->lpWaveFormat) {
227 if (alb->numAudioBlocks >= alb->numAudioAllocated) {
228 DWORD newsize = alb->numAudioAllocated + 32;
229 struct MMIOPos* newindex;
230
231 if (!wma->lpAudioIndex)
232 newindex = HeapAlloc(GetProcessHeap(), 0, newsize * sizeof(struct MMIOPos));
233 else
234 newindex = HeapReAlloc(GetProcessHeap(), 0, wma->lpAudioIndex, newsize * sizeof(struct MMIOPos));
235 if (!newindex) return FALSE;
236 alb->numAudioAllocated = newsize;
237 wma->lpAudioIndex = newindex;
238 }
239 wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset;
240 wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize;
241 if (alb->inAudioSize < mmck->cksize)
242 alb->inAudioSize = mmck->cksize;
243 alb->numAudioBlocks++;
244 } else {
245 WARN("Wave chunk without wave format... discarding\n");
246 }
247 break;
248 default:
249 WARN("Unknown frame type %4.4s\n", (LPSTR)&mmck->ckid);
250 break;
251 }
252 return TRUE;
253}
254
256{
257 MMCKINFO ckMainRIFF;
258 MMCKINFO mmckHead;
259 MMCKINFO mmckList;
260 MMCKINFO mmckInfo;
261 AVIStreamHeader strh;
262 struct AviListBuild alb;
263 DWORD stream_n;
264
265 if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
266 WARN("Can't find 'RIFF' chunk\n");
267 return FALSE;
268 }
269
270 if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
271 WARN("Can't find 'AVI ' chunk\n");
272 return FALSE;
273 }
274
275 mmckHead.fccType = listtypeAVIHEADER;
276 if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
277 WARN("Can't find 'hdrl' list\n");
278 return FALSE;
279 }
280
281 mmckInfo.ckid = ckidAVIMAINHDR;
282 if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
283 WARN("Can't find 'avih' chunk\n");
284 return FALSE;
285 }
286
287 mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));
288
289 TRACE("mah.dwMicroSecPerFrame=%d\n", wma->mah.dwMicroSecPerFrame);
290 TRACE("mah.dwMaxBytesPerSec=%d\n", wma->mah.dwMaxBytesPerSec);
291 TRACE("mah.dwPaddingGranularity=%d\n", wma->mah.dwPaddingGranularity);
292 TRACE("mah.dwFlags=%d\n", wma->mah.dwFlags);
293 TRACE("mah.dwTotalFrames=%d\n", wma->mah.dwTotalFrames);
294 TRACE("mah.dwInitialFrames=%d\n", wma->mah.dwInitialFrames);
295 TRACE("mah.dwStreams=%d\n", wma->mah.dwStreams);
296 TRACE("mah.dwSuggestedBufferSize=%d\n", wma->mah.dwSuggestedBufferSize);
297 TRACE("mah.dwWidth=%d\n", wma->mah.dwWidth);
298 TRACE("mah.dwHeight=%d\n", wma->mah.dwHeight);
299
300 mmioAscend(wma->hFile, &mmckInfo, 0);
301
302 TRACE("Start of streams\n");
303 wma->video_stream_n = 0;
304 wma->audio_stream_n = 0;
305
306 for (stream_n = 0; stream_n < wma->mah.dwStreams; stream_n++)
307 {
308 MMCKINFO mmckStream;
309
310 mmckList.fccType = listtypeSTREAMHEADER;
311 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0)
312 break;
313
314 mmckStream.ckid = ckidSTREAMHEADER;
315 if (mmioDescend(wma->hFile, &mmckStream, &mmckList, MMIO_FINDCHUNK) != 0)
316 {
317 WARN("Can't find 'strh' chunk\n");
318 continue;
319 }
320
321 mmioRead(wma->hFile, (LPSTR)&strh, sizeof(strh));
322
323 TRACE("Stream #%d fccType %4.4s\n", stream_n, (LPSTR)&strh.fccType);
324
325 if (strh.fccType == streamtypeVIDEO)
326 {
327 TRACE("found video stream\n");
328 if (wma->inbih)
329 WARN("ignoring another video stream\n");
330 else
331 {
332 wma->ash_video = strh;
333
334 if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream))
335 return FALSE;
336 wma->video_stream_n = stream_n;
337 wma->dwSet |= 4;
338 }
339 }
340 else if (strh.fccType == streamtypeAUDIO)
341 {
342 TRACE("found audio stream\n");
343 if (wma->lpWaveFormat)
344 WARN("ignoring another audio stream\n");
345 else
346 {
347 wma->ash_audio = strh;
348
349 if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream))
350 return FALSE;
351 wma->audio_stream_n = stream_n;
352 wma->dwSet |= 3;
353 }
354 }
355 else
356 TRACE("Unsupported stream type %4.4s\n", (LPSTR)&strh.fccType);
357
358 mmioAscend(wma->hFile, &mmckList, 0);
359 }
360
361 TRACE("End of streams\n");
362
363 mmioAscend(wma->hFile, &mmckHead, 0);
364
365 /* no need to read optional JUNK chunk */
366
367 mmckList.fccType = listtypeAVIMOVIE;
368 if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
369 WARN("Can't find 'movi' list\n");
370 return FALSE;
371 }
372
375 wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
376 if (!wma->lpVideoIndex) {
377 WARN("Can't alloc video index array\n");
378 return FALSE;
379 }
380 wma->dwPlayableAudioBlocks = 0;
381 wma->lpAudioIndex = NULL;
382
383 alb.numAudioBlocks = alb.numVideoFrames = 0;
384 alb.inVideoSize = alb.inAudioSize = 0;
385 alb.numAudioAllocated = 0;
386
387 while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
388 if (mmckInfo.fccType == listtypeAVIRECORD) {
389 MMCKINFO tmp;
390
391 while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
392 MCIAVI_AddFrame(wma, &tmp, &alb);
393 mmioAscend(wma->hFile, &tmp, 0);
394 }
395 } else {
396 MCIAVI_AddFrame(wma, &mmckInfo, &alb);
397 }
398
399 mmioAscend(wma->hFile, &mmckInfo, 0);
400 }
401
402#ifdef __REACTOS__
403 /* Empty file */
404 if (alb.numVideoFrames == 0) {
405 WARN("NumVideoFrames: %u, Empty or possibly corrupt video file");
406 return FALSE;
407 }
408#endif
409
410 if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
411 WARN("AVI header says %d frames, we found %d video frames, reducing playable frames\n",
414 }
416
418 WARN("inVideoSize=%d suggestedSize=%d\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
420 }
422 WARN("inAudioSize=%d suggestedSize=%d\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
424 }
425
427 if (!wma->indata) {
428 WARN("Can't alloc input buffer\n");
429 return FALSE;
430 }
431
432 return TRUE;
433}
434
436{
437 HDC hDC;
438 DWORD outSize;
439 FOURCC fcc = wma->ash_video.fccHandler;
440
441 TRACE("fcc %4.4s\n", (LPSTR)&fcc);
442
443 wma->dwCachedFrame = -1;
444
445 /* get the right handle */
446 if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
447
448 /* try to get a decompressor for that type */
450 if (!wma->hic) {
451 /* check for builtin DIB compressions */
452 fcc = wma->inbih->biCompression;
453 if ((fcc == mmioFOURCC('D','I','B',' ')) ||
454 (fcc == mmioFOURCC('R','L','E',' ')) ||
455 (fcc == BI_RGB) || (fcc == BI_RLE8) ||
456 (fcc == BI_RLE4) || (fcc == BI_BITFIELDS))
457 goto paint_frame;
458
459 WARN("Can't locate codec for the file\n");
460 return FALSE;
461 }
462
463 outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
464
465 wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
466 if (!wma->outbih) {
467 WARN("Can't alloc output BIH\n");
468 return FALSE;
469 }
470 if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
471 WARN("Can't open decompressor\n");
472 return FALSE;
473 }
474
475 TRACE("bih.biSize=%d\n", wma->outbih->biSize);
476 TRACE("bih.biWidth=%d\n", wma->outbih->biWidth);
477 TRACE("bih.biHeight=%d\n", wma->outbih->biHeight);
478 TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes);
479 TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount);
480 TRACE("bih.biCompression=%x\n", wma->outbih->biCompression);
481 TRACE("bih.biSizeImage=%d\n", wma->outbih->biSizeImage);
482 TRACE("bih.biXPelsPerMeter=%d\n", wma->outbih->biXPelsPerMeter);
483 TRACE("bih.biYPelsPerMeter=%d\n", wma->outbih->biYPelsPerMeter);
484 TRACE("bih.biClrUsed=%d\n", wma->outbih->biClrUsed);
485 TRACE("bih.biClrImportant=%d\n", wma->outbih->biClrImportant);
486
488 if (!wma->outdata) {
489 WARN("Can't alloc output buffer\n");
490 return FALSE;
491 }
492
494 (DWORD_PTR)wma->inbih, (DWORD_PTR)wma->outbih) != ICERR_OK) {
495 WARN("Can't begin decompression\n");
496 return FALSE;
497 }
498
499paint_frame:
500 hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
501 if (hDC)
502 {
504 ReleaseDC(wma->hWndPaint, hDC);
505 }
506 return TRUE;
507}
508
509static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
510 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
511{
512 WINE_MCIAVI *wma = MCIAVI_mciGetOpenDev(dwInstance);
513
514 if (!wma) return;
515
517
518 switch (uMsg) {
519 case WOM_OPEN:
520 case WOM_CLOSE:
521 break;
522 case WOM_DONE:
524 TRACE("Returning waveHdr=%lx\n", dwParam1);
525 SetEvent(wma->hEvent);
526 break;
527 default:
528 ERR("Unknown uMsg=%d\n", uMsg);
529 }
530
532}
533
534DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
535{
536 DWORD dwRet;
537 LPWAVEHDR waveHdr;
538 unsigned i;
539
540 dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
542 if (dwRet != 0) {
543 TRACE("Can't open low level audio device %d\n", dwRet);
544 dwRet = MCIERR_DEVICE_OPEN;
545 wma->hWave = 0;
546 goto cleanUp;
547 }
548
549 /* FIXME: should set up a heuristic to compute the number of wave headers
550 * to be used...
551 */
552 *nHdr = 7;
554 *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize));
555 if (!waveHdr) {
556 TRACE("Can't alloc wave headers\n");
557 dwRet = MCIERR_DEVICE_OPEN;
558 goto cleanUp;
559 }
560
561 for (i = 0; i < *nHdr; i++) {
562 /* other fields are zero:ed on allocation */
563 waveHdr[i].lpData = (char*)waveHdr +
564 *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize;
566 if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) {
567 dwRet = MCIERR_INTERNAL;
568 goto cleanUp;
569 }
570 }
571
572 if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) {
573 FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n");
574 }
575 wma->dwCurrAudioBlock = 0;
576
578 wma->dwEventCount = *nHdr - 1;
579 *pWaveHdr = waveHdr;
580 cleanUp:
581 return dwRet;
582}
583
584void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
585{
586 if (!wma->lpAudioIndex)
587 return;
588 TRACE("%d (ec=%u)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount);
589
590 /* push as many blocks as possible => audio gets priority */
591 while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY &&
593 unsigned whidx = wma->dwCurrAudioBlock % nHdr;
594
595 ResetEvent(wma->hEvent);
596 if (InterlockedDecrement(&wma->dwEventCount) < 0 ||
597 !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset)
598 {
600 break;
601 }
602
603 mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET);
604 mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize);
605
606 waveHdr[whidx].dwFlags &= ~WHDR_DONE;
607 waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize;
608 waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
609 wma->dwCurrAudioBlock++;
610 }
611}
612
614{
615 void* pBitmapData;
616 LPBITMAPINFO pBitmapInfo;
617
618 if (!hDC || !wma->inbih)
619 return 0;
620
621 TRACE("Painting frame %u (cached %u)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame);
622
623 if (wma->dwCurrVideoFrame != wma->dwCachedFrame)
624 {
625#ifdef __REACTOS__
626 if (wma->dwCurrVideoFrame >= wma->dwPlayableVideoFrames) {
627 ERR("Invalid frame requested. Current : %u Total Playable %u\n", wma->dwCurrVideoFrame, wma->dwPlayableVideoFrames);
628 return 0;
629 }
630#endif
631
632 if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
633 return 0;
634
635 if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize)
636 {
637 mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
638 mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
639
640 wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
641
642 if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
643 wma->outbih, wma->outdata) != ICERR_OK)
644 {
645 WARN("Decompression error\n");
646 return 0;
647 }
648 }
649
651 }
652
653 if (wma->hic) {
654 pBitmapData = wma->outdata;
655 pBitmapInfo = (LPBITMAPINFO)wma->outbih;
656 } else {
657 pBitmapData = wma->indata;
658 pBitmapInfo = (LPBITMAPINFO)wma->inbih;
659 }
660
662 wma->dest.left, wma->dest.top,
663 wma->dest.right - wma->dest.left, wma->dest.bottom - wma->dest.top,
664 wma->source.left, wma->source.top,
665 wma->source.right - wma->source.left, wma->source.bottom - wma->source.top,
666 pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
667
668 return (wma->ash_video.dwScale / (double)wma->ash_video.dwRate) * 1000000;
669}
static HDC hDC
Definition: 3dtext.c:33
#define isxdigit(c)
Definition: acclib.h:70
int tolower(int c)
Definition: utclib.c:902
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define streamtypeAUDIO
Definition: aviriff.h:93
#define streamtypeVIDEO
Definition: aviriff.h:92
#define ckidSTREAMHEADER
Definition: aviriff.h:88
#define ckidSTREAMFORMAT
Definition: aviriff.h:125
#define TWOCCFromFOURCC(fcc)
Definition: avisplit.c:49
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define CALLBACK
Definition: compat.h:35
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
Definition: mmio.c:1205
LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Definition: mmio.c:836
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO *lpckParent, UINT uFlags)
Definition: mmio.c:1107
LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Definition: mmio.c:733
DWORD FOURCC
Definition: dmdls.h:25
#define BI_RLE4
Definition: precomp.h:57
#define BI_RGB
Definition: precomp.h:56
ULONG RGBQUAD
Definition: precomp.h:59
void cleanUp()
Definition: main.cpp:469
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define SEEK_SET
Definition: jmemansi.c:26
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
if(dx< 0)
Definition: linetemp.h:194
WINE_MCIAVI * MCIAVI_mciGetOpenDev(UINT wDevID)
Definition: mciavi.c:157
void MCIAVI_PlayAudioBlocks(WINE_MCIAVI *wma, unsigned nHdr, LPWAVEHDR waveHdr)
Definition: mmoutput.c:584
static BOOL MCIAVI_AddFrame(WINE_MCIAVI *wma, LPMMCKINFO mmck, struct AviListBuild *alb)
Definition: mmoutput.c:157
static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
Definition: mmoutput.c:509
DWORD MCIAVI_OpenAudio(WINE_MCIAVI *wma, unsigned *nHdr, LPWAVEHDR *pWaveHdr)
Definition: mmoutput.c:534
static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI *wma, const MMCKINFO *mmckList, MMCKINFO *mmckStream)
Definition: mmoutput.c:27
static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI *wma, const MMCKINFO *mmckList, MMCKINFO *mmckStream)
Definition: mmoutput.c:88
double MCIAVI_PaintFrame(WINE_MCIAVI *wma, HDC hDC)
Definition: mmoutput.c:613
BOOL MCIAVI_GetInfo(WINE_MCIAVI *wma)
Definition: mmoutput.c:255
BOOL MCIAVI_OpenVideo(WINE_MCIAVI *wma)
Definition: mmoutput.c:435
#define BI_BITFIELDS
Definition: mmreg.h:507
#define ICTYPE_VIDEO
Definition: mmreg.h:531
#define WOM_DONE
Definition: mmsystem.h:183
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define WOM_OPEN
Definition: mmsystem.h:181
#define WOM_CLOSE
Definition: mmsystem.h:182
#define MMIO_FINDCHUNK
Definition: mmsystem.h:551
#define WAVE_MAPPER
Definition: mmsystem.h:187
#define MCIERR_DEVICE_OPEN
Definition: mmsystem.h:575
#define MCIERR_INTERNAL
Definition: mmsystem.h:587
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define MCI_MODE_STOP
Definition: mmsystem.h:695
#define CALLBACK_FUNCTION
Definition: mmsystem.h:150
#define MCI_MODE_NOT_READY
Definition: mmsystem.h:694
#define MMIO_FINDLIST
Definition: mmsystem.h:553
static HDC
Definition: imagelist.c:92
DWORD VFWAPIV ICDecompress(HIC hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
Definition: msvideo_main.c:827
LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2)
HIC VFWAPI ICLocate(DWORD type, DWORD handler, BITMAPINFOHEADER *in, BITMAPINFOHEADER *out, WORD mode)
Definition: msvideo_main.c:633
HIC VFWAPI ICGetDisplayFormat(HIC hic, BITMAPINFOHEADER *in, BITMAPINFOHEADER *out, int depth, int width, int height)
Definition: msvideo_main.c:699
unsigned int UINT
Definition: ndis.h:50
#define LOWORD(l)
Definition: pedump.c:82
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwInitialFrames
Definition: vfw.h:964
DWORD dwStart
Definition: vfw.h:967
DWORD dwQuality
Definition: vfw.h:970
WORD wLanguage
Definition: vfw.h:963
DWORD dwSampleSize
Definition: vfw.h:971
FOURCC fccHandler
Definition: vfw.h:960
DWORD dwScale
Definition: vfw.h:965
FOURCC fccType
Definition: vfw.h:959
DWORD dwFlags
Definition: vfw.h:961
struct AVIStreamHeader::@3275 rcFrame
DWORD dwLength
Definition: vfw.h:968
DWORD dwSuggestedBufferSize
Definition: vfw.h:969
DWORD dwRate
Definition: vfw.h:966
WORD wPriority
Definition: vfw.h:962
DWORD numAudioBlocks
Definition: mmoutput.c:152
DWORD inVideoSize
Definition: mmoutput.c:153
DWORD inAudioSize
Definition: mmoutput.c:154
DWORD numAudioAllocated
Definition: mmoutput.c:151
DWORD numVideoFrames
Definition: mmoutput.c:150
LONG biYPelsPerMeter
Definition: amvideo.idl:38
DWORD biCompression
Definition: amvideo.idl:35
DWORD biClrImportant
Definition: amvideo.idl:40
LONG biXPelsPerMeter
Definition: amvideo.idl:37
DWORD biSizeImage
Definition: amvideo.idl:36
MCIDEVICEID wDevID
LPWAVEFORMATEX lpWaveFormat
DWORD audio_stream_n
DWORD dwCurrAudioBlock
LPBITMAPINFOHEADER inbih
CRITICAL_SECTION cs
DWORD dwCurrVideoFrame
DWORD dwCachedFrame
LPVOID outdata
LPBITMAPINFOHEADER outbih
AVIStreamHeader ash_audio
DWORD video_stream_n
struct MMIOPos * lpVideoIndex
DWORD dwPlayableVideoFrames
struct MMIOPos * lpAudioIndex
DWORD dwPlayableAudioBlocks
AVIStreamHeader ash_video
MainAVIHeader mah
FOURCC ckid
Definition: mmsystem.h:1507
DWORD cksize
Definition: mmsystem.h:1508
DWORD dwDataOffset
Definition: mmsystem.h:1510
FOURCC fccType
Definition: mmsystem.h:1509
DWORD dwWidth
Definition: vfw.h:949
DWORD dwSuggestedBufferSize
Definition: vfw.h:948
DWORD dwHeight
Definition: vfw.h:950
DWORD dwPaddingGranularity
Definition: vfw.h:943
DWORD dwStreams
Definition: vfw.h:947
DWORD dwMaxBytesPerSec
Definition: vfw.h:942
DWORD dwInitialFrames
Definition: vfw.h:946
DWORD dwFlags
Definition: vfw.h:944
DWORD dwMicroSecPerFrame
Definition: vfw.h:941
DWORD dwTotalFrames
Definition: vfw.h:945
WORD nBlockAlign
Definition: mmreg.h:82
WORD cbSize
Definition: mmreg.h:84
DWORD nAvgBytesPerSec
Definition: mmreg.h:81
DWORD nSamplesPerSec
Definition: mmreg.h:80
WORD nChannels
Definition: mmreg.h:79
WORD wFormatTag
Definition: mmreg.h:78
WORD wBitsPerSample
Definition: mmreg.h:83
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
DWORD dwBufferLength
Definition: mmsystem.h:1015
DWORD dwFlags
Definition: mmsystem.h:1018
LPSTR lpData
Definition: mmsystem.h:1014
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define HIWORD(l)
Definition: typedefs.h:247
#define listtypeAVIMOVIE
Definition: vfw.h:898
#define ICMODE_DECOMPRESS
Definition: vfw.h:269
#define cktypePALchange
Definition: vfw.h:912
#define listtypeSTREAMHEADER
Definition: vfw.h:892
#define listtypeAVIRECORD
Definition: vfw.h:899
#define ICERR_OK
Definition: vfw.h:50
#define cktypeDIBcompressed
Definition: vfw.h:911
#define listtypeAVIHEADER
Definition: vfw.h:890
#define ckidAVIPADDING
Definition: vfw.h:916
#define cktypeWAVEbytes
Definition: vfw.h:913
#define ICM_DECOMPRESS_BEGIN
Definition: vfw.h:108
#define ckidAVIMAINHDR
Definition: vfw.h:891
#define formtypeAVI
Definition: vfw.h:889
#define cktypeDIBbits
Definition: vfw.h:910
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define DIB_RGB_COLORS
Definition: wingdi.h:367
struct tagBITMAPINFO * LPBITMAPINFO
#define SRCCOPY
Definition: wingdi.h:333
#define BI_RLE8
Definition: wingdi.h:35
int WINAPI StretchDIBits(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ const VOID *, _In_ const BITMAPINFO *, _In_ UINT, _In_ DWORD)
UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2341
MMRESULT WINAPI waveOutOpen(LPHWAVEOUT lphWaveOut, UINT uDeviceID, LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags)
Definition: winmm.c:2246
UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut, WAVEHDR *lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2277
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
HDC WINAPI GetDC(_In_opt_ HWND)
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
char * LPSTR
Definition: xmlstorage.h:182
unsigned char BYTE
Definition: xxhash.c:193