2 * Copyright 1999 Marcus Meissner
3 * Copyright 2002-2003 Michael Günnewig
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #define COM_NO_WINDOWS_H
40 #include "avifile_private.h"
42 #include "wine/debug.h"
43 #include "wine/unicode.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
48 /***********************************************************************
49 * for AVIBuildFilterW -- uses fixed size table
51 #define MAX_FILTERS 30 /* 30 => 7kB */
53 typedef struct _AVIFilter
{
55 WCHAR szExtensions
[MAX_FILTERS
* 7];
58 /***********************************************************************
65 LPAVICOMPRESSOPTIONS
*ppOptions
;
69 /***********************************************************************
70 * copied from dlls/ole32/compobj.c
72 static HRESULT
AVIFILE_CLSIDFromString(LPCSTR idstr
, LPCLSID id
)
80 memset(id
, 0, sizeof(CLSID
));
84 /* validate the CLSID string */
85 if (lstrlenA(idstr
) != 38)
86 return CO_E_CLASSSTRING
;
88 s
= (BYTE
const*)idstr
;
89 if ((s
[0]!='{') || (s
[9]!='-') || (s
[14]!='-') || (s
[19]!='-') ||
90 (s
[24]!='-') || (s
[37]!='}'))
91 return CO_E_CLASSSTRING
;
93 for (i
= 1; i
< 37; i
++) {
94 if ((i
== 9) || (i
== 14) || (i
== 19) || (i
== 24))
96 if (!(((s
[i
] >= '0') && (s
[i
] <= '9')) ||
97 ((s
[i
] >= 'a') && (s
[i
] <= 'f')) ||
98 ((s
[i
] >= 'A') && (s
[i
] <= 'F')))
100 return CO_E_CLASSSTRING
;
103 TRACE("%s -> %p\n", s
, id
);
105 /* quick lookup table */
106 memset(table
, 0, 256);
108 for (i
= 0; i
< 10; i
++)
111 for (i
= 0; i
< 6; i
++) {
112 table
['A' + i
] = i
+10;
113 table
['a' + i
] = i
+10;
116 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
119 s
++; /* skip leading brace */
120 for (i
= 0; i
< 4; i
++) {
121 p
[3 - i
] = table
[*s
]<<4 | table
[*(s
+1)];
127 for (i
= 0; i
< 2; i
++) {
128 p
[1-i
] = table
[*s
]<<4 | table
[*(s
+1)];
134 for (i
= 0; i
< 2; i
++) {
135 p
[1-i
] = table
[*s
]<<4 | table
[*(s
+1)];
141 /* these are just sequential bytes */
142 for (i
= 0; i
< 2; i
++) {
143 *p
++ = table
[*s
]<<4 | table
[*(s
+1)];
148 for (i
= 0; i
< 6; i
++) {
149 *p
++ = table
[*s
]<<4 | table
[*(s
+1)];
156 static BOOL
AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile
, LPCLSID lpclsid
)
160 LPWSTR szExt
= strrchrW(szFile
, '.');
161 LONG len
= sizeof(szValue
) / sizeof(szValue
[0]);
168 wsprintfA(szRegKey
, "AVIFile\\Extensions\\%.3ls", szExt
);
169 if (RegQueryValueA(HKEY_CLASSES_ROOT
, szRegKey
, szValue
, &len
) != ERROR_SUCCESS
)
172 return (AVIFILE_CLSIDFromString(szValue
, lpclsid
) == S_OK
);
175 /***********************************************************************
176 * AVIFileInit (AVIFIL32.@)
177 * AVIFileInit (AVIFILE.100)
179 void WINAPI
AVIFileInit(void) {
183 /***********************************************************************
184 * AVIFileExit (AVIFIL32.@)
185 * AVIFileExit (AVIFILE.101)
187 void WINAPI
AVIFileExit(void) {
188 /* need to free ole32.dll if we are the last exit call */
189 /* OleUnitialize() */
190 FIXME("(): stub!\n");
193 /***********************************************************************
194 * AVIFileOpen (AVIFIL32.@)
195 * AVIFileOpenA (AVIFIL32.@)
196 * AVIFileOpen (AVIFILE.102)
198 HRESULT WINAPI
AVIFileOpenA(PAVIFILE
*ppfile
, LPCSTR szFile
, UINT uMode
,
201 LPWSTR wszFile
= NULL
;
205 TRACE("(%p,%s,0x%08X,%s)\n", ppfile
, debugstr_a(szFile
), uMode
,
206 debugstr_guid(lpHandler
));
208 /* check parameters */
209 if (ppfile
== NULL
|| szFile
== NULL
)
210 return AVIERR_BADPARAM
;
212 /* convert ASCII string to Unicode and call unicode function */
213 len
= MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, NULL
, 0);
215 return AVIERR_BADPARAM
;
217 wszFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
219 return AVIERR_MEMORY
;
221 MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, wszFile
, len
);
223 hr
= AVIFileOpenW(ppfile
, wszFile
, uMode
, lpHandler
);
225 HeapFree(GetProcessHeap(), 0, wszFile
);
230 /***********************************************************************
231 * AVIFileOpenW (AVIFIL32.@)
233 HRESULT WINAPI
AVIFileOpenW(PAVIFILE
*ppfile
, LPCWSTR szFile
, UINT uMode
,
236 IPersistFile
*ppersist
= NULL
;
240 TRACE("(%p,%s,0x%X,%s)\n", ppfile
, debugstr_w(szFile
), uMode
,
241 debugstr_guid(lpHandler
));
243 /* check parameters */
244 if (ppfile
== NULL
|| szFile
== NULL
)
245 return AVIERR_BADPARAM
;
249 /* if no handler then try guessing it by extension */
250 if (lpHandler
== NULL
) {
251 if (! AVIFILE_GetFileHandlerByExtension(szFile
, &clsidHandler
))
252 return AVIERR_UNSUPPORTED
;
254 memcpy(&clsidHandler
, lpHandler
, sizeof(clsidHandler
));
256 /* create instance of handler */
257 hr
= CoCreateInstance(&clsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIFile
, (LPVOID
*)ppfile
);
258 if (FAILED(hr
) || *ppfile
== NULL
)
261 /* ask for IPersistFile interface for loading/creating the file */
262 hr
= IAVIFile_QueryInterface(*ppfile
, &IID_IPersistFile
, (LPVOID
*)&ppersist
);
263 if (FAILED(hr
) || ppersist
== NULL
) {
264 IAVIFile_Release(*ppfile
);
269 hr
= IPersistFile_Load(ppersist
, szFile
, uMode
);
270 IPersistFile_Release(ppersist
);
272 IAVIFile_Release(*ppfile
);
279 /***********************************************************************
280 * AVIFileAddRef (AVIFIL32.@)
281 * AVIFileAddRef (AVIFILE.140)
283 ULONG WINAPI
AVIFileAddRef(PAVIFILE pfile
)
285 TRACE("(%p)\n", pfile
);
288 ERR(": bad handle passed!\n");
292 return IAVIFile_AddRef(pfile
);
295 /***********************************************************************
296 * AVIFileRelease (AVIFIL32.@)
297 * AVIFileRelease (AVIFILE.141)
299 ULONG WINAPI
AVIFileRelease(PAVIFILE pfile
)
301 TRACE("(%p)\n", pfile
);
304 ERR(": bad handle passed!\n");
308 return IAVIFile_Release(pfile
);
311 /***********************************************************************
312 * AVIFileInfo (AVIFIL32.@)
313 * AVIFileInfoA (AVIFIL32.@)
314 * AVIFileInfo (AVIFILE.142)
316 HRESULT WINAPI
AVIFileInfoA(PAVIFILE pfile
, LPAVIFILEINFOA afi
, LONG size
)
321 TRACE("(%p,%p,%ld)\n", pfile
, afi
, size
);
324 return AVIERR_BADHANDLE
;
325 if ((DWORD
)size
< sizeof(AVIFILEINFOA
))
326 return AVIERR_BADSIZE
;
328 hres
= IAVIFile_Info(pfile
, &afiw
, sizeof(afiw
));
330 memcpy(afi
, &afiw
, sizeof(*afi
) - sizeof(afi
->szFileType
));
331 WideCharToMultiByte(CP_ACP
, 0, afiw
.szFileType
, -1, afi
->szFileType
,
332 sizeof(afi
->szFileType
), NULL
, NULL
);
333 afi
->szFileType
[sizeof(afi
->szFileType
) - 1] = 0;
338 /***********************************************************************
339 * AVIFileInfoW (AVIFIL32.@)
341 HRESULT WINAPI
AVIFileInfoW(PAVIFILE pfile
, LPAVIFILEINFOW afiw
, LONG size
)
343 TRACE("(%p,%p,%ld)\n", pfile
, afiw
, size
);
346 return AVIERR_BADHANDLE
;
348 return IAVIFile_Info(pfile
, afiw
, size
);
351 /***********************************************************************
352 * AVIFileGetStream (AVIFIL32.@)
353 * AVIFileGetStream (AVIFILE.143)
355 HRESULT WINAPI
AVIFileGetStream(PAVIFILE pfile
, PAVISTREAM
*avis
,
356 DWORD fccType
, LONG lParam
)
358 TRACE("(%p,%p,'%4.4s',%ld)\n", pfile
, avis
, (char*)&fccType
, lParam
);
361 return AVIERR_BADHANDLE
;
363 return IAVIFile_GetStream(pfile
, avis
, fccType
, lParam
);
366 /***********************************************************************
367 * AVIFileCreateStream (AVIFIL32.@)
368 * AVIFileCreateStreamA (AVIFIL32.@)
369 * AVIFileCreateStream (AVIFILE.144)
371 HRESULT WINAPI
AVIFileCreateStreamA(PAVIFILE pfile
, PAVISTREAM
*ppavi
,
372 LPAVISTREAMINFOA psi
)
376 TRACE("(%p,%p,%p)\n", pfile
, ppavi
, psi
);
379 return AVIERR_BADHANDLE
;
381 /* Only the szName at the end is different */
382 memcpy(&psiw
, psi
, sizeof(*psi
) - sizeof(psi
->szName
));
383 MultiByteToWideChar(CP_ACP
, 0, psi
->szName
, -1, psiw
.szName
,
384 sizeof(psiw
.szName
) / sizeof(psiw
.szName
[0]));
386 return IAVIFile_CreateStream(pfile
, ppavi
, &psiw
);
389 /***********************************************************************
390 * AVIFileCreateStreamW (AVIFIL32.@)
392 HRESULT WINAPI
AVIFileCreateStreamW(PAVIFILE pfile
, PAVISTREAM
*avis
,
393 LPAVISTREAMINFOW asi
)
395 TRACE("(%p,%p,%p)\n", pfile
, avis
, asi
);
398 return AVIERR_BADHANDLE
;
400 return IAVIFile_CreateStream(pfile
, avis
, asi
);
403 /***********************************************************************
404 * AVIFileWriteData (AVIFIL32.@)
405 * AVIFileWriteData (AVIFILE.146)
407 HRESULT WINAPI
AVIFileWriteData(PAVIFILE pfile
,DWORD fcc
,LPVOID lp
,LONG size
)
409 TRACE("(%p,'%4.4s',%p,%ld)\n", pfile
, (char*)&fcc
, lp
, size
);
412 return AVIERR_BADHANDLE
;
414 return IAVIFile_WriteData(pfile
, fcc
, lp
, size
);
417 /***********************************************************************
418 * AVIFileReadData (AVIFIL32.@)
419 * AVIFileReadData (AVIFILE.147)
421 HRESULT WINAPI
AVIFileReadData(PAVIFILE pfile
,DWORD fcc
,LPVOID lp
,LPLONG size
)
423 TRACE("(%p,'%4.4s',%p,%p)\n", pfile
, (char*)&fcc
, lp
, size
);
426 return AVIERR_BADHANDLE
;
428 return IAVIFile_ReadData(pfile
, fcc
, lp
, size
);
431 /***********************************************************************
432 * AVIFileEndRecord (AVIFIL32.@)
433 * AVIFileEndRecord (AVIFILE.148)
435 HRESULT WINAPI
AVIFileEndRecord(PAVIFILE pfile
)
437 TRACE("(%p)\n", pfile
);
440 return AVIERR_BADHANDLE
;
442 return IAVIFile_EndRecord(pfile
);
445 /***********************************************************************
446 * AVIStreamAddRef (AVIFIL32.@)
447 * AVIStreamAddRef (AVIFILE.160)
449 ULONG WINAPI
AVIStreamAddRef(PAVISTREAM pstream
)
451 TRACE("(%p)\n", pstream
);
453 if (pstream
== NULL
) {
454 ERR(": bad handle passed!\n");
458 return IAVIStream_AddRef(pstream
);
461 /***********************************************************************
462 * AVIStreamRelease (AVIFIL32.@)
463 * AVIStreamRelease (AVIFILE.161)
465 ULONG WINAPI
AVIStreamRelease(PAVISTREAM pstream
)
467 TRACE("(%p)\n", pstream
);
469 if (pstream
== NULL
) {
470 ERR(": bad handle passed!\n");
474 return IAVIStream_Release(pstream
);
477 /***********************************************************************
478 * AVIStreamCreate (AVIFIL32.@)
479 * AVIStreamCreate (AVIFILE.104)
481 HRESULT WINAPI
AVIStreamCreate(PAVISTREAM
*ppavi
, LONG lParam1
, LONG lParam2
,
482 LPCLSID pclsidHandler
)
486 TRACE("(%p,0x%08lX,0x%08lX,%s)\n", ppavi
, lParam1
, lParam2
,
487 debugstr_guid(pclsidHandler
));
490 return AVIERR_BADPARAM
;
493 if (pclsidHandler
== NULL
)
494 return AVIERR_UNSUPPORTED
;
496 hr
= CoCreateInstance(pclsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIStream
, (LPVOID
*)ppavi
);
497 if (FAILED(hr
) || *ppavi
== NULL
)
500 hr
= IAVIStream_Create(*ppavi
, lParam1
, lParam2
);
502 IAVIStream_Release(*ppavi
);
509 /***********************************************************************
510 * AVIStreamInfo (AVIFIL32.@)
511 * AVIStreamInfoA (AVIFIL32.@)
512 * AVIStreamInfo (AVIFILE.162)
514 HRESULT WINAPI
AVIStreamInfoA(PAVISTREAM pstream
, LPAVISTREAMINFOA asi
,
520 TRACE("(%p,%p,%ld)\n", pstream
, asi
, size
);
523 return AVIERR_BADHANDLE
;
524 if ((DWORD
)size
< sizeof(AVISTREAMINFOA
))
525 return AVIERR_BADSIZE
;
527 hres
= IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
));
529 memcpy(asi
, &asiw
, sizeof(asiw
) - sizeof(asiw
.szName
));
530 WideCharToMultiByte(CP_ACP
, 0, asiw
.szName
, -1, asi
->szName
,
531 sizeof(asi
->szName
), NULL
, NULL
);
532 asi
->szName
[sizeof(asi
->szName
) - 1] = 0;
537 /***********************************************************************
538 * AVIStreamInfoW (AVIFIL32.@)
540 HRESULT WINAPI
AVIStreamInfoW(PAVISTREAM pstream
, LPAVISTREAMINFOW asi
,
543 TRACE("(%p,%p,%ld)\n", pstream
, asi
, size
);
546 return AVIERR_BADHANDLE
;
548 return IAVIStream_Info(pstream
, asi
, size
);
551 /***********************************************************************
552 * AVIStreamFindSample (AVIFIL32.@)
553 * AVIStreamFindSample (AVIFILE.163)
555 HRESULT WINAPI
AVIStreamFindSample(PAVISTREAM pstream
, LONG pos
, DWORD flags
)
557 TRACE("(%p,%ld,0x%lX)\n", pstream
, pos
, flags
);
562 return IAVIStream_FindSample(pstream
, pos
, flags
);
565 /***********************************************************************
566 * AVIStreamReadFormat (AVIFIL32.@)
567 * AVIStreamReadFormat (AVIFILE.164)
569 HRESULT WINAPI
AVIStreamReadFormat(PAVISTREAM pstream
, LONG pos
,
570 LPVOID format
, LPLONG formatsize
)
572 TRACE("(%p,%ld,%p,%p)\n", pstream
, pos
, format
, formatsize
);
575 return AVIERR_BADHANDLE
;
577 return IAVIStream_ReadFormat(pstream
, pos
, format
, formatsize
);
580 /***********************************************************************
581 * AVIStreamSetFormat (AVIFIL32.@)
582 * AVIStreamSetFormat (AVIFILE.169)
584 HRESULT WINAPI
AVIStreamSetFormat(PAVISTREAM pstream
, LONG pos
,
585 LPVOID format
, LONG formatsize
)
587 TRACE("(%p,%ld,%p,%ld)\n", pstream
, pos
, format
, formatsize
);
590 return AVIERR_BADHANDLE
;
592 return IAVIStream_SetFormat(pstream
, pos
, format
, formatsize
);
595 /***********************************************************************
596 * AVIStreamRead (AVIFIL32.@)
597 * AVIStreamRead (AVIFILE.167)
599 HRESULT WINAPI
AVIStreamRead(PAVISTREAM pstream
, LONG start
, LONG samples
,
600 LPVOID buffer
, LONG buffersize
,
601 LPLONG bytesread
, LPLONG samplesread
)
603 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", pstream
, start
, samples
, buffer
,
604 buffersize
, bytesread
, samplesread
);
607 return AVIERR_BADHANDLE
;
609 return IAVIStream_Read(pstream
, start
, samples
, buffer
, buffersize
,
610 bytesread
, samplesread
);
613 /***********************************************************************
614 * AVIStreamWrite (AVIFIL32.@)
615 * AVIStreamWrite (AVIFILE.168)
617 HRESULT WINAPI
AVIStreamWrite(PAVISTREAM pstream
, LONG start
, LONG samples
,
618 LPVOID buffer
, LONG buffersize
, DWORD flags
,
619 LPLONG sampwritten
, LPLONG byteswritten
)
621 TRACE("(%p,%ld,%ld,%p,%ld,0x%lX,%p,%p)\n", pstream
, start
, samples
, buffer
,
622 buffersize
, flags
, sampwritten
, byteswritten
);
625 return AVIERR_BADHANDLE
;
627 return IAVIStream_Write(pstream
, start
, samples
, buffer
, buffersize
,
628 flags
, sampwritten
, byteswritten
);
631 /***********************************************************************
632 * AVIStreamReadData (AVIFIL32.@)
633 * AVIStreamReadData (AVIFILE.165)
635 HRESULT WINAPI
AVIStreamReadData(PAVISTREAM pstream
, DWORD fcc
, LPVOID lp
,
638 TRACE("(%p,'%4.4s',%p,%p)\n", pstream
, (char*)&fcc
, lp
, lpread
);
641 return AVIERR_BADHANDLE
;
643 return IAVIStream_ReadData(pstream
, fcc
, lp
, lpread
);
646 /***********************************************************************
647 * AVIStreamWriteData (AVIFIL32.@)
648 * AVIStreamWriteData (AVIFILE.166)
650 HRESULT WINAPI
AVIStreamWriteData(PAVISTREAM pstream
, DWORD fcc
, LPVOID lp
,
653 TRACE("(%p,'%4.4s',%p,%ld)\n", pstream
, (char*)&fcc
, lp
, size
);
656 return AVIERR_BADHANDLE
;
658 return IAVIStream_WriteData(pstream
, fcc
, lp
, size
);
661 /***********************************************************************
662 * AVIStreamGetFrameOpen (AVIFIL32.@)
663 * AVIStreamGetFrameOpen (AVIFILE.112)
665 PGETFRAME WINAPI
AVIStreamGetFrameOpen(PAVISTREAM pstream
,
666 LPBITMAPINFOHEADER lpbiWanted
)
670 TRACE("(%p,%p)\n", pstream
, lpbiWanted
);
672 if (FAILED(IAVIStream_QueryInterface(pstream
, &IID_IGetFrame
, (LPVOID
*)&pg
)) ||
674 pg
= AVIFILE_CreateGetFrame(pstream
);
679 if (FAILED(IGetFrame_SetFormat(pg
, lpbiWanted
, NULL
, 0, 0, -1, -1))) {
680 IGetFrame_Release(pg
);
687 /***********************************************************************
688 * AVIStreamGetFrame (AVIFIL32.@)
689 * AVIStreamGetFrame (AVIFILE.110)
691 LPVOID WINAPI
AVIStreamGetFrame(PGETFRAME pg
, LONG pos
)
693 TRACE("(%p,%ld)\n", pg
, pos
);
698 return IGetFrame_GetFrame(pg
, pos
);
701 /***********************************************************************
702 * AVIStreamGetFrameClose (AVIFIL32.@)
703 * AVIStreamGetFrameClose (AVIFILE.111)
705 HRESULT WINAPI
AVIStreamGetFrameClose(PGETFRAME pg
)
710 return IGetFrame_Release(pg
);
714 /***********************************************************************
715 * AVIMakeCompressedStream (AVIFIL32.@)
717 HRESULT WINAPI
AVIMakeCompressedStream(PAVISTREAM
*ppsCompressed
,
719 LPAVICOMPRESSOPTIONS aco
,
720 LPCLSID pclsidHandler
)
727 LONG size
= sizeof(szValue
);
729 TRACE("(%p,%p,%p,%s)\n", ppsCompressed
, psSource
, aco
,
730 debugstr_guid(pclsidHandler
));
732 if (ppsCompressed
== NULL
)
733 return AVIERR_BADPARAM
;
734 if (psSource
== NULL
)
735 return AVIERR_BADHANDLE
;
737 *ppsCompressed
= NULL
;
739 /* if no handler given get default ones based on streamtype */
740 if (pclsidHandler
== NULL
) {
741 hr
= IAVIStream_Info(psSource
, &asiw
, sizeof(asiw
));
745 wsprintfA(szRegKey
, "AVIFile\\Compressors\\%4.4s", (char*)&asiw
.fccType
);
746 if (RegQueryValueA(HKEY_CLASSES_ROOT
, szRegKey
, szValue
, &size
) != ERROR_SUCCESS
)
747 return AVIERR_UNSUPPORTED
;
748 if (AVIFILE_CLSIDFromString(szValue
, &clsidHandler
) != S_OK
)
749 return AVIERR_UNSUPPORTED
;
751 memcpy(&clsidHandler
, pclsidHandler
, sizeof(clsidHandler
));
753 hr
= CoCreateInstance(&clsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIStream
, (LPVOID
*)ppsCompressed
);
754 if (FAILED(hr
) || *ppsCompressed
== NULL
)
757 hr
= IAVIStream_Create(*ppsCompressed
, (LPARAM
)psSource
, (LPARAM
)aco
);
759 IAVIStream_Release(*ppsCompressed
);
760 *ppsCompressed
= NULL
;
766 /***********************************************************************
767 * AVIMakeFileFromStreams (AVIFIL32.@)
769 HRESULT WINAPI
AVIMakeFileFromStreams(PAVIFILE
*ppfile
, int nStreams
,
770 PAVISTREAM
*ppStreams
)
772 TRACE("(%p,%d,%p)\n", ppfile
, nStreams
, ppStreams
);
774 if (nStreams
< 0 || ppfile
== NULL
|| ppStreams
== NULL
)
775 return AVIERR_BADPARAM
;
777 *ppfile
= AVIFILE_CreateAVITempFile(nStreams
, ppStreams
);
779 return AVIERR_MEMORY
;
784 /***********************************************************************
785 * AVIStreamOpenFromFile (AVIFIL32.@)
786 * AVIStreamOpenFromFileA (AVIFIL32.@)
787 * AVIStreamOpenFromFile (AVIFILE.103)
789 HRESULT WINAPI
AVIStreamOpenFromFileA(PAVISTREAM
*ppavi
, LPCSTR szFile
,
790 DWORD fccType
, LONG lParam
,
791 UINT mode
, LPCLSID pclsidHandler
)
793 PAVIFILE pfile
= NULL
;
796 TRACE("(%p,%s,'%4.4s',%ld,0x%X,%s)\n", ppavi
, debugstr_a(szFile
),
797 (char*)&fccType
, lParam
, mode
, debugstr_guid(pclsidHandler
));
799 if (ppavi
== NULL
|| szFile
== NULL
)
800 return AVIERR_BADPARAM
;
804 hr
= AVIFileOpenA(&pfile
, szFile
, mode
, pclsidHandler
);
805 if (FAILED(hr
) || pfile
== NULL
)
808 hr
= IAVIFile_GetStream(pfile
, ppavi
, fccType
, lParam
);
809 IAVIFile_Release(pfile
);
814 /***********************************************************************
815 * AVIStreamOpenFromFileW (AVIFIL32.@)
817 HRESULT WINAPI
AVIStreamOpenFromFileW(PAVISTREAM
*ppavi
, LPCWSTR szFile
,
818 DWORD fccType
, LONG lParam
,
819 UINT mode
, LPCLSID pclsidHandler
)
821 PAVIFILE pfile
= NULL
;
824 TRACE("(%p,%s,'%4.4s',%ld,0x%X,%s)\n", ppavi
, debugstr_w(szFile
),
825 (char*)&fccType
, lParam
, mode
, debugstr_guid(pclsidHandler
));
827 if (ppavi
== NULL
|| szFile
== NULL
)
828 return AVIERR_BADPARAM
;
832 hr
= AVIFileOpenW(&pfile
, szFile
, mode
, pclsidHandler
);
833 if (FAILED(hr
) || pfile
== NULL
)
836 hr
= IAVIFile_GetStream(pfile
, ppavi
, fccType
, lParam
);
837 IAVIFile_Release(pfile
);
842 /***********************************************************************
843 * AVIStreamBeginStreaming (AVIFIL32.@)
845 LONG WINAPI
AVIStreamBeginStreaming(PAVISTREAM pavi
, LONG lStart
, LONG lEnd
, LONG lRate
)
847 IAVIStreaming
* pstream
= NULL
;
850 TRACE("(%p,%ld,%ld,%ld)\n", pavi
, lStart
, lEnd
, lRate
);
853 return AVIERR_BADHANDLE
;
855 hr
= IAVIStream_QueryInterface(pavi
, &IID_IAVIStreaming
, (LPVOID
*)&pstream
);
856 if (SUCCEEDED(hr
) && pstream
!= NULL
) {
857 hr
= IAVIStreaming_Begin(pstream
, lStart
, lEnd
, lRate
);
858 IAVIStreaming_Release(pstream
);
865 /***********************************************************************
866 * AVIStreamEndStreaming (AVIFIL32.@)
868 LONG WINAPI
AVIStreamEndStreaming(PAVISTREAM pavi
)
870 IAVIStreaming
* pstream
= NULL
;
873 TRACE("(%p)\n", pavi
);
875 hr
= IAVIStream_QueryInterface(pavi
, &IID_IAVIStreaming
, (LPVOID
*)&pstream
);
876 if (SUCCEEDED(hr
) && pstream
!= NULL
) {
877 IAVIStreaming_End(pstream
);
878 IAVIStreaming_Release(pstream
);
884 /***********************************************************************
885 * AVIStreamStart (AVIFILE.130)
886 * AVIStreamStart (AVIFIL32.@)
888 LONG WINAPI
AVIStreamStart(PAVISTREAM pstream
)
892 TRACE("(%p)\n", pstream
);
897 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
903 /***********************************************************************
904 * AVIStreamLength (AVIFILE.131)
905 * AVIStreamLength (AVIFIL32.@)
907 LONG WINAPI
AVIStreamLength(PAVISTREAM pstream
)
911 TRACE("(%p)\n", pstream
);
916 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
919 return asiw
.dwLength
;
922 /***********************************************************************
923 * AVIStreamSampleToTime (AVIFILE.133)
924 * AVIStreamSampleToTime (AVIFIL32.@)
926 LONG WINAPI
AVIStreamSampleToTime(PAVISTREAM pstream
, LONG lSample
)
931 TRACE("(%p,%ld)\n", pstream
, lSample
);
936 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
938 if (asiw
.dwRate
== 0)
941 /* limit to stream bounds */
942 if (lSample
< asiw
.dwStart
)
943 lSample
= asiw
.dwStart
;
944 if (lSample
> asiw
.dwStart
+ asiw
.dwLength
)
945 lSample
= asiw
.dwStart
+ asiw
.dwLength
;
947 if (asiw
.dwRate
/ asiw
.dwScale
< 1000)
948 time
= (LONG
)(((float)lSample
* asiw
.dwScale
* 1000) / asiw
.dwRate
);
950 time
= (LONG
)(((float)lSample
* asiw
.dwScale
* 1000 + (asiw
.dwRate
- 1)) / asiw
.dwRate
);
952 TRACE(" -> %ld\n",time
);
956 /***********************************************************************
957 * AVIStreamTimeToSample (AVIFILE.132)
958 * AVIStreamTimeToSample (AVIFIL32.@)
960 LONG WINAPI
AVIStreamTimeToSample(PAVISTREAM pstream
, LONG lTime
)
965 TRACE("(%p,%ld)\n", pstream
, lTime
);
967 if (pstream
== NULL
|| lTime
< 0)
970 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
972 if (asiw
.dwScale
== 0)
975 if (asiw
.dwRate
/ asiw
.dwScale
< 1000)
976 sample
= (LONG
)((((float)asiw
.dwRate
* lTime
) / (asiw
.dwScale
* 1000)));
978 sample
= (LONG
)(((float)asiw
.dwRate
* lTime
+ (asiw
.dwScale
* 1000 - 1)) / (asiw
.dwScale
* 1000));
980 /* limit to stream bounds */
981 if (sample
< asiw
.dwStart
)
982 sample
= asiw
.dwStart
;
983 if (sample
> asiw
.dwStart
+ asiw
.dwLength
)
984 sample
= asiw
.dwStart
+ asiw
.dwLength
;
986 TRACE(" -> %ld\n", sample
);
990 /***********************************************************************
991 * AVIBuildFilter (AVIFIL32.@)
992 * AVIBuildFilterA (AVIFIL32.@)
993 * AVIBuildFilter (AVIFILE.123)
995 HRESULT WINAPI
AVIBuildFilterA(LPSTR szFilter
, LONG cbFilter
, BOOL fSaving
)
1000 TRACE("(%p,%ld,%d)\n", szFilter
, cbFilter
, fSaving
);
1002 /* check parameters */
1003 if (szFilter
== NULL
)
1004 return AVIERR_BADPARAM
;
1006 return AVIERR_BADSIZE
;
1011 wszFilter
= HeapAlloc(GetProcessHeap(), 0, cbFilter
* sizeof(WCHAR
));
1012 if (wszFilter
== NULL
)
1013 return AVIERR_MEMORY
;
1015 hr
= AVIBuildFilterW(wszFilter
, cbFilter
, fSaving
);
1016 if (SUCCEEDED(hr
)) {
1017 WideCharToMultiByte(CP_ACP
, 0, wszFilter
, cbFilter
,
1018 szFilter
, cbFilter
, NULL
, NULL
);
1021 HeapFree(GetProcessHeap(), 0, wszFilter
);
1026 /***********************************************************************
1027 * AVIBuildFilterW (AVIFIL32.@)
1029 HRESULT WINAPI
AVIBuildFilterW(LPWSTR szFilter
, LONG cbFilter
, BOOL fSaving
)
1031 static const WCHAR szClsid
[] = {'C','L','S','I','D',0};
1032 static const WCHAR szExtensionFmt
[] = {';','*','.','%','s',0};
1033 static const WCHAR szAVIFileExtensions
[] =
1034 {'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1037 WCHAR szAllFiles
[40];
1038 WCHAR szFileExt
[10];
1045 TRACE("(%p,%ld,%d)\n", szFilter
, cbFilter
, fSaving
);
1047 /* check parameters */
1048 if (szFilter
== NULL
)
1049 return AVIERR_BADPARAM
;
1051 return AVIERR_BADSIZE
;
1053 lp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, MAX_FILTERS
* sizeof(AVIFilter
));
1055 return AVIERR_MEMORY
;
1058 * 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
1059 * extensions and CLSID's
1060 * 2. iterate over collected CLSID's and copy its description and its
1061 * extensions to szFilter if it fits
1063 * First filter is named "All multimedia files" and its filter is a
1064 * collection of all possible extensions except "*.*".
1066 if (RegOpenKeyW(HKEY_CLASSES_ROOT
, szAVIFileExtensions
, &hKey
) != S_OK
) {
1067 HeapFree(GetProcessHeap(), 0, lp
);
1068 return AVIERR_ERROR
;
1070 for (n
= 0;RegEnumKeyW(hKey
, n
, szFileExt
, sizeof(szFileExt
)) == S_OK
;n
++) {
1071 /* get CLSID to extension */
1072 size
= sizeof(szValue
)/sizeof(szValue
[0]);
1073 if (RegQueryValueW(hKey
, szFileExt
, szValue
, &size
) != S_OK
)
1076 /* search if the CLSID is already known */
1077 for (i
= 1; i
<= count
; i
++) {
1078 if (lstrcmpW(lp
[i
].szClsid
, szValue
) == 0)
1079 break; /* a new one */
1082 if (count
- i
== -1U) {
1083 /* it's a new CLSID */
1085 /* FIXME: How do we get info's about read/write capabilities? */
1087 if (count
>= MAX_FILTERS
) {
1088 /* try to inform user of our full fixed size table */
1089 ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS
);
1093 lstrcpyW(lp
[i
].szClsid
, szValue
);
1098 /* append extension to the filter */
1099 wsprintfW(szValue
, szExtensionFmt
, szFileExt
);
1100 if (lp
[i
].szExtensions
[0] == 0)
1101 lstrcatW(lp
[i
].szExtensions
, szValue
+ 1);
1103 lstrcatW(lp
[i
].szExtensions
, szValue
);
1105 /* also append to the "all multimedia"-filter */
1106 if (lp
[0].szExtensions
[0] == 0)
1107 lstrcatW(lp
[0].szExtensions
, szValue
+ 1);
1109 lstrcatW(lp
[0].szExtensions
, szValue
);
1113 /* 2. get descriptions for the CLSIDs and fill out szFilter */
1114 if (RegOpenKeyW(HKEY_CLASSES_ROOT
, szClsid
, &hKey
) != S_OK
) {
1115 HeapFree(GetProcessHeap(), 0, lp
);
1116 return AVIERR_ERROR
;
1118 for (n
= 0; n
<= count
; n
++) {
1119 /* first the description */
1121 size
= sizeof(szValue
)/sizeof(szValue
[0]);
1122 if (RegQueryValueW(hKey
, lp
[n
].szClsid
, szValue
, &size
) == S_OK
) {
1123 size
= lstrlenW(szValue
);
1124 lstrcpynW(szFilter
, szValue
, cbFilter
);
1127 size
= LoadStringW(AVIFILE_hModule
,IDS_ALLMULTIMEDIA
,szFilter
,cbFilter
);
1129 /* check for enough space */
1131 if (cbFilter
< size
+ lstrlenW(lp
[n
].szExtensions
) + 2) {
1134 HeapFree(GetProcessHeap(), 0, lp
);
1136 return AVIERR_BUFFERTOOSMALL
;
1141 /* and then the filter */
1142 lstrcpynW(szFilter
, lp
[n
].szExtensions
, cbFilter
);
1143 size
= lstrlenW(lp
[n
].szExtensions
) + 1;
1149 HeapFree(GetProcessHeap(), 0, lp
);
1151 /* add "All files" "*.*" filter if enough space left */
1152 size
= LoadStringW(AVIFILE_hModule
, IDS_ALLFILES
,
1153 szAllFiles
, sizeof(szAllFiles
)) + 1;
1154 if (cbFilter
> size
) {
1157 /* replace '@' with \000 to separate description of filter */
1158 for (i
= 0; i
< size
&& szAllFiles
[i
] != 0; i
++) {
1159 if (szAllFiles
[i
] == '@') {
1165 memcpy(szFilter
, szAllFiles
, size
* sizeof(szAllFiles
[0]));
1172 return AVIERR_BUFFERTOOSMALL
;
1176 static BOOL
AVISaveOptionsFmtChoose(HWND hWnd
)
1178 LPAVICOMPRESSOPTIONS pOptions
= SaveOpts
.ppOptions
[SaveOpts
.nCurrent
];
1179 AVISTREAMINFOW sInfo
;
1181 TRACE("(%p)\n", hWnd
);
1183 if (pOptions
== NULL
|| SaveOpts
.ppavis
[SaveOpts
.nCurrent
] == NULL
) {
1184 ERR(": bad state!\n");
1188 if (FAILED(AVIStreamInfoW(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1189 &sInfo
, sizeof(sInfo
)))) {
1190 ERR(": AVIStreamInfoW failed!\n");
1194 if (sInfo
.fccType
== streamtypeVIDEO
) {
1198 memset(&cv
, 0, sizeof(cv
));
1200 if ((pOptions
->dwFlags
& AVICOMPRESSF_VALID
) == 0) {
1201 memset(pOptions
, 0, sizeof(AVICOMPRESSOPTIONS
));
1202 pOptions
->fccType
= streamtypeVIDEO
;
1203 pOptions
->fccHandler
= comptypeDIB
;
1204 pOptions
->dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
1207 cv
.cbSize
= sizeof(cv
);
1208 cv
.dwFlags
= ICMF_COMPVARS_VALID
;
1209 /*cv.fccType = pOptions->fccType; */
1210 cv
.fccHandler
= pOptions
->fccHandler
;
1211 cv
.lQ
= pOptions
->dwQuality
;
1212 cv
.lpState
= pOptions
->lpParms
;
1213 cv
.cbState
= pOptions
->cbParms
;
1214 if (pOptions
->dwFlags
& AVICOMPRESSF_KEYFRAMES
)
1215 cv
.lKey
= pOptions
->dwKeyFrameEvery
;
1218 if (pOptions
->dwFlags
& AVICOMPRESSF_DATARATE
)
1219 cv
.lDataRate
= pOptions
->dwBytesPerSecond
/ 1024; /* need kBytes */
1223 ret
= ICCompressorChoose(hWnd
, SaveOpts
.uFlags
, NULL
,
1224 SaveOpts
.ppavis
[SaveOpts
.nCurrent
], &cv
, NULL
);
1227 pOptions
->fccHandler
= cv
.fccHandler
;
1228 pOptions
->lpParms
= cv
.lpState
;
1229 pOptions
->cbParms
= cv
.cbState
;
1230 pOptions
->dwQuality
= cv
.lQ
;
1232 pOptions
->dwKeyFrameEvery
= cv
.lKey
;
1233 pOptions
->dwFlags
|= AVICOMPRESSF_KEYFRAMES
;
1235 pOptions
->dwFlags
&= ~AVICOMPRESSF_KEYFRAMES
;
1236 if (cv
.lDataRate
!= 0) {
1237 pOptions
->dwBytesPerSecond
= cv
.lDataRate
* 1024; /* need bytes */
1238 pOptions
->dwFlags
|= AVICOMPRESSF_DATARATE
;
1240 pOptions
->dwFlags
&= ~AVICOMPRESSF_DATARATE
;
1241 pOptions
->dwFlags
|= AVICOMPRESSF_VALID
;
1243 ICCompressorFree(&cv
);
1246 } else if (sInfo
.fccType
== streamtypeAUDIO
) {
1247 ACMFORMATCHOOSEW afmtc
;
1251 /* FIXME: check ACM version -- Which version is needed? */
1253 memset(&afmtc
, 0, sizeof(afmtc
));
1254 afmtc
.cbStruct
= sizeof(afmtc
);
1256 afmtc
.hwndOwner
= hWnd
;
1258 acmMetrics(NULL
, ACM_METRIC_MAX_SIZE_FORMAT
, &size
);
1259 if ((pOptions
->cbFormat
== 0 || pOptions
->lpFormat
== NULL
) && size
!= 0) {
1260 pOptions
->lpFormat
= HeapAlloc(GetProcessHeap(), 0, size
);
1261 pOptions
->cbFormat
= size
;
1262 } else if (pOptions
->cbFormat
< (DWORD
)size
) {
1263 pOptions
->lpFormat
= HeapReAlloc(GetProcessHeap(), 0, pOptions
->lpFormat
, size
);
1264 pOptions
->cbFormat
= size
;
1266 if (pOptions
->lpFormat
== NULL
)
1268 afmtc
.pwfx
= pOptions
->lpFormat
;
1269 afmtc
.cbwfx
= pOptions
->cbFormat
;
1272 AVIStreamFormatSize(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1273 sInfo
.dwStart
, &size
);
1274 if (size
< (LONG
)sizeof(PCMWAVEFORMAT
))
1275 size
= sizeof(PCMWAVEFORMAT
);
1276 afmtc
.pwfxEnum
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1277 if (afmtc
.pwfxEnum
!= NULL
) {
1278 AVIStreamReadFormat(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1279 sInfo
.dwStart
, afmtc
.pwfxEnum
, &size
);
1280 afmtc
.fdwEnum
= ACM_FORMATENUMF_CONVERT
;
1283 ret
= acmFormatChooseW(&afmtc
);
1285 pOptions
->dwFlags
|= AVICOMPRESSF_VALID
;
1287 if (afmtc
.pwfxEnum
!= NULL
)
1288 HeapFree(GetProcessHeap(), 0, afmtc
.pwfxEnum
);
1290 return (ret
== S_OK
? TRUE
: FALSE
);
1292 ERR(": unknown streamtype 0x%08lX\n", sInfo
.fccType
);
1297 static void AVISaveOptionsUpdate(HWND hWnd
)
1299 static const WCHAR szVideoFmt
[]={'%','l','d','x','%','l','d','x','%','d',0};
1300 static const WCHAR szAudioFmt
[]={'%','s',' ','%','s',0};
1302 WCHAR szFormat
[128];
1303 AVISTREAMINFOW sInfo
;
1307 TRACE("(%p)\n", hWnd
);
1309 SaveOpts
.nCurrent
= SendDlgItemMessageW(hWnd
,IDC_STREAM
,CB_GETCURSEL
,0,0);
1310 if (SaveOpts
.nCurrent
< 0)
1313 if (FAILED(AVIStreamInfoW(SaveOpts
.ppavis
[SaveOpts
.nCurrent
], &sInfo
, sizeof(sInfo
))))
1316 AVIStreamFormatSize(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],sInfo
.dwStart
,&size
);
1320 /* read format to build format description string */
1321 lpFormat
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1322 if (lpFormat
!= NULL
) {
1323 if (SUCCEEDED(AVIStreamReadFormat(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],sInfo
.dwStart
,lpFormat
, &size
))) {
1324 if (sInfo
.fccType
== streamtypeVIDEO
) {
1325 LPBITMAPINFOHEADER lpbi
= lpFormat
;
1328 wsprintfW(szFormat
, szVideoFmt
, lpbi
->biWidth
,
1329 lpbi
->biHeight
, lpbi
->biBitCount
);
1331 if (lpbi
->biCompression
!= BI_RGB
) {
1334 hic
= ICLocate(ICTYPE_VIDEO
, sInfo
.fccHandler
, lpFormat
,
1335 NULL
, ICMODE_DECOMPRESS
);
1337 if (ICGetInfo(hic
, &icinfo
, sizeof(icinfo
)) == S_OK
)
1338 lstrcatW(szFormat
, icinfo
.szDescription
);
1342 LoadStringW(AVIFILE_hModule
, IDS_UNCOMPRESSED
,
1343 icinfo
.szDescription
, sizeof(icinfo
.szDescription
));
1344 lstrcatW(szFormat
, icinfo
.szDescription
);
1346 } else if (sInfo
.fccType
== streamtypeAUDIO
) {
1347 ACMFORMATTAGDETAILSW aftd
;
1348 ACMFORMATDETAILSW afd
;
1350 memset(&aftd
, 0, sizeof(aftd
));
1351 memset(&afd
, 0, sizeof(afd
));
1353 aftd
.cbStruct
= sizeof(aftd
);
1354 aftd
.dwFormatTag
= afd
.dwFormatTag
=
1355 ((PWAVEFORMATEX
)lpFormat
)->wFormatTag
;
1356 aftd
.cbFormatSize
= afd
.cbwfx
= size
;
1358 afd
.cbStruct
= sizeof(afd
);
1359 afd
.pwfx
= lpFormat
;
1361 if (acmFormatTagDetailsW(NULL
, &aftd
,
1362 ACM_FORMATTAGDETAILSF_FORMATTAG
) == S_OK
) {
1363 if (acmFormatDetailsW(NULL
,&afd
,ACM_FORMATDETAILSF_FORMAT
) == S_OK
)
1364 wsprintfW(szFormat
, szAudioFmt
, afd
.szFormat
, aftd
.szFormatTag
);
1368 HeapFree(GetProcessHeap(), 0, lpFormat
);
1371 /* set text for format description */
1372 SetDlgItemTextW(hWnd
, IDC_FORMATTEXT
, szFormat
);
1374 /* Disable option button for unsupported streamtypes */
1375 if (sInfo
.fccType
== streamtypeVIDEO
||
1376 sInfo
.fccType
== streamtypeAUDIO
)
1377 EnableWindow(GetDlgItem(hWnd
, IDC_OPTIONS
), TRUE
);
1379 EnableWindow(GetDlgItem(hWnd
, IDC_OPTIONS
), FALSE
);
1384 static INT_PTR CALLBACK
AVISaveOptionsDlgProc(HWND hWnd
, UINT uMsg
,
1385 WPARAM wParam
, LPARAM lParam
)
1388 BOOL bIsInterleaved
;
1391 /*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
1395 SaveOpts
.nCurrent
= 0;
1396 if (SaveOpts
.nStreams
== 1) {
1397 EndDialog(hWnd
, AVISaveOptionsFmtChoose(hWnd
));
1402 for (n
= 0; n
< SaveOpts
.nStreams
; n
++) {
1403 AVISTREAMINFOW sInfo
;
1405 AVIStreamInfoW(SaveOpts
.ppavis
[n
], &sInfo
, sizeof(sInfo
));
1406 SendDlgItemMessageW(hWnd
, IDC_STREAM
, CB_ADDSTRING
,
1407 0L, (LPARAM
)sInfo
.szName
);
1410 /* select first stream */
1411 SendDlgItemMessageW(hWnd
, IDC_STREAM
, CB_SETCURSEL
, 0, 0);
1412 SendMessageW(hWnd
, WM_COMMAND
, MAKELONG(IDC_STREAM
, CBN_SELCHANGE
), (LPARAM
)hWnd
);
1414 /* initialize interleave */
1415 if (SaveOpts
.ppOptions
[0] != NULL
&&
1416 (SaveOpts
.ppOptions
[0]->dwFlags
& AVICOMPRESSF_VALID
)) {
1417 bIsInterleaved
= (SaveOpts
.ppOptions
[0]->dwFlags
& AVICOMPRESSF_INTERLEAVE
);
1418 dwInterleave
= SaveOpts
.ppOptions
[0]->dwInterleaveEvery
;
1420 bIsInterleaved
= TRUE
;
1423 CheckDlgButton(hWnd
, IDC_INTERLEAVE
, bIsInterleaved
);
1424 SetDlgItemInt(hWnd
, IDC_INTERLEAVEEVERY
, dwInterleave
, FALSE
);
1425 EnableWindow(GetDlgItem(hWnd
, IDC_INTERLEAVEEVERY
), bIsInterleaved
);
1428 switch (LOWORD(wParam
)) {
1430 /* get data from controls and save them */
1431 dwInterleave
= GetDlgItemInt(hWnd
, IDC_INTERLEAVEEVERY
, NULL
, 0);
1432 bIsInterleaved
= IsDlgButtonChecked(hWnd
, IDC_INTERLEAVE
);
1433 for (n
= 0; n
< SaveOpts
.nStreams
; n
++) {
1434 if (SaveOpts
.ppOptions
[n
] != NULL
) {
1435 if (bIsInterleaved
) {
1436 SaveOpts
.ppOptions
[n
]->dwFlags
|= AVICOMPRESSF_INTERLEAVE
;
1437 SaveOpts
.ppOptions
[n
]->dwInterleaveEvery
= dwInterleave
;
1439 SaveOpts
.ppOptions
[n
]->dwFlags
&= ~AVICOMPRESSF_INTERLEAVE
;
1444 EndDialog(hWnd
, LOWORD(wParam
) == IDOK
);
1446 case IDC_INTERLEAVE
:
1447 EnableWindow(GetDlgItem(hWnd
, IDC_INTERLEAVEEVERY
),
1448 IsDlgButtonChecked(hWnd
, IDC_INTERLEAVE
));
1451 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
1452 /* update control elements */
1453 AVISaveOptionsUpdate(hWnd
);
1457 AVISaveOptionsFmtChoose(hWnd
);
1466 /***********************************************************************
1467 * AVISaveOptions (AVIFIL32.@)
1469 BOOL WINAPI
AVISaveOptions(HWND hWnd
, UINT uFlags
, INT nStreams
,
1470 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*ppOptions
)
1472 LPAVICOMPRESSOPTIONS pSavedOptions
= NULL
;
1475 TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd
, uFlags
, nStreams
,
1478 /* check parameters */
1479 if (nStreams
<= 0 || ppavi
== NULL
|| ppOptions
== NULL
)
1480 return AVIERR_BADPARAM
;
1482 /* save options in case the user presses cancel */
1483 if (ppOptions
!= NULL
&& nStreams
> 1) {
1484 pSavedOptions
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, nStreams
* sizeof(AVICOMPRESSOPTIONS
));
1485 if (pSavedOptions
== NULL
)
1488 for (n
= 0; n
< nStreams
; n
++) {
1489 if (ppOptions
[n
] != NULL
)
1490 memcpy(pSavedOptions
+ n
, ppOptions
[n
], sizeof(AVICOMPRESSOPTIONS
));
1494 SaveOpts
.uFlags
= uFlags
;
1495 SaveOpts
.nStreams
= nStreams
;
1496 SaveOpts
.ppavis
= ppavi
;
1497 SaveOpts
.ppOptions
= ppOptions
;
1499 ret
= DialogBoxW(AVIFILE_hModule
, MAKEINTRESOURCEW(IDD_SAVEOPTIONS
),
1500 hWnd
, AVISaveOptionsDlgProc
);
1505 /* restore options when user pressed cancel */
1506 if (pSavedOptions
!= NULL
) {
1508 for (n
= 0; n
< nStreams
; n
++) {
1509 if (ppOptions
[n
] != NULL
)
1510 memcpy(ppOptions
[n
], pSavedOptions
+ n
, sizeof(AVICOMPRESSOPTIONS
));
1513 HeapFree(GetProcessHeap(), 0, pSavedOptions
);
1519 /***********************************************************************
1520 * AVISaveOptionsFree (AVIFIL32.@)
1521 * AVISaveOptionsFree (AVIFILE.124)
1523 HRESULT WINAPI
AVISaveOptionsFree(INT nStreams
,LPAVICOMPRESSOPTIONS
*ppOptions
)
1525 TRACE("(%d,%p)\n", nStreams
, ppOptions
);
1527 if (nStreams
< 0 || ppOptions
== NULL
)
1528 return AVIERR_BADPARAM
;
1530 for (; nStreams
> 0; nStreams
--) {
1531 if (ppOptions
[nStreams
] != NULL
) {
1532 ppOptions
[nStreams
]->dwFlags
&= ~AVICOMPRESSF_VALID
;
1534 if (ppOptions
[nStreams
]->lpParms
!= NULL
) {
1535 HeapFree(GetProcessHeap(), 0, ppOptions
[nStreams
]->lpParms
);
1536 ppOptions
[nStreams
]->lpParms
= NULL
;
1537 ppOptions
[nStreams
]->cbParms
= 0;
1539 if (ppOptions
[nStreams
]->lpFormat
!= NULL
) {
1540 HeapFree(GetProcessHeap(), 0, ppOptions
[nStreams
]->lpFormat
);
1541 ppOptions
[nStreams
]->lpFormat
= NULL
;
1542 ppOptions
[nStreams
]->cbFormat
= 0;
1550 /***********************************************************************
1551 * AVISaveVA (AVIFIL32.@)
1553 HRESULT WINAPI
AVISaveVA(LPCSTR szFile
, CLSID
*pclsidHandler
,
1554 AVISAVECALLBACK lpfnCallback
, int nStream
,
1555 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*plpOptions
)
1557 LPWSTR wszFile
= NULL
;
1561 TRACE("%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile
), pclsidHandler
,
1562 lpfnCallback
, nStream
, ppavi
, plpOptions
);
1564 if (szFile
== NULL
|| ppavi
== NULL
|| plpOptions
== NULL
)
1565 return AVIERR_BADPARAM
;
1567 /* convert ASCII string to Unicode and call Unicode function */
1568 len
= MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, NULL
, 0);
1570 return AVIERR_BADPARAM
;
1572 wszFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1573 if (wszFile
== NULL
)
1574 return AVIERR_MEMORY
;
1576 MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, wszFile
, len
);
1578 hr
= AVISaveVW(wszFile
, pclsidHandler
, lpfnCallback
,
1579 nStream
, ppavi
, plpOptions
);
1581 HeapFree(GetProcessHeap(), 0, wszFile
);
1586 /***********************************************************************
1587 * AVIFILE_AVISaveDefaultCallback (internal)
1589 static BOOL WINAPI
AVIFILE_AVISaveDefaultCallback(INT progress
)
1591 TRACE("(%d)\n", progress
);
1596 /***********************************************************************
1597 * AVISaveVW (AVIFIL32.@)
1599 HRESULT WINAPI
AVISaveVW(LPCWSTR szFile
, CLSID
*pclsidHandler
,
1600 AVISAVECALLBACK lpfnCallback
, int nStreams
,
1601 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*plpOptions
)
1603 LONG lStart
[MAX_AVISTREAMS
];
1604 PAVISTREAM pOutStreams
[MAX_AVISTREAMS
];
1605 PAVISTREAM pInStreams
[MAX_AVISTREAMS
];
1607 AVISTREAMINFOW sInfo
;
1609 PAVIFILE pfile
= NULL
; /* the output AVI file */
1610 LONG lFirstVideo
= -1;
1613 /* for interleaving ... */
1614 DWORD dwInterleave
= 0; /* interleave rate */
1615 DWORD dwFileInitialFrames
;
1619 /* for reading/writing the data ... */
1620 LPVOID lpBuffer
= NULL
;
1621 LONG cbBuffer
; /* real size of lpBuffer */
1622 LONG lBufferSize
; /* needed bytes for format(s), etc. */
1627 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile
), pclsidHandler
,
1628 lpfnCallback
, nStreams
, ppavi
, plpOptions
);
1630 if (szFile
== NULL
|| ppavi
== NULL
|| plpOptions
== NULL
)
1631 return AVIERR_BADPARAM
;
1632 if (nStreams
>= MAX_AVISTREAMS
) {
1633 WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams
, MAX_AVISTREAMS
);
1634 return AVIERR_INTERNAL
;
1637 if (lpfnCallback
== NULL
)
1638 lpfnCallback
= AVIFILE_AVISaveDefaultCallback
;
1640 /* clear local variable(s) */
1641 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1642 pInStreams
[curStream
] = NULL
;
1643 pOutStreams
[curStream
] = NULL
;
1646 /* open output AVI file (create it if it doesn't exist) */
1647 hres
= AVIFileOpenW(&pfile
, szFile
, OF_CREATE
|OF_SHARE_EXCLUSIVE
|OF_WRITE
,
1651 AVIFileInfoW(pfile
, &fInfo
, sizeof(fInfo
)); /* for dwCaps */
1653 /* initialize our data structures part 1 */
1654 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1655 PAVISTREAM pCurStream
= ppavi
[curStream
];
1657 hres
= AVIStreamInfoW(pCurStream
, &sInfo
, sizeof(sInfo
));
1661 /* search first video stream and check for interleaving */
1662 if (sInfo
.fccType
== streamtypeVIDEO
) {
1663 /* remember first video stream -- needed for interleaving */
1664 if (lFirstVideo
< 0)
1665 lFirstVideo
= curStream
;
1666 } else if (!dwInterleave
&& plpOptions
!= NULL
) {
1667 /* check if any non-video stream wants to be interleaved */
1668 WARN("options.flags=0x%lX options.dwInterleave=%lu\n",plpOptions
[curStream
]->dwFlags
,plpOptions
[curStream
]->dwInterleaveEvery
);
1669 if (plpOptions
[curStream
] != NULL
&&
1670 plpOptions
[curStream
]->dwFlags
& AVICOMPRESSF_INTERLEAVE
)
1671 dwInterleave
= plpOptions
[curStream
]->dwInterleaveEvery
;
1674 /* create de-/compressed stream interface if needed */
1675 pInStreams
[curStream
] = NULL
;
1676 if (plpOptions
!= NULL
&& plpOptions
[curStream
] != NULL
) {
1677 if (plpOptions
[curStream
]->fccHandler
||
1678 plpOptions
[curStream
]->lpFormat
!= NULL
) {
1679 DWORD dwKeySave
= plpOptions
[curStream
]->dwKeyFrameEvery
;
1681 if (fInfo
.dwCaps
& AVIFILECAPS_ALLKEYFRAMES
)
1682 plpOptions
[curStream
]->dwKeyFrameEvery
= 1;
1684 hres
= AVIMakeCompressedStream(&pInStreams
[curStream
], pCurStream
,
1685 plpOptions
[curStream
], NULL
);
1686 plpOptions
[curStream
]->dwKeyFrameEvery
= dwKeySave
;
1687 if (FAILED(hres
) || pInStreams
[curStream
] == NULL
) {
1688 pInStreams
[curStream
] = NULL
;
1692 /* test stream interface and update stream-info */
1693 hres
= AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1699 /* now handle streams which will only be copied */
1700 if (pInStreams
[curStream
] == NULL
) {
1701 pCurStream
= pInStreams
[curStream
] = ppavi
[curStream
];
1702 AVIStreamAddRef(pCurStream
);
1704 pCurStream
= pInStreams
[curStream
];
1706 lStart
[curStream
] = sInfo
.dwStart
;
1707 } /* for all streams */
1709 /* check that first video stream is the first stream */
1710 if (lFirstVideo
> 0) {
1711 PAVISTREAM pTmp
= pInStreams
[lFirstVideo
];
1712 LONG lTmp
= lStart
[lFirstVideo
];
1714 pInStreams
[lFirstVideo
] = pInStreams
[0];
1715 pInStreams
[0] = pTmp
;
1716 lStart
[lFirstVideo
] = lStart
[0];
1721 /* allocate buffer for formats, data, etc. of an initial size of 64 kBytes*/
1722 lpBuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBuffer
= 0x00010000);
1723 if (lpBuffer
== NULL
) {
1724 hres
= AVIERR_MEMORY
;
1728 AVIStreamInfoW(pInStreams
[0], &sInfo
, sizeof(sInfo
));
1729 lFileLength
= sInfo
.dwLength
;
1730 dwFileInitialFrames
= 0;
1731 if (lFirstVideo
>= 0) {
1732 /* check for correct version of the format
1733 * -- need at least BITMAPINFOHEADER or newer
1736 lBufferSize
= cbBuffer
;
1737 hres
= AVIStreamReadFormat(pInStreams
[lFirstVideo
], AVIStreamStart(pInStreams
[lFirstVideo
]), lpBuffer
, &lBufferSize
);
1738 if (lBufferSize
< (LONG
)sizeof(BITMAPINFOHEADER
))
1739 hres
= AVIERR_INTERNAL
;
1742 } else /* use one second blocks for interleaving if no video present */
1743 lSampleInc
= AVIStreamTimeToSample(pInStreams
[0], 1000000);
1745 /* create output streams */
1746 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1747 AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1749 sInfo
.dwInitialFrames
= 0;
1750 if (dwInterleave
!= 0 && curStream
> 0 && sInfo
.fccType
!= streamtypeVIDEO
) {
1751 /* 750 ms initial frames for non-video streams */
1752 sInfo
.dwInitialFrames
= AVIStreamTimeToSample(pInStreams
[0], 750);
1755 hres
= AVIFileCreateStreamW(pfile
, &pOutStreams
[curStream
], &sInfo
);
1756 if (pOutStreams
[curStream
] != NULL
&& SUCCEEDED(hres
)) {
1757 /* copy initial format for this stream */
1758 lBufferSize
= cbBuffer
;
1759 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1760 lpBuffer
, &lBufferSize
);
1763 hres
= AVIStreamSetFormat(pOutStreams
[curStream
], 0, lpBuffer
, lBufferSize
);
1767 /* try to copy stream handler data */
1768 lBufferSize
= cbBuffer
;
1769 hres
= AVIStreamReadData(pInStreams
[curStream
], ckidSTREAMHANDLERDATA
,
1770 lpBuffer
, &lBufferSize
);
1771 if (SUCCEEDED(hres
) && lBufferSize
> 0) {
1772 hres
= AVIStreamWriteData(pOutStreams
[curStream
],ckidSTREAMHANDLERDATA
,
1773 lpBuffer
, lBufferSize
);
1778 if (dwFileInitialFrames
< sInfo
.dwInitialFrames
)
1779 dwFileInitialFrames
= sInfo
.dwInitialFrames
;
1781 AVIStreamSampleToSample(pOutStreams
[0], pInStreams
[curStream
],
1783 if (lFileLength
< lReadBytes
)
1784 lFileLength
= lReadBytes
;
1786 /* creation of de-/compression stream interface failed */
1787 WARN("creation of (de-)compression stream failed for stream %d\n",curStream
);
1788 AVIStreamRelease(pInStreams
[curStream
]);
1789 if (curStream
+ 1 >= nStreams
) {
1790 /* move the others one up */
1791 PAVISTREAM
*ppas
= &pInStreams
[curStream
];
1792 int n
= nStreams
- (curStream
+ 1);
1795 *ppas
= pInStreams
[curStream
+ 1];
1801 } /* create output streams for all input streams */
1803 /* have we still something to write, or lost everything? */
1808 LONG lCurFrame
= -dwFileInitialFrames
;
1810 /* interleaved file */
1811 if (dwInterleave
== 1)
1812 AVIFileEndRecord(pfile
);
1814 for (; lCurFrame
< lFileLength
; lCurFrame
+= lSampleInc
) {
1815 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1818 hres
= AVIStreamInfoW(pOutStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1822 /* initial frames phase at the end for this stream? */
1823 if (-(LONG
)sInfo
.dwInitialFrames
> lCurFrame
)
1826 if ((lFileLength
- lSampleInc
) <= lCurFrame
) {
1827 lLastSample
= AVIStreamLength(pInStreams
[curStream
]);
1828 lFirstVideo
= lLastSample
+ AVIStreamStart(pInStreams
[curStream
]);
1830 if (curStream
!= 0) {
1832 AVIStreamSampleToSample(pInStreams
[curStream
], pInStreams
[0],
1833 (sInfo
.fccType
== streamtypeVIDEO
?
1834 (LONG
)dwInterleave
: lSampleInc
) +
1835 sInfo
.dwInitialFrames
+ lCurFrame
);
1837 lFirstVideo
= lSampleInc
+ (sInfo
.dwInitialFrames
+ lCurFrame
);
1839 lLastSample
= AVIStreamEnd(pInStreams
[curStream
]);
1840 if (lLastSample
<= lFirstVideo
)
1841 lFirstVideo
= lLastSample
;
1844 /* copy needed samples now */
1845 WARN("copy from stream %d samples %ld to %ld...\n",curStream
,
1846 lStart
[curStream
],lFirstVideo
);
1847 while (lFirstVideo
> lStart
[curStream
]) {
1850 /* copy format in case it can change */
1851 lBufferSize
= cbBuffer
;
1852 hres
= AVIStreamReadFormat(pInStreams
[curStream
], lStart
[curStream
],
1853 lpBuffer
, &lBufferSize
);
1856 AVIStreamSetFormat(pOutStreams
[curStream
], lStart
[curStream
],
1857 lpBuffer
, lBufferSize
);
1859 /* try to read data until we got it, or error */
1861 hres
= AVIStreamRead(pInStreams
[curStream
], lStart
[curStream
],
1862 lFirstVideo
- lStart
[curStream
], lpBuffer
,
1863 cbBuffer
, &lReadBytes
, &lReadSamples
);
1864 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1865 (lpBuffer
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1866 if (lpBuffer
== NULL
)
1867 hres
= AVIERR_MEMORY
;
1871 if (AVIStreamIsKeyFrame(pInStreams
[curStream
], (LONG
)sInfo
.dwStart
))
1872 flags
= AVIIF_KEYFRAME
;
1873 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1874 lpBuffer
, lReadBytes
, flags
, NULL
, NULL
);
1878 lStart
[curStream
] += lReadSamples
;
1880 lStart
[curStream
] = lFirstVideo
;
1881 } /* stream by stream */
1883 /* need to close this block? */
1884 if (dwInterleave
== 1) {
1885 hres
= AVIFileEndRecord(pfile
);
1891 if (lpfnCallback(MulDiv(dwFileInitialFrames
+ lCurFrame
, 100,
1892 dwFileInitialFrames
+ lFileLength
))) {
1893 hres
= AVIERR_USERABORT
;
1896 } /* copy frame by frame */
1898 /* non-interleaved file */
1900 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1902 if (lpfnCallback(MulDiv(curStream
, 100, nStreams
))) {
1903 hres
= AVIERR_USERABORT
;
1907 AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1909 if (sInfo
.dwSampleSize
!= 0) {
1910 /* sample-based data like audio */
1911 while (sInfo
.dwStart
< sInfo
.dwLength
) {
1912 LONG lSamples
= cbBuffer
/ sInfo
.dwSampleSize
;
1914 /* copy format in case it can change */
1915 lBufferSize
= cbBuffer
;
1916 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1917 lpBuffer
, &lBufferSize
);
1920 AVIStreamSetFormat(pOutStreams
[curStream
], sInfo
.dwStart
,
1921 lpBuffer
, lBufferSize
);
1923 /* limit to stream boundaries */
1924 if (lSamples
!= (LONG
)(sInfo
.dwLength
- sInfo
.dwStart
))
1925 lSamples
= sInfo
.dwLength
- sInfo
.dwStart
;
1927 /* now try to read until we get it, or an error occurs */
1929 lReadBytes
= cbBuffer
;
1931 hres
= AVIStreamRead(pInStreams
[curStream
],sInfo
.dwStart
,lSamples
,
1932 lpBuffer
,cbBuffer
,&lReadBytes
,&lReadSamples
);
1933 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1934 (lpBuffer
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1935 if (lpBuffer
== NULL
)
1936 hres
= AVIERR_MEMORY
;
1939 if (lReadSamples
!= 0) {
1940 sInfo
.dwStart
+= lReadSamples
;
1941 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1942 lpBuffer
, lReadBytes
, 0, NULL
, NULL
);
1947 if (lpfnCallback(MulDiv(sInfo
.dwStart
,100,nStreams
*sInfo
.dwLength
)+
1948 MulDiv(curStream
, 100, nStreams
))) {
1949 hres
= AVIERR_USERABORT
;
1953 if ((sInfo
.dwLength
- sInfo
.dwStart
) != 1) {
1954 hres
= AVIERR_FILEREAD
;
1960 /* block-based data like video */
1961 for (; sInfo
.dwStart
< sInfo
.dwLength
; sInfo
.dwStart
++) {
1964 /* copy format in case it can change */
1965 lBufferSize
= cbBuffer
;
1966 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1967 lpBuffer
, &lBufferSize
);
1970 AVIStreamSetFormat(pOutStreams
[curStream
], sInfo
.dwStart
,
1971 lpBuffer
, lBufferSize
);
1973 /* try to read block and resize buffer if necessary */
1976 lReadBytes
= cbBuffer
;
1977 hres
= AVIStreamRead(pInStreams
[curStream
], sInfo
.dwStart
, 1,
1978 lpBuffer
, cbBuffer
,&lReadBytes
,&lReadSamples
);
1979 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1980 (lpBuffer
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1981 if (lpBuffer
== NULL
)
1982 hres
= AVIERR_MEMORY
;
1985 if (lReadSamples
!= 1) {
1986 hres
= AVIERR_FILEREAD
;
1990 if (AVIStreamIsKeyFrame(pInStreams
[curStream
], (LONG
)sInfo
.dwStart
))
1991 flags
= AVIIF_KEYFRAME
;
1992 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1993 lpBuffer
, lReadBytes
, flags
, NULL
, NULL
);
1998 if (lpfnCallback(MulDiv(sInfo
.dwStart
,100,nStreams
*sInfo
.dwLength
)+
1999 MulDiv(curStream
, 100, nStreams
))) {
2000 hres
= AVIERR_USERABORT
;
2003 } /* copy all blocks */
2005 } /* copy data stream by stream */
2009 if (lpBuffer
!= NULL
)
2010 HeapFree(GetProcessHeap(), 0, lpBuffer
);
2011 if (pfile
!= NULL
) {
2012 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
2013 if (pOutStreams
[curStream
] != NULL
)
2014 AVIStreamRelease(pOutStreams
[curStream
]);
2015 if (pInStreams
[curStream
] != NULL
)
2016 AVIStreamRelease(pInStreams
[curStream
]);
2019 AVIFileRelease(pfile
);
2025 /***********************************************************************
2026 * CreateEditableStream (AVIFIL32.@)
2028 HRESULT WINAPI
CreateEditableStream(PAVISTREAM
*ppEditable
, PAVISTREAM pSource
)
2030 IAVIEditStream
*pEdit
= NULL
;
2033 TRACE("(%p,%p)\n", ppEditable
, pSource
);
2035 if (ppEditable
== NULL
)
2036 return AVIERR_BADPARAM
;
2040 if (pSource
!= NULL
) {
2041 hr
= IAVIStream_QueryInterface(pSource
, &IID_IAVIEditStream
,
2043 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2044 hr
= IAVIEditStream_Clone(pEdit
, ppEditable
);
2045 IAVIEditStream_Release(pEdit
);
2051 /* need own implementation of IAVIEditStream */
2052 pEdit
= AVIFILE_CreateEditStream(pSource
);
2054 return AVIERR_MEMORY
;
2056 hr
= IAVIEditStream_QueryInterface(pEdit
, &IID_IAVIStream
,
2057 (LPVOID
*)ppEditable
);
2058 IAVIEditStream_Release(pEdit
);
2063 /***********************************************************************
2064 * EditStreamClone (AVIFIL32.@)
2066 HRESULT WINAPI
EditStreamClone(PAVISTREAM pStream
, PAVISTREAM
*ppResult
)
2068 PAVIEDITSTREAM pEdit
= NULL
;
2071 TRACE("(%p,%p)\n", pStream
, ppResult
);
2073 if (pStream
== NULL
)
2074 return AVIERR_BADHANDLE
;
2075 if (ppResult
== NULL
)
2076 return AVIERR_BADPARAM
;
2080 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2081 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2082 hr
= IAVIEditStream_Clone(pEdit
, ppResult
);
2084 IAVIEditStream_Release(pEdit
);
2086 hr
= AVIERR_UNSUPPORTED
;
2091 /***********************************************************************
2092 * EditStreamCopy (AVIFIL32.@)
2094 HRESULT WINAPI
EditStreamCopy(PAVISTREAM pStream
, LONG
*plStart
,
2095 LONG
*plLength
, PAVISTREAM
*ppResult
)
2097 PAVIEDITSTREAM pEdit
= NULL
;
2100 TRACE("(%p,%p,%p,%p)\n", pStream
, plStart
, plLength
, ppResult
);
2102 if (pStream
== NULL
)
2103 return AVIERR_BADHANDLE
;
2104 if (plStart
== NULL
|| plLength
== NULL
|| ppResult
== NULL
)
2105 return AVIERR_BADPARAM
;
2109 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2110 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2111 hr
= IAVIEditStream_Copy(pEdit
, plStart
, plLength
, ppResult
);
2113 IAVIEditStream_Release(pEdit
);
2115 hr
= AVIERR_UNSUPPORTED
;
2120 /***********************************************************************
2121 * EditStreamCut (AVIFIL32.@)
2123 HRESULT WINAPI
EditStreamCut(PAVISTREAM pStream
, LONG
*plStart
,
2124 LONG
*plLength
, PAVISTREAM
*ppResult
)
2126 PAVIEDITSTREAM pEdit
= NULL
;
2129 TRACE("(%p,%p,%p,%p)\n", pStream
, plStart
, plLength
, ppResult
);
2131 if (ppResult
!= NULL
)
2133 if (pStream
== NULL
)
2134 return AVIERR_BADHANDLE
;
2135 if (plStart
== NULL
|| plLength
== NULL
)
2136 return AVIERR_BADPARAM
;
2138 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2139 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2140 hr
= IAVIEditStream_Cut(pEdit
, plStart
, plLength
, ppResult
);
2142 IAVIEditStream_Release(pEdit
);
2144 hr
= AVIERR_UNSUPPORTED
;
2149 /***********************************************************************
2150 * EditStreamPaste (AVIFIL32.@)
2152 HRESULT WINAPI
EditStreamPaste(PAVISTREAM pDest
, LONG
*plStart
, LONG
*plLength
,
2153 PAVISTREAM pSource
, LONG lStart
, LONG lEnd
)
2155 PAVIEDITSTREAM pEdit
= NULL
;
2158 TRACE("(%p,%p,%p,%p,%ld,%ld)\n", pDest
, plStart
, plLength
,
2159 pSource
, lStart
, lEnd
);
2161 if (pDest
== NULL
|| pSource
== NULL
)
2162 return AVIERR_BADHANDLE
;
2163 if (plStart
== NULL
|| plLength
== NULL
|| lStart
< 0)
2164 return AVIERR_BADPARAM
;
2166 hr
= IAVIStream_QueryInterface(pDest
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2167 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2168 hr
= IAVIEditStream_Paste(pEdit
, plStart
, plLength
, pSource
, lStart
, lEnd
);
2170 IAVIEditStream_Release(pEdit
);
2172 hr
= AVIERR_UNSUPPORTED
;
2177 /***********************************************************************
2178 * EditStreamSetInfoA (AVIFIL32.@)
2180 HRESULT WINAPI
EditStreamSetInfoA(PAVISTREAM pstream
, LPAVISTREAMINFOA asi
,
2183 AVISTREAMINFOW asiw
;
2185 TRACE("(%p,%p,%ld)\n", pstream
, asi
, size
);
2187 if (pstream
== NULL
)
2188 return AVIERR_BADHANDLE
;
2189 if ((DWORD
)size
< sizeof(AVISTREAMINFOA
))
2190 return AVIERR_BADSIZE
;
2192 memcpy(&asiw
, asi
, sizeof(asiw
) - sizeof(asiw
.szName
));
2193 MultiByteToWideChar(CP_ACP
, 0, asi
->szName
, -1,
2194 asiw
.szName
, sizeof(asiw
.szName
));
2196 return EditStreamSetInfoW(pstream
, &asiw
, sizeof(asiw
));
2199 /***********************************************************************
2200 * EditStreamSetInfoW (AVIFIL32.@)
2202 HRESULT WINAPI
EditStreamSetInfoW(PAVISTREAM pstream
, LPAVISTREAMINFOW asi
,
2205 PAVIEDITSTREAM pEdit
= NULL
;
2208 TRACE("(%p,%p,%ld)\n", pstream
, asi
, size
);
2210 hr
= IAVIStream_QueryInterface(pstream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2211 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2212 hr
= IAVIEditStream_SetInfo(pEdit
, asi
, size
);
2214 IAVIEditStream_Release(pEdit
);
2216 hr
= AVIERR_UNSUPPORTED
;
2221 /***********************************************************************
2222 * EditStreamSetNameA (AVIFIL32.@)
2224 HRESULT WINAPI
EditStreamSetNameA(PAVISTREAM pstream
, LPCSTR szName
)
2226 AVISTREAMINFOA asia
;
2229 TRACE("(%p,%s)\n", pstream
, debugstr_a(szName
));
2231 if (pstream
== NULL
)
2232 return AVIERR_BADHANDLE
;
2234 return AVIERR_BADPARAM
;
2236 hres
= AVIStreamInfoA(pstream
, &asia
, sizeof(asia
));
2240 memset(asia
.szName
, 0, sizeof(asia
.szName
));
2241 lstrcpynA(asia
.szName
, szName
, sizeof(asia
.szName
)/sizeof(asia
.szName
[0]));
2243 return EditStreamSetInfoA(pstream
, &asia
, sizeof(asia
));
2246 /***********************************************************************
2247 * EditStreamSetNameW (AVIFIL32.@)
2249 HRESULT WINAPI
EditStreamSetNameW(PAVISTREAM pstream
, LPCWSTR szName
)
2251 AVISTREAMINFOW asiw
;
2254 TRACE("(%p,%s)\n", pstream
, debugstr_w(szName
));
2256 if (pstream
== NULL
)
2257 return AVIERR_BADHANDLE
;
2259 return AVIERR_BADPARAM
;
2261 hres
= IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
));
2265 memset(asiw
.szName
, 0, sizeof(asiw
.szName
));
2266 lstrcpynW(asiw
.szName
, szName
, sizeof(asiw
.szName
)/sizeof(asiw
.szName
[0]));
2268 return EditStreamSetInfoW(pstream
, &asiw
, sizeof(asiw
));
2271 /***********************************************************************
2272 * AVIClearClipboard (AVIFIL32.@)
2274 HRESULT WINAPI
AVIClearClipboard(void)
2278 return AVIERR_UNSUPPORTED
; /* OleSetClipboard(NULL); */
2281 /***********************************************************************
2282 * AVIGetFromClipboard (AVIFIL32.@)
2284 HRESULT WINAPI
AVIGetFromClipboard(PAVIFILE
*ppfile
)
2286 FIXME("(%p), stub!\n", ppfile
);
2290 return AVIERR_UNSUPPORTED
;
2293 /***********************************************************************
2294 * AVIMakeStreamFromClipboard (AVIFIL32.@)
2296 HRESULT WINAPI
AVIMakeStreamFromClipboard(UINT cfFormat
, HANDLE hGlobal
,
2297 PAVISTREAM
* ppstream
)
2299 FIXME("(0x%08x,%p,%p), stub!\n", cfFormat
, hGlobal
, ppstream
);
2301 if (ppstream
== NULL
)
2302 return AVIERR_BADHANDLE
;
2304 return AVIERR_UNSUPPORTED
;
2307 /***********************************************************************
2308 * AVIPutFileOnClipboard (AVIFIL32.@)
2310 HRESULT WINAPI
AVIPutFileOnClipboard(PAVIFILE pfile
)
2312 FIXME("(%p), stub!\n", pfile
);
2315 return AVIERR_BADHANDLE
;
2317 return AVIERR_UNSUPPORTED
;
2320 HRESULT CDECL
AVISaveA(LPCSTR szFile
, CLSID
* pclsidHandler
, AVISAVECALLBACK lpfnCallback
,
2321 int nStreams
, PAVISTREAM pavi
, LPAVICOMPRESSOPTIONS lpOptions
, ...)
2323 FIXME("(%s,%p,%p,0x%08x,%p,%p), stub!\n", debugstr_a(szFile
), pclsidHandler
, lpfnCallback
,
2324 nStreams
, pavi
, lpOptions
);
2326 return AVIERR_UNSUPPORTED
;
2329 HRESULT CDECL
AVISaveW(LPCWSTR szFile
, CLSID
* pclsidHandler
, AVISAVECALLBACK lpfnCallback
,
2330 int nStreams
, PAVISTREAM pavi
, LPAVICOMPRESSOPTIONS lpOptions
, ...)
2332 FIXME("(%s,%p,%p,0x%08x,%p,%p), stub!\n", debugstr_w(szFile
), pclsidHandler
, lpfnCallback
,
2333 nStreams
, pavi
, lpOptions
);
2335 return AVIERR_UNSUPPORTED
;