xref: /reactos/dll/win32/avifil32/tmpfile.c (revision 44836a6e)
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