~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/mciavi32/mmoutput.c

Version: ~ [ wine-1.5.31 ] ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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 
 25 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
 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)),
 32                                                 HIBYTE(LOWORD(wma->ash_audio.fccType)),
 33                                                 LOBYTE(HIWORD(wma->ash_audio.fccType)),
 34                                                 HIBYTE(HIWORD(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)),
 37                                                 HIBYTE(LOWORD(wma->ash_audio.fccHandler)),
 38                                                 LOBYTE(HIWORD(wma->ash_audio.fccHandler)),
 39                                                 HIBYTE(HIWORD(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)),
 93                                                 HIBYTE(LOWORD(wma->ash_video.fccType)),
 94                                                 LOBYTE(HIWORD(wma->ash_video.fccType)),
 95                                                 HIBYTE(HIWORD(wma->ash_video.fccType)));
 96     TRACE("ash.fccHandler='%c%c%c%c'\n",        LOBYTE(LOWORD(wma->ash_video.fccHandler)),
 97                                                 HIBYTE(LOWORD(wma->ash_video.fccHandler)),
 98                                                 LOBYTE(HIWORD(wma->ash_video.fccHandler)),
 99                                                 HIBYTE(HIWORD(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     wma->source.left = 0;
144     wma->source.top = 0;
145     wma->source.right = wma->inbih->biWidth;
146     wma->source.bottom = wma->inbih->biHeight;
147 
148     wma->dest = wma->source;
149 
150     return TRUE;
151 }
152 
153 struct AviListBuild {
154     DWORD       numVideoFrames;
155     DWORD       numAudioAllocated;
156     DWORD       numAudioBlocks;
157     DWORD       inVideoSize;
158     DWORD       inAudioSize;
159 };
160 
161 static BOOL     MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck,
162                                 struct AviListBuild* alb)
163 {
164     const BYTE *p;
165     DWORD stream_n;
166     DWORD twocc;
167 
168     if (mmck->ckid == ckidAVIPADDING) return TRUE;
169 
170     p = (const BYTE *)&mmck->ckid;
171 
172     if (!isxdigit(p[0]) || !isxdigit(p[1]))
173     {
174         WARN("wrongly encoded stream #\n");
175         return FALSE;
176     }
177 
178     stream_n = (p[0] <= '9') ? (p[0] - '') : (tolower(p[0]) - 'a' + 10);
179     stream_n <<= 4;
180     stream_n |= (p[1] <= '9') ? (p[1] - '') : (tolower(p[1]) - 'a' + 10);
181 
182     TRACE("ckid %4.4s (stream #%d)\n", (LPSTR)&mmck->ckid, stream_n);
183 
184     /* Some (rare?) AVI files have video streams name XXYY where XX = stream number and YY = TWOCC
185      * of the last 2 characters of the biCompression member of the BITMAPINFOHEADER structure.
186      * Ex: fccHandler = IV32 & biCompression = IV32 => stream name = XX32
187      *     fccHandler = MSVC & biCompression = CRAM => stream name = XXAM
188      * Another possibility is that these TWOCC are simply ignored.
189      * Default to cktypeDIBcompressed when this case happens.
190      */
191     twocc = TWOCCFromFOURCC(mmck->ckid);
192     if (twocc == TWOCCFromFOURCC(wma->inbih->biCompression))
193         twocc = cktypeDIBcompressed;
194     
195     switch (twocc) {
196     case cktypeDIBbits:
197     case cktypeDIBcompressed:
198     case cktypePALchange:
199         if (stream_n != wma->video_stream_n)
200         {
201             TRACE("data belongs to another video stream #%d\n", stream_n);
202             return FALSE;
203         }
204 
205         TRACE("Adding video frame[%d]: %d bytes\n",
206               alb->numVideoFrames, mmck->cksize);
207 
208         if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
209             wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
210             wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
211             if (alb->inVideoSize < mmck->cksize)
212                 alb->inVideoSize = mmck->cksize;
213             alb->numVideoFrames++;
214         } else {
215             WARN("Too many video frames\n");
216         }
217         break;
218     case cktypeWAVEbytes:
219         if (stream_n != wma->audio_stream_n)
220         {
221             TRACE("data belongs to another audio stream #%d\n", stream_n);
222             return FALSE;
223         }
224 
225         TRACE("Adding audio frame[%d]: %d bytes\n",
226               alb->numAudioBlocks, mmck->cksize);
227         if (wma->lpWaveFormat) {
228             if (alb->numAudioBlocks >= alb->numAudioAllocated) {
229                 alb->numAudioAllocated += 32;
230                 if (!wma->lpAudioIndex)
231                     wma->lpAudioIndex = HeapAlloc(GetProcessHeap(), 0,
232                                                   alb->numAudioAllocated * sizeof(struct MMIOPos));
233                 else
234                     wma->lpAudioIndex = HeapReAlloc(GetProcessHeap(), 0, wma->lpAudioIndex,
235                                                     alb->numAudioAllocated * sizeof(struct MMIOPos));
236                 if (!wma->lpAudioIndex) return FALSE;
237             }
238             wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset;
239             wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize;
240             if (alb->inAudioSize < mmck->cksize)
241                 alb->inAudioSize = mmck->cksize;
242             alb->numAudioBlocks++;
243         } else {
244             WARN("Wave chunk without wave format... discarding\n");
245         }
246         break;
247     default:
248         WARN("Unknown frame type %4.4s\n", (LPSTR)&mmck->ckid);
249         break;
250     }
251     return TRUE;
252 }
253 
254 BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
255 {
256     MMCKINFO            ckMainRIFF;
257     MMCKINFO            mmckHead;
258     MMCKINFO            mmckList;
259     MMCKINFO            mmckInfo;
260     AVIStreamHeader strh;
261     struct AviListBuild alb;
262     DWORD stream_n;
263 
264     if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
265         WARN("Can't find 'RIFF' chunk\n");
266         return FALSE;
267     }
268 
269     if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
270         WARN("Can't find 'AVI ' chunk\n");
271         return FALSE;
272     }
273 
274     mmckHead.fccType = listtypeAVIHEADER;
275     if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
276         WARN("Can't find 'hdrl' list\n");
277         return FALSE;
278     }
279 
280     mmckInfo.ckid = ckidAVIMAINHDR;
281     if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
282         WARN("Can't find 'avih' chunk\n");
283         return FALSE;
284     }
285 
286     mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));
287 
288     TRACE("mah.dwMicroSecPerFrame=%d\n",        wma->mah.dwMicroSecPerFrame);
289     TRACE("mah.dwMaxBytesPerSec=%d\n",  wma->mah.dwMaxBytesPerSec);
290     TRACE("mah.dwPaddingGranularity=%d\n",      wma->mah.dwPaddingGranularity);
291     TRACE("mah.dwFlags=%d\n",                   wma->mah.dwFlags);
292     TRACE("mah.dwTotalFrames=%d\n",             wma->mah.dwTotalFrames);
293     TRACE("mah.dwInitialFrames=%d\n",           wma->mah.dwInitialFrames);
294     TRACE("mah.dwStreams=%d\n",                 wma->mah.dwStreams);
295     TRACE("mah.dwSuggestedBufferSize=%d\n",     wma->mah.dwSuggestedBufferSize);
296     TRACE("mah.dwWidth=%d\n",                   wma->mah.dwWidth);
297     TRACE("mah.dwHeight=%d\n",          wma->mah.dwHeight);
298 
299     mmioAscend(wma->hFile, &mmckInfo, 0);
300 
301     TRACE("Start of streams\n");
302     wma->video_stream_n = 0;
303     wma->audio_stream_n = 0;
304 
305     for (stream_n = 0; stream_n < wma->mah.dwStreams; stream_n++)
306     {
307         MMCKINFO mmckStream;
308 
309         mmckList.fccType = listtypeSTREAMHEADER;
310         if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0)
311             break;
312 
313         mmckStream.ckid = ckidSTREAMHEADER;
314         if (mmioDescend(wma->hFile, &mmckStream, &mmckList, MMIO_FINDCHUNK) != 0)
315         {
316             WARN("Can't find 'strh' chunk\n");
317             continue;
318         }
319 
320         mmioRead(wma->hFile, (LPSTR)&strh, sizeof(strh));
321 
322         TRACE("Stream #%d fccType %4.4s\n", stream_n, (LPSTR)&strh.fccType);
323 
324         if (strh.fccType == streamtypeVIDEO)
325         {
326             TRACE("found video stream\n");
327             if (wma->inbih)
328                 WARN("ignoring another video stream\n");
329             else
330             {
331                 wma->ash_video = strh;
332 
333                 if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream))
334                     return FALSE;
335                 wma->video_stream_n = stream_n;
336                 wma->dwSet |= 4;
337             }
338         }
339         else if (strh.fccType == streamtypeAUDIO)
340         {
341             TRACE("found audio stream\n");
342             if (wma->lpWaveFormat)
343                 WARN("ignoring another audio stream\n");
344             else
345             {
346                 wma->ash_audio = strh;
347 
348                 if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream))
349                     return FALSE;
350                 wma->audio_stream_n = stream_n;
351                 wma->dwSet |= 3;
352             }
353         }
354         else
355             TRACE("Unsupported stream type %4.4s\n", (LPSTR)&strh.fccType);
356 
357         mmioAscend(wma->hFile, &mmckList, 0);
358     }
359 
360     TRACE("End of streams\n");
361 
362     mmioAscend(wma->hFile, &mmckHead, 0);
363 
364     /* no need to read optional JUNK chunk */
365 
366     mmckList.fccType = listtypeAVIMOVIE;
367     if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
368         WARN("Can't find 'movi' list\n");
369         return FALSE;
370     }
371 
372     wma->dwPlayableVideoFrames = wma->mah.dwTotalFrames;
373     wma->lpVideoIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
374                                   wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
375     if (!wma->lpVideoIndex) {
376         WARN("Can't alloc video index array\n");
377         return FALSE;
378     }
379     wma->dwPlayableAudioBlocks = 0;
380     wma->lpAudioIndex = NULL;
381 
382     alb.numAudioBlocks = alb.numVideoFrames = 0;
383     alb.inVideoSize = alb.inAudioSize = 0;
384     alb.numAudioAllocated = 0;
385 
386     while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
387         if (mmckInfo.fccType == listtypeAVIRECORD) {
388             MMCKINFO    tmp;
389 
390             while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
391                 MCIAVI_AddFrame(wma, &tmp, &alb);
392                 mmioAscend(wma->hFile, &tmp, 0);
393             }
394         } else {
395             MCIAVI_AddFrame(wma, &mmckInfo, &alb);
396         }
397 
398         mmioAscend(wma->hFile, &mmckInfo, 0);
399     }
400     if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
401         WARN("Found %d video frames (/%d), reducing playable frames\n",
402              alb.numVideoFrames, wma->dwPlayableVideoFrames);
403         wma->dwPlayableVideoFrames = alb.numVideoFrames;
404     }
405     wma->dwPlayableAudioBlocks = alb.numAudioBlocks;
406 
407     if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) {
408         WARN("inVideoSize=%d suggestedSize=%d\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
409         wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize;
410     }
411     if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) {
412         WARN("inAudioSize=%d suggestedSize=%d\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
413         wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize;
414     }
415 
416     wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize);
417     if (!wma->indata) {
418         WARN("Can't alloc input buffer\n");
419         return FALSE;
420     }
421 
422     return TRUE;
423 }
424 
425 BOOL    MCIAVI_OpenVideo(WINE_MCIAVI* wma)
426 {
427     HDC hDC;
428     DWORD       outSize;
429     FOURCC      fcc = wma->ash_video.fccHandler;
430 
431     TRACE("fcc %4.4s\n", (LPSTR)&fcc);
432 
433     wma->dwCachedFrame = -1;
434 
435     /* get the right handle */
436     if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
437 
438     /* try to get a decompressor for that type */
439     wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS);
440     if (!wma->hic) {
441         /* check for builtin DIB compressions */
442         fcc = wma->inbih->biCompression;
443         if ((fcc == mmioFOURCC('D','I','B',' ')) ||
444             (fcc == mmioFOURCC('R','L','E',' ')) ||
445             (fcc == BI_RGB) || (fcc == BI_RLE8) ||
446             (fcc == BI_RLE4) || (fcc == BI_BITFIELDS))
447             goto paint_frame;
448 
449         WARN("Can't locate codec for the file\n");
450         return FALSE;
451     }
452 
453     outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
454 
455     wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
456     if (!wma->outbih) {
457         WARN("Can't alloc output BIH\n");
458         return FALSE;
459     }
460     if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
461         WARN("Can't open decompressor\n");
462         return FALSE;
463     }
464 
465     TRACE("bih.biSize=%d\n",            wma->outbih->biSize);
466     TRACE("bih.biWidth=%d\n",           wma->outbih->biWidth);
467     TRACE("bih.biHeight=%d\n",  wma->outbih->biHeight);
468     TRACE("bih.biPlanes=%d\n",          wma->outbih->biPlanes);
469     TRACE("bih.biBitCount=%d\n",        wma->outbih->biBitCount);
470     TRACE("bih.biCompression=%x\n",     wma->outbih->biCompression);
471     TRACE("bih.biSizeImage=%d\n",       wma->outbih->biSizeImage);
472     TRACE("bih.biXPelsPerMeter=%d\n",   wma->outbih->biXPelsPerMeter);
473     TRACE("bih.biYPelsPerMeter=%d\n",   wma->outbih->biYPelsPerMeter);
474     TRACE("bih.biClrUsed=%d\n",         wma->outbih->biClrUsed);
475     TRACE("bih.biClrImportant=%d\n",    wma->outbih->biClrImportant);
476 
477     wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage);
478     if (!wma->outdata) {
479         WARN("Can't alloc output buffer\n");
480         return FALSE;
481     }
482 
483     if (ICSendMessage(wma->hic, ICM_DECOMPRESS_BEGIN,
484                       (DWORD_PTR)wma->inbih, (DWORD_PTR)wma->outbih) != ICERR_OK) {
485         WARN("Can't begin decompression\n");
486         return FALSE;
487     }
488 
489 paint_frame:
490     hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
491     if (hDC)
492     {
493         MCIAVI_PaintFrame(wma, hDC);
494         ReleaseDC(wma->hWndPaint, hDC);
495     }
496     return TRUE;
497 }
498 
499 static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
500                                         DWORD_PTR dwParam1, DWORD_PTR dwParam2)
501 {
502     WINE_MCIAVI *wma = MCIAVI_mciGetOpenDev(dwInstance);
503 
504     if (!wma) return;
505 
506     EnterCriticalSection(&wma->cs);
507 
508     switch (uMsg) {
509     case WOM_OPEN:
510     case WOM_CLOSE:
511         break;
512     case WOM_DONE:
513         InterlockedIncrement(&wma->dwEventCount);
514         TRACE("Returning waveHdr=%lx\n", dwParam1);
515         SetEvent(wma->hEvent);
516         break;
517     default:
518         ERR("Unknown uMsg=%d\n", uMsg);
519     }
520 
521     LeaveCriticalSection(&wma->cs);
522 }
523 
524 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
525 {
526     DWORD       dwRet;
527     LPWAVEHDR   waveHdr;
528     unsigned    i;
529 
530     dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat,
531                        (DWORD_PTR)MCIAVI_waveCallback, wma->wDevID, CALLBACK_FUNCTION);
532     if (dwRet != 0) {
533         TRACE("Can't open low level audio device %d\n", dwRet);
534         dwRet = MCIERR_DEVICE_OPEN;
535         wma->hWave = 0;
536         goto cleanUp;
537     }
538 
539     /* FIXME: should set up a heuristic to compute the number of wave headers
540      * to be used...
541      */
542     *nHdr = 7;
543     waveHdr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
544                         *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize));
545     if (!waveHdr) {
546         TRACE("Can't alloc wave headers\n");
547         dwRet = MCIERR_DEVICE_OPEN;
548         goto cleanUp;
549     }
550 
551     for (i = 0; i < *nHdr; i++) {
552         /* other fields are zero:ed on allocation */
553         waveHdr[i].lpData = (char*)waveHdr +
554             *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize;
555         waveHdr[i].dwBufferLength = wma->ash_audio.dwSuggestedBufferSize;
556         if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) {
557             dwRet = MCIERR_INTERNAL;
558             goto cleanUp;
559         }
560     }
561 
562     if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) {
563         FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n");
564     }
565     wma->dwCurrAudioBlock = 0;
566 
567     wma->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
568     wma->dwEventCount = *nHdr - 1;
569     *pWaveHdr = waveHdr;
570  cleanUp:
571     return dwRet;
572 }
573 
574 void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
575 {
576     if (!wma->lpAudioIndex) 
577         return;
578     TRACE("%d (ec=%u)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount);
579 
580     /* push as many blocks as possible => audio gets priority */
581     while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY &&
582            wma->dwCurrAudioBlock < wma->dwPlayableAudioBlocks) {
583         unsigned        whidx = wma->dwCurrAudioBlock % nHdr;
584 
585         ResetEvent(wma->hEvent);
586         if (InterlockedDecrement(&wma->dwEventCount) < 0 ||
587             !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset)
588         {
589             InterlockedIncrement(&wma->dwEventCount);
590             break;
591         }
592 
593         mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET);
594         mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize);
595 
596         waveHdr[whidx].dwFlags &= ~WHDR_DONE;
597         waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize;
598         waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
599         wma->dwCurrAudioBlock++;
600     }
601 }
602 
603 LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
604 {
605     void*               pBitmapData;
606     LPBITMAPINFO        pBitmapInfo;
607 
608     if (!hDC || !wma->inbih)
609         return TRUE;
610 
611     TRACE("Painting frame %u (cached %u)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame);
612 
613     if (wma->dwCurrVideoFrame != wma->dwCachedFrame)
614     {
615         if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
616             return FALSE;
617 
618         if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize)
619         {
620             mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
621             mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
622 
623             wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
624 
625             if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata,
626                                          wma->outbih, wma->outdata) != ICERR_OK)
627             {
628                 WARN("Decompression error\n");
629                 return FALSE;
630             }
631         }
632 
633         wma->dwCachedFrame = wma->dwCurrVideoFrame;
634     }
635 
636     if (wma->hic) {
637         pBitmapData = wma->outdata;
638         pBitmapInfo = (LPBITMAPINFO)wma->outbih;
639     } else {
640         pBitmapData = wma->indata;
641         pBitmapInfo = (LPBITMAPINFO)wma->inbih;
642     }
643 
644     StretchDIBits(hDC,
645                   wma->dest.left, wma->dest.top,
646                   wma->dest.right - wma->dest.left, wma->dest.bottom - wma->dest.top,
647                   wma->source.left, wma->source.top,
648                   wma->source.right - wma->source.left, wma->source.bottom - wma->source.top,
649                   pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
650 
651     return TRUE;
652 }
653 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.