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 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,REFIID refiid
,LPVOID
*obj
);
40 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
);
41 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
);
42 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
,LPARAM lParam1
,LPARAM lParam2
);
43 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,AVISTREAMINFOW
*psi
,LONG size
);
44 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
,LONG pos
,LONG flags
);
45 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
,LONG pos
,LPVOID format
,LONG
*formatsize
);
46 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
,LONG pos
,LPVOID format
,LONG formatsize
);
47 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
,LONG start
,LONG samples
,LPVOID buffer
,LONG buffersize
,LONG
*bytesread
,LONG
*samplesread
);
48 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
,LONG start
,LONG samples
,LPVOID buffer
,LONG buffersize
,DWORD flags
,LONG
*sampwritten
,LONG
*byteswritten
);
49 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
,LONG start
,LONG samples
);
50 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
,DWORD fcc
,LPVOID lp
,LONG
*lpread
);
51 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
,DWORD fcc
,LPVOID lp
,LONG size
);
52 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,AVISTREAMINFOW
*info
,LONG infolen
);
54 static const struct IAVIStreamVtbl iacmst
= {
55 ACMStream_fnQueryInterface
,
60 ACMStream_fnFindSample
,
61 ACMStream_fnReadFormat
,
62 ACMStream_fnSetFormat
,
67 ACMStream_fnWriteData
,
71 typedef struct _IAVIStreamImpl
{
73 const IAVIStreamVtbl
*lpVtbl
;
76 /* IAVIStream stuff */
82 LPWAVEFORMATEX lpInFormat
;
85 LPWAVEFORMATEX lpOutFormat
;
88 ACMSTREAMHEADER acmStreamHdr
;
91 /***********************************************************************/
93 #define CONVERT_STREAM_to_THIS(a) do { \
95 acmStreamSize(This->has,*(a) * This->lpInFormat->nBlockAlign,\
96 &__bytes, ACM_STREAMSIZEF_SOURCE); \
97 *(a) = __bytes / This->lpOutFormat->nBlockAlign; } while(0)
99 #define CONVERT_THIS_to_STREAM(a) do { \
101 acmStreamSize(This->has,*(a) * This->lpOutFormat->nBlockAlign,\
102 &__bytes, ACM_STREAMSIZEF_DESTINATION); \
103 *(a) = __bytes / This->lpInFormat->nBlockAlign; } while(0)
105 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
);
107 HRESULT
AVIFILE_CreateACMStream(REFIID riid
, LPVOID
*ppv
)
109 IAVIStreamImpl
*pstream
;
112 assert(riid
!= NULL
&& ppv
!= NULL
);
116 pstream
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IAVIStreamImpl
));
118 return AVIERR_MEMORY
;
120 pstream
->lpVtbl
= &iacmst
;
122 hr
= IAVIStream_QueryInterface((IAVIStream
*)pstream
, riid
, ppv
);
124 HeapFree(GetProcessHeap(), 0, pstream
);
129 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,
130 REFIID refiid
, LPVOID
*obj
)
132 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
134 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(refiid
), obj
);
136 if (IsEqualGUID(&IID_IUnknown
, refiid
) ||
137 IsEqualGUID(&IID_IAVIStream
, refiid
)) {
139 IAVIStream_AddRef(iface
);
144 return OLE_E_ENUM_NOMORE
;
147 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
)
149 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
150 ULONG ref
= InterlockedIncrement(&This
->ref
);
152 TRACE("(%p) -> %d\n", iface
, ref
);
154 /* also add reference to the nested stream */
155 if (This
->pStream
!= NULL
)
156 IAVIStream_AddRef(This
->pStream
);
161 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
)
163 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
164 ULONG ref
= InterlockedDecrement(&This
->ref
);
166 TRACE("(%p) -> %d\n", iface
, ref
);
170 if (This
->has
!= NULL
) {
171 if (This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
)
172 acmStreamUnprepareHeader(This
->has
, &This
->acmStreamHdr
, 0);
173 acmStreamClose(This
->has
, 0);
176 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
177 This
->acmStreamHdr
.pbSrc
= NULL
;
178 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
179 This
->acmStreamHdr
.pbDst
= NULL
;
180 if (This
->lpInFormat
!= NULL
) {
181 HeapFree(GetProcessHeap(), 0, This
->lpInFormat
);
182 This
->lpInFormat
= NULL
;
183 This
->cbInFormat
= 0;
185 if (This
->lpOutFormat
!= NULL
) {
186 HeapFree(GetProcessHeap(), 0, This
->lpOutFormat
);
187 This
->lpOutFormat
= NULL
;
188 This
->cbOutFormat
= 0;
190 if (This
->pStream
!= NULL
) {
191 IAVIStream_Release(This
->pStream
);
192 This
->pStream
= NULL
;
194 HeapFree(GetProcessHeap(), 0, This
);
199 /* also release reference to the nested stream */
200 if (This
->pStream
!= NULL
)
201 IAVIStream_Release(This
->pStream
);
206 /* lParam1: PAVISTREAM
207 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
209 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
, LPARAM lParam1
,
212 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
214 TRACE("(%p,0x%08lX,0x%08lX)\n", iface
, lParam1
, lParam2
);
216 /* check for swapped parameters */
217 if ((LPVOID
)lParam1
!= NULL
&&
218 ((LPAVICOMPRESSOPTIONS
)lParam1
)->fccType
== streamtypeAUDIO
) {
219 register LPARAM tmp
= lParam1
;
225 if ((LPVOID
)lParam1
== NULL
)
226 return AVIERR_BADPARAM
;
228 IAVIStream_Info((PAVISTREAM
)lParam1
, &This
->sInfo
, sizeof(This
->sInfo
));
229 if (This
->sInfo
.fccType
!= streamtypeAUDIO
)
230 return AVIERR_ERROR
; /* error in registry or AVIMakeCompressedStream */
232 This
->sInfo
.fccHandler
= 0; /* be paranoid */
234 /* FIXME: check ACM version? Which version does we need? */
236 if ((LPVOID
)lParam2
!= NULL
) {
237 /* We only need the format from the compress-options */
238 if (((LPAVICOMPRESSOPTIONS
)lParam2
)->fccType
== streamtypeAUDIO
)
239 lParam2
= (LPARAM
)((LPAVICOMPRESSOPTIONS
)lParam2
)->lpFormat
;
241 if (((LPWAVEFORMATEX
)lParam2
)->wFormatTag
!= WAVE_FORMAT_PCM
)
242 This
->cbOutFormat
= sizeof(WAVEFORMATEX
) + ((LPWAVEFORMATEX
)lParam2
)->cbSize
;
244 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
246 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
247 if (This
->lpOutFormat
== NULL
)
248 return AVIERR_MEMORY
;
250 memcpy(This
->lpOutFormat
, (LPVOID
)lParam2
, This
->cbOutFormat
);
252 This
->lpOutFormat
= NULL
;
253 This
->cbOutFormat
= 0;
256 This
->pStream
= (PAVISTREAM
)lParam1
;
257 IAVIStream_AddRef(This
->pStream
);
262 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,LPAVISTREAMINFOW psi
,
265 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
267 TRACE("(%p,%p,%d)\n", iface
, psi
, size
);
270 return AVIERR_BADPARAM
;
272 return AVIERR_BADSIZE
;
274 /* Need codec to correct some values in structure */
275 if (This
->has
== NULL
) {
276 HRESULT hr
= AVIFILE_OpenCompressor(This
);
282 memcpy(psi
, &This
->sInfo
, min(size
, (LONG
)sizeof(This
->sInfo
)));
284 if (size
< (LONG
)sizeof(This
->sInfo
))
285 return AVIERR_BUFFERTOOSMALL
;
289 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
, LONG pos
,
292 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
294 TRACE("(%p,%d,0x%08X)\n",iface
,pos
,flags
);
296 if (flags
& FIND_FROM_START
) {
297 pos
= This
->sInfo
.dwStart
;
298 flags
&= ~(FIND_FROM_START
|FIND_PREV
);
302 /* convert pos from our 'space' to This->pStream's one */
303 CONVERT_THIS_to_STREAM(&pos
);
306 pos
= IAVIStream_FindSample(This
->pStream
, pos
, flags
);
309 /* convert pos back to our 'space' if it's no size or physical pos */
310 if ((flags
& FIND_RET
) == 0)
311 CONVERT_STREAM_to_THIS(&pos
);
317 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
, LONG pos
,
318 LPVOID format
, LONG
*formatsize
)
320 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
322 TRACE("(%p,%d,%p,%p)\n", iface
, pos
, format
, formatsize
);
324 if (formatsize
== NULL
)
325 return AVIERR_BADPARAM
;
327 if (This
->has
== NULL
) {
328 HRESULT hr
= AVIFILE_OpenCompressor(This
);
334 /* only interested in needed buffersize? */
335 if (format
== NULL
|| *formatsize
<= 0) {
336 *formatsize
= This
->cbOutFormat
;
341 /* copy initial format (only as much as will fit) */
342 memcpy(format
, This
->lpOutFormat
, min(*formatsize
, This
->cbOutFormat
));
343 if (*formatsize
< This
->cbOutFormat
) {
344 *formatsize
= This
->cbOutFormat
;
345 return AVIERR_BUFFERTOOSMALL
;
348 *formatsize
= This
->cbOutFormat
;
352 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
, LONG pos
,
353 LPVOID format
, LONG formatsize
)
355 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
359 TRACE("(%p,%d,%p,%d)\n", iface
, pos
, format
, formatsize
);
361 /* check parameters */
362 if (format
== NULL
|| formatsize
<= 0)
363 return AVIERR_BADPARAM
;
365 /* Input format already known?
366 * Changing is unsupported, but be quiet if it's the same */
367 if (This
->lpInFormat
!= NULL
) {
368 if (This
->cbInFormat
!= formatsize
||
369 memcmp(format
, This
->lpInFormat
, formatsize
) != 0)
370 return AVIERR_UNSUPPORTED
;
375 /* Does the nested stream support writing? */
376 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
377 return AVIERR_READONLY
;
379 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, formatsize
);
380 if (This
->lpInFormat
== NULL
)
381 return AVIERR_MEMORY
;
382 This
->cbInFormat
= formatsize
;
383 memcpy(This
->lpInFormat
, format
, formatsize
);
385 /* initialize formats and get compressor */
386 hr
= AVIFILE_OpenCompressor(This
);
390 CONVERT_THIS_to_STREAM(&pos
);
392 /* tell the nested stream the new format */
393 return IAVIStream_SetFormat(This
->pStream
, pos
, This
->lpOutFormat
,
397 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
, LONG start
,
398 LONG samples
, LPVOID buffer
,
399 LONG buffersize
, LPLONG bytesread
,
402 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
407 TRACE("(%p,%d,%d,%p,%d,%p,%p)\n", iface
, start
, samples
, buffer
,
408 buffersize
, bytesread
, samplesread
);
410 /* clear return parameters if given */
411 if (bytesread
!= NULL
)
413 if (samplesread
!= NULL
)
416 /* Do we have our compressor? */
417 if (This
->has
== NULL
) {
418 hr
= AVIFILE_OpenCompressor(This
);
424 /* only need to pass through? */
425 if (This
->cbInFormat
== This
->cbOutFormat
&&
426 memcmp(This
->lpInFormat
, This
->lpOutFormat
, This
->cbInFormat
) == 0) {
427 return IAVIStream_Read(This
->pStream
, start
, samples
, buffer
, buffersize
,
428 bytesread
, samplesread
);
431 /* read as much as fit? */
433 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
434 /* limit to buffersize */
435 if (samples
* This
->lpOutFormat
->nBlockAlign
> buffersize
)
436 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
438 /* only return needed size? */
439 if (buffer
== NULL
|| buffersize
<= 0 || samples
== 0) {
440 if (bytesread
== NULL
&& samplesread
== NULL
)
441 return AVIERR_BADPARAM
;
443 if (bytesread
!= NULL
)
444 *bytesread
= samples
* This
->lpOutFormat
->nBlockAlign
;
445 if (samplesread
!= NULL
)
446 *samplesread
= samples
;
451 /* map our positions to pStream positions */
452 CONVERT_THIS_to_STREAM(&start
);
454 /* our needed internal buffersize */
455 size
= samples
* This
->lpInFormat
->nBlockAlign
;
457 /* Need to free destination buffer used for writing? */
458 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
459 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
);
460 This
->acmStreamHdr
.pbDst
= NULL
;
461 This
->acmStreamHdr
.dwDstUser
= 0;
464 /* need bigger source buffer? */
465 if (This
->acmStreamHdr
.pbSrc
== NULL
||
466 This
->acmStreamHdr
.dwSrcUser
< size
) {
467 if (This
->acmStreamHdr
.pbSrc
== NULL
)
468 This
->acmStreamHdr
.pbSrc
= HeapAlloc(GetProcessHeap(), 0, size
);
470 This
->acmStreamHdr
.pbSrc
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
, size
);
471 if (This
->acmStreamHdr
.pbSrc
== NULL
)
472 return AVIERR_MEMORY
;
473 This
->acmStreamHdr
.dwSrcUser
= size
;
476 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
477 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
478 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
479 This
->acmStreamHdr
.cbSrcLength
= size
;
481 /* read source data */
482 hr
= IAVIStream_Read(This
->pStream
, start
, -1, This
->acmStreamHdr
.pbSrc
,
483 This
->acmStreamHdr
.cbSrcLength
,
484 (LONG
*)&This
->acmStreamHdr
.cbSrcLength
, NULL
);
485 if (FAILED(hr
) || This
->acmStreamHdr
.cbSrcLength
== 0)
488 /* need to prepare stream? */
489 This
->acmStreamHdr
.pbDst
= buffer
;
490 This
->acmStreamHdr
.cbDstLength
= buffersize
;
491 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
492 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
493 This
->acmStreamHdr
.pbDst
= NULL
;
494 This
->acmStreamHdr
.cbDstLength
= 0;
495 return AVIERR_COMPRESSOR
;
499 /* now do the conversion */
500 /* FIXME: use ACM_CONVERTF_* flags */
501 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
502 hr
= AVIERR_COMPRESSOR
;
504 This
->acmStreamHdr
.pbDst
= NULL
;
505 This
->acmStreamHdr
.cbDstLength
= 0;
507 /* fill out return parameters if given */
508 if (bytesread
!= NULL
)
509 *bytesread
= This
->acmStreamHdr
.cbDstLengthUsed
;
510 if (samplesread
!= NULL
)
512 This
->acmStreamHdr
.cbDstLengthUsed
/ This
->lpOutFormat
->nBlockAlign
;
517 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
, LONG start
,
518 LONG samples
, LPVOID buffer
,
519 LONG buffersize
, DWORD flags
,
523 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
528 TRACE("(%p,%d,%d,%p,%d,0x%08X,%p,%p)\n", iface
, start
, samples
,
529 buffer
, buffersize
, flags
, sampwritten
, byteswritten
);
531 /* clear return parameters if given */
532 if (sampwritten
!= NULL
)
534 if (byteswritten
!= NULL
)
537 /* check parameters */
538 if (buffer
== NULL
&& (buffersize
> 0 || samples
> 0))
539 return AVIERR_BADPARAM
;
541 /* Have we write capability? */
542 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
543 return AVIERR_READONLY
;
545 /* also need a compressor */
546 if (This
->has
== NULL
)
547 return AVIERR_NOCOMPRESSOR
;
549 /* map our sizes to pStream sizes */
551 CONVERT_THIS_to_STREAM(&size
);
552 CONVERT_THIS_to_STREAM(&start
);
554 /* no bytes to write? -- short circuit */
556 return IAVIStream_Write(This
->pStream
, -1, samples
, buffer
, size
,
557 flags
, sampwritten
, byteswritten
);
560 /* Need to free source buffer used for reading? */
561 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
562 HeapFree(GetProcessHeap(), 0, This
->acmStreamHdr
.pbSrc
);
563 This
->acmStreamHdr
.pbSrc
= NULL
;
564 This
->acmStreamHdr
.dwSrcUser
= 0;
567 /* Need bigger destination buffer? */
568 if (This
->acmStreamHdr
.pbDst
== NULL
||
569 This
->acmStreamHdr
.dwDstUser
< size
) {
570 if (This
->acmStreamHdr
.pbDst
== NULL
)
571 This
->acmStreamHdr
.pbDst
= HeapAlloc(GetProcessHeap(), 0, size
);
573 This
->acmStreamHdr
.pbDst
= HeapReAlloc(GetProcessHeap(), 0, This
->acmStreamHdr
.pbDst
, size
);
574 if (This
->acmStreamHdr
.pbDst
== NULL
)
575 return AVIERR_MEMORY
;
576 This
->acmStreamHdr
.dwDstUser
= size
;
578 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
579 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
580 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
581 This
->acmStreamHdr
.cbDstLength
= This
->acmStreamHdr
.dwDstUser
;
583 /* need to prepare stream? */
584 This
->acmStreamHdr
.pbSrc
= buffer
;
585 This
->acmStreamHdr
.cbSrcLength
= buffersize
;
586 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
587 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
588 This
->acmStreamHdr
.pbSrc
= NULL
;
589 This
->acmStreamHdr
.cbSrcLength
= 0;
590 return AVIERR_COMPRESSOR
;
594 /* now do the conversion */
595 /* FIXME: use ACM_CONVERTF_* flags */
596 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
597 hr
= AVIERR_COMPRESSOR
;
601 This
->acmStreamHdr
.pbSrc
= NULL
;
602 This
->acmStreamHdr
.cbSrcLength
= 0;
607 return IAVIStream_Write(This
->pStream
,-1,This
->acmStreamHdr
.cbDstLengthUsed
/
608 This
->lpOutFormat
->nBlockAlign
,This
->acmStreamHdr
.pbDst
,
609 This
->acmStreamHdr
.cbDstLengthUsed
,flags
,sampwritten
,
613 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
, LONG start
,
616 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
618 TRACE("(%p,%d,%d)\n", iface
, start
, samples
);
620 /* check parameters */
621 if (start
< 0 || samples
< 0)
622 return AVIERR_BADPARAM
;
624 /* Delete before start of stream? */
625 if ((DWORD
)(start
+ samples
) < This
->sInfo
.dwStart
)
628 /* Delete after end of stream? */
629 if ((DWORD
)start
> This
->sInfo
.dwLength
)
632 /* For the rest we need write capability */
633 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
634 return AVIERR_READONLY
;
636 /* A compressor is also necessary */
637 if (This
->has
== NULL
)
638 return AVIERR_NOCOMPRESSOR
;
640 /* map our positions to pStream positions */
641 CONVERT_THIS_to_STREAM(&start
);
642 CONVERT_THIS_to_STREAM(&samples
);
644 return IAVIStream_Delete(This
->pStream
, start
, samples
);
647 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
, DWORD fcc
,
648 LPVOID lp
, LPLONG lpread
)
650 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
652 TRACE("(%p,0x%08X,%p,%p)\n", iface
, fcc
, lp
, lpread
);
654 assert(This
->pStream
!= NULL
);
656 return IAVIStream_ReadData(This
->pStream
, fcc
, lp
, lpread
);
659 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
, DWORD fcc
,
660 LPVOID lp
, LONG size
)
662 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
664 TRACE("(%p,0x%08x,%p,%d)\n", iface
, fcc
, lp
, size
);
666 assert(This
->pStream
!= NULL
);
668 return IAVIStream_WriteData(This
->pStream
, fcc
, lp
, size
);
671 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,
672 LPAVISTREAMINFOW info
, LONG infolen
)
674 FIXME("(%p,%p,%d): stub\n", iface
, info
, infolen
);
679 /***********************************************************************/
681 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
)
686 assert(This
!= NULL
);
687 assert(This
->pStream
!= NULL
);
689 if (This
->has
!= NULL
)
692 if (This
->lpInFormat
== NULL
) {
693 /* decode or encode the data from pStream */
694 hr
= AVIStreamFormatSize(This
->pStream
, This
->sInfo
.dwStart
, &This
->cbInFormat
);
697 This
->lpInFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbInFormat
);
698 if (This
->lpInFormat
== NULL
)
699 return AVIERR_MEMORY
;
701 hr
= IAVIStream_ReadFormat(This
->pStream
, This
->sInfo
.dwStart
,
702 This
->lpInFormat
, &This
->cbInFormat
);
706 if (This
->lpOutFormat
== NULL
) {
707 /* we must decode to default format */
708 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
709 This
->lpOutFormat
= HeapAlloc(GetProcessHeap(), 0, This
->cbOutFormat
);
710 if (This
->lpOutFormat
== NULL
)
711 return AVIERR_MEMORY
;
713 This
->lpOutFormat
->wFormatTag
= WAVE_FORMAT_PCM
;
714 if (acmFormatSuggest(NULL
, This
->lpInFormat
, This
->lpOutFormat
,
715 This
->cbOutFormat
, ACM_FORMATSUGGESTF_WFORMATTAG
) != S_OK
)
716 return AVIERR_NOCOMPRESSOR
;
718 } else if (This
->lpOutFormat
== NULL
)
719 return AVIERR_ERROR
; /* To what should I encode? */
721 if (acmStreamOpen(&This
->has
, NULL
, This
->lpInFormat
, This
->lpOutFormat
,
722 NULL
, 0, 0, ACM_STREAMOPENF_NONREALTIME
) != S_OK
)
723 return AVIERR_NOCOMPRESSOR
;
725 /* update AVISTREAMINFO structure */
726 This
->sInfo
.dwSampleSize
= This
->lpOutFormat
->nBlockAlign
;
727 This
->sInfo
.dwScale
= This
->lpOutFormat
->nBlockAlign
;
728 This
->sInfo
.dwRate
= This
->lpOutFormat
->nAvgBytesPerSec
;
729 This
->sInfo
.dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
730 SetRectEmpty(&This
->sInfo
.rcFrame
);
732 /* convert positions and sizes to output format */
733 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwStart
);
734 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwLength
);
735 CONVERT_STREAM_to_THIS(&This
->sInfo
.dwSuggestedBufferSize
);