Allow AVIs with multiple data streams to play correctly

Dmitry Timoshkov dmitry at baikal.ru
Sun Jan 4 08:36:15 CST 2004


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 at codeweavers.com>
    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;






More information about the wine-patches mailing list