Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/avifil32/api.c
4394 views
1
/*
2
* Copyright 1999 Marcus Meissner
3
* Copyright 2002-2003 Michael Günnewig
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18
*/
19
20
#include <stdarg.h>
21
22
#define COBJMACROS
23
24
#include "windef.h"
25
#include "winbase.h"
26
#include "winnls.h"
27
#include "wingdi.h"
28
#include "winuser.h"
29
#include "winreg.h"
30
#include "winerror.h"
31
32
#include "ole2.h"
33
#include "shellapi.h"
34
#include "shlobj.h"
35
#include "vfw.h"
36
#include "msacm.h"
37
38
#include "avifile_private.h"
39
40
#include "wine/debug.h"
41
42
WINE_DEFAULT_DEBUG_CHANNEL(avifile);
43
44
45
/***********************************************************************
46
* for AVIBuildFilterW -- uses fixed size table
47
*/
48
#define MAX_FILTERS 30 /* 30 => 7kB */
49
50
typedef struct _AVIFilter {
51
WCHAR szClsid[40];
52
WCHAR szExtensions[MAX_FILTERS * 7];
53
} AVIFilter;
54
55
/***********************************************************************
56
* for AVISaveOptions
57
*/
58
static struct {
59
UINT uFlags;
60
INT nStreams;
61
PAVISTREAM *ppavis;
62
LPAVICOMPRESSOPTIONS *ppOptions;
63
INT nCurrent;
64
} SaveOpts;
65
66
/***********************************************************************
67
* copied from dlls/ole32/compobj.c
68
*/
69
static HRESULT AVIFILE_CLSIDFromString(LPCSTR idstr, LPCLSID id)
70
{
71
BYTE const *s;
72
BYTE *p;
73
INT i;
74
BYTE table[256];
75
76
if (!idstr) {
77
memset(id, 0, sizeof(CLSID));
78
return S_OK;
79
}
80
81
/* validate the CLSID string */
82
if (lstrlenA(idstr) != 38)
83
return CO_E_CLASSSTRING;
84
85
s = (BYTE const*)idstr;
86
if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') ||
87
(s[24]!='-') || (s[37]!='}'))
88
return CO_E_CLASSSTRING;
89
90
for (i = 1; i < 37; i++) {
91
if ((i == 9) || (i == 14) || (i == 19) || (i == 24))
92
continue;
93
if (!(((s[i] >= '0') && (s[i] <= '9')) ||
94
((s[i] >= 'a') && (s[i] <= 'f')) ||
95
((s[i] >= 'A') && (s[i] <= 'F')))
96
)
97
return CO_E_CLASSSTRING;
98
}
99
100
TRACE("%s -> %p\n", s, id);
101
102
/* quick lookup table */
103
memset(table, 0, 256);
104
105
for (i = 0; i < 10; i++)
106
table['0' + i] = i;
107
108
for (i = 0; i < 6; i++) {
109
table['A' + i] = i+10;
110
table['a' + i] = i+10;
111
}
112
113
/* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
114
p = (BYTE *) id;
115
116
s++; /* skip leading brace */
117
for (i = 0; i < 4; i++) {
118
p[3 - i] = table[*s]<<4 | table[*(s+1)];
119
s += 2;
120
}
121
p += 4;
122
s++; /* skip - */
123
124
for (i = 0; i < 2; i++) {
125
p[1-i] = table[*s]<<4 | table[*(s+1)];
126
s += 2;
127
}
128
p += 2;
129
s++; /* skip - */
130
131
for (i = 0; i < 2; i++) {
132
p[1-i] = table[*s]<<4 | table[*(s+1)];
133
s += 2;
134
}
135
p += 2;
136
s++; /* skip - */
137
138
/* these are just sequential bytes */
139
for (i = 0; i < 2; i++) {
140
*p++ = table[*s]<<4 | table[*(s+1)];
141
s += 2;
142
}
143
s++; /* skip - */
144
145
for (i = 0; i < 6; i++) {
146
*p++ = table[*s]<<4 | table[*(s+1)];
147
s += 2;
148
}
149
150
return S_OK;
151
}
152
153
static BOOL AVIFILE_GetFileHandlerByExtension(LPCWSTR szFile, LPCLSID lpclsid)
154
{
155
CHAR szRegKey[25];
156
CHAR szValue[100];
157
LPWSTR szExt = wcsrchr(szFile, '.');
158
LONG len = ARRAY_SIZE(szValue);
159
160
if (szExt == NULL)
161
return FALSE;
162
163
szExt++;
164
165
wsprintfA(szRegKey, "AVIFile\\Extensions\\%.3ls", szExt);
166
if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &len) != ERROR_SUCCESS)
167
return FALSE;
168
169
return (AVIFILE_CLSIDFromString(szValue, lpclsid) == S_OK);
170
}
171
172
/***********************************************************************
173
* AVIFileInit (AVIFIL32.@)
174
*/
175
void WINAPI AVIFileInit(void) {
176
OleInitialize(NULL);
177
}
178
179
/***********************************************************************
180
* AVIFileExit (AVIFIL32.@)
181
*/
182
void WINAPI AVIFileExit(void) {
183
/* need to free ole32.dll if we are the last exit call */
184
/* OleUninitialize() */
185
FIXME("(): stub!\n");
186
}
187
188
/***********************************************************************
189
* AVIFileOpen (AVIFIL32.@)
190
* AVIFileOpenA (AVIFIL32.@)
191
*/
192
HRESULT WINAPI AVIFileOpenA(PAVIFILE *ppfile, LPCSTR szFile, UINT uMode,
193
LPCLSID lpHandler)
194
{
195
LPWSTR wszFile = NULL;
196
HRESULT hr;
197
int len;
198
199
TRACE("(%p,%s,0x%08X,%s)\n", ppfile, debugstr_a(szFile), uMode,
200
debugstr_guid(lpHandler));
201
202
/* check parameters */
203
if (ppfile == NULL || szFile == NULL)
204
return AVIERR_BADPARAM;
205
206
/* convert the ANSI string to Unicode and call the Unicode function */
207
len = MultiByteToWideChar(CP_ACP, 0, szFile, -1, NULL, 0);
208
if (len <= 0)
209
return AVIERR_BADPARAM;
210
211
wszFile = malloc(len * sizeof(WCHAR));
212
if (wszFile == NULL)
213
return AVIERR_MEMORY;
214
215
MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len);
216
217
hr = AVIFileOpenW(ppfile, wszFile, uMode, lpHandler);
218
219
free(wszFile);
220
221
return hr;
222
}
223
224
/***********************************************************************
225
* AVIFileOpenW (AVIFIL32.@)
226
*/
227
HRESULT WINAPI AVIFileOpenW(PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode,
228
LPCLSID lpHandler)
229
{
230
IPersistFile *ppersist = NULL;
231
CLSID clsidHandler;
232
HRESULT hr;
233
234
TRACE("(%p,%s,0x%X,%s)\n", ppfile, debugstr_w(szFile), uMode,
235
debugstr_guid(lpHandler));
236
237
/* check parameters */
238
if (ppfile == NULL || szFile == NULL)
239
return AVIERR_BADPARAM;
240
241
*ppfile = NULL;
242
243
/* if no handler then try guessing it by extension */
244
if (lpHandler == NULL) {
245
if (! AVIFILE_GetFileHandlerByExtension(szFile, &clsidHandler))
246
clsidHandler = CLSID_AVIFile;
247
} else
248
clsidHandler = *lpHandler;
249
250
/* create instance of handler */
251
hr = CoCreateInstance(&clsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIFile, (LPVOID*)ppfile);
252
if (FAILED(hr) || *ppfile == NULL)
253
return hr;
254
255
/* ask for IPersistFile interface for loading/creating the file */
256
hr = IAVIFile_QueryInterface(*ppfile, &IID_IPersistFile, (LPVOID*)&ppersist);
257
if (FAILED(hr) || ppersist == NULL) {
258
IAVIFile_Release(*ppfile);
259
*ppfile = NULL;
260
return hr;
261
}
262
263
if (uMode & OF_CREATE)
264
uMode |= OF_WRITE;
265
266
hr = IPersistFile_Load(ppersist, szFile, uMode);
267
IPersistFile_Release(ppersist);
268
if (FAILED(hr)) {
269
IAVIFile_Release(*ppfile);
270
*ppfile = NULL;
271
}
272
273
return hr;
274
}
275
276
/***********************************************************************
277
* AVIFileAddRef (AVIFIL32.@)
278
*/
279
ULONG WINAPI AVIFileAddRef(PAVIFILE pfile)
280
{
281
TRACE("(%p)\n", pfile);
282
283
if (pfile == NULL) {
284
ERR(": bad handle passed!\n");
285
return 0;
286
}
287
288
return IAVIFile_AddRef(pfile);
289
}
290
291
/***********************************************************************
292
* AVIFileRelease (AVIFIL32.@)
293
*/
294
ULONG WINAPI AVIFileRelease(PAVIFILE pfile)
295
{
296
TRACE("(%p)\n", pfile);
297
298
if (pfile == NULL) {
299
ERR(": bad handle passed!\n");
300
return 0;
301
}
302
303
return IAVIFile_Release(pfile);
304
}
305
306
/***********************************************************************
307
* AVIFileInfo (AVIFIL32.@)
308
* AVIFileInfoA (AVIFIL32.@)
309
*/
310
HRESULT WINAPI AVIFileInfoA(PAVIFILE pfile, LPAVIFILEINFOA afi, LONG size)
311
{
312
AVIFILEINFOW afiw;
313
HRESULT hres;
314
315
TRACE("(%p,%p,%ld)\n", pfile, afi, size);
316
317
if (pfile == NULL)
318
return AVIERR_BADHANDLE;
319
if ((DWORD)size < sizeof(AVIFILEINFOA))
320
return AVIERR_BADSIZE;
321
322
hres = IAVIFile_Info(pfile, &afiw, sizeof(afiw));
323
324
memcpy(afi, &afiw, sizeof(*afi) - sizeof(afi->szFileType));
325
WideCharToMultiByte(CP_ACP, 0, afiw.szFileType, -1, afi->szFileType,
326
sizeof(afi->szFileType), NULL, NULL);
327
afi->szFileType[sizeof(afi->szFileType) - 1] = 0;
328
329
return hres;
330
}
331
332
/***********************************************************************
333
* AVIFileInfoW (AVIFIL32.@)
334
*/
335
HRESULT WINAPI AVIFileInfoW(PAVIFILE pfile, LPAVIFILEINFOW afiw, LONG size)
336
{
337
TRACE("(%p,%p,%ld)\n", pfile, afiw, size);
338
339
if (pfile == NULL)
340
return AVIERR_BADHANDLE;
341
342
return IAVIFile_Info(pfile, afiw, size);
343
}
344
345
/***********************************************************************
346
* AVIFileGetStream (AVIFIL32.@)
347
*/
348
HRESULT WINAPI AVIFileGetStream(PAVIFILE pfile, PAVISTREAM *avis,
349
DWORD fccType, LONG lParam)
350
{
351
TRACE("(%p,%p,'%4.4s',%ld)\n", pfile, avis, (char*)&fccType, lParam);
352
353
if (pfile == NULL)
354
return AVIERR_BADHANDLE;
355
356
return IAVIFile_GetStream(pfile, avis, fccType, lParam);
357
}
358
359
/***********************************************************************
360
* AVIFileCreateStream (AVIFIL32.@)
361
* AVIFileCreateStreamA (AVIFIL32.@)
362
*/
363
HRESULT WINAPI AVIFileCreateStreamA(PAVIFILE pfile, PAVISTREAM *ppavi,
364
LPAVISTREAMINFOA psi)
365
{
366
AVISTREAMINFOW psiw;
367
368
TRACE("(%p,%p,%p)\n", pfile, ppavi, psi);
369
370
if (pfile == NULL)
371
return AVIERR_BADHANDLE;
372
373
/* Only the szName at the end is different */
374
memcpy(&psiw, psi, sizeof(*psi) - sizeof(psi->szName));
375
MultiByteToWideChar(CP_ACP, 0, psi->szName, -1, psiw.szName,
376
ARRAY_SIZE(psiw.szName));
377
378
return IAVIFile_CreateStream(pfile, ppavi, &psiw);
379
}
380
381
/***********************************************************************
382
* AVIFileCreateStreamW (AVIFIL32.@)
383
*/
384
HRESULT WINAPI AVIFileCreateStreamW(PAVIFILE pfile, PAVISTREAM *avis,
385
LPAVISTREAMINFOW asi)
386
{
387
TRACE("(%p,%p,%p)\n", pfile, avis, asi);
388
389
if (pfile == NULL)
390
return AVIERR_BADHANDLE;
391
392
return IAVIFile_CreateStream(pfile, avis, asi);
393
}
394
395
/***********************************************************************
396
* AVIFileWriteData (AVIFIL32.@)
397
*/
398
HRESULT WINAPI AVIFileWriteData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LONG size)
399
{
400
TRACE("(%p,'%4.4s',%p,%ld)\n", pfile, (char*)&fcc, lp, size);
401
402
if (pfile == NULL)
403
return AVIERR_BADHANDLE;
404
405
return IAVIFile_WriteData(pfile, fcc, lp, size);
406
}
407
408
/***********************************************************************
409
* AVIFileReadData (AVIFIL32.@)
410
*/
411
HRESULT WINAPI AVIFileReadData(PAVIFILE pfile,DWORD fcc,LPVOID lp,LPLONG size)
412
{
413
TRACE("(%p,'%4.4s',%p,%p)\n", pfile, (char*)&fcc, lp, size);
414
415
if (pfile == NULL)
416
return AVIERR_BADHANDLE;
417
418
return IAVIFile_ReadData(pfile, fcc, lp, size);
419
}
420
421
/***********************************************************************
422
* AVIFileEndRecord (AVIFIL32.@)
423
*/
424
HRESULT WINAPI AVIFileEndRecord(PAVIFILE pfile)
425
{
426
TRACE("(%p)\n", pfile);
427
428
if (pfile == NULL)
429
return AVIERR_BADHANDLE;
430
431
return IAVIFile_EndRecord(pfile);
432
}
433
434
/***********************************************************************
435
* AVIStreamAddRef (AVIFIL32.@)
436
*/
437
ULONG WINAPI AVIStreamAddRef(PAVISTREAM pstream)
438
{
439
TRACE("(%p)\n", pstream);
440
441
if (pstream == NULL) {
442
ERR(": bad handle passed!\n");
443
return 0;
444
}
445
446
return IAVIStream_AddRef(pstream);
447
}
448
449
/***********************************************************************
450
* AVIStreamRelease (AVIFIL32.@)
451
*/
452
ULONG WINAPI AVIStreamRelease(PAVISTREAM pstream)
453
{
454
TRACE("(%p)\n", pstream);
455
456
if (pstream == NULL) {
457
ERR(": bad handle passed!\n");
458
return 0;
459
}
460
461
return IAVIStream_Release(pstream);
462
}
463
464
/***********************************************************************
465
* AVIStreamCreate (AVIFIL32.@)
466
*/
467
HRESULT WINAPI AVIStreamCreate(PAVISTREAM *ppavi, LONG lParam1, LONG lParam2,
468
LPCLSID pclsidHandler)
469
{
470
HRESULT hr;
471
472
TRACE("(%p,0x%08lX,0x%08lX,%s)\n", ppavi, lParam1, lParam2,
473
debugstr_guid(pclsidHandler));
474
475
if (ppavi == NULL)
476
return AVIERR_BADPARAM;
477
478
*ppavi = NULL;
479
if (pclsidHandler == NULL)
480
return AVIERR_UNSUPPORTED;
481
482
hr = CoCreateInstance(pclsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIStream, (LPVOID*)ppavi);
483
if (FAILED(hr) || *ppavi == NULL)
484
return hr;
485
486
hr = IAVIStream_Create(*ppavi, lParam1, lParam2);
487
if (FAILED(hr)) {
488
IAVIStream_Release(*ppavi);
489
*ppavi = NULL;
490
}
491
492
return hr;
493
}
494
495
/***********************************************************************
496
* AVIStreamInfo (AVIFIL32.@)
497
* AVIStreamInfoA (AVIFIL32.@)
498
*/
499
HRESULT WINAPI AVIStreamInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
500
LONG size)
501
{
502
AVISTREAMINFOW asiw;
503
HRESULT hres;
504
505
TRACE("(%p,%p,%ld)\n", pstream, asi, size);
506
507
if (pstream == NULL)
508
return AVIERR_BADHANDLE;
509
if ((DWORD)size < sizeof(AVISTREAMINFOA))
510
return AVIERR_BADSIZE;
511
512
hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
513
514
memcpy(asi, &asiw, sizeof(asiw) - sizeof(asiw.szName));
515
WideCharToMultiByte(CP_ACP, 0, asiw.szName, -1, asi->szName,
516
sizeof(asi->szName), NULL, NULL);
517
asi->szName[sizeof(asi->szName) - 1] = 0;
518
519
return hres;
520
}
521
522
/***********************************************************************
523
* AVIStreamInfoW (AVIFIL32.@)
524
*/
525
HRESULT WINAPI AVIStreamInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
526
LONG size)
527
{
528
TRACE("(%p,%p,%ld)\n", pstream, asi, size);
529
530
if (pstream == NULL)
531
return AVIERR_BADHANDLE;
532
533
return IAVIStream_Info(pstream, asi, size);
534
}
535
536
/***********************************************************************
537
* AVIStreamFindSample (AVIFIL32.@)
538
*/
539
LONG WINAPI AVIStreamFindSample(PAVISTREAM pstream, LONG pos, LONG flags)
540
{
541
TRACE("(%p,%ld,0x%lX)\n", pstream, pos, flags);
542
543
if (pstream == NULL)
544
return -1;
545
546
return IAVIStream_FindSample(pstream, pos, flags);
547
}
548
549
/***********************************************************************
550
* AVIStreamReadFormat (AVIFIL32.@)
551
*/
552
HRESULT WINAPI AVIStreamReadFormat(PAVISTREAM pstream, LONG pos,
553
LPVOID format, LPLONG formatsize)
554
{
555
TRACE("(%p,%ld,%p,%p)\n", pstream, pos, format, formatsize);
556
557
if (pstream == NULL)
558
return AVIERR_BADHANDLE;
559
560
return IAVIStream_ReadFormat(pstream, pos, format, formatsize);
561
}
562
563
/***********************************************************************
564
* AVIStreamSetFormat (AVIFIL32.@)
565
*/
566
HRESULT WINAPI AVIStreamSetFormat(PAVISTREAM pstream, LONG pos,
567
LPVOID format, LONG formatsize)
568
{
569
TRACE("(%p,%ld,%p,%ld)\n", pstream, pos, format, formatsize);
570
571
if (pstream == NULL)
572
return AVIERR_BADHANDLE;
573
574
return IAVIStream_SetFormat(pstream, pos, format, formatsize);
575
}
576
577
/***********************************************************************
578
* AVIStreamRead (AVIFIL32.@)
579
*/
580
HRESULT WINAPI AVIStreamRead(PAVISTREAM pstream, LONG start, LONG samples,
581
LPVOID buffer, LONG buffersize,
582
LPLONG bytesread, LPLONG samplesread)
583
{
584
TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", pstream, start, samples, buffer,
585
buffersize, bytesread, samplesread);
586
587
if (pstream == NULL)
588
return AVIERR_BADHANDLE;
589
590
return IAVIStream_Read(pstream, start, samples, buffer, buffersize,
591
bytesread, samplesread);
592
}
593
594
/***********************************************************************
595
* AVIStreamWrite (AVIFIL32.@)
596
*/
597
HRESULT WINAPI AVIStreamWrite(PAVISTREAM pstream, LONG start, LONG samples,
598
LPVOID buffer, LONG buffersize, DWORD flags,
599
LPLONG sampwritten, LPLONG byteswritten)
600
{
601
TRACE("(%p,%ld,%ld,%p,%ld,0x%lX,%p,%p)\n", pstream, start, samples, buffer,
602
buffersize, flags, sampwritten, byteswritten);
603
604
if (pstream == NULL)
605
return AVIERR_BADHANDLE;
606
607
return IAVIStream_Write(pstream, start, samples, buffer, buffersize,
608
flags, sampwritten, byteswritten);
609
}
610
611
/***********************************************************************
612
* AVIStreamReadData (AVIFIL32.@)
613
*/
614
HRESULT WINAPI AVIStreamReadData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
615
LPLONG lpread)
616
{
617
TRACE("(%p,'%4.4s',%p,%p)\n", pstream, (char*)&fcc, lp, lpread);
618
619
if (pstream == NULL)
620
return AVIERR_BADHANDLE;
621
622
return IAVIStream_ReadData(pstream, fcc, lp, lpread);
623
}
624
625
/***********************************************************************
626
* AVIStreamWriteData (AVIFIL32.@)
627
*/
628
HRESULT WINAPI AVIStreamWriteData(PAVISTREAM pstream, DWORD fcc, LPVOID lp,
629
LONG size)
630
{
631
TRACE("(%p,'%4.4s',%p,%ld)\n", pstream, (char*)&fcc, lp, size);
632
633
if (pstream == NULL)
634
return AVIERR_BADHANDLE;
635
636
return IAVIStream_WriteData(pstream, fcc, lp, size);
637
}
638
639
/***********************************************************************
640
* AVIStreamGetFrameOpen (AVIFIL32.@)
641
*/
642
PGETFRAME WINAPI AVIStreamGetFrameOpen(PAVISTREAM pstream,
643
LPBITMAPINFOHEADER lpbiWanted)
644
{
645
PGETFRAME pg = NULL;
646
647
TRACE("(%p,%p)\n", pstream, lpbiWanted);
648
649
if (FAILED(IAVIStream_QueryInterface(pstream, &IID_IGetFrame, (LPVOID*)&pg)) ||
650
pg == NULL) {
651
pg = AVIFILE_CreateGetFrame(pstream);
652
if (pg == NULL)
653
return NULL;
654
}
655
656
if (FAILED(IGetFrame_SetFormat(pg, lpbiWanted, NULL, 0, 0, -1, -1))) {
657
IGetFrame_Release(pg);
658
return NULL;
659
}
660
661
return pg;
662
}
663
664
/***********************************************************************
665
* AVIStreamGetFrame (AVIFIL32.@)
666
*/
667
LPVOID WINAPI AVIStreamGetFrame(PGETFRAME pg, LONG pos)
668
{
669
TRACE("(%p,%ld)\n", pg, pos);
670
671
if (pg == NULL)
672
return NULL;
673
674
return IGetFrame_GetFrame(pg, pos);
675
}
676
677
/***********************************************************************
678
* AVIStreamGetFrameClose (AVIFIL32.@)
679
*/
680
HRESULT WINAPI AVIStreamGetFrameClose(PGETFRAME pg)
681
{
682
TRACE("(%p)\n", pg);
683
684
if (pg != NULL)
685
return IGetFrame_Release(pg);
686
return 0;
687
}
688
689
/***********************************************************************
690
* AVIMakeCompressedStream (AVIFIL32.@)
691
*/
692
HRESULT WINAPI AVIMakeCompressedStream(PAVISTREAM *ppsCompressed,
693
PAVISTREAM psSource,
694
LPAVICOMPRESSOPTIONS aco,
695
LPCLSID pclsidHandler)
696
{
697
AVISTREAMINFOW asiw;
698
CHAR szRegKey[25];
699
CHAR szValue[100];
700
CLSID clsidHandler;
701
HRESULT hr;
702
LONG size = sizeof(szValue);
703
704
TRACE("(%p,%p,%p,%s)\n", ppsCompressed, psSource, aco,
705
debugstr_guid(pclsidHandler));
706
707
if (ppsCompressed == NULL)
708
return AVIERR_BADPARAM;
709
if (psSource == NULL)
710
return AVIERR_BADHANDLE;
711
712
*ppsCompressed = NULL;
713
714
/* if no handler given get default ones based on streamtype */
715
if (pclsidHandler == NULL) {
716
hr = IAVIStream_Info(psSource, &asiw, sizeof(asiw));
717
if (FAILED(hr))
718
return hr;
719
720
wsprintfA(szRegKey, "AVIFile\\Compressors\\%4.4s", (char*)&asiw.fccType);
721
if (RegQueryValueA(HKEY_CLASSES_ROOT, szRegKey, szValue, &size) != ERROR_SUCCESS)
722
return AVIERR_UNSUPPORTED;
723
if (AVIFILE_CLSIDFromString(szValue, &clsidHandler) != S_OK)
724
return AVIERR_UNSUPPORTED;
725
} else
726
clsidHandler = *pclsidHandler;
727
728
hr = CoCreateInstance(&clsidHandler, NULL, CLSCTX_INPROC, &IID_IAVIStream, (LPVOID*)ppsCompressed);
729
if (FAILED(hr) || *ppsCompressed == NULL)
730
return hr;
731
732
hr = IAVIStream_Create(*ppsCompressed, (LPARAM)psSource, (LPARAM)aco);
733
if (FAILED(hr)) {
734
IAVIStream_Release(*ppsCompressed);
735
*ppsCompressed = NULL;
736
}
737
738
return hr;
739
}
740
741
/***********************************************************************
742
* AVIMakeFileFromStreams (AVIFIL32.@)
743
*/
744
HRESULT WINAPI AVIMakeFileFromStreams(PAVIFILE *ppfile, int nStreams,
745
PAVISTREAM *ppStreams)
746
{
747
TRACE("(%p,%d,%p)\n", ppfile, nStreams, ppStreams);
748
749
if (nStreams < 0 || ppfile == NULL || ppStreams == NULL)
750
return AVIERR_BADPARAM;
751
752
*ppfile = AVIFILE_CreateAVITempFile(nStreams, ppStreams);
753
if (*ppfile == NULL)
754
return AVIERR_MEMORY;
755
756
return AVIERR_OK;
757
}
758
759
/***********************************************************************
760
* AVIStreamOpenFromFile (AVIFIL32.@)
761
* AVIStreamOpenFromFileA (AVIFIL32.@)
762
*/
763
HRESULT WINAPI AVIStreamOpenFromFileA(PAVISTREAM *ppavi, LPCSTR szFile,
764
DWORD fccType, LONG lParam,
765
UINT mode, LPCLSID pclsidHandler)
766
{
767
PAVIFILE pfile = NULL;
768
HRESULT hr;
769
770
TRACE("(%p,%s,'%4.4s',%ld,0x%X,%s)\n", ppavi, debugstr_a(szFile),
771
(char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
772
773
if (ppavi == NULL || szFile == NULL)
774
return AVIERR_BADPARAM;
775
776
*ppavi = NULL;
777
778
hr = AVIFileOpenA(&pfile, szFile, mode, pclsidHandler);
779
if (FAILED(hr) || pfile == NULL)
780
return hr;
781
782
hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
783
IAVIFile_Release(pfile);
784
785
return hr;
786
}
787
788
/***********************************************************************
789
* AVIStreamOpenFromFileW (AVIFIL32.@)
790
*/
791
HRESULT WINAPI AVIStreamOpenFromFileW(PAVISTREAM *ppavi, LPCWSTR szFile,
792
DWORD fccType, LONG lParam,
793
UINT mode, LPCLSID pclsidHandler)
794
{
795
PAVIFILE pfile = NULL;
796
HRESULT hr;
797
798
TRACE("(%p,%s,'%4.4s',%ld,0x%X,%s)\n", ppavi, debugstr_w(szFile),
799
(char*)&fccType, lParam, mode, debugstr_guid(pclsidHandler));
800
801
if (ppavi == NULL || szFile == NULL)
802
return AVIERR_BADPARAM;
803
804
*ppavi = NULL;
805
806
hr = AVIFileOpenW(&pfile, szFile, mode, pclsidHandler);
807
if (FAILED(hr) || pfile == NULL)
808
return hr;
809
810
hr = IAVIFile_GetStream(pfile, ppavi, fccType, lParam);
811
IAVIFile_Release(pfile);
812
813
return hr;
814
}
815
816
/***********************************************************************
817
* AVIStreamBeginStreaming (AVIFIL32.@)
818
*/
819
LONG WINAPI AVIStreamBeginStreaming(PAVISTREAM pavi, LONG lStart, LONG lEnd, LONG lRate)
820
{
821
IAVIStreaming* pstream = NULL;
822
HRESULT hr;
823
824
TRACE("(%p,%ld,%ld,%ld)\n", pavi, lStart, lEnd, lRate);
825
826
if (pavi == NULL)
827
return AVIERR_BADHANDLE;
828
829
hr = IAVIStream_QueryInterface(pavi, &IID_IAVIStreaming, (LPVOID*)&pstream);
830
if (SUCCEEDED(hr) && pstream != NULL) {
831
hr = IAVIStreaming_Begin(pstream, lStart, lEnd, lRate);
832
IAVIStreaming_Release(pstream);
833
} else
834
hr = AVIERR_OK;
835
836
return hr;
837
}
838
839
/***********************************************************************
840
* AVIStreamEndStreaming (AVIFIL32.@)
841
*/
842
LONG WINAPI AVIStreamEndStreaming(PAVISTREAM pavi)
843
{
844
IAVIStreaming* pstream = NULL;
845
HRESULT hr;
846
847
TRACE("(%p)\n", pavi);
848
849
hr = IAVIStream_QueryInterface(pavi, &IID_IAVIStreaming, (LPVOID*)&pstream);
850
if (SUCCEEDED(hr) && pstream != NULL) {
851
IAVIStreaming_End(pstream);
852
IAVIStreaming_Release(pstream);
853
}
854
855
return AVIERR_OK;
856
}
857
858
/***********************************************************************
859
* AVIStreamStart (AVIFIL32.@)
860
*/
861
LONG WINAPI AVIStreamStart(PAVISTREAM pstream)
862
{
863
AVISTREAMINFOW asiw;
864
865
TRACE("(%p)\n", pstream);
866
867
if (pstream == NULL)
868
return 0;
869
870
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
871
return 0;
872
873
return asiw.dwStart;
874
}
875
876
/***********************************************************************
877
* AVIStreamLength (AVIFIL32.@)
878
*/
879
LONG WINAPI AVIStreamLength(PAVISTREAM pstream)
880
{
881
AVISTREAMINFOW asiw;
882
883
TRACE("(%p)\n", pstream);
884
885
if (pstream == NULL)
886
return 0;
887
888
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
889
return 0;
890
891
return asiw.dwLength;
892
}
893
894
/***********************************************************************
895
* AVIStreamSampleToTime (AVIFIL32.@)
896
*/
897
LONG WINAPI AVIStreamSampleToTime(PAVISTREAM pstream, LONG lSample)
898
{
899
AVISTREAMINFOW asiw;
900
LONG time;
901
902
TRACE("(%p,%ld)\n", pstream, lSample);
903
904
if (pstream == NULL)
905
return -1;
906
907
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
908
return -1;
909
if (asiw.dwRate == 0)
910
return -1;
911
912
/* limit to stream bounds */
913
if (lSample < asiw.dwStart)
914
lSample = asiw.dwStart;
915
if (lSample > asiw.dwStart + asiw.dwLength)
916
lSample = asiw.dwStart + asiw.dwLength;
917
918
if (asiw.dwRate / asiw.dwScale < 1000)
919
time = (LONG)(((float)lSample * asiw.dwScale * 1000) / asiw.dwRate);
920
else
921
time = (LONG)(((float)lSample * asiw.dwScale * 1000 + (asiw.dwRate - 1)) / asiw.dwRate);
922
923
TRACE(" -> %ld\n",time);
924
return time;
925
}
926
927
/***********************************************************************
928
* AVIStreamTimeToSample (AVIFIL32.@)
929
*/
930
LONG WINAPI AVIStreamTimeToSample(PAVISTREAM pstream, LONG lTime)
931
{
932
AVISTREAMINFOW asiw;
933
ULONG sample;
934
935
TRACE("(%p,%ld)\n", pstream, lTime);
936
937
if (pstream == NULL || lTime < 0)
938
return -1;
939
940
if (FAILED(IAVIStream_Info(pstream, &asiw, sizeof(asiw))))
941
return -1;
942
if (asiw.dwScale == 0)
943
return -1;
944
945
if (asiw.dwRate / asiw.dwScale < 1000)
946
sample = (LONG)((((float)asiw.dwRate * lTime) / (asiw.dwScale * 1000)));
947
else
948
sample = (LONG)(((float)asiw.dwRate * lTime + (asiw.dwScale * 1000 - 1)) / (asiw.dwScale * 1000));
949
950
/* limit to stream bounds */
951
if (sample < asiw.dwStart)
952
sample = asiw.dwStart;
953
if (sample > asiw.dwStart + asiw.dwLength)
954
sample = asiw.dwStart + asiw.dwLength;
955
956
TRACE(" -> %ld\n", sample);
957
return sample;
958
}
959
960
/***********************************************************************
961
* AVIBuildFilter (AVIFIL32.@)
962
* AVIBuildFilterA (AVIFIL32.@)
963
*/
964
HRESULT WINAPI AVIBuildFilterA(LPSTR szFilter, LONG cbFilter, BOOL fSaving)
965
{
966
LPWSTR wszFilter;
967
HRESULT hr;
968
969
TRACE("(%p,%ld,%d)\n", szFilter, cbFilter, fSaving);
970
971
/* check parameters */
972
if (szFilter == NULL)
973
return AVIERR_BADPARAM;
974
if (cbFilter < 2)
975
return AVIERR_BADSIZE;
976
977
szFilter[0] = 0;
978
szFilter[1] = 0;
979
980
wszFilter = malloc(cbFilter * sizeof(WCHAR));
981
if (wszFilter == NULL)
982
return AVIERR_MEMORY;
983
984
hr = AVIBuildFilterW(wszFilter, cbFilter, fSaving);
985
if (SUCCEEDED(hr)) {
986
WideCharToMultiByte(CP_ACP, 0, wszFilter, cbFilter,
987
szFilter, cbFilter, NULL, NULL);
988
}
989
990
free(wszFilter);
991
992
return hr;
993
}
994
995
/***********************************************************************
996
* AVIBuildFilterW (AVIFIL32.@)
997
*/
998
HRESULT WINAPI AVIBuildFilterW(LPWSTR szFilter, LONG cbFilter, BOOL fSaving)
999
{
1000
static const WCHAR all_files[] = L"*.*\0";
1001
1002
AVIFilter *lp;
1003
WCHAR szAllFiles[40];
1004
WCHAR szFileExt[10];
1005
WCHAR szValue[128];
1006
HKEY hKey;
1007
DWORD n, i;
1008
LONG size;
1009
DWORD count = 0;
1010
1011
TRACE("(%p,%ld,%d)\n", szFilter, cbFilter, fSaving);
1012
1013
/* check parameters */
1014
if (szFilter == NULL)
1015
return AVIERR_BADPARAM;
1016
if (cbFilter < 2)
1017
return AVIERR_BADSIZE;
1018
1019
lp = calloc(MAX_FILTERS, sizeof(AVIFilter));
1020
if (lp == NULL)
1021
return AVIERR_MEMORY;
1022
1023
/*
1024
* 1. iterate over HKEY_CLASSES_ROOT\\AVIFile\\Extensions and collect
1025
* extensions and CLSIDs
1026
* 2. iterate over collected CLSIDs and copy its description and its
1027
* extensions to szFilter if it fits
1028
*
1029
* First filter is named "All multimedia files" and its filter is a
1030
* collection of all possible extensions except "*.*".
1031
*/
1032
if (RegOpenKeyW(HKEY_CLASSES_ROOT, L"AVIFile\\Extensions", &hKey) != ERROR_SUCCESS) {
1033
free(lp);
1034
return AVIERR_ERROR;
1035
}
1036
for (n = 0;RegEnumKeyW(hKey, n, szFileExt, ARRAY_SIZE(szFileExt)) == ERROR_SUCCESS;n++) {
1037
WCHAR clsidW[40];
1038
1039
/* get CLSID to extension */
1040
size = sizeof(clsidW);
1041
if (RegQueryValueW(hKey, szFileExt, clsidW, &size) != ERROR_SUCCESS)
1042
break;
1043
1044
/* search if the CLSID is already known */
1045
for (i = 1; i <= count; i++) {
1046
if (lstrcmpW(lp[i].szClsid, clsidW) == 0)
1047
break; /* a new one */
1048
}
1049
1050
if (i == count + 1) {
1051
/* it's a new CLSID */
1052
1053
/* FIXME: How do we get info's about read/write capabilities? */
1054
1055
if (count >= MAX_FILTERS) {
1056
/* try to inform user of our full fixed size table */
1057
ERR(": More than %d filters found! Adjust MAX_FILTERS in dlls/avifil32/api.c\n", MAX_FILTERS);
1058
break;
1059
}
1060
1061
lstrcpyW(lp[i].szClsid, clsidW);
1062
1063
count++;
1064
}
1065
1066
/* append extension to the filter */
1067
wsprintfW(szValue, L";*.%s", szFileExt);
1068
if (lp[i].szExtensions[0] == 0)
1069
lstrcatW(lp[i].szExtensions, szValue + 1);
1070
else
1071
lstrcatW(lp[i].szExtensions, szValue);
1072
1073
/* also append to the "all multimedia"-filter */
1074
if (lp[0].szExtensions[0] == 0)
1075
lstrcatW(lp[0].szExtensions, szValue + 1);
1076
else
1077
lstrcatW(lp[0].szExtensions, szValue);
1078
}
1079
RegCloseKey(hKey);
1080
1081
/* 2. get descriptions for the CLSIDs and fill out szFilter */
1082
if (RegOpenKeyW(HKEY_CLASSES_ROOT, L"CLSID", &hKey) != ERROR_SUCCESS) {
1083
free(lp);
1084
return AVIERR_ERROR;
1085
}
1086
for (n = 0; n <= count; n++) {
1087
/* first the description */
1088
if (n != 0) {
1089
size = sizeof(szValue);
1090
if (RegQueryValueW(hKey, lp[n].szClsid, szValue, &size) == ERROR_SUCCESS) {
1091
size = lstrlenW(szValue);
1092
lstrcpynW(szFilter, szValue, cbFilter);
1093
}
1094
} else
1095
size = LoadStringW(AVIFILE_hModule,IDS_ALLMULTIMEDIA,szFilter,cbFilter);
1096
1097
/* check for enough space */
1098
size++;
1099
if (cbFilter < size + lstrlenW(lp[n].szExtensions) + 2) {
1100
szFilter[0] = 0;
1101
szFilter[1] = 0;
1102
free(lp);
1103
RegCloseKey(hKey);
1104
return AVIERR_BUFFERTOOSMALL;
1105
}
1106
cbFilter -= size;
1107
szFilter += size;
1108
1109
/* and then the filter */
1110
lstrcpynW(szFilter, lp[n].szExtensions, cbFilter);
1111
size = lstrlenW(lp[n].szExtensions) + 1;
1112
cbFilter -= size;
1113
szFilter += size;
1114
}
1115
1116
RegCloseKey(hKey);
1117
free(lp);
1118
1119
/* add "All files" "*.*" filter if enough space left */
1120
size = LoadStringW(AVIFILE_hModule, IDS_ALLFILES, szAllFiles,
1121
ARRAY_SIZE(szAllFiles) - ARRAY_SIZE(all_files)) + 1;
1122
memcpy( szAllFiles + size, all_files, sizeof(all_files) );
1123
size += ARRAY_SIZE(all_files);
1124
1125
if (cbFilter > size) {
1126
memcpy(szFilter, szAllFiles, size * sizeof(szAllFiles[0]));
1127
return AVIERR_OK;
1128
} else {
1129
szFilter[0] = 0;
1130
return AVIERR_BUFFERTOOSMALL;
1131
}
1132
}
1133
1134
static BOOL AVISaveOptionsFmtChoose(HWND hWnd)
1135
{
1136
LPAVICOMPRESSOPTIONS pOptions = SaveOpts.ppOptions[SaveOpts.nCurrent];
1137
AVISTREAMINFOW sInfo;
1138
1139
TRACE("(%p)\n", hWnd);
1140
1141
if (pOptions == NULL || SaveOpts.ppavis[SaveOpts.nCurrent] == NULL) {
1142
ERR(": bad state!\n");
1143
return FALSE;
1144
}
1145
1146
if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent],
1147
&sInfo, sizeof(sInfo)))) {
1148
ERR(": AVIStreamInfoW failed!\n");
1149
return FALSE;
1150
}
1151
1152
if (sInfo.fccType == streamtypeVIDEO) {
1153
COMPVARS cv;
1154
BOOL ret;
1155
1156
memset(&cv, 0, sizeof(cv));
1157
1158
if ((pOptions->dwFlags & AVICOMPRESSF_VALID) == 0) {
1159
memset(pOptions, 0, sizeof(AVICOMPRESSOPTIONS));
1160
pOptions->fccType = streamtypeVIDEO;
1161
pOptions->fccHandler = comptypeDIB;
1162
pOptions->dwQuality = (DWORD)ICQUALITY_DEFAULT;
1163
}
1164
1165
cv.cbSize = sizeof(cv);
1166
cv.dwFlags = ICMF_COMPVARS_VALID;
1167
/*cv.fccType = pOptions->fccType; */
1168
cv.fccHandler = pOptions->fccHandler;
1169
cv.lQ = pOptions->dwQuality;
1170
cv.lpState = pOptions->lpParms;
1171
cv.cbState = pOptions->cbParms;
1172
if (pOptions->dwFlags & AVICOMPRESSF_KEYFRAMES)
1173
cv.lKey = pOptions->dwKeyFrameEvery;
1174
else
1175
cv.lKey = 0;
1176
if (pOptions->dwFlags & AVICOMPRESSF_DATARATE)
1177
cv.lDataRate = pOptions->dwBytesPerSecond / 1024; /* need kBytes */
1178
else
1179
cv.lDataRate = 0;
1180
1181
ret = ICCompressorChoose(hWnd, SaveOpts.uFlags, NULL,
1182
SaveOpts.ppavis[SaveOpts.nCurrent], &cv, NULL);
1183
1184
if (ret) {
1185
pOptions->fccHandler = cv.fccHandler;
1186
pOptions->lpParms = cv.lpState;
1187
pOptions->cbParms = cv.cbState;
1188
pOptions->dwQuality = cv.lQ;
1189
if (cv.lKey != 0) {
1190
pOptions->dwKeyFrameEvery = cv.lKey;
1191
pOptions->dwFlags |= AVICOMPRESSF_KEYFRAMES;
1192
} else
1193
pOptions->dwFlags &= ~AVICOMPRESSF_KEYFRAMES;
1194
if (cv.lDataRate != 0) {
1195
pOptions->dwBytesPerSecond = cv.lDataRate * 1024; /* need bytes */
1196
pOptions->dwFlags |= AVICOMPRESSF_DATARATE;
1197
} else
1198
pOptions->dwFlags &= ~AVICOMPRESSF_DATARATE;
1199
pOptions->dwFlags |= AVICOMPRESSF_VALID;
1200
}
1201
ICCompressorFree(&cv);
1202
1203
return ret;
1204
} else if (sInfo.fccType == streamtypeAUDIO) {
1205
ACMFORMATCHOOSEW afmtc;
1206
MMRESULT ret;
1207
LONG size;
1208
1209
/* FIXME: check ACM version -- Which version is needed? */
1210
1211
memset(&afmtc, 0, sizeof(afmtc));
1212
afmtc.cbStruct = sizeof(afmtc);
1213
afmtc.fdwStyle = 0;
1214
afmtc.hwndOwner = hWnd;
1215
1216
acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &size);
1217
if ((pOptions->cbFormat == 0 || pOptions->lpFormat == NULL) && size != 0) {
1218
pOptions->lpFormat = malloc(size);
1219
if (!pOptions->lpFormat) return FALSE;
1220
pOptions->cbFormat = size;
1221
} else if (pOptions->cbFormat < (DWORD)size) {
1222
void *new_buffer = realloc(pOptions->lpFormat, size);
1223
if (!new_buffer) return FALSE;
1224
pOptions->lpFormat = new_buffer;
1225
pOptions->cbFormat = size;
1226
}
1227
afmtc.pwfx = pOptions->lpFormat;
1228
afmtc.cbwfx = pOptions->cbFormat;
1229
1230
size = 0;
1231
AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],
1232
sInfo.dwStart, &size);
1233
if (size < (LONG)sizeof(PCMWAVEFORMAT))
1234
size = sizeof(PCMWAVEFORMAT);
1235
afmtc.pwfxEnum = malloc(size);
1236
if (afmtc.pwfxEnum != NULL) {
1237
AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],
1238
sInfo.dwStart, afmtc.pwfxEnum, &size);
1239
afmtc.fdwEnum = ACM_FORMATENUMF_CONVERT;
1240
}
1241
1242
ret = acmFormatChooseW(&afmtc);
1243
if (ret == S_OK)
1244
pOptions->dwFlags |= AVICOMPRESSF_VALID;
1245
1246
free(afmtc.pwfxEnum);
1247
return ret == S_OK;
1248
} else {
1249
ERR(": unknown streamtype 0x%08lX\n", sInfo.fccType);
1250
return FALSE;
1251
}
1252
}
1253
1254
static void AVISaveOptionsUpdate(HWND hWnd)
1255
{
1256
WCHAR szFormat[128];
1257
AVISTREAMINFOW sInfo;
1258
LPVOID lpFormat;
1259
LONG size;
1260
1261
TRACE("(%p)\n", hWnd);
1262
1263
SaveOpts.nCurrent = SendDlgItemMessageW(hWnd,IDC_STREAM,CB_GETCURSEL,0,0);
1264
if (SaveOpts.nCurrent < 0)
1265
return;
1266
1267
if (FAILED(AVIStreamInfoW(SaveOpts.ppavis[SaveOpts.nCurrent], &sInfo, sizeof(sInfo))))
1268
return;
1269
1270
AVIStreamFormatSize(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,&size);
1271
if (size > 0) {
1272
szFormat[0] = 0;
1273
1274
/* read format to build format description string */
1275
lpFormat = malloc(size);
1276
if (lpFormat != NULL) {
1277
if (SUCCEEDED(AVIStreamReadFormat(SaveOpts.ppavis[SaveOpts.nCurrent],sInfo.dwStart,lpFormat, &size))) {
1278
if (sInfo.fccType == streamtypeVIDEO) {
1279
LPBITMAPINFOHEADER lpbi = lpFormat;
1280
ICINFO icinfo;
1281
1282
wsprintfW(szFormat, L"%ldx%ldx%d", lpbi->biWidth,
1283
lpbi->biHeight, lpbi->biBitCount);
1284
1285
if (lpbi->biCompression != BI_RGB) {
1286
HIC hic;
1287
1288
hic = ICLocate(ICTYPE_VIDEO, sInfo.fccHandler, lpFormat,
1289
NULL, ICMODE_DECOMPRESS);
1290
if (hic != NULL) {
1291
if (ICGetInfo(hic, &icinfo, sizeof(icinfo)) == S_OK)
1292
lstrcatW(szFormat, icinfo.szDescription);
1293
ICClose(hic);
1294
}
1295
} else {
1296
LoadStringW(AVIFILE_hModule, IDS_UNCOMPRESSED,
1297
icinfo.szDescription,
1298
ARRAY_SIZE(icinfo.szDescription));
1299
lstrcatW(szFormat, icinfo.szDescription);
1300
}
1301
} else if (sInfo.fccType == streamtypeAUDIO) {
1302
ACMFORMATTAGDETAILSW aftd;
1303
ACMFORMATDETAILSW afd;
1304
1305
memset(&aftd, 0, sizeof(aftd));
1306
memset(&afd, 0, sizeof(afd));
1307
1308
aftd.cbStruct = sizeof(aftd);
1309
aftd.dwFormatTag = afd.dwFormatTag =
1310
((PWAVEFORMATEX)lpFormat)->wFormatTag;
1311
aftd.cbFormatSize = afd.cbwfx = size;
1312
1313
afd.cbStruct = sizeof(afd);
1314
afd.pwfx = lpFormat;
1315
1316
if (acmFormatTagDetailsW(NULL, &aftd,
1317
ACM_FORMATTAGDETAILSF_FORMATTAG) == S_OK) {
1318
if (acmFormatDetailsW(NULL,&afd,ACM_FORMATDETAILSF_FORMAT) == S_OK)
1319
wsprintfW(szFormat, L"%s %s", afd.szFormat, aftd.szFormatTag);
1320
}
1321
}
1322
}
1323
free(lpFormat);
1324
}
1325
1326
/* set text for format description */
1327
SetDlgItemTextW(hWnd, IDC_FORMATTEXT, szFormat);
1328
1329
/* Disable option button for unsupported streamtypes */
1330
if (sInfo.fccType == streamtypeVIDEO ||
1331
sInfo.fccType == streamtypeAUDIO)
1332
EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), TRUE);
1333
else
1334
EnableWindow(GetDlgItem(hWnd, IDC_OPTIONS), FALSE);
1335
}
1336
1337
}
1338
1339
static INT_PTR CALLBACK AVISaveOptionsDlgProc(HWND hWnd, UINT uMsg,
1340
WPARAM wParam, LPARAM lParam)
1341
{
1342
DWORD dwInterleave;
1343
BOOL bIsInterleaved;
1344
INT n;
1345
1346
/*TRACE("(%p,%u,0x%04X,0x%08lX)\n", hWnd, uMsg, wParam, lParam);*/
1347
1348
switch (uMsg) {
1349
case WM_INITDIALOG:
1350
SaveOpts.nCurrent = 0;
1351
if (SaveOpts.nStreams == 1) {
1352
EndDialog(hWnd, AVISaveOptionsFmtChoose(hWnd));
1353
return TRUE;
1354
}
1355
1356
/* add streams */
1357
for (n = 0; n < SaveOpts.nStreams; n++) {
1358
AVISTREAMINFOW sInfo;
1359
1360
AVIStreamInfoW(SaveOpts.ppavis[n], &sInfo, sizeof(sInfo));
1361
SendDlgItemMessageW(hWnd, IDC_STREAM, CB_ADDSTRING,
1362
0L, (LPARAM)sInfo.szName);
1363
}
1364
1365
/* select first stream */
1366
SendDlgItemMessageW(hWnd, IDC_STREAM, CB_SETCURSEL, 0, 0);
1367
SendMessageW(hWnd, WM_COMMAND, MAKELONG(IDC_STREAM, CBN_SELCHANGE), (LPARAM)hWnd);
1368
1369
/* initialize interleave */
1370
if (SaveOpts.ppOptions[0] != NULL &&
1371
(SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_VALID)) {
1372
bIsInterleaved = (SaveOpts.ppOptions[0]->dwFlags & AVICOMPRESSF_INTERLEAVE);
1373
dwInterleave = SaveOpts.ppOptions[0]->dwInterleaveEvery;
1374
} else {
1375
bIsInterleaved = TRUE;
1376
dwInterleave = 0;
1377
}
1378
CheckDlgButton(hWnd, IDC_INTERLEAVE, bIsInterleaved);
1379
SetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, dwInterleave, FALSE);
1380
EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY), bIsInterleaved);
1381
break;
1382
case WM_COMMAND:
1383
switch (LOWORD(wParam)) {
1384
case IDOK:
1385
/* get data from controls and save them */
1386
dwInterleave = GetDlgItemInt(hWnd, IDC_INTERLEAVEEVERY, NULL, 0);
1387
bIsInterleaved = IsDlgButtonChecked(hWnd, IDC_INTERLEAVE);
1388
for (n = 0; n < SaveOpts.nStreams; n++) {
1389
if (SaveOpts.ppOptions[n] != NULL) {
1390
if (bIsInterleaved) {
1391
SaveOpts.ppOptions[n]->dwFlags |= AVICOMPRESSF_INTERLEAVE;
1392
SaveOpts.ppOptions[n]->dwInterleaveEvery = dwInterleave;
1393
} else
1394
SaveOpts.ppOptions[n]->dwFlags &= ~AVICOMPRESSF_INTERLEAVE;
1395
}
1396
}
1397
/* fall through */
1398
case IDCANCEL:
1399
EndDialog(hWnd, LOWORD(wParam) == IDOK);
1400
break;
1401
case IDC_INTERLEAVE:
1402
EnableWindow(GetDlgItem(hWnd, IDC_INTERLEAVEEVERY),
1403
IsDlgButtonChecked(hWnd, IDC_INTERLEAVE));
1404
break;
1405
case IDC_STREAM:
1406
if (HIWORD(wParam) == CBN_SELCHANGE) {
1407
/* update control elements */
1408
AVISaveOptionsUpdate(hWnd);
1409
}
1410
break;
1411
case IDC_OPTIONS:
1412
AVISaveOptionsFmtChoose(hWnd);
1413
break;
1414
};
1415
return TRUE;
1416
};
1417
1418
return FALSE;
1419
}
1420
1421
/***********************************************************************
1422
* AVISaveOptions (AVIFIL32.@)
1423
*/
1424
BOOL WINAPI AVISaveOptions(HWND hWnd, UINT uFlags, INT nStreams,
1425
PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *ppOptions)
1426
{
1427
LPAVICOMPRESSOPTIONS pSavedOptions = NULL;
1428
INT ret, n;
1429
1430
TRACE("(%p,0x%X,%d,%p,%p)\n", hWnd, uFlags, nStreams,
1431
ppavi, ppOptions);
1432
1433
/* check parameters */
1434
if (nStreams <= 0 || ppavi == NULL || ppOptions == NULL)
1435
return AVIERR_BADPARAM;
1436
1437
/* save options in case the user presses cancel */
1438
if (nStreams > 1) {
1439
pSavedOptions = malloc(nStreams * sizeof(AVICOMPRESSOPTIONS));
1440
if (pSavedOptions == NULL)
1441
return FALSE;
1442
1443
for (n = 0; n < nStreams; n++) {
1444
if (ppOptions[n] != NULL)
1445
memcpy(pSavedOptions + n, ppOptions[n], sizeof(AVICOMPRESSOPTIONS));
1446
}
1447
}
1448
1449
SaveOpts.uFlags = uFlags;
1450
SaveOpts.nStreams = nStreams;
1451
SaveOpts.ppavis = ppavi;
1452
SaveOpts.ppOptions = ppOptions;
1453
1454
ret = DialogBoxW(AVIFILE_hModule, MAKEINTRESOURCEW(IDD_SAVEOPTIONS),
1455
hWnd, AVISaveOptionsDlgProc);
1456
1457
if (ret == -1)
1458
ret = FALSE;
1459
1460
/* restore options when user pressed cancel */
1461
if (pSavedOptions != NULL) {
1462
if (ret == FALSE) {
1463
for (n = 0; n < nStreams; n++) {
1464
if (ppOptions[n] != NULL)
1465
memcpy(ppOptions[n], pSavedOptions + n, sizeof(AVICOMPRESSOPTIONS));
1466
}
1467
}
1468
free(pSavedOptions);
1469
}
1470
1471
return ret;
1472
}
1473
1474
/***********************************************************************
1475
* AVISaveOptionsFree (AVIFIL32.@)
1476
*/
1477
HRESULT WINAPI AVISaveOptionsFree(INT nStreams,LPAVICOMPRESSOPTIONS*ppOptions)
1478
{
1479
TRACE("(%d,%p)\n", nStreams, ppOptions);
1480
1481
if (nStreams < 0 || ppOptions == NULL)
1482
return AVIERR_BADPARAM;
1483
1484
for (nStreams--; nStreams >= 0; nStreams--) {
1485
if (ppOptions[nStreams] != NULL) {
1486
ppOptions[nStreams]->dwFlags &= ~AVICOMPRESSF_VALID;
1487
1488
if (ppOptions[nStreams]->lpParms != NULL) {
1489
free(ppOptions[nStreams]->lpParms);
1490
ppOptions[nStreams]->lpParms = NULL;
1491
ppOptions[nStreams]->cbParms = 0;
1492
}
1493
if (ppOptions[nStreams]->lpFormat != NULL) {
1494
free(ppOptions[nStreams]->lpFormat);
1495
ppOptions[nStreams]->lpFormat = NULL;
1496
ppOptions[nStreams]->cbFormat = 0;
1497
}
1498
}
1499
}
1500
1501
return AVIERR_OK;
1502
}
1503
1504
/***********************************************************************
1505
* AVISaveVA (AVIFIL32.@)
1506
*/
1507
HRESULT WINAPI AVISaveVA(LPCSTR szFile, CLSID *pclsidHandler,
1508
AVISAVECALLBACK lpfnCallback, int nStream,
1509
PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
1510
{
1511
LPWSTR wszFile = NULL;
1512
HRESULT hr;
1513
int len;
1514
1515
TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile), pclsidHandler,
1516
lpfnCallback, nStream, ppavi, plpOptions);
1517
1518
if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
1519
return AVIERR_BADPARAM;
1520
1521
/* convert the ANSI string to Unicode and call the Unicode function */
1522
len = MultiByteToWideChar(CP_ACP, 0, szFile, -1, NULL, 0);
1523
if (len <= 0)
1524
return AVIERR_BADPARAM;
1525
1526
wszFile = malloc(len * sizeof(WCHAR));
1527
if (wszFile == NULL)
1528
return AVIERR_MEMORY;
1529
1530
MultiByteToWideChar(CP_ACP, 0, szFile, -1, wszFile, len);
1531
1532
hr = AVISaveVW(wszFile, pclsidHandler, lpfnCallback,
1533
nStream, ppavi, plpOptions);
1534
1535
free(wszFile);
1536
1537
return hr;
1538
}
1539
1540
/***********************************************************************
1541
* AVIFILE_AVISaveDefaultCallback (internal)
1542
*/
1543
static BOOL WINAPI AVIFILE_AVISaveDefaultCallback(INT progress)
1544
{
1545
TRACE("(%d)\n", progress);
1546
1547
return FALSE;
1548
}
1549
1550
/***********************************************************************
1551
* AVISaveVW (AVIFIL32.@)
1552
*/
1553
HRESULT WINAPI AVISaveVW(LPCWSTR szFile, CLSID *pclsidHandler,
1554
AVISAVECALLBACK lpfnCallback, int nStreams,
1555
PAVISTREAM *ppavi, LPAVICOMPRESSOPTIONS *plpOptions)
1556
{
1557
LONG lStart[MAX_AVISTREAMS];
1558
PAVISTREAM pOutStreams[MAX_AVISTREAMS];
1559
PAVISTREAM pInStreams[MAX_AVISTREAMS];
1560
AVIFILEINFOW fInfo;
1561
AVISTREAMINFOW sInfo;
1562
1563
PAVIFILE pfile = NULL; /* the output AVI file */
1564
LONG lFirstVideo = -1;
1565
int curStream;
1566
1567
/* for interleaving ... */
1568
DWORD dwInterleave = 0; /* interleave rate */
1569
DWORD dwFileInitialFrames;
1570
LONG lFileLength;
1571
LONG lSampleInc;
1572
1573
/* for reading/writing the data ... */
1574
LPVOID lpBuffer = NULL;
1575
LONG cbBuffer; /* real size of lpBuffer */
1576
LONG lBufferSize; /* needed bytes for format(s), etc. */
1577
LONG lReadBytes;
1578
LONG lReadSamples;
1579
HRESULT hres;
1580
1581
TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile), pclsidHandler,
1582
lpfnCallback, nStreams, ppavi, plpOptions);
1583
1584
if (szFile == NULL || ppavi == NULL || plpOptions == NULL)
1585
return AVIERR_BADPARAM;
1586
if (nStreams >= MAX_AVISTREAMS) {
1587
WARN("Can't write AVI with %d streams only supports %d -- change MAX_AVISTREAMS!\n", nStreams, MAX_AVISTREAMS);
1588
return AVIERR_INTERNAL;
1589
}
1590
1591
if (lpfnCallback == NULL)
1592
lpfnCallback = AVIFILE_AVISaveDefaultCallback;
1593
1594
/* clear local variable(s) */
1595
for (curStream = 0; curStream < nStreams; curStream++) {
1596
pInStreams[curStream] = NULL;
1597
pOutStreams[curStream] = NULL;
1598
}
1599
1600
/* open output AVI file (create it if it doesn't exist) */
1601
hres = AVIFileOpenW(&pfile, szFile, OF_CREATE|OF_SHARE_EXCLUSIVE|OF_WRITE,
1602
pclsidHandler);
1603
if (FAILED(hres))
1604
return hres;
1605
AVIFileInfoW(pfile, &fInfo, sizeof(fInfo)); /* for dwCaps */
1606
1607
/* initialize our data structures part 1 */
1608
for (curStream = 0; curStream < nStreams; curStream++) {
1609
PAVISTREAM pCurStream = ppavi[curStream];
1610
1611
hres = AVIStreamInfoW(pCurStream, &sInfo, sizeof(sInfo));
1612
if (FAILED(hres))
1613
goto error;
1614
1615
/* search first video stream and check for interleaving */
1616
if (sInfo.fccType == streamtypeVIDEO) {
1617
/* remember first video stream -- needed for interleaving */
1618
if (lFirstVideo < 0)
1619
lFirstVideo = curStream;
1620
} else if (!dwInterleave) {
1621
/* check if any non-video stream wants to be interleaved */
1622
WARN("options.flags=0x%lX options.dwInterleave=%lu\n",plpOptions[curStream]->dwFlags,plpOptions[curStream]->dwInterleaveEvery);
1623
if (plpOptions[curStream] != NULL &&
1624
plpOptions[curStream]->dwFlags & AVICOMPRESSF_INTERLEAVE)
1625
dwInterleave = plpOptions[curStream]->dwInterleaveEvery;
1626
}
1627
1628
/* create de-/compressed stream interface if needed */
1629
pInStreams[curStream] = NULL;
1630
if (plpOptions[curStream] != NULL) {
1631
if (plpOptions[curStream]->fccHandler ||
1632
plpOptions[curStream]->lpFormat != NULL) {
1633
DWORD dwKeySave = plpOptions[curStream]->dwKeyFrameEvery;
1634
1635
if (fInfo.dwCaps & AVIFILECAPS_ALLKEYFRAMES)
1636
plpOptions[curStream]->dwKeyFrameEvery = 1;
1637
1638
hres = AVIMakeCompressedStream(&pInStreams[curStream], pCurStream,
1639
plpOptions[curStream], NULL);
1640
plpOptions[curStream]->dwKeyFrameEvery = dwKeySave;
1641
if (FAILED(hres) || pInStreams[curStream] == NULL) {
1642
pInStreams[curStream] = NULL;
1643
goto error;
1644
}
1645
1646
/* test stream interface and update stream-info */
1647
hres = AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
1648
if (FAILED(hres))
1649
goto error;
1650
}
1651
}
1652
1653
/* now handle streams which will only be copied */
1654
if (pInStreams[curStream] == NULL) {
1655
pCurStream = pInStreams[curStream] = ppavi[curStream];
1656
AVIStreamAddRef(pCurStream);
1657
} else
1658
pCurStream = pInStreams[curStream];
1659
1660
lStart[curStream] = sInfo.dwStart;
1661
} /* for all streams */
1662
1663
/* check that first video stream is the first stream */
1664
if (lFirstVideo > 0) {
1665
PAVISTREAM pTmp = pInStreams[lFirstVideo];
1666
LONG lTmp = lStart[lFirstVideo];
1667
1668
pInStreams[lFirstVideo] = pInStreams[0];
1669
pInStreams[0] = pTmp;
1670
lStart[lFirstVideo] = lStart[0];
1671
lStart[0] = lTmp;
1672
lFirstVideo = 0;
1673
}
1674
1675
/* allocate buffer for formats, data, etc. of an initial size of 64 kBytes*/
1676
cbBuffer = 0x00010000;
1677
lpBuffer = malloc(cbBuffer);
1678
if (lpBuffer == NULL) {
1679
hres = AVIERR_MEMORY;
1680
goto error;
1681
}
1682
1683
AVIStreamInfoW(pInStreams[0], &sInfo, sizeof(sInfo));
1684
lFileLength = sInfo.dwLength;
1685
dwFileInitialFrames = 0;
1686
if (lFirstVideo >= 0) {
1687
/* check for correct version of the format
1688
* -- need at least BITMAPINFOHEADER or newer
1689
*/
1690
lSampleInc = 1;
1691
lBufferSize = cbBuffer;
1692
hres = AVIStreamReadFormat(pInStreams[lFirstVideo], AVIStreamStart(pInStreams[lFirstVideo]), lpBuffer, &lBufferSize);
1693
if (lBufferSize < (LONG)sizeof(BITMAPINFOHEADER))
1694
hres = AVIERR_INTERNAL;
1695
if (FAILED(hres))
1696
goto error;
1697
} else /* use one second blocks for interleaving if no video present */
1698
lSampleInc = AVIStreamTimeToSample(pInStreams[0], 1000000);
1699
1700
/* create output streams */
1701
for (curStream = 0; curStream < nStreams; curStream++) {
1702
AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
1703
1704
sInfo.dwInitialFrames = 0;
1705
if (dwInterleave != 0 && curStream > 0 && sInfo.fccType != streamtypeVIDEO) {
1706
/* 750 ms initial frames for non-video streams */
1707
sInfo.dwInitialFrames = AVIStreamTimeToSample(pInStreams[0], 750);
1708
}
1709
1710
hres = AVIFileCreateStreamW(pfile, &pOutStreams[curStream], &sInfo);
1711
if (pOutStreams[curStream] != NULL && SUCCEEDED(hres)) {
1712
/* copy initial format for this stream */
1713
lBufferSize = cbBuffer;
1714
hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
1715
lpBuffer, &lBufferSize);
1716
if (FAILED(hres))
1717
goto error;
1718
hres = AVIStreamSetFormat(pOutStreams[curStream], 0, lpBuffer, lBufferSize);
1719
if (FAILED(hres))
1720
goto error;
1721
1722
/* try to copy stream handler data */
1723
lBufferSize = cbBuffer;
1724
hres = AVIStreamReadData(pInStreams[curStream], ckidSTREAMHANDLERDATA,
1725
lpBuffer, &lBufferSize);
1726
if (SUCCEEDED(hres) && lBufferSize > 0) {
1727
hres = AVIStreamWriteData(pOutStreams[curStream],ckidSTREAMHANDLERDATA,
1728
lpBuffer, lBufferSize);
1729
if (FAILED(hres))
1730
goto error;
1731
}
1732
1733
if (dwFileInitialFrames < sInfo.dwInitialFrames)
1734
dwFileInitialFrames = sInfo.dwInitialFrames;
1735
lReadBytes =
1736
AVIStreamSampleToSample(pOutStreams[0], pInStreams[curStream],
1737
sInfo.dwLength);
1738
if (lFileLength < lReadBytes)
1739
lFileLength = lReadBytes;
1740
} else {
1741
/* creation of de-/compression stream interface failed */
1742
WARN("creation of (de-)compression stream failed for stream %d\n",curStream);
1743
AVIStreamRelease(pInStreams[curStream]);
1744
if (curStream + 1 >= nStreams) {
1745
/* move the others one up */
1746
PAVISTREAM *ppas = &pInStreams[curStream];
1747
int n = nStreams - (curStream + 1);
1748
1749
do {
1750
*ppas = pInStreams[curStream + 1];
1751
} while (--n);
1752
}
1753
nStreams--;
1754
curStream--;
1755
}
1756
} /* create output streams for all input streams */
1757
1758
/* have we still something to write, or lost everything? */
1759
if (nStreams <= 0)
1760
goto error;
1761
1762
if (dwInterleave) {
1763
LONG lCurFrame = -dwFileInitialFrames;
1764
1765
/* interleaved file */
1766
if (dwInterleave == 1)
1767
AVIFileEndRecord(pfile);
1768
1769
for (; lCurFrame < lFileLength; lCurFrame += lSampleInc) {
1770
for (curStream = 0; curStream < nStreams; curStream++) {
1771
LONG lLastSample;
1772
1773
hres = AVIStreamInfoW(pOutStreams[curStream], &sInfo, sizeof(sInfo));
1774
if (FAILED(hres))
1775
goto error;
1776
1777
/* initial frames phase at the end for this stream? */
1778
if (-(LONG)sInfo.dwInitialFrames > lCurFrame)
1779
continue;
1780
1781
if ((lFileLength - lSampleInc) <= lCurFrame) {
1782
lLastSample = AVIStreamLength(pInStreams[curStream]);
1783
lFirstVideo = lLastSample + AVIStreamStart(pInStreams[curStream]);
1784
} else {
1785
if (curStream != 0) {
1786
lFirstVideo =
1787
AVIStreamSampleToSample(pInStreams[curStream], pInStreams[0],
1788
(sInfo.fccType == streamtypeVIDEO ?
1789
(LONG)dwInterleave : lSampleInc) +
1790
sInfo.dwInitialFrames + lCurFrame);
1791
} else
1792
lFirstVideo = lSampleInc + (sInfo.dwInitialFrames + lCurFrame);
1793
1794
lLastSample = AVIStreamEnd(pInStreams[curStream]);
1795
if (lLastSample <= lFirstVideo)
1796
lFirstVideo = lLastSample;
1797
}
1798
1799
/* copy needed samples now */
1800
WARN("copy from stream %d samples %ld to %ld...\n",curStream,
1801
lStart[curStream],lFirstVideo);
1802
while (lFirstVideo > lStart[curStream]) {
1803
DWORD flags = 0;
1804
1805
/* copy format in case it can change */
1806
lBufferSize = cbBuffer;
1807
hres = AVIStreamReadFormat(pInStreams[curStream], lStart[curStream],
1808
lpBuffer, &lBufferSize);
1809
if (FAILED(hres))
1810
goto error;
1811
AVIStreamSetFormat(pOutStreams[curStream], lStart[curStream],
1812
lpBuffer, lBufferSize);
1813
1814
/* try to read data until we got it, or error */
1815
do {
1816
hres = AVIStreamRead(pInStreams[curStream], lStart[curStream],
1817
lFirstVideo - lStart[curStream], lpBuffer,
1818
cbBuffer, &lReadBytes, &lReadSamples);
1819
} while ((hres == AVIERR_BUFFERTOOSMALL) &&
1820
(lpBuffer = realloc(lpBuffer, cbBuffer *= 2)) != NULL);
1821
if (lpBuffer == NULL)
1822
hres = AVIERR_MEMORY;
1823
if (FAILED(hres))
1824
goto error;
1825
1826
if (AVIStreamIsKeyFrame(pInStreams[curStream], (LONG)sInfo.dwStart))
1827
flags = AVIIF_KEYFRAME;
1828
hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
1829
lpBuffer, lReadBytes, flags, NULL, NULL);
1830
if (FAILED(hres))
1831
goto error;
1832
1833
lStart[curStream] += lReadSamples;
1834
}
1835
lStart[curStream] = lFirstVideo;
1836
} /* stream by stream */
1837
1838
/* need to close this block? */
1839
if (dwInterleave == 1) {
1840
hres = AVIFileEndRecord(pfile);
1841
if (FAILED(hres))
1842
break;
1843
}
1844
1845
/* show progress */
1846
if (lpfnCallback(MulDiv(dwFileInitialFrames + lCurFrame, 100,
1847
dwFileInitialFrames + lFileLength))) {
1848
hres = AVIERR_USERABORT;
1849
break;
1850
}
1851
} /* copy frame by frame */
1852
} else {
1853
/* non-interleaved file */
1854
1855
for (curStream = 0; curStream < nStreams; curStream++) {
1856
/* show progress */
1857
if (lpfnCallback(MulDiv(curStream, 100, nStreams))) {
1858
hres = AVIERR_USERABORT;
1859
goto error;
1860
}
1861
1862
AVIStreamInfoW(pInStreams[curStream], &sInfo, sizeof(sInfo));
1863
1864
if (sInfo.dwSampleSize != 0) {
1865
/* sample-based data like audio */
1866
while (sInfo.dwStart < sInfo.dwLength) {
1867
LONG lSamples = cbBuffer / sInfo.dwSampleSize;
1868
1869
/* copy format in case it can change */
1870
lBufferSize = cbBuffer;
1871
hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
1872
lpBuffer, &lBufferSize);
1873
if (FAILED(hres))
1874
goto error;
1875
AVIStreamSetFormat(pOutStreams[curStream], sInfo.dwStart,
1876
lpBuffer, lBufferSize);
1877
1878
/* limit to stream boundaries */
1879
if (lSamples != (LONG)(sInfo.dwLength - sInfo.dwStart))
1880
lSamples = sInfo.dwLength - sInfo.dwStart;
1881
1882
/* now try to read until we get it, or an error occurs */
1883
do {
1884
lReadBytes = cbBuffer;
1885
lReadSamples = 0;
1886
hres = AVIStreamRead(pInStreams[curStream],sInfo.dwStart,lSamples,
1887
lpBuffer,cbBuffer,&lReadBytes,&lReadSamples);
1888
} while ((hres == AVIERR_BUFFERTOOSMALL) &&
1889
(lpBuffer = realloc(lpBuffer, cbBuffer *= 2)) != NULL);
1890
if (lpBuffer == NULL)
1891
hres = AVIERR_MEMORY;
1892
if (FAILED(hres))
1893
goto error;
1894
if (lReadSamples != 0) {
1895
sInfo.dwStart += lReadSamples;
1896
hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
1897
lpBuffer, lReadBytes, 0, NULL , NULL);
1898
if (FAILED(hres))
1899
goto error;
1900
1901
/* show progress */
1902
if (lpfnCallback(MulDiv(sInfo.dwStart,100,nStreams*sInfo.dwLength)+
1903
MulDiv(curStream, 100, nStreams))) {
1904
hres = AVIERR_USERABORT;
1905
goto error;
1906
}
1907
} else {
1908
if ((sInfo.dwLength - sInfo.dwStart) != 1) {
1909
hres = AVIERR_FILEREAD;
1910
goto error;
1911
}
1912
}
1913
}
1914
} else {
1915
/* block-based data like video */
1916
for (; sInfo.dwStart < sInfo.dwLength; sInfo.dwStart++) {
1917
DWORD flags = 0;
1918
1919
/* copy format in case it can change */
1920
lBufferSize = cbBuffer;
1921
hres = AVIStreamReadFormat(pInStreams[curStream], sInfo.dwStart,
1922
lpBuffer, &lBufferSize);
1923
if (FAILED(hres))
1924
goto error;
1925
AVIStreamSetFormat(pOutStreams[curStream], sInfo.dwStart,
1926
lpBuffer, lBufferSize);
1927
1928
/* try to read block and resize buffer if necessary */
1929
do {
1930
lReadSamples = 0;
1931
lReadBytes = cbBuffer;
1932
hres = AVIStreamRead(pInStreams[curStream], sInfo.dwStart, 1,
1933
lpBuffer, cbBuffer,&lReadBytes,&lReadSamples);
1934
} while ((hres == AVIERR_BUFFERTOOSMALL) &&
1935
(lpBuffer = realloc(lpBuffer, cbBuffer *= 2)) != NULL);
1936
if (lpBuffer == NULL)
1937
hres = AVIERR_MEMORY;
1938
if (FAILED(hres))
1939
goto error;
1940
if (lReadSamples != 1) {
1941
hres = AVIERR_FILEREAD;
1942
goto error;
1943
}
1944
1945
if (AVIStreamIsKeyFrame(pInStreams[curStream], (LONG)sInfo.dwStart))
1946
flags = AVIIF_KEYFRAME;
1947
hres = AVIStreamWrite(pOutStreams[curStream], -1, lReadSamples,
1948
lpBuffer, lReadBytes, flags, NULL, NULL);
1949
if (FAILED(hres))
1950
goto error;
1951
1952
/* show progress */
1953
if (lpfnCallback(MulDiv(sInfo.dwStart,100,nStreams*sInfo.dwLength)+
1954
MulDiv(curStream, 100, nStreams))) {
1955
hres = AVIERR_USERABORT;
1956
goto error;
1957
}
1958
} /* copy all blocks */
1959
}
1960
} /* copy data stream by stream */
1961
}
1962
1963
error:
1964
free(lpBuffer);
1965
if (pfile != NULL) {
1966
for (curStream = 0; curStream < nStreams; curStream++) {
1967
if (pOutStreams[curStream] != NULL)
1968
AVIStreamRelease(pOutStreams[curStream]);
1969
if (pInStreams[curStream] != NULL)
1970
AVIStreamRelease(pInStreams[curStream]);
1971
}
1972
1973
AVIFileRelease(pfile);
1974
}
1975
1976
return hres;
1977
}
1978
1979
/***********************************************************************
1980
* EditStreamClone (AVIFIL32.@)
1981
*/
1982
HRESULT WINAPI EditStreamClone(PAVISTREAM pStream, PAVISTREAM *ppResult)
1983
{
1984
PAVIEDITSTREAM pEdit = NULL;
1985
HRESULT hr;
1986
1987
TRACE("(%p,%p)\n", pStream, ppResult);
1988
1989
if (pStream == NULL)
1990
return AVIERR_BADHANDLE;
1991
if (ppResult == NULL)
1992
return AVIERR_BADPARAM;
1993
1994
*ppResult = NULL;
1995
1996
hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
1997
if (SUCCEEDED(hr) && pEdit != NULL) {
1998
hr = IAVIEditStream_Clone(pEdit, ppResult);
1999
2000
IAVIEditStream_Release(pEdit);
2001
} else
2002
hr = AVIERR_UNSUPPORTED;
2003
2004
return hr;
2005
}
2006
2007
/***********************************************************************
2008
* EditStreamCopy (AVIFIL32.@)
2009
*/
2010
HRESULT WINAPI EditStreamCopy(PAVISTREAM pStream, LONG *plStart,
2011
LONG *plLength, PAVISTREAM *ppResult)
2012
{
2013
PAVIEDITSTREAM pEdit = NULL;
2014
HRESULT hr;
2015
2016
TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
2017
2018
if (pStream == NULL)
2019
return AVIERR_BADHANDLE;
2020
if (plStart == NULL || plLength == NULL || ppResult == NULL)
2021
return AVIERR_BADPARAM;
2022
2023
*ppResult = NULL;
2024
2025
hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2026
if (SUCCEEDED(hr) && pEdit != NULL) {
2027
hr = IAVIEditStream_Copy(pEdit, plStart, plLength, ppResult);
2028
2029
IAVIEditStream_Release(pEdit);
2030
} else
2031
hr = AVIERR_UNSUPPORTED;
2032
2033
return hr;
2034
}
2035
2036
/***********************************************************************
2037
* EditStreamCut (AVIFIL32.@)
2038
*/
2039
HRESULT WINAPI EditStreamCut(PAVISTREAM pStream, LONG *plStart,
2040
LONG *plLength, PAVISTREAM *ppResult)
2041
{
2042
PAVIEDITSTREAM pEdit = NULL;
2043
HRESULT hr;
2044
2045
TRACE("(%p,%p,%p,%p)\n", pStream, plStart, plLength, ppResult);
2046
2047
if (ppResult != NULL)
2048
*ppResult = NULL;
2049
if (pStream == NULL)
2050
return AVIERR_BADHANDLE;
2051
if (plStart == NULL || plLength == NULL)
2052
return AVIERR_BADPARAM;
2053
2054
hr = IAVIStream_QueryInterface(pStream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2055
if (SUCCEEDED(hr) && pEdit != NULL) {
2056
hr = IAVIEditStream_Cut(pEdit, plStart, plLength, ppResult);
2057
2058
IAVIEditStream_Release(pEdit);
2059
} else
2060
hr = AVIERR_UNSUPPORTED;
2061
2062
return hr;
2063
}
2064
2065
/***********************************************************************
2066
* EditStreamPaste (AVIFIL32.@)
2067
*/
2068
HRESULT WINAPI EditStreamPaste(PAVISTREAM pDest, LONG *plStart, LONG *plLength,
2069
PAVISTREAM pSource, LONG lStart, LONG lEnd)
2070
{
2071
PAVIEDITSTREAM pEdit = NULL;
2072
HRESULT hr;
2073
2074
TRACE("(%p,%p,%p,%p,%ld,%ld)\n", pDest, plStart, plLength,
2075
pSource, lStart, lEnd);
2076
2077
if (pDest == NULL || pSource == NULL)
2078
return AVIERR_BADHANDLE;
2079
if (plStart == NULL || plLength == NULL || lStart < 0)
2080
return AVIERR_BADPARAM;
2081
2082
hr = IAVIStream_QueryInterface(pDest, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2083
if (SUCCEEDED(hr) && pEdit != NULL) {
2084
hr = IAVIEditStream_Paste(pEdit, plStart, plLength, pSource, lStart, lEnd);
2085
2086
IAVIEditStream_Release(pEdit);
2087
} else
2088
hr = AVIERR_UNSUPPORTED;
2089
2090
return hr;
2091
}
2092
2093
/***********************************************************************
2094
* EditStreamSetInfoA (AVIFIL32.@)
2095
*/
2096
HRESULT WINAPI EditStreamSetInfoA(PAVISTREAM pstream, LPAVISTREAMINFOA asi,
2097
LONG size)
2098
{
2099
AVISTREAMINFOW asiw;
2100
2101
TRACE("(%p,%p,%ld)\n", pstream, asi, size);
2102
2103
if (size >= 0 && size < sizeof(AVISTREAMINFOA))
2104
return AVIERR_BADSIZE;
2105
2106
memcpy(&asiw, asi, sizeof(asiw) - sizeof(asiw.szName));
2107
MultiByteToWideChar(CP_ACP, 0, asi->szName, -1, asiw.szName, ARRAY_SIZE(asiw.szName));
2108
2109
return EditStreamSetInfoW(pstream, &asiw, sizeof(asiw));
2110
}
2111
2112
/***********************************************************************
2113
* EditStreamSetInfoW (AVIFIL32.@)
2114
*/
2115
HRESULT WINAPI EditStreamSetInfoW(PAVISTREAM pstream, LPAVISTREAMINFOW asi,
2116
LONG size)
2117
{
2118
PAVIEDITSTREAM pEdit = NULL;
2119
HRESULT hr;
2120
2121
TRACE("(%p,%p,%ld)\n", pstream, asi, size);
2122
2123
if (size >= 0 && size < sizeof(AVISTREAMINFOA))
2124
return AVIERR_BADSIZE;
2125
2126
hr = IAVIStream_QueryInterface(pstream, &IID_IAVIEditStream,(LPVOID*)&pEdit);
2127
if (SUCCEEDED(hr) && pEdit != NULL) {
2128
hr = IAVIEditStream_SetInfo(pEdit, asi, size);
2129
2130
IAVIEditStream_Release(pEdit);
2131
} else
2132
hr = AVIERR_UNSUPPORTED;
2133
2134
return hr;
2135
}
2136
2137
/***********************************************************************
2138
* EditStreamSetNameA (AVIFIL32.@)
2139
*/
2140
HRESULT WINAPI EditStreamSetNameA(PAVISTREAM pstream, LPCSTR szName)
2141
{
2142
AVISTREAMINFOA asia;
2143
HRESULT hres;
2144
2145
TRACE("(%p,%s)\n", pstream, debugstr_a(szName));
2146
2147
if (pstream == NULL)
2148
return AVIERR_BADHANDLE;
2149
if (szName == NULL)
2150
return AVIERR_BADPARAM;
2151
2152
hres = AVIStreamInfoA(pstream, &asia, sizeof(asia));
2153
if (FAILED(hres))
2154
return hres;
2155
2156
memset(asia.szName, 0, sizeof(asia.szName));
2157
lstrcpynA(asia.szName, szName, ARRAY_SIZE(asia.szName));
2158
2159
return EditStreamSetInfoA(pstream, &asia, sizeof(asia));
2160
}
2161
2162
/***********************************************************************
2163
* EditStreamSetNameW (AVIFIL32.@)
2164
*/
2165
HRESULT WINAPI EditStreamSetNameW(PAVISTREAM pstream, LPCWSTR szName)
2166
{
2167
AVISTREAMINFOW asiw;
2168
HRESULT hres;
2169
2170
TRACE("(%p,%s)\n", pstream, debugstr_w(szName));
2171
2172
if (pstream == NULL)
2173
return AVIERR_BADHANDLE;
2174
if (szName == NULL)
2175
return AVIERR_BADPARAM;
2176
2177
hres = IAVIStream_Info(pstream, &asiw, sizeof(asiw));
2178
if (FAILED(hres))
2179
return hres;
2180
2181
memset(asiw.szName, 0, sizeof(asiw.szName));
2182
lstrcpynW(asiw.szName, szName, ARRAY_SIZE(asiw.szName));
2183
2184
return EditStreamSetInfoW(pstream, &asiw, sizeof(asiw));
2185
}
2186
2187
/***********************************************************************
2188
* AVIClearClipboard (AVIFIL32.@)
2189
*/
2190
HRESULT WINAPI AVIClearClipboard(void)
2191
{
2192
TRACE("()\n");
2193
2194
return AVIERR_UNSUPPORTED; /* OleSetClipboard(NULL); */
2195
}
2196
2197
/***********************************************************************
2198
* AVIGetFromClipboard (AVIFIL32.@)
2199
*/
2200
HRESULT WINAPI AVIGetFromClipboard(PAVIFILE *ppfile)
2201
{
2202
FIXME("(%p), stub!\n", ppfile);
2203
2204
*ppfile = NULL;
2205
2206
return AVIERR_UNSUPPORTED;
2207
}
2208
2209
/***********************************************************************
2210
* AVIMakeStreamFromClipboard (AVIFIL32.@)
2211
*/
2212
HRESULT WINAPI AVIMakeStreamFromClipboard(UINT cfFormat, HANDLE hGlobal,
2213
PAVISTREAM * ppstream)
2214
{
2215
FIXME("(0x%08x,%p,%p), stub!\n", cfFormat, hGlobal, ppstream);
2216
2217
if (ppstream == NULL)
2218
return AVIERR_BADHANDLE;
2219
2220
return AVIERR_UNSUPPORTED;
2221
}
2222
2223
/***********************************************************************
2224
* AVIPutFileOnClipboard (AVIFIL32.@)
2225
*/
2226
HRESULT WINAPI AVIPutFileOnClipboard(PAVIFILE pfile)
2227
{
2228
FIXME("(%p), stub!\n", pfile);
2229
2230
if (pfile == NULL)
2231
return AVIERR_BADHANDLE;
2232
2233
return AVIERR_UNSUPPORTED;
2234
}
2235
2236
HRESULT WINAPIV AVISaveA(LPCSTR szFile, CLSID * pclsidHandler, AVISAVECALLBACK lpfnCallback,
2237
int nStreams, PAVISTREAM pavi, LPAVICOMPRESSOPTIONS lpOptions, ...)
2238
{
2239
va_list vl;
2240
int i;
2241
HRESULT ret;
2242
PAVISTREAM *streams;
2243
LPAVICOMPRESSOPTIONS *options;
2244
2245
TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_a(szFile), pclsidHandler, lpfnCallback,
2246
nStreams, pavi, lpOptions);
2247
2248
if (nStreams <= 0) return AVIERR_BADPARAM;
2249
2250
streams = malloc(nStreams * sizeof(*streams));
2251
options = malloc(nStreams * sizeof(*options));
2252
if (!streams || !options)
2253
{
2254
ret = AVIERR_MEMORY;
2255
goto error;
2256
}
2257
2258
streams[0] = pavi;
2259
options[0] = lpOptions;
2260
2261
va_start(vl, lpOptions);
2262
for (i = 1; i < nStreams; i++)
2263
{
2264
streams[i] = va_arg(vl, PAVISTREAM);
2265
options[i] = va_arg(vl, PAVICOMPRESSOPTIONS);
2266
}
2267
va_end(vl);
2268
2269
for (i = 0; i < nStreams; i++)
2270
TRACE("Pair[%d] - Stream = %p, Options = %p\n", i, streams[i], options[i]);
2271
2272
ret = AVISaveVA(szFile, pclsidHandler, lpfnCallback, nStreams, streams, options);
2273
error:
2274
free(streams);
2275
free(options);
2276
return ret;
2277
}
2278
2279
HRESULT WINAPIV AVISaveW(LPCWSTR szFile, CLSID * pclsidHandler, AVISAVECALLBACK lpfnCallback,
2280
int nStreams, PAVISTREAM pavi, LPAVICOMPRESSOPTIONS lpOptions, ...)
2281
{
2282
va_list vl;
2283
int i;
2284
HRESULT ret;
2285
PAVISTREAM *streams;
2286
LPAVICOMPRESSOPTIONS *options;
2287
2288
TRACE("(%s,%p,%p,%d,%p,%p)\n", debugstr_w(szFile), pclsidHandler, lpfnCallback,
2289
nStreams, pavi, lpOptions);
2290
2291
if (nStreams <= 0) return AVIERR_BADPARAM;
2292
2293
streams = malloc(nStreams * sizeof(*streams));
2294
options = malloc(nStreams * sizeof(*options));
2295
if (!streams || !options)
2296
{
2297
ret = AVIERR_MEMORY;
2298
goto error;
2299
}
2300
2301
streams[0] = pavi;
2302
options[0] = lpOptions;
2303
2304
va_start(vl, lpOptions);
2305
for (i = 1; i < nStreams; i++)
2306
{
2307
streams[i] = va_arg(vl, PAVISTREAM);
2308
options[i] = va_arg(vl, PAVICOMPRESSOPTIONS);
2309
}
2310
va_end(vl);
2311
2312
for (i = 0; i < nStreams; i++)
2313
TRACE("Pair[%d] - Stream = %p, Options = %p\n", i, streams[i], options[i]);
2314
2315
ret = AVISaveVW(szFile, pclsidHandler, lpfnCallback, nStreams, streams, options);
2316
error:
2317
free(streams);
2318
free(options);
2319
return ret;
2320
}
2321
2322