1 | /*
|
---|
2 | * Copyright 1999 Marcus Meissner
|
---|
3 | * Copyright 2001 Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
|
---|
4 | *
|
---|
5 | * FIXME - implements editing/writing.
|
---|
6 | */
|
---|
7 |
|
---|
8 | #include <string.h>
|
---|
9 | #include <stdio.h>
|
---|
10 | #include <assert.h>
|
---|
11 |
|
---|
12 | #include "winbase.h"
|
---|
13 | #include "winnls.h"
|
---|
14 | #include "mmsystem.h"
|
---|
15 | #include "winerror.h"
|
---|
16 | #include "vfw.h"
|
---|
17 | #include "debugtools.h"
|
---|
18 | #include "avifile_private.h"
|
---|
19 |
|
---|
20 | DEFAULT_DEBUG_CHANNEL(avifile);
|
---|
21 |
|
---|
22 | #define AVIFILE_STREAMS_MAX 4
|
---|
23 |
|
---|
24 |
|
---|
25 | static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj);
|
---|
26 | static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface);
|
---|
27 | static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface);
|
---|
28 | static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size);
|
---|
29 | static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam);
|
---|
30 | static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi);
|
---|
31 | static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size);
|
---|
32 | static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size);
|
---|
33 | static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface);
|
---|
34 | static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam);
|
---|
35 |
|
---|
36 | struct ICOM_VTABLE(IAVIFile) iavift = {
|
---|
37 | ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
---|
38 | IAVIFile_fnQueryInterface,
|
---|
39 | IAVIFile_fnAddRef,
|
---|
40 | IAVIFile_fnRelease,
|
---|
41 | IAVIFile_fnInfo,
|
---|
42 | IAVIFile_fnGetStream,
|
---|
43 | IAVIFile_fnCreateStream,
|
---|
44 | IAVIFile_fnWriteData,
|
---|
45 | IAVIFile_fnReadData,
|
---|
46 | IAVIFile_fnEndRecord,
|
---|
47 | IAVIFile_fnDeleteStream,
|
---|
48 | /* IAVIFILE_fnOpen */ /* FIXME? */
|
---|
49 | };
|
---|
50 |
|
---|
51 |
|
---|
52 | typedef struct IAVIFileImpl
|
---|
53 | {
|
---|
54 | ICOM_VFIELD(IAVIFile);
|
---|
55 | /* IUnknown stuff */
|
---|
56 | DWORD ref;
|
---|
57 | /* IAVIFile stuff */
|
---|
58 | HANDLE hf;
|
---|
59 | DWORD dwAVIFileCaps;
|
---|
60 | DWORD dwAVIFileScale;
|
---|
61 | DWORD dwAVIFileRate;
|
---|
62 | DWORD dwAVIFileLength;
|
---|
63 | DWORD dwAVIFileEditCount;
|
---|
64 | MainAVIHeader hdr;
|
---|
65 | IAVIStream* pStreams[AVIFILE_STREAMS_MAX];
|
---|
66 | AVIStreamHeader strhdrs[AVIFILE_STREAMS_MAX];
|
---|
67 | DWORD dwMoviTop;
|
---|
68 | DWORD dwCountOfIndexEntry;
|
---|
69 | AVIINDEXENTRY* pIndexEntry;
|
---|
70 | AVIINDEXENTRY* pStreamIndexEntry[AVIFILE_STREAMS_MAX+1];
|
---|
71 | } IAVIFileImpl;
|
---|
72 |
|
---|
73 |
|
---|
74 | /****************************************************************************
|
---|
75 | * AVI file parser.
|
---|
76 | */
|
---|
77 |
|
---|
78 | static HRESULT AVIFILE_IAVIFile_ReadNextChunkHeader(
|
---|
79 | IAVIFileImpl* This, FOURCC* pfcc, DWORD* pdwSize )
|
---|
80 | {
|
---|
81 | BYTE buf[8];
|
---|
82 | DWORD dwRead;
|
---|
83 |
|
---|
84 | if ( ( !ReadFile( This->hf, buf, 8, &dwRead, NULL ) ) ||
|
---|
85 | ( 8 != dwRead ) )
|
---|
86 | return AVIERR_FILEREAD;
|
---|
87 | *pfcc = mmioFOURCC(buf[0],buf[1],buf[2],buf[3]);
|
---|
88 | *pdwSize = ( ((DWORD)buf[4]) ) |
|
---|
89 | ( ((DWORD)buf[5]) << 8 ) |
|
---|
90 | ( ((DWORD)buf[6]) << 16 ) |
|
---|
91 | ( ((DWORD)buf[7]) << 24 );
|
---|
92 |
|
---|
93 | return S_OK;
|
---|
94 | }
|
---|
95 |
|
---|
96 | static HRESULT AVIFILE_IAVIFile_SkipChunkData(
|
---|
97 | IAVIFileImpl* This, DWORD dwChunkSize )
|
---|
98 | {
|
---|
99 | LONG lHigh = 0;
|
---|
100 | DWORD dwRes;
|
---|
101 |
|
---|
102 | if ( dwChunkSize == 0 )
|
---|
103 | return S_OK;
|
---|
104 |
|
---|
105 | SetLastError(NO_ERROR);
|
---|
106 | dwRes = SetFilePointer( This->hf, (LONG)dwChunkSize,
|
---|
107 | &lHigh, FILE_CURRENT );
|
---|
108 | if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
|
---|
109 | return AVIERR_FILEREAD;
|
---|
110 |
|
---|
111 | return S_OK;
|
---|
112 | }
|
---|
113 |
|
---|
114 | static HRESULT AVIFILE_IAVIFile_ReadChunkData(
|
---|
115 | IAVIFileImpl* This, DWORD dwChunkSize,
|
---|
116 | LPVOID lpvBuf, DWORD dwBufSize, LPDWORD lpdwRead )
|
---|
117 | {
|
---|
118 | if ( dwBufSize > dwChunkSize )
|
---|
119 | dwBufSize = dwChunkSize;
|
---|
120 | if ( ( !ReadFile( This->hf, lpvBuf, dwBufSize, lpdwRead, NULL ) ) ||
|
---|
121 | ( dwBufSize != *lpdwRead ) )
|
---|
122 | return AVIERR_FILEREAD;
|
---|
123 |
|
---|
124 | return AVIFILE_IAVIFile_SkipChunkData( This, dwChunkSize - dwBufSize );
|
---|
125 | }
|
---|
126 |
|
---|
127 | static HRESULT AVIFILE_IAVIFile_SeekToSpecifiedChunk(
|
---|
128 | IAVIFileImpl* This, FOURCC fccType, DWORD* pdwLen )
|
---|
129 | {
|
---|
130 | HRESULT hr;
|
---|
131 | FOURCC fcc;
|
---|
132 | BYTE buf[4];
|
---|
133 | DWORD dwRead;
|
---|
134 |
|
---|
135 | while ( 1 )
|
---|
136 | {
|
---|
137 | hr = AVIFILE_IAVIFile_ReadNextChunkHeader(
|
---|
138 | This, &fcc, pdwLen );
|
---|
139 | if ( hr != S_OK )
|
---|
140 | return hr;
|
---|
141 | if ( fcc == fccType )
|
---|
142 | return S_OK;
|
---|
143 |
|
---|
144 | if ( fcc == FOURCC_LIST )
|
---|
145 | {
|
---|
146 | if ( ( !ReadFile( This->hf, buf, 4, &dwRead, NULL ) ) ||
|
---|
147 | ( 4 != dwRead ) )
|
---|
148 | return AVIERR_FILEREAD;
|
---|
149 | }
|
---|
150 | else
|
---|
151 | {
|
---|
152 | hr = AVIFILE_IAVIFile_SkipChunkData(
|
---|
153 | This, *pdwLen );
|
---|
154 | if ( hr != S_OK )
|
---|
155 | return hr;
|
---|
156 | }
|
---|
157 | }
|
---|
158 | }
|
---|
159 |
|
---|
160 |
|
---|
161 | WINE_AVISTREAM_DATA* AVIFILE_Alloc_IAVIStreamData( DWORD dwFmtLen )
|
---|
162 | {
|
---|
163 | WINE_AVISTREAM_DATA* pData;
|
---|
164 |
|
---|
165 | pData = (WINE_AVISTREAM_DATA*)
|
---|
166 | HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
|
---|
167 | sizeof(WINE_AVISTREAM_DATA) );
|
---|
168 | if ( pData == NULL )
|
---|
169 | return NULL;
|
---|
170 | if ( dwFmtLen > 0 )
|
---|
171 | {
|
---|
172 | pData->pbFmt = (BYTE*)
|
---|
173 | HeapAlloc( AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
|
---|
174 | sizeof(BYTE)*dwFmtLen );
|
---|
175 | if ( pData->pbFmt == NULL )
|
---|
176 | {
|
---|
177 | AVIFILE_Free_IAVIStreamData( pData );
|
---|
178 | return NULL;
|
---|
179 | }
|
---|
180 | }
|
---|
181 | pData->dwFmtLen = dwFmtLen;
|
---|
182 |
|
---|
183 | return pData;
|
---|
184 | }
|
---|
185 |
|
---|
186 | void AVIFILE_Free_IAVIStreamData( WINE_AVISTREAM_DATA* pData )
|
---|
187 | {
|
---|
188 | if ( pData != NULL )
|
---|
189 | {
|
---|
190 | if ( pData->pbFmt != NULL )
|
---|
191 | HeapFree( AVIFILE_data.hHeap,0,pData->pbFmt );
|
---|
192 | HeapFree( AVIFILE_data.hHeap,0,pData );
|
---|
193 | }
|
---|
194 | }
|
---|
195 |
|
---|
196 | static void AVIFILE_IAVIFile_InitIndexTable(
|
---|
197 | IAVIFileImpl* This,
|
---|
198 | AVIINDEXENTRY* pIndexBuf,
|
---|
199 | AVIINDEXENTRY* pIndexData,
|
---|
200 | DWORD dwCountOfIndexEntry )
|
---|
201 | {
|
---|
202 | DWORD dwStreamIndex;
|
---|
203 | DWORD dwIndex;
|
---|
204 | FOURCC ckid;
|
---|
205 |
|
---|
206 | dwStreamIndex = 0;
|
---|
207 | for ( ; dwStreamIndex < (AVIFILE_STREAMS_MAX+1); dwStreamIndex ++ )
|
---|
208 | This->pStreamIndexEntry[dwStreamIndex] = NULL;
|
---|
209 |
|
---|
210 | dwStreamIndex = 0;
|
---|
211 | for ( ; dwStreamIndex < This->hdr.dwStreams; dwStreamIndex ++ )
|
---|
212 | {
|
---|
213 | ckid = mmioFOURCC('0','0'+dwStreamIndex,0,0);
|
---|
214 | TRACE( "testing ckid %c%c%c%c\n",
|
---|
215 | (int)(ckid>> 0)&0xff,
|
---|
216 | (int)(ckid>> 8)&0xff,
|
---|
217 | (int)(ckid>>16)&0xff,
|
---|
218 | (int)(ckid>>24)&0xff );
|
---|
219 | This->pStreamIndexEntry[dwStreamIndex] = pIndexBuf;
|
---|
220 | FIXME( "pIndexBuf = %p\n", pIndexBuf );
|
---|
221 | for ( dwIndex = 0; dwIndex < dwCountOfIndexEntry; dwIndex++ )
|
---|
222 | {
|
---|
223 | TRACE( "ckid %c%c%c%c\n",
|
---|
224 | (int)(pIndexData[dwIndex].ckid>> 0)&0xff,
|
---|
225 | (int)(pIndexData[dwIndex].ckid>> 8)&0xff,
|
---|
226 | (int)(pIndexData[dwIndex].ckid>>16)&0xff,
|
---|
227 | (int)(pIndexData[dwIndex].ckid>>24)&0xff );
|
---|
228 |
|
---|
229 | if ( (pIndexData[dwIndex].ckid & mmioFOURCC(0xff,0xff,0,0))
|
---|
230 | == ckid )
|
---|
231 | {
|
---|
232 | memcpy( pIndexBuf, &pIndexData[dwIndex],
|
---|
233 | sizeof(AVIINDEXENTRY) );
|
---|
234 | pIndexBuf ++;
|
---|
235 | }
|
---|
236 | }
|
---|
237 | FIXME( "pIndexBuf = %p\n", pIndexBuf );
|
---|
238 | }
|
---|
239 | This->pStreamIndexEntry[This->hdr.dwStreams] = pIndexBuf;
|
---|
240 | }
|
---|
241 |
|
---|
242 |
|
---|
243 | /****************************************************************************
|
---|
244 | * Create an IAVIFile object.
|
---|
245 | */
|
---|
246 |
|
---|
247 | static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This );
|
---|
248 | static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This );
|
---|
249 |
|
---|
250 | HRESULT AVIFILE_CreateIAVIFile(void** ppobj)
|
---|
251 | {
|
---|
252 | IAVIFileImpl *This;
|
---|
253 | HRESULT hr;
|
---|
254 |
|
---|
255 | TRACE("(%p)\n",ppobj);
|
---|
256 | *ppobj = NULL;
|
---|
257 | This = (IAVIFileImpl*)HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
|
---|
258 | sizeof(IAVIFileImpl));
|
---|
259 | if ( This == NULL )
|
---|
260 | return AVIERR_MEMORY;
|
---|
261 | This->ref = 1;
|
---|
262 | ICOM_VTBL(This) = &iavift;
|
---|
263 | hr = AVIFILE_IAVIFile_Construct( This );
|
---|
264 | if ( hr != S_OK )
|
---|
265 | {
|
---|
266 | AVIFILE_IAVIFile_Destruct( This );
|
---|
267 | return hr;
|
---|
268 | }
|
---|
269 |
|
---|
270 | TRACE("new -> %p\n",This);
|
---|
271 | *ppobj = (LPVOID)This;
|
---|
272 |
|
---|
273 | return S_OK;
|
---|
274 | }
|
---|
275 |
|
---|
276 | /****************************************************************************
|
---|
277 | * IUnknown interface
|
---|
278 | */
|
---|
279 |
|
---|
280 | static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile* iface,REFIID refiid,LPVOID *obj) {
|
---|
281 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
282 |
|
---|
283 | TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj);
|
---|
284 | if ( IsEqualGUID(&IID_IUnknown,refiid) ||
|
---|
285 | IsEqualGUID(&IID_IAVIFile,refiid) )
|
---|
286 | {
|
---|
287 | *obj = iface;
|
---|
288 | IAVIFile_AddRef(iface);
|
---|
289 | return S_OK;
|
---|
290 | }
|
---|
291 | return OLE_E_ENUM_NOMORE;
|
---|
292 | }
|
---|
293 |
|
---|
294 | static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile* iface) {
|
---|
295 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
296 |
|
---|
297 | TRACE("(%p)->AddRef()\n",iface);
|
---|
298 | return ++(This->ref);
|
---|
299 | }
|
---|
300 |
|
---|
301 | static ULONG WINAPI IAVIFile_fnRelease(IAVIFile* iface) {
|
---|
302 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
303 |
|
---|
304 | TRACE("(%p)->Release()\n",iface);
|
---|
305 | if ( (--(This->ref)) > 0 )
|
---|
306 | return This->ref;
|
---|
307 |
|
---|
308 | AVIFILE_IAVIFile_Destruct(This);
|
---|
309 | HeapFree(AVIFILE_data.hHeap,0,iface);
|
---|
310 | return 0;
|
---|
311 | }
|
---|
312 |
|
---|
313 | /****************************************************************************
|
---|
314 | * IAVIFile interface
|
---|
315 | */
|
---|
316 |
|
---|
317 | static HRESULT AVIFILE_IAVIFile_Construct( IAVIFileImpl* This )
|
---|
318 | {
|
---|
319 | DWORD dwIndex;
|
---|
320 |
|
---|
321 | This->hf = INVALID_HANDLE_VALUE;
|
---|
322 | This->dwAVIFileCaps = 0;
|
---|
323 | This->dwAVIFileScale = 0;
|
---|
324 | This->dwAVIFileRate = 0;
|
---|
325 | This->dwAVIFileLength = 0;
|
---|
326 | This->dwAVIFileEditCount = 0;
|
---|
327 | for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
|
---|
328 | This->pStreams[dwIndex] = NULL;
|
---|
329 | This->dwCountOfIndexEntry = 0;
|
---|
330 | This->pIndexEntry = NULL;
|
---|
331 |
|
---|
332 | AVIFILE_data.dwClassObjRef ++;
|
---|
333 |
|
---|
334 | return S_OK;
|
---|
335 | }
|
---|
336 |
|
---|
337 | static void AVIFILE_IAVIFile_Destruct( IAVIFileImpl* This )
|
---|
338 | {
|
---|
339 | DWORD dwIndex;
|
---|
340 |
|
---|
341 | if ( This->pIndexEntry != NULL )
|
---|
342 | {
|
---|
343 | HeapFree(AVIFILE_data.hHeap,0,This->pIndexEntry);
|
---|
344 | This->pIndexEntry = NULL;
|
---|
345 | }
|
---|
346 |
|
---|
347 | for ( dwIndex = 0; dwIndex < AVIFILE_STREAMS_MAX; dwIndex++ )
|
---|
348 | {
|
---|
349 | if ( This->pStreams[dwIndex] != NULL )
|
---|
350 | {
|
---|
351 | IAVIStream_Release( This->pStreams[dwIndex] );
|
---|
352 | This->pStreams[dwIndex] = NULL;
|
---|
353 | }
|
---|
354 | }
|
---|
355 |
|
---|
356 | if ( This->hf != INVALID_HANDLE_VALUE )
|
---|
357 | CloseHandle( This->hf );
|
---|
358 |
|
---|
359 | AVIFILE_data.dwClassObjRef --;
|
---|
360 | }
|
---|
361 |
|
---|
362 | static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile*iface,AVIFILEINFOW*afi,LONG size)
|
---|
363 | {
|
---|
364 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
365 | AVIFILEINFOW fiw;
|
---|
366 |
|
---|
367 | FIXME("(%p)->Info(%p,%ld)\n",iface,afi,size);
|
---|
368 |
|
---|
369 | memset( &fiw, 0, sizeof(fiw) );
|
---|
370 | fiw.dwMaxBytesPerSec = This->hdr.dwMaxBytesPerSec;
|
---|
371 | fiw.dwFlags = This->hdr.dwFlags;
|
---|
372 | fiw.dwCaps = This->dwAVIFileCaps;
|
---|
373 | fiw.dwStreams = This->hdr.dwStreams;
|
---|
374 | fiw.dwSuggestedBufferSize = This->hdr.dwSuggestedBufferSize;
|
---|
375 | fiw.dwWidth = This->hdr.dwWidth;
|
---|
376 | fiw.dwHeight = This->hdr.dwHeight;
|
---|
377 | fiw.dwScale = This->dwAVIFileScale; /* FIXME */
|
---|
378 | fiw.dwRate = This->dwAVIFileRate; /* FIXME */
|
---|
379 | fiw.dwLength = This->dwAVIFileLength; /* FIXME */
|
---|
380 | fiw.dwEditCount = This->dwAVIFileEditCount; /* FIXME */
|
---|
381 | /* fiw.szFileType[64]; */
|
---|
382 |
|
---|
383 | if ( size > sizeof(AVIFILEINFOW) )
|
---|
384 | size = sizeof(AVIFILEINFOW);
|
---|
385 | memcpy( afi, &fiw, size );
|
---|
386 |
|
---|
387 | return S_OK;
|
---|
388 | }
|
---|
389 |
|
---|
390 | static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile*iface,PAVISTREAM*avis,DWORD fccType,LONG lParam)
|
---|
391 | {
|
---|
392 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
393 |
|
---|
394 | FIXME("(%p)->GetStream(%p,0x%08lx,%ld)\n",iface,avis,fccType,lParam);
|
---|
395 | if ( fccType != 0 )
|
---|
396 | return E_FAIL;
|
---|
397 | if ( lParam < 0 || lParam >= This->hdr.dwStreams )
|
---|
398 | return E_FAIL;
|
---|
399 | *avis = This->pStreams[lParam];
|
---|
400 | IAVIStream_AddRef( *avis );
|
---|
401 |
|
---|
402 | return S_OK;
|
---|
403 | }
|
---|
404 |
|
---|
405 | static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile*iface,PAVISTREAM*avis,AVISTREAMINFOW*asi)
|
---|
406 | {
|
---|
407 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
408 |
|
---|
409 | FIXME("(%p,%p,%p)\n",This,avis,asi);
|
---|
410 | return E_FAIL;
|
---|
411 | }
|
---|
412 |
|
---|
413 | static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG size)
|
---|
414 | {
|
---|
415 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
416 |
|
---|
417 | FIXME("(%p)->WriteData(0x%08lx,%p,%ld)\n",This,ckid,lpData,size);
|
---|
418 | /* FIXME: write data to file */
|
---|
419 | return E_FAIL;
|
---|
420 | }
|
---|
421 |
|
---|
422 | static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile*iface,DWORD ckid,LPVOID lpData,LONG *size)
|
---|
423 | {
|
---|
424 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
425 |
|
---|
426 | FIXME("(%p)->ReadData(0x%08lx,%p,%p)\n",This,ckid,lpData,size);
|
---|
427 | /* FIXME: read at most size bytes from file */
|
---|
428 |
|
---|
429 | return E_FAIL;
|
---|
430 | }
|
---|
431 |
|
---|
432 | static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile*iface)
|
---|
433 | {
|
---|
434 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
435 |
|
---|
436 | FIXME("(%p)->EndRecord()\n",This);
|
---|
437 | /* FIXME: end record? */
|
---|
438 | return E_FAIL;
|
---|
439 | }
|
---|
440 |
|
---|
441 | static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile*iface,DWORD fccType,LONG lParam)
|
---|
442 | {
|
---|
443 | ICOM_THIS(IAVIFileImpl,iface);
|
---|
444 |
|
---|
445 | FIXME("(%p)->DeleteStream(0x%08lx,%ld)\n",This,fccType,lParam);
|
---|
446 | /* FIXME: delete stream? */
|
---|
447 | return E_FAIL;
|
---|
448 | }
|
---|
449 |
|
---|
450 | /*****************************************************************************
|
---|
451 | * AVIFILE_IAVIFile_Open (internal)
|
---|
452 | */
|
---|
453 | HRESULT AVIFILE_IAVIFile_Open( PAVIFILE paf, LPCWSTR szFile, UINT uMode )
|
---|
454 | {
|
---|
455 | ICOM_THIS(IAVIFileImpl,paf);
|
---|
456 | HRESULT hr;
|
---|
457 | DWORD dwAcc;
|
---|
458 | DWORD dwShared;
|
---|
459 | DWORD dwCreate;
|
---|
460 | BYTE buf[12];
|
---|
461 | DWORD dwRead;
|
---|
462 | FOURCC fccFileType;
|
---|
463 | DWORD dwLen;
|
---|
464 | DWORD dwIndex;
|
---|
465 |
|
---|
466 | FIXME("(%p)->Open(%p,%u)\n",This,szFile,uMode);
|
---|
467 |
|
---|
468 | if ( This->hf != INVALID_HANDLE_VALUE )
|
---|
469 | {
|
---|
470 | CloseHandle( This->hf );
|
---|
471 | This->hf = INVALID_HANDLE_VALUE;
|
---|
472 | }
|
---|
473 |
|
---|
474 | switch ( uMode & 0x3 )
|
---|
475 | {
|
---|
476 | case OF_READ: /* 0x0 */
|
---|
477 | dwAcc = GENERIC_READ;
|
---|
478 | dwCreate = OPEN_EXISTING;
|
---|
479 | This->dwAVIFileCaps = AVIFILECAPS_CANREAD;
|
---|
480 | break;
|
---|
481 | case OF_WRITE: /* 0x1 */
|
---|
482 | dwAcc = GENERIC_WRITE;
|
---|
483 | dwCreate = OPEN_ALWAYS;
|
---|
484 | This->dwAVIFileCaps = AVIFILECAPS_CANWRITE;
|
---|
485 | break;
|
---|
486 | case OF_READWRITE: /* 0x2 */
|
---|
487 | dwAcc = GENERIC_READ|GENERIC_WRITE;
|
---|
488 | dwCreate = OPEN_ALWAYS;
|
---|
489 | This->dwAVIFileCaps = AVIFILECAPS_CANREAD|AVIFILECAPS_CANWRITE;
|
---|
490 | break;
|
---|
491 | default:
|
---|
492 | return E_FAIL;
|
---|
493 | }
|
---|
494 |
|
---|
495 | if ( This->dwAVIFileCaps & AVIFILECAPS_CANWRITE )
|
---|
496 | {
|
---|
497 | FIXME( "editing AVI is currently not supported!\n" );
|
---|
498 | return E_FAIL;
|
---|
499 | }
|
---|
500 |
|
---|
501 | switch ( uMode & 0x70 )
|
---|
502 | {
|
---|
503 | case OF_SHARE_COMPAT: /* 0x00 */
|
---|
504 | dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
|
---|
505 | break;
|
---|
506 | case OF_SHARE_EXCLUSIVE: /* 0x10 */
|
---|
507 | dwShared = 0;
|
---|
508 | break;
|
---|
509 | case OF_SHARE_DENY_WRITE: /* 0x20 */
|
---|
510 | dwShared = FILE_SHARE_READ;
|
---|
511 | break;
|
---|
512 | case OF_SHARE_DENY_READ: /* 0x30 */
|
---|
513 | dwShared = FILE_SHARE_WRITE;
|
---|
514 | break;
|
---|
515 | case OF_SHARE_DENY_NONE: /* 0x40 */
|
---|
516 | dwShared = FILE_SHARE_READ|FILE_SHARE_WRITE;
|
---|
517 | break;
|
---|
518 | default:
|
---|
519 | return E_FAIL;
|
---|
520 | }
|
---|
521 | if ( uMode & OF_CREATE )
|
---|
522 | dwCreate = CREATE_ALWAYS;
|
---|
523 |
|
---|
524 | This->hf = CreateFileW( szFile, dwAcc, dwShared, NULL,
|
---|
525 | dwCreate, FILE_ATTRIBUTE_NORMAL,
|
---|
526 | (HANDLE)NULL );
|
---|
527 | if ( This->hf == INVALID_HANDLE_VALUE )
|
---|
528 | return AVIERR_FILEOPEN;
|
---|
529 |
|
---|
530 | if ( dwAcc & GENERIC_READ )
|
---|
531 | {
|
---|
532 | if ( !ReadFile( This->hf, buf, 12, &dwRead, NULL ) )
|
---|
533 | return AVIERR_FILEREAD;
|
---|
534 | if ( dwRead == 12 )
|
---|
535 | {
|
---|
536 | if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3]) != FOURCC_RIFF )
|
---|
537 | return AVIERR_BADFORMAT;
|
---|
538 |
|
---|
539 | fccFileType = mmioFOURCC(buf[8],buf[9],buf[10],buf[11]);
|
---|
540 | if ( fccFileType != formtypeAVI )
|
---|
541 | return AVIERR_BADFORMAT;
|
---|
542 |
|
---|
543 | /* get AVI main header. */
|
---|
544 | hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
|
---|
545 | This, ckidAVIMAINHDR, &dwLen );
|
---|
546 | if ( hr != S_OK )
|
---|
547 | return hr;
|
---|
548 | if ( dwLen < (sizeof(DWORD)*10) )
|
---|
549 | return AVIERR_BADFORMAT;
|
---|
550 | hr = AVIFILE_IAVIFile_ReadChunkData(
|
---|
551 | This, dwLen,
|
---|
552 | &(This->hdr), sizeof(MainAVIHeader), &dwLen );
|
---|
553 | if ( This->hdr.dwStreams == 0 ||
|
---|
554 | This->hdr.dwStreams > AVIFILE_STREAMS_MAX )
|
---|
555 | return AVIERR_BADFORMAT;
|
---|
556 |
|
---|
557 | /* get stream headers. */
|
---|
558 | dwIndex = 0;
|
---|
559 | while ( dwIndex < This->hdr.dwStreams )
|
---|
560 | {
|
---|
561 | WINE_AVISTREAM_DATA* pData;
|
---|
562 |
|
---|
563 | hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
|
---|
564 | This, ckidSTREAMHEADER, &dwLen );
|
---|
565 | if ( hr != S_OK )
|
---|
566 | return hr;
|
---|
567 | if ( dwLen < (sizeof(DWORD)*12) )
|
---|
568 | return AVIERR_BADFORMAT;
|
---|
569 | hr = AVIFILE_IAVIFile_ReadChunkData(
|
---|
570 | This, dwLen,
|
---|
571 | &This->strhdrs[dwIndex],
|
---|
572 | sizeof(AVIStreamHeader), &dwLen );
|
---|
573 |
|
---|
574 | hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
|
---|
575 | This, ckidSTREAMFORMAT, &dwLen );
|
---|
576 | if ( hr != S_OK )
|
---|
577 | return hr;
|
---|
578 | pData = AVIFILE_Alloc_IAVIStreamData( dwLen );
|
---|
579 | if ( pData == NULL )
|
---|
580 | return AVIERR_MEMORY;
|
---|
581 | hr = AVIFILE_IAVIFile_ReadChunkData(
|
---|
582 | This, dwLen,
|
---|
583 | pData->pbFmt, dwLen, &dwLen );
|
---|
584 | if ( hr != S_OK )
|
---|
585 | {
|
---|
586 | AVIFILE_Free_IAVIStreamData( pData );
|
---|
587 | return hr;
|
---|
588 | }
|
---|
589 | pData->dwStreamIndex = dwIndex;
|
---|
590 | pData->pstrhdr = &This->strhdrs[dwIndex];
|
---|
591 |
|
---|
592 | hr = AVIStreamCreate(&This->pStreams[dwIndex],
|
---|
593 | (LONG)paf, (LONG)(pData), NULL );
|
---|
594 | if ( hr != S_OK )
|
---|
595 | {
|
---|
596 | AVIFILE_Free_IAVIStreamData( pData );
|
---|
597 | return hr;
|
---|
598 | }
|
---|
599 |
|
---|
600 | if ( (This->strhdrs[dwIndex].fccType
|
---|
601 | == mmioFOURCC('v','i','d','s')) ||
|
---|
602 | (This->strhdrs[dwIndex].fccType
|
---|
603 | == mmioFOURCC('V','I','D','S')) )
|
---|
604 | {
|
---|
605 | This->dwAVIFileScale =
|
---|
606 | This->strhdrs[dwIndex].dwScale;
|
---|
607 | This->dwAVIFileRate =
|
---|
608 | This->strhdrs[dwIndex].dwRate;
|
---|
609 | This->dwAVIFileLength =
|
---|
610 | This->strhdrs[dwIndex].dwLength;
|
---|
611 | }
|
---|
612 | else
|
---|
613 | if ( This->dwAVIFileScale == 0 )
|
---|
614 | {
|
---|
615 | This->dwAVIFileScale =
|
---|
616 | This->strhdrs[dwIndex].dwScale;
|
---|
617 | This->dwAVIFileRate =
|
---|
618 | This->strhdrs[dwIndex].dwRate;
|
---|
619 | This->dwAVIFileLength =
|
---|
620 | This->strhdrs[dwIndex].dwLength;
|
---|
621 | }
|
---|
622 |
|
---|
623 | dwIndex ++;
|
---|
624 | }
|
---|
625 |
|
---|
626 | /* skip movi. */
|
---|
627 | while ( 1 )
|
---|
628 | {
|
---|
629 | hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
|
---|
630 | This, FOURCC_LIST, &dwLen );
|
---|
631 | if ( hr != S_OK )
|
---|
632 | return hr;
|
---|
633 | if ( dwLen < 4 )
|
---|
634 | return AVIERR_BADFORMAT;
|
---|
635 |
|
---|
636 | This->dwMoviTop = SetFilePointer( This->hf,0,NULL,FILE_CURRENT );
|
---|
637 | if ( This->dwMoviTop == 0xffffffff )
|
---|
638 | return AVIERR_BADFORMAT;
|
---|
639 |
|
---|
640 | if ( ( !ReadFile(This->hf, buf, 4, &dwRead, NULL) ) ||
|
---|
641 | ( dwRead != 4 ) )
|
---|
642 | return AVIERR_FILEREAD;
|
---|
643 |
|
---|
644 | hr = AVIFILE_IAVIFile_SkipChunkData(
|
---|
645 | This, dwLen - 4 );
|
---|
646 | if ( hr != S_OK )
|
---|
647 | return hr;
|
---|
648 | if ( mmioFOURCC(buf[0],buf[1],buf[2],buf[3])
|
---|
649 | == mmioFOURCC('m', 'o', 'v', 'i') )
|
---|
650 | break;
|
---|
651 | }
|
---|
652 |
|
---|
653 | /* get idx1. */
|
---|
654 | hr = AVIFILE_IAVIFile_SeekToSpecifiedChunk(
|
---|
655 | This, ckidAVINEWINDEX, &dwLen );
|
---|
656 | if ( hr != S_OK )
|
---|
657 | return hr;
|
---|
658 |
|
---|
659 | This->dwCountOfIndexEntry = dwLen / sizeof(AVIINDEXENTRY);
|
---|
660 | This->pIndexEntry = (AVIINDEXENTRY*)
|
---|
661 | HeapAlloc(AVIFILE_data.hHeap,HEAP_ZERO_MEMORY,
|
---|
662 | sizeof(AVIINDEXENTRY) *
|
---|
663 | This->dwCountOfIndexEntry * 2 );
|
---|
664 | if ( This->pIndexEntry == NULL )
|
---|
665 | return AVIERR_MEMORY;
|
---|
666 | hr = AVIFILE_IAVIFile_ReadChunkData(
|
---|
667 | This, dwLen,
|
---|
668 | This->pIndexEntry + This->dwCountOfIndexEntry,
|
---|
669 | sizeof(AVIINDEXENTRY) *
|
---|
670 | This->dwCountOfIndexEntry, &dwLen );
|
---|
671 | if ( hr != S_OK )
|
---|
672 | return hr;
|
---|
673 | AVIFILE_IAVIFile_InitIndexTable(
|
---|
674 | This, This->pIndexEntry,
|
---|
675 | This->pIndexEntry + This->dwCountOfIndexEntry,
|
---|
676 | This->dwCountOfIndexEntry );
|
---|
677 | }
|
---|
678 | else
|
---|
679 | {
|
---|
680 | /* FIXME - create the handle has GENERIC_WRITE access. */
|
---|
681 | return AVIERR_FILEREAD;
|
---|
682 | }
|
---|
683 | }
|
---|
684 | else
|
---|
685 | {
|
---|
686 | return AVIERR_FILEOPEN; /* FIXME */
|
---|
687 | }
|
---|
688 |
|
---|
689 | return S_OK;
|
---|
690 | }
|
---|
691 |
|
---|
692 | /*****************************************************************************
|
---|
693 | * AVIFILE_IAVIFile_GetIndexTable (internal)
|
---|
694 | */
|
---|
695 | HRESULT AVIFILE_IAVIFile_GetIndexTable( PAVIFILE paf, DWORD dwStreamIndex,
|
---|
696 | AVIINDEXENTRY** ppIndexEntry,
|
---|
697 | DWORD* pdwCountOfIndexEntry )
|
---|
698 | {
|
---|
699 | ICOM_THIS(IAVIFileImpl,paf);
|
---|
700 |
|
---|
701 | if ( dwStreamIndex < 0 || dwStreamIndex >= This->hdr.dwStreams )
|
---|
702 | {
|
---|
703 | FIXME( "invalid stream index %lu\n", dwStreamIndex );
|
---|
704 | return E_FAIL;
|
---|
705 | }
|
---|
706 | FIXME( "cur %p, next %p\n",
|
---|
707 | This->pStreamIndexEntry[dwStreamIndex],
|
---|
708 | This->pStreamIndexEntry[dwStreamIndex+1] );
|
---|
709 | *ppIndexEntry = This->pStreamIndexEntry[dwStreamIndex];
|
---|
710 | *pdwCountOfIndexEntry =
|
---|
711 | This->pStreamIndexEntry[dwStreamIndex+1] -
|
---|
712 | This->pStreamIndexEntry[dwStreamIndex];
|
---|
713 |
|
---|
714 | return S_OK;
|
---|
715 | }
|
---|
716 |
|
---|
717 | /*****************************************************************************
|
---|
718 | * AVIFILE_IAVIFile_ReadMovieData (internal)
|
---|
719 | */
|
---|
720 | HRESULT AVIFILE_IAVIFile_ReadMovieData( PAVIFILE paf, DWORD dwOffset,
|
---|
721 | DWORD dwLength, LPVOID lpvBuf )
|
---|
722 | {
|
---|
723 | ICOM_THIS(IAVIFileImpl,paf);
|
---|
724 | LONG lHigh = 0;
|
---|
725 | DWORD dwRes;
|
---|
726 |
|
---|
727 | if ( dwLength == 0 )
|
---|
728 | return S_OK;
|
---|
729 | SetLastError(NO_ERROR);
|
---|
730 | dwRes = SetFilePointer( This->hf, (LONG)(dwOffset+This->dwMoviTop),
|
---|
731 | &lHigh, FILE_BEGIN );
|
---|
732 | if ( dwRes == (DWORD)0xffffffff && GetLastError() != NO_ERROR )
|
---|
733 | return AVIERR_FILEREAD;
|
---|
734 |
|
---|
735 | if ( ( !ReadFile(This->hf, lpvBuf, dwLength, &dwRes, NULL) ) ||
|
---|
736 | ( dwLength != dwRes ) )
|
---|
737 | {
|
---|
738 | FIXME( "error in ReadFile()\n" );
|
---|
739 | return AVIERR_FILEREAD;
|
---|
740 | }
|
---|
741 |
|
---|
742 | return S_OK;
|
---|
743 | }
|
---|
744 |
|
---|