Hello, This patch allows AVIs with multiple data streams to play correctly. Apparently the same bug exists in avifil32.dll, maintainers, please fix it. Changelog: Dmitry Timoshkov <dmitry@xxxxxxxxxxxxxxx> Decode stream number from AVI frame data and assign the data to appropriate streams. diff -u cvs/hq/wine/dlls/winmm/mciavi/mmoutput.c wine/dlls/winmm/mciavi/mmoutput.c --- cvs/hq/wine/dlls/winmm/mciavi/mmoutput.c 2004-01-01 15:33:54.000000000 +0800 +++ wine/dlls/winmm/mciavi/mmoutput.c 2004-01-04 22:20:14.000000000 +0800 @@ -164,16 +164,41 @@ struct AviListBuild { static BOOL MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck, struct AviListBuild* alb) { + int i; + const BYTE *p; + DWORD stream_n; + if (mmck->ckid == ckidAVIPADDING) return TRUE; + p = (const BYTE *)&mmck->ckid; + stream_n = 0; + + for (i = 0; i < 2; i++) + { + if (!isxdigit(*p) || ((stream_n <<= 4) > 0xff)) + { + WARN("wrongly encoded stream #\n"); + return FALSE; + } + + stream_n |= (*p <= '9') ? (*p - '0') : (tolower(*p) - 'a' + 10); + p++; + } + + TRACE("ckid %4.4s (stream #%ld)\n", (LPSTR)&mmck->ckid, stream_n); + switch (TWOCCFromFOURCC(mmck->ckid)) { case cktypeDIBbits: case cktypeDIBcompressed: case cktypePALchange: + if (stream_n != wma->video_stream_n) + { + TRACE("data belongs to another video stream #%ld\n", stream_n); + return FALSE; + } + TRACE("Adding video frame[%ld]: %ld bytes\n", alb->numVideoFrames, mmck->cksize); - if (!mmck->cksize) - TRACE("got a zero sized frame\n"); if (alb->numVideoFrames < wma->dwPlayableVideoFrames) { wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset; @@ -186,6 +211,12 @@ static BOOL MCIAVI_AddFrame(WINE_MCIAVI* } break; case cktypeWAVEbytes: + if (stream_n != wma->audio_stream_n) + { + TRACE("data belongs to another audio stream #%ld\n", stream_n); + return FALSE; + } + TRACE("Adding audio frame[%ld]: %ld bytes\n", alb->numAudioBlocks, mmck->cksize); if (wma->lpWaveFormat) { @@ -209,7 +240,7 @@ static BOOL MCIAVI_AddFrame(WINE_MCIAVI* } break; default: - WARN("Unknown frame type %04x\n", TWOCCFromFOURCC(mmck->ckid)); + WARN("Unknown frame type %4.4s\n", (LPSTR)&mmck->ckid); break; } return TRUE; @@ -222,6 +253,7 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) MMCKINFO mmckList; MMCKINFO mmckInfo; struct AviListBuild alb; + DWORD stream_n; if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) { WARN("Can't find 'RIFF' chunk\n"); @@ -261,7 +293,10 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) mmioAscend(wma->hFile, &mmckInfo, 0); TRACE("Start of streams\n"); - do + wma->video_stream_n = 0; + wma->audio_stream_n = 0; + + for (stream_n = 0; stream_n < wma->mah.dwStreams; stream_n++) { MMCKINFO mmckStream; @@ -276,25 +311,37 @@ BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma) continue; } - TRACE("Stream fccType %4.4s\n", (LPSTR)&mmckStream.fccType); + TRACE("Stream #%ld fccType %4.4s\n", stream_n, (LPSTR)&mmckStream.fccType); if (mmckStream.fccType == streamtypeVIDEO) { TRACE("found video stream\n"); - if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream)) - return FALSE; + if (wma->inbih) + WARN("ignoring another video stream\n"); + else + { + if (!MCIAVI_GetInfoVideo(wma, &mmckList, &mmckStream)) + return FALSE; + wma->video_stream_n = stream_n; + } } else if (mmckStream.fccType == streamtypeAUDIO) { TRACE("found audio stream\n"); - if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream)) - return FALSE; + if (wma->lpWaveFormat) + WARN("ignoring another audio stream\n"); + else + { + if (!MCIAVI_GetInfoAudio(wma, &mmckList, &mmckStream)) + return FALSE; + wma->audio_stream_n = stream_n; + } } else TRACE("Unsupported stream type %4.4s\n", (LPSTR)&mmckStream.fccType); mmioAscend(wma->hFile, &mmckList, 0); - } while(1); + } TRACE("End of streams\n"); @@ -583,7 +630,8 @@ LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wm TRACE("Drawing frame %lu\n", wma->dwCurrVideoFrame); - if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset) + if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset || + !wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize) return FALSE; mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET); diff -u cvs/hq/wine/dlls/winmm/mciavi/private_mciavi.h wine/dlls/winmm/mciavi/private_mciavi.h --- cvs/hq/wine/dlls/winmm/mciavi/private_mciavi.h 2004-01-01 15:33:54.000000000 +0800 +++ wine/dlls/winmm/mciavi/private_mciavi.h 2004-01-04 21:32:34.000000000 +0800 @@ -51,6 +51,7 @@ typedef struct { DWORD dwSet; /* what's turned on: video & audio l&r */ /* information on the loaded AVI file */ HMMIO hFile; /* mmio file handle open as Element */ + DWORD video_stream_n, audio_stream_n; /* stream #s */ MainAVIHeader mah; AVIStreamHeader ash_video; AVIStreamHeader ash_audio;