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