* Sync up to trunk head (r64829).
[reactos.git] / dll / win32 / avifil32 / tmpfile.c
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 }