- Merge from trunk up to r45543
[reactos.git] / dll / win32 / avifil32 / avifile.c
index b0ef1cb..702ba1c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright 1999 Marcus Meissner
- * Copyright 2002-2003 Michael Günnewig
+ * Copyright 2002-2003 Michael Günnewig
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -217,7 +217,7 @@ static HRESULT AVIFILE_LoadIndex(const IAVIFileImpl *This, DWORD size, DWORD off
 static HRESULT AVIFILE_ParseIndex(const IAVIFileImpl *This, AVIINDEXENTRY *lp,
                                  LONG count, DWORD pos, BOOL *bAbsolute);
 static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD start,
-                                LPVOID buffer, LONG size);
+                                LPVOID buffer, DWORD size);
 static void    AVIFILE_SamplesToBlock(const IAVIStreamImpl *This, LPLONG pos,
                                      LPLONG offset);
 static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This);
@@ -226,7 +226,7 @@ static ULONG   AVIFILE_SearchStream(const IAVIFileImpl *This, DWORD fccType,
                                    LONG lSkip);
 static void    AVIFILE_UpdateInfo(IAVIFileImpl *This);
 static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block,
-                                 FOURCC ckid, DWORD flags, LPVOID buffer,
+                                 FOURCC ckid, DWORD flags, LPCVOID buffer,
                                  LONG size);
 
 HRESULT AVIFILE_CreateAVIFile(REFIID riid, LPVOID *ppv)
