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
19 #include "avifile_private.h"
21 /***********************************************************************/
23 typedef struct _ITmpFileImpl
{
24 IAVIFile IAVIFile_iface
;
28 PAVISTREAM
*ppStreams
;
31 static inline ITmpFileImpl
*impl_from_IAVIFile(IAVIFile
*iface
)
33 return CONTAINING_RECORD(iface
, ITmpFileImpl
, IAVIFile_iface
);
36 static HRESULT WINAPI
ITmpFile_fnQueryInterface(IAVIFile
*iface
, REFIID refiid
,
39 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
41 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(refiid
), obj
);
43 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
44 IsEqualGUID(&IID_IAVIFile
, refiid
)) {
46 IAVIFile_AddRef(iface
);
51 return OLE_E_ENUM_NOMORE
;
54 static ULONG WINAPI
ITmpFile_fnAddRef(IAVIFile
*iface
)
56 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
57 ULONG ref
= InterlockedIncrement(&This
->ref
);
59 TRACE("(%p) -> %d\n", iface
, ref
);
64 static ULONG WINAPI
ITmpFile_fnRelease(IAVIFile
*iface
)
66 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
67 ULONG ref
= InterlockedDecrement(&This
->ref
);
69 TRACE("(%p) -> %d\n", iface
, ref
);
74 for (i
= 0; i
< This
->fInfo
.dwStreams
; i
++) {
75 if (This
->ppStreams
[i
] != NULL
) {
76 AVIStreamRelease(This
->ppStreams
[i
]);
78 This
->ppStreams
[i
] = NULL
;
82 HeapFree(GetProcessHeap(), 0, This
);
89 static HRESULT WINAPI
ITmpFile_fnInfo(IAVIFile
*iface
,
90 AVIFILEINFOW
*afi
, LONG size
)
92 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
94 TRACE("(%p,%p,%d)\n",iface
,afi
,size
);
97 return AVIERR_BADPARAM
;
99 return AVIERR_BADSIZE
;
101 memcpy(afi
, &This
->fInfo
, min((DWORD
)size
, sizeof(This
->fInfo
)));
103 if ((DWORD
)size
< sizeof(This
->fInfo
))
104 return AVIERR_BUFFERTOOSMALL
;
108 static HRESULT WINAPI
ITmpFile_fnGetStream(IAVIFile
*iface
, PAVISTREAM
*avis
,
109 DWORD fccType
, LONG lParam
)
111 ITmpFileImpl
*This
= impl_from_IAVIFile(iface
);
113 ULONG nStream
= (ULONG
)-1;
115 TRACE("(%p,%p,0x%08X,%d)\n", iface
, avis
, fccType
, lParam
);
117 if (avis
== NULL
|| lParam
< 0)
118 return AVIERR_BADPARAM
;
120 if (fccType
!= streamtypeANY
) {
121 /* search the number of the specified stream */
124 for (i
= 0; i
< This
->fInfo
.dwStreams
; i
++) {
125 AVISTREAMINFOW sInfo
;
128 hr
= AVIStreamInfoW(This
->ppStreams
[i
], &sInfo
, sizeof(sInfo
));
132 if (sInfo
.fccType
== fccType
) {
143 /* Does the requested stream exist ? */
144 if (nStream
< This
->fInfo
.dwStreams
&& This
->ppStreams
[nStream
] != NULL
) {
145 *avis
= This
->ppStreams
[nStream
];
146 AVIStreamAddRef(*avis
);
151 /* Sorry, but the specified stream doesn't exist */
152 return AVIERR_NODATA
;
155 static HRESULT WINAPI
ITmpFile_fnCreateStream(IAVIFile
*iface
,PAVISTREAM
*avis
,
158 TRACE("(%p,%p,%p)\n",iface
,avis
,asi
);
160 return AVIERR_UNSUPPORTED
;
163 static HRESULT WINAPI
ITmpFile_fnWriteData(IAVIFile
*iface
, DWORD ckid
,
164 LPVOID lpData
, LONG size
)
166 TRACE("(%p,0x%08X,%p,%d)\n", iface
, ckid
, lpData
, size
);
168 return AVIERR_UNSUPPORTED
;
171 static HRESULT WINAPI
ITmpFile_fnReadData(IAVIFile
*iface
, DWORD ckid
,
172 LPVOID lpData
, LONG
*size
)
174 TRACE("(%p,0x%08X,%p,%p)\n", iface
, ckid
, lpData
, size
);
176 return AVIERR_UNSUPPORTED
;
179 static HRESULT WINAPI
ITmpFile_fnEndRecord(IAVIFile
*iface
)
181 TRACE("(%p)\n",iface
);
186 static HRESULT WINAPI
ITmpFile_fnDeleteStream(IAVIFile
*iface
, DWORD fccType
,
189 TRACE("(%p,0x%08X,%d)\n", iface
, fccType
, lParam
);
191 return AVIERR_UNSUPPORTED
;
194 static const struct IAVIFileVtbl itmpft
= {
195 ITmpFile_fnQueryInterface
,
199 ITmpFile_fnGetStream
,
200 ITmpFile_fnCreateStream
,
201 ITmpFile_fnWriteData
,
203 ITmpFile_fnEndRecord
,
204 ITmpFile_fnDeleteStream
207 PAVIFILE
AVIFILE_CreateAVITempFile(int nStreams
, const PAVISTREAM
*ppStreams
)
209 ITmpFileImpl
*tmpFile
;
212 tmpFile
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ITmpFileImpl
));
216 tmpFile
->IAVIFile_iface
.lpVtbl
= &itmpft
;
218 memset(&tmpFile
->fInfo
, 0, sizeof(tmpFile
->fInfo
));
220 tmpFile
->fInfo
.dwStreams
= nStreams
;
221 tmpFile
->ppStreams
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(PAVISTREAM
));
222 if (tmpFile
->ppStreams
== NULL
) {
223 HeapFree(GetProcessHeap(), 0, tmpFile
);
227 for (i
= 0; i
< nStreams
; i
++) {
228 AVISTREAMINFOW sInfo
;
230 tmpFile
->ppStreams
[i
] = ppStreams
[i
];
232 AVIStreamAddRef(ppStreams
[i
]);
233 AVIStreamInfoW(ppStreams
[i
], &sInfo
, sizeof(sInfo
));
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;
243 if (tmpFile
->fInfo
.dwSuggestedBufferSize
< sInfo
.dwSuggestedBufferSize
)
244 tmpFile
->fInfo
.dwSuggestedBufferSize
= sInfo
.dwSuggestedBufferSize
;
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
;
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
;
263 return &tmpFile
->IAVIFile_iface
;