⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 editstream.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright 2003 Michael G黱newig
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <assert.h>
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "winerror.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 _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
DECLARE_INTERFACE_(IEditStreamInternal,IUnknown)
{
    /*** IUnknown methods ***/
    STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID riid, void** ppvObject) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;
    /*** IEditStreamInternal methods ***/
    STDMETHOD(GetEditStreamImpl)(THIS_ LPVOID*) PURE;
};
#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);

static const struct IAVIEditStreamVtbl ieditstream = {
  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);

static const struct IAVIStreamVtbl ieditstast = {
  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);

static const struct IEditStreamInternalVtbl ieditstreaminternal = {
  IEditStreamInternal_fnQueryInterface,
  IEditStreamInternal_fnAddRef,
  IEditStreamInternal_fnRelease,
  IEditStreamInternal_fnGetEditStreamImpl
};

typedef struct _IAVIEditStreamImpl IAVIEditStreamImpl;

typedef struct _IEditAVIStreamImpl {
  /* IUnknown stuff */
  const IAVIStreamVtbl *lpVtbl;

  /* IAVIStream stuff */
  IAVIEditStreamImpl *pae;
} IEditAVIStreamImpl;

typedef struct _IEditStreamInternalImpl {
  /* IUnknown stuff */
  const IEditStreamInternalVtbl *lpVtbl;

  /* IEditStreamInternal stuff */
  IAVIEditStreamImpl *pae;
} IEditStreamInternalImpl;

struct _IAVIEditStreamImpl {
  /* IUnknown stuff */
  const IAVIEditStreamVtbl *lpVtbl;
  LONG  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 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 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,%u,%p,%p,%p,%d)\n",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,%u,%u)\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,%d)\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 = HeapAlloc(GetProcessHeap(), 0, size1);
  if (fmt1 == NULL)
    return FALSE;
  if (SUCCEEDED(AVIStreamReadFormat(avi1, start1, fmt1, &size1))) {
    fmt2 = HeapAlloc(GetProcessHeap(), 0, size1);
    if (fmt2 != NULL) {
      if (SUCCEEDED(AVIStreamReadFormat(avi2, start2, fmt2, &size1)))
        status = (memcmp(fmt1, fmt2, size1) == 0);
    }
  }

  HeapFree(GetProcessHeap(), 0, fmt2);
  HeapFree(GetProcessHeap(), 0, fmt1);

  return status;
}

/***********************************************************************/

static HRESULT WINAPI IAVIEditStream_fnQueryInterface(IAVIEditStream*iface,REFIID refiid,LPVOID *obj)
{
  IAVIEditStreamImpl *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)
{
  IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
  ULONG ref = InterlockedIncrement(&This->ref);

  TRACE("(%p) -> %d\n", iface, ref);

  return ref;
}

static ULONG   WINAPI IAVIEditStream_fnRelease(IAVIEditStream*iface)
{
  IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
  DWORD i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -