📄 editstream.c
字号:
/*
* 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 + -