1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright 2003 Michael Günnewig
3c2c66affSColin Finck *
4c2c66affSColin Finck * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck * License as published by the Free Software Foundation; either
7c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck *
9c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12c2c66affSColin Finck * Lesser General Public License for more details.
13c2c66affSColin Finck *
14c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck */
18c2c66affSColin Finck
19*44836a6eSAmine Khaldi #include <stdarg.h>
20*44836a6eSAmine Khaldi
21*44836a6eSAmine Khaldi #include "windef.h"
22*44836a6eSAmine Khaldi #include "winbase.h"
23*44836a6eSAmine Khaldi #include "wingdi.h"
24*44836a6eSAmine Khaldi #include "winuser.h"
25*44836a6eSAmine Khaldi #include "winerror.h"
26*44836a6eSAmine Khaldi #include "vfw.h"
27*44836a6eSAmine Khaldi
28c2c66affSColin Finck #include "avifile_private.h"
29*44836a6eSAmine Khaldi #include "extrachunk.h"
30*44836a6eSAmine Khaldi
31*44836a6eSAmine Khaldi #include "wine/debug.h"
32*44836a6eSAmine Khaldi
33*44836a6eSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(avifile);
34c2c66affSColin Finck
35c2c66affSColin Finck /***********************************************************************/
36c2c66affSColin Finck
37c2c66affSColin Finck typedef struct _ITmpFileImpl {
38c2c66affSColin Finck IAVIFile IAVIFile_iface;
39c2c66affSColin Finck LONG ref;
40c2c66affSColin Finck
41c2c66affSColin Finck AVIFILEINFOW fInfo;
42c2c66affSColin Finck PAVISTREAM *ppStreams;
43c2c66affSColin Finck } ITmpFileImpl;
44c2c66affSColin Finck
impl_from_IAVIFile(IAVIFile * iface)45c2c66affSColin Finck static inline ITmpFileImpl *impl_from_IAVIFile(IAVIFile *iface)
46c2c66affSColin Finck {
47c2c66affSColin Finck return CONTAINING_RECORD(iface, ITmpFileImpl, IAVIFile_iface);
48c2c66affSColin Finck }
49c2c66affSColin Finck
ITmpFile_fnQueryInterface(IAVIFile * iface,REFIID refiid,LPVOID * obj)50c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnQueryInterface(IAVIFile *iface, REFIID refiid,
51c2c66affSColin Finck LPVOID *obj)
52c2c66affSColin Finck {
53c2c66affSColin Finck ITmpFileImpl *This = impl_from_IAVIFile(iface);
54c2c66affSColin Finck
55c2c66affSColin Finck TRACE("(%p,%s,%p)\n", This, debugstr_guid(refiid), obj);
56c2c66affSColin Finck
57c2c66affSColin Finck if (IsEqualGUID(&IID_IUnknown, refiid) ||
58c2c66affSColin Finck IsEqualGUID(&IID_IAVIFile, refiid)) {
59c2c66affSColin Finck *obj = iface;
60c2c66affSColin Finck IAVIFile_AddRef(iface);
61c2c66affSColin Finck
62c2c66affSColin Finck return S_OK;
63c2c66affSColin Finck }
64c2c66affSColin Finck
65c2c66affSColin Finck return OLE_E_ENUM_NOMORE;
66c2c66affSColin Finck }
67c2c66affSColin Finck
ITmpFile_fnAddRef(IAVIFile * iface)68c2c66affSColin Finck static ULONG WINAPI ITmpFile_fnAddRef(IAVIFile *iface)
69c2c66affSColin Finck {
70c2c66affSColin Finck ITmpFileImpl *This = impl_from_IAVIFile(iface);
71c2c66affSColin Finck ULONG ref = InterlockedIncrement(&This->ref);
72c2c66affSColin Finck
73c2c66affSColin Finck TRACE("(%p) -> %d\n", iface, ref);
74c2c66affSColin Finck
75c2c66affSColin Finck return ref;
76c2c66affSColin Finck }
77c2c66affSColin Finck
ITmpFile_fnRelease(IAVIFile * iface)78c2c66affSColin Finck static ULONG WINAPI ITmpFile_fnRelease(IAVIFile *iface)
79c2c66affSColin Finck {
80c2c66affSColin Finck ITmpFileImpl *This = impl_from_IAVIFile(iface);
81c2c66affSColin Finck ULONG ref = InterlockedDecrement(&This->ref);
82c2c66affSColin Finck
83c2c66affSColin Finck TRACE("(%p) -> %d\n", iface, ref);
84c2c66affSColin Finck
85c2c66affSColin Finck if (!ref) {
86c2c66affSColin Finck unsigned int i;
87c2c66affSColin Finck
88c2c66affSColin Finck for (i = 0; i < This->fInfo.dwStreams; i++) {
89c2c66affSColin Finck if (This->ppStreams[i] != NULL) {
90c2c66affSColin Finck AVIStreamRelease(This->ppStreams[i]);
91c2c66affSColin Finck
92c2c66affSColin Finck This->ppStreams[i] = NULL;
93c2c66affSColin Finck }
94c2c66affSColin Finck }
95c2c66affSColin Finck
96c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
97c2c66affSColin Finck }
98c2c66affSColin Finck
99c2c66affSColin Finck return ref;
100c2c66affSColin Finck }
101c2c66affSColin Finck
ITmpFile_fnInfo(IAVIFile * iface,AVIFILEINFOW * afi,LONG size)102c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnInfo(IAVIFile *iface,
103c2c66affSColin Finck AVIFILEINFOW *afi, LONG size)
104c2c66affSColin Finck {
105c2c66affSColin Finck ITmpFileImpl *This = impl_from_IAVIFile(iface);
106c2c66affSColin Finck
107c2c66affSColin Finck TRACE("(%p,%p,%d)\n",iface,afi,size);
108c2c66affSColin Finck
109c2c66affSColin Finck if (afi == NULL)
110c2c66affSColin Finck return AVIERR_BADPARAM;
111c2c66affSColin Finck if (size < 0)
112c2c66affSColin Finck return AVIERR_BADSIZE;
113c2c66affSColin Finck
114c2c66affSColin Finck memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
115c2c66affSColin Finck
116c2c66affSColin Finck if ((DWORD)size < sizeof(This->fInfo))
117c2c66affSColin Finck return AVIERR_BUFFERTOOSMALL;
118c2c66affSColin Finck return AVIERR_OK;
119c2c66affSColin Finck }
120c2c66affSColin Finck
ITmpFile_fnGetStream(IAVIFile * iface,PAVISTREAM * avis,DWORD fccType,LONG lParam)121c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnGetStream(IAVIFile *iface, PAVISTREAM *avis,
122c2c66affSColin Finck DWORD fccType, LONG lParam)
123c2c66affSColin Finck {
124c2c66affSColin Finck ITmpFileImpl *This = impl_from_IAVIFile(iface);
125c2c66affSColin Finck
126c2c66affSColin Finck ULONG nStream = (ULONG)-1;
127c2c66affSColin Finck
128c2c66affSColin Finck TRACE("(%p,%p,0x%08X,%d)\n", iface, avis, fccType, lParam);
129c2c66affSColin Finck
130c2c66affSColin Finck if (avis == NULL || lParam < 0)
131c2c66affSColin Finck return AVIERR_BADPARAM;
132c2c66affSColin Finck
133c2c66affSColin Finck if (fccType != streamtypeANY) {
134c2c66affSColin Finck /* search the number of the specified stream */
135c2c66affSColin Finck ULONG i;
136c2c66affSColin Finck
137c2c66affSColin Finck for (i = 0; i < This->fInfo.dwStreams; i++) {
138c2c66affSColin Finck AVISTREAMINFOW sInfo;
139c2c66affSColin Finck HRESULT hr;
140c2c66affSColin Finck
141c2c66affSColin Finck hr = AVIStreamInfoW(This->ppStreams[i], &sInfo, sizeof(sInfo));
142c2c66affSColin Finck if (FAILED(hr))
143c2c66affSColin Finck return hr;
144c2c66affSColin Finck
145c2c66affSColin Finck if (sInfo.fccType == fccType) {
146c2c66affSColin Finck if (lParam == 0) {
147c2c66affSColin Finck nStream = i;
148c2c66affSColin Finck break;
149c2c66affSColin Finck } else
150c2c66affSColin Finck lParam--;
151c2c66affSColin Finck }
152c2c66affSColin Finck }
153c2c66affSColin Finck } else
154c2c66affSColin Finck nStream = lParam;
155c2c66affSColin Finck
156c2c66affSColin Finck /* Does the requested stream exist ? */
157c2c66affSColin Finck if (nStream < This->fInfo.dwStreams && This->ppStreams[nStream] != NULL) {
158c2c66affSColin Finck *avis = This->ppStreams[nStream];
159c2c66affSColin Finck AVIStreamAddRef(*avis);
160c2c66affSColin Finck
161c2c66affSColin Finck return AVIERR_OK;
162c2c66affSColin Finck }
163c2c66affSColin Finck
164c2c66affSColin Finck /* Sorry, but the specified stream doesn't exist */
165c2c66affSColin Finck return AVIERR_NODATA;
166c2c66affSColin Finck }
167c2c66affSColin Finck
ITmpFile_fnCreateStream(IAVIFile * iface,PAVISTREAM * avis,AVISTREAMINFOW * asi)168c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnCreateStream(IAVIFile *iface,PAVISTREAM *avis,
169c2c66affSColin Finck AVISTREAMINFOW *asi)
170c2c66affSColin Finck {
171c2c66affSColin Finck TRACE("(%p,%p,%p)\n",iface,avis,asi);
172c2c66affSColin Finck
173c2c66affSColin Finck return AVIERR_UNSUPPORTED;
174c2c66affSColin Finck }
175c2c66affSColin Finck
ITmpFile_fnWriteData(IAVIFile * iface,DWORD ckid,LPVOID lpData,LONG size)176c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnWriteData(IAVIFile *iface, DWORD ckid,
177c2c66affSColin Finck LPVOID lpData, LONG size)
178c2c66affSColin Finck {
179c2c66affSColin Finck TRACE("(%p,0x%08X,%p,%d)\n", iface, ckid, lpData, size);
180c2c66affSColin Finck
181c2c66affSColin Finck return AVIERR_UNSUPPORTED;
182c2c66affSColin Finck }
183c2c66affSColin Finck
ITmpFile_fnReadData(IAVIFile * iface,DWORD ckid,LPVOID lpData,LONG * size)184c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnReadData(IAVIFile *iface, DWORD ckid,
185c2c66affSColin Finck LPVOID lpData, LONG *size)
186c2c66affSColin Finck {
187c2c66affSColin Finck TRACE("(%p,0x%08X,%p,%p)\n", iface, ckid, lpData, size);
188c2c66affSColin Finck
189c2c66affSColin Finck return AVIERR_UNSUPPORTED;
190c2c66affSColin Finck }
191c2c66affSColin Finck
ITmpFile_fnEndRecord(IAVIFile * iface)192c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnEndRecord(IAVIFile *iface)
193c2c66affSColin Finck {
194c2c66affSColin Finck TRACE("(%p)\n",iface);
195c2c66affSColin Finck
196c2c66affSColin Finck return AVIERR_OK;
197c2c66affSColin Finck }
198c2c66affSColin Finck
ITmpFile_fnDeleteStream(IAVIFile * iface,DWORD fccType,LONG lParam)199c2c66affSColin Finck static HRESULT WINAPI ITmpFile_fnDeleteStream(IAVIFile *iface, DWORD fccType,
200c2c66affSColin Finck LONG lParam)
201c2c66affSColin Finck {
202c2c66affSColin Finck TRACE("(%p,0x%08X,%d)\n", iface, fccType, lParam);
203c2c66affSColin Finck
204c2c66affSColin Finck return AVIERR_UNSUPPORTED;
205c2c66affSColin Finck }
206c2c66affSColin Finck
207c2c66affSColin Finck static const struct IAVIFileVtbl itmpft = {
208c2c66affSColin Finck ITmpFile_fnQueryInterface,
209c2c66affSColin Finck ITmpFile_fnAddRef,
210c2c66affSColin Finck ITmpFile_fnRelease,
211c2c66affSColin Finck ITmpFile_fnInfo,
212c2c66affSColin Finck ITmpFile_fnGetStream,
213c2c66affSColin Finck ITmpFile_fnCreateStream,
214c2c66affSColin Finck ITmpFile_fnWriteData,
215c2c66affSColin Finck ITmpFile_fnReadData,
216c2c66affSColin Finck ITmpFile_fnEndRecord,
217c2c66affSColin Finck ITmpFile_fnDeleteStream
218c2c66affSColin Finck };
219c2c66affSColin Finck
AVIFILE_CreateAVITempFile(int nStreams,const PAVISTREAM * ppStreams)220c2c66affSColin Finck PAVIFILE AVIFILE_CreateAVITempFile(int nStreams, const PAVISTREAM *ppStreams)
221c2c66affSColin Finck {
222c2c66affSColin Finck ITmpFileImpl *tmpFile;
223c2c66affSColin Finck int i;
224c2c66affSColin Finck
225c2c66affSColin Finck tmpFile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITmpFileImpl));
226c2c66affSColin Finck if (tmpFile == NULL)
227c2c66affSColin Finck return NULL;
228c2c66affSColin Finck
229c2c66affSColin Finck tmpFile->IAVIFile_iface.lpVtbl = &itmpft;
230c2c66affSColin Finck tmpFile->ref = 1;
231c2c66affSColin Finck memset(&tmpFile->fInfo, 0, sizeof(tmpFile->fInfo));
232c2c66affSColin Finck
233c2c66affSColin Finck tmpFile->fInfo.dwStreams = nStreams;
234c2c66affSColin Finck tmpFile->ppStreams = HeapAlloc(GetProcessHeap(), 0, nStreams * sizeof(PAVISTREAM));
235c2c66affSColin Finck if (tmpFile->ppStreams == NULL) {
236c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, tmpFile);
237c2c66affSColin Finck return NULL;
238c2c66affSColin Finck }
239c2c66affSColin Finck
240c2c66affSColin Finck for (i = 0; i < nStreams; i++) {
241c2c66affSColin Finck AVISTREAMINFOW sInfo;
242c2c66affSColin Finck
243c2c66affSColin Finck tmpFile->ppStreams[i] = ppStreams[i];
244c2c66affSColin Finck
245c2c66affSColin Finck AVIStreamAddRef(ppStreams[i]);
246c2c66affSColin Finck AVIStreamInfoW(ppStreams[i], &sInfo, sizeof(sInfo));
247c2c66affSColin Finck if (i == 0) {
248c2c66affSColin Finck tmpFile->fInfo.dwScale = sInfo.dwScale;
249c2c66affSColin Finck tmpFile->fInfo.dwRate = sInfo.dwRate;
250c2c66affSColin Finck if (!sInfo.dwScale || !sInfo.dwRate) {
251c2c66affSColin Finck tmpFile->fInfo.dwScale = 1;
252c2c66affSColin Finck tmpFile->fInfo.dwRate = 100;
253c2c66affSColin Finck }
254c2c66affSColin Finck }
255c2c66affSColin Finck
256c2c66affSColin Finck if (tmpFile->fInfo.dwSuggestedBufferSize < sInfo.dwSuggestedBufferSize)
257c2c66affSColin Finck tmpFile->fInfo.dwSuggestedBufferSize = sInfo.dwSuggestedBufferSize;
258c2c66affSColin Finck
259c2c66affSColin Finck {
260c2c66affSColin Finck DWORD tmp;
261c2c66affSColin Finck
262c2c66affSColin Finck tmp = MulDiv(AVIStreamSampleToTime(ppStreams[i], sInfo.dwLength),
263c2c66affSColin Finck tmpFile->fInfo.dwScale, tmpFile->fInfo.dwRate * 1000);
264c2c66affSColin Finck if (tmpFile->fInfo.dwLength < tmp)
265c2c66affSColin Finck tmpFile->fInfo.dwLength = tmp;
266c2c66affSColin Finck
267c2c66affSColin Finck tmp = sInfo.rcFrame.right - sInfo.rcFrame.left;
268c2c66affSColin Finck if (tmpFile->fInfo.dwWidth < tmp)
269c2c66affSColin Finck tmpFile->fInfo.dwWidth = tmp;
270c2c66affSColin Finck tmp = sInfo.rcFrame.bottom - sInfo.rcFrame.top;
271c2c66affSColin Finck if (tmpFile->fInfo.dwHeight < tmp)
272c2c66affSColin Finck tmpFile->fInfo.dwHeight = tmp;
273c2c66affSColin Finck }
274c2c66affSColin Finck }
275c2c66affSColin Finck
276c2c66affSColin Finck return &tmpFile->IAVIFile_iface;
277c2c66affSColin Finck }
278