ReactOS  0.4.13-dev-247-g0f29b3f
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 
27 static 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 
88 static 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 
144  wma->dest = wma->source;
145 
146  return TRUE;
147 }
148 
149 struct AviListBuild {
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:
196  case cktypeDIBcompressed:
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  if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
402  WARN("AVI header says %d frames, we found %d video frames, reducing playable frames\n",
405  }
407 
409  WARN("inVideoSize=%d suggestedSize=%d\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
411  }
413  WARN("inAudioSize=%d suggestedSize=%d\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
415  }
416 
418  if (!wma->indata) {
419  WARN("Can't alloc input buffer\n");
420  return FALSE;
421  }
422 
423  return TRUE;
424 }
425 
427 {
428  HDC hDC;
429  DWORD outSize;
430  FOURCC fcc = wma->ash_video.fccHandler;
431 
432  TRACE("fcc %4.4s\n", (LPSTR)&fcc);
433 
434  wma->dwCachedFrame = -1;
435 
436  /* get the right handle */
437  if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
438 
439  /* try to get a decompressor for that type */
440  wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS);
441  if (!wma->hic) {
442  /* check for builtin DIB compressions */
443  fcc = wma->inbih->biCompression;
444  if ((fcc == mmioFOURCC('D','I','B',' ')) ||
445  (fcc == mmioFOURCC('R','L','E',' ')) ||
446  (fcc == BI_RGB) || (fcc == BI_RLE8) ||
447  (fcc == BI_RLE4) || (fcc == BI_BITFIELDS))
448  goto paint_frame;
449 
450  WARN("Can't locate codec for the file\n");
451  return FALSE;
452  }
453 
454  outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
455 
456  wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
457  if (!wma->outbih) {
458  WARN("Can't alloc output BIH\n");
459  return FALSE;
460  }
461  if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
462  WARN("Can't open decompressor\n");
463  return FALSE;
464  }
465 
466  TRACE("bih.biSize=%d\n", wma->outbih->biSize);
467  TRACE("bih.biWidth=%d\n", wma->outbih->biWidth);
468  TRACE("bih.biHeight=%d\n", wma->outbih->biHeight);
469  TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes);
470  TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount);
471  TRACE("bih.biCompression=%x\n", wma->outbih->biCompression);
472  TRACE("bih.biSizeImage=%d\n", wma->outbih->biSizeImage);
473  TRACE("bih.biXPelsPerMeter=%d\n", wma->outbih->biXPelsPerMeter);
474  TRACE("bih.biYPelsPerMeter=%d\n", wma->outbih->biYPelsPerMeter);
475  TRACE("bih.biClrUsed=%d\n", wma->outbih->biClrUsed);
476  TRACE("bih.biClrImportant=%d\n", wma->outbih->biClrImportant);
477 
478  wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage);
479  if (!wma->outdata) {
480  WARN("Can't alloc output buffer\n");
481  return FALSE;
482  }
483 
485  (DWORD_PTR)wma->inbih, (DWORD_PTR)wma->outbih) != ICERR_OK) {
486  WARN("Can't begin decompression\n");
487  return FALSE;
488  }
489 
490 paint_frame:
491  hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
492  if (hDC)
493  {
494  MCIAVI_PaintFrame(wma, hDC);
495  ReleaseDC(wma->hWndPaint, hDC);
496  }
497  return TRUE;
498 }
499 
500 static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
501  DWORD_PTR dwParam1, DWORD_PTR dwParam2)
502 {
503  WINE_MCIAVI *wma = MCIAVI_mciGetOpenDev(dwInstance);
504 
505  if (!wma) return;
506 
507  EnterCriticalSection(&wma->cs);
508 
509  switch (uMsg) {
510  case WOM_OPEN:
511  case WOM_CLOSE:
512  break;
513  case WOM_DONE:
515  TRACE("Returning waveHdr=%lx\n", dwParam1);
516  SetEvent(wma->hEvent);
517  break;
518  default:
519  ERR("Unknown uMsg=%d\n", uMsg);
520  }
521 
522  LeaveCriticalSection(&wma->cs);
523 }
524 
525 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
526 {
527  DWORD dwRet;
528  LPWAVEHDR waveHdr;
529  unsigned i;
530 
531  dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
533  if (dwRet != 0) {
534  TRACE("Can't open low level audio device %d\n", dwRet);
535  dwRet = MCIERR_DEVICE_OPEN;
536  wma->hWave = 0;
537  goto cleanUp;
538  }
539 
540  /* FIXME: should set up a heuristic to compute the number of wave headers
541  * to be used...
542  */
543  *nHdr = 7;
545  *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 
568  wma->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
569  wma->dwEventCount = *nHdr - 1;
570  *pWaveHdr = waveHdr;
571  cleanUp:
572  return dwRet;
573 }
574 
575 void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
576 {
577  if (!wma->lpAudioIndex)
578  return;
579  TRACE("%d (ec=%u)\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 
609  if (!hDC || !wma->inbih)
610  return 0;
611 
612  TRACE("Painting frame %u (cached %u)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame);
613 
614  if (wma->dwCurrVideoFrame != wma->dwCachedFrame)
615  {
616  if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
617  return 0;
618 
619  if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize)
620  {
621  mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
622  mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
623 
624  wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
625 
626  if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
627  wma->outbih, wma->outdata) != ICERR_OK)
628  {
629  WARN("Decompression error\n");
630  return 0;
631  }
632  }
633 
634  wma->dwCachedFrame = wma->dwCurrVideoFrame;
635  }
636 
637  if (wma->hic) {
638  pBitmapData = wma->outdata;
639  pBitmapInfo = (LPBITMAPINFO)wma->outbih;
640  } else {
641  pBitmapData = wma->indata;
642  pBitmapInfo = (LPBITMAPINFO)wma->inbih;
643  }
644 
646  wma->dest.left, wma->dest.top,
647  wma->dest.right - wma->dest.left, wma->dest.bottom - wma->dest.top,
648  wma->source.left, wma->source.top,
649  wma->source.right - wma->source.left, wma->source.bottom - wma->source.top,
650  pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
651 
652  return (wma->ash_video.dwScale / (double)wma->ash_video.dwRate) * 1000000;
653 }
DWORD dwFlags
Definition: vfw.h:944
DWORD dwInitialFrames
Definition: vfw.h:964
#define WOM_DONE
Definition: mmsystem.h:183
DWORD numAudioBlocks
Definition: mmoutput.c:152
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)
#define MCI_MODE_STOP
Definition: mmsystem.h:695
#define TRUE
Definition: types.h:120
#define ckidSTREAMFORMAT
Definition: aviriff.h:125
#define cktypeDIBcompressed
Definition: vfw.h:911
#define listtypeSTREAMHEADER
Definition: vfw.h:892
DWORD biClrImportant
Definition: amvideo.idl:40
#define LOBYTE(W)
Definition: jmemdos.c:487
struct tagBITMAPINFO * LPBITMAPINFO
HDC WINAPI GetDC(_In_opt_ HWND)
#define ckidAVIPADDING
Definition: vfw.h:916
LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD_PTR lParam1, DWORD_PTR lParam2)
DWORD dwInitialFrames
Definition: vfw.h:946
#define listtypeAVIHEADER
Definition: vfw.h:890
LONG biXPelsPerMeter
Definition: amvideo.idl:37
struct tagBITMAPINFOHEADER BITMAPINFOHEADER
DWORD nAvgBytesPerSec
Definition: mmreg.h:81
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
Definition: mmio.c:1204
WORD nChannels
Definition: mmreg.h:79
DWORD dwLength
Definition: vfw.h:968
#define WARN(fmt,...)
Definition: debug.h:111
DWORD dwDataOffset
Definition: mmsystem.h:1510
LPWAVEFORMATEX lpWaveFormat
#define cktypeDIBbits
Definition: vfw.h:910
static HDC
Definition: imagelist.c:92
#define CALLBACK
Definition: compat.h:27
static BOOL MCIAVI_AddFrame(WINE_MCIAVI *wma, LPMMCKINFO mmck, struct AviListBuild *alb)
Definition: mmoutput.c:157
WINE_MCIAVI * wma
Definition: mciavi.c:492
#define HIBYTE(W)
Definition: jmemdos.c:486
LONG top
Definition: windef.h:292
AVIStreamHeader ash_audio
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD dwStart
Definition: vfw.h:967
#define ckidSTREAMHEADER
Definition: aviriff.h:88
LPSTR lpData
Definition: mmsystem.h:1014
LONG left
Definition: windef.h:291
#define ICERR_OK
Definition: vfw.h:50
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
DWORD dwFlags
Definition: vfw.h:961
char * LPSTR
Definition: xmlstorage.h:182
DWORD dwPlayableAudioBlocks
LONG right
Definition: windef.h:293
LONG biYPelsPerMeter
Definition: amvideo.idl:38
#define WOM_OPEN
Definition: mmsystem.h:181
#define BI_BITFIELDS
Definition: mmreg.h:507
LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Definition: mmio.c:835
DWORD dwMicroSecPerFrame
Definition: vfw.h:941
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:597
UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut, WAVEHDR *lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2280
FOURCC fccHandler
Definition: vfw.h:960
static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
Definition: mmoutput.c:500
#define WOM_CLOSE
Definition: mmsystem.h:182
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
DWORD VFWAPIV ICDecompress(HIC hic, DWORD dwFlags, LPBITMAPINFOHEADER lpbiFormat, LPVOID lpData, LPBITMAPINFOHEADER lpbi, LPVOID lpBits)
Definition: msvideo_main.c:854
unsigned int BOOL
Definition: ntddk_ex.h:94
#define TWOCCFromFOURCC(fcc)
Definition: avisplit.c:49
#define CALLBACK_FUNCTION
Definition: mmsystem.h:150
DWORD dwFlags
Definition: mmsystem.h:1018
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define FIXME(fmt,...)
Definition: debug.h:110
DWORD inAudioSize
Definition: mmoutput.c:154
DWORD biCompression
Definition: amvideo.idl:35
AVIStreamHeader ash_video
DWORD dwCachedFrame
smooth NULL
Definition: ftsmooth.c:416
#define MMIO_FINDCHUNK
Definition: mmsystem.h:551
FOURCC fccType
Definition: vfw.h:959
FOURCC fccType
Definition: mmsystem.h:1509
BOOL MCIAVI_GetInfo(WINE_MCIAVI *wma)
Definition: mmoutput.c:255
DWORD dwStreams
Definition: vfw.h:947
HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut, WORD wMode)
Definition: msvideo_main.c:671
DWORD numVideoFrames
Definition: mmoutput.c:150
WORD wPriority
Definition: vfw.h:962
#define SEEK_SET
Definition: jmemansi.c:26
#define TRACE(s)
Definition: solgame.cpp:4
#define WAVE_MAPPER
Definition: mmsystem.h:187
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define ICMODE_DECOMPRESS
Definition: vfw.h:269
DWORD dwSuggestedBufferSize
Definition: vfw.h:969
#define ICTYPE_VIDEO
Definition: mmreg.h:531
LPVOID outdata
DWORD dwCurrVideoFrame
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD biSizeImage
Definition: amvideo.idl:36
#define listtypeAVIRECORD
Definition: vfw.h:899
DWORD cksize
Definition: mmsystem.h:1508
DWORD dwMaxBytesPerSec
Definition: vfw.h:942
UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2344
WINE_DEFAULT_DEBUG_CHANNEL(mciavi)
WORD wFormatTag
Definition: mmreg.h:78
DWORD dwQuality
Definition: vfw.h:970
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define InterlockedDecrement
Definition: armddk.h:52
LPBITMAPINFOHEADER outbih
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
DWORD dwSampleSize
Definition: vfw.h:971
DWORD inVideoSize
Definition: mmoutput.c:153
DWORD dwBufferLength
Definition: mmsystem.h:1015
#define streamtypeAUDIO
Definition: aviriff.h:93
#define MCIERR_INTERNAL
Definition: mmsystem.h:587
unsigned char BYTE
Definition: mem.h:68
DWORD dwTotalFrames
Definition: vfw.h:945
DWORD dwCurrAudioBlock
uint32_t DWORD_PTR
Definition: typedefs.h:63
DWORD dwSuggestedBufferSize
Definition: vfw.h:948
#define ICM_DECOMPRESS_BEGIN
Definition: vfw.h:108
MainAVIHeader mah
DWORD FOURCC
Definition: dmdls.h:25
HIC VFWAPI ICGetDisplayFormat(HIC hic, BITMAPINFOHEADER *in, BITMAPINFOHEADER *out, int depth, int width, int height)
Definition: msvideo_main.c:726
struct MMIOPos * lpVideoIndex
#define streamtypeVIDEO
Definition: aviriff.h:92
struct AVIStreamHeader::@3128 rcFrame
#define ERR(fmt,...)
Definition: debug.h:109
WINE_MCIAVI * MCIAVI_mciGetOpenDev(UINT wDevID)
Definition: mciavi.c:158
MCIDEVICEID wDevID
static HDC hDC
Definition: 3dtext.c:33
LPBITMAPINFOHEADER inbih
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
DWORD audio_stream_n
BOOL MCIAVI_OpenVideo(WINE_MCIAVI *wma)
Definition: mmoutput.c:426
#define InterlockedIncrement
Definition: armddk.h:53
#define MCI_MODE_NOT_READY
Definition: mmsystem.h:694
MMRESULT WINAPI waveOutOpen(LPHWAVEOUT lphWaveOut, UINT uDeviceID, LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags)
Definition: winmm.c:2249
FOURCC ckid
Definition: mmsystem.h:1507
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO *lpckParent, UINT uFlags)
Definition: mmio.c:1106
#define formtypeAVI
Definition: vfw.h:889
#define HeapReAlloc
Definition: compat.h:393
WORD cbSize
Definition: mmreg.h:84
#define listtypeAVIMOVIE
Definition: vfw.h:898
DWORD dwWidth
Definition: vfw.h:949
DWORD dwScale
Definition: vfw.h:965
unsigned int UINT
Definition: ndis.h:50
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define BI_RLE4
Definition: precomp.h:36
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:660
#define isxdigit(c)
Definition: acclib.h:70
DWORD nSamplesPerSec
Definition: mmreg.h:80
CRITICAL_SECTION cs
WORD nBlockAlign
Definition: mmreg.h:82
#define ckidAVIMAINHDR
Definition: vfw.h:891
DWORD dwPlayableVideoFrames
WORD wBitsPerSample
Definition: mmreg.h:83
#define HIWORD(l)
Definition: typedefs.h:246
#define WHDR_DONE
Definition: mmsystem.h:193
#define MCIERR_DEVICE_OPEN
Definition: mmsystem.h:575
LONG bottom
Definition: windef.h:294
struct MMIOPos * lpAudioIndex
DWORD video_stream_n
DWORD dwPaddingGranularity
Definition: vfw.h:943
#define MMIO_FINDLIST
Definition: mmsystem.h:553
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
GLfloat GLfloat p
Definition: glext.h:8902
#define DIB_RGB_COLORS
Definition: wingdi.h:366
void cleanUp()
Definition: main.cpp:472
#define BI_RLE8
Definition: wingdi.h:35
int tolower(int c)
Definition: utclib.c:902
DWORD dwHeight
Definition: vfw.h:950
WORD wLanguage
Definition: vfw.h:963
#define BI_RGB
Definition: precomp.h:35
#define LOWORD(l)
Definition: pedump.c:82
#define cktypePALchange
Definition: vfw.h:912
#define SRCCOPY
Definition: wingdi.h:332
void MCIAVI_PlayAudioBlocks(WINE_MCIAVI *wma, unsigned nHdr, LPWAVEHDR waveHdr)
Definition: mmoutput.c:575
double MCIAVI_PaintFrame(WINE_MCIAVI *wma, HDC hDC)
Definition: mmoutput.c:604
static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI *wma, const MMCKINFO *mmckList, MMCKINFO *mmckStream)
Definition: mmoutput.c:27
DWORD dwRate
Definition: vfw.h:966
LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Definition: mmio.c:732
static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI *wma, const MMCKINFO *mmckList, MMCKINFO *mmckStream)
Definition: mmoutput.c:88
DWORD numAudioAllocated
Definition: mmoutput.c:151
#define cktypeWAVEbytes
Definition: vfw.h:913
DWORD MCIAVI_OpenAudio(WINE_MCIAVI *wma, unsigned *nHdr, LPWAVEHDR *pWaveHdr)
Definition: mmoutput.c:525