Allow AVIs with multiple data streams to play correctly

Dmitry Timoshkov dmitry at baikal.ru
Mon Jan 5 07:40:53 CST 2004


Hello,

Alexandre, please use this patch instead of the previous one.
Somehow the old patch got corrupted (white space).


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-05 16:06:09.000000000 +0800
+++ wine/dlls/winmm/mciavi/mmoutput.c	2004-01-05 21:17:37.000000000 +0800
@@ -164,16 +164,37 @@ struct AviListBuild {
 static BOOL	MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck,
 				struct AviListBuild* alb)
 {
+    const BYTE *p;
+    DWORD stream_n;
+
     if (mmck->ckid == ckidAVIPADDING) return TRUE;
 
+    p = (const BYTE *)&mmck->ckid;
+
+    if (!isxdigit(p[0]) || !isxdigit(p[1]))
+    {
+        WARN("wrongly encoded stream #\n");
+        return FALSE;
+    }
+
+    stream_n = (p[0] <= '9') ? (p[0] - '0') : (tolower(p[0]) - 'a' + 10);
+    stream_n <<= 4;
+    stream_n |= (p[1] <= '9') ? (p[1] - '0') : (tolower(p[1]) - 'a' + 10);
+
+    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 +207,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 +236,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 +249,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 +289,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 +307,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 +626,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-05 21:18:08.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