@@ -931,7 +931,7 @@ static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream *iface, LONG pos,
 {
   IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
 
-  LPBITMAPINFOHEADER lpbiNew = (LPBITMAPINFOHEADER)format;
+  LPBITMAPINFOHEADER lpbiNew = format;
 
   TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
 
@@ -976,7 +976,7 @@ static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream *iface, LONG pos,
     return AVIERR_OK;
   } else {
     MMCKINFO           ck;
-    LPBITMAPINFOHEADER lpbiOld = (LPBITMAPINFOHEADER)This->lpFormat;
+    LPBITMAPINFOHEADER lpbiOld = This->lpFormat;
     RGBQUAD           *rgbNew  = (RGBQUAD*)((LPBYTE)lpbiNew + lpbiNew->biSize);
     AVIPALCHANGE      *lppc = NULL;
     UINT               n;
@@ -1087,6 +1087,15 @@ static HRESULT WINAPI IAVIStream_fnRead(IAVIStream *iface, LONG start,
     LONG block = start;
     LONG offset = 0;
 
+    if (!buffer)
+    {
+      if (bytesread)
+        *bytesread = samples*This->sInfo.dwSampleSize;
+      if (samplesread)
+        *samplesread = samples;
+      return AVIERR_OK;
+    }
+
     /* convert start sample to block,offset pair */
     AVIFILE_SamplesToBlock(This, &block, &offset);
 
@@ -1094,6 +1103,7 @@ static HRESULT WINAPI IAVIStream_fnRead(IAVIStream *iface, LONG start,
     samples *= This->sInfo.dwSampleSize;
 
     while (samples > 0 && buffersize > 0) {
+      LONG blocksize;
       if (block != This->dwCurrentFrame) {
        hr = AVIFILE_ReadBlock(This, block, NULL, 0);
        if (FAILED(hr))
@@ -1101,7 +1111,9 @@ static HRESULT WINAPI IAVIStream_fnRead(IAVIStream *iface, LONG start,
       }
 
       size = min((DWORD)samples, (DWORD)buffersize);
-      size = min(size, This->cbBuffer - offset);
+      blocksize = This->lpBuffer[1];
+      TRACE("blocksize = %u\n",blocksize);
+      size = min(size, blocksize - offset);
       memcpy(buffer, ((BYTE*)&This->lpBuffer[2]) + offset, size);
 
       block++;
@@ -1362,6 +1374,8 @@ static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream *iface,
 
 static HRESULT AVIFILE_AddFrame(IAVIStreamImpl *This, DWORD ckid, DWORD size, DWORD offset, DWORD flags)
 {
+  UINT n;
+
   /* pre-conditions */
   assert(This != NULL);
 
@@ -1379,31 +1393,32 @@ static HRESULT AVIFILE_AddFrame(IAVIStreamImpl *This, DWORD ckid, DWORD size, DW
       ERR(": found palette change in non-video stream!\n");
       return AVIERR_BADFORMAT;
     }
-    This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
-    This->sInfo.dwFormatChangeCount++;
 
-    if (This->idxFmtChanges == NULL || This->sInfo.dwFormatChangeCount < This->nIdxFmtChanges) {
-      UINT n = This->sInfo.dwFormatChangeCount;
+    if (This->idxFmtChanges == NULL || This->nIdxFmtChanges <= This->sInfo.dwFormatChangeCount) {
+      DWORD new_count = This->nIdxFmtChanges + 16;
+      void *new_buffer;
 
-      This->nIdxFmtChanges += 16;
-      if (This->idxFmtChanges == NULL)
+      if (This->idxFmtChanges == NULL) {
        This->idxFmtChanges =
-         HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->nIdxFmtChanges * sizeof(AVIINDEXENTRY));
-      else
-       This->idxFmtChanges =
-         HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxFmtChanges,
-                          This->nIdxFmtChanges * sizeof(AVIINDEXENTRY));
-      if (This->idxFmtChanges == NULL)
-       return AVIERR_MEMORY;
+          HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(AVIINDEXENTRY));
+        if (!This->idxFmtChanges) return AVIERR_MEMORY;
+      } else {
+        new_buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxFmtChanges,
+                new_count * sizeof(AVIINDEXENTRY));
+        if (!new_buffer) return AVIERR_MEMORY;
+        This->idxFmtChanges = new_buffer;
+      }
+      This->nIdxFmtChanges = new_count;
+    }
 
-      This->idxFmtChanges[n].ckid          = This->lLastFrame;
-      This->idxFmtChanges[n].dwFlags       = 0;
-      This->idxFmtChanges[n].dwChunkOffset = offset;
-      This->idxFmtChanges[n].dwChunkLength = size;
+    This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
+    n = ++This->sInfo.dwFormatChangeCount;
+    This->idxFmtChanges[n].ckid          = This->lLastFrame;
+    This->idxFmtChanges[n].dwFlags       = 0;
+    This->idxFmtChanges[n].dwChunkOffset = offset;
+    This->idxFmtChanges[n].dwChunkLength = size;
 
-      return AVIERR_OK;
-    }
-    break;
+    return AVIERR_OK;
   case cktypeWAVEbytes:
     if (This->paf->fInfo.dwFlags & AVIFILEINFO_TRUSTCKTYPE)
       flags |= AVIIF_KEYFRAME;
@@ -1652,7 +1667,7 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
   This->fInfo.dwCaps                = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE;
   This->fInfo.dwLength              = MainAVIHdr.dwTotalFrames;
   This->fInfo.dwStreams             = MainAVIHdr.dwStreams;
-  This->fInfo.dwSuggestedBufferSize = MainAVIHdr.dwSuggestedBufferSize;
+  This->fInfo.dwSuggestedBufferSize = 0;
   This->fInfo.dwWidth               = MainAVIHdr.dwWidth;
   This->fInfo.dwHeight              = MainAVIHdr.dwHeight;
   LoadStringW(AVIFILE_hModule, IDS_AVIFILETYPE, This->fInfo.szFileType,
@@ -1688,7 +1703,7 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
            return AVIERR_MEMORY;
          pStream->cbHandlerData = ck.cksize;
 
-         if (mmioRead(This->hmmio, (HPSTR)pStream->lpHandlerData, ck.cksize) != ck.cksize)
+          if (mmioRead(This->hmmio, pStream->lpHandlerData, ck.cksize) != ck.cksize)
            return AVIERR_FILEREAD;
          break;
        case ckidSTREAMFORMAT:
@@ -1702,11 +1717,11 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
            return AVIERR_MEMORY;
          pStream->cbFormat = ck.cksize;
 
-         if (mmioRead(This->hmmio, (HPSTR)pStream->lpFormat, ck.cksize) != ck.cksize)
+          if (mmioRead(This->hmmio, pStream->lpFormat, ck.cksize) != ck.cksize)
            return AVIERR_FILEREAD;
 
          if (pStream->sInfo.fccType == streamtypeVIDEO) {
-           LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)pStream->lpFormat;
+            LPBITMAPINFOHEADER lpbi = pStream->lpFormat;
 
            /* some corrections to the video format */
            if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
@@ -1754,8 +1769,7 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
            pStream->sInfo.dwRate                = streamHdr.dwRate;
            pStream->sInfo.dwStart               = streamHdr.dwStart;
            pStream->sInfo.dwLength              = streamHdr.dwLength;
-           pStream->sInfo.dwSuggestedBufferSize =
-             streamHdr.dwSuggestedBufferSize;
+           pStream->sInfo.dwSuggestedBufferSize = 0;
            pStream->sInfo.dwQuality             = streamHdr.dwQuality;
            pStream->sInfo.dwSampleSize          = streamHdr.dwSampleSize;
            pStream->sInfo.rcFrame.left          = streamHdr.rcFrame.left;
@@ -1816,7 +1830,14 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
          if (FAILED(hr))
            return hr;
        };
-
+       if (pStream->lpFormat != NULL && pStream->sInfo.fccType == streamtypeAUDIO)
+       {
+         WAVEFORMATEX *wfx = pStream->lpFormat;          /* wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; could be added */
+         pStream->sInfo.dwSampleSize = wfx->nBlockAlign; /* to deal with corrupt wfx->nBlockAlign but Windows doesn't do this */
+         TRACE("Block size reset to %u, chan=%u bpp=%u\n", wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample);
+         pStream->sInfo.dwScale = 1;
+         pStream->sInfo.dwRate = wfx->nSamplesPerSec;
+       }
        if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
          return AVIERR_FILEREAD;
       }
@@ -1897,6 +1918,13 @@ static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
     }
   }
 
