ReactOS 0.4.17-dev-806-gffa4164
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=%s\n", debugstr_fourcc(wma->ash_audio.fccType));
32 if (wma->ash_audio.fccHandler) /* not all streams specify a handler */
33 TRACE("ash.fccHandler=%s\n", debugstr_fourcc(wma->ash_audio.fccHandler));
34 else
35 TRACE("ash.fccHandler=0, no handler specified\n");
36 TRACE("ash.dwFlags=%ld\n", wma->ash_audio.dwFlags);
37 TRACE("ash.wPriority=%d\n", wma->ash_audio.wPriority);
38 TRACE("ash.wLanguage=%d\n", wma->ash_audio.wLanguage);
39 TRACE("ash.dwInitialFrames=%ld\n", wma->ash_audio.dwInitialFrames);
40 TRACE("ash.dwScale=%ld\n", wma->ash_audio.dwScale);
41 TRACE("ash.dwRate=%ld\n", wma->ash_audio.dwRate);
42 TRACE("ash.dwStart=%ld\n", wma->ash_audio.dwStart);
43 TRACE("ash.dwLength=%ld\n", wma->ash_audio.dwLength);
44 TRACE("ash.dwSuggestedBufferSize=%ld\n", wma->ash_audio.dwSuggestedBufferSize);
45 TRACE("ash.dwQuality=%ld\n", wma->ash_audio.dwQuality);
46 TRACE("ash.dwSampleSize=%ld\n", wma->ash_audio.dwSampleSize);
47 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left,
48 wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right);
49
50 /* rewind to the start of the stream */
51 mmioAscend(wma->hFile, mmckStream, 0);
52
53 mmckInfo.ckid = ckidSTREAMFORMAT;
54 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
55 WARN("Can't find 'strf' chunk\n");
56 return FALSE;
57 }
58 if (mmckInfo.cksize < sizeof(WAVEFORMAT)) {
59 WARN("Size of strf chunk (%ld) < audio format struct\n", mmckInfo.cksize);
60 return FALSE;
61 }
62 wma->lpWaveFormat = malloc(mmckInfo.cksize);
63 if (!wma->lpWaveFormat) {
64 WARN("Can't alloc WaveFormat\n");
65 return FALSE;
66 }
67
68 mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize);
69
70 TRACE("waveFormat.wFormatTag=%d\n", wma->lpWaveFormat->wFormatTag);
71 TRACE("waveFormat.nChannels=%d\n", wma->lpWaveFormat->nChannels);
72 TRACE("waveFormat.nSamplesPerSec=%ld\n", wma->lpWaveFormat->nSamplesPerSec);
73 TRACE("waveFormat.nAvgBytesPerSec=%ld\n", wma->lpWaveFormat->nAvgBytesPerSec);
74 TRACE("waveFormat.nBlockAlign=%d\n", wma->lpWaveFormat->nBlockAlign);
75 TRACE("waveFormat.wBitsPerSample=%d\n", wma->lpWaveFormat->wBitsPerSample);
76 if (mmckInfo.cksize >= sizeof(WAVEFORMATEX))
77 TRACE("waveFormat.cbSize=%d\n", wma->lpWaveFormat->cbSize);
78
79 return TRUE;
80}
81
82static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO* mmckStream)
83{
84 MMCKINFO mmckInfo;
85
86 TRACE("ash.fccType=%s\n", debugstr_fourcc(wma->ash_video.fccType));
87 TRACE("ash.fccHandler=%s\n", debugstr_fourcc(wma->ash_video.fccHandler));
88 TRACE("ash.dwFlags=%ld\n", wma->ash_video.dwFlags);
89 TRACE("ash.wPriority=%d\n", wma->ash_video.wPriority);
90 TRACE("ash.wLanguage=%d\n", wma->ash_video.wLanguage);
91 TRACE("ash.dwInitialFrames=%ld\n", wma->ash_video.dwInitialFrames);
92 TRACE("ash.dwScale=%ld\n", wma->ash_video.dwScale);
93 TRACE("ash.dwRate=%ld\n", wma->ash_video.dwRate);
94 TRACE("ash.dwStart=%ld\n", wma->ash_video.dwStart);
95 TRACE("ash.dwLength=%ld\n", wma->ash_video.dwLength);
96 TRACE("ash.dwSuggestedBufferSize=%ld\n", wma->ash_video.dwSuggestedBufferSize);
97 TRACE("ash.dwQuality=%ld\n", wma->ash_video.dwQuality);
98 TRACE("ash.dwSampleSize=%ld\n", wma->ash_video.dwSampleSize);
99 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left,
100 wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right);
101
102 /* rewind to the start of the stream */
103 mmioAscend(wma->hFile, mmckStream, 0);
104
105 mmckInfo.ckid = ckidSTREAMFORMAT;
106 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
107 WARN("Can't find 'strf' chunk\n");
108 return FALSE;
109 }
110
111 wma->inbih = malloc(mmckInfo.cksize);
112 if (!wma->inbih) {
113 WARN("Can't alloc input BIH\n");
114 return FALSE;
115 }
116
117 mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize);
118
119 TRACE("bih.biSize=%ld\n", wma->inbih->biSize);
120 TRACE("bih.biWidth=%ld\n", wma->inbih->biWidth);
121 TRACE("bih.biHeight=%ld\n", wma->inbih->biHeight);
122 TRACE("bih.biPlanes=%d\n", wma->inbih->biPlanes);
123 TRACE("bih.biBitCount=%d\n", wma->inbih->biBitCount);
124 TRACE("bih.biCompression=%lx\n", wma->inbih->biCompression);
125 TRACE("bih.biSizeImage=%ld\n", wma->inbih->biSizeImage);
126 TRACE("bih.biXPelsPerMeter=%ld\n", wma->inbih->biXPelsPerMeter);
127 TRACE("bih.biYPelsPerMeter=%ld\n", wma->inbih->biYPelsPerMeter);
128 TRACE("bih.biClrUsed=%ld\n", wma->inbih->biClrUsed);
129 TRACE("bih.biClrImportant=%ld\n", wma->inbih->biClrImportant);
130
131 SetRect(&wma->source, 0, 0, wma->inbih->biWidth, wma->inbih->biHeight);
132 wma->dest = wma->source;
133
134 return TRUE;
135}
136
143};
144
146 struct AviListBuild* alb)
147{
148 const BYTE *p;
149 DWORD stream_n;
150 DWORD twocc;
151
152 if (mmck->ckid == ckidAVIPADDING) return TRUE;
153
154 p = (const BYTE *)&mmck->ckid;
155
156 if (!isxdigit(p[0]) || !isxdigit(p[1]))
157 {
158 WARN("wrongly encoded stream #\n");
159 return FALSE;
160 }
161
162 stream_n = (p[0] <= '9') ? (p[0] - '0') : (tolower(p[0]) - 'a' + 10);
163 stream_n <<= 4;
164 stream_n |= (p[1] <= '9') ? (p[1] - '0') : (tolower(p[1]) - 'a' + 10);
165
166 TRACE("ckid %4.4s (stream #%ld)\n", (LPSTR)&mmck->ckid, stream_n);
167
168 /* Some (rare?) AVI files have video streams name XXYY where XX = stream number and YY = TWOCC
169 * of the last 2 characters of the biCompression member of the BITMAPINFOHEADER structure.
170 * Ex: fccHandler = IV32 & biCompression = IV32 => stream name = XX32
171 * fccHandler = MSVC & biCompression = CRAM => stream name = XXAM
172 * Another possibility is that these TWOCC are simply ignored.
173 * Default to cktypeDIBcompressed when this case happens.
174 */
175 twocc = TWOCCFromFOURCC(mmck->ckid);
176 if (twocc == TWOCCFromFOURCC(wma->inbih->biCompression))
177 twocc = cktypeDIBcompressed;
178 /* Also detect some chunks that seem to be used by Indeo videos where the chunk is named
179 * after the codec. */
180 else if (twocc == LOWORD(wma->ash_video.fccHandler))
181 twocc = cktypeDIBcompressed;
182 switch (twocc) {
183 case cktypeDIBbits:
185 case cktypePALchange:
186 if (stream_n != wma->video_stream_n)
187 {
188 TRACE("data belongs to another video stream #%ld\n", stream_n);
189 return FALSE;
190 }
191
192 TRACE("Adding video frame[%ld]: %ld bytes\n",
193 alb->numVideoFrames, mmck->cksize);
194
195 if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
196 wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
197 wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
198 if (alb->inVideoSize < mmck->cksize)
199 alb->inVideoSize = mmck->cksize;
200 alb->numVideoFrames++;
201 } else {
202 WARN("Too many video frames\n");
203 }
204 break;
205 case cktypeWAVEbytes:
206 if (stream_n != wma->audio_stream_n)
207 {
208 TRACE("data belongs to another audio stream #%ld\n", stream_n);
209 return FALSE;
210 }
211
212 TRACE("Adding audio frame[%ld]: %ld bytes\n",
213 alb->numAudioBlocks, mmck->cksize);
214 if (wma->lpWaveFormat) {
215 if (alb->numAudioBlocks >= alb->numAudioAllocated) {
216 DWORD newsize = alb->numAudioAllocated + 32;
217 struct MMIOPos* newindex;
218
219 newindex = realloc(wma->lpAudioIndex, newsize * sizeof(struct MMIOPos));
220 if (!newindex) return FALSE;
221 alb->numAudioAllocated = newsize;
222 wma->lpAudioIndex = newindex;
223 }
224 wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset;
225 wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize;
226 if (alb->inAudioSize < mmck->cksize)
227 alb->inAudioSize = mmck->cksize;
228 alb->numAudioBlocks++;
229 } else {
230 WARN("Wave chunk without wave format... discarding\n");
231 }
232 break;
233 default:
234 WARN("Unknown frame type %4.4s\n", (LPSTR)&mmck->ckid);
235 break;
236 }
237 return TRUE;
238}
239
241{
242 MMCKINFO ckMainRIFF;
243 MMCKINFO mmckHead;
244 MMCKINFO mmckList;
245 MMCKINFO mmckInfo;
246 AVIStreamHeader strh;
247 struct AviListBuild alb;
248 DWORD stream_n;
249
250 if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
251 WARN("Can't find 'RIFF' chunk\n");
252 return FALSE;
253 }
254
255 if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
256 WARN("Can't find 'AVI ' chunk\n");
257 return FALSE;
258 }
259
260 mmckHead.fccType = listtypeAVIHEADER;
261 if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
262 WARN("Can't find 'hdrl' list\n");
263 return FALSE;
264 }
265
266 mmckInfo.ckid = ckidAVIMAINHDR;
267 if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
268 WARN("Can't find 'avih' chunk\n");
269 return FALSE;
270 }
271
272 mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));
273
274 TRACE("mah.dwMicroSecPerFrame=%ld\n", wma->mah.dwMicroSecPerFrame);
275 TRACE("mah.dwMaxBytesPerSec=%ld\n", wma->mah.dwMaxBytesPerSec);
276 TRACE("mah.dwPaddingGranularity=%ld\n", wma->mah.dwPaddingGranularity);
277 TRACE("mah.dwFlags=%ld\n", wma->mah.dwFlags);
278 TRACE("mah.dwTotalFrames=%ld\n", wma->mah.dwTotalFrames);
279 TRACE("mah.dwInitialFrames=%ld\n", wma->mah.dwInitialFrames);
280 TRACE("mah.dwStreams=%ld\n", wma->mah.dwStreams);
281 TRACE("mah.dwSuggestedBufferSize=%ld\n", wma->mah.dwSuggestedBufferSize);
282 TRACE("mah.dwWidth=%ld\n", wma->mah.dwWidth);
283 TRACE("mah.dwHeight=%ld\n", wma->mah.dwHeight);
284
285 mmioAscend(wma->hFile, &mmckInfo, 0);
286
287 TRACE("Start of streams\n");
288 wma->video_stream_n = 0;
289 wma->audio_stream_n = 0;
290
291 for (stream_n = 0; stream_n < wma->mah.dwStreams; stream_n++)
292 {
293 MMCKINFO mmckStream;
294
295 mmckList.fccType = listtypeSTREAMHEADER;
296 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0)
297 break;
298
299 mmckStream.ckid = ckidSTREAMHEADER;
300 if (mmioDescend(wma->hFile, &mmckStream, &mmckList, MMIO_FINDCHUNK) != 0)
301 {
302 WARN("Can't find 'strh' chunk\n");
303 continue;
304 }
305
306 mmioRead(wma->hFile, (LPSTR)&strh, sizeof(strh));
307
308 TRACE("Stream #%ld fccType %4.4s\n", stream_n, (LPSTR)&strh.fccType);
309
310 if (strh.fccType == streamtypeVIDEO)
311 {
312 TRACE("found video stream\n");
313 if (wma->inbih)
314 WARN("ignoring another video stream\n");
315 else
316 {
317 wma->ash_video = strh;
318
319 if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream))
320 return FALSE;
321 wma->video_stream_n = stream_n;
322 wma->dwSet |= 4;
323 }
324 }
325 else if (strh.fccType == streamtypeAUDIO)
326 {
327 TRACE("found audio stream\n");
328 if (wma->lpWaveFormat)
329 WARN("ignoring another audio stream\n");
330 else
331 {
332 wma->ash_audio = strh;
333
334 if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream))
335 return FALSE;
336 wma->audio_stream_n = stream_n;
337 wma->dwSet |= 3;
338 }
339 }
340 else
341 TRACE("Unsupported stream type %4.4s\n", (LPSTR)&strh.fccType);
342
343 mmioAscend(wma->hFile, &mmckList, 0);
344 }
345
346 TRACE("End of streams\n");
347
348 mmioAscend(wma->hFile, &mmckHead, 0);
349
350 /* no need to read optional JUNK chunk */
351
352 mmckList.fccType = listtypeAVIMOVIE;
353 if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
354 WARN("Can't find 'movi' list\n");
355 return FALSE;
356 }
357
359 wma->lpVideoIndex = calloc(wma->dwPlayableVideoFrames, sizeof(struct MMIOPos));
360 if (!wma->lpVideoIndex) {
361 WARN("Can't alloc video index array\n");
362 return FALSE;
363 }
364 wma->dwPlayableAudioBlocks = 0;
365 wma->lpAudioIndex = NULL;
366
367 alb.numAudioBlocks = alb.numVideoFrames = 0;
368 alb.inVideoSize = alb.inAudioSize = 0;
369 alb.numAudioAllocated = 0;
370
371 while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
372 if (mmckInfo.fccType == listtypeAVIRECORD) {
373 MMCKINFO tmp;
374
375 while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
376 MCIAVI_AddFrame(wma, &tmp, &alb);
377 mmioAscend(wma->hFile, &tmp, 0);
378 }
379 } else {
380 MCIAVI_AddFrame(wma, &mmckInfo, &alb);
381 }
382
383 mmioAscend(wma->hFile, &mmckInfo, 0);
384 }
385
386#ifdef __REACTOS__
387 /* Empty file */
388 if (alb.numVideoFrames == 0) {
389 WARN("NumVideoFrames: %u, Empty or possibly corrupt video file");
390 return FALSE;
391 }
392#endif
393
394 if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
395 WARN("AVI header says %ld frames, we found %ld video frames, reducing playable frames\n",
398 }
400
402 WARN("inVideoSize=%ld suggestedSize=%ld\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
404 }
406 WARN("inAudioSize=%ld suggestedSize=%ld\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
408 }
409
411 if (!wma->indata) {
412 WARN("Can't alloc input buffer\n");
413 return FALSE;
414 }
415
416 return TRUE;
417}
418
420{
421 HDC hDC;
422 DWORD outSize;
423 FOURCC fcc = wma->ash_video.fccHandler;
424
425 TRACE("fcc %4.4s\n", (LPSTR)&fcc);
426
427 wma->dwCachedFrame = -1;
428
429 /* get the right handle */
430 if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
431
432 /* try to get a decompressor for that type */
434 if (!wma->hic) {
435 /* check for builtin DIB compressions */
436 fcc = wma->inbih->biCompression;
437 if ((fcc == mmioFOURCC('D','I','B',' ')) ||
438 (fcc == mmioFOURCC('R','L','E',' ')) ||
439 (fcc == BI_RGB) || (fcc == BI_RLE8) ||
440 (fcc == BI_RLE4) || (fcc == BI_BITFIELDS))
441 goto paint_frame;
442
443 WARN("Can't locate codec for the file\n");
444 return FALSE;
445 }
446
447 outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
448
449 wma->outbih = malloc(outSize);
450 if (!wma->outbih) {
451 WARN("Can't alloc output BIH\n");
452 return FALSE;
453 }
454 if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
455 WARN("Can't open decompressor\n");
456 return FALSE;
457 }
458
459 TRACE("bih.biSize=%ld\n", wma->outbih->biSize);
460 TRACE("bih.biWidth=%ld\n", wma->outbih->biWidth);
461 TRACE("bih.biHeight=%ld\n", wma->outbih->biHeight);
462 TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes);
463 TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount);
464 TRACE("bih.biCompression=%lx\n", wma->outbih->biCompression);
465 TRACE("bih.biSizeImage=%ld\n", wma->outbih->biSizeImage);
466 TRACE("bih.biXPelsPerMeter=%ld\n", wma->outbih->biXPelsPerMeter);
467 TRACE("bih.biYPelsPerMeter=%ld\n", wma->outbih->biYPelsPerMeter);
468 TRACE("bih.biClrUsed=%ld\n", wma->outbih->biClrUsed);
469 TRACE("bih.biClrImportant=%ld\n", wma->outbih->biClrImportant);
470
471 wma->outdata = malloc(wma->outbih->biSizeImage);
472 if (!wma->outdata) {
473 WARN("Can't alloc output buffer\n");
474 return FALSE;
475 }
476
478 (DWORD_PTR)wma->inbih, (DWORD_PTR)wma->outbih) != ICERR_OK) {
479 WARN("Can't begin decompression\n");
480 return FALSE;
481 }
482
483paint_frame:
484 if (!(wma->hdd = DrawDibOpen()))
485 {
486 ERR("DrawDibOpen() failed.\n");
487 free(wma->outdata);
488 wma->outdata = NULL;
489 return FALSE;
490 }
491
492 hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
493 if (hDC)
494 {
496 ReleaseDC(wma->hWndPaint, hDC);
497 }
498 return TRUE;
499}
500
501static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
502 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
503{
504 WINE_MCIAVI *wma = MCIAVI_mciGetOpenDev(dwInstance);
505
506 if (!wma) return;
507
509
510 switch (uMsg) {
511 case WOM_OPEN:
512 case WOM_CLOSE:
513 break;
514 case WOM_DONE:
516 TRACE("Returning waveHdr=%Ix\n", dwParam1);
517 SetEvent(wma->hEvent);
518 break;
519 default:
520 ERR("Unknown uMsg=%d\n", uMsg);
521 }
522
524}
525
526DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
527{
528 DWORD dwRet;
529 LPWAVEHDR waveHdr;
530 unsigned i;
531
532 dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
534 if (dwRet != 0) {
535 TRACE("Can't open low level audio device %ld\n", dwRet);
536 dwRet = MCIERR_DEVICE_OPEN;
537 wma->hWave = 0;
538 goto cleanUp;
539 }
540
541 /* FIXME: should set up a heuristic to compute the number of wave headers
542 * to be used...
543 */
544 *nHdr = 7;
545 waveHdr = calloc(*nHdr, sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize);
546 if (!waveHdr) {
547 TRACE("Can't alloc wave headers\n");
548 dwRet = MCIERR_DEVICE_OPEN;
549 goto cleanUp;
550 }
551
552 for (i = 0; i < *nHdr; i++) {
553 /* other fields are zero:ed on allocation */
554 waveHdr[i].lpData = (char*)waveHdr +
555 *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize;
557 if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) {
558 dwRet = MCIERR_INTERNAL;
559 goto cleanUp;
560 }
561 }
562
563 if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) {
564 FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n");
565 }
566 wma->dwCurrAudioBlock = 0;
567
569 wma->dwEventCount = *nHdr - 1;
570 *pWaveHdr = waveHdr;
571 cleanUp:
572 return dwRet;
573}
574
575void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
576{
577 if (!wma->lpAudioIndex)
578 return;
579 TRACE("%ld (ec=%lu)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount);
580
581 /* push as many blocks as possible => audio gets priority */
582 while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY &&
584 unsigned whidx = wma->dwCurrAudioBlock % nHdr;
585
586 ResetEvent(wma->hEvent);
587 if (InterlockedDecrement(&wma->dwEventCount) < 0 ||
588 !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset)
589 {
591 break;
592 }
593
594 mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET);
595 mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize);
596
597 waveHdr[whidx].dwFlags &= ~WHDR_DONE;
598 waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize;
599 waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
600 wma->dwCurrAudioBlock++;
601 }
602}
603
605{
606 void* pBitmapData;
607 LPBITMAPINFO pBitmapInfo;
608 DWORD frame;
609
610 if (!hDC || !wma->inbih)
611 return 0;
612
614 frame = wma->dwPlayableVideoFrames - 1;
615 else
616 frame = wma->dwCurrVideoFrame;
617
618 TRACE("Painting frame %lu (cached %lu)\n", frame, wma->dwCachedFrame);
619
620 if (frame != wma->dwCachedFrame)
621 {
622#ifdef __REACTOS__
623 if (wma->dwCurrVideoFrame >= wma->dwPlayableVideoFrames) {
624 ERR("Invalid frame requested. Current : %u Total Playable %u\n", wma->dwCurrVideoFrame, wma->dwPlayableVideoFrames);
625 return 0;
626 }
627#endif
628 if (!wma->lpVideoIndex[frame].dwOffset)
629 return 0;
630
631 if (wma->lpVideoIndex[frame].dwSize)
632 {
633 mmioSeek(wma->hFile, wma->lpVideoIndex[frame].dwOffset, SEEK_SET);
634 mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[frame].dwSize);
635
636 wma->inbih->biSizeImage = wma->lpVideoIndex[frame].dwSize;
637
638 if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
639 wma->outbih, wma->outdata) != ICERR_OK)
640 {
641 WARN("Decompression error\n");
642 return 0;
643 }
644 }
645
646 wma->dwCachedFrame = frame;
647 }
648
649 if (wma->hic) {
650 pBitmapData = wma->outdata;
651 pBitmapInfo = (LPBITMAPINFO)wma->outbih;
652 } else {
653 pBitmapData = wma->indata;
654 pBitmapInfo = (LPBITMAPINFO)wma->inbih;
655 }
656
657 DrawDibDraw(wma->hdd, hDC, wma->dest.left, wma->dest.top, wma->dest.right - wma->dest.left, wma->dest.bottom - wma->dest.top,
658 &pBitmapInfo->bmiHeader, pBitmapData,
659 wma->source.left, wma->source.top, wma->source.right - wma->source.left, wma->source.bottom - wma->source.top, 0);
660
661 return (wma->ash_video.dwScale / (double)wma->ash_video.dwRate) * 1000000;
662}
static HDC hDC
Definition: 3dtext.c:33
#define isxdigit(c)
Definition: acclib.h:70
#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: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CALLBACK
Definition: compat.h:35
int CDECL tolower(int c)
Definition: ctype.c:572
BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc, INT xDst, INT yDst, INT dxDst, INT dyDst, LPBITMAPINFOHEADER lpbi, LPVOID lpBits, INT xSrc, INT ySrc, INT dxSrc, INT dySrc, UINT wFlags)
Definition: drawdib.c:308
HDRAWDIB VFWAPI DrawDibOpen(void)
Definition: drawdib.c:80
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:45
ULONG RGBQUAD
Definition: precomp.h:47
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
unsigned int UINT
Definition: sysinfo.c:13
#define SEEK_SET
Definition: jmemansi.c:26
if(dx< 0)
Definition: linetemp.h:194
WINE_MCIAVI * MCIAVI_mciGetOpenDev(UINT wDevID)
Definition: mciavi.c:156
void MCIAVI_PlayAudioBlocks(WINE_MCIAVI *wma, unsigned nHdr, LPWAVEHDR waveHdr)
Definition: mmoutput.c:575
static BOOL MCIAVI_AddFrame(WINE_MCIAVI *wma, LPMMCKINFO mmck, struct AviListBuild *alb)
Definition: mmoutput.c:145
static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
Definition: mmoutput.c:501
DWORD MCIAVI_OpenAudio(WINE_MCIAVI *wma, unsigned *nHdr, LPWAVEHDR *pWaveHdr)
Definition: mmoutput.c:526
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:82
double MCIAVI_PaintFrame(WINE_MCIAVI *wma, HDC hDC)
Definition: mmoutput.c:604
BOOL MCIAVI_GetInfo(WINE_MCIAVI *wma)
Definition: mmoutput.c:240
BOOL MCIAVI_OpenVideo(WINE_MCIAVI *wma)
Definition: mmoutput.c:419
#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:88
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
#define LOWORD(l)
Definition: pedump.c:82
#define calloc
Definition: rosglue.h:14
#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::@3683 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:140
DWORD inVideoSize
Definition: mmoutput.c:141
DWORD inAudioSize
Definition: mmoutput.c:142
DWORD numAudioAllocated
Definition: mmoutput.c:139
DWORD numVideoFrames
Definition: mmoutput.c:138
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
HDRAWDIB hdd
AVIStreamHeader ash_video
MainAVIHeader mah
FOURCC ckid
Definition: mmsystem.h:1509
DWORD cksize
Definition: mmsystem.h:1510
DWORD dwDataOffset
Definition: mmsystem.h:1512
FOURCC fccType
Definition: mmsystem.h:1511
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
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1922
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
DWORD dwBufferLength
Definition: mmsystem.h:1017
DWORD dwFlags
Definition: mmsystem.h:1020
LPSTR lpData
Definition: mmsystem.h:1016
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:650
uint32_t DWORD_PTR
Definition: typedefs.h:65
char * LPSTR
Definition: typedefs.h:51
#define BI_RGB
Definition: uefivid.c:46
#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)
struct tagBITMAPINFO * LPBITMAPINFO
#define BI_RLE8
Definition: wingdi.h:35
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)
unsigned char BYTE
Definition: xxhash.c:193