[AVIFIL32] IAVIEditStream implementation and some bugs. [RESEND]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Alexandre, any reason why this isn't accepted yet?

  Michael

Changelog:
  - first part of a new IAVIEditStream implementation.
  - Fixed/Added some parameter checking.
  - Fixed bug in EditStreamSetInfoW.
  - Fixed bug in avifil32.spec (str instead of wstr).
  - Fixed cosmetic bug in IAVIStreamImpl_fnRelease.
  - Fixed typo.

  Michael

Index: dlls/avifil32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/avifil32/Makefile.in,v
retrieving revision 1.27
diff -d -u -r1.27 Makefile.in
--- dlls/avifil32/Makefile.in	23 Aug 2003 22:54:53 -0000	1.27
+++ dlls/avifil32/Makefile.in	19 Sep 2003 15:52:32 -0000
@@ -16,6 +16,7 @@
 	acmstream.c \
 	api.c \
 	avifile.c \
+	editstream.c \
 	extrachunk.c \
 	factory.c \
 	getframe.c \
Index: dlls/avifil32/api.c
===================================================================
RCS file: /home/wine/wine/dlls/avifil32/api.c,v
retrieving revision 1.23
diff -d -u -r1.23 api.c
--- dlls/avifil32/api.c	5 Sep 2003 23:08:44 -0000	1.23
+++ dlls/avifil32/api.c	19 Sep 2003 15:52:40 -0000
@@ -395,6 +395,9 @@
 {
   TRACE("(%p,%p,%p)\n", pfile, avis, asi);
 
+  if (pfile == NULL)
+    return AVIERR_BADHANDLE;
+
   return IAVIFile_CreateStream(pfile, avis, asi);
 }
 
@@ -2030,7 +2033,7 @@
   IAVIEditStream *pEdit = NULL;
   HRESULT	  hr;
 
-  FIXME("(%p,%p), semi stub!\n", ppEditable, pSource);
+  TRACE("(%p,%p)\n", ppEditable, pSource);
 
   if (ppEditable == NULL)
     return AVIERR_BADPARAM;
@@ -2040,14 +2043,21 @@
   if (pSource != NULL) {
     hr = IAVIStream_QueryInterface(pSource, &IID_IAVIEditStream,
 				   (LPVOID*)&pEdit);
-    if (FAILED(hr) || pEdit == NULL) {
-      /* need own implementation of IAVIEditStream */
+    if (SUCCEEDED(hr) && pEdit != NULL) {
+      hr = IAVIEditStream_Clone(pEdit, ppEditable);
+      IAVIEditStream_Release(pEdit);
 
-      return AVIERR_UNSUPPORTED;
+      return hr;
     }
   }
 
-  hr = IAVIEditStream_Clone(pEdit, ppEditable);
+  /* need own implementation of IAVIEditStream */
+  pEdit = AVIFILE_CreateEditStream(pSource);
+  if (pEdit == NULL)
+    return AVIERR_MEMORY;
+
+  hr = IAVIEditStream_QueryInterface(pEdit, &IID_IAVIStream,
+                                     (LPVOID*)ppEditable);
   IAVIEditStream_Release(pEdit);
 
   return hr;
@@ -2121,13 +2131,13 @@
 
   TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
 
+  if (ppResult != NULL)
+    *ppResult = NULL;
   if (pStream == NULL)
     return AVIERR_BADHANDLE;
-  if (plStart == NULL || plLength == NULL || ppResult == NULL)
+  if (plStart == NULL || plLength == NULL)
     return AVIERR_BADPARAM;
 
-  *ppResult = NULL;
-
   hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
   if (SUCCEEDED(hr) && pEdit != NULL) {
     hr = IAVIEditStream_Cut(pEdit, plStart, plLength, ppResult);
@@ -2182,7 +2192,7 @@
   if ((DWORD)size < sizeof(AVISTREAMINFOA))
     return AVIERR_BADSIZE;
 
-  memcpy(&asiw, asi, sizeof(asi) - sizeof(asi->szName));
+  memcpy(&asiw, asi, sizeof(asiw) - sizeof(asiw.szName));
   MultiByteToWideChar(CP_ACP, 0, asi->szName, -1,
 		      asiw.szName, sizeof(asiw.szName));
 
Index: dlls/avifil32/avifil32.spec
===================================================================
RCS file: /home/wine/wine/dlls/avifil32/avifil32.spec,v
retrieving revision 1.20
diff -d -u -r1.20 avifil32.spec
--- dlls/avifil32/avifil32.spec	23 Aug 2003 22:54:53 -0000	1.20
+++ dlls/avifil32/avifil32.spec	19 Sep 2003 15:52:41 -0000
@@ -15,7 +15,7 @@
 @ stdcall AVIFileInit()
 @ stub    AVIFileOpen
 @ stdcall AVIFileOpenA(ptr str long ptr)
-@ stdcall AVIFileOpenW(ptr str long ptr)
+@ stdcall AVIFileOpenW(ptr wstr long ptr)
 @ stdcall AVIFileReadData(ptr long ptr ptr)
 @ stdcall AVIFileRelease(ptr)
 @ stdcall AVIFileWriteData(ptr long ptr long)
Index: dlls/avifil32/avifile.c
===================================================================
RCS file: /home/wine/wine/dlls/avifil32/avifile.c,v
retrieving revision 1.38
diff -d -u -r1.38 avifile.c
--- dlls/avifil32/avifile.c	5 Sep 2003 23:08:44 -0000	1.38
+++ dlls/avifil32/avifile.c	19 Sep 2003 15:52:51 -0000
@@ -305,8 +305,8 @@
     for (i = 0; i < This->fInfo.dwStreams; i++) {
       if (This->ppStreams[i] != NULL) {
 	if (This->ppStreams[i]->ref != 0) {
-	  ERR(": someone has still a reference to stream %u (%p)!\n",
-	       i, This->ppStreams[i]);
+	  ERR(": someone has still %lu reference to stream %u (%p)!\n",
+	       This->ppStreams[i]->ref, i, This->ppStreams[i]);
 	}
 	AVIFILE_DestructAVIStream(This->ppStreams[i]);
 	LocalFree((HLOCAL)This->ppStreams[i]);
@@ -529,7 +529,7 @@
   if (lParam < 0)
     return AVIERR_BADPARAM;
 
-  /* Habe user write permissions? */
+  /* Have user write permissions? */
   if ((This->uMode & MMIO_RWMODE) == 0)
     return AVIERR_READONLY;
 
@@ -756,10 +756,12 @@
     return 0;
   }
 
+  This->ref--;
+
   if (This->paf != NULL)
     IAVIFile_Release((PAVIFILE)This->paf);
 
-  return --This->ref;
+  return This->ref;
 }
 
 static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
Index: dlls/avifil32/avifile_private.h
===================================================================
RCS file: /home/wine/wine/dlls/avifil32/avifile_private.h,v
retrieving revision 1.8
diff -d -u -r1.8 avifile_private.h
--- dlls/avifil32/avifile_private.h	23 Jun 2003 18:10:06 -0000	1.8
+++ dlls/avifil32/avifile_private.h	19 Sep 2003 15:52:52 -0000
@@ -57,6 +57,7 @@
 DEFINE_AVIGUID(CLSID_ICMStream, 0x00020001, 0, 0);
 DEFINE_AVIGUID(CLSID_WAVFile,   0x00020003, 0, 0);
 DEFINE_AVIGUID(CLSID_ACMStream, 0x0002000F, 0, 0);
+DEFINE_AVIGUID(IID_IEditStreamInternal, 0x0002000A,0,0);
 
 extern HMODULE AVIFILE_hModule;
 
@@ -64,6 +65,7 @@
 extern HRESULT AVIFILE_CreateWAVFile(REFIID riid, LPVOID *ppobj);
 extern HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppobj);
 extern HRESULT AVIFILE_CreateICMStream(REFIID riid, LPVOID *ppobj);
+extern PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream);
 extern PGETFRAME AVIFILE_CreateGetFrame(PAVISTREAM pstream);
 extern PAVIFILE  AVIFILE_CreateAVITempFile(int nStreams,PAVISTREAM *ppStreams);
 