+  for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++)
+  {
+    DWORD sugbuf =  This->ppStreams[nStream]->sInfo.dwSuggestedBufferSize;
+    if (This->fInfo.dwSuggestedBufferSize < sugbuf)
+      This->fInfo.dwSuggestedBufferSize = sugbuf;
+  }
+
   /* find other chunks */
   FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ck, &ckRIFF, 0);
 
@@ -2008,7 +2036,7 @@ static HRESULT AVIFILE_ParseIndex(const IAVIFileImpl *This, AVIINDEXENTRY *lp,
 }
 
 static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD pos,
-                                LPVOID buffer, LONG size)
+                                LPVOID buffer, DWORD size)
 {
   /* pre-conditions */
   assert(This != NULL);
@@ -2027,16 +2055,18 @@ static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD pos,
     size += 2 * sizeof(DWORD);
 
     /* check that buffer is big enough -- don't trust dwSuggestedBufferSize */
-    if (This->lpBuffer == NULL || size < This->cbBuffer) {
+    if (This->lpBuffer == NULL || This->cbBuffer < size) {
       DWORD maxSize = max(size, This->sInfo.dwSuggestedBufferSize);
 
-      if (This->lpBuffer == NULL)
+      if (This->lpBuffer == NULL) {
        This->lpBuffer = HeapAlloc(GetProcessHeap(), 0, maxSize);
-      else
-       This->lpBuffer = HeapReAlloc(GetProcessHeap(), 0, This->lpBuffer, maxSize);
-      if (This->lpBuffer == NULL)
-       return AVIERR_MEMORY;
-      This->cbBuffer = max(size, This->sInfo.dwSuggestedBufferSize);
+        if (!This->lpBuffer) return AVIERR_MEMORY;
+      } else {
+        void *new_buffer = HeapReAlloc(GetProcessHeap(), 0, This->lpBuffer, maxSize);
+        if (!new_buffer) return AVIERR_MEMORY;
+        This->lpBuffer = new_buffer;
+      }
+      This->cbBuffer = maxSize;
     }
 
     /* now read the complete chunk into our buffer */
@@ -2059,7 +2089,7 @@ static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD pos,
   } else {
     if (mmioSeek(This->paf->hmmio, This->idxFrames[pos].dwChunkOffset + 2 * sizeof(DWORD), SEEK_SET) == -1)
       return AVIERR_FILEREAD;
-    if (mmioRead(This->paf->hmmio, (HPSTR)buffer, size) != size)
+    if (mmioRead(This->paf->hmmio, buffer, size) != size)
       return AVIERR_FILEREAD;
   }
 
@@ -2206,7 +2236,7 @@ static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This)
     if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
       return AVIERR_FILEWRITE;
     if (pStream->lpFormat != NULL && ck.cksize > 0) {
-      if (mmioWrite(This->hmmio, (HPSTR)pStream->lpFormat, ck.cksize) != ck.cksize)
+      if (mmioWrite(This->hmmio, pStream->lpFormat, ck.cksize) != ck.cksize)
        return AVIERR_FILEWRITE;
     }
     if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
