📄 avifile.c
字号:
* or have already written frames to disk */
return AVIERR_UNSUPPORTED;
}
/* check AVISTREAMINFO for some really needed things */
if (asi->fccType == 0 || asi->dwScale == 0 || asi->dwRate == 0)
return AVIERR_BADFORMAT;
/* now it seems to be save to add the stream */
assert(This->ppStreams[n] == NULL);
This->ppStreams[n] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(IAVIStreamImpl));
if (This->ppStreams[n] == NULL)
return AVIERR_MEMORY;
/* initialize the new allocated stream */
AVIFILE_ConstructAVIStream(This, n, asi);
This->fInfo.dwStreams++;
This->fDirty = TRUE;
/* update our AVIFILEINFO structure */
AVIFILE_UpdateInfo(This);
/* return it */
*avis = (PAVISTREAM)This->ppStreams[n];
IAVIStream_AddRef(*avis);
return AVIERR_OK;
}
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile *iface, DWORD ckid,
LPVOID lpData, LONG size)
{
IAVIFileImpl *This = (IAVIFileImpl *)iface;
TRACE("(%p,0x%08X,%p,%d)\n", iface, ckid, lpData, size);
/* check parameters */
if (lpData == NULL)
return AVIERR_BADPARAM;
if (size < 0)
return AVIERR_BADSIZE;
/* Do we have write permission? */
if ((This->uMode & MMIO_RWMODE) == 0)
return AVIERR_READONLY;
This->fDirty = TRUE;
return WriteExtraChunk(&This->fileextra, ckid, lpData, size);
}
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile *iface, DWORD ckid,
LPVOID lpData, LONG *size)
{
IAVIFileImpl *This = (IAVIFileImpl *)iface;
TRACE("(%p,0x%08X,%p,%p)\n", iface, ckid, lpData, size);
return ReadExtraChunk(&This->fileextra, ckid, lpData, size);
}
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile *iface)
{
IAVIFileImpl *This = (IAVIFileImpl *)iface;
TRACE("(%p)\n",iface);
if ((This->uMode & MMIO_RWMODE) == 0)
return AVIERR_READONLY;
This->fDirty = TRUE;
/* no frames written to any stream? -- compute start of 'movi'-chunk */
if (This->dwMoviChunkPos == 0)
AVIFILE_ComputeMoviStart(This);
This->fInfo.dwFlags |= AVIFILEINFO_ISINTERLEAVED;
/* already written frames to any stream, ... */
if (This->ckLastRecord.dwFlags & MMIO_DIRTY) {
/* close last record */
if (mmioAscend(This->hmmio, &This->ckLastRecord, 0) != 0)
return AVIERR_FILEWRITE;
AVIFILE_AddRecord(This);
if (This->fInfo.dwSuggestedBufferSize < This->ckLastRecord.cksize + 3 * sizeof(DWORD))
This->fInfo.dwSuggestedBufferSize = This->ckLastRecord.cksize + 3 * sizeof(DWORD);
}
/* write out a new record into file, but don't close it */
This->ckLastRecord.cksize = 0;
This->ckLastRecord.fccType = listtypeAVIRECORD;
if (mmioSeek(This->hmmio, This->dwNextFramePos, SEEK_SET) == -1)
return AVIERR_FILEWRITE;
if (mmioCreateChunk(This->hmmio, &This->ckLastRecord, MMIO_CREATELIST) != 0)
return AVIERR_FILEWRITE;
This->dwNextFramePos += 3 * sizeof(DWORD);
return AVIERR_OK;
}
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
LONG lParam)
{
IAVIFileImpl *This = (IAVIFileImpl *)iface;
ULONG nStream;
TRACE("(%p,0x%08X,%d)\n", iface, fccType, lParam);
/* check parameter */
if (lParam < 0)
return AVIERR_BADPARAM;
/* Have user write permissions? */
if ((This->uMode & MMIO_RWMODE) == 0)
return AVIERR_READONLY;
nStream = AVIFILE_SearchStream(This, fccType, lParam);
/* Does the requested stream exist? */
if (nStream < This->fInfo.dwStreams &&
This->ppStreams[nStream] != NULL) {
/* ... so delete it now */
HeapFree(GetProcessHeap(), 0, This->ppStreams[nStream]);
if (This->fInfo.dwStreams - nStream > 0)
memcpy(This->ppStreams + nStream, This->ppStreams + nStream + 1,
(This->fInfo.dwStreams - nStream) * sizeof(IAVIStreamImpl*));
This->ppStreams[This->fInfo.dwStreams] = NULL;
This->fInfo.dwStreams--;
This->fDirty = TRUE;
/* This->fInfo will be updated further when asked for */
return AVIERR_OK;
} else
return AVIERR_NODATA;
}
/***********************************************************************/
static HRESULT WINAPI IPersistFile_fnQueryInterface(IPersistFile *iface,
REFIID refiid, LPVOID *obj)
{
IPersistFileImpl *This = (IPersistFileImpl *)iface;
assert(This->paf != NULL);
return IAVIFile_QueryInterface((PAVIFILE)This->paf, refiid, obj);
}
static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile *iface)
{
IPersistFileImpl *This = (IPersistFileImpl *)iface;
assert(This->paf != NULL);
return IAVIFile_AddRef((PAVIFILE)This->paf);
}
static ULONG WINAPI IPersistFile_fnRelease(IPersistFile *iface)
{
IPersistFileImpl *This = (IPersistFileImpl *)iface;
assert(This->paf != NULL);
return IAVIFile_Release((PAVIFILE)This->paf);
}
static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile *iface,
LPCLSID pClassID)
{
TRACE("(%p,%p)\n", iface, pClassID);
if (pClassID == NULL)
return AVIERR_BADPARAM;
memcpy(pClassID, &CLSID_AVIFile, sizeof(CLSID_AVIFile));
return AVIERR_OK;
}
static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile *iface)
{
IPersistFileImpl *This = (IPersistFileImpl *)iface;
TRACE("(%p)\n", iface);
assert(This->paf != NULL);
return (This->paf->fDirty ? S_OK : S_FALSE);
}
static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile *iface,
LPCOLESTR pszFileName, DWORD dwMode)
{
IPersistFileImpl *This = (IPersistFileImpl *)iface;
int len;
TRACE("(%p,%s,0x%08X)\n", iface, debugstr_w(pszFileName), dwMode);
/* check parameter */
if (pszFileName == NULL)
return AVIERR_BADPARAM;
assert(This->paf != NULL);
if (This->paf->hmmio != NULL)
return AVIERR_ERROR; /* No reuse of this object for another file! */
/* remeber mode and name */
This->paf->uMode = dwMode;
len = lstrlenW(pszFileName) + 1;
This->paf->szFileName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (This->paf->szFileName == NULL)
return AVIERR_MEMORY;
lstrcpyW(This->paf->szFileName, pszFileName);
/* try to open the file */
This->paf->hmmio = mmioOpenW(This->paf->szFileName, NULL,
MMIO_ALLOCBUF | dwMode);
if (This->paf->hmmio == NULL) {
/* mmioOpenW not in native DLLs of Win9x -- try mmioOpenA */
LPSTR szFileName;
len = WideCharToMultiByte(CP_ACP, 0, This->paf->szFileName, -1,
NULL, 0, NULL, NULL);
szFileName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(CHAR));
if (szFileName == NULL)
return AVIERR_MEMORY;
WideCharToMultiByte(CP_ACP, 0, This->paf->szFileName, -1, szFileName,
len, NULL, NULL);
This->paf->hmmio = mmioOpenA(szFileName, NULL, MMIO_ALLOCBUF | dwMode);
HeapFree(GetProcessHeap(), 0, szFileName);
if (This->paf->hmmio == NULL)
return AVIERR_FILEOPEN;
}
/* should we create a new file? */
if (dwMode & OF_CREATE) {
memset(& This->paf->fInfo, 0, sizeof(This->paf->fInfo));
This->paf->fInfo.dwFlags = AVIFILEINFO_HASINDEX | AVIFILEINFO_TRUSTCKTYPE;
return AVIERR_OK;
} else
return AVIFILE_LoadFile(This->paf);
}
static HRESULT WINAPI IPersistFile_fnSave(IPersistFile *iface,
LPCOLESTR pszFileName,BOOL fRemember)
{
TRACE("(%p,%s,%d)\n", iface, debugstr_w(pszFileName), fRemember);
/* We write directly to disk, so nothing to do. */
return AVIERR_OK;
}
static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile *iface,
LPCOLESTR pszFileName)
{
TRACE("(%p,%s)\n", iface, debugstr_w(pszFileName));
/* We write directly to disk, so nothing to do. */
return AVIERR_OK;
}
static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile *iface,
LPOLESTR *ppszFileName)
{
IPersistFileImpl *This = (IPersistFileImpl *)iface;
TRACE("(%p,%p)\n", iface, ppszFileName);
if (ppszFileName == NULL)
return AVIERR_BADPARAM;
*ppszFileName = NULL;
assert(This->paf != NULL);
if (This->paf->szFileName != NULL) {
int len = lstrlenW(This->paf->szFileName) + 1;
*ppszFileName = CoTaskMemAlloc(len * sizeof(WCHAR));
if (*ppszFileName == NULL)
return AVIERR_MEMORY;
strcpyW(*ppszFileName, This->paf->szFileName);
}
return AVIERR_OK;
}
/***********************************************************************/
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream *iface,
REFIID refiid, LPVOID *obj)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
if (IsEqualGUID(&IID_IUnknown, refiid) ||
IsEqualGUID(&IID_IAVIStream, refiid)) {
*obj = This;
IAVIStream_AddRef(iface);
return S_OK;
}
/* FIXME: IAVIStreaming interface */
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream *iface)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) -> %d\n", iface, ref);
/* also add ref to parent, so that it doesn't kill us */
if (This->paf != NULL)
IAVIFile_AddRef((PAVIFILE)This->paf);
return ref;
}
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream* iface)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) -> %d\n", iface, ref);
if (This->paf != NULL)
IAVIFile_Release((PAVIFILE)This->paf);
return ref;
}
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
LPARAM lParam2)
{
TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
/* This IAVIStream interface needs an AVIFile */
return AVIERR_UNSUPPORTED;
}
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
LONG size)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
TRACE("(%p,%p,%d)\n", iface, psi, size);
if (psi == NULL)
return AVIERR_BADPARAM;
if (size < 0)
return AVIERR_BADSIZE;
memcpy(psi, &This->sInfo, min((DWORD)size, sizeof(This->sInfo)));
if ((DWORD)size < sizeof(This->sInfo))
return AVIERR_BUFFERTOOSMALL;
return AVIERR_OK;
}
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream *iface, LONG pos,
LONG flags)
{
IAVIStreamImpl *This = (IAVIStreamImpl *)iface;
LONG offset = 0;
TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);
if (flags & FIND_FROM_START) {
pos = This->sInfo.dwStart;
flags &= ~(FIND_FROM_START|FIND_PREV);
flags |= FIND_NEXT;
}
if (This->sInfo.dwSampleSize != 0) {
/* convert samples into block number with offset */
AVIFILE_SamplesToBlock(This, &pos, &offset);
}
if (flags & FIND_TYPE) {
if (flags & FIND_KEY) {
while (0 <= pos && pos <= This->lLastFrame) {
if (This->idxFrames[pos].dwFlags & AVIIF_KEYFRAME)
goto RETURN_FOUND;
if (flags & FIND_NEXT)
pos++;
else
pos--;
};
} else if (flags & FIND_ANY) {
while (0 <= pos && pos <= This->lLastFrame) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -