2 * Copyright 2003 Michael Günnewig
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "avifile_private.h"
32 #include "extrachunk.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(avifile);
38 /***********************************************************************/
40 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
41 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile* iface);
42 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile* iface);
43 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
44 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
45 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
46 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
47 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
48 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile*iface);
49 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
51 static const struct IAVIFileVtbl itmpft = {
52 ITmpFile_fnQueryInterface,
57 ITmpFile_fnCreateStream,
61 ITmpFile_fnDeleteStream
64 typedef struct _ITmpFileImpl {
66 const IAVIFileVtbl *lpVtbl;
71 PAVISTREAM *ppStreams;
74 PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, PAVISTREAM *ppStreams) {
75 ITmpFileImpl *tmpFile;
78 tmpFile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITmpFileImpl));
82 tmpFile->lpVtbl = &itmpft;
84 memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
86 tmpFile->fInfo.dwStreams = nStreams;
87 tmpFile->ppStreams = HeapAlloc(GetProcessHeap(), 0, nStreams * sizeof(PAVISTREAM));
88 if (tmpFile->ppStreams == NULL) {
89 HeapFree(GetProcessHeap(), 0, tmpFile);
93 for (i = 0; i < nStreams; i++) {
96 tmpFile->ppStreams[i] = ppStreams[i];
98 AVIStreamAddRef(ppStreams[i]);
99 AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
101 tmpFile->fInfo.dwScale = sInfo.dwScale;
102 tmpFile->fInfo.dwRate = sInfo.dwRate;
103 if (!sInfo.dwScale || !sInfo.dwRate) {
104 tmpFile->fInfo.dwScale = 1;
105 tmpFile->fInfo.dwRate = 100;
109 if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
110 tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
115 tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength), \
116 tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
117 if (tmpFile->fInfo.dwLength < tmp)
118 tmpFile->fInfo.dwLength = tmp;
120 tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
121 if (tmpFile->fInfo.dwWidth < tmp)
122 tmpFile->fInfo.dwWidth = tmp;
123 tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
124 if (tmpFile->fInfo.dwHeight < tmp)
125 tmpFile->fInfo.dwHeight = tmp;
129 return (PAVIFILE)tmpFile;
132 static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
135 ITmpFileImpl *This = (ITmpFileImpl *)iface;
137 TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
139 if (IsEqualGUID(&IID_IUnknown, refiid) ||
140 IsEqualGUID(&IID_IAVIFile, refiid)) {
142 IAVIFile_AddRef(iface);
147 return OLE_E_ENUM_NOMORE;
150 static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
152 ITmpFileImpl *This = (ITmpFileImpl *)iface;
153 ULONG ref = InterlockedIncrement(&This->ref);
155 TRACE("(%p) -> %d\n", iface, ref);
160 static ULONG WINAPI ITmpFile_fnRelease(IAVIFile *iface)
162 ITmpFileImpl *This = (ITmpFileImpl *)iface;
163 ULONG ref = InterlockedDecrement(&This->ref);
165 TRACE("(%p) -> %d\n", iface, ref);
170 for (i = 0; i < This->fInfo.dwStreams; i++) {
171 if (This->ppStreams[i] != NULL) {
172 AVIStreamRelease(This->ppStreams[i]);
174 This->ppStreams[i] = NULL;
178 HeapFree(GetProcessHeap(), 0, This);
185 static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
186 AVIFILEINFOW *afi, LONG size)
188 ITmpFileImpl *This = (ITmpFileImpl *)iface;
190 TRACE("(%p,%p,%d)\n",iface,afi,size);
193 return AVIERR_BADPARAM;
195 return AVIERR_BADSIZE;
197 memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
199 if ((DWORD)size < sizeof(This->fInfo))
200 return AVIERR_BUFFERTOOSMALL;
204 static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
205 DWORD fccType, LONG lParam)
207 ITmpFileImpl *This = (ITmpFileImpl *)iface;
209 ULONG nStream = (ULONG)-1;
211 TRACE("(%p,%p,0x%08X,%d)\n", iface, avis, fccType, lParam);
213 if (avis == NULL || lParam < 0)
214 return AVIERR_BADPARAM;
216 if (fccType != streamtypeANY) {
217 /* search the number of the specified stream */
220 for (i = 0; i < This->fInfo.dwStreams; i++) {
221 AVISTREAMINFOW sInfo;
224 hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
228 if (sInfo.fccType == fccType) {
239 /* Does the requested stream exist ? */
240 if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
241 *avis = This->ppStreams[nStream];
242 AVIStreamAddRef(*avis);
247 /* Sorry, but the specified stream doesn't exist */
248 return AVIERR_NODATA;
251 static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
254 TRACE("(%p,%p,%p)\n",iface,avis,asi);
256 return AVIERR_UNSUPPORTED;
259 static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
260 LPVOID lpData, LONG size)
262 TRACE("(%p,0x%08X,%p,%d)\n", iface, ckid, lpData, size);
264 return AVIERR_UNSUPPORTED;
267 static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
268 LPVOID lpData, LONG *size)
270 TRACE("(%p,0x%08X,%p,%p)\n", iface, ckid, lpData, size);
272 return AVIERR_UNSUPPORTED;
275 static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
277 TRACE("(%p)\n",iface);
282 static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
285 TRACE("(%p,0x%08X,%d)\n", iface, fccType, lParam);
287 return AVIERR_UNSUPPORTED;