@@ -2218,7 +2248,7 @@ static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This)
       ck.cksize = pStream->cbHandlerData;
       if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
        return AVIERR_FILEWRITE;
-      if (mmioWrite(This->hmmio, (HPSTR)pStream->lpHandlerData, ck.cksize) != ck.cksize)
+      if (mmioWrite(This->hmmio, pStream->lpHandlerData, ck.cksize) != ck.cksize)
        return AVIERR_FILEWRITE;
       if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
        return AVIERR_FILEWRITE;
@@ -2227,7 +2257,7 @@ static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This)
     /* ... some optional additional extra chunk for this stream ... */
     if (pStream->extra.lp != NULL && pStream->extra.cb > 0) {
       /* the chunk header(s) are already in the structure */
-      if (mmioWrite(This->hmmio, (HPSTR)pStream->extra.lp, pStream->extra.cb) != pStream->extra.cb)
+      if (mmioWrite(This->hmmio, pStream->extra.lp, pStream->extra.cb) != pStream->extra.cb)
        return AVIERR_FILEWRITE;
     }
 
@@ -2302,7 +2332,7 @@ static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This)
   /* write optional extra file chunks */
   if (This->fileextra.lp != NULL && This->fileextra.cb > 0) {
     /* as for the streams, are the chunk header(s) in the structure */
-    if (mmioWrite(This->hmmio, (HPSTR)This->fileextra.lp, This->fileextra.cb) != This->fileextra.cb)
+    if (mmioWrite(This->hmmio, This->fileextra.lp, This->fileextra.cb) != This->fileextra.cb)
       return AVIERR_FILEWRITE;
   }
 
@@ -2543,7 +2573,7 @@ static void    AVIFILE_UpdateInfo(IAVIFileImpl *This)
 }
 
 static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block,
-                                 FOURCC ckid, DWORD flags, LPVOID buffer,
+                                 FOURCC ckid, DWORD flags, LPCVOID buffer,
                                  LONG size)
 {
   MMCKINFO ck;
@@ -2562,7 +2592,7 @@ static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block,
   if (mmioCreateChunk(This->paf->hmmio, &ck, 0) != S_OK)
     return AVIERR_FILEWRITE;
   if (buffer != NULL && size > 0) {
-    if (mmioWrite(This->paf->hmmio, (HPSTR)buffer, size) != size)
+    if (mmioWrite(This->paf->hmmio, buffer, size) != size)
       return AVIERR_FILEWRITE;
   }
   if (mmioAscend(This->paf->hmmio, &ck, 0) != S_OK)