2 * Copyright 2002 Michael Günnewig
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.
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.
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
31 #include "avifile_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
37 /***********************************************************************/
39 typedef struct _IAVIStreamImpl
{
41 IAVIStream IAVIStream_iface
;
44 /* IAVIStream stuff */
50 LPWAVEFORMATEX lpInFormat
;
53 LPWAVEFORMATEX lpOutFormat
;
56 ACMSTREAMHEADER acmStreamHdr
;
59 /***********************************************************************/
61 #define CONVERT_STREAM_to_THIS(a) do { \
63 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
64 &__bytes, ACM_STREAMSIZEF_SOURCE); \
65 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
67 #define CONVERT_THIS_to_STREAM(a) do { \
69 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
70 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
71 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
73 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
)
79 assert(This
->pStream
!= NULL
);
81 if (This
->has
!= NULL
)
84 if (This
->lpInFormat
== NULL
) {
85 /* decode or encode the data from pStream */
86 hr
= AVIStreamFormatSize(This
->pStream
, This
->sInfo
.dwStart
, &This
->cbInFormat
);
89 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbInFormat
);
90 if (This
->lpInFormat
== NULL
)
93 hr
= IAVIStream_ReadFormat(This
->pStream
, This
->sInfo
.dwStart
,
94 This
->lpInFormat
, &This
->cbInFormat
);
98 if (This
->lpOutFormat
== NULL
) {
99 /* we must decode to default format */
100 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
101 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
102 if (This
->lpOutFormat
== NULL
)
103 return AVIERR_MEMORY
;
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
;
110 } else if (This
->lpOutFormat
== NULL
)
111 return AVIERR_ERROR
; /* To what should I encode? */
113 if (acmStreamOpen(&This
->has
, NULL
, This
->lpInFormat
, This
->lpOutFormat
,
114 NULL
, 0, 0, ACM_STREAMOPENF_NONREALTIME
) != S_OK
)
115 return AVIERR_NOCOMPRESSOR
;
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
);
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
);
132 static inline IAVIStreamImpl
*impl_from_IAVIStream(IAVIStream
*iface
)
134 return CONTAINING_RECORD(iface
, IAVIStreamImpl
, IAVIStream_iface
);
137 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,
138 REFIID refiid
, LPVOID
*obj
)
140 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
142 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(refiid
), obj
);
144 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
145 IsEqualGUID(&IID_IAVIStream
, refiid
)) {
146 *obj
= &This
->IAVIStream_iface
;
147 IAVIStream_AddRef(iface
);
152 return OLE_E_ENUM_NOMORE
;
155 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
)
157 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
158 ULONG ref
= InterlockedIncrement(&This
->ref
);
160 TRACE("(%p) -> %d\n", iface
, ref
);
162 /* also add reference to the nested stream */
163 if (This
->pStream
!= NULL
)
164 IAVIStream_AddRef(This
->pStream
);
169 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
)
171 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
172 ULONG ref
= InterlockedDecrement(&This
->ref
);
174 TRACE("(%p) -> %d\n", iface
, ref
);
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);
184 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
185 This
->acmStreamHdr
.pbSrc
= NULL
;
186 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
187 This
->acmStreamHdr
.pbDst
= NULL
;
188 if (This
->lpInFormat
!= NULL
) {
189 HeapFree(GetProcessHeap(), 0, This
->lpInFormat
);
190 This
->lpInFormat
= NULL
;
191 This
->cbInFormat
= 0;
193 if (This
->lpOutFormat
!= NULL
) {
194 HeapFree(GetProcessHeap(), 0, This
->lpOutFormat
);
195 This
->lpOutFormat
= NULL
;
196 This
->cbOutFormat
= 0;
198 if (This
->pStream
!= NULL
) {
199 IAVIStream_Release(This
->pStream
);
200 This
->pStream
= NULL
;
202 HeapFree(GetProcessHeap(), 0, This
);
207 /* also release reference to the nested stream */
208 if (This
->pStream
!= NULL
)
209 IAVIStream_Release(This
->pStream
);
214 /* lParam1: PAVISTREAM
215 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
217 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
, LPARAM lParam1
,
220 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
222 TRACE("(%p,0x%08lX,0x%08lX)\n", iface
, lParam1
, lParam2
);
224 /* check for swapped parameters */
225 if ((LPVOID
)lParam1
!= NULL
&&
226 ((LPAVICOMPRESSOPTIONS
)lParam1
)->fccType
== streamtypeAUDIO
) {
227 LPARAM tmp
= lParam1
;
233 if ((LPVOID
)lParam1
== NULL
)
234 return AVIERR_BADPARAM
;
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 */
240 This
->sInfo
.fccHandler
= 0; /* be paranoid */
242 /* FIXME: check ACM version? Which version does we need? */
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
;
249 if (((LPWAVEFORMATEX
)lParam2
)->wFormatTag
!= WAVE_FORMAT_PCM
)
250 This
->cbOutFormat
= sizeof(WAVEFORMATEX
) + ((LPWAVEFORMATEX
)lParam2
)->cbSize
;
252 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
254 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
255 if (This
->lpOutFormat
== NULL
)
256 return AVIERR_MEMORY
;
258 memcpy(This
->lpOutFormat
, (LPVOID
)lParam2
, This
->cbOutFormat
);
260 This
->lpOutFormat
= NULL
;
261 This
->cbOutFormat
= 0;
264 This
->pStream
= (PAVISTREAM
)lParam1
;
265 IAVIStream_AddRef(This
->pStream
);
270 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,LPAVISTREAMINFOW psi
,
273 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
275 TRACE("(%p,%p,%d)\n", iface
, psi
, size
);
278 return AVIERR_BADPARAM
;
280 return AVIERR_BADSIZE
;
282 /* Need codec to correct some values in structure */
283 if (This
->has
== NULL
) {
284 HRESULT hr
= AVIFILE_OpenCompressor(This
);
290 memcpy(psi
, &This
->sInfo
, min(size
, (LONG
)sizeof(This
->sInfo
)));
292 if (size
< (LONG
)sizeof(This
->sInfo
))
293 return AVIERR_BUFFERTOOSMALL
;
297 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
, LONG pos
,
300 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
302 TRACE("(%p,%d,0x%08X)\n",iface
,pos
,flags
);
304 if (flags
& FIND_FROM_START
) {
305 pos
= This
->sInfo
.dwStart
;
306 flags
&= ~(FIND_FROM_START
|FIND_PREV
);
310 /* convert pos from our 'space' to This->pStream's one */
311 CONVERT_THIS_to_STREAM(&pos
);
314 pos
= IAVIStream_FindSample(This
->pStream
, pos
, flags
);
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
);
325 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
, LONG pos
,
326 LPVOID format
, LONG
*formatsize
)
328 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
330 TRACE("(%p,%d,%p,%p)\n", iface
, pos
, format
, formatsize
);
332 if (formatsize
== NULL
)
333 return AVIERR_BADPARAM
;
335 if (This
->has
== NULL
) {
336 HRESULT hr
= AVIFILE_OpenCompressor(This
);
342 /* only interested in needed buffersize? */
343 if (format
== NULL
|| *formatsize
<= 0) {
344 *formatsize
= This
->cbOutFormat
;
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
;
356 *formatsize
= This
->cbOutFormat
;
360 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
, LONG pos
,
361 LPVOID format
, LONG formatsize
)
363 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
367 TRACE("(%p,%d,%p,%d)\n", iface
, pos
, format
, formatsize
);
369 /* check parameters */
370 if (format
== NULL
|| formatsize
<= 0)
371 return AVIERR_BADPARAM
;
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
;
383 /* Does the nested stream support writing? */
384 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
385 return AVIERR_READONLY
;
387 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, formatsize
);
388 if (This
->lpInFormat
== NULL
)
389 return AVIERR_MEMORY
;
390 This
->cbInFormat
= formatsize
;
391 memcpy(This
->lpInFormat
, format
, formatsize
);
393 /* initialize formats and get compressor */
394 hr
= AVIFILE_OpenCompressor(This
);
398 CONVERT_THIS_to_STREAM(&pos
);
400 /* tell the nested stream the new format */
401 return IAVIStream_SetFormat(This
->pStream
, pos
, This
->lpOutFormat
,
405 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
, LONG start
,
406 LONG samples
, LPVOID buffer
,
407 LONG buffersize
, LPLONG bytesread
,
410 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
415 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface
, start
, samples
, buffer
,
416 buffersize
, bytesread
, samplesread
);
418 /* clear return parameters if given */
419 if (bytesread
!= NULL
)
421 if (samplesread
!= NULL
)
424 /* Do we have our compressor? */
425 if (This
->has
== NULL
) {
426 hr
= AVIFILE_OpenCompressor(This
);
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
);
439 /* read as much as fit? */
441 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
442 /* limit to buffersize */
443 if (samples
* This
->lpOutFormat
->nBlockAlign
> buffersize
)
444 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
446 /* only return needed size? */
447 if (buffer
== NULL
|| buffersize
<= 0 || samples
== 0) {
448 if (bytesread
== NULL
&& samplesread
== NULL
)
449 return AVIERR_BADPARAM
;
451 if (bytesread
!= NULL
)
452 *bytesread
= samples
* This
->lpOutFormat
->nBlockAlign
;
453 if (samplesread
!= NULL
)
454 *samplesread
= samples
;
459 /* map our positions to pStream positions */
460 CONVERT_THIS_to_STREAM(&start
);
462 /* our needed internal buffersize */
463 size
= samples
* This
->lpInFormat
->nBlockAlign
;
465 /* Need to free destination buffer used for writing? */
466 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
467 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
468 This
->acmStreamHdr
.pbDst
= NULL
;
469 This
->acmStreamHdr
.dwDstUser
= 0;
472 /* need bigger source buffer? */
473 if (This
->acmStreamHdr
.pbSrc
== NULL
||
474 This
->acmStreamHdr
.dwSrcUser
< size
) {
475 if (This
->acmStreamHdr
.pbSrc
== NULL
)
476 This
->acmStreamHdr
.pbSrc
= HeapAlloc(GetProcessHeap(), 0, size
);
478 This
->acmStreamHdr
.pbSrc
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
, size
);
479 if (This
->acmStreamHdr
.pbSrc
== NULL
)
480 return AVIERR_MEMORY
;
481 This
->acmStreamHdr
.dwSrcUser
= size
;
484 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
485 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
486 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
487 This
->acmStreamHdr
.cbSrcLength
= size
;
489 /* read source data */
490 hr
= IAVIStream_Read(This
->pStream
, start
, -1, This
->acmStreamHdr
.pbSrc
,
491 This
->acmStreamHdr
.cbSrcLength
,
492 (LONG
*)&This
->acmStreamHdr
.cbSrcLength
, NULL
);
493 if (FAILED(hr
) || This
->acmStreamHdr
.cbSrcLength
== 0)
496 /* need to prepare stream? */
497 This
->acmStreamHdr
.pbDst
= buffer
;
498 This
->acmStreamHdr
.cbDstLength
= buffersize
;
499 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
500 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
501 This
->acmStreamHdr
.pbDst
= NULL
;
502 This
->acmStreamHdr
.cbDstLength
= 0;
503 return AVIERR_COMPRESSOR
;
507 /* now do the conversion */
508 /* FIXME: use ACM_CONVERTF_* flags */
509 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
510 hr
= AVIERR_COMPRESSOR
;
512 This
->acmStreamHdr
.pbDst
= NULL
;
513 This
->acmStreamHdr
.cbDstLength
= 0;
515 /* fill out return parameters if given */
516 if (bytesread
!= NULL
)
517 *bytesread
= This
->acmStreamHdr
.cbDstLengthUsed
;
518 if (samplesread
!= NULL
)
520 This
->acmStreamHdr
.cbDstLengthUsed
/ This
->lpOutFormat
->nBlockAlign
;
525 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
, LONG start
,
526 LONG samples
, LPVOID buffer
,
527 LONG buffersize
, DWORD flags
,
531 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
536 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface
, start
, samples
,
537 buffer
, buffersize
, flags
, sampwritten
, byteswritten
);
539 /* clear return parameters if given */
540 if (sampwritten
!= NULL
)
542 if (byteswritten
!= NULL
)
545 /* check parameters */
546 if (buffer
== NULL
&& (buffersize
> 0 || samples
> 0))
547 return AVIERR_BADPARAM
;
549 /* Have we write capability? */
550 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
551 return AVIERR_READONLY
;
553 /* also need a compressor */
554 if (This
->has
== NULL
)
555 return AVIERR_NOCOMPRESSOR
;
557 /* map our sizes to pStream sizes */
559 CONVERT_THIS_to_STREAM(&size
);
560 CONVERT_THIS_to_STREAM(&start
);
562 /* no bytes to write? -- short circuit */
564 return IAVIStream_Write(This
->pStream
, -1, samples
, buffer
, size
,
565 flags
, sampwritten
, byteswritten
);
568 /* Need to free source buffer used for reading? */
569 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
570 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
571 This
->acmStreamHdr
.pbSrc
= NULL
;
572 This
->acmStreamHdr
.dwSrcUser
= 0;
575 /* Need bigger destination buffer? */
576 if (This
->acmStreamHdr
.pbDst
== NULL
||
577 This
->acmStreamHdr
.dwDstUser
< size
) {
578 if (This
->acmStreamHdr
.pbDst
== NULL
)
579 This
->acmStreamHdr
.pbDst
= HeapAlloc(GetProcessHeap(), 0, size
);
581 This
->acmStreamHdr
.pbDst
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
, size
);
582 if (This
->acmStreamHdr
.pbDst
== NULL
)
583 return AVIERR_MEMORY
;
584 This
->acmStreamHdr
.dwDstUser
= size
;
586 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
587 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
588 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
589 This
->acmStreamHdr
.cbDstLength
= This
->acmStreamHdr
.dwDstUser
;
591 /* need to prepare stream? */
592 This
->acmStreamHdr
.pbSrc
= buffer
;
593 This
->acmStreamHdr
.cbSrcLength
= buffersize
;
594 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
595 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
596 This
->acmStreamHdr
.pbSrc
= NULL
;
597 This
->acmStreamHdr
.cbSrcLength
= 0;
598 return AVIERR_COMPRESSOR
;
602 /* now do the conversion */
603 /* FIXME: use ACM_CONVERTF_* flags */
604 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
605 hr
= AVIERR_COMPRESSOR
;
609 This
->acmStreamHdr
.pbSrc
= NULL
;
610 This
->acmStreamHdr
.cbSrcLength
= 0;
615 return IAVIStream_Write(This
->pStream
,-1,This
->acmStreamHdr
.cbDstLengthUsed
/
616 This
->lpOutFormat
->nBlockAlign
,This
->acmStreamHdr
.pbDst
,
617 This
->acmStreamHdr
.cbDstLengthUsed
,flags
,sampwritten
,
621 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
, LONG start
,
624 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
626 TRACE("(%p,%d,%d)\n", iface
, start
, samples
);
628 /* check parameters */
629 if (start
< 0 || samples
< 0)
630 return AVIERR_BADPARAM
;
632 /* Delete before start of stream? */
633 if ((DWORD
)(start
+ samples
) < This
->sInfo
.dwStart
)
636 /* Delete after end of stream? */
637 if ((DWORD
)start
> This
->sInfo
.dwLength
)
640 /* For the rest we need write capability */
641 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
642 return AVIERR_READONLY
;
644 /* A compressor is also necessary */
645 if (This
->has
== NULL
)
646 return AVIERR_NOCOMPRESSOR
;
648 /* map our positions to pStream positions */
649 CONVERT_THIS_to_STREAM(&start
);
650 CONVERT_THIS_to_STREAM(&samples
);
652 return IAVIStream_Delete(This
->pStream
, start
, samples
);
655 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
, DWORD fcc
,
656 LPVOID lp
, LPLONG lpread
)
658 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
660 TRACE("(%p,0x%08X,%p,%p)\n", iface
, fcc
, lp
, lpread
);
662 assert(This
->pStream
!= NULL
);
664 return IAVIStream_ReadData(This
->pStream
, fcc
, lp
, lpread
);
667 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
, DWORD fcc
,
668 LPVOID lp
, LONG size
)
670 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
672 TRACE("(%p,0x%08x,%p,%d)\n", iface
, fcc
, lp
, size
);
674 assert(This
->pStream
!= NULL
);
676 return IAVIStream_WriteData(This
->pStream
, fcc
, lp
, size
);
679 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,
680 LPAVISTREAMINFOW info
, LONG infolen
)
682 FIXME("(%p,%p,%d): stub\n", iface
, info
, infolen
);
687 static const struct IAVIStreamVtbl iacmst
= {
688 ACMStream_fnQueryInterface
,
693 ACMStream_fnFindSample
,
694 ACMStream_fnReadFormat
,
695 ACMStream_fnSetFormat
,
699 ACMStream_fnReadData
,
700 ACMStream_fnWriteData
,
704 HRESULT
AVIFILE_CreateACMStream(REFIID riid
, LPVOID
*ppv
)
706 IAVIStreamImpl
*pstream
;
709 assert(riid
!= NULL
&& ppv
!= NULL
);
713 pstream
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAVIStreamImpl
));
715 return AVIERR_MEMORY
;
717 pstream
->IAVIStream_iface
.lpVtbl
= &iacmst
;
719 hr
= IAVIStream_QueryInterface(&pstream
->IAVIStream_iface
, riid
, ppv
);
721 HeapFree(GetProcessHeap(), 0, pstream
);