Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmmoutput.c
Go to the documentation of this file.
00001 /* 00002 * Digital video MCI Wine Driver 00003 * 00004 * Copyright 1999, 2000 Eric POUECH 00005 * Copyright 2003 Dmitry Timoshkov 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "private_mciavi.h" 00023 #include "wine/debug.h" 00024 00025 WINE_DEFAULT_DEBUG_CHANNEL(mciavi); 00026 00027 static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO *mmckStream) 00028 { 00029 MMCKINFO mmckInfo; 00030 00031 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccType)), 00032 HIBYTE(LOWORD(wma->ash_audio.fccType)), 00033 LOBYTE(HIWORD(wma->ash_audio.fccType)), 00034 HIBYTE(HIWORD(wma->ash_audio.fccType))); 00035 if (wma->ash_audio.fccHandler) /* not all streams specify a handler */ 00036 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_audio.fccHandler)), 00037 HIBYTE(LOWORD(wma->ash_audio.fccHandler)), 00038 LOBYTE(HIWORD(wma->ash_audio.fccHandler)), 00039 HIBYTE(HIWORD(wma->ash_audio.fccHandler))); 00040 else 00041 TRACE("ash.fccHandler=0, no handler specified\n"); 00042 TRACE("ash.dwFlags=%d\n", wma->ash_audio.dwFlags); 00043 TRACE("ash.wPriority=%d\n", wma->ash_audio.wPriority); 00044 TRACE("ash.wLanguage=%d\n", wma->ash_audio.wLanguage); 00045 TRACE("ash.dwInitialFrames=%d\n", wma->ash_audio.dwInitialFrames); 00046 TRACE("ash.dwScale=%d\n", wma->ash_audio.dwScale); 00047 TRACE("ash.dwRate=%d\n", wma->ash_audio.dwRate); 00048 TRACE("ash.dwStart=%d\n", wma->ash_audio.dwStart); 00049 TRACE("ash.dwLength=%d\n", wma->ash_audio.dwLength); 00050 TRACE("ash.dwSuggestedBufferSize=%d\n", wma->ash_audio.dwSuggestedBufferSize); 00051 TRACE("ash.dwQuality=%d\n", wma->ash_audio.dwQuality); 00052 TRACE("ash.dwSampleSize=%d\n", wma->ash_audio.dwSampleSize); 00053 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left, 00054 wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right); 00055 00056 /* rewind to the start of the stream */ 00057 mmioAscend(wma->hFile, mmckStream, 0); 00058 00059 mmckInfo.ckid = ckidSTREAMFORMAT; 00060 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) { 00061 WARN("Can't find 'strf' chunk\n"); 00062 return FALSE; 00063 } 00064 if (mmckInfo.cksize < sizeof(WAVEFORMAT)) { 00065 WARN("Size of strf chunk (%d) < audio format struct\n", mmckInfo.cksize); 00066 return FALSE; 00067 } 00068 wma->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); 00069 if (!wma->lpWaveFormat) { 00070 WARN("Can't alloc WaveFormat\n"); 00071 return FALSE; 00072 } 00073 00074 mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize); 00075 00076 TRACE("waveFormat.wFormatTag=%d\n", wma->lpWaveFormat->wFormatTag); 00077 TRACE("waveFormat.nChannels=%d\n", wma->lpWaveFormat->nChannels); 00078 TRACE("waveFormat.nSamplesPerSec=%d\n", wma->lpWaveFormat->nSamplesPerSec); 00079 TRACE("waveFormat.nAvgBytesPerSec=%d\n", wma->lpWaveFormat->nAvgBytesPerSec); 00080 TRACE("waveFormat.nBlockAlign=%d\n", wma->lpWaveFormat->nBlockAlign); 00081 TRACE("waveFormat.wBitsPerSample=%d\n", wma->lpWaveFormat->wBitsPerSample); 00082 if (mmckInfo.cksize >= sizeof(WAVEFORMATEX)) 00083 TRACE("waveFormat.cbSize=%d\n", wma->lpWaveFormat->cbSize); 00084 00085 return TRUE; 00086 } 00087 00088 static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList, MMCKINFO* mmckStream) 00089 { 00090 MMCKINFO mmckInfo; 00091 00092 TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccType)), 00093 HIBYTE(LOWORD(wma->ash_video.fccType)), 00094 LOBYTE(HIWORD(wma->ash_video.fccType)), 00095 HIBYTE(HIWORD(wma->ash_video.fccType))); 00096 TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(wma->ash_video.fccHandler)), 00097 HIBYTE(LOWORD(wma->ash_video.fccHandler)), 00098 LOBYTE(HIWORD(wma->ash_video.fccHandler)), 00099 HIBYTE(HIWORD(wma->ash_video.fccHandler))); 00100 TRACE("ash.dwFlags=%d\n", wma->ash_video.dwFlags); 00101 TRACE("ash.wPriority=%d\n", wma->ash_video.wPriority); 00102 TRACE("ash.wLanguage=%d\n", wma->ash_video.wLanguage); 00103 TRACE("ash.dwInitialFrames=%d\n", wma->ash_video.dwInitialFrames); 00104 TRACE("ash.dwScale=%d\n", wma->ash_video.dwScale); 00105 TRACE("ash.dwRate=%d\n", wma->ash_video.dwRate); 00106 TRACE("ash.dwStart=%d\n", wma->ash_video.dwStart); 00107 TRACE("ash.dwLength=%d\n", wma->ash_video.dwLength); 00108 TRACE("ash.dwSuggestedBufferSize=%d\n", wma->ash_video.dwSuggestedBufferSize); 00109 TRACE("ash.dwQuality=%d\n", wma->ash_video.dwQuality); 00110 TRACE("ash.dwSampleSize=%d\n", wma->ash_video.dwSampleSize); 00111 TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left, 00112 wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right); 00113 00114 /* rewind to the start of the stream */ 00115 mmioAscend(wma->hFile, mmckStream, 0); 00116 00117 mmckInfo.ckid = ckidSTREAMFORMAT; 00118 if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) { 00119 WARN("Can't find 'strf' chunk\n"); 00120 return FALSE; 00121 } 00122 00123 wma->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); 00124 if (!wma->inbih) { 00125 WARN("Can't alloc input BIH\n"); 00126 return FALSE; 00127 } 00128 00129 mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize); 00130 00131 TRACE("bih.biSize=%d\n", wma->inbih->biSize); 00132 TRACE("bih.biWidth=%d\n", wma->inbih->biWidth); 00133 TRACE("bih.biHeight=%d\n", wma->inbih->biHeight); 00134 TRACE("bih.biPlanes=%d\n", wma->inbih->biPlanes); 00135 TRACE("bih.biBitCount=%d\n", wma->inbih->biBitCount); 00136 TRACE("bih.biCompression=%x\n", wma->inbih->biCompression); 00137 TRACE("bih.biSizeImage=%d\n", wma->inbih->biSizeImage); 00138 TRACE("bih.biXPelsPerMeter=%d\n", wma->inbih->biXPelsPerMeter); 00139 TRACE("bih.biYPelsPerMeter=%d\n", wma->inbih->biYPelsPerMeter); 00140 TRACE("bih.biClrUsed=%d\n", wma->inbih->biClrUsed); 00141 TRACE("bih.biClrImportant=%d\n", wma->inbih->biClrImportant); 00142 00143 wma->source.left = 0; 00144 wma->source.top = 0; 00145 wma->source.right = wma->inbih->biWidth; 00146 wma->source.bottom = wma->inbih->biHeight; 00147 00148 wma->dest = wma->source; 00149 00150 return TRUE; 00151 } 00152 00153 struct AviListBuild { 00154 DWORD numVideoFrames; 00155 DWORD numAudioAllocated; 00156 DWORD numAudioBlocks; 00157 DWORD inVideoSize; 00158 DWORD inAudioSize; 00159 }; 00160 00161 static BOOL MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck, 00162 struct AviListBuild* alb) 00163 { 00164 const BYTE *p; 00165 DWORD stream_n; 00166 DWORD twocc; 00167 00168 if (mmck->ckid == ckidAVIPADDING) return TRUE; 00169 00170 p = (const BYTE *)&mmck->ckid; 00171 00172 if (!isxdigit(p[0]) || !isxdigit(p[1])) 00173 { 00174 WARN("wrongly encoded stream #\n"); 00175 return FALSE; 00176 } 00177 00178 stream_n = (p[0] <= '9') ? (p[0] - '0') : (tolower(p[0]) - 'a' + 10); 00179 stream_n <<= 4; 00180 stream_n |= (p[1] <= '9') ? (p[1] - '0') : (tolower(p[1]) - 'a' + 10); 00181 00182 TRACE("ckid %4.4s (stream #%d)\n", (LPSTR)&mmck->ckid, stream_n); 00183 00184 /* Some (rare?) AVI files have video streams name XXYY where XX = stream number and YY = TWOCC 00185 * of the last 2 characters of the biCompression member of the BITMAPINFOHEADER structure. 00186 * Ex: fccHandler = IV32 & biCompression = IV32 => stream name = XX32 00187 * fccHandler = MSVC & biCompression = CRAM => stream name = XXAM 00188 * Another possibility is that these TWOCC are simply ignored. 00189 * Default to cktypeDIBcompressed when this case happens. 00190 */ 00191 twocc = TWOCCFromFOURCC(mmck->ckid); 00192 if (twocc == TWOCCFromFOURCC(wma->inbih->biCompression)) 00193 twocc = cktypeDIBcompressed; 00194 00195 switch (twocc) { 00196 case cktypeDIBbits: 00197 case cktypeDIBcompressed: 00198 case cktypePALchange: 00199 if (stream_n != wma->video_stream_n) 00200 { 00201 TRACE("data belongs to another video stream #%d\n", stream_n); 00202 return FALSE; 00203 } 00204 00205 TRACE("Adding video frame[%d]: %d bytes\n", 00206 alb->numVideoFrames, mmck->cksize); 00207 00208 if (alb->numVideoFrames < wma->dwPlayableVideoFrames) { 00209 wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset; 00210 wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize; 00211 if (alb->inVideoSize < mmck->cksize) 00212 alb->inVideoSize = mmck->cksize; 00213 alb->numVideoFrames++; 00214 } else { 00215 WARN("Too many video frames\n"); 00216 } 00217 break; 00218 case cktypeWAVEbytes: 00219 if (stream_n != wma->audio_stream_n) 00220 { 00221 TRACE("data belongs to another audio stream #%d\n", stream_n); 00222 return FALSE; 00223 } 00224 00225 TRACE("Adding audio frame[%d]: %d bytes\n", 00226 alb->numAudioBlocks, mmck->cksize); 00227 if (wma->lpWaveFormat) { 00228 if (alb->numAudioBlocks >= alb->numAudioAllocated) { 00229 alb->numAudioAllocated += 32; 00230 if (!wma->lpAudioIndex) 00231 wma->lpAudioIndex = HeapAlloc(GetProcessHeap(), 0, 00232 alb->numAudioAllocated * sizeof(struct MMIOPos)); 00233 else 00234 wma->lpAudioIndex = HeapReAlloc(GetProcessHeap(), 0, wma->lpAudioIndex, 00235 alb->numAudioAllocated * sizeof(struct MMIOPos)); 00236 if (!wma->lpAudioIndex) return FALSE; 00237 } 00238 wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset; 00239 wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize; 00240 if (alb->inAudioSize < mmck->cksize) 00241 alb->inAudioSize = mmck->cksize; 00242 alb->numAudioBlocks++; 00243 } else { 00244 WARN("Wave chunk without wave format... discarding\n"); 00245 } 00246 break; 00247 default: 00248 WARN("Unknown frame type %4.4s\n", (LPSTR)&mmck->ckid); 00249 break; 00250 } 00251 return TRUE; 00252 } 00253 00254 BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) 00255 { 00256 MMCKINFO ckMainRIFF; 00257 MMCKINFO mmckHead; 00258 MMCKINFO mmckList; 00259 MMCKINFO mmckInfo; 00260 AVIStreamHeader strh; 00261 struct AviListBuild alb; 00262 DWORD stream_n; 00263 00264 if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) { 00265 WARN("Can't find 'RIFF' chunk\n"); 00266 return FALSE; 00267 } 00268 00269 if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) { 00270 WARN("Can't find 'AVI ' chunk\n"); 00271 return FALSE; 00272 } 00273 00274 mmckHead.fccType = listtypeAVIHEADER; 00275 if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) { 00276 WARN("Can't find 'hdrl' list\n"); 00277 return FALSE; 00278 } 00279 00280 mmckInfo.ckid = ckidAVIMAINHDR; 00281 if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) { 00282 WARN("Can't find 'avih' chunk\n"); 00283 return FALSE; 00284 } 00285 00286 mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah)); 00287 00288 TRACE("mah.dwMicroSecPerFrame=%d\n", wma->mah.dwMicroSecPerFrame); 00289 TRACE("mah.dwMaxBytesPerSec=%d\n", wma->mah.dwMaxBytesPerSec); 00290 TRACE("mah.dwPaddingGranularity=%d\n", wma->mah.dwPaddingGranularity); 00291 TRACE("mah.dwFlags=%d\n", wma->mah.dwFlags); 00292 TRACE("mah.dwTotalFrames=%d\n", wma->mah.dwTotalFrames); 00293 TRACE("mah.dwInitialFrames=%d\n", wma->mah.dwInitialFrames); 00294 TRACE("mah.dwStreams=%d\n", wma->mah.dwStreams); 00295 TRACE("mah.dwSuggestedBufferSize=%d\n", wma->mah.dwSuggestedBufferSize); 00296 TRACE("mah.dwWidth=%d\n", wma->mah.dwWidth); 00297 TRACE("mah.dwHeight=%d\n", wma->mah.dwHeight); 00298 00299 mmioAscend(wma->hFile, &mmckInfo, 0); 00300 00301 TRACE("Start of streams\n"); 00302 wma->video_stream_n = 0; 00303 wma->audio_stream_n = 0; 00304 00305 for (stream_n = 0; stream_n < wma->mah.dwStreams; stream_n++) 00306 { 00307 MMCKINFO mmckStream; 00308 00309 mmckList.fccType = listtypeSTREAMHEADER; 00310 if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) 00311 break; 00312 00313 mmckStream.ckid = ckidSTREAMHEADER; 00314 if (mmioDescend(wma->hFile, &mmckStream, &mmckList, MMIO_FINDCHUNK) != 0) 00315 { 00316 WARN("Can't find 'strh' chunk\n"); 00317 continue; 00318 } 00319 00320 mmioRead(wma->hFile, (LPSTR)&strh, sizeof(strh)); 00321 00322 TRACE("Stream #%d fccType %4.4s\n", stream_n, (LPSTR)&strh.fccType); 00323 00324 if (strh.fccType == streamtypeVIDEO) 00325 { 00326 TRACE("found video stream\n"); 00327 if (wma->inbih) 00328 WARN("ignoring another video stream\n"); 00329 else 00330 { 00331 wma->ash_video = strh; 00332 00333 if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream)) 00334 return FALSE; 00335 wma->video_stream_n = stream_n; 00336 wma->dwSet |= 4; 00337 } 00338 } 00339 else if (strh.fccType == streamtypeAUDIO) 00340 { 00341 TRACE("found audio stream\n"); 00342 if (wma->lpWaveFormat) 00343 WARN("ignoring another audio stream\n"); 00344 else 00345 { 00346 wma->ash_audio = strh; 00347 00348 if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream)) 00349 return FALSE; 00350 wma->audio_stream_n = stream_n; 00351 wma->dwSet |= 3; 00352 } 00353 } 00354 else 00355 TRACE("Unsupported stream type %4.4s\n", (LPSTR)&strh.fccType); 00356 00357 mmioAscend(wma->hFile, &mmckList, 0); 00358 } 00359 00360 TRACE("End of streams\n"); 00361 00362 mmioAscend(wma->hFile, &mmckHead, 0); 00363 00364 /* no need to read optional JUNK chunk */ 00365 00366 mmckList.fccType = listtypeAVIMOVIE; 00367 if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) { 00368 WARN("Can't find 'movi' list\n"); 00369 return FALSE; 00370 } 00371 00372 wma->dwPlayableVideoFrames = wma->mah.dwTotalFrames; 00373 wma->lpVideoIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 00374 wma->dwPlayableVideoFrames * sizeof(struct MMIOPos)); 00375 if (!wma->lpVideoIndex) { 00376 WARN("Can't alloc video index array\n"); 00377 return FALSE; 00378 } 00379 wma->dwPlayableAudioBlocks = 0; 00380 wma->lpAudioIndex = NULL; 00381 00382 alb.numAudioBlocks = alb.numVideoFrames = 0; 00383 alb.inVideoSize = alb.inAudioSize = 0; 00384 alb.numAudioAllocated = 0; 00385 00386 while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) { 00387 if (mmckInfo.fccType == listtypeAVIRECORD) { 00388 MMCKINFO tmp; 00389 00390 while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) { 00391 MCIAVI_AddFrame(wma, &tmp, &alb); 00392 mmioAscend(wma->hFile, &tmp, 0); 00393 } 00394 } else { 00395 MCIAVI_AddFrame(wma, &mmckInfo, &alb); 00396 } 00397 00398 mmioAscend(wma->hFile, &mmckInfo, 0); 00399 } 00400 if (alb.numVideoFrames != wma->dwPlayableVideoFrames) { 00401 WARN("Found %d video frames (/%d), reducing playable frames\n", 00402 alb.numVideoFrames, wma->dwPlayableVideoFrames); 00403 wma->dwPlayableVideoFrames = alb.numVideoFrames; 00404 } 00405 wma->dwPlayableAudioBlocks = alb.numAudioBlocks; 00406 00407 if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) { 00408 WARN("inVideoSize=%d suggestedSize=%d\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize); 00409 wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize; 00410 } 00411 if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) { 00412 WARN("inAudioSize=%d suggestedSize=%d\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize); 00413 wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize; 00414 } 00415 00416 wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize); 00417 if (!wma->indata) { 00418 WARN("Can't alloc input buffer\n"); 00419 return FALSE; 00420 } 00421 00422 return TRUE; 00423 } 00424 00425 BOOL MCIAVI_OpenVideo(WINE_MCIAVI* wma) 00426 { 00427 HDC hDC; 00428 DWORD outSize; 00429 FOURCC fcc = wma->ash_video.fccHandler; 00430 00431 TRACE("fcc %4.4s\n", (LPSTR)&fcc); 00432 00433 wma->dwCachedFrame = -1; 00434 00435 /* get the right handle */ 00436 if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C'); 00437 00438 /* try to get a decompressor for that type */ 00439 wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS); 00440 if (!wma->hic) { 00441 /* check for builtin DIB compressions */ 00442 fcc = wma->inbih->biCompression; 00443 if ((fcc == mmioFOURCC('D','I','B',' ')) || 00444 (fcc == mmioFOURCC('R','L','E',' ')) || 00445 (fcc == BI_RGB) || (fcc == BI_RLE8) || 00446 (fcc == BI_RLE4) || (fcc == BI_BITFIELDS)) 00447 goto paint_frame; 00448 00449 WARN("Can't locate codec for the file\n"); 00450 return FALSE; 00451 } 00452 00453 outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD); 00454 00455 wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize); 00456 if (!wma->outbih) { 00457 WARN("Can't alloc output BIH\n"); 00458 return FALSE; 00459 } 00460 if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) { 00461 WARN("Can't open decompressor\n"); 00462 return FALSE; 00463 } 00464 00465 TRACE("bih.biSize=%d\n", wma->outbih->biSize); 00466 TRACE("bih.biWidth=%d\n", wma->outbih->biWidth); 00467 TRACE("bih.biHeight=%d\n", wma->outbih->biHeight); 00468 TRACE("bih.biPlanes=%d\n", wma->outbih->biPlanes); 00469 TRACE("bih.biBitCount=%d\n", wma->outbih->biBitCount); 00470 TRACE("bih.biCompression=%x\n", wma->outbih->biCompression); 00471 TRACE("bih.biSizeImage=%d\n", wma->outbih->biSizeImage); 00472 TRACE("bih.biXPelsPerMeter=%d\n", wma->outbih->biXPelsPerMeter); 00473 TRACE("bih.biYPelsPerMeter=%d\n", wma->outbih->biYPelsPerMeter); 00474 TRACE("bih.biClrUsed=%d\n", wma->outbih->biClrUsed); 00475 TRACE("bih.biClrImportant=%d\n", wma->outbih->biClrImportant); 00476 00477 wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage); 00478 if (!wma->outdata) { 00479 WARN("Can't alloc output buffer\n"); 00480 return FALSE; 00481 } 00482 00483 if (ICSendMessage(wma->hic, ICM_DECOMPRESS_BEGIN, 00484 (DWORD_PTR)wma->inbih, (DWORD_PTR)wma->outbih) != ICERR_OK) { 00485 WARN("Can't begin decompression\n"); 00486 return FALSE; 00487 } 00488 00489 paint_frame: 00490 hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; 00491 if (hDC) 00492 { 00493 MCIAVI_PaintFrame(wma, hDC); 00494 ReleaseDC(wma->hWndPaint, hDC); 00495 } 00496 return TRUE; 00497 } 00498 00499 static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, 00500 DWORD_PTR dwParam1, DWORD_PTR dwParam2) 00501 { 00502 WINE_MCIAVI *wma = MCIAVI_mciGetOpenDev(dwInstance); 00503 00504 if (!wma) return; 00505 00506 EnterCriticalSection(&wma->cs); 00507 00508 switch (uMsg) { 00509 case WOM_OPEN: 00510 case WOM_CLOSE: 00511 break; 00512 case WOM_DONE: 00513 InterlockedIncrement(&wma->dwEventCount); 00514 TRACE("Returning waveHdr=%lx\n", dwParam1); 00515 SetEvent(wma->hEvent); 00516 break; 00517 default: 00518 ERR("Unknown uMsg=%d\n", uMsg); 00519 } 00520 00521 LeaveCriticalSection(&wma->cs); 00522 } 00523 00524 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr) 00525 { 00526 DWORD dwRet; 00527 LPWAVEHDR waveHdr; 00528 unsigned i; 00529 00530 dwRet = waveOutOpen((HWAVEOUT *)&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat, 00531 (DWORD_PTR)MCIAVI_waveCallback, wma->wDevID, CALLBACK_FUNCTION); 00532 if (dwRet != 0) { 00533 TRACE("Can't open low level audio device %d\n", dwRet); 00534 dwRet = MCIERR_DEVICE_OPEN; 00535 wma->hWave = 0; 00536 goto cleanUp; 00537 } 00538 00539 /* FIXME: should set up a heuristic to compute the number of wave headers 00540 * to be used... 00541 */ 00542 *nHdr = 7; 00543 waveHdr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 00544 *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize)); 00545 if (!waveHdr) { 00546 TRACE("Can't alloc wave headers\n"); 00547 dwRet = MCIERR_DEVICE_OPEN; 00548 goto cleanUp; 00549 } 00550 00551 for (i = 0; i < *nHdr; i++) { 00552 /* other fields are zero:ed on allocation */ 00553 waveHdr[i].lpData = (char*)waveHdr + 00554 *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize; 00555 waveHdr[i].dwBufferLength = wma->ash_audio.dwSuggestedBufferSize; 00556 if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) { 00557 dwRet = MCIERR_INTERNAL; 00558 goto cleanUp; 00559 } 00560 } 00561 00562 if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) { 00563 FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n"); 00564 } 00565 wma->dwCurrAudioBlock = 0; 00566 00567 wma->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 00568 wma->dwEventCount = *nHdr - 1; 00569 *pWaveHdr = waveHdr; 00570 cleanUp: 00571 return dwRet; 00572 } 00573 00574 void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr) 00575 { 00576 if (!wma->lpAudioIndex) 00577 return; 00578 TRACE("%d (ec=%u)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount); 00579 00580 /* push as many blocks as possible => audio gets priority */ 00581 while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY && 00582 wma->dwCurrAudioBlock < wma->dwPlayableAudioBlocks) { 00583 unsigned whidx = wma->dwCurrAudioBlock % nHdr; 00584 00585 ResetEvent(wma->hEvent); 00586 if (InterlockedDecrement(&wma->dwEventCount) < 0 || 00587 !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset) 00588 { 00589 InterlockedIncrement(&wma->dwEventCount); 00590 break; 00591 } 00592 00593 mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET); 00594 mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize); 00595 00596 waveHdr[whidx].dwFlags &= ~WHDR_DONE; 00597 waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize; 00598 waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR)); 00599 wma->dwCurrAudioBlock++; 00600 } 00601 } 00602 00603 LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC) 00604 { 00605 void* pBitmapData; 00606 LPBITMAPINFO pBitmapInfo; 00607 00608 if (!hDC || !wma->inbih) 00609 return TRUE; 00610 00611 TRACE("Painting frame %u (cached %u)\n", wma->dwCurrVideoFrame, wma->dwCachedFrame); 00612 00613 if (wma->dwCurrVideoFrame != wma->dwCachedFrame) 00614 { 00615 if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset) 00616 return FALSE; 00617 00618 if (wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize) 00619 { 00620 mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET); 00621 mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize); 00622 00623 wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize; 00624 00625 if (wma->hic && ICDecompress(wma->hic, 0, wma->inbih, wma->indata, 00626 wma->outbih, wma->outdata) != ICERR_OK) 00627 { 00628 WARN("Decompression error\n"); 00629 return FALSE; 00630 } 00631 } 00632 00633 wma->dwCachedFrame = wma->dwCurrVideoFrame; 00634 } 00635 00636 if (wma->hic) { 00637 pBitmapData = wma->outdata; 00638 pBitmapInfo = (LPBITMAPINFO)wma->outbih; 00639 } else { 00640 pBitmapData = wma->indata; 00641 pBitmapInfo = (LPBITMAPINFO)wma->inbih; 00642 } 00643 00644 StretchDIBits(hDC, 00645 wma->dest.left, wma->dest.top, 00646 wma->dest.right - wma->dest.left, wma->dest.bottom - wma->dest.top, 00647 wma->source.left, wma->source.top, 00648 wma->source.right - wma->source.left, wma->source.bottom - wma->source.top, 00649 pBitmapData, pBitmapInfo, DIB_RGB_COLORS, SRCCOPY); 00650 00651 return TRUE; 00652 } Generated on Sat May 26 2012 04:23:13 for ReactOS by
1.7.6.1
|