static HRESULT WINAPI IEditAVIStream_fnCreate(IAVIStream*iface, LPARAM lParam1,LPARAM lParam2) { IAVIEditStreamImpl *This = impl_from_IAVIStream( iface ); if (lParam2 != 0) return AVIERR_ERROR; if (This->pStreams == NULL) { This->pStreams = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 256 * sizeof(EditStreamTable)); if (This->pStreams == NULL) return AVIERR_MEMORY; This->nTableSize = 256; } if (lParam1 != 0) { IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo)); IAVIStream_AddRef((PAVISTREAM)lParam1); This->pStreams[0].pStream = (PAVISTREAM)lParam1; This->pStreams[0].dwStart = This->sInfo.dwStart; This->pStreams[0].dwLength = This->sInfo.dwLength; This->nStreams = 1; } return AVIERR_OK; }
/* lParam1: PAVISTREAM * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT */ static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1, LPARAM lParam2) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2); /* check for swapped parameters */ if ((LPVOID)lParam1 != NULL && ((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) { register LPARAM tmp = lParam1; lParam1 = lParam2; lParam2 = tmp; } if ((LPVOID)lParam1 == NULL) return AVIERR_BADPARAM; IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo)); if (This->sInfo.fccType != streamtypeAUDIO) return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */ This->sInfo.fccHandler = 0; /* be paranoid */ /* FIXME: check ACM version? Which version does we need? */ if ((LPVOID)lParam2 != NULL) { /* We only need the format from the compress-options */ if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO) lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat; if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM) This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize; else This->cbOutFormat = sizeof(PCMWAVEFORMAT); This->lpOutFormat = HeapAlloc(GetProcessHeap(), 0, This->cbOutFormat); if (This->lpOutFormat == NULL) return AVIERR_MEMORY; memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat); } else { This->lpOutFormat = NULL; This->cbOutFormat = 0; } This->pStream = (PAVISTREAM)lParam1; IAVIStream_AddRef(This->pStream); return AVIERR_OK; }
static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface) { IAVIStreamImpl *This = (IAVIStreamImpl *)iface; ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) -> %d\n", iface, ref); /* also add reference to the nested stream */ if (This->pStream != NULL) IAVIStream_AddRef(This->pStream); return ref; }
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile *iface, IAVIStream **avis, AVISTREAMINFOW *asi) { IAVIFileImpl *This = impl_from_IAVIFile(iface); TRACE("(%p,%p,%p)\n", iface, avis, asi); /* check parameters */ if (avis == NULL || asi == NULL) return AVIERR_BADPARAM; *avis = NULL; /* We only support one audio stream */ if (This->fInfo.dwStreams != 0 || This->lpFormat != NULL) return AVIERR_UNSUPPORTED; if (asi->fccType != streamtypeAUDIO) return AVIERR_UNSUPPORTED; /* Does the user have write permission? */ if ((This->uMode & MMIO_RWMODE) == 0) return AVIERR_READONLY; This->cbFormat = 0; This->lpFormat = NULL; memcpy(&This->sInfo, asi, sizeof(This->sInfo)); /* make sure streaminfo if okay for us */ This->sInfo.fccHandler = 0; This->sInfo.dwFlags = 0; This->sInfo.dwCaps = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE; This->sInfo.dwStart = 0; This->sInfo.dwInitialFrames = 0; This->sInfo.dwFormatChangeCount = 0; memset(&This->sInfo.rcFrame, 0, sizeof(This->sInfo.rcFrame)); This->fInfo.dwStreams = 1; This->fInfo.dwScale = This->sInfo.dwScale; This->fInfo.dwRate = This->sInfo.dwRate; This->fInfo.dwLength = This->sInfo.dwLength; This->ckData.dwDataOffset = 0; This->ckData.cksize = 0; *avis = &This->IAVIStream_iface; IAVIStream_AddRef(*avis); return AVIERR_OK; }
static HRESULT WINAPI ACMStream_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; } return OLE_E_ENUM_NOMORE; }
PGETFRAME AVIFILE_CreateGetFrame(PAVISTREAM pStream) { IGetFrameImpl *pg; /* check parameter */ if (pStream == NULL) return NULL; pg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGetFrameImpl)); if (pg != NULL) { pg->IGetFrame_iface.lpVtbl = &igetframeVtbl; pg->ref = 1; pg->lCurrentFrame = -1; pg->pStream = pStream; IAVIStream_AddRef(pStream); } return &pg->IGetFrame_iface; }
static HRESULT WINAPI IAVIEditStream_fnClone(IAVIEditStream*iface, PAVISTREAM*ppResult) { IAVIEditStreamImpl *This = impl_from_IAVIEditStream(iface); IAVIEditStreamImpl* pEdit; DWORD i; TRACE("(%p,%p)\n",iface,ppResult); if (ppResult == NULL) return AVIERR_BADPARAM; *ppResult = NULL; pEdit = 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 = &This->IAVIStream_iface; return AVIERR_OK; }
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile *iface, IAVIStream **avis, DWORD fccType, LONG lParam) { IAVIFileImpl *This = impl_from_IAVIFile(iface); TRACE("(%p,%p,0x%08X,%d)\n", iface, avis, fccType, lParam); /* check parameter */ if (avis == NULL) return AVIERR_BADPARAM; *avis = NULL; /* Does our stream exists? */ if (lParam != 0 || This->fInfo.dwStreams == 0) return AVIERR_NODATA; if (fccType != 0 && fccType != streamtypeAUDIO) return AVIERR_NODATA; *avis = &This->IAVIStream_iface; IAVIStream_AddRef(*avis); return AVIERR_OK; }
static HRESULT WINAPI IAVIEditStream_fnPaste(IAVIEditStream*iface,LONG*plStart, LONG*plLength,PAVISTREAM pSource, LONG lStart,LONG lLength) { IAVIEditStreamImpl *This = impl_from_IAVIEditStream(iface); AVISTREAMINFOW srcInfo; 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(&This->IAVIStream_iface, 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*)&pEdit))) IAVIEditStream_Release(&pEdit->IAVIEditStream_iface); /* pSource holds a reference */ /* 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(&This->IAVIStream_iface, *plStart) != *plStart || (This->nStreams > 0 && !AVIFILE_FormatsEqual(&This->IAVIStream_iface, 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 desired 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_fnCut(IAVIEditStream*iface,LONG*plStart, LONG*plLength,PAVISTREAM*ppResult) { IAVIEditStreamImpl *This = impl_from_IAVIEditStream(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 cut 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; }
/* lParam1: PAVISTREAM * lParam2: LPAVICOMPRESSOPTIONS */ static HRESULT WINAPI ICMStream_fnCreate(IAVIStream *iface, LPARAM lParam1, LPARAM lParam2) { IAVIStreamImpl *This = impl_from_IAVIStream(iface); ICINFO icinfo; ICCOMPRESSFRAMES icFrames; LPAVICOMPRESSOPTIONS pco = (LPAVICOMPRESSOPTIONS)lParam2; TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2); /* check parameter */ if ((LPVOID)lParam1 == NULL) return AVIERR_BADPARAM; /* get infos from stream */ IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo)); if (This->sInfo.fccType != streamtypeVIDEO) return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */ /* add reference to the stream */ This->pStream = (PAVISTREAM)lParam1; IAVIStream_AddRef(This->pStream); AVIFILE_Reset(This); if (pco != NULL && pco->fccHandler != comptypeDIB) { /* we should compress */ This->sInfo.fccHandler = pco->fccHandler; This->hic = ICOpen(ICTYPE_VIDEO, pco->fccHandler, ICMODE_COMPRESS); if (This->hic == NULL) return AVIERR_NOCOMPRESSOR; /* restore saved state of codec */ if (pco->cbParms > 0 && pco->lpParms != NULL) { ICSetState(This->hic, pco->lpParms, pco->cbParms); } /* set quality -- resolve default quality */ This->sInfo.dwQuality = pco->dwQuality; if (pco->dwQuality == ICQUALITY_DEFAULT) This->sInfo.dwQuality = ICGetDefaultQuality(This->hic); /* get capabilities of codec */ ICGetInfo(This->hic, &icinfo, sizeof(icinfo)); This->dwICMFlags = icinfo.dwFlags; /* use keyframes? */ if ((pco->dwFlags & AVICOMPRESSF_KEYFRAMES) && (icinfo.dwFlags & (VIDCF_TEMPORAL|VIDCF_FASTTEMPORALC))) { This->lKeyFrameEvery = pco->dwKeyFrameEvery; } else This->lKeyFrameEvery = 1; /* use datarate? */ if ((pco->dwFlags & AVICOMPRESSF_DATARATE)) { /* Do we have a chance to reduce size to desired one? */ if ((icinfo.dwFlags & (VIDCF_CRUNCH|VIDCF_QUALITY)) == 0) return AVIERR_NOCOMPRESSOR; assert(This->sInfo.dwRate != 0); This->dwBytesPerFrame = MulDiv(pco->dwBytesPerSecond, This->sInfo.dwScale, This->sInfo.dwRate); } else { pco->dwBytesPerSecond = 0; This->dwBytesPerFrame = 0; } if (icinfo.dwFlags & VIDCF_COMPRESSFRAMES) { memset(&icFrames, 0, sizeof(icFrames)); icFrames.lpbiOutput = This->lpbiOutput; icFrames.lpbiInput = This->lpbiInput; icFrames.lFrameCount = This->sInfo.dwLength; icFrames.lQuality = This->sInfo.dwQuality; icFrames.lDataRate = pco->dwBytesPerSecond; icFrames.lKeyRate = This->lKeyFrameEvery; icFrames.dwRate = This->sInfo.dwRate; icFrames.dwScale = This->sInfo.dwScale; ICSendMessage(This->hic, ICM_COMPRESS_FRAMES_INFO, (LPARAM)&icFrames, (LPARAM)sizeof(icFrames)); } } else This->sInfo.fccHandler = comptypeDIB; return AVIERR_OK; }