2 * Copyright 2003 Michael Günnewig
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.
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.
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
28 #include "avifile_private.h"
29 #include "extrachunk.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
35 /***********************************************************************/
37 typedef struct _ITmpFileImpl
{
38 IAVIFile IAVIFile_iface
;
42 PAVISTREAM
*ppStreams
;
45 static inline ITmpFileImpl
*impl_from_IAVIFile(IAVIFile
*iface
)
47 return CONTAINING_RECORD(iface
, ITmpFileImpl
, IAVIFile_iface
);
50 static HRESULT WINAPI
ITmpFile_fnQueryInterface(IAVIFile
*iface
, REFIID refiid
,
53 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
55 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(refiid
), obj
);
57 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
58 IsEqualGUID(&IID_IAVIFile
, refiid
)) {
60 IAVIFile_AddRef(iface
);
65 return OLE_E_ENUM_NOMORE
;
68 static ULONG WINAPI
ITmpFile_fnAddRef(IAVIFile
*iface
)
70 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
71 ULONG ref
= InterlockedIncrement(&This
->ref
);
73 TRACE("(%p) -> %d\n", iface
, ref
);
78 static ULONG WINAPI
ITmpFile_fnRelease(IAVIFile
*iface
)
80 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
81 ULONG ref
= InterlockedDecrement(&This
->ref
);
83 TRACE("(%p) -> %d\n", iface
, ref
);
88 for (i
= 0; i
< This
->fInfo
.dwStreams
; i
++) {
89 if (This
->ppStreams
[i
] != NULL
) {
90 AVIStreamRelease(This
->ppStreams
[i
]);
92 This
->ppStreams
[i
] = NULL
;
96 HeapFree(GetProcessHeap(), 0, This
);
102 static HRESULT WINAPI
ITmpFile_fnInfo(IAVIFile
*iface
,
103 AVIFILEINFOW
*afi
, LONG size
)
105 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
107 TRACE("(%p,%p,%d)\n",iface
,afi
,size
);
110 return AVIERR_BADPARAM
;
112 return AVIERR_BADSIZE
;
114 memcpy(afi
, &This
->fInfo
, min((DWORD
)size
, sizeof(This
->fInfo
)));
116 if ((DWORD
)size
< sizeof(This
->fInfo
))
117 return AVIERR_BUFFERTOOSMALL
;
121 static HRESULT WINAPI
ITmpFile_fnGetStream(IAVIFile
*iface
, PAVISTREAM
*avis
,
122 DWORD fccType
, LONG lParam
)
124 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
126 ULONG nStream
= (ULONG
)-1;
128 TRACE("(%p,%p,0x%08X,%d)\n", iface
, avis
, fccType
, lParam
);
130 if (avis
== NULL
|| lParam
< 0)
131 return AVIERR_BADPARAM
;
133 if (fccType
!= streamtypeANY
) {
134 /* search the number of the specified stream */
137 for (i
= 0; i
< This
->fInfo
.dwStreams
; i
++) {
138 AVISTREAMINFOW sInfo
;
141 hr
= AVIStreamInfoW(This
->ppStreams
[i
], &sInfo
, sizeof(sInfo
));
145 if (sInfo
.fccType
== fccType
) {
156 /* Does the requested stream exist ? */
157 if (nStream
< This
->fInfo
.dwStreams
&& This
->ppStreams
[nStream
] != NULL
) {
158 *avis
= This
->ppStreams
[nStream
];
159 AVIStreamAddRef(*avis
);
164 /* Sorry, but the specified stream doesn't exist */
165 return AVIERR_NODATA
;
168 static HRESULT WINAPI
ITmpFile_fnCreateStream(IAVIFile
*iface
,PAVISTREAM
*avis
,
171 TRACE("(%p,%p,%p)\n",iface
,avis
,asi
);
173 return AVIERR_UNSUPPORTED
;
176 static HRESULT WINAPI
ITmpFile_fnWriteData(IAVIFile
*iface
, DWORD ckid
,
177 LPVOID lpData
, LONG size
)
179 TRACE("(%p,0x%08X,%p,%d)\n", iface
, ckid
, lpData
, size
);
181 return AVIERR_UNSUPPORTED
;
184 static HRESULT WINAPI
ITmpFile_fnReadData(IAVIFile
*iface
, DWORD ckid
,
185 LPVOID lpData
, LONG
*size
)
187 TRACE("(%p,0x%08X,%p,%p)\n", iface
, ckid
, lpData
, size
);
189 return AVIERR_UNSUPPORTED
;
192 static HRESULT WINAPI
ITmpFile_fnEndRecord(IAVIFile
*iface
)
194 TRACE("(%p)\n",iface
);
199 static HRESULT WINAPI
ITmpFile_fnDeleteStream(IAVIFile
*iface
, DWORD fccType
,
202 TRACE("(%p,0x%08X,%d)\n", iface
, fccType
, lParam
);
204 return AVIERR_UNSUPPORTED
;
207 static const struct IAVIFileVtbl itmpft
= {
208 ITmpFile_fnQueryInterface
,
212 ITmpFile_fnGetStream
,
213 ITmpFile_fnCreateStream
,
214 ITmpFile_fnWriteData
,
216 ITmpFile_fnEndRecord
,
217 ITmpFile_fnDeleteStream
220 PAVIFILE
AVIFILE_CreateAVITempFile(int nStreams
, const PAVISTREAM
*ppStreams
)
222 ITmpFileImpl
*tmpFile
;
225 tmpFile
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ITmpFileImpl
));
229 tmpFile
->IAVIFile_iface
.lpVtbl
= &itmpft
;
231 memset(&tmpFile
->fInfo
, 0, sizeof(tmpFile
->fInfo
));
233 tmpFile
->fInfo
.dwStreams
= nStreams
;
234 tmpFile
->ppStreams
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(PAVISTREAM
));
235 if (tmpFile
->ppStreams
== NULL
) {
236 HeapFree(GetProcessHeap(), 0, tmpFile
);
240 for (i
= 0; i
< nStreams
; i
++) {
241 AVISTREAMINFOW sInfo
;
243 tmpFile
->ppStreams
[i
] = ppStreams
[i
];
245 AVIStreamAddRef(ppStreams
[i
]);
246 AVIStreamInfoW(ppStreams
[i
], &sInfo
, sizeof(sInfo
));
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;
256 if (tmpFile
->fInfo
.dwSuggestedBufferSize
< sInfo
.dwSuggestedBufferSize
)
257 tmpFile
->fInfo
.dwSuggestedBufferSize
= sInfo
.dwSuggestedBufferSize
;
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
;
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
;
276 return &tmpFile
->IAVIFile_iface
;