Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/avifil32/tmpfile.c
4389 views
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) -> %ld\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) -> %ld\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
free(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,%ld)\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%08lX,%ld)\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%08lX,%p,%ld)\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%08lX,%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%08lX,%ld)\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 = calloc(1, 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 = malloc(nStreams * sizeof(PAVISTREAM));
235
if (tmpFile->ppStreams == NULL) {
236
free(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
279