ReactOS 0.4.15-dev-7788-g1ad9096
avifile.c
Go to the documentation of this file.
1/*
2 * Copyright 1999 Marcus Meissner
3 * Copyright 2002-2003 Michael Günnewig
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20/* TODO:
21 * - IAVIStreaming interface is missing for the IAVIStreamImpl
22 * - IAVIStream_fnFindSample: FIND_INDEX isn't supported.
23 * - IAVIStream_fnReadFormat: formatchanges aren't read in.
24 * - IAVIStream_fnDelete: a stub.
25 * - IAVIStream_fnSetInfo: a stub.
26 * - make thread safe
27 *
28 * KNOWN Bugs:
29 * - native version can hangup when reading a file generated with this DLL.
30 * When index is missing it works, but index seems to be okay.
31 */
32
33#define COBJMACROS
34#include <assert.h>
35#include <stdarg.h>
36
37#include "windef.h"
38#include "winbase.h"
39#include "wingdi.h"
40#include "winuser.h"
41#include "winnls.h"
42#include "winerror.h"
43#include "mmsystem.h"
44#include "vfw.h"
45
46#include "avifile_private.h"
47#include "extrachunk.h"
48
49#include "wine/debug.h"
50
52
53#ifndef IDX_PER_BLOCK
54#define IDX_PER_BLOCK 2730
55#endif
56
58
59typedef struct _IAVIStreamImpl {
61 LONG ref;
62
64 DWORD nStream; /* the n-th stream in file */
66
69
72
74
76 DWORD cbBuffer; /* size of lpBuffer */
77 DWORD dwCurrentFrame; /* frame/block currently in lpBuffer */
78
79 LONG lLastFrame; /* last correct index in idxFrames */
81 DWORD nIdxFrames; /* upper index limit of idxFrames */
83 DWORD nIdxFmtChanges; /* upper index limit of idxFmtChanges */
85
87{
88 return CONTAINING_RECORD(iface, IAVIStreamImpl, IAVIStream_iface);
89}
90
97
100
102
103 DWORD dwMoviChunkPos; /* some stuff for saving ... */
107
109 AVIINDEXENTRY *idxRecords; /* won't be updated while loading */
110 DWORD nIdxRecords; /* current fill level */
111 DWORD cbIdxRecords; /* size of idxRecords */
112
113 /* IPersistFile stuff ... */
114 HMMIO hmmio;
118};
119
121{
122 return CONTAINING_RECORD(iface, IAVIFileImpl, IUnknown_inner);
123}
124
126{
127 return CONTAINING_RECORD(iface, IAVIFileImpl, IAVIFile_iface);
128}
129
131{
132 return CONTAINING_RECORD(iface, IAVIFileImpl, IPersistFile_iface);
133}
134
135/***********************************************************************/
136
142 const AVISTREAMINFOW *asi);
147 LONG count, DWORD pos, BOOL *bAbsolute);
151 LPLONG offset);
154static ULONG AVIFILE_SearchStream(const IAVIFileImpl *This, DWORD fccType,
155 LONG lSkip);
159 LONG size);
160
162{
164
165 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
166
167 if (!ppv) {
168 WARN("invalid parameter\n");
169 return E_INVALIDARG;
170 }
171 *ppv = NULL;
172
174 *ppv = &This->IUnknown_inner;
175 else if (IsEqualIID(riid, &IID_IAVIFile))
176 *ppv = &This->IAVIFile_iface;
178 *ppv = &This->IPersistFile_iface;
179 else {
180 WARN("unknown IID %s\n", debugstr_guid(riid));
181 return E_NOINTERFACE;
182 }
183
184 /* Violation of the COM aggregation ref counting rule */
185 IUnknown_AddRef(&This->IUnknown_inner);
186 return S_OK;
187}
188
190{
193
194 TRACE("(%p) ref=%d\n", This, ref);
195
196 return ref;
197}
198
200{
203 UINT i;
204
205 TRACE("(%p) ref=%d\n", This, ref);
206
207 if (!ref) {
208 if (This->fDirty)
210
211 for (i = 0; i < This->fInfo.dwStreams; i++) {
212 if (This->ppStreams[i] != NULL) {
213 if (This->ppStreams[i]->ref != 0)
214 ERR(": someone has still %u reference to stream %u (%p)!\n",
215 This->ppStreams[i]->ref, i, This->ppStreams[i]);
216 AVIFILE_DestructAVIStream(This->ppStreams[i]);
217 HeapFree(GetProcessHeap(), 0, This->ppStreams[i]);
218 This->ppStreams[i] = NULL;
219 }
220 }
221
222 if (This->idxRecords != NULL) {
223 HeapFree(GetProcessHeap(), 0, This->idxRecords);
224 This->idxRecords = NULL;
225 This->nIdxRecords = 0;
226 }
227
228 if (This->fileextra.lp != NULL) {
229 HeapFree(GetProcessHeap(), 0, This->fileextra.lp);
230 This->fileextra.lp = NULL;
231 This->fileextra.cb = 0;
232 }
233
234 HeapFree(GetProcessHeap(), 0, This->szFileName);
235 This->szFileName = NULL;
236
237 if (This->hmmio != NULL) {
238 mmioClose(This->hmmio, 0);
239 This->hmmio = NULL;
240 }
241
243 }
244 return ref;
245}
246
247static const IUnknownVtbl unk_vtbl =
248{
252};
253
255{
257
258 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
259}
260
262{
264
265 return IUnknown_AddRef(This->outer_unk);
266}
267
269{
271
272 return IUnknown_Release(This->outer_unk);
273}
274
276{
278
279 TRACE("(%p,%p,%d)\n",iface,afi,size);
280
281 if (afi == NULL)
282 return AVIERR_BADPARAM;
283 if (size < 0)
284 return AVIERR_BADSIZE;
285
287
288 memcpy(afi, &This->fInfo, min((DWORD)size, sizeof(This->fInfo)));
289
290 if ((DWORD)size < sizeof(This->fInfo))
292 return AVIERR_OK;
293}
294
296 LONG lParam)
297{
299 ULONG nStream;
300
301 TRACE("(%p,%p,0x%08X,%d)\n", iface, avis, fccType, lParam);
302
303 if (avis == NULL || lParam < 0)
304 return AVIERR_BADPARAM;
305
306 nStream = AVIFILE_SearchStream(This, fccType, lParam);
307
308 /* Does the requested stream exist? */
309 if (nStream < This->fInfo.dwStreams &&
310 This->ppStreams[nStream] != NULL) {
311 *avis = &This->ppStreams[nStream]->IAVIStream_iface;
312 IAVIStream_AddRef(*avis);
313
314 return AVIERR_OK;
315 }
316
317 /* Sorry, but the specified stream doesn't exist */
318 *avis = NULL;
319 return AVIERR_NODATA;
320}
321
323 AVISTREAMINFOW *asi)
324{
326 DWORD n;
327
328 TRACE("(%p,%p,%p)\n", iface, avis, asi);
329
330 /* check parameters */
331 if (avis == NULL || asi == NULL)
332 return AVIERR_BADPARAM;
333
334 *avis = NULL;
335
336 /* Does the user have write permission? */
337 if ((This->uMode & MMIO_RWMODE) == 0)
338 return AVIERR_READONLY;
339
340 /* Can we add another stream? */
341 n = This->fInfo.dwStreams;
342 if (n >= MAX_AVISTREAMS || This->dwMoviChunkPos != 0) {
343 /* already reached max nr of streams
344 * or have already written frames to disk */
345 return AVIERR_UNSUPPORTED;
346 }
347
348 /* check AVISTREAMINFO for some really needed things */
349 if (asi->fccType == 0 || asi->dwScale == 0 || asi->dwRate == 0)
350 return AVIERR_BADFORMAT;
351
352 /* now it seems to be save to add the stream */
353 assert(This->ppStreams[n] == NULL);
355 sizeof(IAVIStreamImpl));
356 if (This->ppStreams[n] == NULL)
357 return AVIERR_MEMORY;
358
359 /* initialize the new allocated stream */
361
362 This->fInfo.dwStreams++;
363 This->fDirty = TRUE;
364
365 /* update our AVIFILEINFO structure */
367
368 /* return it */
369 *avis = &This->ppStreams[n]->IAVIStream_iface;
370 IAVIStream_AddRef(*avis);
371
372 return AVIERR_OK;
373}
374
375static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile *iface, DWORD ckid, void *lpData, LONG size)
376{
378
379 TRACE("(%p,0x%08X,%p,%d)\n", iface, ckid, lpData, size);
380
381 /* check parameters */
382 if (lpData == NULL)
383 return AVIERR_BADPARAM;
384 if (size < 0)
385 return AVIERR_BADSIZE;
386
387 /* Do we have write permission? */
388 if ((This->uMode & MMIO_RWMODE) == 0)
389 return AVIERR_READONLY;
390
391 This->fDirty = TRUE;
392
393 return WriteExtraChunk(&This->fileextra, ckid, lpData, size);
394}
395
396static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile *iface, DWORD ckid, void *lpData, LONG *size)
397{
399
400 TRACE("(%p,0x%08X,%p,%p)\n", iface, ckid, lpData, size);
401
402 return ReadExtraChunk(&This->fileextra, ckid, lpData, size);
403}
404
406{
408
409 TRACE("(%p)\n",iface);
410
411 if ((This->uMode & MMIO_RWMODE) == 0)
412 return AVIERR_READONLY;
413
414 This->fDirty = TRUE;
415
416 /* no frames written to any stream? -- compute start of 'movi'-chunk */
417 if (This->dwMoviChunkPos == 0)
419
420 This->fInfo.dwFlags |= AVIFILEINFO_ISINTERLEAVED;
421
422 /* already written frames to any stream, ... */
423 if (This->ckLastRecord.dwFlags & MMIO_DIRTY) {
424 /* close last record */
425 if (mmioAscend(This->hmmio, &This->ckLastRecord, 0) != 0)
426 return AVIERR_FILEWRITE;
427
429
430 if (This->fInfo.dwSuggestedBufferSize < This->ckLastRecord.cksize + 3 * sizeof(DWORD))
431 This->fInfo.dwSuggestedBufferSize = This->ckLastRecord.cksize + 3 * sizeof(DWORD);
432 }
433
434 /* write out a new record into file, but don't close it */
435 This->ckLastRecord.cksize = 0;
436 This->ckLastRecord.fccType = listtypeAVIRECORD;
437 if (mmioSeek(This->hmmio, This->dwNextFramePos, SEEK_SET) == -1)
438 return AVIERR_FILEWRITE;
439 if (mmioCreateChunk(This->hmmio, &This->ckLastRecord, MMIO_CREATELIST) != 0)
440 return AVIERR_FILEWRITE;
441 This->dwNextFramePos += 3 * sizeof(DWORD);
442
443 return AVIERR_OK;
444}
445
447{
449 ULONG nStream;
450
451 TRACE("(%p,0x%08X,%d)\n", iface, fccType, lParam);
452
453 /* check parameter */
454 if (lParam < 0)
455 return AVIERR_BADPARAM;
456
457 /* Have user write permissions? */
458 if ((This->uMode & MMIO_RWMODE) == 0)
459 return AVIERR_READONLY;
460
461 nStream = AVIFILE_SearchStream(This, fccType, lParam);
462
463 /* Does the requested stream exist? */
464 if (nStream < This->fInfo.dwStreams &&
465 This->ppStreams[nStream] != NULL) {
466 /* ... so delete it now */
467 HeapFree(GetProcessHeap(), 0, This->ppStreams[nStream]);
468 This->fInfo.dwStreams--;
469 if (nStream < This->fInfo.dwStreams)
470 memmove(&This->ppStreams[nStream], &This->ppStreams[nStream + 1],
471 (This->fInfo.dwStreams - nStream) * sizeof(This->ppStreams[0]));
472
473 This->ppStreams[This->fInfo.dwStreams] = NULL;
474 This->fDirty = TRUE;
475
476 /* This->fInfo will be updated further when asked for */
477 return AVIERR_OK;
478 } else
479 return AVIERR_NODATA;
480}
481
482static const struct IAVIFileVtbl avif_vt = {
493};
494
495
497{
499
500 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
501}
502
504{
506
507 return IUnknown_AddRef(This->outer_unk);
508}
509
511{
513
514 return IUnknown_Release(This->outer_unk);
515}
516
518{
519 TRACE("(%p,%p)\n", iface, pClassID);
520
521 if (pClassID == NULL)
522 return AVIERR_BADPARAM;
523
524 *pClassID = CLSID_AVIFile;
525
526 return AVIERR_OK;
527}
528
530{
532
533 TRACE("(%p)\n", iface);
534
535 return (This->fDirty ? S_OK : S_FALSE);
536}
537
539{
541 int len;
542
543 TRACE("(%p,%s,0x%08X)\n", iface, debugstr_w(pszFileName), dwMode);
544
545 /* check parameter */
546 if (pszFileName == NULL)
547 return AVIERR_BADPARAM;
548
549 if (This->hmmio != NULL)
550 return AVIERR_ERROR; /* No reuse of this object for another file! */
551
552 /* remember mode and name */
553 This->uMode = dwMode;
554
555 len = lstrlenW(pszFileName) + 1;
556 This->szFileName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
557 if (This->szFileName == NULL)
558 return AVIERR_MEMORY;
559 lstrcpyW(This->szFileName, pszFileName);
560
561 /* try to open the file */
562 This->hmmio = mmioOpenW(This->szFileName, NULL, MMIO_ALLOCBUF | dwMode);
563 if (This->hmmio == NULL) {
564 /* mmioOpenW not in native DLLs of Win9x -- try mmioOpenA */
565 LPSTR szFileName;
566
567 len = WideCharToMultiByte(CP_ACP, 0, This->szFileName, -1, NULL, 0, NULL, NULL);
568 szFileName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(CHAR));
569 if (szFileName == NULL)
570 return AVIERR_MEMORY;
571
572 WideCharToMultiByte(CP_ACP, 0, This->szFileName, -1, szFileName, len, NULL, NULL);
573
574 This->hmmio = mmioOpenA(szFileName, NULL, MMIO_ALLOCBUF | dwMode);
575 HeapFree(GetProcessHeap(), 0, szFileName);
576 if (This->hmmio == NULL)
577 return AVIERR_FILEOPEN;
578 }
579
580 /* should we create a new file? */
581 if (dwMode & OF_CREATE) {
582 memset(& This->fInfo, 0, sizeof(This->fInfo));
584
585 return AVIERR_OK;
586 } else
587 return AVIFILE_LoadFile(This);
588}
589
591 BOOL fRemember)
592{
593 TRACE("(%p,%s,%d)\n", iface, debugstr_w(pszFileName), fRemember);
594
595 /* We write directly to disk, so nothing to do. */
596
597 return AVIERR_OK;
598}
599
601{
602 TRACE("(%p,%s)\n", iface, debugstr_w(pszFileName));
603
604 /* We write directly to disk, so nothing to do. */
605
606 return AVIERR_OK;
607}
608
610{
612
613 TRACE("(%p,%p)\n", iface, ppszFileName);
614
615 if (ppszFileName == NULL)
616 return AVIERR_BADPARAM;
617
618 *ppszFileName = NULL;
619
620 if (This->szFileName != NULL) {
621 int len = lstrlenW(This->szFileName) + 1;
622
623 *ppszFileName = CoTaskMemAlloc(len * sizeof(WCHAR));
624 if (*ppszFileName == NULL)
625 return AVIERR_MEMORY;
626
627 lstrcpyW(*ppszFileName, This->szFileName);
628 }
629
630 return AVIERR_OK;
631}
632
633static const struct IPersistFileVtbl pf_vt = {
643};
644
646{
648 HRESULT hr;
649
650 *ppv = NULL;
652 if (!obj)
653 return AVIERR_MEMORY;
654
655 obj->IUnknown_inner.lpVtbl = &unk_vtbl;
656 obj->IAVIFile_iface.lpVtbl = &avif_vt;
657 obj->IPersistFile_iface.lpVtbl = &pf_vt;
658 obj->ref = 1;
659 if (pUnkOuter)
660 obj->outer_unk = pUnkOuter;
661 else
662 obj->outer_unk = &obj->IUnknown_inner;
663
664 hr = IUnknown_QueryInterface(&obj->IUnknown_inner, riid, ppv);
665 IUnknown_Release(&obj->IUnknown_inner);
666
667 return hr;
668}
669
670
672{
674
675 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
676
677 if (!ppv) {
678 WARN("invalid parameter\n");
679 return E_INVALIDARG;
680 }
681 *ppv = NULL;
682
683 if (IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IAVIStream, riid)) {
684 *ppv = iface;
685 IAVIStream_AddRef(iface);
686
687 return S_OK;
688 }
689 /* FIXME: IAVIStreaming interface */
690
691 return E_NOINTERFACE;
692}
693
695{
698
699 TRACE("(%p) ref=%d\n", This, ref);
700
701 /* also add ref to parent, so that it doesn't kill us */
702 if (This->paf != NULL)
703 IAVIFile_AddRef(&This->paf->IAVIFile_iface);
704
705 return ref;
706}
707
709{
712
713 TRACE("(%p) ref=%d\n", This, ref);
714
715 if (This->paf != NULL)
716 IAVIFile_Release(&This->paf->IAVIFile_iface);
717
718 return ref;
719}
720
722{
723 TRACE("(%p,0x%08lX,0x%08lX)\n", iface, lParam1, lParam2);
724
725 /* This IAVIStream interface needs an AVIFile */
726 return AVIERR_UNSUPPORTED;
727}
728
730{
732
733 TRACE("(%p,%p,%d)\n", iface, psi, size);
734
735 if (psi == NULL)
736 return AVIERR_BADPARAM;
737 if (size < 0)
738 return AVIERR_BADSIZE;
739
740 memcpy(psi, &This->sInfo, min((DWORD)size, sizeof(This->sInfo)));
741
742 if ((DWORD)size < sizeof(This->sInfo))
744 return AVIERR_OK;
745}
746
748{
750 LONG offset = 0;
751
752 TRACE("(%p,%d,0x%08X)\n",iface,pos,flags);
753
754 if (flags & FIND_FROM_START) {
755 pos = This->sInfo.dwStart;
757 flags |= FIND_NEXT;
758 }
759
760 if (This->sInfo.dwSampleSize != 0) {
761 /* convert samples into block number with offset */
763 }
764
765 if (flags & FIND_TYPE) {
766 if (flags & FIND_KEY) {
767 while (0 <= pos && pos <= This->lLastFrame) {
768 if (This->idxFrames[pos].dwFlags & AVIIF_KEYFRAME)
769 goto RETURN_FOUND;
770
771 if (flags & FIND_NEXT)
772 pos++;
773 else
774 pos--;
775 };
776 } else if (flags & FIND_ANY) {
777 while (0 <= pos && pos <= This->lLastFrame) {
778 if (This->idxFrames[pos].dwChunkLength > 0)
779 goto RETURN_FOUND;
780
781 if (flags & FIND_NEXT)
782 pos++;
783 else
784 pos--;
785
786 };
787 } else if ((flags & FIND_FORMAT) && This->idxFmtChanges != NULL &&
788 This->sInfo.fccType == streamtypeVIDEO) {
789 if (flags & FIND_NEXT) {
790 ULONG n;
791
792 for (n = 0; n < This->sInfo.dwFormatChangeCount; n++)
793 if (This->idxFmtChanges[n].ckid >= pos) {
794 pos = This->idxFmtChanges[n].ckid;
795 goto RETURN_FOUND;
796 }
797 } else {
798 LONG n;
799
800 for (n = (LONG)This->sInfo.dwFormatChangeCount; n >= 0; n--) {
801 if (This->idxFmtChanges[n].ckid <= pos) {
802 pos = This->idxFmtChanges[n].ckid;
803 goto RETURN_FOUND;
804 }
805 }
806
807 if (pos > (LONG)This->sInfo.dwStart)
808 return 0; /* format changes always for first frame */
809 }
810 }
811
812 return -1;
813 }
814
815 RETURN_FOUND:
816 if (pos < (LONG)This->sInfo.dwStart)
817 return -1;
818
819 switch (flags & FIND_RET) {
820 case FIND_LENGTH:
821 /* physical size */
822 pos = This->idxFrames[pos].dwChunkLength;
823 break;
824 case FIND_OFFSET:
825 /* physical position */
826 pos = This->idxFrames[pos].dwChunkOffset + 2 * sizeof(DWORD)
827 + offset * This->sInfo.dwSampleSize;
828 break;
829 case FIND_SIZE:
830 /* logical size */
831 if (This->sInfo.dwSampleSize)
832 pos = This->sInfo.dwSampleSize;
833 else
834 pos = 1;
835 break;
836 case FIND_INDEX:
837 FIXME(": FIND_INDEX flag is not supported!\n");
838 /* This is an index in the index-table on disc. */
839 break;
840 }; /* else logical position */
841
842 return pos;
843}
844
846 LONG *formatsize)
847{
849
850 TRACE("(%p,%d,%p,%p)\n", iface, pos, format, formatsize);
851
852 if (formatsize == NULL)
853 return AVIERR_BADPARAM;
854
855 /* only interested in needed buffersize? */
856 if (format == NULL || *formatsize <= 0) {
857 *formatsize = This->cbFormat;
858
859 return AVIERR_OK;
860 }
861
862 /* copy initial format (only as much as will fit) */
863 memcpy(format, This->lpFormat, min(*(DWORD*)formatsize, This->cbFormat));
864 if (*(DWORD*)formatsize < This->cbFormat) {
865 *formatsize = This->cbFormat;
867 }
868
869 /* Could format change? When yes will it change? */
870 if ((This->sInfo.dwFlags & AVISTREAMINFO_FORMATCHANGES) &&
871 pos > This->sInfo.dwStart) {
872 LONG lLastFmt;
873
875 if (lLastFmt > 0) {
876 FIXME(": need to read formatchange for %d -- unimplemented!\n",lLastFmt);
877 }
878 }
879
880 *formatsize = This->cbFormat;
881 return AVIERR_OK;
882}
883
885 LONG formatsize)
886{
888 BITMAPINFOHEADER *lpbiNew = format;
889
890 TRACE("(%p,%d,%p,%d)\n", iface, pos, format, formatsize);
891
892 /* check parameters */
893 if (format == NULL || formatsize <= 0)
894 return AVIERR_BADPARAM;
895
896 /* Do we have write permission? */
897 if ((This->paf->uMode & MMIO_RWMODE) == 0)
898 return AVIERR_READONLY;
899
900 /* can only set format before frame is written! */
901 if (This->lLastFrame > pos)
902 return AVIERR_UNSUPPORTED;
903
904 /* initial format or a formatchange? */
905 if (This->lpFormat == NULL) {
906 /* initial format */
907 if (This->paf->dwMoviChunkPos != 0)
908 return AVIERR_ERROR; /* user has used API in wrong sequence! */
909
910 This->lpFormat = HeapAlloc(GetProcessHeap(), 0, formatsize);
911 if (This->lpFormat == NULL)
912 return AVIERR_MEMORY;
913 This->cbFormat = formatsize;
914
915 memcpy(This->lpFormat, format, formatsize);
916
917 /* update some infos about stream */
918 if (This->sInfo.fccType == streamtypeVIDEO) {
919 LONG lDim;
920
921 lDim = This->sInfo.rcFrame.right - This->sInfo.rcFrame.left;
922 if (lDim < lpbiNew->biWidth)
923 This->sInfo.rcFrame.right = This->sInfo.rcFrame.left + lpbiNew->biWidth;
924 lDim = This->sInfo.rcFrame.bottom - This->sInfo.rcFrame.top;
925 if (lDim < lpbiNew->biHeight)
926 This->sInfo.rcFrame.bottom = This->sInfo.rcFrame.top + lpbiNew->biHeight;
927 } else if (This->sInfo.fccType == streamtypeAUDIO)
928 This->sInfo.dwSampleSize = ((LPWAVEFORMATEX)This->lpFormat)->nBlockAlign;
929
930 return AVIERR_OK;
931 } else {
932 MMCKINFO ck;
933 LPBITMAPINFOHEADER lpbiOld = This->lpFormat;
934 RGBQUAD *rgbNew = (RGBQUAD*)((LPBYTE)lpbiNew + lpbiNew->biSize);
935 AVIPALCHANGE *lppc = NULL;
936 UINT n;
937
938 /* perhaps format change, check it ... */
939 if (This->cbFormat != formatsize)
940 return AVIERR_UNSUPPORTED;
941
942 /* no format change, only the initial one */
943 if (memcmp(This->lpFormat, format, formatsize) == 0)
944 return AVIERR_OK;
945
946 /* check that's only the palette, which changes */
947 if (lpbiOld->biSize != lpbiNew->biSize ||
948 lpbiOld->biWidth != lpbiNew->biWidth ||
949 lpbiOld->biHeight != lpbiNew->biHeight ||
950 lpbiOld->biPlanes != lpbiNew->biPlanes ||
951 lpbiOld->biBitCount != lpbiNew->biBitCount ||
952 lpbiOld->biCompression != lpbiNew->biCompression ||
953 lpbiOld->biClrUsed != lpbiNew->biClrUsed)
954 return AVIERR_UNSUPPORTED;
955
956 This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
957
958 /* simply say all colors have changed */
959 ck.ckid = MAKEAVICKID(cktypePALchange, This->nStream);
960 ck.cksize = 2 * sizeof(WORD) + lpbiOld->biClrUsed * sizeof(PALETTEENTRY);
961 lppc = HeapAlloc(GetProcessHeap(), 0, ck.cksize);
962 if (lppc == NULL)
963 return AVIERR_MEMORY;
964
965 lppc->bFirstEntry = 0;
966 lppc->bNumEntries = (lpbiOld->biClrUsed < 256 ? lpbiOld->biClrUsed : 0);
967 lppc->wFlags = 0;
968 for (n = 0; n < lpbiOld->biClrUsed; n++) {
969 lppc->peNew[n].peRed = rgbNew[n].rgbRed;
970 lppc->peNew[n].peGreen = rgbNew[n].rgbGreen;
971 lppc->peNew[n].peBlue = rgbNew[n].rgbBlue;
972 lppc->peNew[n].peFlags = 0;
973 }
974
975 if (mmioSeek(This->paf->hmmio, This->paf->dwNextFramePos, SEEK_SET) == -1 ||
976 mmioCreateChunk(This->paf->hmmio, &ck, 0) != S_OK ||
977 mmioWrite(This->paf->hmmio, (HPSTR)lppc, ck.cksize) != ck.cksize ||
978 mmioAscend(This->paf->hmmio, &ck, 0) != S_OK)
979 {
980 HeapFree(GetProcessHeap(), 0, lppc);
981 return AVIERR_FILEWRITE;
982 }
983
984 This->paf->dwNextFramePos += ck.cksize + 2 * sizeof(DWORD);
985
986 HeapFree(GetProcessHeap(), 0, lppc);
987
989 }
990}
991
993 LONG buffersize, LONG *bytesread, LONG *samplesread)
994{
996 DWORD size;
997 HRESULT hr;
998
999 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface, start, samples, buffer,
1000 buffersize, bytesread, samplesread);
1001
1002 /* clear return parameters if given */
1003 if (bytesread != NULL)
1004 *bytesread = 0;
1005 if (samplesread != NULL)
1006 *samplesread = 0;
1007
1008 /* check parameters */
1009 if ((LONG)This->sInfo.dwStart > start)
1010 return AVIERR_NODATA; /* couldn't read before start of stream */
1011 if (This->sInfo.dwStart + This->sInfo.dwLength < (DWORD)start)
1012 return AVIERR_NODATA; /* start is past end of stream */
1013
1014 /* should we read as much as possible? */
1015 if (samples == -1) {
1016 /* User should know how much we have read */
1017 if (bytesread == NULL && samplesread == NULL)
1018 return AVIERR_BADPARAM;
1019
1020 if (This->sInfo.dwSampleSize != 0)
1021 samples = buffersize / This->sInfo.dwSampleSize;
1022 else
1023 samples = 1;
1024 }
1025
1026 /* limit to end of stream */
1027 if ((LONG)This->sInfo.dwLength < samples)
1028 samples = This->sInfo.dwLength;
1029 if ((start - This->sInfo.dwStart) > (This->sInfo.dwLength - samples))
1030 samples = This->sInfo.dwLength - (start - This->sInfo.dwStart);
1031
1032 /* nothing to read? Then leave ... */
1033 if (samples == 0)
1034 return AVIERR_OK;
1035
1036 if (This->sInfo.dwSampleSize != 0) {
1037 /* fixed samplesize -- we can read over frame/block boundaries */
1038 LONG block = start;
1039 LONG offset = 0;
1040
1041 if (!buffer)
1042 {
1043 if (bytesread)
1044 *bytesread = samples*This->sInfo.dwSampleSize;
1045 if (samplesread)
1046 *samplesread = samples;
1047 return AVIERR_OK;
1048 }
1049
1050 /* convert start sample to block,offset pair */
1052
1053 /* convert samples to bytes */
1054 samples *= This->sInfo.dwSampleSize;
1055
1056 while (samples > 0 && buffersize > 0) {
1057 LONG blocksize;
1058 if (block != This->dwCurrentFrame) {
1060 if (FAILED(hr))
1061 return hr;
1062 }
1063
1064 size = min((DWORD)samples, (DWORD)buffersize);
1065 blocksize = This->lpBuffer[1];
1066 TRACE("blocksize = %u\n",blocksize);
1067 size = min(size, blocksize - offset);
1068 memcpy(buffer, ((BYTE*)&This->lpBuffer[2]) + offset, size);
1069
1070 block++;
1071 offset = 0;
1072 buffer = ((LPBYTE)buffer)+size;
1073 samples -= size;
1074 buffersize -= size;
1075
1076 /* fill out return parameters if given */
1077 if (bytesread != NULL)
1078 *bytesread += size;
1079 if (samplesread != NULL)
1080 *samplesread += size / This->sInfo.dwSampleSize;
1081 }
1082
1083 if (samples == 0)
1084 return AVIERR_OK;
1085 else
1086 return AVIERR_BUFFERTOOSMALL;
1087 } else {
1088 /* variable samplesize -- we can only read one full frame/block */
1089 if (samples > 1)
1090 samples = 1;
1091
1092 assert(start <= This->lLastFrame);
1093 size = This->idxFrames[start].dwChunkLength;
1094 if (buffer != NULL && buffersize >= size) {
1096 if (FAILED(hr))
1097 return hr;
1098 } else if (buffer != NULL)
1099 return AVIERR_BUFFERTOOSMALL;
1100
1101 /* fill out return parameters if given */
1102 if (bytesread != NULL)
1103 *bytesread = size;
1104 if (samplesread != NULL)
1105 *samplesread = samples;
1106
1107 return AVIERR_OK;
1108 }
1109}
1110
1112 LONG buffersize, DWORD flags, LONG *sampwritten, LONG *byteswritten)
1113{
1115 FOURCC ckid;
1116 HRESULT hr;
1117
1118 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface, start, samples,
1119 buffer, buffersize, flags, sampwritten, byteswritten);
1120
1121 /* clear return parameters if given */
1122 if (sampwritten != NULL)
1123 *sampwritten = 0;
1124 if (byteswritten != NULL)
1125 *byteswritten = 0;
1126
1127 /* check parameters */
1128 if (buffer == NULL && (buffersize > 0 || samples > 0))
1129 return AVIERR_BADPARAM;
1130
1131 /* Have we write permission? */
1132 if ((This->paf->uMode & MMIO_RWMODE) == 0)
1133 return AVIERR_READONLY;
1134
1135 switch (This->sInfo.fccType) {
1136 case streamtypeAUDIO:
1137 ckid = MAKEAVICKID(cktypeWAVEbytes, This->nStream);
1138 break;
1139 default:
1140 if ((flags & AVIIF_KEYFRAME) && buffersize != 0)
1141 ckid = MAKEAVICKID(cktypeDIBbits, This->nStream);
1142 else
1143 ckid = MAKEAVICKID(cktypeDIBcompressed, This->nStream);
1144 break;
1145 };
1146
1147 /* append to end of stream? */
1148 if (start == -1) {
1149 if (This->lLastFrame == -1)
1150 start = This->sInfo.dwStart;
1151 else
1152 start = This->sInfo.dwLength;
1153 } else if (This->lLastFrame == -1)
1154 This->sInfo.dwStart = start;
1155
1156 if (This->sInfo.dwSampleSize != 0) {
1157 /* fixed sample size -- audio like */
1158 if (samples * This->sInfo.dwSampleSize != buffersize)
1159 return AVIERR_BADPARAM;
1160
1161 /* Couldn't skip audio-like data -- User must supply appropriate silence */
1162 if (This->sInfo.dwLength != start)
1163 return AVIERR_UNSUPPORTED;
1164
1165 /* Convert position to frame/block */
1166 start = This->lLastFrame + 1;
1167
1168 if ((This->paf->fInfo.dwFlags & AVIFILEINFO_ISINTERLEAVED) == 0) {
1169 FIXME(": not interleaved, could collect audio data!\n");
1170 }
1171 } else {
1172 /* variable sample size -- video like */
1173 if (samples > 1)
1174 return AVIERR_UNSUPPORTED;
1175
1176 /* must we fill up with empty frames? */
1177 if (This->lLastFrame != -1) {
1178 FOURCC ckid2 = MAKEAVICKID(cktypeDIBcompressed, This->nStream);
1179
1180 while (start > This->lLastFrame + 1) {
1181 hr = AVIFILE_WriteBlock(This, This->lLastFrame + 1, ckid2, 0, NULL, 0);
1182 if (FAILED(hr))
1183 return hr;
1184 }
1185 }
1186 }
1187
1188 /* write the block now */
1189 hr = AVIFILE_WriteBlock(This, start, ckid, flags, buffer, buffersize);
1190 if (SUCCEEDED(hr)) {
1191 /* fill out return parameters if given */
1192 if (sampwritten != NULL)
1193 *sampwritten = samples;
1194 if (byteswritten != NULL)
1195 *byteswritten = buffersize;
1196 }
1197
1198 return hr;
1199}
1200
1202{
1204
1205 FIXME("(%p,%d,%d): stub\n", iface, start, samples);
1206
1207 /* check parameters */
1208 if (start < 0 || samples < 0)
1209 return AVIERR_BADPARAM;
1210
1211 /* Delete before start of stream? */
1212 if (start + samples < This->sInfo.dwStart)
1213 return AVIERR_OK;
1214
1215 /* Delete after end of stream? */
1216 if (start > This->sInfo.dwLength)
1217 return AVIERR_OK;
1218
1219 /* For the rest we need write permissions */
1220 if ((This->paf->uMode & MMIO_RWMODE) == 0)
1221 return AVIERR_READONLY;
1222
1223 /* 1. overwrite the data with JUNK
1224 *
1225 * if ISINTERLEAVED {
1226 * 2. concat all neighboured JUNK-blocks in this record to one
1227 * 3. if this record only contains JUNK and is at end set dwNextFramePos
1228 * to start of this record, repeat this.
1229 * } else {
1230 * 2. concat all neighboured JUNK-blocks.
1231 * 3. if the JUNK block is at the end, then set dwNextFramePos to
1232 * start of this block.
1233 * }
1234 */
1235
1236 return AVIERR_UNSUPPORTED;
1237}
1238
1239static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream *iface, DWORD fcc, void *lp, LONG *lpread)
1240{
1242
1243 TRACE("(%p,0x%08X,%p,%p)\n", iface, fcc, lp, lpread);
1244
1245 if (fcc == ckidSTREAMHANDLERDATA) {
1246 if (This->lpHandlerData != NULL && This->cbHandlerData > 0) {
1247 if (lp == NULL || *lpread <= 0) {
1248 *lpread = This->cbHandlerData;
1249 return AVIERR_OK;
1250 }
1251
1252 memcpy(lp, This->lpHandlerData, min(This->cbHandlerData, *lpread));
1253 if (*lpread < This->cbHandlerData)
1254 return AVIERR_BUFFERTOOSMALL;
1255 return AVIERR_OK;
1256 } else
1257 return AVIERR_NODATA;
1258 } else
1259 return ReadExtraChunk(&This->extra, fcc, lp, lpread);
1260}
1261
1263{
1265
1266 TRACE("(%p,0x%08x,%p,%d)\n", iface, fcc, lp, size);
1267
1268 /* check parameters */
1269 if (lp == NULL)
1270 return AVIERR_BADPARAM;
1271 if (size <= 0)
1272 return AVIERR_BADSIZE;
1273
1274 /* need write permission */
1275 if ((This->paf->uMode & MMIO_RWMODE) == 0)
1276 return AVIERR_READONLY;
1277
1278 /* already written something to this file? */
1279 if (This->paf->dwMoviChunkPos != 0) {
1280 /* the data will be inserted before the 'movi' chunk, so check for
1281 * enough space */
1282 DWORD dwPos = AVIFILE_ComputeMoviStart(This->paf);
1283
1284 /* ckid,size => 2 * sizeof(DWORD) */
1285 dwPos += 2 * sizeof(DWORD) + size;
1286 if (dwPos >= This->paf->dwMoviChunkPos - 2 * sizeof(DWORD))
1287 return AVIERR_UNSUPPORTED; /* not enough space left */
1288 }
1289
1290 This->paf->fDirty = TRUE;
1291
1292 if (fcc == ckidSTREAMHANDLERDATA) {
1293 if (This->lpHandlerData != NULL) {
1294 FIXME(": handler data already set -- overwrite?\n");
1295 return AVIERR_UNSUPPORTED;
1296 }
1297
1298 This->lpHandlerData = HeapAlloc(GetProcessHeap(), 0, size);
1299 if (This->lpHandlerData == NULL)
1300 return AVIERR_MEMORY;
1301 This->cbHandlerData = size;
1302 memcpy(This->lpHandlerData, lp, size);
1303
1304 return AVIERR_OK;
1305 } else
1306 return WriteExtraChunk(&This->extra, fcc, lp, size);
1307}
1308
1310{
1311 FIXME("(%p,%p,%d): stub\n", iface, info, infolen);
1312
1313 return E_FAIL;
1314}
1315
1316static const struct IAVIStreamVtbl avist_vt = {
1331};
1332
1333
1335{
1336 UINT n;
1337
1338 /* pre-conditions */
1339 assert(This != NULL);
1340
1341 switch (TWOCCFromFOURCC(ckid)) {
1342 case cktypeDIBbits:
1343 if (This->paf->fInfo.dwFlags & AVIFILEINFO_TRUSTCKTYPE)
1345 break;
1347 if (This->paf->fInfo.dwFlags & AVIFILEINFO_TRUSTCKTYPE)
1348 flags &= ~AVIIF_KEYFRAME;
1349 break;
1350 case cktypePALchange:
1351 if (This->sInfo.fccType != streamtypeVIDEO) {
1352 ERR(": found palette change in non-video stream!\n");
1353 return AVIERR_BADFORMAT;
1354 }
1355
1356 if (This->idxFmtChanges == NULL || This->nIdxFmtChanges <= This->sInfo.dwFormatChangeCount) {
1357 DWORD new_count = This->nIdxFmtChanges + 16;
1358 void *new_buffer;
1359
1360 if (This->idxFmtChanges == NULL) {
1361 This->idxFmtChanges =
1362 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(AVIINDEXENTRY));
1363 if (!This->idxFmtChanges) return AVIERR_MEMORY;
1364 } else {
1365 new_buffer = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxFmtChanges,
1366 new_count * sizeof(AVIINDEXENTRY));
1367 if (!new_buffer) return AVIERR_MEMORY;
1368 This->idxFmtChanges = new_buffer;
1369 }
1370 This->nIdxFmtChanges = new_count;
1371 }
1372
1373 This->sInfo.dwFlags |= AVISTREAMINFO_FORMATCHANGES;
1374 n = ++This->sInfo.dwFormatChangeCount;
1375 This->idxFmtChanges[n].ckid = This->lLastFrame;
1376 This->idxFmtChanges[n].dwFlags = 0;
1377 This->idxFmtChanges[n].dwChunkOffset = offset;
1378 This->idxFmtChanges[n].dwChunkLength = size;
1379
1380 return AVIERR_OK;
1381 case cktypeWAVEbytes:
1382 if (This->paf->fInfo.dwFlags & AVIFILEINFO_TRUSTCKTYPE)
1384 break;
1385 default:
1386 WARN(": unknown TWOCC 0x%04X found\n", TWOCCFromFOURCC(ckid));
1387 break;
1388 };
1389
1390 /* first frame is always a keyframe */
1391 if (This->lLastFrame == -1)
1393
1394 if (This->sInfo.dwSuggestedBufferSize < size)
1395 This->sInfo.dwSuggestedBufferSize = size;
1396
1397 /* get memory for index */
1398 if (This->idxFrames == NULL || This->lLastFrame + 1 >= This->nIdxFrames) {
1399 This->nIdxFrames += 512;
1400 if (This->idxFrames == NULL)
1401 This->idxFrames = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->nIdxFrames * sizeof(AVIINDEXENTRY));
1402 else
1403 This->idxFrames = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxFrames,
1404 This->nIdxFrames * sizeof(AVIINDEXENTRY));
1405 if (This->idxFrames == NULL)
1406 return AVIERR_MEMORY;
1407 }
1408
1409 This->lLastFrame++;
1410 This->idxFrames[This->lLastFrame].ckid = ckid;
1411 This->idxFrames[This->lLastFrame].dwFlags = flags;
1412 This->idxFrames[This->lLastFrame].dwChunkOffset = offset;
1413 This->idxFrames[This->lLastFrame].dwChunkLength = size;
1414
1415 /* update AVISTREAMINFO structure if necessary */
1416 if (This->sInfo.dwLength <= This->lLastFrame)
1417 This->sInfo.dwLength = This->lLastFrame + 1;
1418
1419 return AVIERR_OK;
1420}
1421
1423{
1424 /* pre-conditions */
1425 assert(This != NULL && This->ppStreams[0] != NULL);
1426
1427 if (This->idxRecords == NULL || This->cbIdxRecords / sizeof(AVIINDEXENTRY) <= This->nIdxRecords) {
1428 DWORD new_count = This->cbIdxRecords + 1024 * sizeof(AVIINDEXENTRY);
1429 void *mem;
1430 if (!This->idxRecords)
1432 else
1433 mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->idxRecords, new_count);
1434 if (mem) {
1435 This->cbIdxRecords = new_count;
1436 This->idxRecords = mem;
1437 } else {
1438 HeapFree(GetProcessHeap(), 0, This->idxRecords);
1439 This->idxRecords = NULL;
1440 return AVIERR_MEMORY;
1441 }
1442 }
1443
1444 assert(This->nIdxRecords < This->cbIdxRecords/sizeof(AVIINDEXENTRY));
1445
1446 This->idxRecords[This->nIdxRecords].ckid = listtypeAVIRECORD;
1447 This->idxRecords[This->nIdxRecords].dwFlags = AVIIF_LIST;
1448 This->idxRecords[This->nIdxRecords].dwChunkOffset =
1449 This->ckLastRecord.dwDataOffset - 2 * sizeof(DWORD);
1450 This->idxRecords[This->nIdxRecords].dwChunkLength =
1451 This->ckLastRecord.cksize;
1452 This->nIdxRecords++;
1453
1454 return AVIERR_OK;
1455}
1456
1458{
1459 DWORD dwPos;
1460 DWORD nStream;
1461
1462 /* RIFF,hdrl,movi,avih => (3 * 3 + 2) * sizeof(DWORD) = 11 * sizeof(DWORD) */
1463 dwPos = 11 * sizeof(DWORD) + sizeof(MainAVIHeader);
1464
1465 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++) {
1466 IAVIStreamImpl *pStream = This->ppStreams[nStream];
1467
1468 /* strl,strh,strf => (3 + 2 * 2) * sizeof(DWORD) = 7 * sizeof(DWORD) */
1469 dwPos += 7 * sizeof(DWORD) + sizeof(AVIStreamHeader);
1470 dwPos += ((pStream->cbFormat + 1) & ~1U);
1471 if (pStream->lpHandlerData != NULL && pStream->cbHandlerData > 0)
1472 dwPos += 2 * sizeof(DWORD) + ((pStream->cbHandlerData + 1) & ~1U);
1473 if (pStream->sInfo.szName[0])
1474 dwPos += 2 * sizeof(DWORD) + ((lstrlenW(pStream->sInfo.szName) + 1) & ~1U);
1475 }
1476
1477 if (This->dwMoviChunkPos == 0) {
1478 This->dwNextFramePos = dwPos;
1479
1480 /* pad to multiple of AVI_HEADERSIZE only if we are more than 8 bytes away from it */
1481 if (((dwPos + AVI_HEADERSIZE) & ~(AVI_HEADERSIZE - 1)) - dwPos > 2 * sizeof(DWORD))
1482 This->dwNextFramePos = (dwPos + AVI_HEADERSIZE) & ~(AVI_HEADERSIZE - 1);
1483
1484 This->dwMoviChunkPos = This->dwNextFramePos - sizeof(DWORD);
1485 }
1486
1487 return dwPos;
1488}
1489
1491{
1492 IAVIStreamImpl *pstream;
1493
1494 /* pre-conditions */
1495 assert(paf != NULL);
1497 assert(paf->ppStreams[nr] != NULL);
1498
1499 pstream = paf->ppStreams[nr];
1500
1501 pstream->IAVIStream_iface.lpVtbl = &avist_vt;
1502 pstream->ref = 0;
1503 pstream->paf = paf;
1504 pstream->nStream = nr;
1505 pstream->dwCurrentFrame = (DWORD)-1;
1506 pstream->lLastFrame = -1;
1507
1508 if (asi != NULL) {
1509 memcpy(&pstream->sInfo, asi, sizeof(pstream->sInfo));
1510
1511 if (asi->dwLength > 0) {
1512 /* pre-allocate mem for frame-index structure */
1513 pstream->idxFrames =
1515 if (pstream->idxFrames != NULL)
1516 pstream->nIdxFrames = asi->dwLength;
1517 }
1518 if (asi->dwFormatChangeCount > 0) {
1519 /* pre-allocate mem for formatchange-index structure */
1520 pstream->idxFmtChanges =
1522 if (pstream->idxFmtChanges != NULL)
1523 pstream->nIdxFmtChanges = asi->dwFormatChangeCount;
1524 }
1525
1526 /* These values will be computed */
1527 pstream->sInfo.dwLength = 0;
1528 pstream->sInfo.dwSuggestedBufferSize = 0;
1529 pstream->sInfo.dwFormatChangeCount = 0;
1530 pstream->sInfo.dwEditCount = 1;
1531 if (pstream->sInfo.dwSampleSize > 0)
1532 SetRectEmpty(&pstream->sInfo.rcFrame);
1533 }
1534
1536}
1537
1539{
1540 /* pre-conditions */
1541 assert(This != NULL);
1542
1543 This->dwCurrentFrame = (DWORD)-1;
1544 This->lLastFrame = -1;
1545 This->paf = NULL;
1546 if (This->idxFrames != NULL) {
1547 HeapFree(GetProcessHeap(), 0, This->idxFrames);
1548 This->idxFrames = NULL;
1549 This->nIdxFrames = 0;
1550 }
1551 HeapFree(GetProcessHeap(), 0, This->idxFmtChanges);
1552 This->idxFmtChanges = NULL;
1553 if (This->lpBuffer != NULL) {
1554 HeapFree(GetProcessHeap(), 0, This->lpBuffer);
1555 This->lpBuffer = NULL;
1556 This->cbBuffer = 0;
1557 }
1558 if (This->lpHandlerData != NULL) {
1559 HeapFree(GetProcessHeap(), 0, This->lpHandlerData);
1560 This->lpHandlerData = NULL;
1561 This->cbHandlerData = 0;
1562 }
1563 if (This->extra.lp != NULL) {
1564 HeapFree(GetProcessHeap(), 0, This->extra.lp);
1565 This->extra.lp = NULL;
1566 This->extra.cb = 0;
1567 }
1568 if (This->lpFormat != NULL) {
1569 HeapFree(GetProcessHeap(), 0, This->lpFormat);
1570 This->lpFormat = NULL;
1571 This->cbFormat = 0;
1572 }
1573}
1574
1576{
1577 MainAVIHeader MainAVIHdr;
1578 MMCKINFO ckRIFF;
1579 MMCKINFO ckLIST1;
1580 MMCKINFO ckLIST2;
1581 MMCKINFO ck;
1582 IAVIStreamImpl *pStream;
1583 DWORD nStream;
1584 HRESULT hr;
1585
1586 if (This->hmmio == NULL)
1587 return AVIERR_FILEOPEN;
1588
1589 /* initialize stream ptr's */
1590 memset(This->ppStreams, 0, sizeof(This->ppStreams));
1591
1592 /* try to get "RIFF" chunk -- must not be at beginning of file! */
1593 ckRIFF.fccType = formtypeAVI;
1594 if (mmioDescend(This->hmmio, &ckRIFF, NULL, MMIO_FINDRIFF) != S_OK) {
1595 ERR(": not an AVI!\n");
1596 return AVIERR_FILEREAD;
1597 }
1598
1599 /* get "LIST" "hdrl" */
1600 ckLIST1.fccType = listtypeAVIHEADER;
1601 hr = FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ckLIST1, &ckRIFF, MMIO_FINDLIST);
1602 if (FAILED(hr))
1603 return hr;
1604
1605 /* get "avih" chunk */
1606 ck.ckid = ckidAVIMAINHDR;
1607 hr = FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ck, &ckLIST1, MMIO_FINDCHUNK);
1608 if (FAILED(hr))
1609 return hr;
1610
1611 if (ck.cksize != sizeof(MainAVIHdr)) {
1612 ERR(": invalid size of %d for MainAVIHeader!\n", ck.cksize);
1613 return AVIERR_BADFORMAT;
1614 }
1615 if (mmioRead(This->hmmio, (HPSTR)&MainAVIHdr, ck.cksize) != ck.cksize)
1616 return AVIERR_FILEREAD;
1617
1618 /* check for MAX_AVISTREAMS limit */
1619 if (MainAVIHdr.dwStreams > MAX_AVISTREAMS) {
1620 WARN("file contains %u streams, but only supports %d -- change MAX_AVISTREAMS!\n", MainAVIHdr.dwStreams, MAX_AVISTREAMS);
1621 return AVIERR_UNSUPPORTED;
1622 }
1623
1624 /* adjust permissions if copyrighted material in file */
1625 if (MainAVIHdr.dwFlags & AVIFILEINFO_COPYRIGHTED) {
1626 This->uMode &= ~MMIO_RWMODE;
1627 This->uMode |= MMIO_READ;
1628 }
1629
1630 /* convert MainAVIHeader into AVIFILINFOW */
1631 memset(&This->fInfo, 0, sizeof(This->fInfo));
1632 This->fInfo.dwRate = MainAVIHdr.dwMicroSecPerFrame;
1633 This->fInfo.dwScale = 1000000;
1634 This->fInfo.dwMaxBytesPerSec = MainAVIHdr.dwMaxBytesPerSec;
1635 This->fInfo.dwFlags = MainAVIHdr.dwFlags;
1637 This->fInfo.dwLength = MainAVIHdr.dwTotalFrames;
1638 This->fInfo.dwStreams = MainAVIHdr.dwStreams;
1639 This->fInfo.dwSuggestedBufferSize = 0;
1640 This->fInfo.dwWidth = MainAVIHdr.dwWidth;
1641 This->fInfo.dwHeight = MainAVIHdr.dwHeight;
1642 LoadStringW(AVIFILE_hModule, IDS_AVIFILETYPE, This->fInfo.szFileType,
1643 ARRAY_SIZE(This->fInfo.szFileType));
1644
1645 /* go back to into header list */
1646 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
1647 return AVIERR_FILEREAD;
1648
1649 /* foreach stream exists a "LIST","strl" chunk */
1650 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++) {
1651 /* get next nested chunk in this "LIST","strl" */
1652 if (mmioDescend(This->hmmio, &ckLIST2, &ckLIST1, 0) != S_OK)
1653 return AVIERR_FILEREAD;
1654
1655 /* nested chunk must be of type "LIST","strl" -- when not normally JUNK */
1656 if (ckLIST2.ckid == FOURCC_LIST &&
1657 ckLIST2.fccType == listtypeSTREAMHEADER) {
1658 pStream = This->ppStreams[nStream] =
1660 if (pStream == NULL)
1661 return AVIERR_MEMORY;
1663
1664 ck.ckid = 0;
1665 while (mmioDescend(This->hmmio, &ck, &ckLIST2, 0) == S_OK) {
1666 switch (ck.ckid) {
1668 if (pStream->lpHandlerData != NULL)
1669 return AVIERR_BADFORMAT;
1670 pStream->lpHandlerData = HeapAlloc(GetProcessHeap(), 0, ck.cksize);
1671 if (pStream->lpHandlerData == NULL)
1672 return AVIERR_MEMORY;
1673 pStream->cbHandlerData = ck.cksize;
1674
1675 if (mmioRead(This->hmmio, pStream->lpHandlerData, ck.cksize) != ck.cksize)
1676 return AVIERR_FILEREAD;
1677 break;
1678 case ckidSTREAMFORMAT:
1679 if (pStream->lpFormat != NULL)
1680 return AVIERR_BADFORMAT;
1681 if (ck.cksize == 0)
1682 break;
1683
1684 pStream->lpFormat = HeapAlloc(GetProcessHeap(), 0, ck.cksize);
1685 if (pStream->lpFormat == NULL)
1686 return AVIERR_MEMORY;
1687 pStream->cbFormat = ck.cksize;
1688
1689 if (mmioRead(This->hmmio, pStream->lpFormat, ck.cksize) != ck.cksize)
1690 return AVIERR_FILEREAD;
1691
1692 if (pStream->sInfo.fccType == streamtypeVIDEO) {
1693 LPBITMAPINFOHEADER lpbi = pStream->lpFormat;
1694
1695 /* some corrections to the video format */
1696 if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
1697 lpbi->biClrUsed = 1u << lpbi->biBitCount;
1698 if (lpbi->biCompression == BI_RGB && lpbi->biSizeImage == 0)
1699 lpbi->biSizeImage = DIBWIDTHBYTES(*lpbi) * lpbi->biHeight;
1700 if (lpbi->biCompression != BI_RGB && lpbi->biBitCount == 8) {
1701 if (pStream->sInfo.fccHandler == mmioFOURCC('R','L','E','0') ||
1702 pStream->sInfo.fccHandler == mmioFOURCC('R','L','E',' '))
1703 lpbi->biCompression = BI_RLE8;
1704 }
1705 if (lpbi->biCompression == BI_RGB &&
1706 (pStream->sInfo.fccHandler == 0 ||
1707 pStream->sInfo.fccHandler == mmioFOURCC('N','O','N','E')))
1708 pStream->sInfo.fccHandler = comptypeDIB;
1709
1710 /* init rcFrame if it's empty */
1711 if (IsRectEmpty(&pStream->sInfo.rcFrame))
1712 SetRect(&pStream->sInfo.rcFrame, 0, 0, lpbi->biWidth, lpbi->biHeight);
1713 }
1714 break;
1715 case ckidSTREAMHEADER:
1716 {
1717 static const WCHAR streamTypeFmt[] = {'%','4','.','4','h','s',0};
1718 static const WCHAR streamNameFmt[] = {'%','s',' ','%','s',' ','#','%','d',0};
1719
1720 AVIStreamHeader streamHdr;
1721 WCHAR szType[25];
1722 UINT count;
1723 LONG n = ck.cksize;
1724
1725 if (ck.cksize > sizeof(streamHdr))
1726 n = sizeof(streamHdr);
1727
1728 if (mmioRead(This->hmmio, (HPSTR)&streamHdr, n) != n)
1729 return AVIERR_FILEREAD;
1730
1731 pStream->sInfo.fccType = streamHdr.fccType;
1732 pStream->sInfo.fccHandler = streamHdr.fccHandler;
1733 pStream->sInfo.dwFlags = streamHdr.dwFlags;
1734 pStream->sInfo.wPriority = streamHdr.wPriority;
1735 pStream->sInfo.wLanguage = streamHdr.wLanguage;
1736 pStream->sInfo.dwInitialFrames = streamHdr.dwInitialFrames;
1737 pStream->sInfo.dwScale = streamHdr.dwScale;
1738 pStream->sInfo.dwRate = streamHdr.dwRate;
1739 pStream->sInfo.dwStart = streamHdr.dwStart;
1740 pStream->sInfo.dwLength = streamHdr.dwLength;
1741 pStream->sInfo.dwSuggestedBufferSize = 0;
1742 pStream->sInfo.dwQuality = streamHdr.dwQuality;
1743 pStream->sInfo.dwSampleSize = streamHdr.dwSampleSize;
1744 pStream->sInfo.rcFrame.left = streamHdr.rcFrame.left;
1745 pStream->sInfo.rcFrame.top = streamHdr.rcFrame.top;
1746 pStream->sInfo.rcFrame.right = streamHdr.rcFrame.right;
1747 pStream->sInfo.rcFrame.bottom = streamHdr.rcFrame.bottom;
1748 pStream->sInfo.dwEditCount = 0;
1749 pStream->sInfo.dwFormatChangeCount = 0;
1750
1751 /* generate description for stream like "filename.avi Type #n" */
1752 if (streamHdr.fccType == streamtypeVIDEO)
1754 else if (streamHdr.fccType == streamtypeAUDIO)
1756 else
1757 wsprintfW(szType, streamTypeFmt, (char*)&streamHdr.fccType);
1758
1759 /* get count of this streamtype up to this stream */
1760 count = 0;
1761 for (n = nStream; 0 <= n; n--) {
1762 if (This->ppStreams[n]->sInfo.fccHandler == streamHdr.fccType)
1763 count++;
1764 }
1765
1766 memset(pStream->sInfo.szName, 0, sizeof(pStream->sInfo.szName));
1767
1768 /* FIXME: avoid overflow -- better use wsnprintfW, which doesn't exists ! */
1769 wsprintfW(pStream->sInfo.szName, streamNameFmt,
1770 AVIFILE_BasenameW(This->szFileName), szType, count);
1771 }
1772 break;
1773 case ckidSTREAMNAME:
1774 { /* streamname will be saved as ASCII string */
1776 if (str == NULL)
1777 return AVIERR_MEMORY;
1778
1779 if (mmioRead(This->hmmio, str, ck.cksize) != ck.cksize)
1780 {
1782 return AVIERR_FILEREAD;
1783 }
1784
1785 MultiByteToWideChar(CP_ACP, 0, str, -1, pStream->sInfo.szName,
1786 ARRAY_SIZE(pStream->sInfo.szName));
1787
1789 }
1790 break;
1791 case ckidAVIPADDING:
1792 case mmioFOURCC('p','a','d','d'):
1793 break;
1794 default:
1795 WARN(": found extra chunk 0x%08X\n", ck.ckid);
1796 hr = ReadChunkIntoExtra(&pStream->extra, This->hmmio, &ck);
1797 if (FAILED(hr))
1798 return hr;
1799 };
1800 if (pStream->lpFormat != NULL && pStream->sInfo.fccType == streamtypeAUDIO)
1801 {
1802 WAVEFORMATEX *wfx = pStream->lpFormat; /* wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; could be added */
1803 pStream->sInfo.dwSampleSize = wfx->nBlockAlign; /* to deal with corrupt wfx->nBlockAlign but Windows doesn't do this */
1804 TRACE("Block size reset to %u, chan=%u bpp=%u\n", wfx->nBlockAlign, wfx->nChannels, wfx->wBitsPerSample);
1805 pStream->sInfo.dwScale = 1;
1806 pStream->sInfo.dwRate = wfx->nSamplesPerSec;
1807 }
1808 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
1809 return AVIERR_FILEREAD;
1810 }
1811 } else {
1812 /* nested chunks in "LIST","hdrl" which are not of type "LIST","strl" */
1813 hr = ReadChunkIntoExtra(&This->fileextra, This->hmmio, &ckLIST2);
1814 if (FAILED(hr))
1815 return hr;
1816 }
1817 if (mmioAscend(This->hmmio, &ckLIST2, 0) != S_OK)
1818 return AVIERR_FILEREAD;
1819 }
1820
1821 /* read any extra headers in "LIST","hdrl" */
1822 FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ck, &ckLIST1, 0);
1823 if (mmioAscend(This->hmmio, &ckLIST1, 0) != S_OK)
1824 return AVIERR_FILEREAD;
1825
1826 /* search "LIST","movi" chunk in "RIFF","AVI " */
1827 ckLIST1.fccType = listtypeAVIMOVIE;
1828 hr = FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ckLIST1, &ckRIFF,
1830 if (FAILED(hr))
1831 return hr;
1832
1833 This->dwMoviChunkPos = ckLIST1.dwDataOffset;
1834 This->dwIdxChunkPos = ckLIST1.cksize + ckLIST1.dwDataOffset;
1835 if (mmioAscend(This->hmmio, &ckLIST1, 0) != S_OK)
1836 return AVIERR_FILEREAD;
1837
1838 /* try to find an index */
1839 ck.ckid = ckidAVINEWINDEX;
1840 hr = FindChunkAndKeepExtras(&This->fileextra, This->hmmio,
1841 &ck, &ckRIFF, MMIO_FINDCHUNK);
1842 if (SUCCEEDED(hr) && ck.cksize > 0) {
1843 if (FAILED(AVIFILE_LoadIndex(This, ck.cksize, ckLIST1.dwDataOffset)))
1844 This->fInfo.dwFlags &= ~AVIFILEINFO_HASINDEX;
1845 }
1846
1847 /* when we haven't found an index or it's bad, then build one
1848 * by parsing 'movi' chunk */
1849 if ((This->fInfo.dwFlags & AVIFILEINFO_HASINDEX) == 0) {
1850 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++)
1851 This->ppStreams[nStream]->lLastFrame = -1;
1852
1853 if (mmioSeek(This->hmmio, ckLIST1.dwDataOffset + sizeof(DWORD), SEEK_SET) == -1) {
1854 ERR(": Oops, can't seek back to 'movi' chunk!\n");
1855 return AVIERR_FILEREAD;
1856 }
1857
1858 /* seek through the 'movi' list until end */
1859 while (mmioDescend(This->hmmio, &ck, &ckLIST1, 0) == S_OK) {
1860 if (ck.ckid != FOURCC_LIST) {
1861 if (mmioAscend(This->hmmio, &ck, 0) == S_OK) {
1862 nStream = StreamFromFOURCC(ck.ckid);
1863
1864 if (nStream > This->fInfo.dwStreams)
1865 return AVIERR_BADFORMAT;
1866
1867 AVIFILE_AddFrame(This->ppStreams[nStream], ck.ckid, ck.cksize,
1868 ck.dwDataOffset - 2 * sizeof(DWORD), 0);
1869 } else {
1870 nStream = StreamFromFOURCC(ck.ckid);
1871 WARN(": file seems to be truncated!\n");
1872 if (nStream <= This->fInfo.dwStreams &&
1873 This->ppStreams[nStream]->sInfo.dwSampleSize > 0) {
1874 ck.cksize = mmioSeek(This->hmmio, 0, SEEK_END);
1875 if (ck.cksize != -1) {
1876 ck.cksize -= ck.dwDataOffset;
1877 ck.cksize &= ~(This->ppStreams[nStream]->sInfo.dwSampleSize - 1);
1878
1879 AVIFILE_AddFrame(This->ppStreams[nStream], ck.ckid, ck.cksize,
1880 ck.dwDataOffset - 2 * sizeof(DWORD), 0);
1881 }
1882 }
1883 }
1884 }
1885 }
1886 }
1887
1888 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++)
1889 {
1890 DWORD sugbuf = This->ppStreams[nStream]->sInfo.dwSuggestedBufferSize;
1891 if (This->fInfo.dwSuggestedBufferSize < sugbuf)
1892 This->fInfo.dwSuggestedBufferSize = sugbuf;
1893 }
1894
1895 /* find other chunks */
1896 FindChunkAndKeepExtras(&This->fileextra, This->hmmio, &ck, &ckRIFF, 0);
1897
1898 return AVIERR_OK;
1899}
1900
1902{
1903 AVIINDEXENTRY *lp;
1904 DWORD pos, n;
1906 BOOL bAbsolute = TRUE;
1907
1909 if (lp == NULL)
1910 return AVIERR_MEMORY;
1911
1912 /* adjust limits for index tables, so that inserting will be faster */
1913 for (n = 0; n < This->fInfo.dwStreams; n++) {
1914 IAVIStreamImpl *pStream = This->ppStreams[n];
1915
1916 pStream->lLastFrame = -1;
1917
1918 if (pStream->idxFrames != NULL) {
1919 HeapFree(GetProcessHeap(), 0, pStream->idxFrames);
1920 pStream->idxFrames = NULL;
1921 pStream->nIdxFrames = 0;
1922 }
1923
1924 if (pStream->sInfo.dwSampleSize != 0) {
1925 if (n > 0 && This->fInfo.dwFlags & AVIFILEINFO_ISINTERLEAVED) {
1926 pStream->nIdxFrames = This->ppStreams[0]->nIdxFrames;
1927 } else if (pStream->sInfo.dwSuggestedBufferSize) {
1928 pStream->nIdxFrames =
1929 pStream->sInfo.dwLength / pStream->sInfo.dwSuggestedBufferSize;
1930 }
1931 } else
1932 pStream->nIdxFrames = pStream->sInfo.dwLength;
1933
1934 pStream->idxFrames =
1936 if (pStream->idxFrames == NULL && pStream->nIdxFrames > 0) {
1937 pStream->nIdxFrames = 0;
1938 HeapFree(GetProcessHeap(), 0, lp);
1939 return AVIERR_MEMORY;
1940 }
1941 }
1942
1943 pos = (DWORD)-1;
1944 while (size != 0) {
1946
1947 if (mmioRead(This->hmmio, (HPSTR)lp, read) != read) {
1949 break;
1950 }
1951 size -= read;
1952
1953 if (pos == (DWORD)-1)
1954 pos = offset - lp->dwChunkOffset + sizeof(DWORD);
1955
1957 pos, &bAbsolute);
1958 }
1959
1960 HeapFree(GetProcessHeap(), 0, lp);
1961
1962 /* checking ... */
1963 for (n = 0; n < This->fInfo.dwStreams; n++) {
1964 IAVIStreamImpl *pStream = This->ppStreams[n];
1965
1966 if (pStream->sInfo.dwSampleSize == 0 &&
1967 pStream->sInfo.dwLength != pStream->lLastFrame+1)
1968 ERR("stream %u length mismatch: dwLength=%u found=%d\n",
1969 n, pStream->sInfo.dwLength, pStream->lLastFrame);
1970 }
1971
1972 return hr;
1973}
1974
1976 LONG count, DWORD pos, BOOL *bAbsolute)
1977{
1978 if (lp == NULL)
1979 return AVIERR_BADPARAM;
1980
1981 for (; count > 0; count--, lp++) {
1982 WORD nStream = StreamFromFOURCC(lp->ckid);
1983
1984 if (lp->ckid == listtypeAVIRECORD || nStream == 0x7F)
1985 continue; /* skip these */
1986
1987 if (nStream > This->fInfo.dwStreams)
1988 return AVIERR_BADFORMAT;
1989
1990 /* Video frames can be either indexed in a relative position to the
1991 * "movi" chunk or in a absolute position in the file. If the index
1992 * is relative the frame offset will always be so small that it will
1993 * virtually never reach the "movi" offset so we can detect if the
1994 * video is relative very fast.
1995 */
1996 if (*bAbsolute && lp->dwChunkOffset < This->dwMoviChunkPos)
1997 *bAbsolute = FALSE;
1998
1999 if (!*bAbsolute)
2000 lp->dwChunkOffset += pos; /* make the offset absolute */
2001
2002 if (FAILED(AVIFILE_AddFrame(This->ppStreams[nStream], lp->ckid, lp->dwChunkLength, lp->dwChunkOffset, lp->dwFlags)))
2003 return AVIERR_MEMORY;
2004 }
2005
2006 return AVIERR_OK;
2007}
2008
2011{
2012 /* pre-conditions */
2013 assert(This != NULL);
2014 assert(This->paf != NULL);
2015 assert(This->paf->hmmio != NULL);
2016 assert(This->sInfo.dwStart <= pos && pos < This->sInfo.dwLength);
2017 assert(pos <= This->lLastFrame);
2018
2019 /* should we read as much as block gives us? */
2020 if (size == 0 || size > This->idxFrames[pos].dwChunkLength)
2021 size = This->idxFrames[pos].dwChunkLength;
2022
2023 /* read into out own buffer or given one? */
2024 if (buffer == NULL) {
2025 /* we also read the chunk */
2026 size += 2 * sizeof(DWORD);
2027
2028 /* check that buffer is big enough -- don't trust dwSuggestedBufferSize */
2029 if (This->lpBuffer == NULL || This->cbBuffer < size) {
2030 DWORD maxSize = max(size, This->sInfo.dwSuggestedBufferSize);
2031
2032 if (This->lpBuffer == NULL) {
2033 This->lpBuffer = HeapAlloc(GetProcessHeap(), 0, maxSize);
2034 if (!This->lpBuffer) return AVIERR_MEMORY;
2035 } else {
2036 void *new_buffer = HeapReAlloc(GetProcessHeap(), 0, This->lpBuffer, maxSize);
2037 if (!new_buffer) return AVIERR_MEMORY;
2038 This->lpBuffer = new_buffer;
2039 }
2040 This->cbBuffer = maxSize;
2041 }
2042
2043 /* now read the complete chunk into our buffer */
2044 if (mmioSeek(This->paf->hmmio, This->idxFrames[pos].dwChunkOffset, SEEK_SET) == -1)
2045 return AVIERR_FILEREAD;
2046 if (mmioRead(This->paf->hmmio, (HPSTR)This->lpBuffer, size) != size)
2047 return AVIERR_FILEREAD;
2048
2049 /* check if it was the correct block which we have read */
2050 if (This->lpBuffer[0] != This->idxFrames[pos].ckid ||
2051 This->lpBuffer[1] != This->idxFrames[pos].dwChunkLength) {
2052 ERR(": block %d not found at 0x%08X\n", pos, This->idxFrames[pos].dwChunkOffset);
2053 ERR(": Index says: '%4.4s'(0x%08X) size 0x%08X\n",
2054 (char*)&This->idxFrames[pos].ckid, This->idxFrames[pos].ckid,
2055 This->idxFrames[pos].dwChunkLength);
2056 ERR(": Data says: '%4.4s'(0x%08X) size 0x%08X\n",
2057 (char*)&This->lpBuffer[0], This->lpBuffer[0], This->lpBuffer[1]);
2058 return AVIERR_FILEREAD;
2059 }
2060 } else {
2061 if (mmioSeek(This->paf->hmmio, This->idxFrames[pos].dwChunkOffset + 2 * sizeof(DWORD), SEEK_SET) == -1)
2062 return AVIERR_FILEREAD;
2063 if (mmioRead(This->paf->hmmio, buffer, size) != size)
2064 return AVIERR_FILEREAD;
2065 }
2066
2067 return AVIERR_OK;
2068}
2069
2071{
2072 LONG block;
2073
2074 /* pre-conditions */
2075 assert(This != NULL);
2076 assert(pos != NULL);
2077 assert(offset != NULL);
2078 assert(This->sInfo.dwSampleSize != 0);
2079 assert(*pos >= This->sInfo.dwStart);
2080
2081 /* convert start sample to start bytes */
2082 (*offset) = (*pos) - This->sInfo.dwStart;
2083 (*offset) *= This->sInfo.dwSampleSize;
2084
2085 /* convert bytes to block number */
2086 for (block = 0; block <= This->lLastFrame; block++) {
2087 if (This->idxFrames[block].dwChunkLength <= *offset)
2088 (*offset) -= This->idxFrames[block].dwChunkLength;
2089 else
2090 break;
2091 }
2092
2093 *pos = block;
2094}
2095
2097{
2098 MainAVIHeader MainAVIHdr;
2099 IAVIStreamImpl* pStream;
2100 MMCKINFO ckRIFF;
2101 MMCKINFO ckLIST1;
2102 MMCKINFO ckLIST2;
2103 MMCKINFO ck;
2104 DWORD nStream;
2105 DWORD dwPos;
2106 HRESULT hr;
2107
2108 /* initialize some things */
2109 if (This->dwMoviChunkPos == 0)
2111
2112 /* written one record too much? */
2113 if (This->ckLastRecord.dwFlags & MMIO_DIRTY) {
2114 This->dwNextFramePos -= 3 * sizeof(DWORD);
2115 if (This->nIdxRecords > 0)
2116 This->nIdxRecords--;
2117 }
2118
2120
2121 assert(This->fInfo.dwScale != 0);
2122
2123 memset(&MainAVIHdr, 0, sizeof(MainAVIHdr));
2124 MainAVIHdr.dwMicroSecPerFrame = MulDiv(This->fInfo.dwRate, 1000000,
2125 This->fInfo.dwScale);
2126 MainAVIHdr.dwMaxBytesPerSec = This->fInfo.dwMaxBytesPerSec;
2128 MainAVIHdr.dwFlags = This->fInfo.dwFlags;
2129 MainAVIHdr.dwTotalFrames = This->fInfo.dwLength;
2130 MainAVIHdr.dwInitialFrames = 0;
2131 MainAVIHdr.dwStreams = This->fInfo.dwStreams;
2132 MainAVIHdr.dwSuggestedBufferSize = This->fInfo.dwSuggestedBufferSize;
2133 MainAVIHdr.dwWidth = This->fInfo.dwWidth;
2134 MainAVIHdr.dwHeight = This->fInfo.dwHeight;
2135 MainAVIHdr.dwInitialFrames = This->dwInitialFrames;
2136
2137 /* now begin writing ... */
2138 mmioSeek(This->hmmio, 0, SEEK_SET);
2139
2140 /* RIFF chunk */
2141 ckRIFF.cksize = 0;
2142 ckRIFF.fccType = formtypeAVI;
2143 if (mmioCreateChunk(This->hmmio, &ckRIFF, MMIO_CREATERIFF) != S_OK)
2144 return AVIERR_FILEWRITE;
2145
2146 /* AVI headerlist */
2147 ckLIST1.cksize = 0;
2148 ckLIST1.fccType = listtypeAVIHEADER;
2149 if (mmioCreateChunk(This->hmmio, &ckLIST1, MMIO_CREATELIST) != S_OK)
2150 return AVIERR_FILEWRITE;
2151
2152 /* MainAVIHeader */
2153 ck.ckid = ckidAVIMAINHDR;
2154 ck.cksize = sizeof(MainAVIHdr);
2155 ck.fccType = 0;
2156 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2157 return AVIERR_FILEWRITE;
2158 if (mmioWrite(This->hmmio, (HPSTR)&MainAVIHdr, ck.cksize) != ck.cksize)
2159 return AVIERR_FILEWRITE;
2160 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2161 return AVIERR_FILEWRITE;
2162
2163 /* write the headers of each stream into a separate streamheader list */
2164 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++) {
2165 AVIStreamHeader strHdr;
2166
2167 pStream = This->ppStreams[nStream];
2168
2169 /* begin the new streamheader list */
2170 ckLIST2.cksize = 0;
2171 ckLIST2.fccType = listtypeSTREAMHEADER;
2172 if (mmioCreateChunk(This->hmmio, &ckLIST2, MMIO_CREATELIST) != S_OK)
2173 return AVIERR_FILEWRITE;
2174
2175 /* create an AVIStreamHeader from the AVSTREAMINFO */
2176 strHdr.fccType = pStream->sInfo.fccType;
2177 strHdr.fccHandler = pStream->sInfo.fccHandler;
2178 strHdr.dwFlags = pStream->sInfo.dwFlags;
2179 strHdr.wPriority = pStream->sInfo.wPriority;
2180 strHdr.wLanguage = pStream->sInfo.wLanguage;
2181 strHdr.dwInitialFrames = pStream->sInfo.dwInitialFrames;
2182 strHdr.dwScale = pStream->sInfo.dwScale;
2183 strHdr.dwRate = pStream->sInfo.dwRate;
2184 strHdr.dwStart = pStream->sInfo.dwStart;
2185 strHdr.dwLength = pStream->sInfo.dwLength;
2187 strHdr.dwQuality = pStream->sInfo.dwQuality;
2188 strHdr.dwSampleSize = pStream->sInfo.dwSampleSize;
2189 strHdr.rcFrame.left = pStream->sInfo.rcFrame.left;
2190 strHdr.rcFrame.top = pStream->sInfo.rcFrame.top;
2191 strHdr.rcFrame.right = pStream->sInfo.rcFrame.right;
2192 strHdr.rcFrame.bottom = pStream->sInfo.rcFrame.bottom;
2193
2194 /* now write the AVIStreamHeader */
2196 ck.cksize = sizeof(strHdr);
2197 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2198 return AVIERR_FILEWRITE;
2199 if (mmioWrite(This->hmmio, (HPSTR)&strHdr, ck.cksize) != ck.cksize)
2200 return AVIERR_FILEWRITE;
2201 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2202 return AVIERR_FILEWRITE;
2203
2204 /* ... the hopefully ever present streamformat ... */
2206 ck.cksize = pStream->cbFormat;
2207 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2208 return AVIERR_FILEWRITE;
2209 if (pStream->lpFormat != NULL && ck.cksize > 0) {
2210 if (mmioWrite(This->hmmio, pStream->lpFormat, ck.cksize) != ck.cksize)
2211 return AVIERR_FILEWRITE;
2212 }
2213 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2214 return AVIERR_FILEWRITE;
2215
2216 /* ... some optional existing handler data ... */
2217 if (pStream->lpHandlerData != NULL && pStream->cbHandlerData > 0) {
2219 ck.cksize = pStream->cbHandlerData;
2220 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2221 return AVIERR_FILEWRITE;
2222 if (mmioWrite(This->hmmio, pStream->lpHandlerData, ck.cksize) != ck.cksize)
2223 return AVIERR_FILEWRITE;
2224 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2225 return AVIERR_FILEWRITE;
2226 }
2227
2228 /* ... some optional additional extra chunk for this stream ... */
2229 if (pStream->extra.lp != NULL && pStream->extra.cb > 0) {
2230 /* the chunk header(s) are already in the structure */
2231 if (mmioWrite(This->hmmio, pStream->extra.lp, pStream->extra.cb) != pStream->extra.cb)
2232 return AVIERR_FILEWRITE;
2233 }
2234
2235 /* ... an optional name for this stream ... */
2236 if (pStream->sInfo.szName[0]) {
2237 LPSTR str;
2238
2239 ck.ckid = ckidSTREAMNAME;
2240 ck.cksize = lstrlenW(pStream->sInfo.szName) + 1;
2241 if (ck.cksize & 1) /* align */
2242 ck.cksize++;
2243 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2244 return AVIERR_FILEWRITE;
2245
2246 /* the streamname must be saved in ASCII not Unicode */
2247 str = HeapAlloc(GetProcessHeap(), 0, ck.cksize);
2248 if (str == NULL)
2249 return AVIERR_MEMORY;
2250 WideCharToMultiByte(CP_ACP, 0, pStream->sInfo.szName, -1, str,
2251 ck.cksize, NULL, NULL);
2252
2253 if (mmioWrite(This->hmmio, str, ck.cksize) != ck.cksize) {
2254 HeapFree(GetProcessHeap(), 0, str);
2255 return AVIERR_FILEWRITE;
2256 }
2257
2259 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2260 return AVIERR_FILEWRITE;
2261 }
2262
2263 /* close streamheader list for this stream */
2264 if (mmioAscend(This->hmmio, &ckLIST2, 0) != S_OK)
2265 return AVIERR_FILEWRITE;
2266 } /* for (0 <= nStream < MainAVIHdr.dwStreams) */
2267
2268 /* close the aviheader list */
2269 if (mmioAscend(This->hmmio, &ckLIST1, 0) != S_OK)
2270 return AVIERR_FILEWRITE;
2271
2272 /* check for padding to pre-guessed 'movi'-chunk position */
2273 dwPos = ckLIST1.dwDataOffset + ckLIST1.cksize;
2274 if (This->dwMoviChunkPos - 2 * sizeof(DWORD) > dwPos) {
2275 ck.ckid = ckidAVIPADDING;
2276 ck.cksize = This->dwMoviChunkPos - dwPos - 4 * sizeof(DWORD);
2277 assert((LONG)ck.cksize >= 0);
2278
2279 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2280 return AVIERR_FILEWRITE;
2281 if (mmioSeek(This->hmmio, ck.cksize, SEEK_CUR) == -1)
2282 return AVIERR_FILEWRITE;
2283 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2284 return AVIERR_FILEWRITE;
2285 }
2286
2287 /* now write the 'movi' chunk */
2288 mmioSeek(This->hmmio, This->dwMoviChunkPos - 2 * sizeof(DWORD), SEEK_SET);
2289 ckLIST1.cksize = 0;
2290 ckLIST1.fccType = listtypeAVIMOVIE;
2291 if (mmioCreateChunk(This->hmmio, &ckLIST1, MMIO_CREATELIST) != S_OK)
2292 return AVIERR_FILEWRITE;
2293 if (mmioSeek(This->hmmio, This->dwNextFramePos, SEEK_SET) == -1)
2294 return AVIERR_FILEWRITE;
2295 if (mmioAscend(This->hmmio, &ckLIST1, 0) != S_OK)
2296 return AVIERR_FILEWRITE;
2297
2298 /* write 'idx1' chunk */
2300 if (FAILED(hr))
2301 return hr;
2302
2303 /* write optional extra file chunks */
2304 if (This->fileextra.lp != NULL && This->fileextra.cb > 0) {
2305 /* as for the streams, are the chunk header(s) in the structure */
2306 if (mmioWrite(This->hmmio, This->fileextra.lp, This->fileextra.cb) != This->fileextra.cb)
2307 return AVIERR_FILEWRITE;
2308 }
2309
2310 /* close RIFF chunk */
2311 if (mmioAscend(This->hmmio, &ckRIFF, 0) != S_OK)
2312 return AVIERR_FILEWRITE;
2313
2314 /* add some JUNK at end for bad parsers */
2315 memset(&ckRIFF, 0, sizeof(ckRIFF));
2316 mmioWrite(This->hmmio, (HPSTR)&ckRIFF, sizeof(ckRIFF));
2317 mmioFlush(This->hmmio, 0);
2318
2319 return AVIERR_OK;
2320}
2321
2323{
2324 IAVIStreamImpl *pStream;
2326 MMCKINFO ck;
2327 DWORD nStream;
2328 LONG n;
2329
2330 ck.ckid = ckidAVINEWINDEX;
2331 ck.cksize = 0;
2332 if (mmioCreateChunk(This->hmmio, &ck, 0) != S_OK)
2333 return AVIERR_FILEWRITE;
2334
2335 if (This->fInfo.dwFlags & AVIFILEINFO_ISINTERLEAVED) {
2336 /* is interleaved -- write block of corresponding frames */
2337 LONG lInitialFrames = 0;
2338 LONG stepsize;
2339 LONG i;
2340
2341 if (This->ppStreams[0]->sInfo.dwSampleSize == 0)
2342 stepsize = 1;
2343 else
2344 stepsize = AVIStreamTimeToSample(&This->ppStreams[0]->IAVIStream_iface, 1000000);
2345
2346 assert(stepsize > 0);
2347
2348 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++) {
2349 if (lInitialFrames < This->ppStreams[nStream]->sInfo.dwInitialFrames)
2350 lInitialFrames = This->ppStreams[nStream]->sInfo.dwInitialFrames;
2351 }
2352
2353 for (i = -lInitialFrames; i < (LONG)This->fInfo.dwLength - lInitialFrames;
2354 i += stepsize) {
2355 DWORD nFrame = lInitialFrames + i;
2356
2357 assert(nFrame < This->nIdxRecords);
2358
2359 idx.ckid = listtypeAVIRECORD;
2360 idx.dwFlags = AVIIF_LIST;
2361 idx.dwChunkLength = This->idxRecords[nFrame].dwChunkLength;
2362 idx.dwChunkOffset = This->idxRecords[nFrame].dwChunkOffset
2363 - This->dwMoviChunkPos;
2364 if (mmioWrite(This->hmmio, (HPSTR)&idx, sizeof(idx)) != sizeof(idx))
2365 return AVIERR_FILEWRITE;
2366
2367 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++) {
2368 pStream = This->ppStreams[nStream];
2369
2370 /* heave we reached start of this stream? */
2371 if (-(LONG)pStream->sInfo.dwInitialFrames > i)
2372 continue;
2373
2374 if (pStream->sInfo.dwInitialFrames < lInitialFrames)
2375 nFrame -= (lInitialFrames - pStream->sInfo.dwInitialFrames);
2376
2377 /* reached end of this stream? */
2378 if (pStream->lLastFrame <= nFrame)
2379 continue;
2380
2381 if ((pStream->sInfo.dwFlags & AVISTREAMINFO_FORMATCHANGES) &&
2382 pStream->sInfo.dwFormatChangeCount != 0 &&
2383 pStream->idxFmtChanges != NULL) {
2384 DWORD pos;
2385
2386 for (pos = 0; pos < pStream->sInfo.dwFormatChangeCount; pos++) {
2387 if (pStream->idxFmtChanges[pos].ckid == nFrame) {
2388 idx.dwFlags = AVIIF_NOTIME;
2389 idx.ckid = MAKEAVICKID(cktypePALchange, pStream->nStream);
2390 idx.dwChunkLength = pStream->idxFmtChanges[pos].dwChunkLength;
2391 idx.dwChunkOffset = pStream->idxFmtChanges[pos].dwChunkOffset
2392 - This->dwMoviChunkPos;
2393
2394 if (mmioWrite(This->hmmio, (HPSTR)&idx, sizeof(idx)) != sizeof(idx))
2395 return AVIERR_FILEWRITE;
2396 break;
2397 }
2398 }
2399 } /* if have formatchanges */
2400
2401 idx.ckid = pStream->idxFrames[nFrame].ckid;
2402 idx.dwFlags = pStream->idxFrames[nFrame].dwFlags;
2403 idx.dwChunkLength = pStream->idxFrames[nFrame].dwChunkLength;
2404 idx.dwChunkOffset = pStream->idxFrames[nFrame].dwChunkOffset
2405 - This->dwMoviChunkPos;
2406 if (mmioWrite(This->hmmio, (HPSTR)&idx, sizeof(idx)) != sizeof(idx))
2407 return AVIERR_FILEWRITE;
2408 }
2409 }
2410 } else {
2411 /* not interleaved -- write index for each stream at once */
2412 for (nStream = 0; nStream < This->fInfo.dwStreams; nStream++) {
2413 pStream = This->ppStreams[nStream];
2414
2415 for (n = 0; n <= pStream->lLastFrame; n++) {
2416 if ((pStream->sInfo.dwFlags & AVISTREAMINFO_FORMATCHANGES) &&
2417 (pStream->sInfo.dwFormatChangeCount != 0)) {
2418 DWORD pos;
2419
2420 for (pos = 0; pos < pStream->sInfo.dwFormatChangeCount; pos++) {
2421 if (pStream->idxFmtChanges[pos].ckid == n) {
2422 idx.dwFlags = AVIIF_NOTIME;
2423 idx.ckid = MAKEAVICKID(cktypePALchange, pStream->nStream);
2424 idx.dwChunkLength = pStream->idxFmtChanges[pos].dwChunkLength;
2425 idx.dwChunkOffset =
2426 pStream->idxFmtChanges[pos].dwChunkOffset - This->dwMoviChunkPos;
2427 if (mmioWrite(This->hmmio, (HPSTR)&idx, sizeof(idx)) != sizeof(idx))
2428 return AVIERR_FILEWRITE;
2429 break;
2430 }
2431 }
2432 } /* if have formatchanges */
2433
2434 idx.ckid = pStream->idxFrames[n].ckid;
2435 idx.dwFlags = pStream->idxFrames[n].dwFlags;
2436 idx.dwChunkLength = pStream->idxFrames[n].dwChunkLength;
2437 idx.dwChunkOffset = pStream->idxFrames[n].dwChunkOffset
2438 - This->dwMoviChunkPos;
2439
2440 if (mmioWrite(This->hmmio, (HPSTR)&idx, sizeof(idx)) != sizeof(idx))
2441 return AVIERR_FILEWRITE;
2442 }
2443 }
2444 } /* if not interleaved */
2445
2446 if (mmioAscend(This->hmmio, &ck, 0) != S_OK)
2447 return AVIERR_FILEWRITE;
2448
2449 return AVIERR_OK;
2450}
2451
2453{
2454 UINT i;
2455 UINT nStream;
2456
2457 /* pre-condition */
2458 assert(lSkip >= 0);
2459
2460 if (fcc != 0) {
2461 /* search the number of the specified stream */
2462 nStream = (ULONG)-1;
2463 for (i = 0; i < This->fInfo.dwStreams; i++) {
2464 assert(This->ppStreams[i] != NULL);
2465
2466 if (This->ppStreams[i]->sInfo.fccType == fcc) {
2467 if (lSkip == 0) {
2468 nStream = i;
2469 break;
2470 } else
2471 lSkip--;
2472 }
2473 }
2474 } else
2475 nStream = lSkip;
2476
2477 return nStream;
2478}
2479
2481{
2482 UINT i;
2483
2484 /* pre-conditions */
2485 assert(This != NULL);
2486
2487 This->fInfo.dwMaxBytesPerSec = 0;
2489 This->fInfo.dwSuggestedBufferSize = 0;
2490 This->fInfo.dwWidth = 0;
2491 This->fInfo.dwHeight = 0;
2492 This->fInfo.dwScale = 0;
2493 This->fInfo.dwRate = 0;
2494 This->fInfo.dwLength = 0;
2495 This->dwInitialFrames = 0;
2496
2497 for (i = 0; i < This->fInfo.dwStreams; i++) {
2498 AVISTREAMINFOW *psi;
2499 DWORD n;
2500
2501 /* pre-conditions */
2502 assert(This->ppStreams[i] != NULL);
2503
2504 psi = &This->ppStreams[i]->sInfo;
2505 assert(psi->dwScale != 0);
2506 assert(psi->dwRate != 0);
2507
2508 if (i == 0) {
2509 /* use first stream timings as base */
2510 This->fInfo.dwScale = psi->dwScale;
2511 This->fInfo.dwRate = psi->dwRate;
2512 This->fInfo.dwLength = psi->dwLength;
2513 } else {
2514 n = AVIStreamSampleToSample(&This->ppStreams[0]->IAVIStream_iface,
2515 &This->ppStreams[i]->IAVIStream_iface, psi->dwLength);
2516 if (This->fInfo.dwLength < n)
2517 This->fInfo.dwLength = n;
2518 }
2519
2520 if (This->dwInitialFrames < psi->dwInitialFrames)
2521 This->dwInitialFrames = psi->dwInitialFrames;
2522
2523 if (This->fInfo.dwSuggestedBufferSize < psi->dwSuggestedBufferSize)
2524 This->fInfo.dwSuggestedBufferSize = psi->dwSuggestedBufferSize;
2525
2526 if (psi->dwSampleSize != 0) {
2527 /* fixed sample size -- exact computation */
2528 This->fInfo.dwMaxBytesPerSec += MulDiv(psi->dwSampleSize, psi->dwRate,
2529 psi->dwScale);
2530 } else {
2531 /* variable sample size -- only upper limit */
2532 This->fInfo.dwMaxBytesPerSec += MulDiv(psi->dwSuggestedBufferSize,
2533 psi->dwRate, psi->dwScale);
2534
2535 /* update dimensions */
2536 n = psi->rcFrame.right - psi->rcFrame.left;
2537 if (This->fInfo.dwWidth < n)
2538 This->fInfo.dwWidth = n;
2539 n = psi->rcFrame.bottom - psi->rcFrame.top;
2540 if (This->fInfo.dwHeight < n)
2541 This->fInfo.dwHeight = n;
2542 }
2543 }
2544}
2545
2548 LONG size)
2549{
2550 MMCKINFO ck;
2551
2552 ck.ckid = ckid;
2553 ck.cksize = size;
2554 ck.fccType = 0;
2555
2556 /* if no frame/block is already written, we must compute start of movi chunk */
2557 if (This->paf->dwMoviChunkPos == 0)
2559
2560 if (mmioSeek(This->paf->hmmio, This->paf->dwNextFramePos, SEEK_SET) == -1)
2561 return AVIERR_FILEWRITE;
2562
2563 if (mmioCreateChunk(This->paf->hmmio, &ck, 0) != S_OK)
2564 return AVIERR_FILEWRITE;
2565 if (buffer != NULL && size > 0) {
2566 if (mmioWrite(This->paf->hmmio, buffer, size) != size)
2567 return AVIERR_FILEWRITE;
2568 }
2569 if (mmioAscend(This->paf->hmmio, &ck, 0) != S_OK)
2570 return AVIERR_FILEWRITE;
2571
2572 This->paf->fDirty = TRUE;
2573 This->paf->dwNextFramePos = mmioSeek(This->paf->hmmio, 0, SEEK_CUR);
2574
2575 return AVIFILE_AddFrame(This, ckid, size,
2576 ck.dwDataOffset - 2 * sizeof(DWORD), flags);
2577}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define read
Definition: acwin.h:96
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
HMODULE AVIFILE_hModule
Definition: factory.c:39
static HRESULT WINAPI IAVIFile_fnEndRecord(IAVIFile *iface)
Definition: avifile.c:405
static HRESULT WINAPI IPersistFile_fnSave(IPersistFile *iface, LPCOLESTR pszFileName, BOOL fRemember)
Definition: avifile.c:590
static DWORD AVIFILE_ComputeMoviStart(IAVIFileImpl *This)
Definition: avifile.c:1457
static HRESULT AVIFILE_WriteBlock(IAVIStreamImpl *This, DWORD block, FOURCC ckid, DWORD flags, LPCVOID buffer, LONG size)
Definition: avifile.c:2546
static ULONG WINAPI IAVIStream_fnAddRef(IAVIStream *iface)
Definition: avifile.c:694
static ULONG WINAPI IUnknown_fnRelease(IUnknown *iface)
Definition: avifile.c:199
static HRESULT AVIFILE_LoadFile(IAVIFileImpl *This)
Definition: avifile.c:1575
#define IDX_PER_BLOCK
Definition: avifile.c:54
static HRESULT WINAPI IPersistFile_fnIsDirty(IPersistFile *iface)
Definition: avifile.c:529
static HRESULT WINAPI IAVIStream_fnSetFormat(IAVIStream *iface, LONG pos, void *format, LONG formatsize)
Definition: avifile.c:884
static HRESULT WINAPI IPersistFile_fnQueryInterface(IPersistFile *iface, REFIID riid, void **ppv)
Definition: avifile.c:496
static HRESULT WINAPI IAVIStream_fnQueryInterface(IAVIStream *iface, REFIID riid, void **ppv)
Definition: avifile.c:671
static ULONG WINAPI IUnknown_fnAddRef(IUnknown *iface)
Definition: avifile.c:189
static ULONG WINAPI IPersistFile_fnRelease(IPersistFile *iface)
Definition: avifile.c:510
static HRESULT WINAPI IAVIStream_fnCreate(IAVIStream *iface, LPARAM lParam1, LPARAM lParam2)
Definition: avifile.c:721
static HRESULT WINAPI IAVIFile_fnInfo(IAVIFile *iface, AVIFILEINFOW *afi, LONG size)
Definition: avifile.c:275
static ULONG WINAPI IPersistFile_fnAddRef(IPersistFile *iface)
Definition: avifile.c:503
static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD start, LPVOID buffer, DWORD size)
Definition: avifile.c:2009
static HRESULT WINAPI IPersistFile_fnSaveCompleted(IPersistFile *iface, LPCOLESTR pszFileName)
Definition: avifile.c:600
static HRESULT WINAPI IAVIFile_fnReadData(IAVIFile *iface, DWORD ckid, void *lpData, LONG *size)
Definition: avifile.c:396
static HRESULT WINAPI IAVIStream_fnDelete(IAVIStream *iface, LONG start, LONG samples)
Definition: avifile.c:1201
static HRESULT AVIFILE_SaveIndex(const IAVIFileImpl *This)
Definition: avifile.c:2322
static HRESULT WINAPI IAVIStream_fnRead(IAVIStream *iface, LONG start, LONG samples, void *buffer, LONG buffersize, LONG *bytesread, LONG *samplesread)
Definition: avifile.c:992
static HRESULT WINAPI IPersistFile_fnGetClassID(IPersistFile *iface, LPCLSID pClassID)
Definition: avifile.c:517
static HRESULT WINAPI IAVIFile_fnGetStream(IAVIFile *iface, IAVIStream **avis, DWORD fccType, LONG lParam)
Definition: avifile.c:295
static HRESULT WINAPI IPersistFile_fnGetCurFile(IPersistFile *iface, LPOLESTR *ppszFileName)
Definition: avifile.c:609
static void AVIFILE_ConstructAVIStream(IAVIFileImpl *paf, DWORD nr, const AVISTREAMINFOW *asi)
Definition: avifile.c:1490
static ULONG WINAPI IAVIStream_fnRelease(IAVIStream *iface)
Definition: avifile.c:708
struct _IAVIStreamImpl IAVIStreamImpl
static IAVIFileImpl * impl_from_IUnknown(IUnknown *iface)
Definition: avifile.c:120
static HRESULT AVIFILE_AddRecord(IAVIFileImpl *This)
Definition: avifile.c:1422
static HRESULT WINAPI IAVIStream_fnInfo(IAVIStream *iface, AVISTREAMINFOW *psi, LONG size)
Definition: avifile.c:729
static ULONG WINAPI IAVIFile_fnAddRef(IAVIFile *iface)
Definition: avifile.c:261
static HRESULT WINAPI IAVIFile_fnWriteData(IAVIFile *iface, DWORD ckid, void *lpData, LONG size)
Definition: avifile.c:375
static HRESULT WINAPI IAVIFile_fnQueryInterface(IAVIFile *iface, REFIID riid, void **ppv)
Definition: avifile.c:254
static IAVIFileImpl * impl_from_IAVIFile(IAVIFile *iface)
Definition: avifile.c:125
static ULONG AVIFILE_SearchStream(const IAVIFileImpl *This, DWORD fccType, LONG lSkip)
Definition: avifile.c:2452
static HRESULT AVIFILE_SaveFile(IAVIFileImpl *This)
Definition: avifile.c:2096
static const struct IAVIFileVtbl avif_vt
Definition: avifile.c:482
static LONG WINAPI IAVIStream_fnFindSample(IAVIStream *iface, LONG pos, LONG flags)
Definition: avifile.c:747
static void AVIFILE_DestructAVIStream(IAVIStreamImpl *This)
Definition: avifile.c:1538
static HRESULT AVIFILE_ParseIndex(const IAVIFileImpl *This, AVIINDEXENTRY *lp, LONG count, DWORD pos, BOOL *bAbsolute)
Definition: avifile.c:1975
static HRESULT WINAPI IAVIStream_fnWriteData(IAVIStream *iface, DWORD fcc, void *lp, LONG size)
Definition: avifile.c:1262
static const IUnknownVtbl unk_vtbl
Definition: avifile.c:247
static HRESULT WINAPI IAVIStream_fnReadFormat(IAVIStream *iface, LONG pos, void *format, LONG *formatsize)
Definition: avifile.c:845
static IAVIStreamImpl * impl_from_IAVIStream(IAVIStream *iface)
Definition: avifile.c:86
static HRESULT AVIFILE_LoadIndex(const IAVIFileImpl *This, DWORD size, DWORD offset)
Definition: avifile.c:1901
static void AVIFILE_SamplesToBlock(const IAVIStreamImpl *This, LPLONG pos, LPLONG offset)
Definition: avifile.c:2070
static HRESULT WINAPI IAVIStream_fnWrite(IAVIStream *iface, LONG start, LONG samples, void *buffer, LONG buffersize, DWORD flags, LONG *sampwritten, LONG *byteswritten)
Definition: avifile.c:1111
static ULONG WINAPI IAVIFile_fnRelease(IAVIFile *iface)
Definition: avifile.c:268
static HRESULT WINAPI IAVIStream_fnReadData(IAVIStream *iface, DWORD fcc, void *lp, LONG *lpread)
Definition: avifile.c:1239
static HRESULT AVIFILE_AddFrame(IAVIStreamImpl *This, DWORD ckid, DWORD size, DWORD offset, DWORD flags)
Definition: avifile.c:1334
static HRESULT WINAPI IUnknown_fnQueryInterface(IUnknown *iface, REFIID riid, void **ppv)
Definition: avifile.c:161
static const struct IPersistFileVtbl pf_vt
Definition: avifile.c:633
static IAVIFileImpl * impl_from_IPersistFile(IPersistFile *iface)
Definition: avifile.c:130
static const struct IAVIStreamVtbl avist_vt
Definition: avifile.c:1316
static void AVIFILE_UpdateInfo(IAVIFileImpl *This)
Definition: avifile.c:2480
static HRESULT WINAPI IAVIStream_fnSetInfo(IAVIStream *iface, AVISTREAMINFOW *info, LONG infolen)
Definition: avifile.c:1309
static HRESULT WINAPI IAVIFile_fnCreateStream(IAVIFile *iface, IAVIStream **avis, AVISTREAMINFOW *asi)
Definition: avifile.c:322
static HRESULT WINAPI IPersistFile_fnLoad(IPersistFile *iface, LPCOLESTR pszFileName, DWORD dwMode)
Definition: avifile.c:538
HRESULT AVIFILE_CreateAVIFile(IUnknown *pUnkOuter, REFIID riid, void **ppv)
Definition: avifile.c:645
static HRESULT WINAPI IAVIFile_fnDeleteStream(IAVIFile *iface, DWORD fccType, LONG lParam)
Definition: avifile.c:446
LPCWSTR AVIFILE_BasenameW(LPCWSTR szFileName) DECLSPEC_HIDDEN
Definition: factory.c:162
#define IDS_VIDEO
#define DIBWIDTHBYTES(bi)
#define MAX_AVISTREAMS
#define IDS_AVIFILETYPE
#define IDS_AUDIO
#define AVIIF_KEYFRAME
Definition: aviriff.h:131
#define streamtypeAUDIO
Definition: aviriff.h:93
#define AVIIF_LIST
Definition: aviriff.h:130
#define streamtypeVIDEO
Definition: aviriff.h:92
#define ckidSTREAMHEADER
Definition: aviriff.h:88
#define ckidSTREAMFORMAT
Definition: aviriff.h:125
#define TWOCCFromFOURCC(fcc)
Definition: avisplit.c:49
static const WCHAR avifile[]
Definition: avisplitter.c:273
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:33
const GUID IID_IUnknown
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define SEEK_END
Definition: cabinet.c:29
LPARAM lParam
Definition: combotst.c:139
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
Definition: api.c:927
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrlenW
Definition: compat.h:750
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
Definition: mmio.c:1205
MMRESULT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:961
LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Definition: mmio.c:836
HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:693
MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:702
LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
Definition: mmio.c:782
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO *lpckParent, UINT uFlags)
Definition: mmio.c:1107
LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Definition: mmio.c:733
MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO *lpck, UINT uFlags)
Definition: mmio.c:1239
HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:670
#define assert(x)
Definition: debug.h:53
DWORD FOURCC
Definition: dmdls.h:25
#define BI_RGB
Definition: precomp.h:47
ULONG RGBQUAD
Definition: precomp.h:50
HRESULT FindChunkAndKeepExtras(LPEXTRACHUNKS extra, HMMIO hmmio, MMCKINFO *lpck, MMCKINFO *lpckParent, UINT flags)
Definition: extrachunk.c:143
HRESULT WriteExtraChunk(LPEXTRACHUNKS extra, FOURCC ckid, LPCVOID lpData, LONG size)
Definition: extrachunk.c:70
HRESULT ReadExtraChunk(const EXTRACHUNKS *extra, FOURCC ckid, LPVOID lpData, LPLONG size)
Definition: extrachunk.c:32
HRESULT ReadChunkIntoExtra(LPEXTRACHUNKS extra, HMMIO hmmio, const MMCKINFO *lpck)
Definition: extrachunk.c:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLsizei samples
Definition: glext.h:7006
GLuint buffer
Definition: glext.h:5915
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define SEEK_SET
Definition: jmemansi.c:26
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
struct _WAVEFORMATEX * LPWAVEFORMATEX
#define MMIO_FINDRIFF
Definition: mmsystem.h:552
#define MMIO_ALLOCBUF
Definition: mmsystem.h:532
#define MMIO_FINDCHUNK
Definition: mmsystem.h:551
#define FOURCC_LIST
Definition: mmsystem.h:565
#define MMIO_CREATELIST
Definition: mmsystem.h:555
#define MMIO_RWMODE
Definition: mmsystem.h:526
#define MMIO_DIRTY
Definition: mmsystem.h:534
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define MMIO_READ
Definition: mmsystem.h:535
#define MMIO_CREATERIFF
Definition: mmsystem.h:554
char * HPSTR
Definition: mmsystem.h:1477
#define MMIO_FINDLIST
Definition: mmsystem.h:553
#define SEEK_CUR
Definition: util.h:63
ULONG nr
Definition: thread.c:7
static LPOLESTR
Definition: stg_prop.c:27
#define min(a, b)
Definition: monoChain.cc:55
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
const GUID IID_IPersistFile
long LONG
Definition: pedump.c:60
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
const WCHAR * str
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwInitialFrames
Definition: vfw.h:964
DWORD dwStart
Definition: vfw.h:967
DWORD dwQuality
Definition: vfw.h:970
WORD wLanguage
Definition: vfw.h:963
DWORD dwSampleSize
Definition: vfw.h:971
FOURCC fccHandler
Definition: vfw.h:960
DWORD dwScale
Definition: vfw.h:965
FOURCC fccType
Definition: vfw.h:959
DWORD dwFlags
Definition: vfw.h:961
DWORD dwLength
Definition: vfw.h:968
DWORD dwSuggestedBufferSize
Definition: vfw.h:969
struct AVIStreamHeader::@3270 rcFrame
DWORD dwRate
Definition: vfw.h:966
WORD wPriority
Definition: vfw.h:962
DWORD biCompression
Definition: amvideo.idl:35
DWORD biSizeImage
Definition: amvideo.idl:36
WORD wBitsPerSample
Definition: audioclient.idl:45
DWORD nSamplesPerSec
Definition: audioclient.idl:42
DWORD dwChunkLength
Definition: vfw.h:989
DWORD dwChunkOffset
Definition: vfw.h:988
DWORD ckid
Definition: vfw.h:986
DWORD dwFlags
Definition: vfw.h:987
PALETTEENTRY peNew[1]
Definition: vfw.h:996
BYTE bNumEntries
Definition: vfw.h:994
WORD wFlags
Definition: vfw.h:995
BYTE bFirstEntry
Definition: vfw.h:993
DWORD dwSuggestedBufferSize
Definition: avifil32.idl:40
DWORD dwInitialFrames
Definition: avifil32.idl:39
DWORD fccHandler
Definition: avifil32.idl:30
WCHAR szName[64]
Definition: avifil32.idl:46
DWORD dwEditCount
Definition: avifil32.idl:44
DWORD dwFormatChangeCount
Definition: avifil32.idl:45
DWORD dwSampleSize
Definition: avifil32.idl:42
LPVOID lp
Definition: extrachunk.h:33
AVIFILEINFOW fInfo
Definition: avifile.c:98
IAVIFile IAVIFile_iface
Definition: avifile.c:93
DWORD cbIdxRecords
Definition: avifile.c:111
MMCKINFO ckLastRecord
Definition: avifile.c:108
LPWSTR szFileName
Definition: avifile.c:115
IUnknown * outer_unk
Definition: avifile.c:95
AVIINDEXENTRY * idxRecords
Definition: avifile.c:109
UINT uMode
Definition: avifile.c:116
DWORD dwNextFramePos
Definition: avifile.c:105
IUnknown IUnknown_inner
Definition: avifile.c:92
HMMIO hmmio
Definition: avifile.c:114
LONG ref
Definition: avifile.c:96
IPersistFile IPersistFile_iface
Definition: avifile.c:94
DWORD dwMoviChunkPos
Definition: avifile.c:103
DWORD dwInitialFrames
Definition: avifile.c:106
EXTRACHUNKS fileextra
Definition: avifile.c:101
IAVIStreamImpl * ppStreams[MAX_AVISTREAMS]
Definition: avifile.c:99
BOOL fDirty
Definition: avifile.c:117
DWORD dwIdxChunkPos
Definition: avifile.c:104
DWORD nIdxRecords
Definition: avifile.c:110
DWORD nStream
Definition: avifile.c:64
AVIINDEXENTRY * idxFrames
Definition: avifile.c:80
DWORD dwCurrentFrame
Definition: avifile.c:77
IAVIFileImpl * paf
Definition: avifile.c:63
IAVIStream IAVIStream_iface
Definition: acmstream.c:41
AVIINDEXENTRY * idxFmtChanges
Definition: avifile.c:82
DWORD nIdxFrames
Definition: avifile.c:81
DWORD cbFormat
Definition: avifile.c:68
LPVOID lpFormat
Definition: avifile.c:67
DWORD nIdxFmtChanges
Definition: avifile.c:83
AVISTREAMINFOW sInfo
Definition: acmstream.c:46
EXTRACHUNKS extra
Definition: avifile.c:73
LONG lLastFrame
Definition: avifile.c:79
LPDWORD lpBuffer
Definition: avifile.c:75
DWORD cbHandlerData
Definition: avifile.c:71
DWORD cbBuffer
Definition: avifile.c:76
LPVOID lpHandlerData
Definition: avifile.c:70
FOURCC ckid
Definition: mmsystem.h:1507
DWORD cksize
Definition: mmsystem.h:1508
DWORD dwDataOffset
Definition: mmsystem.h:1510
FOURCC fccType
Definition: mmsystem.h:1509
DWORD dwWidth
Definition: vfw.h:949
DWORD dwSuggestedBufferSize
Definition: vfw.h:948
DWORD dwHeight
Definition: vfw.h:950
DWORD dwPaddingGranularity
Definition: vfw.h:943
DWORD dwStreams
Definition: vfw.h:947
DWORD dwMaxBytesPerSec
Definition: vfw.h:942
DWORD dwInitialFrames
Definition: vfw.h:946
DWORD dwFlags
Definition: vfw.h:944
DWORD dwMicroSecPerFrame
Definition: vfw.h:941
DWORD dwTotalFrames
Definition: vfw.h:945
Definition: mem.c:156
Definition: send.c:48
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
#define max(a, b)
Definition: svc.c:63
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t * LPLONG
Definition: typedefs.h:58
uint32_t * LPDWORD
Definition: typedefs.h:59
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
#define FIND_NEXT
Definition: vfw.h:1118
#define comptypeDIB
Definition: vfw.h:147
#define listtypeAVIMOVIE
Definition: vfw.h:898
#define cktypePALchange
Definition: vfw.h:912
#define IAVIStream_AddRef(p)
Definition: vfw.h:1176
#define listtypeSTREAMHEADER
Definition: vfw.h:892
#define FIND_OFFSET
Definition: vfw.h:1130
#define listtypeAVIRECORD
Definition: vfw.h:899
#define AVISTREAMINFO_FORMATCHANGES
Definition: vfw.h:1049
#define AVIERR_UNSUPPORTED
Definition: vfw.h:1743
#define AVIStreamSampleToSample(pavi1, pavi2, samp2)
Definition: vfw.h:1442
#define FIND_LENGTH
Definition: vfw.h:1129
#define FIND_INDEX
Definition: vfw.h:1132
#define AVIERR_ERROR
Definition: vfw.h:1761
#define cktypeDIBcompressed
Definition: vfw.h:911
#define FIND_PREV
Definition: vfw.h:1119
#define AVIERR_FILEOPEN
Definition: vfw.h:1753
#define AVIERR_FILEREAD
Definition: vfw.h:1751
#define FIND_SIZE
Definition: vfw.h:1131
#define FIND_TYPE
Definition: vfw.h:1122
#define AVIERR_BADSIZE
Definition: vfw.h:1749
#define listtypeAVIHEADER
Definition: vfw.h:890
#define AVIERR_BADFORMAT
Definition: vfw.h:1744
#define AVIFILECAPS_CANWRITE
Definition: vfw.h:1061
#define AVI_HEADERSIZE
Definition: vfw.h:935
#define AVIERR_FILEWRITE
Definition: vfw.h:1752
#define FIND_ANY
Definition: vfw.h:1124
#define ckidAVIPADDING
Definition: vfw.h:916
#define FIND_FROM_START
Definition: vfw.h:1120
#define AVIERR_READONLY
Definition: vfw.h:1756
#define cktypeWAVEbytes
Definition: vfw.h:913
#define ckidSTREAMNAME
Definition: vfw.h:896
#define AVIERR_OK
Definition: vfw.h:1740
#define FIND_RET
Definition: vfw.h:1127
#define AVIFILEINFO_ISINTERLEAVED
Definition: vfw.h:1054
#define ckidAVIMAINHDR
Definition: vfw.h:891
#define ckidSTREAMHANDLERDATA
Definition: vfw.h:895
#define AVIIF_NOTIME
Definition: vfw.h:982
#define MAKEAVICKID(tcc, stream)
Definition: vfw.h:923
#define AVIFILEINFO_HASINDEX
Definition: vfw.h:1052
#define IAVIFile_Release(p)
Definition: vfw.h:1604
#define formtypeAVI
Definition: vfw.h:889
#define AVIFILEINFO_TRUSTCKTYPE
Definition: vfw.h:1055
#define ckidAVINEWINDEX
Definition: vfw.h:901
#define IAVIFile_AddRef(p)
Definition: vfw.h:1603
#define AVIERR_MEMORY
Definition: vfw.h:1745
#define FIND_KEY
Definition: vfw.h:1123
#define AVIERR_BUFFERTOOSMALL
Definition: vfw.h:1758
struct _AVIINDEXENTRY AVIINDEXENTRY
#define cktypeDIBbits
Definition: vfw.h:910
#define AVIFILEINFO_COPYRIGHTED
Definition: vfw.h:1057
#define FIND_FORMAT
Definition: vfw.h:1125
#define AVIERR_NODATA
Definition: vfw.h:1757
#define AVIFILECAPS_CANREAD
Definition: vfw.h:1060
#define AVIERR_BADPARAM
Definition: vfw.h:1748
#define StreamFromFOURCC(fcc)
Definition: vfw.h:919
#define OF_CREATE
Definition: winbase.h:125
LONG_PTR LPARAM
Definition: windef.h:208
CONST void * LPCVOID
Definition: windef.h:191
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define E_NOINTERFACE
Definition: winerror.h:2364
#define BI_RLE8
Definition: wingdi.h:35
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
BOOL WINAPI SetRectEmpty(_Out_ LPRECT)
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
static unsigned int block
Definition: xmlmemory.c:101
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193