Index: dlls/avifil32/getframe.c
===================================================================
RCS file: /home/wine/wine/dlls/avifil32/getframe.c,v
retrieving revision 1.9
diff -d -u -r1.9 getframe.c
--- dlls/avifil32/getframe.c	9 Sep 2003 19:39:32 -0000	1.9
+++ dlls/avifil32/getframe.c	19 Sep 2003 15:52:54 -0000
@@ -171,7 +171,7 @@
   if (!--(This->ref)) {
     AVIFILE_CloseCompressor(This);
     if (This->pStream != NULL) {
-      AVIStreamRelease(This->pStream);
+      IAVIStream_Release(This->pStream);
       This->pStream = NULL;
     }
 
@@ -191,6 +191,10 @@
 
   TRACE("(%p,%ld)\n", iface, lPos);
 
+  /* We don't want negative start values! -- marks invalid buffer content */
+  if (lPos < 0)
+    return NULL;
+
   /* check state */
   if (This->pStream == NULL)
     return NULL;
@@ -226,17 +230,18 @@
   }
 
   if (lPos != This->lCurrentFrame) {
-    LONG lNext = AVIStreamFindSample(This->pStream, lPos, FIND_KEY|FIND_PREV);
+    LONG lNext = IAVIStream_FindSample(This->pStream,lPos,FIND_KEY|FIND_PREV);
 
     if (lNext == -1)
-      return NULL;
+      return NULL; /* frame doesn't exist */
     if (lNext <= This->lCurrentFrame && This->lCurrentFrame < lPos)
       lNext = This->lCurrentFrame + 1;
 
     for (; lNext <= lPos; lNext++) {
       /* new format for this frame? */
       if (This->bFormatChanges) {
-	AVIStreamReadFormat(This->pStream, lNext, This->lpInFormat, &This->cbInFormat);
+	IAVIStream_ReadFormat(This->pStream, lNext,
+			      This->lpInFormat, &This->cbInFormat);
 	if (This->lpOutFormat != NULL) {
 	  if (This->lpOutFormat->biBitCount <= 8)
 	    ICDecompressGetPalette(This->hic, This->lpInFormat,
@@ -250,17 +255,26 @@
 	/* not enough memory for input buffer? */
 	readBytes = 0;
 	if (FAILED(AVIStreamSampleSize(This->pStream, lNext, &readBytes)))
+	  return NULL; /* bad thing, but bad things will happen */
+	if (readBytes <= 0) {
+	  ERR(": IAVIStream::REad doesn't return needed bytes!\n");
 	  return NULL;
+	}
+
+	/* IAVIStream::Read failed because of other reasons not buffersize? */
 	if (This->cbInBuffer >= readBytes)
 	  break;
-	This->lpInFormat = GlobalReAllocPtr(This->lpInFormat, This->cbInFormat + readBytes, 0);
+	This->cbInBuffer = This->cbInFormat + readBytes;
+	This->lpInFormat = GlobalReAllocPtr(This->lpInFormat, This->cbInBuffer, 0);
 	if (This->lpInFormat == NULL)
-	  return NULL;
+	  return NULL; /* out of memory */
 	This->lpInBuffer = (BYTE*)This->lpInFormat + This->cbInFormat;
       }
 
-      if (readSamples != 1)
+      if (readSamples != 1) {
+	ERR(": no frames read\n");
 	return NULL;
+      }
       if (readBytes != 0) {
 	This->lpInFormat->biSizeImage = readBytes;
 
@@ -349,7 +363,8 @@
     if (This->cbInBuffer == 0)
       This->cbInBuffer = 1024;
 
-    AVIStreamFormatSize(This->pStream, sInfo.dwStart, &This->cbInFormat);
+    IAVIStream_ReadFormat(This->pStream, sInfo.dwStart,
+			  NULL, &This->cbInFormat);
 
     This->lpInFormat =
       (LPBITMAPINFOHEADER)GlobalAllocPtr(GHND, This->cbInFormat + This->cbInBuffer);
@@ -358,8 +373,9 @@
       return AVIERR_MEMORY;
     }
 
-    hr = AVIStreamReadFormat(This->pStream, sInfo.dwStart, This->lpInFormat, &This->cbInFormat);
+    hr = IAVIStream_ReadFormat(This->pStream, sInfo.dwStart,
+			       This->lpInFormat, &This->cbInFormat);
     if (FAILED(hr)) {
       AVIFILE_CloseCompressor(This);
       return hr;
--- /dev/null	2002-09-09 22:24:09.000000000 +0200
+++ dlls/avifil32/editstream.c	2003-09-19 09:58:45.000000000 +0200
@@ -0,0 +1,1037 @@
+/*
+ * Copyright 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define COM_NO_WINDOWS_H
+#include <assert.h>
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "winnls.h"
+#include "winerror.h"
+#include "windowsx.h"
+#include "mmsystem.h"
+#include "vfw.h"
+
+#include "avifile_private.h"
+#include "extrachunk.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(avifile);
+
+/***********************************************************************/
+
+/* internal interface to get access to table of stream in an editable stream */
+typedef struct IEditStreamInternal IEditStreamInternal;
+
+typedef struct _EditStreamTable {
+  PAVISTREAM pStream;  /* stream which contains the data */
+  DWORD      dwStart;  /* where starts the part which is also our */
+  DWORD      dwLength; /* how many is also in this stream */
+} EditStreamTable;
+
+#define INTERFACE IEditStreamInternal
+#define IEditStreamInternal_METHODS \
+    IUnknown_METHODS \
+    STDMETHOD(GetEditStreamImpl)(THIS_ LPVOID*) PURE;
+ICOM_DEFINE(IEditStreamInternal, IUnknown)
+#undef INTERFACE
+
+#define EditStreamEnd(This,streamNr) ((This)->pStreams[streamNr].dwStart + \
+                                      (This)->pStreams[streamNr].dwLength)
+
+/***********************************************************************/
+
+static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj);
+static ULONG   WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface);
+static ULONG   WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface);
+static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
+                                           LONG*plLength,PAVISTREAM*ppResult);
+static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart,
+                                            LONG*plLength,PAVISTREAM*ppResult);
+static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart,
+                                             LONG*plLength,PAVISTREAM pSource,
+                                             LONG lStart,LONG lEnd);
+static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
+                                             PAVISTREAM*ppResult);
+static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface,
+                                               LPAVISTREAMINFOW asi,LONG size);
+
+struct ICOM_VTABLE(IAVIEditStream) ieditstream = {
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  IAVIEditStream_fnQueryInterface,
+  IAVIEditStream_fnAddRef,
+  IAVIEditStream_fnRelease,
+  IAVIEditStream_fnCut,
+  IAVIEditStream_fnCopy,
+  IAVIEditStream_fnPaste,
+  IAVIEditStream_fnClone,
+  IAVIEditStream_fnSetInfo
+};
+
+static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,REFIID refiid,LPVOID*obj);
+static ULONG   WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface);
+static ULONG   WINAPI IEditAVIStream_fnRelease(IAVIStream*iface);
+static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,LPARAM lParam1,LPARAM lParam2);
+static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,AVISTREAMINFOW *psi,LONG size);
+static LONG    WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos,
+                                                  LONG flags);
+static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG*formatsize);
+static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,LPVOID format,LONG formatsize);
+static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start,
+                                            LONG samples,LPVOID buffer,
+                                            LONG buffersize,LONG*bytesread,
+                                            LONG*samplesread);
+static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start,
+                                             LONG samples,LPVOID buffer,
+                                             LONG buffersize,DWORD flags,
+                                             LONG*sampwritten,LONG*byteswritten);
+static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,LONG samples);
+static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,
+                                                LPVOID lp,LONG *lpread);
+static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,
+                                                 LPVOID lp,LONG size);
+static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,AVISTREAMINFOW*info,LONG infolen);
+
+struct ICOM_VTABLE(IAVIStream) ieditstast = {
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  IEditAVIStream_fnQueryInterface,
+  IEditAVIStream_fnAddRef,
+  IEditAVIStream_fnRelease,
+  IEditAVIStream_fnCreate,
+  IEditAVIStream_fnInfo,
+  IEditAVIStream_fnFindSample,
+  IEditAVIStream_fnReadFormat,
+  IEditAVIStream_fnSetFormat,
+  IEditAVIStream_fnRead,
+  IEditAVIStream_fnWrite,
+  IEditAVIStream_fnDelete,
+  IEditAVIStream_fnReadData,
+  IEditAVIStream_fnWriteData,
+  IEditAVIStream_fnSetInfo
+};
+
+static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj);
+static ULONG   WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface);
+static ULONG   WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface);
+static HRESULT WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl);
+
+struct ICOM_VTABLE(IEditStreamInternal) ieditstreaminternal = {
+  ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
+  IEditStreamInternal_fnQueryInterface,
+  IEditStreamInternal_fnAddRef,
+  IEditStreamInternal_fnRelease,
+  IEditStreamInternal_fnGetEditStreamImpl
+};
+
+typedef struct _IAVIEditStreamImpl IAVIEditStreamImpl;
+
+typedef struct _IEditAVIStreamImpl {
+  /* IUnknown stuff */
+  ICOM_VFIELD(IAVIStream);
+
+  /* IAVIStream stuff */
+  IAVIEditStreamImpl *pae;
+} IEditAVIStreamImpl;
+
+typedef struct _IEditStreamInternalImpl {
+  /* IUnknown stuff */
+  ICOM_VFIELD(IEditStreamInternal);
+
+  /* IEditStreamInternal stuff */
+  IAVIEditStreamImpl *pae;
+} IEditStreamInternalImpl;
+
+struct _IAVIEditStreamImpl {
+  /* IUnknown stuff */
+  ICOM_VFIELD(IAVIEditStream);
+  DWORD  ref;
+
+  /* IAVIEditStream stuff */
+  IEditAVIStreamImpl      iAVIStream;
+  IEditStreamInternalImpl iEditStreamInternal;
+
+  AVISTREAMINFOW       sInfo;
+
+  EditStreamTable     *pStreams;
+  DWORD                nStreams;   /* current fill level of pStreams table */
+  DWORD                nTableSize; /* size of pStreams table */
+
+  BOOL                 bDecompress;
+  PAVISTREAM           pCurStream;
+  PGETFRAME            pg;         /* IGetFrame for pCurStream */
+  LPBITMAPINFOHEADER   lpFrame;    /* frame of pCurStream */
+};
+
+/***********************************************************************/
+
+PAVIEDITSTREAM AVIFILE_CreateEditStream(PAVISTREAM pstream)
+{
+  IAVIEditStreamImpl *pedit = NULL;
+
+  pedit = (IAVIEditStreamImpl*)LocalAlloc(LPTR,sizeof(IAVIEditStreamImpl));
+  if (pedit == NULL)
+    return NULL;
+
+  pedit->lpVtbl            = &ieditstream;
+  pedit->iAVIStream.lpVtbl = &ieditstast;
+  pedit->iAVIStream.pae    = pedit;
+  pedit->iEditStreamInternal.lpVtbl = &ieditstreaminternal;
+  pedit->iEditStreamInternal.pae    = pedit;
+  pedit->ref = 1;
+
+  IAVIStream_Create((PAVISTREAM)&pedit->iAVIStream,(LPARAM)pstream,0);
+
+  return (PAVIEDITSTREAM)pedit;
+}
+
+static HRESULT AVIFILE_FindStreamInTable(IAVIEditStreamImpl* const This,
+					 DWORD pos,PAVISTREAM *ppStream,
+					 DWORD* streamPos,
+					 DWORD* streamNr,BOOL bFindSample)
+{
+  DWORD n;
+
+  TRACE("(%p,%lu,%p,%p,%p,%d)",This,pos,ppStream,streamPos,
+        streamNr,bFindSample);
+
+  if (pos < This->sInfo.dwStart)
+    return AVIERR_BADPARAM;
+
+  pos -= This->sInfo.dwStart;
+  for (n = 0; n < This->nStreams; n++) {
+    if (pos < This->pStreams[n].dwLength) {
+      *ppStream  = This->pStreams[n].pStream;
+      *streamPos = This->pStreams[n].dwStart + pos;
+      if (streamNr != NULL)
+        *streamNr = n;
+
+      return AVIERR_OK;
+    }
+    pos -= This->pStreams[n].dwLength;
+  }
+  if (pos == 0 && bFindSample) {
+    *ppStream  = This->pStreams[--n].pStream;
+    *streamPos = EditStreamEnd(This, n);
+    if (streamNr != NULL)
+      *streamNr = n;
+
+    TRACE(" -- pos=0 && b=1 -> (%p,%lu,%lu)\n",*ppStream, *streamPos, n);
+    return AVIERR_OK;
+  } else {
+    *ppStream = NULL;
+    *streamPos = 0;
+    if (streamNr != NULL)
+      *streamNr = 0;
+
+    TRACE(" -> ERROR (NULL,0,0)\n");
+    return AVIERR_BADPARAM;
+  }
+}
+
+static LPVOID AVIFILE_ReadFrame(IAVIEditStreamImpl* const This,
+                                PAVISTREAM pstream, LONG pos)
+{
+  PGETFRAME pg;
+
+  TRACE("(%p,%p,%ld)\n",This,pstream,pos);
+
+  if (pstream == NULL)
+    return NULL;
+
+  /* if stream changes make sure that only palette changes */
+  if (This->pCurStream != pstream) {
+    pg = AVIStreamGetFrameOpen(pstream, NULL);
+    if (pg == NULL)
+      return NULL;
+    if (This->pg != NULL) {
+      if (IGetFrame_SetFormat(pg, This->lpFrame, NULL, 0, 0, -1, -1)) {
+        AVIStreamGetFrameClose(pg);
+        ERR(": IGetFrame_SetFormat failed\n");
+        return NULL;
+      }
+      AVIStreamGetFrameClose(This->pg);
+    }
+    This->pg         = pg;
+    This->pCurStream = pstream;
+  }
+
+  /* now get the decompressed frame */
+  This->lpFrame = AVIStreamGetFrame(This->pg, pos);
+  if (This->lpFrame != NULL)
+    This->sInfo.dwSuggestedBufferSize = This->lpFrame->biSizeImage;
+
+  return This->lpFrame;
+}
+
+static HRESULT AVIFILE_RemoveStream(IAVIEditStreamImpl* const This, DWORD nr)
+{
+  assert(This != NULL);
+  assert(nr < This->nStreams);
+
+  /* remove part nr */
+  IAVIStream_Release(This->pStreams[nr].pStream);
+  This->nStreams--;
+  if (This->nStreams - nr > 0) {
+    memmove(This->pStreams + nr, This->pStreams + nr + 1,
+            (This->nStreams - nr) * sizeof(EditStreamTable));
+  }
+  This->pStreams[This->nStreams].pStream  = NULL;
+  This->pStreams[This->nStreams].dwStart  = 0;
+  This->pStreams[This->nStreams].dwLength = 0;
+
+  /* try to merge the part before the deleted one and the one after it */
+  if (0 < nr && 0 < This->nStreams &&
+      This->pStreams[nr - 1].pStream == This->pStreams[nr].pStream) {
+    if (EditStreamEnd(This, nr - 1) == This->pStreams[nr].dwStart) {
+      This->pStreams[nr - 1].dwLength += This->pStreams[nr].dwLength;
+      return AVIFILE_RemoveStream(This, nr);
+    }
+  }
+
+  return AVIERR_OK;
+}
+
+static BOOL AVIFILE_FormatsEqual(PAVISTREAM avi1, PAVISTREAM avi2)
+{
+  LPVOID fmt1 = NULL, fmt2 = NULL;
+  LONG size1, size2, start1, start2;
+  BOOL status = FALSE;
+
+  assert(avi1 != NULL && avi2 != NULL);
+
+  /* get stream starts and check format sizes */
+  start1 = AVIStreamStart(avi1);
+  start2 = AVIStreamStart(avi2);
+  if (FAILED(AVIStreamFormatSize(avi1, start1, &size1)))
+    return FALSE;
+  if (FAILED(AVIStreamFormatSize(avi2, start2, &size2)))
+    return FALSE;
+  if (size1 != size2)
+    return FALSE;
+
+  /* sizes match, now get formats and compare them */
+  fmt1 = GlobalAllocPtr(GHND, size1);
+  if (fmt1 == NULL)
+    return FALSE;
+  if (SUCCEEDED(AVIStreamReadFormat(avi1, start1, fmt1, &size1))) {
+    fmt2 = GlobalAllocPtr(GHND, size1);
+    if (fmt2 != NULL) {
+      if (SUCCEEDED(AVIStreamReadFormat(avi2, start2, fmt2, &size1)))
+        status = memcmp(fmt1, fmt2, size1);
+    }
+  }
+
+  if (fmt2 != NULL)
+    GlobalFreePtr(fmt2);
+  GlobalFreePtr(fmt1);
+
+  return status;
+}
+
+/***********************************************************************/
+
+static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+
+  TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
+
+  if (IsEqualGUID(&IID_IUnknown, refiid) ||
+      IsEqualGUID(&IID_IAVIEditStream, refiid)) {
+    *obj = iface;
+    IAVIEditStream_AddRef(iface);
+
+    return S_OK;
+  } else if (IsEqualGUID(&IID_IAVIStream, refiid)) {
+    *obj = &This->iAVIStream;
+    IAVIEditStream_AddRef(iface);
+
+    return S_OK;
+  } else if (IsEqualGUID(&IID_IEditStreamInternal, refiid)) {
+    *obj = &This->iEditStreamInternal;
+    IAVIEditStream_AddRef(iface);
+
+    return S_OK;
+  }
+
+  return OLE_E_ENUM_NOMORE;
+}
+
+static ULONG   WINAPI IAVIEditStream_fnAddRef(IAVIEditStream*iface)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+
+  TRACE("(%p) -> %ld\n", iface, This->ref + 1);
+  return ++(This->ref);
+}
+
+static ULONG   WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+  DWORD i;
+
+  TRACE("(%p) -> %ld\n", iface, This->ref - 1);
+
+  if (!--(This->ref)) {
+    /* releaase memory */
+    if (This->pg != NULL)
+      AVIStreamGetFrameClose(This->pg);
+    if (This->pStreams != NULL) {
+      for (i = 0; i < This->nStreams; i++) {
+        if (This->pStreams[i].pStream != NULL)
+          IAVIStream_Release(This->pStreams[i].pStream);
+      }
+      GlobalFreePtr(This->pStreams);
+    }
+
+    LocalFree((HLOCAL)This);
+    return 0;
+  }
+  return This->ref;
+}
+
+static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
+                                           LONG*plLength,PAVISTREAM*ppResult)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+  PAVISTREAM stream;
+  DWORD      start, len, streamPos, streamNr;
+  HRESULT    hr;
+
+  TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult);
+
+  if (ppResult != NULL)
+    *ppResult = NULL;
+  if (plStart == NULL || plLength == NULL || *plStart < 0)
+    return AVIERR_BADPARAM;
+
+  /* if asked for cutted part copy it before deleting */
+  if (ppResult != NULL) {
+    hr = IAVIEditStream_Copy(iface, plStart, plLength, ppResult);
+    if (FAILED(hr))
+      return hr;
+  }
+
+  start = *plStart;
+  len   = *plLength;
+
+  /* now delete the requested part */
+  while (len > 0) {
+    hr = AVIFILE_FindStreamInTable(This, start, &stream,
+                                   &streamPos, &streamNr, FALSE);
+    if (FAILED(hr))
+      return hr;
+    if (This->pStreams[streamNr].dwStart == streamPos) {
+      /* deleting from start of part */
+      if (len < This->pStreams[streamNr].dwLength) {
+        start += len;
+        This->pStreams[streamNr].dwStart  += len;
+        This->pStreams[streamNr].dwLength -= len;
+        This->sInfo.dwLength -= len;
+        len = 0;
+
+        /* we must return decompressed data now */
+        This->bDecompress = TRUE;
+      } else {
+        /* deleting hole part */
+        len -= This->pStreams[streamNr].dwLength;
+        AVIFILE_RemoveStream(This,streamNr);
+      }
+    } else if (EditStreamEnd(This, streamNr) <= streamPos + len) {
+      /* deleting at end of a part */
+      DWORD count = EditStreamEnd(This, streamNr) - streamPos;
+      This->sInfo.dwLength -= count;
+      len                  -= count;
+      This->pStreams[streamNr].dwLength =
+        streamPos - This->pStreams[streamNr].dwStart;
+    } else {
+      /* splitting */
+      if (This->nStreams + 1 >= This->nTableSize) {
+        This->pStreams =
+          GlobalReAllocPtr(This->pStreams, (This->nTableSize + 32) * sizeof(EditStreamTable), GMEM_SHARE|GHND);
+        if (This->pStreams == NULL)
+          return AVIERR_MEMORY;
+        This->nTableSize += 32;
+      }
+      memmove(This->pStreams + streamNr + 1, This->pStreams + streamNr,
+              (This->nStreams - streamNr) * sizeof(EditStreamTable));
+      This->nStreams++;
+
+      IAVIStream_AddRef(This->pStreams[streamNr + 1].pStream);
+      This->pStreams[streamNr + 1].dwStart  = streamPos + len;
+      This->pStreams[streamNr + 1].dwLength =
+        EditStreamEnd(This, streamNr) - This->pStreams[streamNr + 1].dwStart;
+
+      This->pStreams[streamNr].dwLength =
+        streamPos - This->pStreams[streamNr].dwStart;
+      This->sInfo.dwLength -= len;
+      len = 0;
+    }
+  }
+
+  This->sInfo.dwEditCount++;
+
+  return AVIERR_OK;
+}
+
+static HRESULT WINAPI IAVIEditStream_fnCopy(IAVIEditStream*iface,LONG*plStart,
+                                            LONG*plLength,PAVISTREAM*ppResult)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+  IAVIEditStreamImpl* pEdit;
+  HRESULT hr;
+  LONG start = 0;
+
+  TRACE("(%p,%p,%p,%p)\n",iface,plStart,plLength,ppResult);
+
+  if (ppResult == NULL)
+    return AVIERR_BADPARAM;
+  *ppResult = NULL;
+  if (plStart == NULL || plLength == NULL || *plStart < 0 || *plLength < 0)
+    return AVIERR_BADPARAM;
+
+  /* check bounds */
+  if (*(LPDWORD)plLength > This->sInfo.dwLength)
+    *(LPDWORD)plLength = This->sInfo.dwLength;
+  if (*(LPDWORD)plStart < This->sInfo.dwStart) {
+    *(LPDWORD)plLength -= This->sInfo.dwStart - *(LPDWORD)plStart;
+    *(LPDWORD)plStart   = This->sInfo.dwStart;
+    if (*plLength < 0)
+      return AVIERR_BADPARAM;
+  }
+  if (*(LPDWORD)plStart + *(LPDWORD)plLength > This->sInfo.dwStart + This->sInfo.dwLength)
+    *(LPDWORD)plLength = This->sInfo.dwStart + This->sInfo.dwLength -
+      *(LPDWORD)plStart;
+
+  pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL);
+  if (pEdit == NULL)
+    return AVIERR_MEMORY;
+
+  hr = IAVIEditStream_Paste((PAVIEDITSTREAM)pEdit,&start,plLength,
+                            (PAVISTREAM)&This->iAVIStream,*plStart,
+                            *plStart + *plLength);
+  *plStart = start;
+  if (FAILED(hr))
+    IAVIEditStream_Release((PAVIEDITSTREAM)pEdit);
+  else
+    *ppResult = (PAVISTREAM)&pEdit->iAVIStream;
+
+  return hr;
+}
+
+static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart,
+                                             LONG*plLength,PAVISTREAM pSource,
+                                             LONG lStart,LONG lLength)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+  AVISTREAMINFOW      srcInfo;
+  IEditStreamInternal*pTable = NULL;
+  IAVIEditStreamImpl *pEdit  = NULL;
+
+  FIXME("(%p,%p,%p,%p,%ld,%ld),stub!\n",iface,plStart,plLength,
+        pSource,lStart,lLength);
+
+  if (plStart == NULL || pSource == NULL || lLength < 0)
+    return AVIERR_BADPARAM;
+  if (This->sInfo.dwStart + This->sInfo.dwLength < *plStart)
+    return AVIERR_BADPARAM; /* FIXME: or change plStart to end of stream? */
+  if (FAILED(IAVIStream_Info(pSource, &srcInfo, sizeof(srcInfo))))
+    return AVIERR_ERROR;
+  if (lStart < srcInfo.dwStart || lStart >= srcInfo.dwStart + srcInfo.dwLength)
+    return AVIERR_BADPARAM;
+  if (This->sInfo.fccType != srcInfo.fccType)
+    return AVIERR_UNSUPPORTED; /* different stream types */
+  if (This->sInfo.fccType == 0) {
+    IAVIStream_Info(pSource, &This->sInfo, sizeof(This->sInfo));
+    This->sInfo.dwStart  = *plStart;
+    This->sInfo.dwLength = 0;
+  }
+  if (lStart + lLength > srcInfo.dwStart + srcInfo.dwLength)
+    lLength = srcInfo.dwStart + srcInfo.dwLength - lStart;
+  if (lLength + *plStart >= 0x80000000)
+    return AVIERR_MEMORY;
+
+  /* streamtype specific tests */
+  if (srcInfo.fccType == streamtypeVIDEO) {
+    DWORD size;
+
+    size = srcInfo.rcFrame.right - srcInfo.rcFrame.left;
+    if (size != This->sInfo.rcFrame.right - This->sInfo.rcFrame.left)
+      return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */
+    size = srcInfo.rcFrame.bottom - srcInfo.rcFrame.top;
+    if (size != This->sInfo.rcFrame.bottom - This->sInfo.rcFrame.top)
+      return AVIERR_UNSUPPORTED; /* FIXME: Can't GetFrame convert it? */
+  } else if (srcInfo.fccType == streamtypeAUDIO) {
+    if (! AVIFILE_FormatsEqual((PAVISTREAM)&This->iAVIStream, pSource))
+      return AVIERR_UNSUPPORTED;
+  } else {
+    /* FIXME: streamtypeMIDI and streamtypeTEXT */
+    return AVIERR_UNSUPPORTED;
+  }
+  
+  /* try to get an IEditStreamInternal interface */
+  if (SUCCEEDED(IAVIStream_QueryInterface(pSource, &IID_IEditStreamInternal,
+                                          (LPVOID*)&pTable))) {
+    pTable->lpVtbl->GetEditStreamImpl(pTable, (LPVOID*)&pEdit);
+    pTable->lpVtbl->Release(pTable);
+  }
+
+  /* FIXME: for video must check for change of format */
+  /* FIXME: if stream to insert is an editable stream insert the
+   *        'sub-streams' else the given stream.
+   */
+
+  return AVIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
+                                             PAVISTREAM*ppResult)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+  IAVIEditStreamImpl* pEdit;
+  DWORD i;
+
+  TRACE("(%p,%p)\n",iface,ppResult);
+
+  if (ppResult == NULL)
+    return AVIERR_BADPARAM;
+  *ppResult = NULL;
+
+  pEdit = (IAVIEditStreamImpl*)AVIFILE_CreateEditStream(NULL);
+  if (pEdit == NULL)
+    return AVIERR_MEMORY;
+  if (This->nStreams > pEdit->nTableSize) {
+    pEdit->pStreams = GlobalReAllocPtr(pEdit->pStreams, This->nStreams * sizeof(EditStreamTable),GMEM_SHARE|GHND);
+    if (pEdit->pStreams == NULL)
+      return AVIERR_MEMORY;
+    pEdit->nTableSize = This->nStreams;
+  }
+  pEdit->nStreams = This->nStreams;
+  memcpy(pEdit->pStreams, This->pStreams,
+         This->nStreams * sizeof(EditStreamTable));
+  memcpy(&pEdit->sInfo,&This->sInfo,sizeof(This->sInfo));
+  for (i = 0; i < This->nStreams; i++) {
+    if (pEdit->pStreams[i].pStream != NULL)
+      IAVIStream_AddRef(pEdit->pStreams[i].pStream);
+  }
+
+  *ppResult = (PAVISTREAM)&pEdit->iAVIStream;
+
+  return AVIERR_OK;
+}
+
+static HRESULT WINAPI IAVIEditStream_fnSetInfo(IAVIEditStream*iface,
+                                               LPAVISTREAMINFOW asi,LONG size)
+{
+  ICOM_THIS(IAVIEditStreamImpl,iface);
+
+  TRACE("(%p,%p,%ld)",iface,asi,size);
+
+  /* check parameters */
+  if (asi == NULL)
+    return AVIERR_BADPARAM;
+  if (size != sizeof(AVISTREAMINFOW))
+    return AVIERR_BADSIZE;
+  if (asi->dwScale == 0 || asi->dwRate == 0 || (LONG)asi->dwQuality < -1 ||
+      asi->dwQuality > ICQUALITY_HIGH)
+    return AVIERR_ERROR;
+
+  This->sInfo.wLanguage = asi->wLanguage;
+  This->sInfo.wPriority = asi->wPriority;
+  This->sInfo.dwStart   = asi->dwStart;
+  if (asi->dwRate != 0)
+    This->sInfo.dwRate  = asi->dwRate;
+  if (asi->dwScale != 0)
+    This->sInfo.dwScale = asi->dwScale;
+  if (asi->dwQuality <= ICQUALITY_HIGH)
+    This->sInfo.dwQuality = ICQUALITY_HIGH;
+  CopyRect(&This->sInfo.rcFrame, &asi->rcFrame);
+  memcpy(&This->sInfo.szName, &asi->szName, sizeof(asi->szName));
+  This->sInfo.dwEditCount++;
+
+  return AVIERR_OK;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnQueryInterface(IAVIStream*iface,
+                                                      REFIID refiid,LPVOID*obj)
+{
+  ICOM_THIS(IEditAVIStreamImpl,iface);
+
+  assert(This->pae != NULL);
+
+  return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae,refiid,obj);
+}
+
+static ULONG   WINAPI IEditAVIStream_fnAddRef(IAVIStream*iface)
+{
+  ICOM_THIS(IEditAVIStreamImpl,iface);
+
+  assert(This->pae != NULL);
+
+  return IAVIEditStream_AddRef((IAVIEditStream*)This->pae);
+}
+
+static ULONG   WINAPI IEditAVIStream_fnRelease(IAVIStream*iface)
+{
+  ICOM_THIS(IEditAVIStreamImpl,iface);
+
+  assert(This->pae != NULL);
+
+  return IAVIEditStream_Release((IAVIEditStream*)This->pae);
+}
+
+static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface,
+                                              LPARAM lParam1,LPARAM lParam2)
+{
+  IAVIEditStreamImpl *This = ((IEditAVIStreamImpl*)iface)->pae;
+
+  if (lParam2 != 0)
+    return AVIERR_ERROR;
+
+  if (This->pStreams == NULL) {
+    This->pStreams =
+      GlobalAllocPtr(GMEM_SHARE|GHND, 256 * sizeof(EditStreamTable));
+    if (This->pStreams == NULL)
+      return AVIERR_MEMORY;
+    This->nTableSize = 256;
+  }
+
+  if (lParam1 != 0) {
+    IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
+    IAVIStream_AddRef((PAVISTREAM)lParam1);
+    This->pStreams[0].pStream  = (PAVISTREAM)lParam1;
+    This->pStreams[0].dwStart  = This->sInfo.dwStart;
+    This->pStreams[0].dwLength = This->sInfo.dwLength;
+    This->nStreams = 1;
+  }
+  return AVIERR_OK;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnInfo(IAVIStream*iface,
+                                            AVISTREAMINFOW *psi,LONG size)
+{
+  ICOM_THIS(IEditAVIStreamImpl,iface);
+
+  TRACE("(%p,%p,%ld)\n",iface,psi,size);
+
+  assert(This->pae != NULL);
+
+  if (psi == NULL)
+    return AVIERR_BADPARAM;
+  if (size < 0)
+    return AVIERR_BADSIZE;
+
+  if (This->pae->bDecompress)
+    This->pae->sInfo.fccHandler = 0;
+
+  memcpy(psi, &This->pae->sInfo, min((DWORD)size, sizeof(This->pae->sInfo)));
+
+  if ((DWORD)size < sizeof(This->pae->sInfo))
+    return AVIERR_BUFFERTOOSMALL;
+  return AVIERR_OK;
+}
+
+static LONG    WINAPI IEditAVIStream_fnFindSample(IAVIStream*iface,LONG pos,
+                                                  LONG flags)
+{
+  IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
+  PAVISTREAM stream;
+  DWORD      streamPos, streamNr;
+
+  TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
+
+  if (flags & FIND_FROM_START)
+    pos = (LONG)This->sInfo.dwStart;
+
+  /* outside of stream? */
+  if (pos < (LONG)This->sInfo.dwStart ||
+      (LONG)This->sInfo.dwStart + (LONG)This->sInfo.dwLength <= pos)
+    return -1;
+
+  /* map our position to a stream and position in it */
+  if (AVIFILE_FindStreamInTable(This, pos, &stream, &streamPos,
+                                &streamNr, TRUE))
+    return -1; /* doesn't exist */
+
+  if (This->bDecompress) {
+    /* only one stream -- format changes only at start */
+    if (flags & FIND_FORMAT)
+      return (flags & FIND_NEXT ? -1 : 0);
+
+    /* FIXME: map positions back to us */
+    return IAVIStream_FindSample(stream, streamPos, flags);
+  } else {
+    /* assume change of format every frame */
+    return pos;
+  }
+}
+
+static HRESULT WINAPI IEditAVIStream_fnReadFormat(IAVIStream*iface,LONG pos,
+                                                  LPVOID format,LONG*fmtsize)
+{
+  IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
+  LPBITMAPINFOHEADER  lp;
+  PAVISTREAM          stream;
+  DWORD               n;
+  HRESULT             hr;
+
+  TRACE("(%p,%ld,%p,%p)\n",iface,pos,format,fmtsize);
+
+  if (fmtsize == NULL || pos < This->sInfo.dwStart ||
+      This->sInfo.dwStart + This->sInfo.dwLength <= pos)
+    return AVIERR_BADPARAM;
+
+  /* find stream corresponding to position */
+  hr = AVIFILE_FindStreamInTable(This, pos, &stream, &n, NULL, FALSE);
+  if (FAILED(hr))
+    return hr;
+
+  if (! This->bDecompress)
+    return IAVIStream_ReadFormat(stream, n, format, fmtsize);
+
+  lp = (LPBITMAPINFOHEADER)AVIFILE_ReadFrame(This, stream, n);
+  if (lp == NULL)
+    return AVIERR_ERROR;
+  if (lp->biBitCount <= 8) {
+    n  = (lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount);
+    n *= sizeof(RGBQUAD);
+  } else
+    n = 0;
+  n += lp->biSize;
+  
+  memcpy(format, lp, min((LONG)n, *fmtsize));
+  hr = ((LONG)n > *fmtsize ? AVIERR_BUFFERTOOSMALL : AVIERR_OK);
+  *fmtsize = n;
+
+  return hr;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnSetFormat(IAVIStream*iface,LONG pos,
+                                                 LPVOID format,LONG formatsize)
+{
+  TRACE("(%p,%ld,%p,%ld)\n",iface,pos,format,formatsize);
+
+  return AVIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnRead(IAVIStream*iface,LONG start,
+                                            LONG samples,LPVOID buffer,
+                                            LONG buffersize,LONG*bytesread,
+                                            LONG*samplesread)
+{
+  IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
+  PAVISTREAM stream;
+  DWORD   streamPos, streamNr;
+  LONG    readBytes, readSamples, count;
+  HRESULT hr;
+
+  TRACE("(%p,%ld,%ld,%p,%ld,%p,%p) -- 0x%08lX\n",iface,start,samples,
+        buffer,buffersize,bytesread,samplesread,This->sInfo.fccType);
+
+  /* check parameters */
+  if (bytesread != NULL)
+    *bytesread = 0;
+  if (samplesread != NULL)
+    *samplesread = 0;
+  if (buffersize < 0)
+    return AVIERR_BADSIZE;
+  if ((DWORD)start < This->sInfo.dwStart ||
+      This->sInfo.dwStart + This->sInfo.dwLength < (DWORD)start)
+    return AVIERR_BADPARAM;
+
+  if (! This->bDecompress) {
+    /* audio like data -- sample-based */
+    do {
+      if (samples == 0)
+        return AVIERR_OK; /* nothing at all or already done */
+
+      if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream,
+                                           &streamPos, &streamNr, FALSE)))
+        return AVIERR_ERROR;
+
+      /* limit to end of the stream */
+      count = samples;
+      if (streamPos + count > EditStreamEnd(This, streamNr))
+        count = EditStreamEnd(This, streamNr) - streamPos;
+
+      hr = IAVIStream_Read(stream, streamPos, count, buffer, buffersize,
+                           &readBytes, &readSamples);
+      if (FAILED(hr))
+        return hr;
+      if (readBytes == 0 && readSamples == 0 && count != 0)
+        return AVIERR_FILEREAD; /* for bad stream implementations */
+
+      if (samplesread != NULL)
+        *samplesread += readSamples;
+      if (bytesread != NULL)
+        *bytesread += readBytes;
+      if (buffer != NULL) {
+        (LPBYTE)buffer += readBytes;
+        buffersize     -= readBytes;
+      }
+      start   += count;
+      samples -= count;
+    } while (This->sInfo.dwStart + This->sInfo.dwLength > start);
+  } else {
+    /* video like data -- frame-based */
+    LPBITMAPINFOHEADER lp;
+
+    if (samples == 0)
+      return AVIERR_OK;
+
+    if (FAILED(AVIFILE_FindStreamInTable(This, start, &stream,
+                                         &streamPos, &streamNr, FALSE)))
+      return AVIERR_ERROR;
+
+    lp = AVIFILE_ReadFrame(This, stream, streamPos);
+    if (lp == NULL)
+      return AVIERR_ERROR;
+
+    if (buffer != NULL) {
+      /* need size of format to skip */
+      if (lp->biBitCount <= 8) {
+        count  = lp->biClrUsed > 0 ? lp->biClrUsed : 1 << lp->biBitCount;
+        count *= sizeof(RGBQUAD);
+      } else
+        count = 0;
+      count += lp->biSize;
+
+      if (buffersize < lp->biSizeImage)
+        return AVIERR_BUFFERTOOSMALL;
+      memcpy(buffer, (LPBYTE)lp + count, lp->biSizeImage);
+    }
+
+    if (bytesread != NULL)
+      *bytesread = lp->biSizeImage;
+    if (samplesread != NULL)
+      *samplesread = 1;
+  }
+
+  return AVIERR_OK;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnWrite(IAVIStream*iface,LONG start,
+                                             LONG samples,LPVOID buffer,
+                                             LONG buffersize,DWORD flags,
+                                             LONG*sampwritten,LONG*byteswritten)
+{
+  TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)",iface,start,samples,buffer,
+        buffersize,flags,sampwritten,byteswritten);
+
+  /* be sure return parameters have correct values */
+  if (sampwritten != NULL)
+    *sampwritten = 0;
+  if (byteswritten != NULL)
+    *byteswritten = 0;
+
+  return AVIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnDelete(IAVIStream*iface,LONG start,
+                                              LONG samples)
+{
+  ICOM_THIS(IEditAVIStreamImpl,iface);
+
+  TRACE("(%p,%ld,%ld)\n",iface,start,samples);
+
+  return IAVIEditStream_Cut((IAVIEditStream*)This->pae,&start,&samples,NULL);
+}
+
+static HRESULT WINAPI IEditAVIStream_fnReadData(IAVIStream*iface,DWORD fcc,
+                                                LPVOID lp,LONG *lpread)
+{
+  IAVIEditStreamImpl* const This = ((IEditAVIStreamImpl* const)iface)->pae;
+  DWORD n;
+
+  TRACE("(%p,0x%08lX,%p,%p)",iface,fcc,lp,lpread);
+
+  /* check parameters */
+  if (lp == NULL || lpread == NULL)
+    return AVIERR_BADPARAM;
+
+  /* simply ask every stream and return the first block found */
+  for (n = 0; n < This->nStreams; n++) {
+    HRESULT hr = IAVIStream_ReadData(This->pStreams[n].pStream,fcc,lp,lpread);
+
+    if (SUCCEEDED(hr))
+      return hr;
+  }
+
+  *lpread = 0;
+  return AVIERR_NODATA;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnWriteData(IAVIStream*iface,DWORD fcc,
+                                                 LPVOID lp,LONG size)
+{
+  TRACE("(%p,0x%08lX,%p,%ld)",iface,fcc,lp,size);
+
+  return AVIERR_UNSUPPORTED;
+}
+
+static HRESULT WINAPI IEditAVIStream_fnSetInfo(IAVIStream*iface,
+                                               AVISTREAMINFOW*info,LONG len)
+{
+  ICOM_THIS(IEditAVIStreamImpl,iface);
+
+  TRACE("(%p,%p,%ld)\n",iface,info,len);
+
+  return IAVIEditStream_SetInfo((IAVIEditStream*)This->pae,info,len);
+}
+
+static HRESULT WINAPI IEditStreamInternal_fnQueryInterface(IEditStreamInternal*iface,REFIID refiid,LPVOID*obj)
+{
+  ICOM_THIS(IEditStreamInternalImpl,iface);
+
+  assert(This->pae != NULL);
+
+  return IAVIEditStream_QueryInterface((IAVIEditStream*)This->pae, refiid, obj);
+}
+
+static ULONG   WINAPI IEditStreamInternal_fnAddRef(IEditStreamInternal*iface)
+{
+  ICOM_THIS(IEditStreamInternalImpl,iface);
+
+  assert(This->pae != NULL);
+
+  return IAVIEditStream_AddRef((IAVIEditStream*)This->pae);
+}
+
+static ULONG   WINAPI IEditStreamInternal_fnRelease(IEditStreamInternal*iface)
+{
+  ICOM_THIS(IEditStreamInternalImpl,iface);
+
+  assert(This->pae != NULL);
+
+  return IAVIEditStream_Release((IAVIEditStream*)This->pae);
+}
+
+static HRESULT  WINAPI IEditStreamInternal_fnGetEditStreamImpl(IEditStreamInternal*iface,LPVOID*ppimpl)
+{
+  ICOM_THIS(IEditStreamInternalImpl,iface);
+
+  assert(This->pae != NULL);
+  assert(ppimpl != NULL);
+
+  *ppimpl = This->pae;
+  return AVIERR_OK;
+}

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux