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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #define COM_NO_WINDOWS_H
34 #include "avifile_private.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(avifile
);
40 /***********************************************************************/
42 static HRESULT WINAPI
ACMStream_fnQueryInterface(IAVIStream
*iface
,REFIID refiid
,LPVOID
*obj
);
43 static ULONG WINAPI
ACMStream_fnAddRef(IAVIStream
*iface
);
44 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
);
45 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
,LPARAM lParam1
,LPARAM lParam2
);
46 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,AVISTREAMINFOW
*psi
,LONG size
);
47 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
,LONG pos
,LONG flags
);
48 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
,LONG pos
,LPVOID format
,LONG
*formatsize
);
49 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
,LONG pos
,LPVOID format
,LONG formatsize
);
50 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
,LONG start
,LONG samples
,LPVOID buffer
,LONG buffersize
,LONG
*bytesread
,LONG
*samplesread
);
51 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
,LONG start
,LONG samples
,LPVOID buffer
,LONG buffersize
,DWORD flags
,LONG
*sampwritten
,LONG
*byteswritten
);
52 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
,LONG start
,LONG samples
);
53 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
,DWORD fcc
,LPVOID lp
,LONG
*lpread
);
54 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
,DWORD fcc
,LPVOID lp
,LONG size
);
55 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,AVISTREAMINFOW
*info
,LONG infolen
);
57 struct IAVIStreamVtbl iacmst
= {
58 ACMStream_fnQueryInterface
,
63 ACMStream_fnFindSample
,
64 ACMStream_fnReadFormat
,
65 ACMStream_fnSetFormat
,
70 ACMStream_fnWriteData
,
74 typedef struct _IAVIStreamImpl
{
76 IAVIStreamVtbl
*lpVtbl
;
79 /* IAVIStream stuff */
85 LPWAVEFORMATEX lpInFormat
;
88 LPWAVEFORMATEX lpOutFormat
;
91 ACMSTREAMHEADER acmStreamHdr
;
94 /***********************************************************************/
96 #define CONVERT_STREAM_to_THIS(a) { \
97 acmStreamSize(This->has,(a)*This->lpInFormat->nBlockAlign,\
98 &(a), ACM_STREAMSIZEF_SOURCE); \
99 (a) /= This->lpOutFormat->nBlockAlign; }
100 #define CONVERT_THIS_to_STREAM(a) { \
101 acmStreamSize(This->has,(a)*This->lpOutFormat->nBlockAlign,\
102 &(a), ACM_STREAMSIZEF_DESTINATION); \
103 (a) /= This->lpInFormat->nBlockAlign; }
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
= (IAVIStreamImpl
*)LocalAlloc(LPTR
, sizeof(IAVIStreamImpl
));
118 return AVIERR_MEMORY
;
120 pstream
->lpVtbl
= &iacmst
;
122 hr
= IUnknown_QueryInterface((IUnknown
*)pstream
, riid
, ppv
);
124 LocalFree((HLOCAL
)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
;
151 TRACE("(%p) -> %ld\n", iface
, This
->ref
+ 1);
153 /* also add reference to the nested stream */
154 if (This
->pStream
!= NULL
)
155 IAVIStream_AddRef(This
->pStream
);
157 return ++(This
->ref
);
160 static ULONG WINAPI
ACMStream_fnRelease(IAVIStream
* iface
)
162 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
164 TRACE("(%p) -> %ld\n", iface
, This
->ref
- 1);
166 if (This
->ref
== 0) {
168 if (This
->has
!= NULL
) {
169 if (This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
)
170 acmStreamUnprepareHeader(This
->has
, &This
->acmStreamHdr
, 0);
171 acmStreamClose(This
->has
, 0);
174 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
175 GlobalFreePtr(This
->acmStreamHdr
.pbSrc
);
176 This
->acmStreamHdr
.pbSrc
= NULL
;
178 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
179 GlobalFreePtr(This
->acmStreamHdr
.pbDst
);
180 This
->acmStreamHdr
.pbDst
= NULL
;
182 if (This
->lpInFormat
!= NULL
) {
183 GlobalFreePtr(This
->lpInFormat
);
184 This
->lpInFormat
= NULL
;
185 This
->cbInFormat
= 0;
187 if (This
->lpOutFormat
!= NULL
) {
188 GlobalFreePtr(This
->lpOutFormat
);
189 This
->lpOutFormat
= NULL
;
190 This
->cbOutFormat
= 0;
192 if (This
->pStream
!= NULL
) {
193 IAVIStream_Release(This
->pStream
);
194 This
->pStream
= NULL
;
196 LocalFree((HLOCAL
)This
);
201 /* also release reference to the nested stream */
202 if (This
->pStream
!= NULL
)
203 IAVIStream_Release(This
->pStream
);
208 /* lParam1: PAVISTREAM
209 * lParam2: LPAVICOMPRESSOPTIONS -- even if doc's say LPWAVEFORMAT
211 static HRESULT WINAPI
ACMStream_fnCreate(IAVIStream
*iface
, LPARAM lParam1
,
214 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
216 TRACE("(%p,0x%08lX,0x%08lX)\n", iface
, lParam1
, lParam2
);
218 /* check for swapped parameters */
219 if ((LPVOID
)lParam1
!= NULL
&&
220 ((LPAVICOMPRESSOPTIONS
)lParam1
)->fccType
== streamtypeAUDIO
) {
221 register LPARAM tmp
= lParam1
;
227 if ((LPVOID
)lParam1
== NULL
)
228 return AVIERR_BADPARAM
;
230 IAVIStream_Info((PAVISTREAM
)lParam1
, &This
->sInfo
, sizeof(This
->sInfo
));
231 if (This
->sInfo
.fccType
!= streamtypeAUDIO
)
232 return AVIERR_ERROR
; /* error in registry or AVIMakeCompressedStream */
234 This
->sInfo
.fccHandler
= 0; /* be paranoid */
236 /* FIXME: check ACM version? Which version does we need? */
238 if ((LPVOID
)lParam2
!= NULL
) {
239 /* We only need the format from the compress-options */
240 if (((LPAVICOMPRESSOPTIONS
)lParam2
)->fccType
== streamtypeAUDIO
)
241 lParam2
= (LPARAM
)((LPAVICOMPRESSOPTIONS
)lParam2
)->lpFormat
;
243 if (((LPWAVEFORMATEX
)lParam2
)->wFormatTag
!= WAVE_FORMAT_PCM
)
244 This
->cbOutFormat
= sizeof(WAVEFORMATEX
) + ((LPWAVEFORMATEX
)lParam2
)->cbSize
;
246 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
248 This
->lpOutFormat
= (LPWAVEFORMATEX
)GlobalAllocPtr(GHND
, This
->cbOutFormat
);
249 if (This
->lpOutFormat
== NULL
)
250 return AVIERR_MEMORY
;
252 memcpy(This
->lpOutFormat
, (LPVOID
)lParam2
, This
->cbOutFormat
);
254 This
->lpOutFormat
= NULL
;
255 This
->cbOutFormat
= 0;
258 This
->pStream
= (PAVISTREAM
)lParam1
;
259 IAVIStream_AddRef(This
->pStream
);
264 static HRESULT WINAPI
ACMStream_fnInfo(IAVIStream
*iface
,LPAVISTREAMINFOW psi
,
267 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
269 TRACE("(%p,%p,%ld)\n", iface
, psi
, size
);
272 return AVIERR_BADPARAM
;
274 return AVIERR_BADSIZE
;
276 /* Need codec to correct some values in structure */
277 if (This
->has
== NULL
) {
278 HRESULT hr
= AVIFILE_OpenCompressor(This
);
284 memcpy(psi
, &This
->sInfo
, min(size
, (LONG
)sizeof(This
->sInfo
)));
286 if (size
< (LONG
)sizeof(This
->sInfo
))
287 return AVIERR_BUFFERTOOSMALL
;
291 static LONG WINAPI
ACMStream_fnFindSample(IAVIStream
*iface
, LONG pos
,
294 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
296 TRACE("(%p,%ld,0x%08lX)\n",iface
,pos
,flags
);
298 if (flags
& FIND_FROM_START
) {
299 pos
= This
->sInfo
.dwStart
;
300 flags
&= ~(FIND_FROM_START
|FIND_PREV
);
304 /* convert pos from our 'space' to This->pStream's one */
305 CONVERT_THIS_to_STREAM(pos
);
308 pos
= IAVIStream_FindSample(This
->pStream
, pos
, flags
);
311 /* convert pos back to our 'space' if it's no size or physical pos */
312 if ((flags
& FIND_RET
) == 0)
313 CONVERT_STREAM_to_THIS(pos
);
319 static HRESULT WINAPI
ACMStream_fnReadFormat(IAVIStream
*iface
, LONG pos
,
320 LPVOID format
, LONG
*formatsize
)
322 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
324 TRACE("(%p,%ld,%p,%p)\n", iface
, pos
, format
, formatsize
);
326 if (formatsize
== NULL
)
327 return AVIERR_BADPARAM
;
329 if (This
->has
== NULL
) {
330 HRESULT hr
= AVIFILE_OpenCompressor(This
);
336 /* only interested in needed buffersize? */
337 if (format
== NULL
|| *formatsize
<= 0) {
338 *formatsize
= This
->cbOutFormat
;
343 /* copy initial format (only as much as will fit) */
344 memcpy(format
, This
->lpOutFormat
, min(*formatsize
, This
->cbOutFormat
));
345 if (*formatsize
< This
->cbOutFormat
) {
346 *formatsize
= This
->cbOutFormat
;
347 return AVIERR_BUFFERTOOSMALL
;
350 *formatsize
= This
->cbOutFormat
;
354 static HRESULT WINAPI
ACMStream_fnSetFormat(IAVIStream
*iface
, LONG pos
,
355 LPVOID format
, LONG formatsize
)
357 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
361 TRACE("(%p,%ld,%p,%ld)\n", iface
, pos
, format
, formatsize
);
363 /* check parameters */
364 if (format
== NULL
|| formatsize
<= 0)
365 return AVIERR_BADPARAM
;
367 /* Input format already known?
368 * Changing is unsupported, but be quiet if it's the same */
369 if (This
->lpInFormat
!= NULL
) {
370 if (This
->cbInFormat
!= formatsize
||
371 memcmp(format
, This
->lpInFormat
, formatsize
) != 0)
372 return AVIERR_UNSUPPORTED
;
377 /* Does the nested stream support writing? */
378 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
379 return AVIERR_READONLY
;
381 This
->lpInFormat
= (LPWAVEFORMATEX
)GlobalAllocPtr(GMEM_MOVEABLE
, formatsize
);
382 if (This
->lpInFormat
== NULL
)
383 return AVIERR_MEMORY
;
384 This
->cbInFormat
= formatsize
;
385 memcpy(This
->lpInFormat
, format
, formatsize
);
387 /* initialize formats and get compressor */
388 hr
= AVIFILE_OpenCompressor(This
);
392 CONVERT_THIS_to_STREAM(pos
);
394 /* tell the nested stream the new format */
395 return IAVIStream_SetFormat(This
->pStream
, pos
, This
->lpOutFormat
,
399 static HRESULT WINAPI
ACMStream_fnRead(IAVIStream
*iface
, LONG start
,
400 LONG samples
, LPVOID buffer
,
401 LONG buffersize
, LPLONG bytesread
,
404 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
409 TRACE("(%p,%ld,%ld,%p,%ld,%p,%p)\n", iface
, start
, samples
, buffer
,
410 buffersize
, bytesread
, samplesread
);
412 /* clear return parameters if given */
413 if (bytesread
!= NULL
)
415 if (samplesread
!= NULL
)
418 /* Do we have our compressor? */
419 if (This
->has
== NULL
) {
420 hr
= AVIFILE_OpenCompressor(This
);
426 /* only need to pass through? */
427 if (This
->cbInFormat
== This
->cbOutFormat
&&
428 memcmp(This
->lpInFormat
, This
->lpOutFormat
, This
->cbInFormat
) == 0) {
429 return IAVIStream_Read(This
->pStream
, start
, samples
, buffer
, buffersize
,
430 bytesread
, samplesread
);
433 /* read as much as fit? */
435 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
436 /* limit to buffersize */
437 if (samples
* This
->lpOutFormat
->nBlockAlign
> buffersize
)
438 samples
= buffersize
/ This
->lpOutFormat
->nBlockAlign
;
440 /* only return needed size? */
441 if (buffer
== NULL
|| buffersize
<= 0 || samples
== 0) {
442 if (bytesread
== NULL
&& samplesread
== NULL
)
443 return AVIERR_BADPARAM
;
445 if (bytesread
!= NULL
)
446 *bytesread
= samples
* This
->lpOutFormat
->nBlockAlign
;
447 if (samplesread
!= NULL
)
448 *samplesread
= samples
;
453 /* map our positions to pStream positions */
454 CONVERT_THIS_to_STREAM(start
);
456 /* our needed internal buffersize */
457 size
= samples
* This
->lpInFormat
->nBlockAlign
;
459 /* Need to free destination buffer used for writing? */
460 if (This
->acmStreamHdr
.pbDst
!= NULL
) {
461 GlobalFreePtr(This
->acmStreamHdr
.pbDst
);
462 This
->acmStreamHdr
.pbDst
= NULL
;
463 This
->acmStreamHdr
.dwDstUser
= 0;
466 /* need bigger source buffer? */
467 if (This
->acmStreamHdr
.pbSrc
== NULL
||
468 This
->acmStreamHdr
.dwSrcUser
< size
) {
469 if (This
->acmStreamHdr
.pbSrc
== NULL
)
470 This
->acmStreamHdr
.pbSrc
= GlobalAllocPtr(GMEM_MOVEABLE
, size
);
472 This
->acmStreamHdr
.pbSrc
= GlobalReAllocPtr(This
->acmStreamHdr
.pbSrc
,
473 size
, GMEM_MOVEABLE
);
474 if (This
->acmStreamHdr
.pbSrc
== NULL
)
475 return AVIERR_MEMORY
;
476 This
->acmStreamHdr
.dwSrcUser
= size
;
479 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
480 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
481 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
482 This
->acmStreamHdr
.cbSrcLength
= size
;
484 /* read source data */
485 hr
= IAVIStream_Read(This
->pStream
, start
, -1, This
->acmStreamHdr
.pbSrc
,
486 This
->acmStreamHdr
.cbSrcLength
,
487 &This
->acmStreamHdr
.cbSrcLength
, NULL
);
488 if (FAILED(hr
) || This
->acmStreamHdr
.cbSrcLength
== 0)
491 /* need to prepare stream? */
492 This
->acmStreamHdr
.pbDst
= buffer
;
493 This
->acmStreamHdr
.cbDstLength
= buffersize
;
494 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
495 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
496 This
->acmStreamHdr
.pbDst
= NULL
;
497 This
->acmStreamHdr
.cbDstLength
= 0;
498 return AVIERR_COMPRESSOR
;
502 /* now do the conversion */
503 /* FIXME: use ACM_CONVERTF_* flags */
504 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
505 hr
= AVIERR_COMPRESSOR
;
507 This
->acmStreamHdr
.pbDst
= NULL
;
508 This
->acmStreamHdr
.cbDstLength
= 0;
510 /* fill out return parameters if given */
511 if (bytesread
!= NULL
)
512 *bytesread
= This
->acmStreamHdr
.cbDstLengthUsed
;
513 if (samplesread
!= NULL
)
515 This
->acmStreamHdr
.cbDstLengthUsed
/ This
->lpOutFormat
->nBlockAlign
;
520 static HRESULT WINAPI
ACMStream_fnWrite(IAVIStream
*iface
, LONG start
,
521 LONG samples
, LPVOID buffer
,
522 LONG buffersize
, DWORD flags
,
526 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
531 TRACE("(%p,%ld,%ld,%p,%ld,0x%08lX,%p,%p)\n", iface
, start
, samples
,
532 buffer
, buffersize
, flags
, sampwritten
, byteswritten
);
534 /* clear return parameters if given */
535 if (sampwritten
!= NULL
)
537 if (byteswritten
!= NULL
)
540 /* check parameters */
541 if (buffer
== NULL
&& (buffersize
> 0 || samples
> 0))
542 return AVIERR_BADPARAM
;
544 /* Have we write capability? */
545 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
546 return AVIERR_READONLY
;
548 /* also need a compressor */
549 if (This
->has
== NULL
)
550 return AVIERR_NOCOMPRESSOR
;
552 /* map our sizes to pStream sizes */
554 CONVERT_THIS_to_STREAM(size
);
555 CONVERT_THIS_to_STREAM(start
);
557 /* no bytes to write? -- short circuit */
559 return IAVIStream_Write(This
->pStream
, -1, samples
, buffer
, size
,
560 flags
, sampwritten
, byteswritten
);
563 /* Need to free source buffer used for reading? */
564 if (This
->acmStreamHdr
.pbSrc
!= NULL
) {
565 GlobalFreePtr(This
->acmStreamHdr
.pbSrc
);
566 This
->acmStreamHdr
.pbSrc
= NULL
;
567 This
->acmStreamHdr
.dwSrcUser
= 0;
570 /* Need bigger destination buffer? */
571 if (This
->acmStreamHdr
.pbDst
== NULL
||
572 This
->acmStreamHdr
.dwDstUser
< size
) {
573 if (This
->acmStreamHdr
.pbDst
== NULL
)
574 This
->acmStreamHdr
.pbDst
= GlobalAllocPtr(GMEM_MOVEABLE
, size
);
576 This
->acmStreamHdr
.pbDst
= GlobalReAllocPtr(This
->acmStreamHdr
.pbDst
,
577 size
, GMEM_MOVEABLE
);
578 if (This
->acmStreamHdr
.pbDst
== NULL
)
579 return AVIERR_MEMORY
;
580 This
->acmStreamHdr
.dwDstUser
= size
;
582 This
->acmStreamHdr
.cbStruct
= sizeof(This
->acmStreamHdr
);
583 This
->acmStreamHdr
.cbSrcLengthUsed
= 0;
584 This
->acmStreamHdr
.cbDstLengthUsed
= 0;
585 This
->acmStreamHdr
.cbDstLength
= This
->acmStreamHdr
.dwDstUser
;
587 /* need to prepare stream? */
588 This
->acmStreamHdr
.pbSrc
= buffer
;
589 This
->acmStreamHdr
.cbSrcLength
= buffersize
;
590 if ((This
->acmStreamHdr
.fdwStatus
& ACMSTREAMHEADER_STATUSF_PREPARED
) == 0) {
591 if (acmStreamPrepareHeader(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
) {
592 This
->acmStreamHdr
.pbSrc
= NULL
;
593 This
->acmStreamHdr
.cbSrcLength
= 0;
594 return AVIERR_COMPRESSOR
;
598 /* now do the conversion */
599 /* FIXME: use ACM_CONVERTF_* flags */
600 if (acmStreamConvert(This
->has
, &This
->acmStreamHdr
, 0) != S_OK
)
601 hr
= AVIERR_COMPRESSOR
;
605 This
->acmStreamHdr
.pbSrc
= NULL
;
606 This
->acmStreamHdr
.cbSrcLength
= 0;
611 return IAVIStream_Write(This
->pStream
,-1,This
->acmStreamHdr
.cbDstLengthUsed
/
612 This
->lpOutFormat
->nBlockAlign
,This
->acmStreamHdr
.pbDst
,
613 This
->acmStreamHdr
.cbDstLengthUsed
,flags
,sampwritten
,
617 static HRESULT WINAPI
ACMStream_fnDelete(IAVIStream
*iface
, LONG start
,
620 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
622 TRACE("(%p,%ld,%ld)\n", iface
, start
, samples
);
624 /* check parameters */
625 if (start
< 0 || samples
< 0)
626 return AVIERR_BADPARAM
;
628 /* Delete before start of stream? */
629 if ((DWORD
)(start
+ samples
) < This
->sInfo
.dwStart
)
632 /* Delete after end of stream? */
633 if ((DWORD
)start
> This
->sInfo
.dwLength
)
636 /* For the rest we need write capability */
637 if ((This
->sInfo
.dwCaps
& AVIFILECAPS_CANWRITE
) == 0)
638 return AVIERR_READONLY
;
640 /* A compressor is also necessary */
641 if (This
->has
== NULL
)
642 return AVIERR_NOCOMPRESSOR
;
644 /* map our positions to pStream positions */
645 CONVERT_THIS_to_STREAM(start
);
646 CONVERT_THIS_to_STREAM(samples
);
648 return IAVIStream_Delete(This
->pStream
, start
, samples
);
651 static HRESULT WINAPI
ACMStream_fnReadData(IAVIStream
*iface
, DWORD fcc
,
652 LPVOID lp
, LPLONG lpread
)
654 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
656 TRACE("(%p,0x%08lX,%p,%p)\n", iface
, fcc
, lp
, lpread
);
658 assert(This
->pStream
!= NULL
);
660 return IAVIStream_ReadData(This
->pStream
, fcc
, lp
, lpread
);
663 static HRESULT WINAPI
ACMStream_fnWriteData(IAVIStream
*iface
, DWORD fcc
,
664 LPVOID lp
, LONG size
)
666 IAVIStreamImpl
*This
= (IAVIStreamImpl
*)iface
;
668 TRACE("(%p,0x%08lx,%p,%ld)\n", iface
, fcc
, lp
, size
);
670 assert(This
->pStream
!= NULL
);
672 return IAVIStream_WriteData(This
->pStream
, fcc
, lp
, size
);
675 static HRESULT WINAPI
ACMStream_fnSetInfo(IAVIStream
*iface
,
676 LPAVISTREAMINFOW info
, LONG infolen
)
678 FIXME("(%p,%p,%ld): stub\n", iface
, info
, infolen
);
683 /***********************************************************************/
685 static HRESULT
AVIFILE_OpenCompressor(IAVIStreamImpl
*This
)
690 assert(This
!= NULL
);
691 assert(This
->pStream
!= NULL
);
693 if (This
->has
!= NULL
)
696 if (This
->lpInFormat
== NULL
) {
697 /* decode or encode the data from pStream */
698 hr
= AVIStreamFormatSize(This
->pStream
, This
->sInfo
.dwStart
, &This
->cbInFormat
);
701 This
->lpInFormat
= (LPWAVEFORMATEX
)GlobalAllocPtr(GMEM_MOVEABLE
, This
->cbInFormat
);
702 if (This
->lpInFormat
== NULL
)
703 return AVIERR_MEMORY
;
705 hr
= IAVIStream_ReadFormat(This
->pStream
, This
->sInfo
.dwStart
,
706 This
->lpInFormat
, &This
->cbInFormat
);
710 if (This
->lpOutFormat
== NULL
) {
711 /* we must decode to default format */
712 This
->cbOutFormat
= sizeof(PCMWAVEFORMAT
);
713 This
->lpOutFormat
= (LPWAVEFORMATEX
)GlobalAllocPtr(GHND
, This
->cbOutFormat
);
714 if (This
->lpOutFormat
== NULL
)
715 return AVIERR_MEMORY
;
717 This
->lpOutFormat
->wFormatTag
= WAVE_FORMAT_PCM
;
718 if (acmFormatSuggest(NULL
, This
->lpInFormat
, This
->lpOutFormat
,
719 This
->cbOutFormat
, ACM_FORMATSUGGESTF_WFORMATTAG
) != S_OK
)
720 return AVIERR_NOCOMPRESSOR
;
722 } else if (This
->lpOutFormat
== NULL
)
723 return AVIERR_ERROR
; /* To what should I encode? */
725 if (acmStreamOpen(&This
->has
, NULL
, This
->lpInFormat
, This
->lpOutFormat
,
726 NULL
, 0, 0, ACM_STREAMOPENF_NONREALTIME
) != S_OK
)
727 return AVIERR_NOCOMPRESSOR
;
729 /* update AVISTREAMINFO structure */
730 This
->sInfo
.dwSampleSize
= This
->lpOutFormat
->nBlockAlign
;
731 This
->sInfo
.dwScale
= This
->lpOutFormat
->nBlockAlign
;
732 This
->sInfo
.dwRate
= This
->lpOutFormat
->nAvgBytesPerSec
;
733 This
->sInfo
.dwQuality
= (DWORD
)ICQUALITY_DEFAULT
;
734 SetRectEmpty(&This
->sInfo
.rcFrame
);
736 /* convert positions ansd sizes to output format */
737 CONVERT_STREAM_to_THIS(This
->sInfo
.dwStart
);
738 CONVERT_STREAM_to_THIS(This
->sInfo
.dwLength
);
739 CONVERT_STREAM_to_THIS(This
->sInfo
.dwSuggestedBufferSize
);