[AVIFILE] Implemented Paste for IAVIEditStream

Michael Günnewig MichaelGuennewig at gmx.de
Sun Nov 23 12:40:25 CST 2003


Now the IAVIEditStream implementation is complete.

The only support still missing in avifil32.dll is the clipoard
functionallity and the possibility to embed as OLE objects.

Changlog:
  Implemented IAVIEditSTream_fnPaste method.


  Michael Günnewig

--- dlls/avifil32/editstream.c.~1.1.~	2003-10-04 05:05:25.000000000 +0200
+++ dlls/avifil32/editstream.c	2003-11-23 19:05:42.000000000 +0100
@@ -210,7 +210,7 @@
 {
   DWORD n;
 
-  TRACE("(%p,%lu,%p,%p,%p,%d)",This,pos,ppStream,streamPos,
+  TRACE("(%p,%lu,%p,%p,%p,%d)\n",This,pos,ppStream,streamPos,
         streamNr,bFindSample);
 
   if (pos < This->sInfo.dwStart)
@@ -336,7 +336,7 @@
     fmt2 = GlobalAllocPtr(GHND, size1);
     if (fmt2 != NULL) {
       if (SUCCEEDED(AVIStreamReadFormat(avi2, start2, fmt2, &size1)))
-        status = memcmp(fmt1, fmt2, size1);
+        status = (memcmp(fmt1, fmt2, size1) == 0);
     }
   }
 
@@ -544,27 +544,34 @@
 {
   ICOM_THIS(IAVIEditStreamImpl,iface);
   AVISTREAMINFOW      srcInfo;
-  IEditStreamInternal*pTable = NULL;
-  IAVIEditStreamImpl *pEdit  = NULL;
+  IEditStreamInternal*pInternal = NULL;
+  IAVIEditStreamImpl *pEdit = NULL;
+  PAVISTREAM          pStream;
+  DWORD               startPos, endPos, streamNr, n, nStreams;
 
-  FIXME("(%p,%p,%p,%p,%ld,%ld),stub!\n",iface,plStart,plLength,
-        pSource,lStart,lLength);
+  TRACE("(%p,%p,%p,%p,%ld,%ld)\n",iface,plStart,plLength,
+	pSource,lStart,lLength);
 
-  if (plStart == NULL || pSource == NULL || lLength < 0)
+  if (pSource == NULL)
+    return AVIERR_BADHANDLE;
+  if (plStart == NULL || *plStart < 0)
     return AVIERR_BADPARAM;
   if (This->sInfo.dwStart + This->sInfo.dwLength < *plStart)
-    return AVIERR_BADPARAM; /* FIXME: or change plStart to end of stream? */
+    return AVIERR_BADPARAM; /* Can't paste with holes */
   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) {
+    /* This stream is empty */
     IAVIStream_Info(pSource, &This->sInfo, sizeof(This->sInfo));
     This->sInfo.dwStart  = *plStart;
     This->sInfo.dwLength = 0;
   }
+  if (This->sInfo.fccType != srcInfo.fccType)
+    return AVIERR_UNSUPPORTED; /* different stream types */
+  if (lLength == -1) /* Copy the hole stream */
+    lLength = srcInfo.dwLength;
   if (lStart + lLength > srcInfo.dwStart + srcInfo.dwLength)
     lLength = srcInfo.dwStart + srcInfo.dwLength - lStart;
   if (lLength + *plStart >= 0x80000000)
@@ -587,20 +594,140 @@
     /* 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);
+                                          (LPVOID*)&pInternal))) {
+    pInternal->lpVtbl->GetEditStreamImpl(pInternal, (LPVOID*)&pEdit);
+    pInternal->lpVtbl->Release(pInternal);
   }
 
-  /* 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.
-   */
+  /* for video must check for change of format */
+  if (This->sInfo.fccType == streamtypeVIDEO) {
+    if (! This->bDecompress) {
+      /* Need to decompress if any of the following conditions matches:
+       *  - pSource is an editable stream which decompresses
+       *  - the nearest keyframe of pSource isn't lStart
+       *  - the nearest keyframe of this stream isn't *plStart
+       *  - the format of pSource doesn't match this one
+       */
+      if ((pEdit != NULL && pEdit->bDecompress) ||
+	  AVIStreamNearestKeyFrame(pSource, lStart) != lStart ||
+	  AVIStreamNearestKeyFrame((PAVISTREAM)&This->iAVIStream, *plStart) != *plStart ||
+	  (This->nStreams > 0 && !AVIFILE_FormatsEqual((PAVISTREAM)&This->iAVIStream, pSource))) {
+	/* Use first stream part to get format to convert everything to */
+	AVIFILE_ReadFrame(This, This->pStreams[0].pStream,
+			  This->pStreams[0].dwStart);
 
-  return AVIERR_UNSUPPORTED;
+	/* Check if we could convert the source streams to the disired format... */
+	if (pEdit != NULL) {
+	  if (FAILED(AVIFILE_FindStreamInTable(pEdit, lStart, &pStream,
+					       &startPos, &streamNr, TRUE)))
+	    return AVIERR_INTERNAL;
+	  for (n = lStart; n < lStart + lLength; streamNr++) {
+	    if (AVIFILE_ReadFrame(This, pEdit->pStreams[streamNr].pStream, startPos) == NULL)
+	      return AVIERR_BADFORMAT;
+	    startPos = pEdit->pStreams[streamNr].dwStart;
+	    n += pEdit->pStreams[streamNr].dwLength;
+	  }
+	} else if (AVIFILE_ReadFrame(This, pSource, lStart) == NULL)
+	  return AVIERR_BADFORMAT;
+
+	This->bDecompress      = TRUE;
+	This->sInfo.fccHandler = 0;
+      }
+    } else if (AVIFILE_ReadFrame(This, pSource, lStart) == NULL)
+      return AVIERR_BADFORMAT; /* Can't convert source to own format */
+  } // FIXME: something special for the other formats?
+
+  /* Make sure we have enough memory for parts */
+  if (pEdit != NULL) {
+    DWORD nLastStream;
+
+    AVIFILE_FindStreamInTable(pEdit, lStart + lLength, &pStream,
+			      &endPos, &nLastStream, TRUE);
+    AVIFILE_FindStreamInTable(pEdit, lStart, &pStream,
+			      &startPos, &streamNr, FALSE);
+    if (nLastStream == streamNr)
+      nLastStream++;
+
+    nStreams = nLastStream - streamNr;
+  } else 
+    nStreams = 1;
+  if (This->nStreams + nStreams + 1 > This->nTableSize) {
+    n = This->nStreams + nStreams + 33;
+
+    This->pStreams =
+      GlobalReAllocPtr(This->pStreams, n * sizeof(EditStreamTable), GMEM_SHARE|GHND);
+    if (This->pStreams == NULL)
+      return AVIERR_MEMORY;
+    This->nTableSize = n;
+  }
+
+  if (plLength != NULL)
+    *plLength = lLength;
+
+  /* now do the real work */
+  if (This->sInfo.dwStart + This->sInfo.dwLength > *plStart) {
+    AVIFILE_FindStreamInTable(This, *plStart, &pStream,
+			      &startPos, &streamNr, FALSE);
+    if (startPos != This->pStreams[streamNr].dwStart) {
+      // split stream streamNr at startPos
+      memmove(This->pStreams + streamNr + nStreams + 1,
+	      This->pStreams + streamNr,
+	      (This->nStreams + nStreams - streamNr + 1) * sizeof(EditStreamTable));
+
+      This->pStreams[streamNr + 2].dwLength =
+	EditStreamEnd(This, streamNr + 2) - startPos;
+      This->pStreams[streamNr + 2].dwStart = startPos;
+      This->pStreams[streamNr].dwLength =
+	startPos - This->pStreams[streamNr].dwStart;
+      IAVIStream_AddRef(This->pStreams[streamNr].pStream);
+      streamNr++;
+    } else {
+      // insert before stream at streamNr
+      memmove(This->pStreams + streamNr + nStreams, This->pStreams + streamNr,
+	      (This->nStreams + nStreams - streamNr) * sizeof(EditStreamTable));
+    }
+  } else // append the streams
+    streamNr = This->nStreams;
+
+  if (pEdit != NULL) {
+    // insert the parts of the editable stream instead of itself
+    AVIFILE_FindStreamInTable(pEdit, lStart + lLength, &pStream,
+			      &endPos, NULL, FALSE);
+    AVIFILE_FindStreamInTable(pEdit, lStart, &pStream, &startPos, &n, FALSE);
+
+    memcpy(This->pStreams + streamNr, pEdit->pStreams + n,
+	   nStreams * sizeof(EditStreamTable));
+    if (This->pStreams[streamNr].dwStart < startPos) {
+      This->pStreams[streamNr].dwLength =
+	EditStreamEnd(This, streamNr) - startPos;
+      This->pStreams[streamNr].dwStart  = startPos;
+    }
+    if (endPos < EditStreamEnd(This, streamNr + nStreams))
+      This->pStreams[streamNr + nStreams].dwLength =
+	endPos - This->pStreams[streamNr + nStreams].dwStart;
+  } else {
+    // a simple stream
+    This->pStreams[streamNr].pStream  = pSource;
+    This->pStreams[streamNr].dwStart  = lStart;
+    This->pStreams[streamNr].dwLength = lLength;
+  }
+
+  for (n = 0; n < nStreams; n++) {
+    IAVIStream_AddRef(This->pStreams[streamNr + n].pStream);
+    if (0 < streamNr + n &&
+	This->pStreams[streamNr + n - 1].pStream != This->pStreams[streamNr + n].pStream) {
+      This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
+      This->sInfo.dwFormatChangeCount++;
+    }
+  }
+  This->sInfo.dwEditCount++;
+  This->sInfo.dwLength += lLength;
+  This->nStreams += nStreams;
+
+  return AVIERR_OK;
 }
 
 static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface,
@@ -1029,6 +1156,8 @@
 {
   ICOM_THIS(IEditStreamInternalImpl,iface);
 
+  TRACE("(%p,%p) -> %p\n", iface, ppimpl, This->pae);
+
   assert(This->pae != NULL);
   assert(ppimpl != NULL);
 






More information about the wine-patches mailing list