Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/avifil32/acmstream.c
4388 views
1
/*
2
* Copyright 2002 Michael Günnewig
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#include <assert.h>
20
#include <stdarg.h>
21
22
#include "windef.h"
23
#include "winbase.h"
24
#include "wingdi.h"
25
#include "winuser.h"
26
#include "winerror.h"
27
#include "mmsystem.h"
28
#include "vfw.h"
29
#include "msacm.h"
30
31
#include "avifile_private.h"
32
33
#include "wine/debug.h"
34
35
WINE_DEFAULT_DEBUG_CHANNEL(avifile);
36
37
/***********************************************************************/
38
39
typedef struct _IAVIStreamImpl {
40
/* IUnknown stuff */
41
IAVIStream IAVIStream_iface;
42
LONG ref;
43
44
/* IAVIStream stuff */
45
PAVISTREAM pStream;
46
AVISTREAMINFOW sInfo;
47
48
HACMSTREAM has;
49
50
LPWAVEFORMATEX lpInFormat;
51
LONG cbInFormat;
52
53
LPWAVEFORMATEX lpOutFormat;
54
LONG cbOutFormat;
55
56
ACMSTREAMHEADER acmStreamHdr;
57
} IAVIStreamImpl;
58
59
/***********************************************************************/
60
61
#define CONVERT_STREAM_to_THIS(a) do { \
62
DWORD __bytes; \
63
acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
64
&__bytes, ACM_STREAMSIZEF_SOURCE); \
65
*(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
66
67
#define CONVERT_THIS_to_STREAM(a) do { \
68
DWORD __bytes; \
69
acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
70
&__bytes, ACM_STREAMSIZEF_DESTINATION); \
71
*(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
72
73
static HRESULT AVIFILE_OpenCompressor(IAVIStreamImpl *This)
74
{
75
HRESULT hr;
76
77
/* pre-conditions */
78
assert(This != NULL);
79
assert(This->pStream != NULL);
80
81
if (This->has != NULL)
82
return AVIERR_OK;
83
84
if (This->lpInFormat == NULL) {
85
/* decode or encode the data from pStream */
86
hr = AVIStreamFormatSize(This->pStream, This->sInfo.dwStart, &This->cbInFormat);
87
if (FAILED(hr))
88
return hr;
89
This->lpInFormat = malloc(This->cbInFormat);
90
if (This->lpInFormat == NULL)
91
return AVIERR_MEMORY;
92
93
hr = IAVIStream_ReadFormat(This->pStream, This->sInfo.dwStart,
94
This->lpInFormat, &This->cbInFormat);
95
if (FAILED(hr))
96
return hr;
97
98
if (This->lpOutFormat == NULL) {
99
/* we must decode to default format */
100
This->cbOutFormat = sizeof(WAVEFORMATEX);
101
This->lpOutFormat = malloc(This->cbOutFormat);
102
if (This->lpOutFormat == NULL)
103
return AVIERR_MEMORY;
104
105
This->lpOutFormat->wFormatTag = WAVE_FORMAT_PCM;
106
if (acmFormatSuggest(NULL, This->lpInFormat, This->lpOutFormat,
107
This->cbOutFormat, ACM_FORMATSUGGESTF_WFORMATTAG) != S_OK)
108
return AVIERR_NOCOMPRESSOR;
109
}
110
} else if (This->lpOutFormat == NULL)
111
return AVIERR_ERROR; /* To what should I encode? */
112
113
if (acmStreamOpen(&This->has, NULL, This->lpInFormat, This->lpOutFormat,
114
NULL, 0, 0, ACM_STREAMOPENF_NONREALTIME) != S_OK)
115
return AVIERR_NOCOMPRESSOR;
116
117
/* update AVISTREAMINFO structure */
118
This->sInfo.dwSampleSize = This->lpOutFormat->nBlockAlign;
119
This->sInfo.dwScale = This->lpOutFormat->nBlockAlign;
120
This->sInfo.dwRate = This->lpOutFormat->nAvgBytesPerSec;
121
This->sInfo.dwQuality = (DWORD)ICQUALITY_DEFAULT;
122
SetRectEmpty(&This->sInfo.rcFrame);
123
124
/* convert positions and sizes to output format */
125
CONVERT_STREAM_to_THIS(&This->sInfo.dwStart);
126
CONVERT_STREAM_to_THIS(&This->sInfo.dwLength);
127
CONVERT_STREAM_to_THIS(&This->sInfo.dwSuggestedBufferSize);
128
129
return AVIERR_OK;
130
}
131
132
static inline IAVIStreamImpl *impl_from_IAVIStream(IAVIStream *iface)
133
{
134
return CONTAINING_RECORD(iface, IAVIStreamImpl, IAVIStream_iface);
135
}
136
137
static HRESULT WINAPI ACMStream_fnQueryInterface(IAVIStream *iface,
138
REFIID refiid, LPVOID *obj)
139
{
140
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
141
142
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(refiid), obj);
143
144
if (IsEqualGUID(&IID_IUnknown, refiid) ||
145
IsEqualGUID(&IID_IAVIStream, refiid)) {
146
*obj = &This->IAVIStream_iface;
147
IAVIStream_AddRef(iface);
148
149
return S_OK;
150
}
151
152
return OLE_E_ENUM_NOMORE;
153
}
154
155
static ULONG WINAPI ACMStream_fnAddRef(IAVIStream *iface)
156
{
157
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
158
ULONG ref = InterlockedIncrement(&This->ref);
159
160
TRACE("(%p) -> %ld\n", iface, ref);
161
162
/* also add reference to the nested stream */
163
if (This->pStream != NULL)
164
IAVIStream_AddRef(This->pStream);
165
166
return ref;
167
}
168
169
static ULONG WINAPI ACMStream_fnRelease(IAVIStream* iface)
170
{
171
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
172
ULONG ref = InterlockedDecrement(&This->ref);
173
174
TRACE("(%p) -> %ld\n", iface, ref);
175
176
if (ref == 0) {
177
/* destruct */
178
if (This->has != NULL) {
179
if (This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
180
acmStreamUnprepareHeader(This->has, &This->acmStreamHdr, 0);
181
acmStreamClose(This->has, 0);
182
This->has = NULL;
183
}
184
free(This->acmStreamHdr.pbSrc);
185
This->acmStreamHdr.pbSrc = NULL;
186
free(This->acmStreamHdr.pbDst);
187
This->acmStreamHdr.pbDst = NULL;
188
if (This->lpInFormat != NULL) {
189
free(This->lpInFormat);
190
This->lpInFormat = NULL;
191
This->cbInFormat = 0;
192
}
193
if (This->lpOutFormat != NULL) {
194
free(This->lpOutFormat);
195
This->lpOutFormat = NULL;
196
This->cbOutFormat = 0;
197
}
198
if (This->pStream != NULL) {
199
IAVIStream_Release(This->pStream);
200
This->pStream = NULL;
201
}
202
free(This);
203
204
return 0;
205
}
206
207
/* also release reference to the nested stream */
208
if (This->pStream != NULL)
209
IAVIStream_Release(This->pStream);
210
211
return ref;
212
}
213
214
/* lParam1: PAVISTREAM
215
* lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
216
*/
217
static HRESULT WINAPI ACMStream_fnCreate(IAVIStream *iface, LPARAM lParam1,
218
LPARAM lParam2)
219
{
220
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
221
222
TRACE("(%p,0x%08IX,0x%08IX)\n", iface, lParam1, lParam2);
223
224
/* check for swapped parameters */
225
if ((LPVOID)lParam1 != NULL &&
226
((LPAVICOMPRESSOPTIONS)lParam1)->fccType == streamtypeAUDIO) {
227
LPARAM tmp = lParam1;
228
229
lParam1 = lParam2;
230
lParam2 = tmp;
231
}
232
233
if ((LPVOID)lParam1 == NULL)
234
return AVIERR_BADPARAM;
235
236
IAVIStream_Info((PAVISTREAM)lParam1, &This->sInfo, sizeof(This->sInfo));
237
if (This->sInfo.fccType != streamtypeAUDIO)
238
return AVIERR_ERROR; /* error in registry or AVIMakeCompressedStream */
239
240
This->sInfo.fccHandler = 0; /* be paranoid */
241
242
/* FIXME: check ACM version? Which version does we need? */
243
244
if ((LPVOID)lParam2 != NULL) {
245
/* We only need the format from the compress-options */
246
if (((LPAVICOMPRESSOPTIONS)lParam2)->fccType == streamtypeAUDIO)
247
lParam2 = (LPARAM)((LPAVICOMPRESSOPTIONS)lParam2)->lpFormat;
248
249
if (((LPWAVEFORMATEX)lParam2)->wFormatTag != WAVE_FORMAT_PCM)
250
This->cbOutFormat = sizeof(WAVEFORMATEX) + ((LPWAVEFORMATEX)lParam2)->cbSize;
251
else
252
This->cbOutFormat = sizeof(WAVEFORMATEX);
253
254
This->lpOutFormat = malloc(This->cbOutFormat);
255
if (This->lpOutFormat == NULL)
256
return AVIERR_MEMORY;
257
258
memcpy(This->lpOutFormat, (LPVOID)lParam2, This->cbOutFormat);
259
} else {
260
This->lpOutFormat = NULL;
261
This->cbOutFormat = 0;
262
}
263
264
This->pStream = (PAVISTREAM)lParam1;
265
IAVIStream_AddRef(This->pStream);
266
267
return AVIERR_OK;
268
}
269
270
static HRESULT WINAPI ACMStream_fnInfo(IAVIStream *iface,LPAVISTREAMINFOW psi,
271
LONG size)
272
{
273
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
274
275
TRACE("(%p,%p,%ld)\n", iface, psi, size);
276
277
if (psi == NULL)
278
return AVIERR_BADPARAM;
279
if (size < 0)
280
return AVIERR_BADSIZE;
281
282
/* Need codec to correct some values in structure */
283
if (This->has == NULL) {
284
HRESULT hr = AVIFILE_OpenCompressor(This);
285
286
if (FAILED(hr))
287
return hr;
288
}
289
290
memcpy(psi, &This->sInfo, min(size, (LONG)sizeof(This->sInfo)));
291
292
if (size < (LONG)sizeof(This->sInfo))
293
return AVIERR_BUFFERTOOSMALL;
294
return AVIERR_OK;
295
}
296
297
static LONG WINAPI ACMStream_fnFindSample(IAVIStream *iface, LONG pos,
298
LONG flags)
299
{
300
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
301
302
TRACE("(%p,%ld,0x%08lX)\n",iface,pos,flags);
303
304
if (flags & FIND_FROM_START) {
305
pos = This->sInfo.dwStart;
306
flags &= ~(FIND_FROM_START|FIND_PREV);
307
flags |= FIND_NEXT;
308
}
309
310
/* convert pos from our 'space' to This->pStream's one */
311
CONVERT_THIS_to_STREAM(&pos);
312
313
/* ask stream */
314
pos = IAVIStream_FindSample(This->pStream, pos, flags);
315
316
if (pos != -1) {
317
/* convert pos back to our 'space' if it's no size or physical pos */
318
if ((flags & FIND_RET) == 0)
319
CONVERT_STREAM_to_THIS(&pos);
320
}
321
322
return pos;
323
}
324
325
static HRESULT WINAPI ACMStream_fnReadFormat(IAVIStream *iface, LONG pos,
326
LPVOID format, LONG *formatsize)
327
{
328
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
329
330
TRACE("(%p,%ld,%p,%p)\n", iface, pos, format, formatsize);
331
332
if (formatsize == NULL)
333
return AVIERR_BADPARAM;
334
335
if (This->has == NULL) {
336
HRESULT hr = AVIFILE_OpenCompressor(This);
337
338
if (FAILED(hr))
339
return hr;
340
}
341
342
/* only interested in needed buffersize? */
343
if (format == NULL || *formatsize <= 0) {
344
*formatsize = This->cbOutFormat;
345
346
return AVIERR_OK;
347
}
348
349
/* copy initial format (only as much as will fit) */
350
memcpy(format, This->lpOutFormat, min(*formatsize, This->cbOutFormat));
351
if (*formatsize < This->cbOutFormat) {
352
*formatsize = This->cbOutFormat;
353
return AVIERR_BUFFERTOOSMALL;
354
}
355
356
*formatsize = This->cbOutFormat;
357
return AVIERR_OK;
358
}
359
360
static HRESULT WINAPI ACMStream_fnSetFormat(IAVIStream *iface, LONG pos,
361
LPVOID format, LONG formatsize)
362
{
363
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
364
365
HRESULT hr;
366
367
TRACE("(%p,%ld,%p,%ld)\n", iface, pos, format, formatsize);
368
369
/* check parameters */
370
if (format == NULL || formatsize <= 0)
371
return AVIERR_BADPARAM;
372
373
/* Input format already known?
374
* Changing is unsupported, but be quiet if it's the same */
375
if (This->lpInFormat != NULL) {
376
if (This->cbInFormat != formatsize ||
377
memcmp(format, This->lpInFormat, formatsize) != 0)
378
return AVIERR_UNSUPPORTED;
379
380
return AVIERR_OK;
381
}
382
383
/* Does the nested stream support writing? */
384
if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
385
return AVIERR_READONLY;
386
387
This->lpInFormat = malloc(formatsize);
388
if (This->lpInFormat == NULL)
389
return AVIERR_MEMORY;
390
This->cbInFormat = formatsize;
391
memcpy(This->lpInFormat, format, formatsize);
392
393
/* initialize formats and get compressor */
394
hr = AVIFILE_OpenCompressor(This);
395
if (FAILED(hr))
396
return hr;
397
398
CONVERT_THIS_to_STREAM(&pos);
399
400
/* tell the nested stream the new format */
401
return IAVIStream_SetFormat(This->pStream, pos, This->lpOutFormat,
402
This->cbOutFormat);
403
}
404
405
static HRESULT WINAPI ACMStream_fnRead(IAVIStream *iface, LONG start,
406
LONG samples, LPVOID buffer,
407
LONG buffersize, LPLONG bytesread,
408
LPLONG samplesread)
409
{
410
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
411
412
HRESULT hr;
413
DWORD size;
414
415
TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface, start, samples, buffer,
416
buffersize, bytesread, samplesread);
417
418
/* clear return parameters if given */
419
if (bytesread != NULL)
420
*bytesread = 0;
421
if (samplesread != NULL)
422
*samplesread = 0;
423
424
/* Do we have our compressor? */
425
if (This->has == NULL) {
426
hr = AVIFILE_OpenCompressor(This);
427
428
if (FAILED(hr))
429
return hr;
430
}
431
432
/* only need to pass through? */
433
if (This->cbInFormat == This->cbOutFormat &&
434
memcmp(This->lpInFormat, This->lpOutFormat, This->cbInFormat) == 0) {
435
return IAVIStream_Read(This->pStream, start, samples, buffer, buffersize,
436
bytesread, samplesread);
437
}
438
439
/* read as much as fit? */
440
if (samples == -1)
441
samples = buffersize / This->lpOutFormat->nBlockAlign;
442
/* limit to buffersize */
443
if (samples * This->lpOutFormat->nBlockAlign > buffersize)
444
samples = buffersize / This->lpOutFormat->nBlockAlign;
445
446
/* only return needed size? */
447
if (buffer == NULL || buffersize <= 0 || samples == 0) {
448
if (bytesread == NULL && samplesread == NULL)
449
return AVIERR_BADPARAM;
450
451
if (bytesread != NULL)
452
*bytesread = samples * This->lpOutFormat->nBlockAlign;
453
if (samplesread != NULL)
454
*samplesread = samples;
455
456
return AVIERR_OK;
457
}
458
459
/* map our positions to pStream positions */
460
CONVERT_THIS_to_STREAM(&start);
461
462
/* our needed internal buffersize */
463
size = samples * This->lpInFormat->nBlockAlign;
464
465
/* Need to free destination buffer used for writing? */
466
if (This->acmStreamHdr.pbDst != NULL) {
467
free(This->acmStreamHdr.pbDst);
468
This->acmStreamHdr.pbDst = NULL;
469
This->acmStreamHdr.dwDstUser = 0;
470
}
471
472
/* need bigger source buffer? */
473
if (This->acmStreamHdr.pbSrc == NULL ||
474
This->acmStreamHdr.dwSrcUser < size) {
475
This->acmStreamHdr.pbSrc = realloc(This->acmStreamHdr.pbSrc, size);
476
if (This->acmStreamHdr.pbSrc == NULL)
477
return AVIERR_MEMORY;
478
This->acmStreamHdr.dwSrcUser = size;
479
}
480
481
This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
482
This->acmStreamHdr.cbSrcLengthUsed = 0;
483
This->acmStreamHdr.cbDstLengthUsed = 0;
484
This->acmStreamHdr.cbSrcLength = size;
485
486
/* read source data */
487
hr = IAVIStream_Read(This->pStream, start, -1, This->acmStreamHdr.pbSrc,
488
This->acmStreamHdr.cbSrcLength,
489
(LONG *)&This->acmStreamHdr.cbSrcLength, NULL);
490
if (FAILED(hr) || This->acmStreamHdr.cbSrcLength == 0)
491
return hr;
492
493
/* need to prepare stream? */
494
This->acmStreamHdr.pbDst = buffer;
495
This->acmStreamHdr.cbDstLength = buffersize;
496
if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
497
if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
498
This->acmStreamHdr.pbDst = NULL;
499
This->acmStreamHdr.cbDstLength = 0;
500
return AVIERR_COMPRESSOR;
501
}
502
}
503
504
/* now do the conversion */
505
/* FIXME: use ACM_CONVERTF_* flags */
506
if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
507
hr = AVIERR_COMPRESSOR;
508
509
This->acmStreamHdr.pbDst = NULL;
510
This->acmStreamHdr.cbDstLength = 0;
511
512
/* fill out return parameters if given */
513
if (bytesread != NULL)
514
*bytesread = This->acmStreamHdr.cbDstLengthUsed;
515
if (samplesread != NULL)
516
*samplesread =
517
This->acmStreamHdr.cbDstLengthUsed / This->lpOutFormat->nBlockAlign;
518
519
return hr;
520
}
521
522
static HRESULT WINAPI ACMStream_fnWrite(IAVIStream *iface, LONG start,
523
LONG samples, LPVOID buffer,
524
LONG buffersize, DWORD flags,
525
LPLONG sampwritten,
526
LPLONG byteswritten)
527
{
528
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
529
530
HRESULT hr;
531
ULONG size;
532
533
TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface, start, samples,
534
buffer, buffersize, flags, sampwritten, byteswritten);
535
536
/* clear return parameters if given */
537
if (sampwritten != NULL)
538
*sampwritten = 0;
539
if (byteswritten != NULL)
540
*byteswritten = 0;
541
542
/* check parameters */
543
if (buffer == NULL && (buffersize > 0 || samples > 0))
544
return AVIERR_BADPARAM;
545
546
/* Have we write capability? */
547
if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
548
return AVIERR_READONLY;
549
550
/* also need a compressor */
551
if (This->has == NULL)
552
return AVIERR_NOCOMPRESSOR;
553
554
/* map our sizes to pStream sizes */
555
size = buffersize;
556
CONVERT_THIS_to_STREAM(&size);
557
CONVERT_THIS_to_STREAM(&start);
558
559
/* no bytes to write? -- short circuit */
560
if (size == 0) {
561
return IAVIStream_Write(This->pStream, -1, samples, buffer, size,
562
flags, sampwritten, byteswritten);
563
}
564
565
/* Need to free source buffer used for reading? */
566
if (This->acmStreamHdr.pbSrc != NULL) {
567
free(This->acmStreamHdr.pbSrc);
568
This->acmStreamHdr.pbSrc = NULL;
569
This->acmStreamHdr.dwSrcUser = 0;
570
}
571
572
/* Need bigger destination buffer? */
573
if (This->acmStreamHdr.pbDst == NULL ||
574
This->acmStreamHdr.dwDstUser < size) {
575
This->acmStreamHdr.pbDst = realloc(This->acmStreamHdr.pbDst, size);
576
if (This->acmStreamHdr.pbDst == NULL)
577
return AVIERR_MEMORY;
578
This->acmStreamHdr.dwDstUser = size;
579
}
580
This->acmStreamHdr.cbStruct = sizeof(This->acmStreamHdr);
581
This->acmStreamHdr.cbSrcLengthUsed = 0;
582
This->acmStreamHdr.cbDstLengthUsed = 0;
583
This->acmStreamHdr.cbDstLength = This->acmStreamHdr.dwDstUser;
584
585
/* need to prepare stream? */
586
This->acmStreamHdr.pbSrc = buffer;
587
This->acmStreamHdr.cbSrcLength = buffersize;
588
if ((This->acmStreamHdr.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED) == 0) {
589
if (acmStreamPrepareHeader(This->has, &This->acmStreamHdr, 0) != S_OK) {
590
This->acmStreamHdr.pbSrc = NULL;
591
This->acmStreamHdr.cbSrcLength = 0;
592
return AVIERR_COMPRESSOR;
593
}
594
}
595
596
/* now do the conversion */
597
/* FIXME: use ACM_CONVERTF_* flags */
598
if (acmStreamConvert(This->has, &This->acmStreamHdr, 0) != S_OK)
599
hr = AVIERR_COMPRESSOR;
600
else
601
hr = AVIERR_OK;
602
603
This->acmStreamHdr.pbSrc = NULL;
604
This->acmStreamHdr.cbSrcLength = 0;
605
606
if (FAILED(hr))
607
return hr;
608
609
return IAVIStream_Write(This->pStream,-1,This->acmStreamHdr.cbDstLengthUsed /
610
This->lpOutFormat->nBlockAlign,This->acmStreamHdr.pbDst,
611
This->acmStreamHdr.cbDstLengthUsed,flags,sampwritten,
612
byteswritten);
613
}
614
615
static HRESULT WINAPI ACMStream_fnDelete(IAVIStream *iface, LONG start,
616
LONG samples)
617
{
618
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
619
620
TRACE("(%p,%ld,%ld)\n", iface, start, samples);
621
622
/* check parameters */
623
if (start < 0 || samples < 0)
624
return AVIERR_BADPARAM;
625
626
/* Delete before start of stream? */
627
if ((DWORD)(start + samples) < This->sInfo.dwStart)
628
return AVIERR_OK;
629
630
/* Delete after end of stream? */
631
if ((DWORD)start > This->sInfo.dwLength)
632
return AVIERR_OK;
633
634
/* For the rest we need write capability */
635
if ((This->sInfo.dwCaps & AVIFILECAPS_CANWRITE) == 0)
636
return AVIERR_READONLY;
637
638
/* A compressor is also necessary */
639
if (This->has == NULL)
640
return AVIERR_NOCOMPRESSOR;
641
642
/* map our positions to pStream positions */
643
CONVERT_THIS_to_STREAM(&start);
644
CONVERT_THIS_to_STREAM(&samples);
645
646
return IAVIStream_Delete(This->pStream, start, samples);
647
}
648
649
static HRESULT WINAPI ACMStream_fnReadData(IAVIStream *iface, DWORD fcc,
650
LPVOID lp, LPLONG lpread)
651
{
652
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
653
654
TRACE("(%p,0x%08lX,%p,%p)\n", iface, fcc, lp, lpread);
655
656
assert(This->pStream != NULL);
657
658
return IAVIStream_ReadData(This->pStream, fcc, lp, lpread);
659
}
660
661
static HRESULT WINAPI ACMStream_fnWriteData(IAVIStream *iface, DWORD fcc,
662
LPVOID lp, LONG size)
663
{
664
IAVIStreamImpl *This = impl_from_IAVIStream(iface);
665
666
TRACE("(%p,0x%08lx,%p,%ld)\n", iface, fcc, lp, size);
667
668
assert(This->pStream != NULL);
669
670
return IAVIStream_WriteData(This->pStream, fcc, lp, size);
671
}
672
673
static HRESULT WINAPI ACMStream_fnSetInfo(IAVIStream *iface,
674
LPAVISTREAMINFOW info, LONG infolen)
675
{
676
FIXME("(%p,%p,%ld): stub\n", iface, info, infolen);
677
678
return E_FAIL;
679
}
680
681
static const struct IAVIStreamVtbl iacmst = {
682
ACMStream_fnQueryInterface,
683
ACMStream_fnAddRef,
684
ACMStream_fnRelease,
685
ACMStream_fnCreate,
686
ACMStream_fnInfo,
687
ACMStream_fnFindSample,
688
ACMStream_fnReadFormat,
689
ACMStream_fnSetFormat,
690
ACMStream_fnRead,
691
ACMStream_fnWrite,
692
ACMStream_fnDelete,
693
ACMStream_fnReadData,
694
ACMStream_fnWriteData,
695
ACMStream_fnSetInfo
696
};
697
698
HRESULT AVIFILE_CreateACMStream(REFIID riid, LPVOID *ppv)
699
{
700
IAVIStreamImpl *pstream;
701
HRESULT hr;
702
703
assert(riid != NULL && ppv != NULL);
704
705
*ppv = NULL;
706
707
pstream = calloc(1, sizeof(IAVIStreamImpl));
708
if (pstream == NULL)
709
return AVIERR_MEMORY;
710
711
pstream->IAVIStream_iface.lpVtbl = &iacmst;
712
713
hr = IAVIStream_QueryInterface(&pstream->IAVIStream_iface, riid, ppv);
714
if (FAILED(hr))
715
free(pstream);
716
717
return hr;
718
}
719
720