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
19 #define WIN32_NO_STATUS
21 #define COM_NO_WINDOWS_H
29 //#include "winuser.h"
30 //#include "winerror.h"
31 //#include "mmsystem.h"
35 //#include "avifile_private.h"
37 #include <wine/debug.h>
39 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
41 /***********************************************************************/
43 typedef struct _IAVIStreamImpl
{
45 IAVIStream IAVIStream_iface
;
48 /* IAVIStream stuff */
54 LPWAVEFORMATEX lpInFormat
;
57 LPWAVEFORMATEX lpOutFormat
;
60 ACMSTREAMHEADER acmStreamHdr
;
63 /***********************************************************************/
65 #define CONVERT_STREAM_to_THIS(a) do { \
67 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
68 &__bytes, ACM_STREAMSIZEF_SOURCE); \
69 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
71 #define CONVERT_THIS_to_STREAM(a) do { \
73 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
74 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
75 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
77 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
)
83 assert(This
->pStream
!= NULL
);
85 if (This
->has
!= NULL
)
88 if (This
->lpInFormat
== NULL
) {
89 /* decode or encode the data from pStream */
90 hr
= AVIStreamFormatSize(This
->pStream
, This
->sInfo
.dwStart
, &This
->cbInFormat
);
93 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbInFormat
);
94 if (This
->lpInFormat
== NULL
)
97 hr
= IAVIStream_ReadFormat(This
->pStream
, This
->sInfo
.dwStart
,
98 This
->lpInFormat
, &This
->cbInFormat
);
102 if (This
->lpOutFormat
== NULL
) {
103 /* we must decode to default format */
104 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
105 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
106 if (This
->lpOutFormat
== NULL
)
107 return AVIERR_MEMORY
;
109 This
->lpOutFormat
->wFormatTag
= WAVE_FORMAT_PCM
;
110 if (acmFormatSuggest(NULL
, This
->lpInFormat
, This
->lpOutFormat
,
111 This
->cbOutFormat
, ACM_FORMATSUGGESTF_WFORMATTAG
) != S_OK
)
112 return AVIERR_NOCOMPRESSOR
;
114 } else if (This
->lpOutFormat
== NULL
)
115 return AVIERR_ERROR
; /* To what should I encode? */
117 if (acmStreamOpen(&This
->has
, NULL
, This
->lpInFormat
, This
->lpOutFormat
,
118 NULL
, 0, 0, ACM_STREAMOPENF_NONREALTIME
) != S_OK
)
119 return AVIERR_NOCOMPRESSOR
;
121 /* update AVISTREAMINFO structure */
122 This
->sInfo
.dwSampleSize
= This
->lpOutFormat
->nBlockAlign
;
123 This
->sInfo
.dwScale
= This
->lpOutFormat
->nBlockAlign
;
124 This
->sInfo
.dwRate
= This
->lpOutFormat
->nAvgBytesPerSec
;
125 This
->sInfo
.dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
126 SetRectEmpty(&This
->sInfo
.rcFrame
);
128 /* convert positions and sizes to output format */
129 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwStart
);
130 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwLength
);
131 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwSuggestedBufferSize
);
136 static inline IAVIStreamImpl
*impl_from_IAVIStream(IAVIStream
*iface
)
138 return CONTAINING_RECORD(iface
, IAVIStreamImpl
, IAVIStream_iface
);
141 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,
142 REFIID refiid
, LPVOID
*obj
)
144 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
146 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(refiid
), obj
);
148 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
149 IsEqualGUID(&IID_IAVIStream
, refiid
)) {
151 IAVIStream_AddRef(iface
);
156 return OLE_E_ENUM_NOMORE
;
159 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
)
161 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
162 ULONG ref
= InterlockedIncrement(&This
->ref
);
164 TRACE("(%p) -> %d\n", iface
, ref
);
166 /* also add reference to the nested stream */
167 if (This
->pStream
!= NULL
)
168 IAVIStream_AddRef(This
->pStream
);
173 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
)
175 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
176 ULONG ref
= InterlockedDecrement(&This
->ref
);
178 TRACE("(%p) -> %d\n", iface
, ref
);
182 if (This
->has
!= NULL
) {
183 if (This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
)
184 acmStreamUnprepareHeader(This
->has
, &This
->acmStreamHdr
, 0);
185 acmStreamClose(This
->has
, 0);
188 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
189 This
->acmStreamHdr
.pbSrc
= NULL
;
190 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
191 This
->acmStreamHdr
.pbDst
= NULL
;
192 if (This
->lpInFormat
!= NULL
) {
193 HeapFree(GetProcessHeap(), 0, This
->lpInFormat
);
194 This
->lpInFormat
= NULL
;
195 This
->cbInFormat
= 0;
197 if (This
->lpOutFormat
!= NULL
) {
198 HeapFree(GetProcessHeap(), 0, This
->lpOutFormat
);
199 This
->lpOutFormat
= NULL
;
200 This
->cbOutFormat
= 0;
202 if (This
->pStream
!= NULL
) {
203 IAVIStream_Release(This
->pStream
);
204 This
->pStream
= NULL
;
206 HeapFree(GetProcessHeap(), 0, This
);
211 /* also release reference to the nested stream */
212 if (This
->pStream
!= NULL
)
213 IAVIStream_Release(This
->pStream
);
218 /* lParam1: PAVISTREAM
219 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
221 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
, LPARAM lParam1
,
224 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
226 TRACE("(%p,0x%08lX,0x%08lX)\n", iface
, lParam1
, lParam2
);
228 /* check for swapped parameters */
229 if ((LPVOID
)lParam1
!= NULL
&&
230 ((LPAVICOMPRESSOPTIONS
)lParam1
)->fccType
== streamtypeAUDIO
) {
231 register LPARAM tmp
= lParam1
;
237 if ((LPVOID
)lParam1
== NULL
)
238 return AVIERR_BADPARAM
;
240 IAVIStream_Info((PAVISTREAM
)lParam1
, &This
->sInfo
, sizeof(This
->sInfo
));
241 if (This
->sInfo
.fccType
!= streamtypeAUDIO
)
242 return AVIERR_ERROR
; /* error in registry or AVIMakeCompressedStream */
244 This
->sInfo
.fccHandler
= 0; /* be paranoid */
246 /* FIXME: check ACM version? Which version does we need? */
248 if ((LPVOID
)lParam2
!= NULL
) {
249 /* We only need the format from the compress-options */
250 if (((LPAVICOMPRESSOPTIONS
)lParam2
)->fccType
== streamtypeAUDIO
)
251 lParam2
= (LPARAM
)((LPAVICOMPRESSOPTIONS
)lParam2
)->lpFormat
;
253 if (((LPWAVEFORMATEX
)lParam2
)->wFormatTag
!= WAVE_FORMAT_PCM
)
254 This
->cbOutFormat
= sizeof(WAVEFORMATEX
) + ((LPWAVEFORMATEX
)lParam2
)->cbSize
;
256 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
258 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
259 if (This
->lpOutFormat
== NULL
)
260 return AVIERR_MEMORY
;
262 memcpy(This
->lpOutFormat
, (LPVOID
)lParam2
, This
->cbOutFormat
);
264 This
->lpOutFormat
= NULL
;
265 This
->cbOutFormat
= 0;
268 This
->pStream
= (PAVISTREAM
)lParam1
;
269 IAVIStream_AddRef(This
->pStream
);
274 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,LPAVISTREAMINFOW psi
,
277 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
279 TRACE("(%p,%p,%d)\n", iface
, psi
, size
);
282 return AVIERR_BADPARAM
;
284 return AVIERR_BADSIZE
;
286 /* Need codec to correct some values in structure */
287 if (This
->has
== NULL
) {
288 HRESULT hr
= AVIFILE_OpenCompressor(This
);
294 memcpy(psi
, &This
->sInfo
, min(size
, (LONG
)sizeof(This
->sInfo
)));
296 if (size
< (LONG
)sizeof(This
->sInfo
))
297 return AVIERR_BUFFERTOOSMALL
;
301 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
, LONG pos
,
304 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
306 TRACE("(%p,%d,0x%08X)\n",iface
,pos
,flags
);
308 if (flags
& FIND_FROM_START
) {
309 pos
= This
->sInfo
.dwStart
;
310 flags
&= ~(FIND_FROM_START
|FIND_PREV
);
314 /* convert pos from our 'space' to This->pStream's one */
315 CONVERT_THIS_to_STREAM(&pos
);
318 pos
= IAVIStream_FindSample(This
->pStream
, pos
, flags
);
321 /* convert pos back to our 'space' if it's no size or physical pos */
322 if ((flags
& FIND_RET
) == 0)
323 CONVERT_STREAM_to_THIS(&pos
);
329 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
, LONG pos
,
330 LPVOID format
, LONG
*formatsize
)
332 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
334 TRACE("(%p,%d,%p,%p)\n", iface
, pos
, format
, formatsize
);
336 if (formatsize
== NULL
)
337 return AVIERR_BADPARAM
;
339 if (This
->has
== NULL
) {
340 HRESULT hr
= AVIFILE_OpenCompressor(This
);
346 /* only interested in needed buffersize? */
347 if (format
== NULL
|| *formatsize
<= 0) {
348 *formatsize
= This
->cbOutFormat
;
353 /* copy initial format (only as much as will fit) */
354 memcpy(format
, This
->lpOutFormat
, min(*formatsize
, This
->cbOutFormat
));
355 if (*formatsize
< This
->cbOutFormat
) {
356 *formatsize
= This
->cbOutFormat
;
357 return AVIERR_BUFFERTOOSMALL
;
360 *formatsize
= This
->cbOutFormat
;
364 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
, LONG pos
,
365 LPVOID format
, LONG formatsize
)
367 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
371 TRACE("(%p,%d,%p,%d)\n", iface
, pos
, format
, formatsize
);
373 /* check parameters */
374 if (format
== NULL
|| formatsize
<= 0)
375 return AVIERR_BADPARAM
;
377 /* Input format already known?
378 * Changing is unsupported, but be quiet if it's the same */
379 if (This
->lpInFormat
!= NULL
) {
380 if (This
->cbInFormat
!= formatsize
||
381 memcmp(format
, This
->lpInFormat
, formatsize
) != 0)
382 return AVIERR_UNSUPPORTED
;
387 /* Does the nested stream support writing? */
388 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
389 return AVIERR_READONLY
;
391 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, formatsize
);
392 if (This
->lpInFormat
== NULL
)
393 return AVIERR_MEMORY
;
394 This
->cbInFormat
= formatsize
;
395 memcpy(This
->lpInFormat
, format
, formatsize
);
397 /* initialize formats and get compressor */
398 hr
= AVIFILE_OpenCompressor(This
);
402 CONVERT_THIS_to_STREAM(&pos
);
404 /* tell the nested stream the new format */
405 return IAVIStream_SetFormat(This
->pStream
, pos
, This
->lpOutFormat
,
409 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
, LONG start
,
410 LONG samples
, LPVOID buffer
,
411 LONG buffersize
, LPLONG bytesread
,
414 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
419 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface
, start
, samples
, buffer
,
420 buffersize
, bytesread
, samplesread
);
422 /* clear return parameters if given */
423 if (bytesread
!= NULL
)
425 if (samplesread
!= NULL
)
428 /* Do we have our compressor? */
429 if (This
->has
== NULL
) {
430 hr
= AVIFILE_OpenCompressor(This
);
436 /* only need to pass through? */
437 if (This
->cbInFormat
== This
->cbOutFormat
&&
438 memcmp(This
->lpInFormat
, This
->lpOutFormat
, This
->cbInFormat
) == 0) {
439 return IAVIStream_Read(This
->pStream
, start
, samples
, buffer
, buffersize
,
440 bytesread
, samplesread
);
443 /* read as much as fit? */
445 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
446 /* limit to buffersize */
447 if (samples
* This
->lpOutFormat
->nBlockAlign
> buffersize
)
448 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
450 /* only return needed size? */
451 if (buffer
== NULL
|| buffersize
<= 0 || samples
== 0) {
452 if (bytesread
== NULL
&& samplesread
== NULL
)
453 return AVIERR_BADPARAM
;
455 if (bytesread
!= NULL
)
456 *bytesread
= samples
* This
->lpOutFormat
->nBlockAlign
;
457 if (samplesread
!= NULL
)
458 *samplesread
= samples
;
463 /* map our positions to pStream positions */
464 CONVERT_THIS_to_STREAM(&start
);
466 /* our needed internal buffersize */
467 size
= samples
* This
->lpInFormat
->nBlockAlign
;
469 /* Need to free destination buffer used for writing? */
470 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
471 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
472 This
->acmStreamHdr
.pbDst
= NULL
;
473 This
->acmStreamHdr
.dwDstUser
= 0;
476 /* need bigger source buffer? */
477 if (This
->acmStreamHdr
.pbSrc
== NULL
||
478 This
->acmStreamHdr
.dwSrcUser
< size
) {
479 if (This
->acmStreamHdr
.pbSrc
== NULL
)
480 This
->acmStreamHdr
.pbSrc
= HeapAlloc(GetProcessHeap(), 0, size
);
482 This
->acmStreamHdr
.pbSrc
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
, size
);
483 if (This
->acmStreamHdr
.pbSrc
== NULL
)
484 return AVIERR_MEMORY
;
485 This
->acmStreamHdr
.dwSrcUser
= size
;
488 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
489 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
490 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
491 This
->acmStreamHdr
.cbSrcLength
= size
;
493 /* read source data */
494 hr
= IAVIStream_Read(This
->pStream
, start
, -1, This
->acmStreamHdr
.pbSrc
,
495 This
->acmStreamHdr
.cbSrcLength
,
496 (LONG
*)&This
->acmStreamHdr
.cbSrcLength
, NULL
);
497 if (FAILED(hr
) || This
->acmStreamHdr
.cbSrcLength
== 0)
500 /* need to prepare stream? */
501 This
->acmStreamHdr
.pbDst
= buffer
;
502 This
->acmStreamHdr
.cbDstLength
= buffersize
;
503 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
504 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
505 This
->acmStreamHdr
.pbDst
= NULL
;
506 This
->acmStreamHdr
.cbDstLength
= 0;
507 return AVIERR_COMPRESSOR
;
511 /* now do the conversion */
512 /* FIXME: use ACM_CONVERTF_* flags */
513 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
514 hr
= AVIERR_COMPRESSOR
;
516 This
->acmStreamHdr
.pbDst
= NULL
;
517 This
->acmStreamHdr
.cbDstLength
= 0;
519 /* fill out return parameters if given */
520 if (bytesread
!= NULL
)
521 *bytesread
= This
->acmStreamHdr
.cbDstLengthUsed
;
522 if (samplesread
!= NULL
)
524 This
->acmStreamHdr
.cbDstLengthUsed
/ This
->lpOutFormat
->nBlockAlign
;
529 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
, LONG start
,
530 LONG samples
, LPVOID buffer
,
531 LONG buffersize
, DWORD flags
,
535 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
540 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface
, start
, samples
,
541 buffer
, buffersize
, flags
, sampwritten
, byteswritten
);
543 /* clear return parameters if given */
544 if (sampwritten
!= NULL
)
546 if (byteswritten
!= NULL
)
549 /* check parameters */
550 if (buffer
== NULL
&& (buffersize
> 0 || samples
> 0))
551 return AVIERR_BADPARAM
;
553 /* Have we write capability? */
554 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
555 return AVIERR_READONLY
;
557 /* also need a compressor */
558 if (This
->has
== NULL
)
559 return AVIERR_NOCOMPRESSOR
;
561 /* map our sizes to pStream sizes */
563 CONVERT_THIS_to_STREAM(&size
);
564 CONVERT_THIS_to_STREAM(&start
);
566 /* no bytes to write? -- short circuit */
568 return IAVIStream_Write(This
->pStream
, -1, samples
, buffer
, size
,
569 flags
, sampwritten
, byteswritten
);
572 /* Need to free source buffer used for reading? */
573 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
574 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
575 This
->acmStreamHdr
.pbSrc
= NULL
;
576 This
->acmStreamHdr
.dwSrcUser
= 0;
579 /* Need bigger destination buffer? */
580 if (This
->acmStreamHdr
.pbDst
== NULL
||
581 This
->acmStreamHdr
.dwDstUser
< size
) {
582 if (This
->acmStreamHdr
.pbDst
== NULL
)
583 This
->acmStreamHdr
.pbDst
= HeapAlloc(GetProcessHeap(), 0, size
);
585 This
->acmStreamHdr
.pbDst
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
, size
);
586 if (This
->acmStreamHdr
.pbDst
== NULL
)
587 return AVIERR_MEMORY
;
588 This
->acmStreamHdr
.dwDstUser
= size
;
590 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
591 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
592 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
593 This
->acmStreamHdr
.cbDstLength
= This
->acmStreamHdr
.dwDstUser
;
595 /* need to prepare stream? */
596 This
->acmStreamHdr
.pbSrc
= buffer
;
597 This
->acmStreamHdr
.cbSrcLength
= buffersize
;
598 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
599 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
600 This
->acmStreamHdr
.pbSrc
= NULL
;
601 This
->acmStreamHdr
.cbSrcLength
= 0;
602 return AVIERR_COMPRESSOR
;
606 /* now do the conversion */
607 /* FIXME: use ACM_CONVERTF_* flags */
608 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
609 hr
= AVIERR_COMPRESSOR
;
613 This
->acmStreamHdr
.pbSrc
= NULL
;
614 This
->acmStreamHdr
.cbSrcLength
= 0;
619 return IAVIStream_Write(This
->pStream
,-1,This
->acmStreamHdr
.cbDstLengthUsed
/
620 This
->lpOutFormat
->nBlockAlign
,This
->acmStreamHdr
.pbDst
,
621 This
->acmStreamHdr
.cbDstLengthUsed
,flags
,sampwritten
,
625 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
, LONG start
,
628 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
630 TRACE("(%p,%d,%d)\n", iface
, start
, samples
);
632 /* check parameters */
633 if (start
< 0 || samples
< 0)
634 return AVIERR_BADPARAM
;
636 /* Delete before start of stream? */
637 if ((DWORD
)(start
+ samples
) < This
->sInfo
.dwStart
)
640 /* Delete after end of stream? */
641 if ((DWORD
)start
> This
->sInfo
.dwLength
)
644 /* For the rest we need write capability */
645 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
646 return AVIERR_READONLY
;
648 /* A compressor is also necessary */
649 if (This
->has
== NULL
)
650 return AVIERR_NOCOMPRESSOR
;
652 /* map our positions to pStream positions */
653 CONVERT_THIS_to_STREAM(&start
);
654 CONVERT_THIS_to_STREAM(&samples
);
656 return IAVIStream_Delete(This
->pStream
, start
, samples
);
659 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
, DWORD fcc
,
660 LPVOID lp
, LPLONG lpread
)
662 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
664 TRACE("(%p,0x%08X,%p,%p)\n", iface
, fcc
, lp
, lpread
);
666 assert(This
->pStream
!= NULL
);
668 return IAVIStream_ReadData(This
->pStream
, fcc
, lp
, lpread
);
671 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
, DWORD fcc
,
672 LPVOID lp
, LONG size
)
674 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
676 TRACE("(%p,0x%08x,%p,%d)\n", iface
, fcc
, lp
, size
);
678 assert(This
->pStream
!= NULL
);
680 return IAVIStream_WriteData(This
->pStream
, fcc
, lp
, size
);
683 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,
684 LPAVISTREAMINFOW info
, LONG infolen
)
686 FIXME("(%p,%p,%d): stub\n", iface
, info
, infolen
);
691 static const struct IAVIStreamVtbl iacmst
= {
692 ACMStream_fnQueryInterface
,
697 ACMStream_fnFindSample
,
698 ACMStream_fnReadFormat
,
699 ACMStream_fnSetFormat
,
703 ACMStream_fnReadData
,
704 ACMStream_fnWriteData
,
708 HRESULT
AVIFILE_CreateACMStream(REFIID riid
, LPVOID
*ppv
)
710 IAVIStreamImpl
*pstream
;
713 assert(riid
!= NULL
&& ppv
!= NULL
);
717 pstream
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAVIStreamImpl
));
719 return AVIERR_MEMORY
;
721 pstream
->IAVIStream_iface
.lpVtbl
= &iacmst
;
723 hr
= IAVIStream_QueryInterface(&pstream
->IAVIStream_iface
, riid
, ppv
);
725 HeapFree(GetProcessHeap(), 0, pstream
);