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