📄 editstream.c
字号:
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) -> %d\n", iface, ref);
if (!ref) {
/* release 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);
}
HeapFree(GetProcessHeap(), 0, This->pStreams);
}
HeapFree(GetProcessHeap(), 0, This);
return 0;
}
return ref;
}
static HRESULT WINAPI IAVIEditStream_fnCut(IAVIEditStream*iface,LONG*plStart,
LONG*plLength,PAVISTREAM*ppResult)
{
IAVIEditStreamImpl *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 = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pStreams,
(This->nTableSize + 32) * sizeof(EditStreamTable));
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)
{
IAVIEditStreamImpl *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)
{
IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
AVISTREAMINFOW srcInfo;
IEditStreamInternal*pInternal = NULL;
IAVIEditStreamImpl *pEdit = NULL;
PAVISTREAM pStream;
DWORD startPos, endPos, streamNr, nStreams;
ULONG n;
TRACE("(%p,%p,%p,%p,%d,%d)\n",iface,plStart,plLength,
pSource,lStart,lLength);
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; /* 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 == 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)
return AVIERR_MEMORY;
/* streamtype specific tests */
if (srcInfo.fccType == streamtypeVIDEO) {
LONG 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*)&pInternal))) {
pInternal->lpVtbl->GetEditStreamImpl(pInternal, (LPVOID*)&pEdit);
pInternal->lpVtbl->Release(pInternal);
}
/* 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);
/* 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 = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pStreams, n * sizeof(EditStreamTable));
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,
PAVISTREAM*ppResult)
{
IAVIEditStreamImpl *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 = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pEdit->pStreams,
This->nStreams * sizeof(EditStreamTable));
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)
{
IAVIEditStreamImpl *This = (IAVIEditStreamImpl *)iface;
TRACE("(%p,%p,%d)\n",iface,asi,size);
/* check parameters */
if (asi == NULL)
return AVIERR_BADPARAM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -