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 #include "avifile_private.h"
21 /***********************************************************************/
23 typedef struct _IAVIStreamImpl
{
25 IAVIStream IAVIStream_iface
;
28 /* IAVIStream stuff */
34 LPWAVEFORMATEX lpInFormat
;
37 LPWAVEFORMATEX lpOutFormat
;
40 ACMSTREAMHEADER acmStreamHdr
;
43 /***********************************************************************/
45 #define CONVERT_STREAM_to_THIS(a) do { \
47 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
48 &__bytes, ACM_STREAMSIZEF_SOURCE); \
49 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
51 #define CONVERT_THIS_to_STREAM(a) do { \
53 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
54 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
55 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
57 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
)
63 assert(This
->pStream
!= NULL
);
65 if (This
->has
!= NULL
)
68 if (This
->lpInFormat
== NULL
) {
69 /* decode or encode the data from pStream */
70 hr
= AVIStreamFormatSize(This
->pStream
, This
->sInfo
.dwStart
, &This
->cbInFormat
);
73 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbInFormat
);
74 if (This
->lpInFormat
== NULL
)
77 hr
= IAVIStream_ReadFormat(This
->pStream
, This
->sInfo
.dwStart
,
78 This
->lpInFormat
, &This
->cbInFormat
);
82 if (This
->lpOutFormat
== NULL
) {
83 /* we must decode to default format */
84 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
85 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
86 if (This
->lpOutFormat
== NULL
)
89 This
->lpOutFormat
->wFormatTag
= WAVE_FORMAT_PCM
;
90 if (acmFormatSuggest(NULL
, This
->lpInFormat
, This
->lpOutFormat
,
91 This
->cbOutFormat
, ACM_FORMATSUGGESTF_WFORMATTAG
) != S_OK
)
92 return AVIERR_NOCOMPRESSOR
;
94 } else if (This
->lpOutFormat
== NULL
)
95 return AVIERR_ERROR
; /* To what should I encode? */
97 if (acmStreamOpen(&This
->has
, NULL
, This
->lpInFormat
, This
->lpOutFormat
,
98 NULL
, 0, 0, ACM_STREAMOPENF_NONREALTIME
) != S_OK
)
99 return AVIERR_NOCOMPRESSOR
;
101 /* update AVISTREAMINFO structure */
102 This
->sInfo
.dwSampleSize
= This
->lpOutFormat
->nBlockAlign
;
103 This
->sInfo
.dwScale
= This
->lpOutFormat
->nBlockAlign
;
104 This
->sInfo
.dwRate
= This
->lpOutFormat
->nAvgBytesPerSec
;
105 This
->sInfo
.dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
106 SetRectEmpty(&This
->sInfo
.rcFrame
);
108 /* convert positions and sizes to output format */
109 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwStart
);
110 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwLength
);
111 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwSuggestedBufferSize
);
116 static inline IAVIStreamImpl
*impl_from_IAVIStream(IAVIStream
*iface
)
118 return CONTAINING_RECORD(iface
, IAVIStreamImpl
, IAVIStream_iface
);
121 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,
122 REFIID refiid
, LPVOID
*obj
)
124 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
126 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(refiid
), obj
);
128 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
129 IsEqualGUID(&IID_IAVIStream
, refiid
)) {
131 IAVIStream_AddRef(iface
);
136 return OLE_E_ENUM_NOMORE
;
139 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
)
141 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
142 ULONG ref
= InterlockedIncrement(&This
->ref
);
144 TRACE("(%p) -> %d\n", iface
, ref
);
146 /* also add reference to the nested stream */
147 if (This
->pStream
!= NULL
)
148 IAVIStream_AddRef(This
->pStream
);
153 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
)
155 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
156 ULONG ref
= InterlockedDecrement(&This
->ref
);
158 TRACE("(%p) -> %d\n", iface
, ref
);
162 if (This
->has
!= NULL
) {
163 if (This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
)
164 acmStreamUnprepareHeader(This
->has
, &This
->acmStreamHdr
, 0);
165 acmStreamClose(This
->has
, 0);
168 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
169 This
->acmStreamHdr
.pbSrc
= NULL
;
170 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
171 This
->acmStreamHdr
.pbDst
= NULL
;
172 if (This
->lpInFormat
!= NULL
) {
173 HeapFree(GetProcessHeap(), 0, This
->lpInFormat
);
174 This
->lpInFormat
= NULL
;
175 This
->cbInFormat
= 0;
177 if (This
->lpOutFormat
!= NULL
) {
178 HeapFree(GetProcessHeap(), 0, This
->lpOutFormat
);
179 This
->lpOutFormat
= NULL
;
180 This
->cbOutFormat
= 0;
182 if (This
->pStream
!= NULL
) {
183 IAVIStream_Release(This
->pStream
);
184 This
->pStream
= NULL
;
186 HeapFree(GetProcessHeap(), 0, This
);
191 /* also release reference to the nested stream */
192 if (This
->pStream
!= NULL
)
193 IAVIStream_Release(This
->pStream
);
198 /* lParam1: PAVISTREAM
199 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
201 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
, LPARAM lParam1
,
204 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
206 TRACE("(%p,0x%08lX,0x%08lX)\n", iface
, lParam1
, lParam2
);
208 /* check for swapped parameters */
209 if ((LPVOID
)lParam1
!= NULL
&&
210 ((LPAVICOMPRESSOPTIONS
)lParam1
)->fccType
== streamtypeAUDIO
) {
211 LPARAM tmp
= lParam1
;
217 if ((LPVOID
)lParam1
== NULL
)
218 return AVIERR_BADPARAM
;
220 IAVIStream_Info((PAVISTREAM
)lParam1
, &This
->sInfo
, sizeof(This
->sInfo
));
221 if (This
->sInfo
.fccType
!= streamtypeAUDIO
)
222 return AVIERR_ERROR
; /* error in registry or AVIMakeCompressedStream */
224 This
->sInfo
.fccHandler
= 0; /* be paranoid */
226 /* FIXME: check ACM version? Which version does we need? */
228 if ((LPVOID
)lParam2
!= NULL
) {
229 /* We only need the format from the compress-options */
230 if (((LPAVICOMPRESSOPTIONS
)lParam2
)->fccType
== streamtypeAUDIO
)
231 lParam2
= (LPARAM
)((LPAVICOMPRESSOPTIONS
)lParam2
)->lpFormat
;
233 if (((LPWAVEFORMATEX
)lParam2
)->wFormatTag
!= WAVE_FORMAT_PCM
)
234 This
->cbOutFormat
= sizeof(WAVEFORMATEX
) + ((LPWAVEFORMATEX
)lParam2
)->cbSize
;
236 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
238 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
239 if (This
->lpOutFormat
== NULL
)
240 return AVIERR_MEMORY
;
242 memcpy(This
->lpOutFormat
, (LPVOID
)lParam2
, This
->cbOutFormat
);
244 This
->lpOutFormat
= NULL
;
245 This
->cbOutFormat
= 0;
248 This
->pStream
= (PAVISTREAM
)lParam1
;
249 IAVIStream_AddRef(This
->pStream
);
254 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,LPAVISTREAMINFOW psi
,
257 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
259 TRACE("(%p,%p,%d)\n", iface
, psi
, size
);
262 return AVIERR_BADPARAM
;
264 return AVIERR_BADSIZE
;
266 /* Need codec to correct some values in structure */
267 if (This
->has
== NULL
) {
268 HRESULT hr
= AVIFILE_OpenCompressor(This
);
274 memcpy(psi
, &This
->sInfo
, min(size
, (LONG
)sizeof(This
->sInfo
)));
276 if (size
< (LONG
)sizeof(This
->sInfo
))
277 return AVIERR_BUFFERTOOSMALL
;
281 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
, LONG pos
,
284 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
286 TRACE("(%p,%d,0x%08X)\n",iface
,pos
,flags
);
288 if (flags
& FIND_FROM_START
) {
289 pos
= This
->sInfo
.dwStart
;
290 flags
&= ~(FIND_FROM_START
|FIND_PREV
);
294 /* convert pos from our 'space' to This->pStream's one */
295 CONVERT_THIS_to_STREAM(&pos
);
298 pos
= IAVIStream_FindSample(This
->pStream
, pos
, flags
);
301 /* convert pos back to our 'space' if it's no size or physical pos */
302 if ((flags
& FIND_RET
) == 0)
303 CONVERT_STREAM_to_THIS(&pos
);
309 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
, LONG pos
,
310 LPVOID format
, LONG
*formatsize
)
312 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
314 TRACE("(%p,%d,%p,%p)\n", iface
, pos
, format
, formatsize
);
316 if (formatsize
== NULL
)
317 return AVIERR_BADPARAM
;
319 if (This
->has
== NULL
) {
320 HRESULT hr
= AVIFILE_OpenCompressor(This
);
326 /* only interested in needed buffersize? */
327 if (format
== NULL
|| *formatsize
<= 0) {
328 *formatsize
= This
->cbOutFormat
;
333 /* copy initial format (only as much as will fit) */
334 memcpy(format
, This
->lpOutFormat
, min(*formatsize
, This
->cbOutFormat
));
335 if (*formatsize
< This
->cbOutFormat
) {
336 *formatsize
= This
->cbOutFormat
;
337 return AVIERR_BUFFERTOOSMALL
;
340 *formatsize
= This
->cbOutFormat
;
344 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
, LONG pos
,
345 LPVOID format
, LONG formatsize
)
347 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
351 TRACE("(%p,%d,%p,%d)\n", iface
, pos
, format
, formatsize
);
353 /* check parameters */
354 if (format
== NULL
|| formatsize
<= 0)
355 return AVIERR_BADPARAM
;
357 /* Input format already known?
358 * Changing is unsupported, but be quiet if it's the same */
359 if (This
->lpInFormat
!= NULL
) {
360 if (This
->cbInFormat
!= formatsize
||
361 memcmp(format
, This
->lpInFormat
, formatsize
) != 0)
362 return AVIERR_UNSUPPORTED
;
367 /* Does the nested stream support writing? */
368 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
369 return AVIERR_READONLY
;
371 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, formatsize
);
372 if (This
->lpInFormat
== NULL
)
373 return AVIERR_MEMORY
;
374 This
->cbInFormat
= formatsize
;
375 memcpy(This
->lpInFormat
, format
, formatsize
);
377 /* initialize formats and get compressor */
378 hr
= AVIFILE_OpenCompressor(This
);
382 CONVERT_THIS_to_STREAM(&pos
);
384 /* tell the nested stream the new format */
385 return IAVIStream_SetFormat(This
->pStream
, pos
, This
->lpOutFormat
,
389 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
, LONG start
,
390 LONG samples
, LPVOID buffer
,
391 LONG buffersize
, LPLONG bytesread
,
394 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
399 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface
, start
, samples
, buffer
,
400 buffersize
, bytesread
, samplesread
);
402 /* clear return parameters if given */
403 if (bytesread
!= NULL
)
405 if (samplesread
!= NULL
)
408 /* Do we have our compressor? */
409 if (This
->has
== NULL
) {
410 hr
= AVIFILE_OpenCompressor(This
);
416 /* only need to pass through? */
417 if (This
->cbInFormat
== This
->cbOutFormat
&&
418 memcmp(This
->lpInFormat
, This
->lpOutFormat
, This
->cbInFormat
) == 0) {
419 return IAVIStream_Read(This
->pStream
, start
, samples
, buffer
, buffersize
,
420 bytesread
, samplesread
);
423 /* read as much as fit? */
425 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
426 /* limit to buffersize */
427 if (samples
* This
->lpOutFormat
->nBlockAlign
> buffersize
)
428 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
430 /* only return needed size? */
431 if (buffer
== NULL
|| buffersize
<= 0 || samples
== 0) {
432 if (bytesread
== NULL
&& samplesread
== NULL
)
433 return AVIERR_BADPARAM
;
435 if (bytesread
!= NULL
)
436 *bytesread
= samples
* This
->lpOutFormat
->nBlockAlign
;
437 if (samplesread
!= NULL
)
438 *samplesread
= samples
;
443 /* map our positions to pStream positions */
444 CONVERT_THIS_to_STREAM(&start
);
446 /* our needed internal buffersize */
447 size
= samples
* This
->lpInFormat
->nBlockAlign
;
449 /* Need to free destination buffer used for writing? */
450 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
451 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
452 This
->acmStreamHdr
.pbDst
= NULL
;
453 This
->acmStreamHdr
.dwDstUser
= 0;
456 /* need bigger source buffer? */
457 if (This
->acmStreamHdr
.pbSrc
== NULL
||
458 This
->acmStreamHdr
.dwSrcUser
< size
) {
459 if (This
->acmStreamHdr
.pbSrc
== NULL
)
460 This
->acmStreamHdr
.pbSrc
= HeapAlloc(GetProcessHeap(), 0, size
);
462 This
->acmStreamHdr
.pbSrc
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
, size
);
463 if (This
->acmStreamHdr
.pbSrc
== NULL
)
464 return AVIERR_MEMORY
;
465 This
->acmStreamHdr
.dwSrcUser
= size
;
468 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
469 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
470 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
471 This
->acmStreamHdr
.cbSrcLength
= size
;
473 /* read source data */
474 hr
= IAVIStream_Read(This
->pStream
, start
, -1, This
->acmStreamHdr
.pbSrc
,
475 This
->acmStreamHdr
.cbSrcLength
,
476 (LONG
*)&This
->acmStreamHdr
.cbSrcLength
, NULL
);
477 if (FAILED(hr
) || This
->acmStreamHdr
.cbSrcLength
== 0)
480 /* need to prepare stream? */
481 This
->acmStreamHdr
.pbDst
= buffer
;
482 This
->acmStreamHdr
.cbDstLength
= buffersize
;
483 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
484 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
485 This
->acmStreamHdr
.pbDst
= NULL
;
486 This
->acmStreamHdr
.cbDstLength
= 0;
487 return AVIERR_COMPRESSOR
;
491 /* now do the conversion */
492 /* FIXME: use ACM_CONVERTF_* flags */
493 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
494 hr
= AVIERR_COMPRESSOR
;
496 This
->acmStreamHdr
.pbDst
= NULL
;
497 This
->acmStreamHdr
.cbDstLength
= 0;
499 /* fill out return parameters if given */
500 if (bytesread
!= NULL
)
501 *bytesread
= This
->acmStreamHdr
.cbDstLengthUsed
;
502 if (samplesread
!= NULL
)
504 This
->acmStreamHdr
.cbDstLengthUsed
/ This
->lpOutFormat
->nBlockAlign
;
509 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
, LONG start
,
510 LONG samples
, LPVOID buffer
,
511 LONG buffersize
, DWORD flags
,
515 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
520 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface
, start
, samples
,
521 buffer
, buffersize
, flags
, sampwritten
, byteswritten
);
523 /* clear return parameters if given */
524 if (sampwritten
!= NULL
)
526 if (byteswritten
!= NULL
)
529 /* check parameters */
530 if (buffer
== NULL
&& (buffersize
> 0 || samples
> 0))
531 return AVIERR_BADPARAM
;
533 /* Have we write capability? */
534 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
535 return AVIERR_READONLY
;
537 /* also need a compressor */
538 if (This
->has
== NULL
)
539 return AVIERR_NOCOMPRESSOR
;
541 /* map our sizes to pStream sizes */
543 CONVERT_THIS_to_STREAM(&size
);
544 CONVERT_THIS_to_STREAM(&start
);
546 /* no bytes to write? -- short circuit */
548 return IAVIStream_Write(This
->pStream
, -1, samples
, buffer
, size
,
549 flags
, sampwritten
, byteswritten
);
552 /* Need to free source buffer used for reading? */
553 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
554 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
555 This
->acmStreamHdr
.pbSrc
= NULL
;
556 This
->acmStreamHdr
.dwSrcUser
= 0;
559 /* Need bigger destination buffer? */
560 if (This
->acmStreamHdr
.pbDst
== NULL
||
561 This
->acmStreamHdr
.dwDstUser
< size
) {
562 if (This
->acmStreamHdr
.pbDst
== NULL
)
563 This
->acmStreamHdr
.pbDst
= HeapAlloc(GetProcessHeap(), 0, size
);
565 This
->acmStreamHdr
.pbDst
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
, size
);
566 if (This
->acmStreamHdr
.pbDst
== NULL
)
567 return AVIERR_MEMORY
;
568 This
->acmStreamHdr
.dwDstUser
= size
;
570 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
571 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
572 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
573 This
->acmStreamHdr
.cbDstLength
= This
->acmStreamHdr
.dwDstUser
;
575 /* need to prepare stream? */
576 This
->acmStreamHdr
.pbSrc
= buffer
;
577 This
->acmStreamHdr
.cbSrcLength
= buffersize
;
578 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
579 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
580 This
->acmStreamHdr
.pbSrc
= NULL
;
581 This
->acmStreamHdr
.cbSrcLength
= 0;
582 return AVIERR_COMPRESSOR
;
586 /* now do the conversion */
587 /* FIXME: use ACM_CONVERTF_* flags */
588 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
589 hr
= AVIERR_COMPRESSOR
;
593 This
->acmStreamHdr
.pbSrc
= NULL
;
594 This
->acmStreamHdr
.cbSrcLength
= 0;
599 return IAVIStream_Write(This
->pStream
,-1,This
->acmStreamHdr
.cbDstLengthUsed
/
600 This
->lpOutFormat
->nBlockAlign
,This
->acmStreamHdr
.pbDst
,
601 This
->acmStreamHdr
.cbDstLengthUsed
,flags
,sampwritten
,
605 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
, LONG start
,
608 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
610 TRACE("(%p,%d,%d)\n", iface
, start
, samples
);
612 /* check parameters */
613 if (start
< 0 || samples
< 0)
614 return AVIERR_BADPARAM
;
616 /* Delete before start of stream? */
617 if ((DWORD
)(start
+ samples
) < This
->sInfo
.dwStart
)
620 /* Delete after end of stream? */
621 if ((DWORD
)start
> This
->sInfo
.dwLength
)
624 /* For the rest we need write capability */
625 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
626 return AVIERR_READONLY
;
628 /* A compressor is also necessary */
629 if (This
->has
== NULL
)
630 return AVIERR_NOCOMPRESSOR
;
632 /* map our positions to pStream positions */
633 CONVERT_THIS_to_STREAM(&start
);
634 CONVERT_THIS_to_STREAM(&samples
);
636 return IAVIStream_Delete(This
->pStream
, start
, samples
);
639 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
, DWORD fcc
,
640 LPVOID lp
, LPLONG lpread
)
642 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
644 TRACE("(%p,0x%08X,%p,%p)\n", iface
, fcc
, lp
, lpread
);
646 assert(This
->pStream
!= NULL
);
648 return IAVIStream_ReadData(This
->pStream
, fcc
, lp
, lpread
);
651 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
, DWORD fcc
,
652 LPVOID lp
, LONG size
)
654 IAVIStreamImpl
*This
= impl_from_IAVIStream(iface
);
656 TRACE("(%p,0x%08x,%p,%d)\n", iface
, fcc
, lp
, size
);
658 assert(This
->pStream
!= NULL
);
660 return IAVIStream_WriteData(This
->pStream
, fcc
, lp
, size
);
663 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,
664 LPAVISTREAMINFOW info
, LONG infolen
)
666 FIXME("(%p,%p,%d): stub\n", iface
, info
, infolen
);
671 static const struct IAVIStreamVtbl iacmst
= {
672 ACMStream_fnQueryInterface
,
677 ACMStream_fnFindSample
,
678 ACMStream_fnReadFormat
,
679 ACMStream_fnSetFormat
,
683 ACMStream_fnReadData
,
684 ACMStream_fnWriteData
,
688 HRESULT
AVIFILE_CreateACMStream(REFIID riid
, LPVOID
*ppv
)
690 IAVIStreamImpl
*pstream
;
693 assert(riid
!= NULL
&& ppv
!= NULL
);
697 pstream
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAVIStreamImpl
));
699 return AVIERR_MEMORY
;
701 pstream
->IAVIStream_iface
.lpVtbl
= &iacmst
;
703 hr
= IAVIStream_QueryInterface(&pstream
->IAVIStream_iface
, riid
, ppv
);
705 HeapFree(GetProcessHeap(), 0, pstream
);