source: trunk/src/avifil32/iafile.c@ 6666

Last change on this file since 6666 was 6652, checked in by bird, 24 years ago

Added $Id:$ keyword.

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