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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
39 #include "avifile_private.h"
41 #include "wine/debug.h"
42 #include "wine/unicode.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
47 /***********************************************************************
48 * for AVIBuildFilterW -- uses fixed size table
50 #define MAX_FILTERS 30 /* 30 => 7kB */
52 typedef struct _AVIFilter
{
54 WCHAR szExtensions
[MAX_FILTERS
* 7];
57 /***********************************************************************
64 LPAVICOMPRESSOPTIONS
*ppOptions
;
68 /***********************************************************************
69 * copied from dlls/ole32/compobj.c
71 static HRESULT
AVIFILE_CLSIDFromString(LPCSTR idstr
, LPCLSID id
)
79 memset(id
, 0, sizeof(CLSID
));
83 /* validate the CLSID string */
84 if (lstrlenA(idstr
) != 38)
85 return CO_E_CLASSSTRING
;
87 s
= (BYTE
const*)idstr
;
88 if ((s
[0]!='{') || (s
[9]!='-') || (s
[14]!='-') || (s
[19]!='-') ||
89 (s
[24]!='-') || (s
[37]!='}'))
90 return CO_E_CLASSSTRING
;
92 for (i
= 1; i
< 37; i
++) {
93 if ((i
== 9) || (i
== 14) || (i
== 19) || (i
== 24))
95 if (!(((s
[i
] >= '0') && (s
[i
] <= '9')) ||
96 ((s
[i
] >= 'a') && (s
[i
] <= 'f')) ||
97 ((s
[i
] >= 'A') && (s
[i
] <= 'F')))
99 return CO_E_CLASSSTRING
;
102 TRACE("%s -> %p\n", s
, id
);
104 /* quick lookup table */
105 memset(table
, 0, 256);
107 for (i
= 0; i
< 10; i
++)
110 for (i
= 0; i
< 6; i
++) {
111 table
['A' + i
] = i
+10;
112 table
['a' + i
] = i
+10;
115 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
118 s
++; /* skip leading brace */
119 for (i
= 0; i
< 4; i
++) {
120 p
[3 - i
] = table
[*s
]<<4 | table
[*(s
+1)];
126 for (i
= 0; i
< 2; i
++) {
127 p
[1-i
] = table
[*s
]<<4 | table
[*(s
+1)];
133 for (i
= 0; i
< 2; i
++) {
134 p
[1-i
] = table
[*s
]<<4 | table
[*(s
+1)];
140 /* these are just sequential bytes */
141 for (i
= 0; i
< 2; i
++) {
142 *p
++ = table
[*s
]<<4 | table
[*(s
+1)];
147 for (i
= 0; i
< 6; i
++) {
148 *p
++ = table
[*s
]<<4 | table
[*(s
+1)];
155 static BOOL
AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile
, LPCLSID lpclsid
)
159 LPWSTR szExt
= strrchrW(szFile
, '.');
160 LONG len
= sizeof(szValue
) / sizeof(szValue
[0]);
167 wsprintfA(szRegKey
, "AVIFile\\Extensions\\%.3ls", szExt
);
168 if (RegQueryValueA(HKEY_CLASSES_ROOT
, szRegKey
, szValue
, &len
) != ERROR_SUCCESS
)
171 return (AVIFILE_CLSIDFromString(szValue
, lpclsid
) == S_OK
);
174 /***********************************************************************
175 * AVIFileInit (AVIFIL32.@)
176 * AVIFileInit (AVIFILE.100)
178 void WINAPI
AVIFileInit(void) {
182 /***********************************************************************
183 * AVIFileExit (AVIFIL32.@)
184 * AVIFileExit (AVIFILE.101)
186 void WINAPI
AVIFileExit(void) {
187 /* need to free ole32.dll if we are the last exit call */
188 /* OleUnitialize() */
189 FIXME("(): stub!\n");
192 /***********************************************************************
193 * AVIFileOpen (AVIFIL32.@)
194 * AVIFileOpenA (AVIFIL32.@)
195 * AVIFileOpen (AVIFILE.102)
197 HRESULT WINAPI
AVIFileOpenA(PAVIFILE
*ppfile
, LPCSTR szFile
, UINT uMode
,
200 LPWSTR wszFile
= NULL
;
204 TRACE("(%p,%s,0x%08X,%s)\n", ppfile
, debugstr_a(szFile
), uMode
,
205 debugstr_guid(lpHandler
));
207 /* check parameters */
208 if (ppfile
== NULL
|| szFile
== NULL
)
209 return AVIERR_BADPARAM
;
211 /* convert ASCII string to Unicode and call unicode function */
212 len
= MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, NULL
, 0);
214 return AVIERR_BADPARAM
;
216 wszFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
218 return AVIERR_MEMORY
;
220 MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, wszFile
, len
);
222 hr
= AVIFileOpenW(ppfile
, wszFile
, uMode
, lpHandler
);
224 HeapFree(GetProcessHeap(), 0, wszFile
);
229 /***********************************************************************
230 * AVIFileOpenW (AVIFIL32.@)
232 HRESULT WINAPI
AVIFileOpenW(PAVIFILE
*ppfile
, LPCWSTR szFile
, UINT uMode
,
235 IPersistFile
*ppersist
= NULL
;
239 TRACE("(%p,%s,0x%X,%s)\n", ppfile
, debugstr_w(szFile
), uMode
,
240 debugstr_guid(lpHandler
));
242 /* check parameters */
243 if (ppfile
== NULL
|| szFile
== NULL
)
244 return AVIERR_BADPARAM
;
248 /* if no handler then try guessing it by extension */
249 if (lpHandler
== NULL
) {
250 if (! AVIFILE_GetFileHandlerByExtension(szFile
, &clsidHandler
))
251 return AVIERR_UNSUPPORTED
;
253 memcpy(&clsidHandler
, lpHandler
, sizeof(clsidHandler
));
255 /* create instance of handler */
256 hr
= CoCreateInstance(&clsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIFile
, (LPVOID
*)ppfile
);
257 if (FAILED(hr
) || *ppfile
== NULL
)
260 /* ask for IPersistFile interface for loading/creating the file */
261 hr
= IAVIFile_QueryInterface(*ppfile
, &IID_IPersistFile
, (LPVOID
*)&ppersist
);
262 if (FAILED(hr
) || ppersist
== NULL
) {
263 IAVIFile_Release(*ppfile
);
268 hr
= IPersistFile_Load(ppersist
, szFile
, uMode
);
269 IPersistFile_Release(ppersist
);
271 IAVIFile_Release(*ppfile
);
278 /***********************************************************************
279 * AVIFileAddRef (AVIFIL32.@)
280 * AVIFileAddRef (AVIFILE.140)
282 ULONG WINAPI
AVIFileAddRef(PAVIFILE pfile
)
284 TRACE("(%p)\n", pfile
);
287 ERR(": bad handle passed!\n");
291 return IAVIFile_AddRef(pfile
);
294 /***********************************************************************
295 * AVIFileRelease (AVIFIL32.@)
296 * AVIFileRelease (AVIFILE.141)
298 ULONG WINAPI
AVIFileRelease(PAVIFILE pfile
)
300 TRACE("(%p)\n", pfile
);
303 ERR(": bad handle passed!\n");
307 return IAVIFile_Release(pfile
);
310 /***********************************************************************
311 * AVIFileInfo (AVIFIL32.@)
312 * AVIFileInfoA (AVIFIL32.@)
313 * AVIFileInfo (AVIFILE.142)
315 HRESULT WINAPI
AVIFileInfoA(PAVIFILE pfile
, LPAVIFILEINFOA afi
, LONG size
)
320 TRACE("(%p,%p,%d)\n", pfile
, afi
, size
);
323 return AVIERR_BADHANDLE
;
324 if ((DWORD
)size
< sizeof(AVIFILEINFOA
))
325 return AVIERR_BADSIZE
;
327 hres
= IAVIFile_Info(pfile
, &afiw
, sizeof(afiw
));
329 memcpy(afi
, &afiw
, sizeof(*afi
) - sizeof(afi
->szFileType
));
330 WideCharToMultiByte(CP_ACP
, 0, afiw
.szFileType
, -1, afi
->szFileType
,
331 sizeof(afi
->szFileType
), NULL
, NULL
);
332 afi
->szFileType
[sizeof(afi
->szFileType
) - 1] = 0;
337 /***********************************************************************
338 * AVIFileInfoW (AVIFIL32.@)
340 HRESULT WINAPI
AVIFileInfoW(PAVIFILE pfile
, LPAVIFILEINFOW afiw
, LONG size
)
342 TRACE("(%p,%p,%d)\n", pfile
, afiw
, size
);
345 return AVIERR_BADHANDLE
;
347 return IAVIFile_Info(pfile
, afiw
, size
);
350 /***********************************************************************
351 * AVIFileGetStream (AVIFIL32.@)
352 * AVIFileGetStream (AVIFILE.143)
354 HRESULT WINAPI
AVIFileGetStream(PAVIFILE pfile
, PAVISTREAM
*avis
,
355 DWORD fccType
, LONG lParam
)
357 TRACE("(%p,%p,'%4.4s',%d)\n", pfile
, avis
, (char*)&fccType
, lParam
);
360 return AVIERR_BADHANDLE
;
362 return IAVIFile_GetStream(pfile
, avis
, fccType
, lParam
);
365 /***********************************************************************
366 * AVIFileCreateStream (AVIFIL32.@)
367 * AVIFileCreateStreamA (AVIFIL32.@)
368 * AVIFileCreateStream (AVIFILE.144)
370 HRESULT WINAPI
AVIFileCreateStreamA(PAVIFILE pfile
, PAVISTREAM
*ppavi
,
371 LPAVISTREAMINFOA psi
)
375 TRACE("(%p,%p,%p)\n", pfile
, ppavi
, psi
);
378 return AVIERR_BADHANDLE
;
380 /* Only the szName at the end is different */
381 memcpy(&psiw
, psi
, sizeof(*psi
) - sizeof(psi
->szName
));
382 MultiByteToWideChar(CP_ACP
, 0, psi
->szName
, -1, psiw
.szName
,
383 sizeof(psiw
.szName
) / sizeof(psiw
.szName
[0]));
385 return IAVIFile_CreateStream(pfile
, ppavi
, &psiw
);
388 /***********************************************************************
389 * AVIFileCreateStreamW (AVIFIL32.@)
391 HRESULT WINAPI
AVIFileCreateStreamW(PAVIFILE pfile
, PAVISTREAM
*avis
,
392 LPAVISTREAMINFOW asi
)
394 TRACE("(%p,%p,%p)\n", pfile
, avis
, asi
);
397 return AVIERR_BADHANDLE
;
399 return IAVIFile_CreateStream(pfile
, avis
, asi
);
402 /***********************************************************************
403 * AVIFileWriteData (AVIFIL32.@)
404 * AVIFileWriteData (AVIFILE.146)
406 HRESULT WINAPI
AVIFileWriteData(PAVIFILE pfile
,DWORD fcc
,LPVOID lp
,LONG size
)
408 TRACE("(%p,'%4.4s',%p,%d)\n", pfile
, (char*)&fcc
, lp
, size
);
411 return AVIERR_BADHANDLE
;
413 return IAVIFile_WriteData(pfile
, fcc
, lp
, size
);
416 /***********************************************************************
417 * AVIFileReadData (AVIFIL32.@)
418 * AVIFileReadData (AVIFILE.147)
420 HRESULT WINAPI
AVIFileReadData(PAVIFILE pfile
,DWORD fcc
,LPVOID lp
,LPLONG size
)
422 TRACE("(%p,'%4.4s',%p,%p)\n", pfile
, (char*)&fcc
, lp
, size
);
425 return AVIERR_BADHANDLE
;
427 return IAVIFile_ReadData(pfile
, fcc
, lp
, size
);
430 /***********************************************************************
431 * AVIFileEndRecord (AVIFIL32.@)
432 * AVIFileEndRecord (AVIFILE.148)
434 HRESULT WINAPI
AVIFileEndRecord(PAVIFILE pfile
)
436 TRACE("(%p)\n", pfile
);
439 return AVIERR_BADHANDLE
;
441 return IAVIFile_EndRecord(pfile
);
444 /***********************************************************************
445 * AVIStreamAddRef (AVIFIL32.@)
446 * AVIStreamAddRef (AVIFILE.160)
448 ULONG WINAPI
AVIStreamAddRef(PAVISTREAM pstream
)
450 TRACE("(%p)\n", pstream
);
452 if (pstream
== NULL
) {
453 ERR(": bad handle passed!\n");
457 return IAVIStream_AddRef(pstream
);
460 /***********************************************************************
461 * AVIStreamRelease (AVIFIL32.@)
462 * AVIStreamRelease (AVIFILE.161)
464 ULONG WINAPI
AVIStreamRelease(PAVISTREAM pstream
)
466 TRACE("(%p)\n", pstream
);
468 if (pstream
== NULL
) {
469 ERR(": bad handle passed!\n");
473 return IAVIStream_Release(pstream
);
476 /***********************************************************************
477 * AVIStreamCreate (AVIFIL32.@)
478 * AVIStreamCreate (AVIFILE.104)
480 HRESULT WINAPI
AVIStreamCreate(PAVISTREAM
*ppavi
, LONG lParam1
, LONG lParam2
,
481 LPCLSID pclsidHandler
)
485 TRACE("(%p,0x%08X,0x%08X,%s)\n", ppavi
, lParam1
, lParam2
,
486 debugstr_guid(pclsidHandler
));
489 return AVIERR_BADPARAM
;
492 if (pclsidHandler
== NULL
)
493 return AVIERR_UNSUPPORTED
;
495 hr
= CoCreateInstance(pclsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIStream
, (LPVOID
*)ppavi
);
496 if (FAILED(hr
) || *ppavi
== NULL
)
499 hr
= IAVIStream_Create(*ppavi
, lParam1
, lParam2
);
501 IAVIStream_Release(*ppavi
);
508 /***********************************************************************
509 * AVIStreamInfo (AVIFIL32.@)
510 * AVIStreamInfoA (AVIFIL32.@)
511 * AVIStreamInfo (AVIFILE.162)
513 HRESULT WINAPI
AVIStreamInfoA(PAVISTREAM pstream
, LPAVISTREAMINFOA asi
,
519 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
522 return AVIERR_BADHANDLE
;
523 if ((DWORD
)size
< sizeof(AVISTREAMINFOA
))
524 return AVIERR_BADSIZE
;
526 hres
= IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
));
528 memcpy(asi
, &asiw
, sizeof(asiw
) - sizeof(asiw
.szName
));
529 WideCharToMultiByte(CP_ACP
, 0, asiw
.szName
, -1, asi
->szName
,
530 sizeof(asi
->szName
), NULL
, NULL
);
531 asi
->szName
[sizeof(asi
->szName
) - 1] = 0;
536 /***********************************************************************
537 * AVIStreamInfoW (AVIFIL32.@)
539 HRESULT WINAPI
AVIStreamInfoW(PAVISTREAM pstream
, LPAVISTREAMINFOW asi
,
542 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
545 return AVIERR_BADHANDLE
;
547 return IAVIStream_Info(pstream
, asi
, size
);
550 /***********************************************************************
551 * AVIStreamFindSample (AVIFIL32.@)
552 * AVIStreamFindSample (AVIFILE.163)
554 HRESULT WINAPI
AVIStreamFindSample(PAVISTREAM pstream
, LONG pos
, DWORD flags
)
556 TRACE("(%p,%d,0x%X)\n", pstream
, pos
, flags
);
561 return IAVIStream_FindSample(pstream
, pos
, flags
);
564 /***********************************************************************
565 * AVIStreamReadFormat (AVIFIL32.@)
566 * AVIStreamReadFormat (AVIFILE.164)
568 HRESULT WINAPI
AVIStreamReadFormat(PAVISTREAM pstream
, LONG pos
,
569 LPVOID format
, LPLONG formatsize
)
571 TRACE("(%p,%d,%p,%p)\n", pstream
, pos
, format
, formatsize
);
574 return AVIERR_BADHANDLE
;
576 return IAVIStream_ReadFormat(pstream
, pos
, format
, formatsize
);
579 /***********************************************************************
580 * AVIStreamSetFormat (AVIFIL32.@)
581 * AVIStreamSetFormat (AVIFILE.169)
583 HRESULT WINAPI
AVIStreamSetFormat(PAVISTREAM pstream
, LONG pos
,
584 LPVOID format
, LONG formatsize
)
586 TRACE("(%p,%d,%p,%d)\n", pstream
, pos
, format
, formatsize
);
589 return AVIERR_BADHANDLE
;
591 return IAVIStream_SetFormat(pstream
, pos
, format
, formatsize
);
594 /***********************************************************************
595 * AVIStreamRead (AVIFIL32.@)
596 * AVIStreamRead (AVIFILE.167)
598 HRESULT WINAPI
AVIStreamRead(PAVISTREAM pstream
, LONG start
, LONG samples
,
599 LPVOID buffer
, LONG buffersize
,
600 LPLONG bytesread
, LPLONG samplesread
)
602 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", pstream
, start
, samples
, buffer
,
603 buffersize
, bytesread
, samplesread
);
606 return AVIERR_BADHANDLE
;
608 return IAVIStream_Read(pstream
, start
, samples
, buffer
, buffersize
,
609 bytesread
, samplesread
);
612 /***********************************************************************
613 * AVIStreamWrite (AVIFIL32.@)
614 * AVIStreamWrite (AVIFILE.168)
616 HRESULT WINAPI
AVIStreamWrite(PAVISTREAM pstream
, LONG start
, LONG samples
,
617 LPVOID buffer
, LONG buffersize
, DWORD flags
,
618 LPLONG sampwritten
, LPLONG byteswritten
)
620 TRACE("(%p,%d,%d,%p,%d,0x%X,%p,%p)\n", pstream
, start
, samples
, buffer
,
621 buffersize
, flags
, sampwritten
, byteswritten
);
624 return AVIERR_BADHANDLE
;
626 return IAVIStream_Write(pstream
, start
, samples
, buffer
, buffersize
,
627 flags
, sampwritten
, byteswritten
);
630 /***********************************************************************
631 * AVIStreamReadData (AVIFIL32.@)
632 * AVIStreamReadData (AVIFILE.165)
634 HRESULT WINAPI
AVIStreamReadData(PAVISTREAM pstream
, DWORD fcc
, LPVOID lp
,
637 TRACE("(%p,'%4.4s',%p,%p)\n", pstream
, (char*)&fcc
, lp
, lpread
);
640 return AVIERR_BADHANDLE
;
642 return IAVIStream_ReadData(pstream
, fcc
, lp
, lpread
);
645 /***********************************************************************
646 * AVIStreamWriteData (AVIFIL32.@)
647 * AVIStreamWriteData (AVIFILE.166)
649 HRESULT WINAPI
AVIStreamWriteData(PAVISTREAM pstream
, DWORD fcc
, LPVOID lp
,
652 TRACE("(%p,'%4.4s',%p,%d)\n", pstream
, (char*)&fcc
, lp
, size
);
655 return AVIERR_BADHANDLE
;
657 return IAVIStream_WriteData(pstream
, fcc
, lp
, size
);
660 /***********************************************************************
661 * AVIStreamGetFrameOpen (AVIFIL32.@)
662 * AVIStreamGetFrameOpen (AVIFILE.112)
664 PGETFRAME WINAPI
AVIStreamGetFrameOpen(PAVISTREAM pstream
,
665 LPBITMAPINFOHEADER lpbiWanted
)
669 TRACE("(%p,%p)\n", pstream
, lpbiWanted
);
671 if (FAILED(IAVIStream_QueryInterface(pstream
, &IID_IGetFrame
, (LPVOID
*)&pg
)) ||
673 pg
= AVIFILE_CreateGetFrame(pstream
);
678 if (FAILED(IGetFrame_SetFormat(pg
, lpbiWanted
, NULL
, 0, 0, -1, -1))) {
679 IGetFrame_Release(pg
);
686 /***********************************************************************
687 * AVIStreamGetFrame (AVIFIL32.@)
688 * AVIStreamGetFrame (AVIFILE.110)
690 LPVOID WINAPI
AVIStreamGetFrame(PGETFRAME pg
, LONG pos
)
692 TRACE("(%p,%d)\n", pg
, pos
);
697 return IGetFrame_GetFrame(pg
, pos
);
700 /***********************************************************************
701 * AVIStreamGetFrameClose (AVIFIL32.@)
702 * AVIStreamGetFrameClose (AVIFILE.111)
704 HRESULT WINAPI
AVIStreamGetFrameClose(PGETFRAME pg
)
709 return IGetFrame_Release(pg
);
713 /***********************************************************************
714 * AVIMakeCompressedStream (AVIFIL32.@)
716 HRESULT WINAPI
AVIMakeCompressedStream(PAVISTREAM
*ppsCompressed
,
718 LPAVICOMPRESSOPTIONS aco
,
719 LPCLSID pclsidHandler
)
726 LONG size
= sizeof(szValue
);
728 TRACE("(%p,%p,%p,%s)\n", ppsCompressed
, psSource
, aco
,
729 debugstr_guid(pclsidHandler
));
731 if (ppsCompressed
== NULL
)
732 return AVIERR_BADPARAM
;
733 if (psSource
== NULL
)
734 return AVIERR_BADHANDLE
;
736 *ppsCompressed
= NULL
;
738 /* if no handler given get default ones based on streamtype */
739 if (pclsidHandler
== NULL
) {
740 hr
= IAVIStream_Info(psSource
, &asiw
, sizeof(asiw
));
744 wsprintfA(szRegKey
, "AVIFile\\Compressors\\%4.4s", (char*)&asiw
.fccType
);
745 if (RegQueryValueA(HKEY_CLASSES_ROOT
, szRegKey
, szValue
, &size
) != ERROR_SUCCESS
)
746 return AVIERR_UNSUPPORTED
;
747 if (AVIFILE_CLSIDFromString(szValue
, &clsidHandler
) != S_OK
)
748 return AVIERR_UNSUPPORTED
;
750 memcpy(&clsidHandler
, pclsidHandler
, sizeof(clsidHandler
));
752 hr
= CoCreateInstance(&clsidHandler
, NULL
, CLSCTX_INPROC
, &IID_IAVIStream
, (LPVOID
*)ppsCompressed
);
753 if (FAILED(hr
) || *ppsCompressed
== NULL
)
756 hr
= IAVIStream_Create(*ppsCompressed
, (LPARAM
)psSource
, (LPARAM
)aco
);
758 IAVIStream_Release(*ppsCompressed
);
759 *ppsCompressed
= NULL
;
765 /***********************************************************************
766 * AVIMakeFileFromStreams (AVIFIL32.@)
768 HRESULT WINAPI
AVIMakeFileFromStreams(PAVIFILE
*ppfile
, int nStreams
,
769 PAVISTREAM
*ppStreams
)
771 TRACE("(%p,%d,%p)\n", ppfile
, nStreams
, ppStreams
);
773 if (nStreams
< 0 || ppfile
== NULL
|| ppStreams
== NULL
)
774 return AVIERR_BADPARAM
;
776 *ppfile
= AVIFILE_CreateAVITempFile(nStreams
, ppStreams
);
778 return AVIERR_MEMORY
;
783 /***********************************************************************
784 * AVIStreamOpenFromFile (AVIFIL32.@)
785 * AVIStreamOpenFromFileA (AVIFIL32.@)
786 * AVIStreamOpenFromFile (AVIFILE.103)
788 HRESULT WINAPI
AVIStreamOpenFromFileA(PAVISTREAM
*ppavi
, LPCSTR szFile
,
789 DWORD fccType
, LONG lParam
,
790 UINT mode
, LPCLSID pclsidHandler
)
792 PAVIFILE pfile
= NULL
;
795 TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi
, debugstr_a(szFile
),
796 (char*)&fccType
, lParam
, mode
, debugstr_guid(pclsidHandler
));
798 if (ppavi
== NULL
|| szFile
== NULL
)
799 return AVIERR_BADPARAM
;
803 hr
= AVIFileOpenA(&pfile
, szFile
, mode
, pclsidHandler
);
804 if (FAILED(hr
) || pfile
== NULL
)
807 hr
= IAVIFile_GetStream(pfile
, ppavi
, fccType
, lParam
);
808 IAVIFile_Release(pfile
);
813 /***********************************************************************
814 * AVIStreamOpenFromFileW (AVIFIL32.@)
816 HRESULT WINAPI
AVIStreamOpenFromFileW(PAVISTREAM
*ppavi
, LPCWSTR szFile
,
817 DWORD fccType
, LONG lParam
,
818 UINT mode
, LPCLSID pclsidHandler
)
820 PAVIFILE pfile
= NULL
;
823 TRACE("(%p,%s,'%4.4s',%d,0x%X,%s)\n", ppavi
, debugstr_w(szFile
),
824 (char*)&fccType
, lParam
, mode
, debugstr_guid(pclsidHandler
));
826 if (ppavi
== NULL
|| szFile
== NULL
)
827 return AVIERR_BADPARAM
;
831 hr
= AVIFileOpenW(&pfile
, szFile
, mode
, pclsidHandler
);
832 if (FAILED(hr
) || pfile
== NULL
)
835 hr
= IAVIFile_GetStream(pfile
, ppavi
, fccType
, lParam
);
836 IAVIFile_Release(pfile
);
841 /***********************************************************************
842 * AVIStreamBeginStreaming (AVIFIL32.@)
844 LONG WINAPI
AVIStreamBeginStreaming(PAVISTREAM pavi
, LONG lStart
, LONG lEnd
, LONG lRate
)
846 IAVIStreaming
* pstream
= NULL
;
849 TRACE("(%p,%d,%d,%d)\n", pavi
, lStart
, lEnd
, lRate
);
852 return AVIERR_BADHANDLE
;
854 hr
= IAVIStream_QueryInterface(pavi
, &IID_IAVIStreaming
, (LPVOID
*)&pstream
);
855 if (SUCCEEDED(hr
) && pstream
!= NULL
) {
856 hr
= IAVIStreaming_Begin(pstream
, lStart
, lEnd
, lRate
);
857 IAVIStreaming_Release(pstream
);
864 /***********************************************************************
865 * AVIStreamEndStreaming (AVIFIL32.@)
867 LONG WINAPI
AVIStreamEndStreaming(PAVISTREAM pavi
)
869 IAVIStreaming
* pstream
= NULL
;
872 TRACE("(%p)\n", pavi
);
874 hr
= IAVIStream_QueryInterface(pavi
, &IID_IAVIStreaming
, (LPVOID
*)&pstream
);
875 if (SUCCEEDED(hr
) && pstream
!= NULL
) {
876 IAVIStreaming_End(pstream
);
877 IAVIStreaming_Release(pstream
);
883 /***********************************************************************
884 * AVIStreamStart (AVIFILE.130)
885 * AVIStreamStart (AVIFIL32.@)
887 LONG WINAPI
AVIStreamStart(PAVISTREAM pstream
)
891 TRACE("(%p)\n", pstream
);
896 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
902 /***********************************************************************
903 * AVIStreamLength (AVIFILE.131)
904 * AVIStreamLength (AVIFIL32.@)
906 LONG WINAPI
AVIStreamLength(PAVISTREAM pstream
)
910 TRACE("(%p)\n", pstream
);
915 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
918 return asiw
.dwLength
;
921 /***********************************************************************
922 * AVIStreamSampleToTime (AVIFILE.133)
923 * AVIStreamSampleToTime (AVIFIL32.@)
925 LONG WINAPI
AVIStreamSampleToTime(PAVISTREAM pstream
, LONG lSample
)
930 TRACE("(%p,%d)\n", pstream
, lSample
);
935 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
937 if (asiw
.dwRate
== 0)
940 /* limit to stream bounds */
941 if (lSample
< asiw
.dwStart
)
942 lSample
= asiw
.dwStart
;
943 if (lSample
> asiw
.dwStart
+ asiw
.dwLength
)
944 lSample
= asiw
.dwStart
+ asiw
.dwLength
;
946 if (asiw
.dwRate
/ asiw
.dwScale
< 1000)
947 time
= (LONG
)(((float)lSample
* asiw
.dwScale
* 1000) / asiw
.dwRate
);
949 time
= (LONG
)(((float)lSample
* asiw
.dwScale
* 1000 + (asiw
.dwRate
- 1)) / asiw
.dwRate
);
951 TRACE(" -> %d\n",time
);
955 /***********************************************************************
956 * AVIStreamTimeToSample (AVIFILE.132)
957 * AVIStreamTimeToSample (AVIFIL32.@)
959 LONG WINAPI
AVIStreamTimeToSample(PAVISTREAM pstream
, LONG lTime
)
964 TRACE("(%p,%d)\n", pstream
, lTime
);
966 if (pstream
== NULL
|| lTime
< 0)
969 if (FAILED(IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
))))
971 if (asiw
.dwScale
== 0)
974 if (asiw
.dwRate
/ asiw
.dwScale
< 1000)
975 sample
= (LONG
)((((float)asiw
.dwRate
* lTime
) / (asiw
.dwScale
* 1000)));
977 sample
= (LONG
)(((float)asiw
.dwRate
* lTime
+ (asiw
.dwScale
* 1000 - 1)) / (asiw
.dwScale
* 1000));
979 /* limit to stream bounds */
980 if (sample
< asiw
.dwStart
)
981 sample
= asiw
.dwStart
;
982 if (sample
> asiw
.dwStart
+ asiw
.dwLength
)
983 sample
= asiw
.dwStart
+ asiw
.dwLength
;
985 TRACE(" -> %d\n", sample
);
989 /***********************************************************************
990 * AVIBuildFilter (AVIFIL32.@)
991 * AVIBuildFilterA (AVIFIL32.@)
992 * AVIBuildFilter (AVIFILE.123)
994 HRESULT WINAPI
AVIBuildFilterA(LPSTR szFilter
, LONG cbFilter
, BOOL fSaving
)
999 TRACE("(%p,%d,%d)\n", szFilter
, cbFilter
, fSaving
);
1001 /* check parameters */
1002 if (szFilter
== NULL
)
1003 return AVIERR_BADPARAM
;
1005 return AVIERR_BADSIZE
;
1010 wszFilter
= HeapAlloc(GetProcessHeap(), 0, cbFilter
* sizeof(WCHAR
));
1011 if (wszFilter
== NULL
)
1012 return AVIERR_MEMORY
;
1014 hr
= AVIBuildFilterW(wszFilter
, cbFilter
, fSaving
);
1015 if (SUCCEEDED(hr
)) {
1016 WideCharToMultiByte(CP_ACP
, 0, wszFilter
, cbFilter
,
1017 szFilter
, cbFilter
, NULL
, NULL
);
1020 HeapFree(GetProcessHeap(), 0, wszFilter
);
1025 /***********************************************************************
1026 * AVIBuildFilterW (AVIFIL32.@)
1028 HRESULT WINAPI
AVIBuildFilterW(LPWSTR szFilter
, LONG cbFilter
, BOOL fSaving
)
1030 static const WCHAR szClsid
[] = {'C','L','S','I','D',0};
1031 static const WCHAR szExtensionFmt
[] = {';','*','.','%','s',0};
1032 static const WCHAR szAVIFileExtensions
[] =
1033 {'A','V','I','F','i','l','e','\\','E','x','t','e','n','s','i','o','n','s',0};
1036 WCHAR szAllFiles
[40];
1037 WCHAR szFileExt
[10];
1044 TRACE("(%p,%d,%d)\n", szFilter
, cbFilter
, fSaving
);
1046 /* check parameters */
1047 if (szFilter
== NULL
)
1048 return AVIERR_BADPARAM
;
1050 return AVIERR_BADSIZE
;
1052 lp
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, MAX_FILTERS
* sizeof(AVIFilter
));
1054 return AVIERR_MEMORY
;
1057 * 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
1058 * extensions and CLSID's
1059 * 2. iterate over collected CLSID's and copy its description and its
1060 * extensions to szFilter if it fits
1062 * First filter is named "All multimedia files" and its filter is a
1063 * collection of all possible extensions except "*.*".
1065 if (RegOpenKeyW(HKEY_CLASSES_ROOT
, szAVIFileExtensions
, &hKey
) != S_OK
) {
1066 HeapFree(GetProcessHeap(), 0, lp
);
1067 return AVIERR_ERROR
;
1069 for (n
= 0;RegEnumKeyW(hKey
, n
, szFileExt
, sizeof(szFileExt
)) == S_OK
;n
++) {
1070 /* get CLSID to extension */
1071 size
= sizeof(szValue
)/sizeof(szValue
[0]);
1072 if (RegQueryValueW(hKey
, szFileExt
, szValue
, &size
) != S_OK
)
1075 /* search if the CLSID is already known */
1076 for (i
= 1; i
<= count
; i
++) {
1077 if (lstrcmpW(lp
[i
].szClsid
, szValue
) == 0)
1078 break; /* a new one */
1081 if (count
- i
== -1U) {
1082 /* it's a new CLSID */
1084 /* FIXME: How do we get info's about read/write capabilities? */
1086 if (count
>= MAX_FILTERS
) {
1087 /* try to inform user of our full fixed size table */
1088 ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS
);
1092 lstrcpyW(lp
[i
].szClsid
, szValue
);
1097 /* append extension to the filter */
1098 wsprintfW(szValue
, szExtensionFmt
, szFileExt
);
1099 if (lp
[i
].szExtensions
[0] == 0)
1100 lstrcatW(lp
[i
].szExtensions
, szValue
+ 1);
1102 lstrcatW(lp
[i
].szExtensions
, szValue
);
1104 /* also append to the "all multimedia"-filter */
1105 if (lp
[0].szExtensions
[0] == 0)
1106 lstrcatW(lp
[0].szExtensions
, szValue
+ 1);
1108 lstrcatW(lp
[0].szExtensions
, szValue
);
1112 /* 2. get descriptions for the CLSIDs and fill out szFilter */
1113 if (RegOpenKeyW(HKEY_CLASSES_ROOT
, szClsid
, &hKey
) != S_OK
) {
1114 HeapFree(GetProcessHeap(), 0, lp
);
1115 return AVIERR_ERROR
;
1117 for (n
= 0; n
<= count
; n
++) {
1118 /* first the description */
1120 size
= sizeof(szValue
)/sizeof(szValue
[0]);
1121 if (RegQueryValueW(hKey
, lp
[n
].szClsid
, szValue
, &size
) == S_OK
) {
1122 size
= lstrlenW(szValue
);
1123 lstrcpynW(szFilter
, szValue
, cbFilter
);
1126 size
= LoadStringW(AVIFILE_hModule
,IDS_ALLMULTIMEDIA
,szFilter
,cbFilter
);
1128 /* check for enough space */
1130 if (cbFilter
< size
+ lstrlenW(lp
[n
].szExtensions
) + 2) {
1133 HeapFree(GetProcessHeap(), 0, lp
);
1135 return AVIERR_BUFFERTOOSMALL
;
1140 /* and then the filter */
1141 lstrcpynW(szFilter
, lp
[n
].szExtensions
, cbFilter
);
1142 size
= lstrlenW(lp
[n
].szExtensions
) + 1;
1148 HeapFree(GetProcessHeap(), 0, lp
);
1150 /* add "All files" "*.*" filter if enough space left */
1151 size
= LoadStringW(AVIFILE_hModule
, IDS_ALLFILES
,
1152 szAllFiles
, sizeof(szAllFiles
)) + 1;
1153 if (cbFilter
> size
) {
1156 /* replace '@' with \000 to separate description of filter */
1157 for (i
= 0; i
< size
&& szAllFiles
[i
] != 0; i
++) {
1158 if (szAllFiles
[i
] == '@') {
1164 memcpy(szFilter
, szAllFiles
, size
* sizeof(szAllFiles
[0]));
1171 return AVIERR_BUFFERTOOSMALL
;
1175 static BOOL
AVISaveOptionsFmtChoose(HWND hWnd
)
1177 LPAVICOMPRESSOPTIONS pOptions
= SaveOpts
.ppOptions
[SaveOpts
.nCurrent
];
1178 AVISTREAMINFOW sInfo
;
1180 TRACE("(%p)\n", hWnd
);
1182 if (pOptions
== NULL
|| SaveOpts
.ppavis
[SaveOpts
.nCurrent
] == NULL
) {
1183 ERR(": bad state!\n");
1187 if (FAILED(AVIStreamInfoW(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1188 &sInfo
, sizeof(sInfo
)))) {
1189 ERR(": AVIStreamInfoW failed!\n");
1193 if (sInfo
.fccType
== streamtypeVIDEO
) {
1197 memset(&cv
, 0, sizeof(cv
));
1199 if ((pOptions
->dwFlags
& AVICOMPRESSF_VALID
) == 0) {
1200 memset(pOptions
, 0, sizeof(AVICOMPRESSOPTIONS
));
1201 pOptions
->fccType
= streamtypeVIDEO
;
1202 pOptions
->fccHandler
= comptypeDIB
;
1203 pOptions
->dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
1206 cv
.cbSize
= sizeof(cv
);
1207 cv
.dwFlags
= ICMF_COMPVARS_VALID
;
1208 /*cv.fccType = pOptions->fccType; */
1209 cv
.fccHandler
= pOptions
->fccHandler
;
1210 cv
.lQ
= pOptions
->dwQuality
;
1211 cv
.lpState
= pOptions
->lpParms
;
1212 cv
.cbState
= pOptions
->cbParms
;
1213 if (pOptions
->dwFlags
& AVICOMPRESSF_KEYFRAMES
)
1214 cv
.lKey
= pOptions
->dwKeyFrameEvery
;
1217 if (pOptions
->dwFlags
& AVICOMPRESSF_DATARATE
)
1218 cv
.lDataRate
= pOptions
->dwBytesPerSecond
/ 1024; /* need kBytes */
1222 ret
= ICCompressorChoose(hWnd
, SaveOpts
.uFlags
, NULL
,
1223 SaveOpts
.ppavis
[SaveOpts
.nCurrent
], &cv
, NULL
);
1226 pOptions
->fccHandler
= cv
.fccHandler
;
1227 pOptions
->lpParms
= cv
.lpState
;
1228 pOptions
->cbParms
= cv
.cbState
;
1229 pOptions
->dwQuality
= cv
.lQ
;
1231 pOptions
->dwKeyFrameEvery
= cv
.lKey
;
1232 pOptions
->dwFlags
|= AVICOMPRESSF_KEYFRAMES
;
1234 pOptions
->dwFlags
&= ~AVICOMPRESSF_KEYFRAMES
;
1235 if (cv
.lDataRate
!= 0) {
1236 pOptions
->dwBytesPerSecond
= cv
.lDataRate
* 1024; /* need bytes */
1237 pOptions
->dwFlags
|= AVICOMPRESSF_DATARATE
;
1239 pOptions
->dwFlags
&= ~AVICOMPRESSF_DATARATE
;
1240 pOptions
->dwFlags
|= AVICOMPRESSF_VALID
;
1242 ICCompressorFree(&cv
);
1245 } else if (sInfo
.fccType
== streamtypeAUDIO
) {
1246 ACMFORMATCHOOSEW afmtc
;
1250 /* FIXME: check ACM version -- Which version is needed? */
1252 memset(&afmtc
, 0, sizeof(afmtc
));
1253 afmtc
.cbStruct
= sizeof(afmtc
);
1255 afmtc
.hwndOwner
= hWnd
;
1257 acmMetrics(NULL
, ACM_METRIC_MAX_SIZE_FORMAT
, &size
);
1258 if ((pOptions
->cbFormat
== 0 || pOptions
->lpFormat
== NULL
) && size
!= 0) {
1259 pOptions
->lpFormat
= HeapAlloc(GetProcessHeap(), 0, size
);
1260 pOptions
->cbFormat
= size
;
1261 } else if (pOptions
->cbFormat
< (DWORD
)size
) {
1262 pOptions
->lpFormat
= HeapReAlloc(GetProcessHeap(), 0, pOptions
->lpFormat
, size
);
1263 pOptions
->cbFormat
= size
;
1265 if (pOptions
->lpFormat
== NULL
)
1267 afmtc
.pwfx
= pOptions
->lpFormat
;
1268 afmtc
.cbwfx
= pOptions
->cbFormat
;
1271 AVIStreamFormatSize(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1272 sInfo
.dwStart
, &size
);
1273 if (size
< (LONG
)sizeof(PCMWAVEFORMAT
))
1274 size
= sizeof(PCMWAVEFORMAT
);
1275 afmtc
.pwfxEnum
= HeapAlloc(GetProcessHeap(), 0, size
);
1276 if (afmtc
.pwfxEnum
!= NULL
) {
1277 AVIStreamReadFormat(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],
1278 sInfo
.dwStart
, afmtc
.pwfxEnum
, &size
);
1279 afmtc
.fdwEnum
= ACM_FORMATENUMF_CONVERT
;
1282 ret
= acmFormatChooseW(&afmtc
);
1284 pOptions
->dwFlags
|= AVICOMPRESSF_VALID
;
1286 HeapFree(GetProcessHeap(), 0, afmtc
.pwfxEnum
);
1287 return (ret
== S_OK
? TRUE
: FALSE
);
1289 ERR(": unknown streamtype 0x%08X\n", sInfo
.fccType
);
1294 static void AVISaveOptionsUpdate(HWND hWnd
)
1296 static const WCHAR szVideoFmt
[]={'%','l','d','x','%','l','d','x','%','d',0};
1297 static const WCHAR szAudioFmt
[]={'%','s',' ','%','s',0};
1299 WCHAR szFormat
[128];
1300 AVISTREAMINFOW sInfo
;
1304 TRACE("(%p)\n", hWnd
);
1306 SaveOpts
.nCurrent
= SendDlgItemMessageW(hWnd
,IDC_STREAM
,CB_GETCURSEL
,0,0);
1307 if (SaveOpts
.nCurrent
< 0)
1310 if (FAILED(AVIStreamInfoW(SaveOpts
.ppavis
[SaveOpts
.nCurrent
], &sInfo
, sizeof(sInfo
))))
1313 AVIStreamFormatSize(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],sInfo
.dwStart
,&size
);
1317 /* read format to build format description string */
1318 lpFormat
= HeapAlloc(GetProcessHeap(), 0, size
);
1319 if (lpFormat
!= NULL
) {
1320 if (SUCCEEDED(AVIStreamReadFormat(SaveOpts
.ppavis
[SaveOpts
.nCurrent
],sInfo
.dwStart
,lpFormat
, &size
))) {
1321 if (sInfo
.fccType
== streamtypeVIDEO
) {
1322 LPBITMAPINFOHEADER lpbi
= lpFormat
;
1325 wsprintfW(szFormat
, szVideoFmt
, lpbi
->biWidth
,
1326 lpbi
->biHeight
, lpbi
->biBitCount
);
1328 if (lpbi
->biCompression
!= BI_RGB
) {
1331 hic
= ICLocate(ICTYPE_VIDEO
, sInfo
.fccHandler
, lpFormat
,
1332 NULL
, ICMODE_DECOMPRESS
);
1334 if (ICGetInfo(hic
, &icinfo
, sizeof(icinfo
)) == S_OK
)
1335 lstrcatW(szFormat
, icinfo
.szDescription
);
1339 LoadStringW(AVIFILE_hModule
, IDS_UNCOMPRESSED
,
1340 icinfo
.szDescription
, sizeof(icinfo
.szDescription
));
1341 lstrcatW(szFormat
, icinfo
.szDescription
);
1343 } else if (sInfo
.fccType
== streamtypeAUDIO
) {
1344 ACMFORMATTAGDETAILSW aftd
;
1345 ACMFORMATDETAILSW afd
;
1347 memset(&aftd
, 0, sizeof(aftd
));
1348 memset(&afd
, 0, sizeof(afd
));
1350 aftd
.cbStruct
= sizeof(aftd
);
1351 aftd
.dwFormatTag
= afd
.dwFormatTag
=
1352 ((PWAVEFORMATEX
)lpFormat
)->wFormatTag
;
1353 aftd
.cbFormatSize
= afd
.cbwfx
= size
;
1355 afd
.cbStruct
= sizeof(afd
);
1356 afd
.pwfx
= lpFormat
;
1358 if (acmFormatTagDetailsW(NULL
, &aftd
,
1359 ACM_FORMATTAGDETAILSF_FORMATTAG
) == S_OK
) {
1360 if (acmFormatDetailsW(NULL
,&afd
,ACM_FORMATDETAILSF_FORMAT
) == S_OK
)
1361 wsprintfW(szFormat
, szAudioFmt
, afd
.szFormat
, aftd
.szFormatTag
);
1365 HeapFree(GetProcessHeap(), 0, lpFormat
);
1368 /* set text for format description */
1369 SetDlgItemTextW(hWnd
, IDC_FORMATTEXT
, szFormat
);
1371 /* Disable option button for unsupported streamtypes */
1372 if (sInfo
.fccType
== streamtypeVIDEO
||
1373 sInfo
.fccType
== streamtypeAUDIO
)
1374 EnableWindow(GetDlgItem(hWnd
, IDC_OPTIONS
), TRUE
);
1376 EnableWindow(GetDlgItem(hWnd
, IDC_OPTIONS
), FALSE
);
1381 static INT_PTR CALLBACK
AVISaveOptionsDlgProc(HWND hWnd
, UINT uMsg
,
1382 WPARAM wParam
, LPARAM lParam
)
1385 BOOL bIsInterleaved
;
1388 /*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
1392 SaveOpts
.nCurrent
= 0;
1393 if (SaveOpts
.nStreams
== 1) {
1394 EndDialog(hWnd
, AVISaveOptionsFmtChoose(hWnd
));
1399 for (n
= 0; n
< SaveOpts
.nStreams
; n
++) {
1400 AVISTREAMINFOW sInfo
;
1402 AVIStreamInfoW(SaveOpts
.ppavis
[n
], &sInfo
, sizeof(sInfo
));
1403 SendDlgItemMessageW(hWnd
, IDC_STREAM
, CB_ADDSTRING
,
1404 0L, (LPARAM
)sInfo
.szName
);
1407 /* select first stream */
1408 SendDlgItemMessageW(hWnd
, IDC_STREAM
, CB_SETCURSEL
, 0, 0);
1409 SendMessageW(hWnd
, WM_COMMAND
, MAKELONG(IDC_STREAM
, CBN_SELCHANGE
), (LPARAM
)hWnd
);
1411 /* initialize interleave */
1412 if (SaveOpts
.ppOptions
[0] != NULL
&&
1413 (SaveOpts
.ppOptions
[0]->dwFlags
& AVICOMPRESSF_VALID
)) {
1414 bIsInterleaved
= (SaveOpts
.ppOptions
[0]->dwFlags
& AVICOMPRESSF_INTERLEAVE
);
1415 dwInterleave
= SaveOpts
.ppOptions
[0]->dwInterleaveEvery
;
1417 bIsInterleaved
= TRUE
;
1420 CheckDlgButton(hWnd
, IDC_INTERLEAVE
, bIsInterleaved
);
1421 SetDlgItemInt(hWnd
, IDC_INTERLEAVEEVERY
, dwInterleave
, FALSE
);
1422 EnableWindow(GetDlgItem(hWnd
, IDC_INTERLEAVEEVERY
), bIsInterleaved
);
1425 switch (LOWORD(wParam
)) {
1427 /* get data from controls and save them */
1428 dwInterleave
= GetDlgItemInt(hWnd
, IDC_INTERLEAVEEVERY
, NULL
, 0);
1429 bIsInterleaved
= IsDlgButtonChecked(hWnd
, IDC_INTERLEAVE
);
1430 for (n
= 0; n
< SaveOpts
.nStreams
; n
++) {
1431 if (SaveOpts
.ppOptions
[n
] != NULL
) {
1432 if (bIsInterleaved
) {
1433 SaveOpts
.ppOptions
[n
]->dwFlags
|= AVICOMPRESSF_INTERLEAVE
;
1434 SaveOpts
.ppOptions
[n
]->dwInterleaveEvery
= dwInterleave
;
1436 SaveOpts
.ppOptions
[n
]->dwFlags
&= ~AVICOMPRESSF_INTERLEAVE
;
1441 EndDialog(hWnd
, LOWORD(wParam
) == IDOK
);
1443 case IDC_INTERLEAVE
:
1444 EnableWindow(GetDlgItem(hWnd
, IDC_INTERLEAVEEVERY
),
1445 IsDlgButtonChecked(hWnd
, IDC_INTERLEAVE
));
1448 if (HIWORD(wParam
) == CBN_SELCHANGE
) {
1449 /* update control elements */
1450 AVISaveOptionsUpdate(hWnd
);
1454 AVISaveOptionsFmtChoose(hWnd
);
1463 /***********************************************************************
1464 * AVISaveOptions (AVIFIL32.@)
1466 BOOL WINAPI
AVISaveOptions(HWND hWnd
, UINT uFlags
, INT nStreams
,
1467 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*ppOptions
)
1469 LPAVICOMPRESSOPTIONS pSavedOptions
= NULL
;
1472 TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd
, uFlags
, nStreams
,
1475 /* check parameters */
1476 if (nStreams
<= 0 || ppavi
== NULL
|| ppOptions
== NULL
)
1477 return AVIERR_BADPARAM
;
1479 /* save options in case the user presses cancel */
1480 if (ppOptions
!= NULL
&& nStreams
> 1) {
1481 pSavedOptions
= HeapAlloc(GetProcessHeap(), 0, nStreams
* sizeof(AVICOMPRESSOPTIONS
));
1482 if (pSavedOptions
== NULL
)
1485 for (n
= 0; n
< nStreams
; n
++) {
1486 if (ppOptions
[n
] != NULL
)
1487 memcpy(pSavedOptions
+ n
, ppOptions
[n
], sizeof(AVICOMPRESSOPTIONS
));
1491 SaveOpts
.uFlags
= uFlags
;
1492 SaveOpts
.nStreams
= nStreams
;
1493 SaveOpts
.ppavis
= ppavi
;
1494 SaveOpts
.ppOptions
= ppOptions
;
1496 ret
= DialogBoxW(AVIFILE_hModule
, MAKEINTRESOURCEW(IDD_SAVEOPTIONS
),
1497 hWnd
, AVISaveOptionsDlgProc
);
1502 /* restore options when user pressed cancel */
1503 if (pSavedOptions
!= NULL
) {
1505 for (n
= 0; n
< nStreams
; n
++) {
1506 if (ppOptions
[n
] != NULL
)
1507 memcpy(ppOptions
[n
], pSavedOptions
+ n
, sizeof(AVICOMPRESSOPTIONS
));
1510 HeapFree(GetProcessHeap(), 0, pSavedOptions
);
1516 /***********************************************************************
1517 * AVISaveOptionsFree (AVIFIL32.@)
1518 * AVISaveOptionsFree (AVIFILE.124)
1520 HRESULT WINAPI
AVISaveOptionsFree(INT nStreams
,LPAVICOMPRESSOPTIONS
*ppOptions
)
1522 TRACE("(%d,%p)\n", nStreams
, ppOptions
);
1524 if (nStreams
< 0 || ppOptions
== NULL
)
1525 return AVIERR_BADPARAM
;
1527 for (; nStreams
> 0; nStreams
--) {
1528 if (ppOptions
[nStreams
] != NULL
) {
1529 ppOptions
[nStreams
]->dwFlags
&= ~AVICOMPRESSF_VALID
;
1531 if (ppOptions
[nStreams
]->lpParms
!= NULL
) {
1532 HeapFree(GetProcessHeap(), 0, ppOptions
[nStreams
]->lpParms
);
1533 ppOptions
[nStreams
]->lpParms
= NULL
;
1534 ppOptions
[nStreams
]->cbParms
= 0;
1536 if (ppOptions
[nStreams
]->lpFormat
!= NULL
) {
1537 HeapFree(GetProcessHeap(), 0, ppOptions
[nStreams
]->lpFormat
);
1538 ppOptions
[nStreams
]->lpFormat
= NULL
;
1539 ppOptions
[nStreams
]->cbFormat
= 0;
1547 /***********************************************************************
1548 * AVISaveVA (AVIFIL32.@)
1550 HRESULT WINAPI
AVISaveVA(LPCSTR szFile
, CLSID
*pclsidHandler
,
1551 AVISAVECALLBACK lpfnCallback
, int nStream
,
1552 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*plpOptions
)
1554 LPWSTR wszFile
= NULL
;
1558 TRACE("%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile
), pclsidHandler
,
1559 lpfnCallback
, nStream
, ppavi
, plpOptions
);
1561 if (szFile
== NULL
|| ppavi
== NULL
|| plpOptions
== NULL
)
1562 return AVIERR_BADPARAM
;
1564 /* convert ASCII string to Unicode and call Unicode function */
1565 len
= MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, NULL
, 0);
1567 return AVIERR_BADPARAM
;
1569 wszFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1570 if (wszFile
== NULL
)
1571 return AVIERR_MEMORY
;
1573 MultiByteToWideChar(CP_ACP
, 0, szFile
, -1, wszFile
, len
);
1575 hr
= AVISaveVW(wszFile
, pclsidHandler
, lpfnCallback
,
1576 nStream
, ppavi
, plpOptions
);
1578 HeapFree(GetProcessHeap(), 0, wszFile
);
1583 /***********************************************************************
1584 * AVIFILE_AVISaveDefaultCallback (internal)
1586 static BOOL WINAPI
AVIFILE_AVISaveDefaultCallback(INT progress
)
1588 TRACE("(%d)\n", progress
);
1593 /***********************************************************************
1594 * AVISaveVW (AVIFIL32.@)
1596 HRESULT WINAPI
AVISaveVW(LPCWSTR szFile
, CLSID
*pclsidHandler
,
1597 AVISAVECALLBACK lpfnCallback
, int nStreams
,
1598 PAVISTREAM
*ppavi
, LPAVICOMPRESSOPTIONS
*plpOptions
)
1600 LONG lStart
[MAX_AVISTREAMS
];
1601 PAVISTREAM pOutStreams
[MAX_AVISTREAMS
];
1602 PAVISTREAM pInStreams
[MAX_AVISTREAMS
];
1604 AVISTREAMINFOW sInfo
;
1606 PAVIFILE pfile
= NULL
; /* the output AVI file */
1607 LONG lFirstVideo
= -1;
1610 /* for interleaving ... */
1611 DWORD dwInterleave
= 0; /* interleave rate */
1612 DWORD dwFileInitialFrames
;
1616 /* for reading/writing the data ... */
1617 LPVOID lpBuffer
= NULL
;
1618 LONG cbBuffer
; /* real size of lpBuffer */
1619 LONG lBufferSize
; /* needed bytes for format(s), etc. */
1624 TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile
), pclsidHandler
,
1625 lpfnCallback
, nStreams
, ppavi
, plpOptions
);
1627 if (szFile
== NULL
|| ppavi
== NULL
|| plpOptions
== NULL
)
1628 return AVIERR_BADPARAM
;
1629 if (nStreams
>= MAX_AVISTREAMS
) {
1630 WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams
, MAX_AVISTREAMS
);
1631 return AVIERR_INTERNAL
;
1634 if (lpfnCallback
== NULL
)
1635 lpfnCallback
= AVIFILE_AVISaveDefaultCallback
;
1637 /* clear local variable(s) */
1638 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1639 pInStreams
[curStream
] = NULL
;
1640 pOutStreams
[curStream
] = NULL
;
1643 /* open output AVI file (create it if it doesn't exist) */
1644 hres
= AVIFileOpenW(&pfile
, szFile
, OF_CREATE
|OF_SHARE_EXCLUSIVE
|OF_WRITE
,
1648 AVIFileInfoW(pfile
, &fInfo
, sizeof(fInfo
)); /* for dwCaps */
1650 /* initialize our data structures part 1 */
1651 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1652 PAVISTREAM pCurStream
= ppavi
[curStream
];
1654 hres
= AVIStreamInfoW(pCurStream
, &sInfo
, sizeof(sInfo
));
1658 /* search first video stream and check for interleaving */
1659 if (sInfo
.fccType
== streamtypeVIDEO
) {
1660 /* remember first video stream -- needed for interleaving */
1661 if (lFirstVideo
< 0)
1662 lFirstVideo
= curStream
;
1663 } else if (!dwInterleave
&& plpOptions
!= NULL
) {
1664 /* check if any non-video stream wants to be interleaved */
1665 WARN("options.flags=0x%X options.dwInterleave=%u\n",plpOptions
[curStream
]->dwFlags
,plpOptions
[curStream
]->dwInterleaveEvery
);
1666 if (plpOptions
[curStream
] != NULL
&&
1667 plpOptions
[curStream
]->dwFlags
& AVICOMPRESSF_INTERLEAVE
)
1668 dwInterleave
= plpOptions
[curStream
]->dwInterleaveEvery
;
1671 /* create de-/compressed stream interface if needed */
1672 pInStreams
[curStream
] = NULL
;
1673 if (plpOptions
!= NULL
&& plpOptions
[curStream
] != NULL
) {
1674 if (plpOptions
[curStream
]->fccHandler
||
1675 plpOptions
[curStream
]->lpFormat
!= NULL
) {
1676 DWORD dwKeySave
= plpOptions
[curStream
]->dwKeyFrameEvery
;
1678 if (fInfo
.dwCaps
& AVIFILECAPS_ALLKEYFRAMES
)
1679 plpOptions
[curStream
]->dwKeyFrameEvery
= 1;
1681 hres
= AVIMakeCompressedStream(&pInStreams
[curStream
], pCurStream
,
1682 plpOptions
[curStream
], NULL
);
1683 plpOptions
[curStream
]->dwKeyFrameEvery
= dwKeySave
;
1684 if (FAILED(hres
) || pInStreams
[curStream
] == NULL
) {
1685 pInStreams
[curStream
] = NULL
;
1689 /* test stream interface and update stream-info */
1690 hres
= AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1696 /* now handle streams which will only be copied */
1697 if (pInStreams
[curStream
] == NULL
) {
1698 pCurStream
= pInStreams
[curStream
] = ppavi
[curStream
];
1699 AVIStreamAddRef(pCurStream
);
1701 pCurStream
= pInStreams
[curStream
];
1703 lStart
[curStream
] = sInfo
.dwStart
;
1704 } /* for all streams */
1706 /* check that first video stream is the first stream */
1707 if (lFirstVideo
> 0) {
1708 PAVISTREAM pTmp
= pInStreams
[lFirstVideo
];
1709 LONG lTmp
= lStart
[lFirstVideo
];
1711 pInStreams
[lFirstVideo
] = pInStreams
[0];
1712 pInStreams
[0] = pTmp
;
1713 lStart
[lFirstVideo
] = lStart
[0];
1718 /* allocate buffer for formats, data, etc. of an initial size of 64 kBytes*/
1719 cbBuffer
= 0x00010000;
1720 lpBuffer
= HeapAlloc(GetProcessHeap(), 0, cbBuffer
);
1721 if (lpBuffer
== NULL
) {
1722 hres
= AVIERR_MEMORY
;
1726 AVIStreamInfoW(pInStreams
[0], &sInfo
, sizeof(sInfo
));
1727 lFileLength
= sInfo
.dwLength
;
1728 dwFileInitialFrames
= 0;
1729 if (lFirstVideo
>= 0) {
1730 /* check for correct version of the format
1731 * -- need at least BITMAPINFOHEADER or newer
1734 lBufferSize
= cbBuffer
;
1735 hres
= AVIStreamReadFormat(pInStreams
[lFirstVideo
], AVIStreamStart(pInStreams
[lFirstVideo
]), lpBuffer
, &lBufferSize
);
1736 if (lBufferSize
< (LONG
)sizeof(BITMAPINFOHEADER
))
1737 hres
= AVIERR_INTERNAL
;
1740 } else /* use one second blocks for interleaving if no video present */
1741 lSampleInc
= AVIStreamTimeToSample(pInStreams
[0], 1000000);
1743 /* create output streams */
1744 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1745 AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1747 sInfo
.dwInitialFrames
= 0;
1748 if (dwInterleave
!= 0 && curStream
> 0 && sInfo
.fccType
!= streamtypeVIDEO
) {
1749 /* 750 ms initial frames for non-video streams */
1750 sInfo
.dwInitialFrames
= AVIStreamTimeToSample(pInStreams
[0], 750);
1753 hres
= AVIFileCreateStreamW(pfile
, &pOutStreams
[curStream
], &sInfo
);
1754 if (pOutStreams
[curStream
] != NULL
&& SUCCEEDED(hres
)) {
1755 /* copy initial format for this stream */
1756 lBufferSize
= cbBuffer
;
1757 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1758 lpBuffer
, &lBufferSize
);
1761 hres
= AVIStreamSetFormat(pOutStreams
[curStream
], 0, lpBuffer
, lBufferSize
);
1765 /* try to copy stream handler data */
1766 lBufferSize
= cbBuffer
;
1767 hres
= AVIStreamReadData(pInStreams
[curStream
], ckidSTREAMHANDLERDATA
,
1768 lpBuffer
, &lBufferSize
);
1769 if (SUCCEEDED(hres
) && lBufferSize
> 0) {
1770 hres
= AVIStreamWriteData(pOutStreams
[curStream
],ckidSTREAMHANDLERDATA
,
1771 lpBuffer
, lBufferSize
);
1776 if (dwFileInitialFrames
< sInfo
.dwInitialFrames
)
1777 dwFileInitialFrames
= sInfo
.dwInitialFrames
;
1779 AVIStreamSampleToSample(pOutStreams
[0], pInStreams
[curStream
],
1781 if (lFileLength
< lReadBytes
)
1782 lFileLength
= lReadBytes
;
1784 /* creation of de-/compression stream interface failed */
1785 WARN("creation of (de-)compression stream failed for stream %d\n",curStream
);
1786 AVIStreamRelease(pInStreams
[curStream
]);
1787 if (curStream
+ 1 >= nStreams
) {
1788 /* move the others one up */
1789 PAVISTREAM
*ppas
= &pInStreams
[curStream
];
1790 int n
= nStreams
- (curStream
+ 1);
1793 *ppas
= pInStreams
[curStream
+ 1];
1799 } /* create output streams for all input streams */
1801 /* have we still something to write, or lost everything? */
1806 LONG lCurFrame
= -dwFileInitialFrames
;
1808 /* interleaved file */
1809 if (dwInterleave
== 1)
1810 AVIFileEndRecord(pfile
);
1812 for (; lCurFrame
< lFileLength
; lCurFrame
+= lSampleInc
) {
1813 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1816 hres
= AVIStreamInfoW(pOutStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1820 /* initial frames phase at the end for this stream? */
1821 if (-(LONG
)sInfo
.dwInitialFrames
> lCurFrame
)
1824 if ((lFileLength
- lSampleInc
) <= lCurFrame
) {
1825 lLastSample
= AVIStreamLength(pInStreams
[curStream
]);
1826 lFirstVideo
= lLastSample
+ AVIStreamStart(pInStreams
[curStream
]);
1828 if (curStream
!= 0) {
1830 AVIStreamSampleToSample(pInStreams
[curStream
], pInStreams
[0],
1831 (sInfo
.fccType
== streamtypeVIDEO
?
1832 (LONG
)dwInterleave
: lSampleInc
) +
1833 sInfo
.dwInitialFrames
+ lCurFrame
);
1835 lFirstVideo
= lSampleInc
+ (sInfo
.dwInitialFrames
+ lCurFrame
);
1837 lLastSample
= AVIStreamEnd(pInStreams
[curStream
]);
1838 if (lLastSample
<= lFirstVideo
)
1839 lFirstVideo
= lLastSample
;
1842 /* copy needed samples now */
1843 WARN("copy from stream %d samples %d to %d...\n",curStream
,
1844 lStart
[curStream
],lFirstVideo
);
1845 while (lFirstVideo
> lStart
[curStream
]) {
1848 /* copy format in case it can change */
1849 lBufferSize
= cbBuffer
;
1850 hres
= AVIStreamReadFormat(pInStreams
[curStream
], lStart
[curStream
],
1851 lpBuffer
, &lBufferSize
);
1854 AVIStreamSetFormat(pOutStreams
[curStream
], lStart
[curStream
],
1855 lpBuffer
, lBufferSize
);
1857 /* try to read data until we got it, or error */
1859 hres
= AVIStreamRead(pInStreams
[curStream
], lStart
[curStream
],
1860 lFirstVideo
- lStart
[curStream
], lpBuffer
,
1861 cbBuffer
, &lReadBytes
, &lReadSamples
);
1862 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1863 (lpBuffer
= HeapReAlloc(GetProcessHeap(), 0, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1864 if (lpBuffer
== NULL
)
1865 hres
= AVIERR_MEMORY
;
1869 if (AVIStreamIsKeyFrame(pInStreams
[curStream
], (LONG
)sInfo
.dwStart
))
1870 flags
= AVIIF_KEYFRAME
;
1871 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1872 lpBuffer
, lReadBytes
, flags
, NULL
, NULL
);
1876 lStart
[curStream
] += lReadSamples
;
1878 lStart
[curStream
] = lFirstVideo
;
1879 } /* stream by stream */
1881 /* need to close this block? */
1882 if (dwInterleave
== 1) {
1883 hres
= AVIFileEndRecord(pfile
);
1889 if (lpfnCallback(MulDiv(dwFileInitialFrames
+ lCurFrame
, 100,
1890 dwFileInitialFrames
+ lFileLength
))) {
1891 hres
= AVIERR_USERABORT
;
1894 } /* copy frame by frame */
1896 /* non-interleaved file */
1898 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
1900 if (lpfnCallback(MulDiv(curStream
, 100, nStreams
))) {
1901 hres
= AVIERR_USERABORT
;
1905 AVIStreamInfoW(pInStreams
[curStream
], &sInfo
, sizeof(sInfo
));
1907 if (sInfo
.dwSampleSize
!= 0) {
1908 /* sample-based data like audio */
1909 while (sInfo
.dwStart
< sInfo
.dwLength
) {
1910 LONG lSamples
= cbBuffer
/ sInfo
.dwSampleSize
;
1912 /* copy format in case it can change */
1913 lBufferSize
= cbBuffer
;
1914 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1915 lpBuffer
, &lBufferSize
);
1918 AVIStreamSetFormat(pOutStreams
[curStream
], sInfo
.dwStart
,
1919 lpBuffer
, lBufferSize
);
1921 /* limit to stream boundaries */
1922 if (lSamples
!= (LONG
)(sInfo
.dwLength
- sInfo
.dwStart
))
1923 lSamples
= sInfo
.dwLength
- sInfo
.dwStart
;
1925 /* now try to read until we get it, or an error occurs */
1927 lReadBytes
= cbBuffer
;
1929 hres
= AVIStreamRead(pInStreams
[curStream
],sInfo
.dwStart
,lSamples
,
1930 lpBuffer
,cbBuffer
,&lReadBytes
,&lReadSamples
);
1931 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1932 (lpBuffer
= HeapReAlloc(GetProcessHeap(), 0, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1933 if (lpBuffer
== NULL
)
1934 hres
= AVIERR_MEMORY
;
1937 if (lReadSamples
!= 0) {
1938 sInfo
.dwStart
+= lReadSamples
;
1939 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1940 lpBuffer
, lReadBytes
, 0, NULL
, NULL
);
1945 if (lpfnCallback(MulDiv(sInfo
.dwStart
,100,nStreams
*sInfo
.dwLength
)+
1946 MulDiv(curStream
, 100, nStreams
))) {
1947 hres
= AVIERR_USERABORT
;
1951 if ((sInfo
.dwLength
- sInfo
.dwStart
) != 1) {
1952 hres
= AVIERR_FILEREAD
;
1958 /* block-based data like video */
1959 for (; sInfo
.dwStart
< sInfo
.dwLength
; sInfo
.dwStart
++) {
1962 /* copy format in case it can change */
1963 lBufferSize
= cbBuffer
;
1964 hres
= AVIStreamReadFormat(pInStreams
[curStream
], sInfo
.dwStart
,
1965 lpBuffer
, &lBufferSize
);
1968 AVIStreamSetFormat(pOutStreams
[curStream
], sInfo
.dwStart
,
1969 lpBuffer
, lBufferSize
);
1971 /* try to read block and resize buffer if necessary */
1974 lReadBytes
= cbBuffer
;
1975 hres
= AVIStreamRead(pInStreams
[curStream
], sInfo
.dwStart
, 1,
1976 lpBuffer
, cbBuffer
,&lReadBytes
,&lReadSamples
);
1977 } while ((hres
== AVIERR_BUFFERTOOSMALL
) &&
1978 (lpBuffer
= HeapReAlloc(GetProcessHeap(), 0, lpBuffer
, cbBuffer
*= 2)) != NULL
);
1979 if (lpBuffer
== NULL
)
1980 hres
= AVIERR_MEMORY
;
1983 if (lReadSamples
!= 1) {
1984 hres
= AVIERR_FILEREAD
;
1988 if (AVIStreamIsKeyFrame(pInStreams
[curStream
], (LONG
)sInfo
.dwStart
))
1989 flags
= AVIIF_KEYFRAME
;
1990 hres
= AVIStreamWrite(pOutStreams
[curStream
], -1, lReadSamples
,
1991 lpBuffer
, lReadBytes
, flags
, NULL
, NULL
);
1996 if (lpfnCallback(MulDiv(sInfo
.dwStart
,100,nStreams
*sInfo
.dwLength
)+
1997 MulDiv(curStream
, 100, nStreams
))) {
1998 hres
= AVIERR_USERABORT
;
2001 } /* copy all blocks */
2003 } /* copy data stream by stream */
2007 HeapFree(GetProcessHeap(), 0, lpBuffer
);
2008 if (pfile
!= NULL
) {
2009 for (curStream
= 0; curStream
< nStreams
; curStream
++) {
2010 if (pOutStreams
[curStream
] != NULL
)
2011 AVIStreamRelease(pOutStreams
[curStream
]);
2012 if (pInStreams
[curStream
] != NULL
)
2013 AVIStreamRelease(pInStreams
[curStream
]);
2016 AVIFileRelease(pfile
);
2022 /***********************************************************************
2023 * CreateEditableStream (AVIFIL32.@)
2025 HRESULT WINAPI
CreateEditableStream(PAVISTREAM
*ppEditable
, PAVISTREAM pSource
)
2027 IAVIEditStream
*pEdit
= NULL
;
2030 TRACE("(%p,%p)\n", ppEditable
, pSource
);
2032 if (ppEditable
== NULL
)
2033 return AVIERR_BADPARAM
;
2037 if (pSource
!= NULL
) {
2038 hr
= IAVIStream_QueryInterface(pSource
, &IID_IAVIEditStream
,
2040 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2041 hr
= IAVIEditStream_Clone(pEdit
, ppEditable
);
2042 IAVIEditStream_Release(pEdit
);
2048 /* need own implementation of IAVIEditStream */
2049 pEdit
= AVIFILE_CreateEditStream(pSource
);
2051 return AVIERR_MEMORY
;
2053 hr
= IAVIEditStream_QueryInterface(pEdit
, &IID_IAVIStream
,
2054 (LPVOID
*)ppEditable
);
2055 IAVIEditStream_Release(pEdit
);
2060 /***********************************************************************
2061 * EditStreamClone (AVIFIL32.@)
2063 HRESULT WINAPI
EditStreamClone(PAVISTREAM pStream
, PAVISTREAM
*ppResult
)
2065 PAVIEDITSTREAM pEdit
= NULL
;
2068 TRACE("(%p,%p)\n", pStream
, ppResult
);
2070 if (pStream
== NULL
)
2071 return AVIERR_BADHANDLE
;
2072 if (ppResult
== NULL
)
2073 return AVIERR_BADPARAM
;
2077 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2078 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2079 hr
= IAVIEditStream_Clone(pEdit
, ppResult
);
2081 IAVIEditStream_Release(pEdit
);
2083 hr
= AVIERR_UNSUPPORTED
;
2088 /***********************************************************************
2089 * EditStreamCopy (AVIFIL32.@)
2091 HRESULT WINAPI
EditStreamCopy(PAVISTREAM pStream
, LONG
*plStart
,
2092 LONG
*plLength
, PAVISTREAM
*ppResult
)
2094 PAVIEDITSTREAM pEdit
= NULL
;
2097 TRACE("(%p,%p,%p,%p)\n", pStream
, plStart
, plLength
, ppResult
);
2099 if (pStream
== NULL
)
2100 return AVIERR_BADHANDLE
;
2101 if (plStart
== NULL
|| plLength
== NULL
|| ppResult
== NULL
)
2102 return AVIERR_BADPARAM
;
2106 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2107 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2108 hr
= IAVIEditStream_Copy(pEdit
, plStart
, plLength
, ppResult
);
2110 IAVIEditStream_Release(pEdit
);
2112 hr
= AVIERR_UNSUPPORTED
;
2117 /***********************************************************************
2118 * EditStreamCut (AVIFIL32.@)
2120 HRESULT WINAPI
EditStreamCut(PAVISTREAM pStream
, LONG
*plStart
,
2121 LONG
*plLength
, PAVISTREAM
*ppResult
)
2123 PAVIEDITSTREAM pEdit
= NULL
;
2126 TRACE("(%p,%p,%p,%p)\n", pStream
, plStart
, plLength
, ppResult
);
2128 if (ppResult
!= NULL
)
2130 if (pStream
== NULL
)
2131 return AVIERR_BADHANDLE
;
2132 if (plStart
== NULL
|| plLength
== NULL
)
2133 return AVIERR_BADPARAM
;
2135 hr
= IAVIStream_QueryInterface(pStream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2136 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2137 hr
= IAVIEditStream_Cut(pEdit
, plStart
, plLength
, ppResult
);
2139 IAVIEditStream_Release(pEdit
);
2141 hr
= AVIERR_UNSUPPORTED
;
2146 /***********************************************************************
2147 * EditStreamPaste (AVIFIL32.@)
2149 HRESULT WINAPI
EditStreamPaste(PAVISTREAM pDest
, LONG
*plStart
, LONG
*plLength
,
2150 PAVISTREAM pSource
, LONG lStart
, LONG lEnd
)
2152 PAVIEDITSTREAM pEdit
= NULL
;
2155 TRACE("(%p,%p,%p,%p,%d,%d)\n", pDest
, plStart
, plLength
,
2156 pSource
, lStart
, lEnd
);
2158 if (pDest
== NULL
|| pSource
== NULL
)
2159 return AVIERR_BADHANDLE
;
2160 if (plStart
== NULL
|| plLength
== NULL
|| lStart
< 0)
2161 return AVIERR_BADPARAM
;
2163 hr
= IAVIStream_QueryInterface(pDest
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2164 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2165 hr
= IAVIEditStream_Paste(pEdit
, plStart
, plLength
, pSource
, lStart
, lEnd
);
2167 IAVIEditStream_Release(pEdit
);
2169 hr
= AVIERR_UNSUPPORTED
;
2174 /***********************************************************************
2175 * EditStreamSetInfoA (AVIFIL32.@)
2177 HRESULT WINAPI
EditStreamSetInfoA(PAVISTREAM pstream
, LPAVISTREAMINFOA asi
,
2180 AVISTREAMINFOW asiw
;
2182 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
2184 if (pstream
== NULL
)
2185 return AVIERR_BADHANDLE
;
2186 if ((DWORD
)size
< sizeof(AVISTREAMINFOA
))
2187 return AVIERR_BADSIZE
;
2189 memcpy(&asiw
, asi
, sizeof(asiw
) - sizeof(asiw
.szName
));
2190 MultiByteToWideChar(CP_ACP
, 0, asi
->szName
, -1,
2191 asiw
.szName
, sizeof(asiw
.szName
)/sizeof(WCHAR
));
2193 return EditStreamSetInfoW(pstream
, &asiw
, sizeof(asiw
));
2196 /***********************************************************************
2197 * EditStreamSetInfoW (AVIFIL32.@)
2199 HRESULT WINAPI
EditStreamSetInfoW(PAVISTREAM pstream
, LPAVISTREAMINFOW asi
,
2202 PAVIEDITSTREAM pEdit
= NULL
;
2205 TRACE("(%p,%p,%d)\n", pstream
, asi
, size
);
2207 hr
= IAVIStream_QueryInterface(pstream
, &IID_IAVIEditStream
,(LPVOID
*)&pEdit
);
2208 if (SUCCEEDED(hr
) && pEdit
!= NULL
) {
2209 hr
= IAVIEditStream_SetInfo(pEdit
, asi
, size
);
2211 IAVIEditStream_Release(pEdit
);
2213 hr
= AVIERR_UNSUPPORTED
;
2218 /***********************************************************************
2219 * EditStreamSetNameA (AVIFIL32.@)
2221 HRESULT WINAPI
EditStreamSetNameA(PAVISTREAM pstream
, LPCSTR szName
)
2223 AVISTREAMINFOA asia
;
2226 TRACE("(%p,%s)\n", pstream
, debugstr_a(szName
));
2228 if (pstream
== NULL
)
2229 return AVIERR_BADHANDLE
;
2231 return AVIERR_BADPARAM
;
2233 hres
= AVIStreamInfoA(pstream
, &asia
, sizeof(asia
));
2237 memset(asia
.szName
, 0, sizeof(asia
.szName
));
2238 lstrcpynA(asia
.szName
, szName
, sizeof(asia
.szName
)/sizeof(asia
.szName
[0]));
2240 return EditStreamSetInfoA(pstream
, &asia
, sizeof(asia
));
2243 /***********************************************************************
2244 * EditStreamSetNameW (AVIFIL32.@)
2246 HRESULT WINAPI
EditStreamSetNameW(PAVISTREAM pstream
, LPCWSTR szName
)
2248 AVISTREAMINFOW asiw
;
2251 TRACE("(%p,%s)\n", pstream
, debugstr_w(szName
));
2253 if (pstream
== NULL
)
2254 return AVIERR_BADHANDLE
;
2256 return AVIERR_BADPARAM
;
2258 hres
= IAVIStream_Info(pstream
, &asiw
, sizeof(asiw
));
2262 memset(asiw
.szName
, 0, sizeof(asiw
.szName
));
2263 lstrcpynW(asiw
.szName
, szName
, sizeof(asiw
.szName
)/sizeof(asiw
.szName
[0]));
2265 return EditStreamSetInfoW(pstream
, &asiw
, sizeof(asiw
));
2268 /***********************************************************************
2269 * AVIClearClipboard (AVIFIL32.@)
2271 HRESULT WINAPI
AVIClearClipboard(void)
2275 return AVIERR_UNSUPPORTED
; /* OleSetClipboard(NULL); */
2278 /***********************************************************************
2279 * AVIGetFromClipboard (AVIFIL32.@)
2281 HRESULT WINAPI
AVIGetFromClipboard(PAVIFILE
*ppfile
)
2283 FIXME("(%p), stub!\n", ppfile
);
2287 return AVIERR_UNSUPPORTED
;
2290 /***********************************************************************
2291 * AVIMakeStreamFromClipboard (AVIFIL32.@)
2293 HRESULT WINAPI
AVIMakeStreamFromClipboard(UINT cfFormat
, HANDLE hGlobal
,
2294 PAVISTREAM
* ppstream
)
2296 FIXME("(0x%08x,%p,%p), stub!\n", cfFormat
, hGlobal
, ppstream
);
2298 if (ppstream
== NULL
)
2299 return AVIERR_BADHANDLE
;
2301 return AVIERR_UNSUPPORTED
;
2304 /***********************************************************************
2305 * AVIPutFileOnClipboard (AVIFIL32.@)
2307 HRESULT WINAPI
AVIPutFileOnClipboard(PAVIFILE pfile
)
2309 FIXME("(%p), stub!\n", pfile
);
2312 return AVIERR_BADHANDLE
;
2314 return AVIERR_UNSUPPORTED
;
2317 HRESULT WINAPIV
AVISaveA(LPCSTR szFile
, CLSID
* pclsidHandler
, AVISAVECALLBACK lpfnCallback
,
2318 int nStreams
, PAVISTREAM pavi
, LPAVICOMPRESSOPTIONS lpOptions
, ...)
2320 FIXME("(%s,%p,%p,0x%08x,%p,%p), stub!\n", debugstr_a(szFile
), pclsidHandler
, lpfnCallback
,
2321 nStreams
, pavi
, lpOptions
);
2323 return AVIERR_UNSUPPORTED
;
2326 HRESULT WINAPIV
AVISaveW(LPCWSTR szFile
, CLSID
* pclsidHandler
, AVISAVECALLBACK lpfnCallback
,
2327 int nStreams
, PAVISTREAM pavi
, LPAVICOMPRESSOPTIONS lpOptions
, ...)
2329 FIXME("(%s,%p,%p,0x%08x,%p,%p), stub!\n", debugstr_w(szFile
), pclsidHandler
, lpfnCallback
,
2330 nStreams
, pavi
, lpOptions
);
2332 return AVIERR_UNSUPPORTED
;