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