ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mmoutput.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.